src/pEpEngine.c
author Edouard Tisserant <edouard@pep-project.org>
Fri, 30 Sep 2016 17:25:15 +0200
branchkeysync
changeset 1235 cfc9214a60a5
parent 1234 c03758736a0b
child 1236 991afc1aa2a1
permissions -rw-r--r--
sync : added get_device_group sql stuff
     1 #include "pEp_internal.h"
     2 #include "dynamic_api.h"
     3 #include "cryptotech.h"
     4 #include "transport.h"
     5 #include "blacklist.h"
     6 #include "sync_fsm.h"
     7 
     8 static int init_count = -1;
     9 char sync_uuid[37];
    10 
    11 static int user_version(void *_version, int count, char **text, char **name)
    12 {
    13     assert(_version);
    14     assert(count == 1);
    15     assert(text && text[0]);
    16     if (!(_version && count == 1 && text && text[0]))
    17         return -1;
    18 
    19     int *version = (int *) _version;
    20     *version = atoi(text[0]);
    21     return 0;
    22 }
    23 
    24 DYNAMIC_API PEP_STATUS init(PEP_SESSION *session)
    25 {
    26     PEP_STATUS status = PEP_STATUS_OK;
    27     int int_result;
    28     static const char *sql_log;
    29     static const char *sql_trustword;
    30     static const char *sql_get_identity;
    31     static const char *sql_set_person;
    32     static const char *sql_set_device_group;
    33     static const char *sql_get_device_group;
    34     static const char *sql_set_pgp_keypair;
    35     static const char *sql_set_identity;
    36     static const char *sql_set_identity_flags;
    37     static const char *sql_set_trust;
    38     static const char *sql_get_trust;
    39     static const char *sql_least_trust;
    40     static const char *sql_mark_as_compromized;
    41     static const char *sql_crashdump;
    42     static const char *sql_languagelist;
    43     static const char *sql_i18n_token;
    44 
    45     // blacklist
    46     static const char *sql_blacklist_add;
    47     static const char *sql_blacklist_delete;
    48     static const char *sql_blacklist_is_listed;
    49     static const char *sql_blacklist_retrieve;
    50 
    51     // Own keys
    52     static const char *sql_own_key_is_listed;
    53     static const char *sql_own_identities_retrieve;
    54 
    55     // Sequence
    56     static const char *sql_sequence_value1;
    57     static const char *sql_sequence_value2;
    58     static const char *sql_sequence_value3;
    59 
    60     // Revocation tracking
    61     static const char *sql_set_revoked;
    62     static const char *sql_get_revoked;
    63     
    64     bool in_first = false;
    65 
    66     assert(sqlite3_threadsafe());
    67     if (!sqlite3_threadsafe())
    68         return PEP_INIT_SQLITE3_WITHOUT_MUTEX;
    69 
    70     // a little race condition - but still a race condition
    71     // mitigated by calling caveat (see documentation)
    72 
    73     ++init_count;
    74     if (init_count == 0)
    75         in_first = true;
    76 
    77     assert(session);
    78     if (session == NULL)
    79         return PEP_ILLEGAL_VALUE;
    80 
    81     *session = NULL;
    82 
    83     pEpSession *_session = calloc(1, sizeof(pEpSession));
    84     assert(_session);
    85     if (_session == NULL)
    86         goto enomem;
    87 
    88     _session->version = PEP_ENGINE_VERSION;
    89 
    90     assert(LOCAL_DB);
    91     if (LOCAL_DB == NULL) {
    92         status = PEP_INIT_CANNOT_OPEN_DB;
    93         goto pep_error;
    94     }
    95 
    96     int_result = sqlite3_open_v2(
    97             LOCAL_DB,
    98             &_session->db,
    99             SQLITE_OPEN_READWRITE
   100                 | SQLITE_OPEN_CREATE
   101                 | SQLITE_OPEN_FULLMUTEX
   102                 | SQLITE_OPEN_PRIVATECACHE,
   103             NULL 
   104         );
   105 
   106     if (int_result != SQLITE_OK) {
   107         status = PEP_INIT_CANNOT_OPEN_DB;
   108         goto pep_error;
   109     }
   110 
   111     sqlite3_busy_timeout(_session->db, BUSY_WAIT_TIME);
   112 
   113     assert(SYSTEM_DB);
   114     if (SYSTEM_DB == NULL) {
   115         status = PEP_INIT_CANNOT_OPEN_SYSTEM_DB;
   116         goto pep_error;
   117     }
   118 
   119     int_result = sqlite3_open_v2(
   120             SYSTEM_DB, &_session->system_db,
   121             SQLITE_OPEN_READONLY
   122                 | SQLITE_OPEN_FULLMUTEX
   123                 | SQLITE_OPEN_SHAREDCACHE,
   124             NULL
   125         );
   126 
   127     if (int_result != SQLITE_OK) {
   128         status = PEP_INIT_CANNOT_OPEN_SYSTEM_DB;
   129         goto pep_error;
   130     }
   131 
   132     sqlite3_busy_timeout(_session->system_db, 1000);
   133 
   134 // increment this when patching DDL
   135 #define _DDL_USER_VERSION "3"
   136 
   137     if (in_first) {
   138         memset(sync_uuid, 0, 37);
   139 
   140         int_result = sqlite3_exec(
   141             _session->db,
   142                 "create table if not exists version_info (\n"
   143                 "   id integer primary key,\n"
   144                 "   timestamp integer default (datetime('now')),\n"
   145                 "   version text,\n"
   146                 "   comment text\n"
   147                 ");\n",
   148                 NULL,
   149                 NULL,
   150                 NULL
   151         );
   152         int_result = sqlite3_exec(
   153             _session->db,
   154                 "PRAGMA application_id = 0x23423423;\n"
   155                 "create table if not exists log (\n"
   156                 "   timestamp integer default (datetime('now')),\n"
   157                 "   title text not null,\n"
   158                 "   entity text not null,\n"
   159                 "   description text,\n"
   160                 "   comment text\n"
   161                 ");\n"
   162                 "create index if not exists log_timestamp on log (\n"
   163                 "   timestamp\n"
   164                 ");\n"
   165                 "create table if not exists pgp_keypair (\n"
   166                 "   fpr text primary key,\n"
   167                 "   public_id text unique,\n"
   168                 "   private_id text,\n"
   169                 "   created integer,\n"
   170                 "   expires integer,\n"
   171                 "   comment text,\n"
   172                 "   flags integer default 0\n"
   173                 ");\n"
   174                 "create index if not exists pgp_keypair_expires on pgp_keypair (\n"
   175                 "   expires\n"
   176                 ");\n"
   177                 "create table if not exists person (\n"
   178                 "   id text primary key,\n"
   179                 "   username text not null,\n"
   180                 "   main_key_id text\n"
   181                 "       references pgp_keypair (fpr)\n"
   182                 "       on delete set null,\n"
   183                 "   lang text,\n"
   184                 "   comment text,\n"
   185                 "   device_group text\n"
   186                 ");\n"
   187                 "create table if not exists identity (\n"
   188                 "   address text,\n"
   189                 "   user_id text\n"
   190                 "       references person (id)\n"
   191                 "       on delete cascade,\n"
   192                 "   main_key_id text\n"
   193                 "       references pgp_keypair (fpr)\n"
   194                 "       on delete set null,\n"
   195                 "   comment text,\n"
   196                 "   flags integer default 0,"
   197                 "   primary key (address, user_id)\n"
   198                 ");\n"
   199                 "create table if not exists trust (\n"
   200                 "   user_id text not null\n"
   201                 "       references person (id)\n"
   202                 "       on delete cascade,\n"
   203                 "   pgp_keypair_fpr text not null\n"
   204                 "       references pgp_keypair (fpr)\n"
   205                 "       on delete cascade,\n"
   206                 "   comm_type integer not null,\n"
   207                 "   comment text,\n"
   208                 "   primary key (user_id, pgp_keypair_fpr)\n"
   209                 ");\n"
   210                 // blacklist
   211                 "create table if not exists blacklist_keys (\n"
   212                 "   fpr text primary key\n"
   213                 ");\n"
   214                 // sequences
   215                 "create table if not exists sequences(\n"
   216                 "   name text primary key,\n"
   217                 "   value integer default 0,\n"
   218                 "   own integer default 0\n"
   219                 ");\n"
   220                 "create table if not exists revoked_keys (\n"
   221                 "   revoked_fpr text primary key,\n"
   222                 "   replacement_fpr text not null\n"
   223                 "       references pgp_keypair (fpr)\n"
   224                 "       on delete cascade,\n"
   225                 "   revocation_date integer\n"
   226                 ");\n"
   227                 ,
   228             NULL,
   229             NULL,
   230             NULL
   231         );
   232         assert(int_result == SQLITE_OK);
   233 
   234         int version;
   235         int_result = sqlite3_exec(
   236             _session->db,
   237             "pragma user_version;",
   238             user_version,
   239             &version,
   240             NULL
   241         );
   242         assert(int_result == SQLITE_OK);
   243 
   244         if (version < 1) {
   245             int_result = sqlite3_exec(
   246                 _session->db,
   247                 "alter table identity\n"
   248                 "   add column flags integer default 0;\n",
   249                 NULL,
   250                 NULL,
   251                 NULL
   252             );
   253         }
   254 
   255         if (version < 2) {
   256             int_result = sqlite3_exec(
   257                 _session->db,
   258                 "alter table pgp_keypair\n"
   259                 "   add column flags integer default 0;\n"
   260                 "alter table person\n"
   261                 "   add column device_group text;\n",
   262                 NULL,
   263                 NULL,
   264                 NULL
   265             );
   266         }
   267 
   268         if (version < 3) {
   269             int_result = sqlite3_exec(
   270                 _session->db,
   271                 "alter table sequences\n"
   272                 "   add column own integer default 0;\n",
   273                 NULL,
   274                 NULL,
   275                 NULL
   276             );
   277         }
   278 
   279         if (version < atoi(_DDL_USER_VERSION)) {
   280             int_result = sqlite3_exec(
   281                 _session->db,
   282                 "pragma user_version = "_DDL_USER_VERSION";\n"
   283                 "insert or replace into version_info (id, version)"
   284                     "values (1, '" PEP_ENGINE_VERSION "');",
   285                 NULL,
   286                 NULL,
   287                 NULL
   288             );
   289             assert(int_result == SQLITE_OK);
   290         }
   291 
   292         if (version <= atoi(_DDL_USER_VERSION)) {
   293             int_result = sqlite3_exec(
   294                 _session->db,
   295                 "pragma user_version = "_DDL_USER_VERSION";\n"
   296                 "insert or replace into version_info (id, version)"
   297                     "values (1, '" PEP_ENGINE_VERSION "');",
   298                 NULL,
   299                 NULL,
   300                 NULL
   301             );
   302             assert(int_result == SQLITE_OK);
   303         }
   304 
   305         sql_log = "insert into log (title, entity, description, comment)"
   306                   "values (?1, ?2, ?3, ?4);";
   307 
   308         sql_get_identity =  "select fpr, username, comm_type, lang,"
   309                             "   identity.flags | pgp_keypair.flags"
   310                             "   from identity"
   311                             "   join person on id = identity.user_id"
   312                             "   join pgp_keypair on fpr = identity.main_key_id"
   313                             "   join trust on id = trust.user_id"
   314                             "       and pgp_keypair_fpr = identity.main_key_id"
   315                             "   where address = ?1 and identity.user_id = ?2;";
   316 
   317         sql_trustword = "select id, word from wordlist where lang = lower(?1) "
   318                        "and id = ?2 ;";
   319 
   320         // Set person, but if already exist, only update.
   321         // if main_key_id already set, don't touch.
   322         sql_set_person = "insert or replace into person (id, username, lang, main_key_id)"
   323                          "  values (?1, ?2, ?3,"
   324                          "    (select coalesce((select main_key_id from person "
   325                          "      where id = ?1), upper(replace(?4,' ',''))))) ;";
   326 
   327         sql_set_device_group = "update person set device_group = ?1 "
   328                                "where user_id = '" PEP_OWN_USERID "';";
   329 
   330         sql_get_device_group = "select device_group from person "
   331                                "where user_id = '" PEP_OWN_USERID "';";
   332 
   333         sql_set_pgp_keypair = "insert or replace into pgp_keypair (fpr) "
   334                               "values (upper(replace(?1,' ',''))) ;";
   335 
   336         sql_set_identity = "insert or replace into identity (address, main_key_id, "
   337                            "user_id, flags) values (?1, upper(replace(?2,' ','')),"
   338                            "?3, ?4 & 255) ;";
   339 
   340         sql_set_identity_flags = "update identity set flags = ?1 & 255 "
   341                                  "where address = ?2 and user_id = ?3 ;";
   342 
   343         sql_set_trust = "insert or replace into trust (user_id, pgp_keypair_fpr, comm_type) "
   344                         "values (?1, upper(replace(?2,' ','')), ?3) ;";
   345 
   346         sql_get_trust = "select comm_type from trust where user_id = ?1 "
   347                         "and pgp_keypair_fpr = upper(replace(?2,' ','')) ;";
   348 
   349         sql_least_trust = "select min(comm_type) from trust where pgp_keypair_fpr = upper(replace(?1,' ','')) ;";
   350 
   351         sql_mark_as_compromized = "update trust not indexed set comm_type = 15"
   352                                   " where pgp_keypair_fpr = upper(replace(?1,' ','')) ;";
   353 
   354         sql_crashdump = "select timestamp, title, entity, description, comment"
   355                         " from log order by timestamp desc limit ?1 ;";
   356 
   357         sql_languagelist = "select i18n_language.lang, name, phrase from i18n_language join i18n_token using (lang) where i18n_token.id = 1000;" ;
   358 
   359         sql_i18n_token = "select phrase from i18n_token where lang = lower(?1) and id = ?2 ;";
   360 
   361         // blacklist
   362 
   363         sql_blacklist_add = "insert or replace into blacklist_keys (fpr) values (upper(replace(?1,' ',''))) ;"
   364                             "delete from identity where main_key_id = upper(replace(?1,' ','')) ;"
   365                             "delete from pgp_keypair where fpr = upper(replace(?1,' ','')) ;";
   366 
   367         sql_blacklist_delete = "delete from blacklist_keys where fpr = upper(replace(?1,' ','')) ;";
   368 
   369         sql_blacklist_is_listed = "select count(*) from blacklist_keys where fpr = upper(replace(?1,' ','')) ;";
   370 
   371         sql_blacklist_retrieve = "select * from blacklist_keys ;";
   372         
   373         // Own keys
   374         
   375         sql_own_key_is_listed =
   376                                 "select count(*) from ("
   377                                 " select main_key_id from person "
   378                                 "   where main_key_id = upper(replace(?1,' ',''))"
   379                                 "    and id = '" PEP_OWN_USERID "' "
   380                                 " union "
   381                                 "  select main_key_id from identity "
   382                                 "   where main_key_id = upper(replace(?1,' ',''))"
   383                                 "    and user_id = '" PEP_OWN_USERID "' );";
   384 
   385         sql_own_identities_retrieve =  "select address, fpr, username, "
   386                             "   lang, identity.flags | pgp_keypair.flags"
   387                             "   from identity"
   388                             "   join person on id = identity.user_id"
   389                             "   join pgp_keypair on fpr = identity.main_key_id"
   390                             "   join trust on id = trust.user_id"
   391                             "       and pgp_keypair_fpr = identity.main_key_id"
   392                             "   where identity.user_id = '" PEP_OWN_USERID "';";
   393         
   394         sql_sequence_value1 = "insert or replace into sequences (name, value, own) "
   395                               "values (?1, "
   396                               "(select coalesce((select value + 1 from sequences "
   397                               "where name = ?1), 1 )), ?2) ; ";
   398         sql_sequence_value2 = "select value, own from sequences where name = ?1 ;";
   399         sql_sequence_value3 = "update sequences set value = ?2, own = ?3 where name = ?1 ;";
   400         
   401         sql_set_revoked =     "insert or replace into revoked_keys ("
   402                               "    revoked_fpr, replacement_fpr, revocation_date) "
   403                               "values (upper(replace(?1,' ','')),"
   404                               "        upper(replace(?2,' ','')),"
   405                               "        ?3) ;";
   406         
   407         sql_get_revoked =     "select revoked_fpr, revocation_date from revoked_keys"
   408                               "    where replacement_fpr = upper(replace(?1,' ','')) ;";
   409     }
   410 
   411     int_result = sqlite3_prepare_v2(_session->db, sql_log,
   412             (int)strlen(sql_log), &_session->log, NULL);
   413     assert(int_result == SQLITE_OK);
   414 
   415     int_result = sqlite3_prepare_v2(_session->system_db, sql_trustword,
   416             (int)strlen(sql_trustword), &_session->trustword, NULL);
   417     assert(int_result == SQLITE_OK);
   418 
   419     int_result = sqlite3_prepare_v2(_session->db, sql_get_identity,
   420             (int)strlen(sql_get_identity), &_session->get_identity, NULL);
   421     assert(int_result == SQLITE_OK);
   422 
   423     int_result = sqlite3_prepare_v2(_session->db, sql_set_person,
   424             (int)strlen(sql_set_person), &_session->set_person, NULL);
   425     assert(int_result == SQLITE_OK);
   426 
   427     int_result = sqlite3_prepare_v2(_session->db, sql_set_device_group,
   428             (int)strlen(sql_set_device_group), &_session->set_device_group, NULL);
   429     assert(int_result == SQLITE_OK);
   430 
   431     int_result = sqlite3_prepare_v2(_session->db, sql_get_device_group,
   432             (int)strlen(sql_get_device_group), &_session->get_device_group, NULL);
   433     assert(int_result == SQLITE_OK);
   434 
   435     int_result = sqlite3_prepare_v2(_session->db, sql_set_pgp_keypair,
   436             (int)strlen(sql_set_pgp_keypair), &_session->set_pgp_keypair,
   437             NULL);
   438     assert(int_result == SQLITE_OK);
   439 
   440     int_result = sqlite3_prepare_v2(_session->db, sql_set_identity,
   441             (int)strlen(sql_set_identity), &_session->set_identity, NULL);
   442     assert(int_result == SQLITE_OK);
   443 
   444     int_result = sqlite3_prepare_v2(_session->db, sql_set_identity_flags,
   445             (int)strlen(sql_set_identity_flags), &_session->set_identity_flags,
   446             NULL);
   447     assert(int_result == SQLITE_OK);
   448 
   449     int_result = sqlite3_prepare_v2(_session->db, sql_set_trust,
   450             (int)strlen(sql_set_trust), &_session->set_trust, NULL);
   451     assert(int_result == SQLITE_OK);
   452 
   453     int_result = sqlite3_prepare_v2(_session->db, sql_get_trust,
   454             (int)strlen(sql_get_trust), &_session->get_trust, NULL);
   455     assert(int_result == SQLITE_OK);
   456 
   457     int_result = sqlite3_prepare_v2(_session->db, sql_least_trust,
   458             (int)strlen(sql_least_trust), &_session->least_trust, NULL);
   459     assert(int_result == SQLITE_OK);
   460 
   461     int_result = sqlite3_prepare_v2(_session->db, sql_mark_as_compromized,
   462             (int)strlen(sql_mark_as_compromized), &_session->mark_compromized,
   463             NULL);
   464     assert(int_result == SQLITE_OK);
   465 
   466     int_result = sqlite3_prepare_v2(_session->db, sql_crashdump,
   467             (int)strlen(sql_crashdump), &_session->crashdump, NULL);
   468     assert(int_result == SQLITE_OK);
   469 
   470     int_result = sqlite3_prepare_v2(_session->system_db, sql_languagelist,
   471             (int)strlen(sql_languagelist), &_session->languagelist, NULL);
   472     assert(int_result == SQLITE_OK);
   473 
   474     int_result = sqlite3_prepare_v2(_session->system_db, sql_i18n_token,
   475             (int)strlen(sql_i18n_token), &_session->i18n_token, NULL);
   476     assert(int_result == SQLITE_OK);
   477 
   478     // blacklist
   479 
   480     int_result = sqlite3_prepare_v2(_session->db, sql_blacklist_add,
   481             (int)strlen(sql_blacklist_add), &_session->blacklist_add, NULL);
   482     assert(int_result == SQLITE_OK);
   483 
   484     int_result = sqlite3_prepare_v2(_session->db, sql_blacklist_delete,
   485             (int)strlen(sql_blacklist_delete), &_session->blacklist_delete,
   486             NULL);
   487     assert(int_result == SQLITE_OK);
   488 
   489     int_result = sqlite3_prepare_v2(_session->db, sql_blacklist_is_listed,
   490             (int)strlen(sql_blacklist_is_listed),
   491             &_session->blacklist_is_listed, NULL);
   492     assert(int_result == SQLITE_OK);
   493 
   494     int_result = sqlite3_prepare_v2(_session->db, sql_blacklist_retrieve,
   495             (int)strlen(sql_blacklist_retrieve), &_session->blacklist_retrieve,
   496             NULL);
   497     assert(int_result == SQLITE_OK);
   498 
   499     // Own keys
   500     
   501     int_result = sqlite3_prepare_v2(_session->db, sql_own_key_is_listed,
   502             (int)strlen(sql_own_key_is_listed), &_session->own_key_is_listed,
   503             NULL);
   504     assert(int_result == SQLITE_OK);
   505     
   506     int_result = sqlite3_prepare_v2(_session->db, sql_own_identities_retrieve,
   507             (int)strlen(sql_own_identities_retrieve),
   508             &_session->own_identities_retrieve, NULL);
   509     assert(int_result == SQLITE_OK);
   510  
   511     // Sequence
   512 
   513     int_result = sqlite3_prepare_v2(_session->db, sql_sequence_value1,
   514             (int)strlen(sql_sequence_value1), &_session->sequence_value1,
   515             NULL);
   516     assert(int_result == SQLITE_OK);
   517 
   518     int_result = sqlite3_prepare_v2(_session->db, sql_sequence_value2,
   519             (int)strlen(sql_sequence_value2), &_session->sequence_value2,
   520             NULL);
   521     assert(int_result == SQLITE_OK);
   522 
   523     int_result = sqlite3_prepare_v2(_session->db, sql_sequence_value3,
   524             (int)strlen(sql_sequence_value3), &_session->sequence_value3,
   525             NULL);
   526     assert(int_result == SQLITE_OK);
   527 
   528     // Revocation tracking
   529     
   530     int_result = sqlite3_prepare_v2(_session->db, sql_set_revoked,
   531             (int)strlen(sql_set_revoked), &_session->set_revoked, NULL);
   532     assert(int_result == SQLITE_OK);
   533     
   534     int_result = sqlite3_prepare_v2(_session->db, sql_get_revoked,
   535             (int)strlen(sql_get_revoked), &_session->get_revoked, NULL);
   536     assert(int_result == SQLITE_OK);
   537     
   538     status = init_cryptotech(_session, in_first);
   539     if (status != PEP_STATUS_OK)
   540         goto pep_error;
   541 
   542     status = init_transport_system(_session, in_first);
   543     if (status != PEP_STATUS_OK)
   544         goto pep_error;
   545 
   546     status = log_event(_session, "init", "pEp " PEP_ENGINE_VERSION, NULL, NULL);
   547     if (status != PEP_STATUS_OK)
   548         goto pep_error;
   549 
   550     // runtime config
   551 
   552 #ifdef ANDROID
   553     _session->use_only_own_private_keys = true;
   554 #elif TARGET_OS_IPHONE
   555     _session->use_only_own_private_keys = true;
   556 #else
   557     _session->use_only_own_private_keys = false;
   558 #endif
   559 
   560     *session = _session;
   561     return PEP_STATUS_OK;
   562 
   563 enomem:
   564     status = PEP_OUT_OF_MEMORY;
   565 
   566 pep_error:
   567     release(_session);
   568     return status;
   569 }
   570 
   571 DYNAMIC_API void release(PEP_SESSION session)
   572 {
   573     bool out_last = false;
   574 
   575     assert(init_count >= 0);
   576     assert(session);
   577 
   578     if (!((init_count >= 0) && session))
   579         return;
   580 
   581     // a small race condition but still a race condition
   582     // mitigated by calling caveat (see documentation)
   583 
   584     if (init_count == 0)
   585         out_last = true;
   586     --init_count;
   587 
   588     if (session) {
   589         if (session->sync_state != DeviceState_state_NONE)
   590             unregister_sync_callbacks(session);
   591 
   592         if (session->db) {
   593             if (session->log)
   594                 sqlite3_finalize(session->log);
   595             if (session->trustword)
   596                 sqlite3_finalize(session->trustword);
   597             if (session->get_identity)
   598                 sqlite3_finalize(session->get_identity);
   599             if (session->set_person)
   600                 sqlite3_finalize(session->set_person);
   601             if (session->set_device_group)
   602                 sqlite3_finalize(session->set_device_group);
   603             if (session->get_device_group)
   604                 sqlite3_finalize(session->get_device_group);
   605             if (session->set_pgp_keypair)
   606                 sqlite3_finalize(session->set_pgp_keypair);
   607             if (session->set_identity)
   608                 sqlite3_finalize(session->set_identity);
   609             if (session->set_identity_flags)
   610                 sqlite3_finalize(session->set_identity_flags);
   611             if (session->set_trust)
   612                 sqlite3_finalize(session->set_trust);
   613             if (session->get_trust)
   614                 sqlite3_finalize(session->get_trust);
   615             if (session->least_trust)
   616                 sqlite3_finalize(session->least_trust);
   617             if (session->mark_compromized)
   618                 sqlite3_finalize(session->mark_compromized);
   619             if (session->crashdump)
   620                 sqlite3_finalize(session->crashdump);
   621             if (session->languagelist)
   622                 sqlite3_finalize(session->languagelist);
   623             if (session->i18n_token)
   624                 sqlite3_finalize(session->i18n_token);
   625             if (session->blacklist_add)
   626                 sqlite3_finalize(session->blacklist_add);
   627             if (session->blacklist_delete)
   628                 sqlite3_finalize(session->blacklist_delete);
   629             if (session->blacklist_is_listed)
   630                 sqlite3_finalize(session->blacklist_is_listed);
   631             if (session->blacklist_retrieve)
   632                 sqlite3_finalize(session->blacklist_retrieve);
   633             if (session->own_key_is_listed)
   634                 sqlite3_finalize(session->own_key_is_listed);
   635             if (session->own_identities_retrieve)
   636                 sqlite3_finalize(session->own_identities_retrieve);
   637             if (session->sequence_value1)
   638                 sqlite3_finalize(session->sequence_value1);
   639             if (session->sequence_value2)
   640                 sqlite3_finalize(session->sequence_value2);
   641             if (session->sequence_value3)
   642                 sqlite3_finalize(session->sequence_value3);
   643             if (session->set_revoked)
   644                 sqlite3_finalize(session->set_revoked);
   645             if (session->get_revoked)
   646                 sqlite3_finalize(session->get_revoked);
   647 
   648             if (session->db)
   649                 sqlite3_close_v2(session->db);
   650             if (session->system_db)
   651                 sqlite3_close_v2(session->system_db);
   652         }
   653 
   654         release_transport_system(session, out_last);
   655         release_cryptotech(session, out_last);
   656 
   657         free(session);
   658     }
   659 }
   660 
   661 DYNAMIC_API void config_passive_mode(PEP_SESSION session, bool enable)
   662 {
   663     assert(session);
   664     session->passive_mode = enable;
   665 }
   666 
   667 DYNAMIC_API void config_unencrypted_subject(PEP_SESSION session, bool enable)
   668 {
   669     assert(session);
   670     session->unencrypted_subject = enable;
   671 }
   672 
   673 DYNAMIC_API void config_use_only_own_private_keys(PEP_SESSION session,
   674         bool enable)
   675 {
   676     assert(session);
   677     session->use_only_own_private_keys = enable;
   678 }
   679 
   680 DYNAMIC_API void config_keep_sync_msg(PEP_SESSION session, bool enable)
   681 {
   682     assert(session);
   683     session->keep_sync_msg = enable;
   684 }
   685 
   686 DYNAMIC_API PEP_STATUS log_event(
   687         PEP_SESSION session,
   688         const char *title,
   689         const char *entity,
   690         const char *description,
   691         const char *comment
   692     )
   693 {
   694     PEP_STATUS status = PEP_STATUS_OK;
   695     int result;
   696 
   697     assert(session);
   698     assert(title);
   699     assert(entity);
   700 
   701     if (!(session && title && entity))
   702         return PEP_ILLEGAL_VALUE;
   703 
   704     sqlite3_reset(session->log);
   705     sqlite3_bind_text(session->log, 1, title, -1, SQLITE_STATIC);
   706     sqlite3_bind_text(session->log, 2, entity, -1, SQLITE_STATIC);
   707     if (description)
   708         sqlite3_bind_text(session->log, 3, description, -1, SQLITE_STATIC);
   709     else
   710         sqlite3_bind_null(session->log, 3);
   711     if (comment)
   712         sqlite3_bind_text(session->log, 4, comment, -1, SQLITE_STATIC);
   713     else
   714         sqlite3_bind_null(session->log, 4);
   715     do {
   716         result = sqlite3_step(session->log);
   717         assert(result == SQLITE_DONE || result == SQLITE_BUSY);
   718         if (result != SQLITE_DONE && result != SQLITE_BUSY)
   719             status = PEP_UNKNOWN_ERROR;
   720     } while (result == SQLITE_BUSY);
   721     sqlite3_reset(session->log);
   722 
   723     return status;
   724 }
   725 
   726 DYNAMIC_API PEP_STATUS trustword(
   727             PEP_SESSION session, uint16_t value, const char *lang,
   728             char **word, size_t *wsize
   729         )
   730 {
   731     PEP_STATUS status = PEP_STATUS_OK;
   732 
   733     assert(session);
   734     assert(word);
   735     assert(wsize);
   736 
   737     if (!(session && word && wsize))
   738         return PEP_ILLEGAL_VALUE;
   739 
   740     *word = NULL;
   741     *wsize = 0;
   742 
   743     if (lang == NULL)
   744         lang = "en";
   745 
   746     assert((lang[0] >= 'A' && lang[0] <= 'Z')
   747             || (lang[0] >= 'a' && lang[0] <= 'z'));
   748     assert((lang[1] >= 'A' && lang[1] <= 'Z')
   749             || (lang[1] >= 'a' && lang[1] <= 'z'));
   750     assert(lang[2] == 0);
   751 
   752     sqlite3_reset(session->trustword);
   753     sqlite3_bind_text(session->trustword, 1, lang, -1, SQLITE_STATIC);
   754     sqlite3_bind_int(session->trustword, 2, value);
   755 
   756     const int result = sqlite3_step(session->trustword);
   757     if (result == SQLITE_ROW) {
   758         *word = strdup((const char *) sqlite3_column_text(session->trustword,
   759                     1));
   760         if (*word)
   761             *wsize = sqlite3_column_bytes(session->trustword, 1);
   762         else
   763             status = PEP_OUT_OF_MEMORY;
   764     } else
   765         status = PEP_TRUSTWORD_NOT_FOUND;
   766 
   767     sqlite3_reset(session->trustword);
   768     return status;
   769 }
   770 
   771 DYNAMIC_API PEP_STATUS trustwords(
   772         PEP_SESSION session, const char *fingerprint, const char *lang,
   773         char **words, size_t *wsize, int max_words
   774     )
   775 {
   776     const char *source = fingerprint;
   777     char *buffer;
   778     char *dest;
   779     size_t fsize;
   780 
   781     assert(session);
   782     assert(fingerprint);
   783     assert(words);
   784     assert(wsize);
   785     assert(max_words >= 0);
   786 
   787     if (!(session && fingerprint && words && wsize && max_words >= 0))
   788         return PEP_ILLEGAL_VALUE;
   789 
   790     *words = NULL;
   791     *wsize = 0;
   792 
   793     buffer = calloc(1, MAX_TRUSTWORDS_SPACE);
   794     assert(buffer);
   795     if (buffer == NULL)
   796         return PEP_OUT_OF_MEMORY;
   797     dest = buffer;
   798 
   799     fsize = strlen(fingerprint);
   800 
   801     if (!lang || !lang[0])
   802         lang = "en";
   803 
   804     assert((lang[0] >= 'A' && lang[0] <= 'Z')
   805             || (lang[0] >= 'a' && lang[0] <= 'z'));
   806     assert((lang[1] >= 'A' && lang[1] <= 'Z')
   807             || (lang[1] >= 'a' && lang[1] <= 'z'));
   808     assert(lang[2] == 0);
   809 
   810     int n_words = 0;
   811     while (source < fingerprint + fsize) {
   812         PEP_STATUS _status;
   813         uint16_t value;
   814         char *word;
   815         size_t _wsize;
   816         int j;
   817 
   818         for (value=0, j=0; j < 4 && source < fingerprint + fsize; ) {
   819             if (*source >= 'a' && *source <= 'f')
   820                 value += (*source - 'a' + 10) << (3 - j++) * 4;
   821             else if (*source >= 'A' && *source <= 'F')
   822                 value += (*source - 'A' + 10) << (3 - j++) * 4;
   823             else if (*source >= '0' && *source <= '9')
   824                 value += (*source - '0') << (3 - j++) * 4;
   825             
   826             source++;
   827         }
   828 
   829         _status = trustword(session, value, lang, &word, &_wsize);
   830         if (_status == PEP_OUT_OF_MEMORY) {
   831             free(buffer);
   832             return PEP_OUT_OF_MEMORY;
   833         }
   834         if (word == NULL) {
   835             free(buffer);
   836             return PEP_TRUSTWORD_NOT_FOUND;
   837         }
   838 
   839         if (dest + _wsize < buffer + MAX_TRUSTWORDS_SPACE - 1) {
   840             strncpy(dest, word, _wsize);
   841             free(word);
   842             dest += _wsize;
   843         }
   844         else {
   845             free(word);
   846             break; // buffer full
   847         }
   848 
   849         if (source < fingerprint + fsize
   850                 && dest + _wsize < buffer + MAX_TRUSTWORDS_SPACE - 1)
   851             *dest++ = ' ';
   852 
   853         ++n_words;
   854         if (max_words && n_words >= max_words)
   855             break;
   856     }
   857 
   858     *words = buffer;
   859     *wsize = dest - buffer;
   860     return PEP_STATUS_OK;
   861 }
   862 
   863 pEp_identity *new_identity(
   864         const char *address, const char *fpr, const char *user_id,
   865         const char *username
   866     )
   867 {
   868     pEp_identity *result = calloc(1, sizeof(pEp_identity));
   869     assert(result);
   870     if (result) {
   871         if (address) {
   872             result->address = strdup(address);
   873             assert(result->address);
   874             if (result->address == NULL) {
   875                 free(result);
   876                 return NULL;
   877             }
   878         }
   879         if (fpr) {
   880             result->fpr = strdup(fpr);
   881             assert(result->fpr);
   882             if (result->fpr == NULL) {
   883                 free_identity(result);
   884                 return NULL;
   885             }
   886         }
   887         if (user_id) {
   888             result->user_id = strdup(user_id);
   889             assert(result->user_id);
   890             if (result->user_id == NULL) {
   891                 free_identity(result);
   892                 return NULL;
   893             }
   894         }
   895         if (username) {
   896             result->username = strdup(username);
   897             assert(result->username);
   898             if (result->username == NULL) {
   899                 free_identity(result);
   900                 return NULL;
   901             }
   902         }
   903     }
   904     return result;
   905 }
   906 
   907 pEp_identity *identity_dup(const pEp_identity *src)
   908 {
   909     assert(src);
   910 
   911     pEp_identity *dup = new_identity(src->address, src->fpr, src->user_id,
   912             src->username);
   913     assert(dup);
   914     if (dup == NULL)
   915         return NULL;
   916     
   917     dup->comm_type = src->comm_type;
   918     dup->lang[0] = src->lang[0];
   919     dup->lang[1] = src->lang[1];
   920     dup->lang[2] = 0;
   921     dup->me = src->me;
   922     dup->flags = src->flags;
   923 
   924     return dup;
   925 }
   926 
   927 void free_identity(pEp_identity *identity)
   928 {
   929     if (identity) {
   930         free(identity->address);
   931         free(identity->fpr);
   932         free(identity->user_id);
   933         free(identity->username);
   934         free(identity);
   935     }
   936 }
   937 
   938 DYNAMIC_API PEP_STATUS get_identity(
   939         PEP_SESSION session,
   940         const char *address,
   941         const char *user_id,
   942         pEp_identity **identity
   943     )
   944 {
   945     PEP_STATUS status = PEP_STATUS_OK;
   946     static pEp_identity *_identity;
   947 
   948     assert(session);
   949     assert(address);
   950     assert(address[0]);
   951     assert(identity);
   952 
   953     if (!(session && address && address[0] && identity))
   954         return PEP_ILLEGAL_VALUE;
   955 
   956     *identity = NULL;
   957 
   958     sqlite3_reset(session->get_identity);
   959     sqlite3_bind_text(session->get_identity, 1, address, -1, SQLITE_STATIC);
   960     sqlite3_bind_text(session->get_identity, 2, user_id, -1, SQLITE_STATIC);
   961 
   962     const int result = sqlite3_step(session->get_identity);
   963     switch (result) {
   964     case SQLITE_ROW:
   965         _identity = new_identity(
   966                 address,
   967                 (const char *) sqlite3_column_text(session->get_identity, 0),
   968                 user_id,
   969                 (const char *) sqlite3_column_text(session->get_identity, 1)
   970                 );
   971         assert(_identity);
   972         if (_identity == NULL)
   973             return PEP_OUT_OF_MEMORY;
   974 
   975         _identity->comm_type = (PEP_comm_type)
   976             sqlite3_column_int(session->get_identity, 2);
   977         const char* const _lang = (const char *)
   978             sqlite3_column_text(session->get_identity, 3);
   979         if (_lang && _lang[0]) {
   980             assert(_lang[0] >= 'a' && _lang[0] <= 'z');
   981             assert(_lang[1] >= 'a' && _lang[1] <= 'z');
   982             assert(_lang[2] == 0);
   983             _identity->lang[0] = _lang[0];
   984             _identity->lang[1] = _lang[1];
   985             _identity->lang[2] = 0;
   986         }
   987         _identity->flags = (unsigned int)
   988             sqlite3_column_int(session->get_identity, 4);
   989         *identity = _identity;
   990         break;
   991     default:
   992         status = PEP_CANNOT_FIND_IDENTITY;
   993         *identity = NULL;
   994     }
   995 
   996     sqlite3_reset(session->get_identity);
   997     return status;
   998 }
   999 
  1000 DYNAMIC_API PEP_STATUS set_identity(
  1001         PEP_SESSION session, const pEp_identity *identity
  1002     )
  1003 {
  1004     int result;
  1005 
  1006     assert(session);
  1007     assert(identity);
  1008     assert(identity->address);
  1009     assert(identity->fpr);
  1010     assert(identity->user_id);
  1011     assert(identity->username);
  1012 
  1013     if (!(session && identity && identity->address && identity->fpr &&
  1014                 identity->user_id && identity->username))
  1015         return PEP_ILLEGAL_VALUE;
  1016 
  1017     bool listed;
  1018     PEP_STATUS status = blacklist_is_listed(session, identity->fpr, &listed);
  1019     assert(status == PEP_STATUS_OK);
  1020     if (status != PEP_STATUS_OK)
  1021         return status;
  1022 
  1023     if (listed)
  1024         return PEP_KEY_BLACKLISTED;
  1025 
  1026     sqlite3_exec(session->db, "BEGIN ;", NULL, NULL, NULL);
  1027 
  1028     if (identity->lang[0]) {
  1029         assert(identity->lang[0] >= 'a' && identity->lang[0] <= 'z');
  1030         assert(identity->lang[1] >= 'a' && identity->lang[1] <= 'z');
  1031         assert(identity->lang[2] == 0);
  1032     }
  1033 
  1034     sqlite3_reset(session->set_person);
  1035     sqlite3_bind_text(session->set_person, 1, identity->user_id, -1,
  1036             SQLITE_STATIC);
  1037     sqlite3_bind_text(session->set_person, 2, identity->username, -1,
  1038             SQLITE_STATIC);
  1039     if (identity->lang[0])
  1040         sqlite3_bind_text(session->set_person, 3, identity->lang, 2,
  1041                 SQLITE_STATIC);
  1042     else
  1043         sqlite3_bind_null(session->set_person, 3);
  1044     sqlite3_bind_text(session->set_person, 4, identity->fpr, -1,
  1045                       SQLITE_STATIC);
  1046     result = sqlite3_step(session->set_person);
  1047     sqlite3_reset(session->set_person);
  1048     if (result != SQLITE_DONE) {
  1049         sqlite3_exec(session->db, "ROLLBACK ;", NULL, NULL, NULL);
  1050         return PEP_CANNOT_SET_PERSON;
  1051     }
  1052 
  1053     sqlite3_reset(session->set_pgp_keypair);
  1054     sqlite3_bind_text(session->set_pgp_keypair, 1, identity->fpr, -1,
  1055             SQLITE_STATIC);
  1056     result = sqlite3_step(session->set_pgp_keypair);
  1057     sqlite3_reset(session->set_pgp_keypair);
  1058     if (result != SQLITE_DONE) {
  1059         sqlite3_exec(session->db, "ROLLBACK ;", NULL, NULL, NULL);
  1060         return PEP_CANNOT_SET_PGP_KEYPAIR;
  1061     }
  1062 
  1063     sqlite3_reset(session->set_identity);
  1064     sqlite3_bind_text(session->set_identity, 1, identity->address, -1,
  1065             SQLITE_STATIC);
  1066     sqlite3_bind_text(session->set_identity, 2, identity->fpr, -1,
  1067             SQLITE_STATIC);
  1068     sqlite3_bind_text(session->set_identity, 3, identity->user_id, -1,
  1069             SQLITE_STATIC);
  1070     sqlite3_bind_int(session->set_identity, 4, identity->flags);
  1071     result = sqlite3_step(session->set_identity);
  1072     sqlite3_reset(session->set_identity);
  1073     if (result != SQLITE_DONE) {
  1074         sqlite3_exec(session->db, "ROLLBACK ;", NULL, NULL, NULL);
  1075         return PEP_CANNOT_SET_IDENTITY;
  1076     }
  1077 
  1078     sqlite3_reset(session->set_trust);
  1079     sqlite3_bind_text(session->set_trust, 1, identity->user_id, -1,
  1080             SQLITE_STATIC);
  1081     sqlite3_bind_text(session->set_trust, 2, identity->fpr, -1,
  1082             SQLITE_STATIC);
  1083     sqlite3_bind_int(session->set_trust, 3, identity->comm_type);
  1084     result = sqlite3_step(session->set_trust);
  1085     sqlite3_reset(session->set_trust);
  1086     if (result != SQLITE_DONE) {
  1087         sqlite3_exec(session->db, "ROLLBACK ;", NULL, NULL, NULL);
  1088         return PEP_CANNOT_SET_TRUST;
  1089     }
  1090 
  1091     result = sqlite3_exec(session->db, "COMMIT ;", NULL, NULL, NULL);
  1092     if (result == SQLITE_OK)
  1093         return PEP_STATUS_OK;
  1094     else
  1095         return PEP_COMMIT_FAILED;
  1096 }
  1097 
  1098 DYNAMIC_API PEP_STATUS set_device_group(
  1099         PEP_SESSION session,
  1100         const char *group_name
  1101     )
  1102 {
  1103     int result;
  1104 
  1105     assert(session);
  1106     assert(group_name);
  1107 
  1108     if (!(session && group_name))
  1109         return PEP_ILLEGAL_VALUE;
  1110 
  1111     sqlite3_reset(session->set_device_group);
  1112     sqlite3_bind_text(session->set_device_group, 1, group_name, -1,
  1113             SQLITE_STATIC);
  1114     result = sqlite3_step(session->set_device_group);
  1115     sqlite3_reset(session->set_device_group);
  1116     if (result != SQLITE_DONE)
  1117         return PEP_CANNOT_SET_PERSON;
  1118 
  1119     return PEP_STATUS_OK;
  1120 }
  1121 
  1122 DYNAMIC_API PEP_STATUS get_device_group(PEP_SESSION session, char **group_name)
  1123 {
  1124     PEP_STATUS status = PEP_STATUS_OK;
  1125     int result;
  1126 
  1127     assert(session);
  1128     assert(group_name);
  1129 
  1130     if (!(session && group_name))
  1131         return PEP_ILLEGAL_VALUE;
  1132 
  1133     sqlite3_reset(session->get_device_group);
  1134 
  1135     result = sqlite3_step(session->get_device_group);
  1136     switch (result) {
  1137     case SQLITE_ROW: {
  1138         *group_name = strdup(
  1139             (const char *) sqlite3_column_text(session->get_device_group, 0));
  1140             if(*group_name == NULL)
  1141                 status = PEP_OUT_OF_MEMORY;
  1142         break;
  1143     }
  1144  
  1145     default:
  1146         status = PEP_RECORD_NOT_FOUND;
  1147     }
  1148 
  1149     sqlite3_reset(session->get_device_group);
  1150     return status;
  1151 }
  1152 
  1153 DYNAMIC_API PEP_STATUS set_identity_flags(
  1154         PEP_SESSION session,
  1155         pEp_identity *identity,
  1156         unsigned int flags
  1157     )
  1158 {
  1159     int result;
  1160 
  1161     assert(session);
  1162     assert(identity);
  1163     assert(identity->address);
  1164     assert(identity->user_id);
  1165 
  1166     if (!(session && identity && identity->address && identity->user_id))
  1167         return PEP_ILLEGAL_VALUE;
  1168 
  1169     sqlite3_reset(session->set_identity_flags);
  1170     sqlite3_bind_int(session->set_identity_flags, 1, flags);
  1171     sqlite3_bind_text(session->set_identity_flags, 2, identity->address, -1,
  1172             SQLITE_STATIC);
  1173     sqlite3_bind_text(session->set_identity_flags, 3, identity->user_id, -1,
  1174             SQLITE_STATIC);
  1175     result = sqlite3_step(session->set_identity_flags);
  1176     sqlite3_reset(session->set_identity_flags);
  1177     if (result != SQLITE_DONE)
  1178         return PEP_CANNOT_SET_IDENTITY;
  1179 
  1180     identity->flags = flags;
  1181     return PEP_STATUS_OK;
  1182 }
  1183 
  1184 DYNAMIC_API PEP_STATUS mark_as_compromized(
  1185         PEP_SESSION session,
  1186         const char *fpr
  1187     )
  1188 {
  1189     int result;
  1190 
  1191     assert(session);
  1192     assert(fpr && fpr[0]);
  1193 
  1194     if (!(session && fpr && fpr[0]))
  1195         return PEP_ILLEGAL_VALUE;
  1196 
  1197     sqlite3_reset(session->mark_compromized);
  1198     sqlite3_bind_text(session->mark_compromized, 1, fpr, -1,
  1199             SQLITE_STATIC);
  1200     result = sqlite3_step(session->mark_compromized);
  1201     sqlite3_reset(session->mark_compromized);
  1202 
  1203     if (result != SQLITE_DONE)
  1204         return PEP_CANNOT_SET_TRUST;
  1205 
  1206     return PEP_STATUS_OK;
  1207 }
  1208 
  1209 void pEp_free(void *p)
  1210 {
  1211     free(p);
  1212 }
  1213 
  1214 DYNAMIC_API PEP_STATUS get_trust(PEP_SESSION session, pEp_identity *identity)
  1215 {
  1216     PEP_STATUS status = PEP_STATUS_OK;
  1217     int result;
  1218 
  1219     assert(session);
  1220     assert(identity);
  1221     assert(identity->user_id);
  1222     assert(identity->user_id[0]);
  1223     assert(identity->fpr);
  1224     assert(identity->fpr[0]);
  1225 
  1226     if (!(session && identity && identity->user_id && identity->user_id[0] &&
  1227                 identity->fpr && identity->fpr[0]))
  1228         return PEP_ILLEGAL_VALUE;
  1229 
  1230     identity->comm_type = PEP_ct_unknown;
  1231 
  1232     sqlite3_reset(session->get_trust);
  1233     sqlite3_bind_text(session->get_trust, 1, identity->user_id, -1,
  1234             SQLITE_STATIC);
  1235     sqlite3_bind_text(session->get_trust, 2, identity->fpr, -1, SQLITE_STATIC);
  1236 
  1237     result = sqlite3_step(session->get_trust);
  1238     switch (result) {
  1239     case SQLITE_ROW: {
  1240         int comm_type = (PEP_comm_type) sqlite3_column_int(session->get_trust,
  1241                 0);
  1242         identity->comm_type = comm_type;
  1243         break;
  1244     }
  1245  
  1246     default:
  1247         status = PEP_CANNOT_FIND_IDENTITY;
  1248     }
  1249 
  1250     sqlite3_reset(session->get_trust);
  1251     return status;
  1252 }
  1253 
  1254 DYNAMIC_API PEP_STATUS least_trust(
  1255         PEP_SESSION session,
  1256         const char *fpr,
  1257         PEP_comm_type *comm_type
  1258     )
  1259 {
  1260     PEP_STATUS status = PEP_STATUS_OK;
  1261     int result;
  1262 
  1263     assert(session);
  1264     assert(fpr);
  1265     assert(comm_type);
  1266 
  1267     if (!(session && fpr && comm_type))
  1268         return PEP_ILLEGAL_VALUE;
  1269 
  1270     *comm_type = PEP_ct_unknown;
  1271 
  1272     sqlite3_reset(session->least_trust);
  1273     sqlite3_bind_text(session->least_trust, 1, fpr, -1, SQLITE_STATIC);
  1274 
  1275     result = sqlite3_step(session->least_trust);
  1276     switch (result) {
  1277         case SQLITE_ROW: {
  1278             int _comm_type = sqlite3_column_int(session->least_trust, 0);
  1279             *comm_type = (PEP_comm_type) _comm_type;
  1280             break;
  1281         }
  1282         default:
  1283             status = PEP_CANNOT_FIND_IDENTITY;
  1284     }
  1285 
  1286     sqlite3_reset(session->least_trust);
  1287     return status;
  1288 }
  1289 
  1290 DYNAMIC_API PEP_STATUS decrypt_and_verify(
  1291     PEP_SESSION session, const char *ctext, size_t csize,
  1292     char **ptext, size_t *psize, stringlist_t **keylist
  1293     )
  1294 {
  1295     assert(session);
  1296     assert(ctext);
  1297     assert(csize);
  1298     assert(ptext);
  1299     assert(psize);
  1300     assert(keylist);
  1301 
  1302     if (!(session && ctext && csize && ptext && psize && keylist))
  1303         return PEP_ILLEGAL_VALUE;
  1304 
  1305     return session->cryptotech[PEP_crypt_OpenPGP].decrypt_and_verify(
  1306             session, ctext, csize, ptext, psize, keylist);
  1307 }
  1308 
  1309 DYNAMIC_API PEP_STATUS encrypt_and_sign(
  1310     PEP_SESSION session, const stringlist_t *keylist, const char *ptext,
  1311     size_t psize, char **ctext, size_t *csize
  1312     )
  1313 {
  1314     assert(session);
  1315     assert(keylist);
  1316     assert(ptext);
  1317     assert(psize);
  1318     assert(ctext);
  1319     assert(csize);
  1320 
  1321     if (!(session && keylist && ptext && psize && ctext && csize))
  1322         return PEP_ILLEGAL_VALUE;
  1323 
  1324     return session->cryptotech[PEP_crypt_OpenPGP].encrypt_and_sign(session,
  1325             keylist, ptext, psize, ctext, csize);
  1326 }
  1327 
  1328 DYNAMIC_API PEP_STATUS verify_text(
  1329     PEP_SESSION session, const char *text, size_t size,
  1330     const char *signature, size_t sig_size, stringlist_t **keylist
  1331     )
  1332 {
  1333     assert(session);
  1334     assert(text);
  1335     assert(size);
  1336     assert(signature);
  1337     assert(sig_size);
  1338     assert(keylist);
  1339 
  1340     if (!(session && text && size && signature && sig_size && keylist))
  1341         return PEP_ILLEGAL_VALUE;
  1342 
  1343     return session->cryptotech[PEP_crypt_OpenPGP].verify_text(session, text,
  1344             size, signature, sig_size, keylist);
  1345 }
  1346 
  1347 DYNAMIC_API PEP_STATUS delete_keypair(PEP_SESSION session, const char *fpr)
  1348 {
  1349     assert(session);
  1350     assert(fpr);
  1351 
  1352     if (!(session && fpr))
  1353         return PEP_ILLEGAL_VALUE;
  1354 
  1355     return session->cryptotech[PEP_crypt_OpenPGP].delete_keypair(session, fpr);
  1356 }
  1357 
  1358 DYNAMIC_API PEP_STATUS export_key(
  1359         PEP_SESSION session, const char *fpr, char **key_data, size_t *size
  1360     )
  1361 {
  1362     assert(session);
  1363     assert(fpr);
  1364     assert(key_data);
  1365     assert(size);
  1366 
  1367     if (!(session && fpr && key_data && size))
  1368         return PEP_ILLEGAL_VALUE;
  1369 
  1370     return session->cryptotech[PEP_crypt_OpenPGP].export_key(session, fpr,
  1371             key_data, size, false);
  1372 }
  1373 
  1374 DYNAMIC_API PEP_STATUS export_secrect_key(
  1375         PEP_SESSION session, const char *fpr, char **key_data, size_t *size
  1376     )
  1377 {
  1378     assert(session);
  1379     assert(fpr);
  1380     assert(key_data);
  1381     assert(size);
  1382 
  1383     if (!(session && fpr && key_data && size))
  1384         return PEP_ILLEGAL_VALUE;
  1385 
  1386     // don't accept key IDs but full fingerprints only
  1387     if (strlen(fpr) < 16)
  1388         return PEP_ILLEGAL_VALUE;
  1389 
  1390     return session->cryptotech[PEP_crypt_OpenPGP].export_key(session, fpr,
  1391             key_data, size, true);
  1392 }
  1393 
  1394 DYNAMIC_API PEP_STATUS find_keys(
  1395         PEP_SESSION session, const char *pattern, stringlist_t **keylist
  1396     )
  1397 {
  1398     assert(session);
  1399     assert(pattern);
  1400     assert(keylist);
  1401 
  1402     if (!(session && pattern && keylist))
  1403         return PEP_ILLEGAL_VALUE;
  1404 
  1405     return session->cryptotech[PEP_crypt_OpenPGP].find_keys(session, pattern,
  1406             keylist);
  1407 }
  1408 
  1409 
  1410 DYNAMIC_API PEP_STATUS generate_keypair(
  1411         PEP_SESSION session, pEp_identity *identity
  1412     )
  1413 {
  1414     assert(session);
  1415     assert(identity);
  1416     assert(identity->address);
  1417     assert(identity->fpr == NULL || identity->fpr[0] == 0);
  1418     assert(identity->username);
  1419 
  1420     if (!(session && identity && identity->address &&
  1421             (identity->fpr == NULL || identity->fpr[0] == 0) &&
  1422             identity->username))
  1423         return PEP_ILLEGAL_VALUE;
  1424 
  1425     PEP_STATUS status =
  1426         session->cryptotech[PEP_crypt_OpenPGP].generate_keypair(session,
  1427                 identity);
  1428     if (status != PEP_STATUS_OK)
  1429         return status;
  1430 
  1431     return status;
  1432 }
  1433 
  1434 DYNAMIC_API PEP_STATUS get_key_rating(
  1435         PEP_SESSION session,
  1436         const char *fpr,
  1437         PEP_comm_type *comm_type
  1438     )
  1439 {
  1440     assert(session);
  1441     assert(fpr);
  1442     assert(comm_type);
  1443 
  1444     if (!(session && fpr && comm_type))
  1445         return PEP_ILLEGAL_VALUE;
  1446 
  1447     return session->cryptotech[PEP_crypt_OpenPGP].get_key_rating(session, fpr,
  1448             comm_type);
  1449 }
  1450 
  1451 DYNAMIC_API PEP_STATUS import_key(
  1452         PEP_SESSION session,
  1453         const char *key_data,
  1454         size_t size,
  1455         identity_list **private_keys
  1456     )
  1457 {
  1458     assert(session);
  1459     assert(key_data);
  1460 
  1461     if (!(session && key_data))
  1462         return PEP_ILLEGAL_VALUE;
  1463 
  1464     return session->cryptotech[PEP_crypt_OpenPGP].import_key(session, key_data,
  1465             size, private_keys);
  1466 }
  1467 
  1468 DYNAMIC_API PEP_STATUS recv_key(PEP_SESSION session, const char *pattern)
  1469 {
  1470     assert(session);
  1471     assert(pattern);
  1472 
  1473     if (!(session && pattern))
  1474         return PEP_ILLEGAL_VALUE;
  1475 
  1476     return session->cryptotech[PEP_crypt_OpenPGP].recv_key(session, pattern);
  1477 }
  1478 
  1479 DYNAMIC_API PEP_STATUS send_key(PEP_SESSION session, const char *pattern)
  1480 {
  1481     assert(session);
  1482     assert(pattern);
  1483 
  1484     if (!(session && pattern))
  1485         return PEP_ILLEGAL_VALUE;
  1486 
  1487     return session->cryptotech[PEP_crypt_OpenPGP].send_key(session, pattern);
  1488 }
  1489 
  1490 DYNAMIC_API PEP_STATUS renew_key(
  1491         PEP_SESSION session,
  1492         const char *fpr,
  1493         const timestamp *ts
  1494     )
  1495 {
  1496     assert(session);
  1497     assert(fpr);
  1498 
  1499     if (!(session && fpr))
  1500         return PEP_ILLEGAL_VALUE;
  1501 
  1502     return session->cryptotech[PEP_crypt_OpenPGP].renew_key(session, fpr, ts);
  1503 }
  1504 
  1505 DYNAMIC_API PEP_STATUS revoke_key(
  1506         PEP_SESSION session,
  1507         const char *fpr,
  1508         const char *reason
  1509     )
  1510 {
  1511     assert(session);
  1512     assert(fpr);
  1513 
  1514     if (!(session && fpr))
  1515         return PEP_ILLEGAL_VALUE;
  1516 
  1517     return session->cryptotech[PEP_crypt_OpenPGP].revoke_key(session, fpr,
  1518             reason);
  1519 }
  1520 
  1521 DYNAMIC_API PEP_STATUS key_expired(
  1522         PEP_SESSION session,
  1523         const char *fpr,
  1524         const time_t when,
  1525         bool *expired
  1526     )
  1527 {
  1528     assert(session);
  1529     assert(fpr);
  1530     assert(expired);
  1531 
  1532     if (!(session && fpr && expired))
  1533         return PEP_ILLEGAL_VALUE;
  1534 
  1535     return session->cryptotech[PEP_crypt_OpenPGP].key_expired(session, fpr,
  1536             when, expired);
  1537 }
  1538 
  1539 DYNAMIC_API PEP_STATUS key_revoked(
  1540        PEP_SESSION session,
  1541        const char *fpr,
  1542        bool *revoked
  1543    )
  1544 {
  1545     assert(session);
  1546     assert(fpr);
  1547     assert(revoked);
  1548     
  1549     if (!(session && fpr && revoked))
  1550         return PEP_ILLEGAL_VALUE;
  1551     
  1552     return session->cryptotech[PEP_crypt_OpenPGP].key_revoked(session, fpr,
  1553             revoked);
  1554 }
  1555 
  1556 static void _clean_log_value(char *text)
  1557 {
  1558     if (text) {
  1559         for (char *c = text; *c; c++) {
  1560             if (*c < 32 && *c != '\n')
  1561                 *c = 32;
  1562             else if (*c == '"')
  1563                 *c = '\'';
  1564         }
  1565     }
  1566 }
  1567 
  1568 static char *_concat_string(char *str1, const char *str2, char delim)
  1569 {
  1570     str2 = str2 ? str2 : "";
  1571     size_t len1 = str1 ? strlen(str1) : 0;
  1572     size_t len2 = strlen(str2);
  1573     size_t len = len1 + len2 + 3;
  1574     char * result = realloc(str1, len + 1);
  1575 
  1576     if (result) {
  1577         result[len1] = '"';
  1578         strcpy(result + len1 + 1, str2);
  1579         result[len - 2] = '"';
  1580         result[len - 1] = delim;
  1581         result[len] = 0;
  1582     }
  1583     else {
  1584         free(str1);
  1585     }
  1586 
  1587     return result;
  1588 }
  1589 
  1590 DYNAMIC_API PEP_STATUS get_crashdump_log(
  1591         PEP_SESSION session,
  1592         int maxlines,
  1593         char **logdata
  1594     )
  1595 {
  1596     PEP_STATUS status = PEP_STATUS_OK;
  1597     char *_logdata= NULL;
  1598 
  1599     assert(session);
  1600     assert(maxlines >= 0 && maxlines <= CRASHDUMP_MAX_LINES);
  1601     assert(logdata);
  1602 
  1603     if (!(session && logdata && maxlines >= 0 && maxlines <=
  1604             CRASHDUMP_MAX_LINES))
  1605         return PEP_ILLEGAL_VALUE;
  1606 
  1607     *logdata = NULL;
  1608 
  1609     int limit = maxlines ? maxlines : CRASHDUMP_DEFAULT_LINES;
  1610     const char *timestamp = NULL;
  1611     const char *title = NULL;
  1612     const char *entity = NULL;
  1613     const char *desc = NULL;
  1614     const char *comment = NULL;
  1615 
  1616     sqlite3_reset(session->crashdump);
  1617     sqlite3_bind_int(session->crashdump, 1, limit);
  1618 
  1619     int result;
  1620 
  1621     do {
  1622         result = sqlite3_step(session->crashdump);
  1623         switch (result) {
  1624         case SQLITE_ROW:
  1625             timestamp = (const char *) sqlite3_column_text(session->crashdump,
  1626                     0);
  1627             title   = (const char *) sqlite3_column_text(session->crashdump,
  1628                     1);
  1629             entity  = (const char *) sqlite3_column_text(session->crashdump,
  1630                     2);
  1631             desc    = (const char *) sqlite3_column_text(session->crashdump,
  1632                     3);
  1633             comment = (const char *) sqlite3_column_text(session->crashdump,
  1634                     4);
  1635 
  1636             _logdata = _concat_string(_logdata, timestamp, ',');
  1637             if (_logdata == NULL)
  1638                 goto enomem;
  1639 
  1640             _logdata = _concat_string(_logdata, title, ',');
  1641             if (_logdata == NULL)
  1642                 goto enomem;
  1643 
  1644             _logdata = _concat_string(_logdata, entity, ',');
  1645             if (_logdata == NULL)
  1646                 goto enomem;
  1647 
  1648             _logdata = _concat_string(_logdata, desc, ',');
  1649             if (_logdata == NULL)
  1650                 goto enomem;
  1651 
  1652             _logdata = _concat_string(_logdata, comment, '\n');
  1653             if (_logdata == NULL)
  1654                 goto enomem;
  1655 
  1656             _clean_log_value(_logdata);
  1657             break;
  1658 
  1659         case SQLITE_DONE:
  1660             break;
  1661 
  1662         default:
  1663             status = PEP_UNKNOWN_ERROR;
  1664             result = SQLITE_DONE;
  1665         }
  1666     } while (result != SQLITE_DONE);
  1667 
  1668     sqlite3_reset(session->crashdump);
  1669     if (status == PEP_STATUS_OK)
  1670         *logdata = _logdata;
  1671 
  1672     goto the_end;
  1673 
  1674 enomem:
  1675     status = PEP_OUT_OF_MEMORY;
  1676 
  1677 the_end:
  1678     return status;
  1679 }
  1680 
  1681 DYNAMIC_API PEP_STATUS get_languagelist(
  1682         PEP_SESSION session,
  1683         char **languages
  1684     )
  1685 {
  1686     PEP_STATUS status = PEP_STATUS_OK;
  1687     char *_languages= NULL;
  1688 
  1689     assert(session);
  1690     assert(languages);
  1691 
  1692     if (!(session && languages))
  1693         return PEP_ILLEGAL_VALUE;
  1694 
  1695     *languages = NULL;
  1696 
  1697     const char *lang = NULL;
  1698     const char *name = NULL;
  1699     const char *phrase = NULL;
  1700 
  1701     sqlite3_reset(session->languagelist);
  1702 
  1703     int result;
  1704 
  1705     do {
  1706         result = sqlite3_step(session->languagelist);
  1707         switch (result) {
  1708         case SQLITE_ROW:
  1709             lang = (const char *) sqlite3_column_text(session->languagelist,
  1710                     0);
  1711             name = (const char *) sqlite3_column_text(session->languagelist,
  1712                     1);
  1713             phrase = (const char *) sqlite3_column_text(session->languagelist,
  1714                     2);
  1715 
  1716             _languages = _concat_string(_languages, lang, ',');
  1717             if (_languages == NULL)
  1718                 goto enomem;
  1719 
  1720             _languages = _concat_string(_languages, name, ',');
  1721             if (_languages == NULL)
  1722                 goto enomem;
  1723 
  1724             _languages = _concat_string(_languages, phrase, '\n');
  1725             if (_languages == NULL)
  1726                 goto enomem;
  1727 
  1728             break;
  1729 
  1730         case SQLITE_DONE:
  1731             break;
  1732 
  1733         default:
  1734             status = PEP_UNKNOWN_ERROR;
  1735             result = SQLITE_DONE;
  1736         }
  1737     } while (result != SQLITE_DONE);
  1738 
  1739     sqlite3_reset(session->languagelist);
  1740     if (status == PEP_STATUS_OK)
  1741         *languages = _languages;
  1742 
  1743     goto the_end;
  1744 
  1745 enomem:
  1746     status = PEP_OUT_OF_MEMORY;
  1747 
  1748 the_end:
  1749     return status;
  1750 }
  1751 
  1752 DYNAMIC_API PEP_STATUS get_phrase(
  1753         PEP_SESSION session,
  1754         const char *lang,
  1755         int phrase_id,
  1756         char **phrase
  1757     )
  1758 {
  1759     PEP_STATUS status = PEP_STATUS_OK;
  1760 
  1761     assert(session && lang && lang[0] && lang[1] && lang[2] == 0 && phrase);
  1762     if (!(session && lang && lang[0] && lang[1] && lang[2] == 0 && phrase))
  1763         return PEP_ILLEGAL_VALUE;
  1764 
  1765     *phrase = NULL;
  1766 
  1767     sqlite3_reset(session->i18n_token);
  1768     sqlite3_bind_text(session->i18n_token, 1, lang, -1, SQLITE_STATIC);
  1769     sqlite3_bind_int(session->i18n_token, 2, phrase_id);
  1770 
  1771     const char *_phrase = NULL;
  1772     int result;
  1773 
  1774     result = sqlite3_step(session->i18n_token);
  1775     switch (result) {
  1776     case SQLITE_ROW:
  1777         _phrase = (const char *) sqlite3_column_text(session->i18n_token, 0);
  1778         break;
  1779 
  1780     case SQLITE_DONE:
  1781         status = PEP_PHRASE_NOT_FOUND;
  1782         break;
  1783 
  1784     default:
  1785         status = PEP_UNKNOWN_ERROR;
  1786     }
  1787 
  1788     if (status == PEP_STATUS_OK) {
  1789         *phrase = strdup(_phrase);
  1790         if (*phrase == NULL)
  1791             goto enomem;
  1792     }
  1793 
  1794     sqlite3_reset(session->i18n_token);
  1795     goto the_end;
  1796 
  1797 enomem:
  1798     status = PEP_OUT_OF_MEMORY;
  1799 
  1800 the_end:
  1801     return status;
  1802 }
  1803 
  1804 static PEP_STATUS _get_sequence_value(PEP_SESSION session, const char *name,
  1805         int32_t *value)
  1806 {
  1807     assert(session && name && value);
  1808     if (!(session && name && value))
  1809         return PEP_ILLEGAL_VALUE;
  1810 
  1811     PEP_STATUS status = PEP_STATUS_OK;
  1812 
  1813     sqlite3_reset(session->sequence_value2);
  1814     sqlite3_bind_text(session->sequence_value2, 1, name, -1,
  1815             SQLITE_STATIC);
  1816     int result = sqlite3_step(session->sequence_value2);
  1817     switch (result) {
  1818         case SQLITE_ROW: {
  1819             int32_t _value = (int32_t)
  1820                     sqlite3_column_int(session->sequence_value2, 0);
  1821             int _own = (int)
  1822                     sqlite3_column_int(session->sequence_value2, 1);
  1823             *value = _value;
  1824             if (_own)
  1825                 status = PEP_OWN_SEQUENCE;
  1826             break;
  1827         }
  1828         case SQLITE_DONE:
  1829             status = PEP_RECORD_NOT_FOUND;
  1830             break;
  1831         default:
  1832             status = PEP_UNKNOWN_ERROR;
  1833     }
  1834     sqlite3_reset(session->sequence_value2);
  1835 
  1836     return status;
  1837 }
  1838 
  1839 static PEP_STATUS _increment_sequence_value(PEP_SESSION session,
  1840         const char *name, int own)
  1841 {
  1842     assert(session && name);
  1843     if (!(session && name))
  1844         return PEP_ILLEGAL_VALUE;
  1845 
  1846     sqlite3_reset(session->sequence_value1);
  1847     sqlite3_bind_text(session->sequence_value1, 1, name, -1, SQLITE_STATIC);
  1848     sqlite3_bind_int(session->sequence_value1, 2, own);
  1849     int result = sqlite3_step(session->sequence_value1);
  1850     assert(result == SQLITE_DONE);
  1851     sqlite3_reset(session->sequence_value1);
  1852     if (result == SQLITE_DONE)
  1853         return PEP_STATUS_OK;
  1854     else
  1855         return PEP_CANNOT_INCREASE_SEQUENCE;
  1856 }
  1857 
  1858 static PEP_STATUS _set_sequence_value(PEP_SESSION session,
  1859         const char *name, int32_t value, int own)
  1860 {
  1861     assert(session && name && value > 0);
  1862     if (!(session && name && value > 0))
  1863         return PEP_ILLEGAL_VALUE;
  1864 
  1865     sqlite3_reset(session->sequence_value3);
  1866     sqlite3_bind_text(session->sequence_value3, 1, name, -1, SQLITE_STATIC);
  1867     sqlite3_bind_int(session->sequence_value3, 2, value);
  1868     sqlite3_bind_int(session->sequence_value3, 3, own);
  1869     int result = sqlite3_step(session->sequence_value3);
  1870     assert(result == SQLITE_DONE);
  1871     sqlite3_reset(session->sequence_value3);
  1872     if (result == SQLITE_DONE)
  1873         return PEP_STATUS_OK;
  1874     else
  1875         return PEP_CANNOT_SET_SEQUENCE_VALUE;
  1876 }
  1877 
  1878 DYNAMIC_API PEP_STATUS sequence_value(
  1879         PEP_SESSION session,
  1880         char *name,
  1881         int32_t *value
  1882     )
  1883 {
  1884     PEP_STATUS status = PEP_STATUS_OK;
  1885 
  1886     assert(session);
  1887     assert(name && value && *value >= 0);
  1888 
  1889     if (!(session && name && value && *value >= 0))
  1890         return PEP_ILLEGAL_VALUE;
  1891 
  1892     int own = 0;
  1893     if (!name[0]) {
  1894         unsigned char uuid[16];
  1895         uuid_generate_random(uuid);
  1896         uuid_unparse_upper(uuid, name);
  1897         own = 1;
  1898     }
  1899     else {
  1900         if (name == sync_uuid || strcmp(name, sync_uuid) == 0)
  1901             own = 1;
  1902     }
  1903 
  1904     if (*value) {
  1905         int32_t old_value = 0;
  1906         status = _get_sequence_value(session, name, &old_value);
  1907         if (status != PEP_STATUS_OK && status != PEP_RECORD_NOT_FOUND)
  1908             return status;
  1909 
  1910         if (old_value >= *value) {
  1911             return PEP_SEQUENCE_VIOLATED;
  1912         }
  1913         else {
  1914             status = _set_sequence_value(session, name, *value, own);
  1915             return status;
  1916         }
  1917     }
  1918 
  1919     assert(*value == 0);
  1920     status = _increment_sequence_value(session, name, own);
  1921     if (status == PEP_STATUS_OK) {
  1922         status = _get_sequence_value(session, name, value);
  1923         assert(*value < INT32_MAX);
  1924         if (*value == INT32_MAX)
  1925             return PEP_CANNOT_INCREASE_SEQUENCE;
  1926     }
  1927     return status;
  1928 }
  1929 
  1930 DYNAMIC_API PEP_STATUS set_revoked(
  1931        PEP_SESSION session,
  1932        const char *revoked_fpr,
  1933        const char *replacement_fpr,
  1934        const uint64_t revocation_date
  1935     )
  1936 {
  1937     PEP_STATUS status = PEP_STATUS_OK;
  1938     
  1939     assert(session &&
  1940            revoked_fpr && revoked_fpr[0] &&
  1941            replacement_fpr && replacement_fpr[0]
  1942           );
  1943     
  1944     if (!(session &&
  1945           revoked_fpr && revoked_fpr[0] &&
  1946           replacement_fpr && replacement_fpr[0]
  1947          ))
  1948         return PEP_ILLEGAL_VALUE;
  1949     
  1950     sqlite3_reset(session->set_revoked);
  1951     sqlite3_bind_text(session->set_revoked, 1, revoked_fpr, -1, SQLITE_STATIC);
  1952     sqlite3_bind_text(session->set_revoked, 2, replacement_fpr, -1,
  1953             SQLITE_STATIC);
  1954     sqlite3_bind_int64(session->set_revoked, 3, revocation_date);
  1955 
  1956     int result;
  1957     
  1958     result = sqlite3_step(session->set_revoked);
  1959     switch (result) {
  1960         case SQLITE_DONE:
  1961             status = PEP_STATUS_OK;
  1962             break;
  1963             
  1964         default:
  1965             status = PEP_UNKNOWN_ERROR;
  1966     }
  1967     
  1968     sqlite3_reset(session->set_revoked);
  1969     return status;
  1970 }
  1971 
  1972 DYNAMIC_API PEP_STATUS get_revoked(
  1973         PEP_SESSION session,
  1974         const char *fpr,
  1975         char **revoked_fpr,
  1976         uint64_t *revocation_date
  1977     )
  1978 {
  1979     PEP_STATUS status = PEP_STATUS_OK;
  1980 
  1981     assert(session &&
  1982            revoked_fpr &&
  1983            fpr && fpr[0]
  1984           );
  1985     
  1986     if (!(session &&
  1987            revoked_fpr &&
  1988            fpr && fpr[0]
  1989           ))
  1990         return PEP_ILLEGAL_VALUE;
  1991 
  1992     *revoked_fpr = NULL;
  1993     *revocation_date = 0;
  1994 
  1995     sqlite3_reset(session->get_revoked);
  1996     sqlite3_bind_text(session->get_revoked, 1, fpr, -1, SQLITE_STATIC);
  1997 
  1998     int result;
  1999     
  2000     result = sqlite3_step(session->get_revoked);
  2001     switch (result) {
  2002         case SQLITE_ROW: {
  2003             *revoked_fpr = strdup((const char *)
  2004                     sqlite3_column_text(session->get_revoked, 0));
  2005             if(*revoked_fpr)
  2006                 *revocation_date = sqlite3_column_int64(session->get_revoked,
  2007                         1);
  2008             else
  2009                 status = PEP_OUT_OF_MEMORY;
  2010 
  2011             break;
  2012         }
  2013         default:
  2014             status = PEP_CANNOT_FIND_IDENTITY;
  2015     }
  2016 
  2017     sqlite3_reset(session->get_revoked);
  2018 
  2019     return status;
  2020 }
  2021 
  2022 PEP_STATUS key_created(
  2023         PEP_SESSION session,
  2024         const char *fpr,
  2025         time_t *created
  2026     )
  2027 {
  2028     assert(session && fpr && created);
  2029     if (!(session && fpr && created))
  2030         return PEP_ILLEGAL_VALUE;
  2031 
  2032     return session->cryptotech[PEP_crypt_OpenPGP].key_created(session, fpr,
  2033             created);
  2034 }
  2035 
  2036 DYNAMIC_API const char* get_engine_version() {
  2037     return PEP_ENGINE_VERSION;
  2038 }
  2039 
  2040 
  2041 DYNAMIC_API PEP_STATUS reset_peptest_hack(PEP_SESSION session)
  2042 {
  2043     assert(session);
  2044 
  2045     if (!session)
  2046         return PEP_ILLEGAL_VALUE;
  2047 
  2048     int int_result = sqlite3_exec(
  2049         session->db,
  2050         "delete from identity where address like '%@peptest.ch' ;",
  2051         NULL,
  2052         NULL,
  2053         NULL
  2054     );
  2055     assert(int_result == SQLITE_OK);
  2056 
  2057     return PEP_STATUS_OK;
  2058 }
  2059