SelfProfile related things is done, not tested yet.
diff --git a/src/contact-storage.cpp b/src/contact-storage.cpp
index f42ec21..3eb8ac1 100644
--- a/src/contact-storage.cpp
+++ b/src/contact-storage.cpp
@@ -13,11 +13,35 @@
 
 #include <string>
 #include <boost/filesystem.hpp>
+#include "logging.h"
 
 using namespace std;
 using namespace ndn;
 namespace fs = boost::filesystem;
 
+INIT_LOGGER ("ContactStorage");
+
+const string INIT_SP_TABLE = "\
+CREATE TABLE IF NOT EXISTS                                           \n \
+  SelfProfile(                                                       \n \
+      profile_id        INTEGER PRIMARY KEY AUTOINCREMENT,           \n \
+      profile_type      BLOB NOT NULL,                               \n \
+      profile_value     BLOB NOT NULL                                \n \
+  );                                                                 \n \
+                                                                     \
+CREATE INDEX sp_index ON SelfProfile(profile_type);                  \n \
+";
+
+const string INIT_PD_TABLE = "\
+CREATE TABLE IF NOT EXISTS                                           \n \
+  ProfileData(                                                       \n \
+      identity          BLOB NOT NULL UNIQUE,                        \n \
+      profile_data      BLOB NOT NULL,                               \n \
+                                                                     \
+      PRIMARY KEY (identity)                                         \n \
+  );                                                                 \n \
+CREATE INDEX pd_index ON ProfileData(identity);                      \n \
+";
 
 const string INIT_TC_TABLE = "\
 CREATE TABLE IF NOT EXISTS                                           \n \
@@ -46,7 +70,8 @@
 CREATE INDEX nc_index ON NormalContact(contact_namespace);           \n \
 ";
 
-ContactStorage::ContactStorage()
+ContactStorage::ContactStorage(Ptr<security::IdentityManager> identityManager)
+  : m_identityManager(identityManager)
 {
   fs::path chronosDir = fs::path(getenv("HOME")) / ".chronos";
   fs::create_directories (chronosDir);
@@ -55,8 +80,43 @@
   if (res != SQLITE_OK)
     throw LnException("Chronos DB cannot be open/created");
 
-  // Check if TrustedContact table exists
+  // Check if SelfProfile table exists
   sqlite3_stmt *stmt;
+  sqlite3_prepare_v2 (m_db, "SELECT name FROM sqlite_master WHERE type='table' And name='SelfProfile'", -1, &stmt, 0);
+  res = sqlite3_step (stmt);
+
+  bool spTableExist = false;
+  if (res == SQLITE_ROW)
+      spTableExist = true;
+  sqlite3_finalize (stmt);
+
+  if(!spTableExist)
+    {
+      char *errmsg = 0;
+      res = sqlite3_exec (m_db, INIT_SP_TABLE.c_str (), NULL, NULL, &errmsg);
+      if (res != SQLITE_OK && errmsg != 0)
+        throw LnException("Init \"error\" in SelfProfile");
+    }
+
+  // Check if ProfileData table exists
+  sqlite3_prepare_v2 (m_db, "SELECT name FROM sqlite_master WHERE type='table' And name='ProfileData'", -1, &stmt, 0);
+  res = sqlite3_step (stmt);
+
+  bool pdTableExist = false;
+  if (res == SQLITE_ROW)
+      pdTableExist = true;
+  sqlite3_finalize (stmt);
+
+  if(!pdTableExist)
+    {
+      char *errmsg = 0;
+      res = sqlite3_exec (m_db, INIT_PD_TABLE.c_str (), NULL, NULL, &errmsg);
+      if (res != SQLITE_OK && errmsg != 0)
+        throw LnException("Init \"error\" in ProfileData");
+    }
+
+
+  // Check if TrustedContact table exists
   sqlite3_prepare_v2 (m_db, "SELECT name FROM sqlite_master WHERE type='table' And name='TrustedContact'", -1, &stmt, 0);
   res = sqlite3_step (stmt);
 
@@ -71,7 +131,6 @@
       res = sqlite3_exec (m_db, INIT_TC_TABLE.c_str (), NULL, NULL, &errmsg);
       if (res != SQLITE_OK && errmsg != 0)
         throw LnException("Init \"error\" in TrustedContact");
-      sqlite3_finalize (stmt);
     }
     
   // Check if NormalContact table exists
@@ -93,6 +152,102 @@
     }
 }
 
