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