+bool
+ContactStorage::doesSelfEntryExist(const string& profileType)
+{
+  bool result = false;
+  
+  sqlite3_stmt *stmt;
+  sqlite3_prepare_v2 (m_db, "SELECT count(*) FROM SelfProfile WHERE profile_type=?", -1, &stmt, 0);
+  sqlite3_bind_text(stmt, 1, profileType.c_str(), profileType.size(), SQLITE_TRANSIENT);
+
+  int res = sqlite3_step (stmt);
+    
+  if (res == SQLITE_ROW)
+    {
+      int countAll = sqlite3_column_int (stmt, 0);
+      if (countAll > 0)
+        result = true;
+    } 
+  sqlite3_finalize (stmt); 
+  return result;
+}
+
+void
+ContactStorage::setSelfProfileIdentity(const Name& identity)
+{
+  string profileType("IDENTITY");
+  Blob identityBlob(identity.toUri().c_str(), identity.toUri().size());
+  
+  sqlite3_stmt *stmt;  
+  if(doesSelfEntryExist(profileType))
+    {
+      sqlite3_prepare_v2 (m_db, "UPDATE SelfProfile SET profile_value=? WHERE profile_type=?", -1, &stmt, 0);
+      sqlite3_bind_text(stmt, 1, identityBlob.buf(), identityBlob.size(), SQLITE_TRANSIENT);
+      sqlite3_bind_text(stmt, 2, profileType.c_str(), profileType.size(), SQLITE_TRANSIENT);
+    }
+  else
+    {
+      sqlite3_prepare_v2 (m_db, "INSERT INTO SelfProfile (profile_type, profile_value) values (?, ?)", -1, &stmt, 0);
+      sqlite3_bind_text(stmt, 1, profileType.c_str(), profileType.size(), SQLITE_TRANSIENT);
+      sqlite3_bind_text(stmt, 2, identityBlob.buf(), identityBlob.size(), SQLITE_TRANSIENT);
+    }
+  sqlite3_step (stmt);
+  sqlite3_finalize (stmt);
+}
+
+void
+ContactStorage::setSelfProfileEntry(const string& profileType, const Blob& profileValue)
+{
+  if(profileType == string("IDENTITY"))
+    return;
+
+  sqlite3_stmt *stmt;  
+  if(doesSelfEntryExist(profileType))
+    {
+      sqlite3_prepare_v2 (m_db, "UPDATE SelfProfile SET profile_value=? WHERE profile_type=?", -1, &stmt, 0);
+      sqlite3_bind_text(stmt, 1, profileValue.buf(), profileValue.size(), SQLITE_TRANSIENT);
+      sqlite3_bind_text(stmt, 2, profileType.c_str(), profileType.size(), SQLITE_TRANSIENT);
+    }
+  else
+    {
+      sqlite3_prepare_v2 (m_db, "INSERT INTO SelfProfile (profile_type, profile_value) values (?, ?)", -1, &stmt, 0);
+      sqlite3_bind_text(stmt, 1, profileType.c_str(), profileType.size(), SQLITE_TRANSIENT);
+      sqlite3_bind_text(stmt, 2, profileValue.buf(), profileValue.size(), SQLITE_TRANSIENT);
+    }
+  sqlite3_step (stmt);
+  sqlite3_finalize (stmt);
+}
+
+Ptr<Profile>
+ContactStorage::getSelfProfile()
+{
+  string idString("IDENTITY");
+  sqlite3_stmt *stmt;
+  sqlite3_prepare_v2(m_db, "SELECT profile_value FROM SelfProfile WHERE profile_type=?", -1, &stmt, 0);
+  sqlite3_bind_text(stmt, 1, idString.c_str(), idString.size(), SQLITE_TRANSIENT);
+
+  Name nameSpace;
+  int res = sqlite3_step (stmt);
+  if (res == SQLITE_ROW)
+    nameSpace.append(string(reinterpret_cast<const char *>(sqlite3_column_text(stmt, 0)), sqlite3_column_bytes (stmt, 0)));
+
+  Ptr<Profile> profile = Ptr<Profile>(new Profile(nameSpace));
+  
+  sqlite3_prepare_v2(m_db, "SELECT profile_type, profile_value FROM SelfProfile WHERE profile_type!=?", -1, &stmt, 0);
+  sqlite3_bind_text(stmt, 1, idString.c_str(), idString.size(), SQLITE_TRANSIENT);
+  
+  while( sqlite3_step (stmt) == SQLITE_ROW)
+    {
+      string profileType(reinterpret_cast<const char *>(sqlite3_column_text(stmt, 0)), sqlite3_column_bytes (stmt, 0));
+      Blob profileValue(reinterpret_cast<const char *>(sqlite3_column_text(stmt, 1)), sqlite3_column_bytes (stmt, 1));
+
+      profile->setProfileEntry(profileType, profileValue );
+    }
+
+  return profile;
+}
+
 void
 ContactStorage::addTrustedContact(const TrustedContact& trustedContact)
 {
@@ -213,3 +368,96 @@
   
   return normalContacts;
 }
+
+void
+ContactStorage::updateProfileData() const
+{
+  sqlite3_stmt *stmt;
+  sqlite3_prepare_v2 (m_db, "SELECT identity, profile_data FROM ProfileData", -1, &stmt, 0);
+
+  if(sqlite3_step (stmt) != SQLITE_ROW)
+    {
+      sqlite3_finalize (stmt);
+      return;
+    }
+
+  Name identity(string(reinterpret_cast<const char *>(sqlite3_column_text(stmt, 0)), sqlite3_column_bytes (stmt, 0)));
+
+  Ptr<Blob> profileDataBlob = Ptr<Blob>(new Blob(reinterpret_cast<const char *>(sqlite3_column_text(stmt, 1)), sqlite3_column_bytes (stmt, 1)));
+  Ptr<Data> plainData = Data::decodeFromWire(profileDataBlob);
+  const Blob& oldProfileBlob = plainData->content();
+  sqlite3_finalize (stmt);
+  
+  Ptr<Profile> newProfile = getSelfProfile();
+  if(NULL == newProfile)
+    return;
+  Ptr<Blob> newProfileBlob = newProfile->toDerBlob();
+  
+  if(oldProfileBlob == *newProfileBlob)
+    return;
+  
+  string idString("IDENTITY");
+  Ptr<const Blob> identityBlob = newProfile->getProfileEntry(idString);
+  Name newIdentity(string(identityBlob->buf(), identityBlob->size()));
+
+  Ptr<ProfileData> newProfileData = getSignedSelfProfileData(newIdentity, *newProfile);
+  Ptr<Blob> newProfileDataBlob = newProfileData->encodeToWire();
+
+  if(identity == newIdentity)
+    {
+      sqlite3_prepare_v2 (m_db, "UPDATE ProfileData SET profile_data=? WHERE identity=?", -1, &stmt, 0);
+      sqlite3_bind_text(stmt, 1, newProfileDataBlob->buf(), newProfileDataBlob->size(), SQLITE_TRANSIENT);
+      sqlite3_bind_text(stmt, 2, newIdentity.toUri().c_str(), newIdentity.toUri().size(), SQLITE_TRANSIENT);
+    }
+  else
+    {
+      sqlite3_prepare_v2 (m_db, "INSERT INTO ProfileData (identity, profile_data) values (?, ?)", -1, &stmt, 0);
+      sqlite3_bind_text(stmt, 2, newIdentity.toUri().c_str(), newIdentity.toUri().size(), SQLITE_TRANSIENT);
+      sqlite3_bind_text(stmt, 1, newProfileDataBlob->buf(), newProfileDataBlob->size(), SQLITE_TRANSIENT);
+    }
+}
+
+Ptr<Profile>
+ContactStorage::getSelfProfile() const
+{
+  string idString("IDENTITY");
+
+  sqlite3_stmt *stmt;
+  sqlite3_prepare_v2 (m_db, "SELECT profile_value FROM SelfProfile WHERE profile_type=?", -1, &stmt, 0);
+  sqlite3_bind_text(stmt, 1, idString.c_str(), idString.size(), SQLITE_TRANSIENT);
+
+  if(sqlite3_step (stmt) != SQLITE_ROW)
+    {
+      sqlite3_finalize (stmt);
+      return NULL;
+    }
+
+  Name identity(string(reinterpret_cast<const char *>(sqlite3_column_text(stmt, 0)), sqlite3_column_bytes (stmt, 0)));
+  
+  Ptr<Profile> profile = Ptr<Profile>(new Profile(identity));
+  sqlite3_finalize (stmt);
+  
+  sqlite3_prepare_v2 (m_db, "SELECT profile_type, profile_value FROM SelfProfile WHERE profile_type!=? and profile_type!=?", -1, &stmt, 0);
+  sqlite3_bind_text(stmt, 1, idString.c_str(), idString.size(), SQLITE_TRANSIENT);
+
+  while( sqlite3_step (stmt) == SQLITE_ROW)
+    {
+      string profileType(reinterpret_cast<const char *>(sqlite3_column_text(stmt, 0)), sqlite3_column_bytes (stmt, 0));
+      Blob profileValue(reinterpret_cast<const char *>(sqlite3_column_text(stmt, 1)), sqlite3_column_bytes (stmt, 1));
+      profile->setProfileEntry(profileType, profileValue);
+    }
+
+  return profile;
+}
+
+Ptr<ProfileData>
+ContactStorage::getSignedSelfProfileData(const Name& identity,
+                         const Profile& profile) const
+{
+  Name certificateName = m_identityManager->getDefaultCertificateNameByIdentity(identity);
+  Ptr<ProfileData> profileData = Ptr<ProfileData>(new ProfileData(identity, profile));
+  m_identityManager->signByCertificate(*profileData, certificateName);
+
+  return profileData;
+}
+