src/pgp_sequoia.c
author Neal H. Walfield <neal@pep.foundation>
Wed, 26 Dec 2018 20:48:02 +0100
branchsync
changeset 3211 8ca54e726b3c
parent 3209 c15b4ca2b52a
child 3212 fb4124923112
permissions -rw-r--r--
Make it easier to enable or disable tracing in the Sequoia build.

- If TRACE is not explicitly set, make the default still depend on
NDEBUG.
     1 // This file is under GNU General Public License 3.0
     2 // see LICENSE.txt
     3 
     4 #define _GNU_SOURCE 1
     5 
     6 #include "platform.h"
     7 #include "pEp_internal.h"
     8 #include "pgp_gpg.h"
     9 
    10 #include <limits.h>
    11 #include <sys/stat.h>
    12 #include <sys/types.h>
    13 #include <error.h>
    14 
    15 #include <sqlite3.h>
    16 
    17 #include "wrappers.h"
    18 
    19 #define TRACE 0
    20 #ifndef TRACING
    21 #  ifndef NDEBUG
    22 #    define TRACING 0
    23 #  else
    24 #    define TRACING 1
    25 #  endif
    26 #endif
    27 
    28 // enable tracing if in debugging mode
    29 #if TRACING
    30 #  define _T(...) do {                          \
    31         fprintf(stderr, ##__VA_ARGS__);         \
    32     } while (0)
    33 #else
    34 #  define _T(...) do { } while (0)
    35 #endif
    36 
    37 // Show the start of a tracepoint (i.e., don't print a newline).
    38 #define TC(...) do {       \
    39     _T("%s: ", __func__);  \
    40     _T(__VA_ARGS__);       \
    41 } while (0)
    42 
    43 // Show a trace point.
    44 #  define T(...) do {  \
    45     TC(__VA_ARGS__); \
    46     _T("\n");          \
    47 } while(0)
    48 
    49 // Verbosely displays errors.
    50 #  define DUMP_ERR(__de_session, __de_status, ...) do {             \
    51     TC(__VA_ARGS__);                                                \
    52     _T(": ");                                                       \
    53     if ((__de_session->ctx)) {                                      \
    54         sq_error_t __de_err                                         \
    55             = sq_context_last_error((__de_session->ctx));           \
    56         if (__de_err)                                               \
    57             _T("Sequoia: %s => ", sq_error_string(__de_err));       \
    58         sq_error_free(__de_err);                                    \
    59     }                                                               \
    60     _T("%s\n", pep_status_to_string(__de_status));                  \
    61 } while(0)
    62 
    63 // If __ec_status is an error, then disable the error, set 'status' to
    64 // it, and jump to 'out'.
    65 #define ERROR_OUT(__e_session, __ec_status, ...) do {               \
    66     PEP_STATUS ___ec_status = (__ec_status);                        \
    67     if ((___ec_status) != PEP_STATUS_OK) {                          \
    68         DUMP_ERR((__e_session), (___ec_status), ##__VA_ARGS__);     \
    69         status = (___ec_status);                                    \
    70         goto out;                                                   \
    71     }                                                               \
    72 } while(0)
    73 
    74 PEP_STATUS pgp_init(PEP_SESSION session, bool in_first)
    75 {
    76     PEP_STATUS status = PEP_STATUS_OK;
    77 
    78     sq_error_t err;
    79     session->ctx = sq_context_new("foundation.pep", &err);
    80     if (session->ctx == NULL)
    81         ERROR_OUT(session, PEP_INIT_GPGME_INIT_FAILED,
    82                   "initializing sequoia context");
    83 
    84     // Create the home directory.
    85     char *home_env = getenv("HOME");
    86     if (!home_env)
    87         ERROR_OUT(session, PEP_INIT_GPGME_INIT_FAILED, "HOME unset");
    88 
    89     // Create the DB and initialize it.
    90     char *path = NULL;
    91     asprintf(&path, "%s/.pEp_keys.db", home_env);
    92     if (!path)
    93         ERROR_OUT(session, PEP_OUT_OF_MEMORY, "out of memory");
    94 
    95     int sqlite_result;
    96     sqlite_result = sqlite3_open_v2(path,
    97                                     &session->key_db,
    98                                     SQLITE_OPEN_READWRITE
    99                                     | SQLITE_OPEN_CREATE
   100                                     | SQLITE_OPEN_FULLMUTEX
   101                                     | SQLITE_OPEN_PRIVATECACHE,
   102                                     NULL);
   103     free(path);
   104     if (sqlite_result != SQLITE_OK)
   105         ERROR_OUT(session, PEP_INIT_CANNOT_OPEN_DB,
   106                   "opening keys DB: %s",
   107                   sqlite3_errmsg(session->key_db));
   108 
   109     sqlite_result = sqlite3_exec(session->key_db,
   110                                  "PRAGMA locking_mode=NORMAL;\n"
   111                                  "PRAGMA journal_mode=WAL;\n",
   112                                  NULL, NULL, NULL);
   113     if (sqlite_result != SQLITE_OK)
   114         ERROR_OUT(session, PEP_INIT_CANNOT_OPEN_DB,
   115                   "setting pragmas: %s", sqlite3_errmsg(session->key_db));
   116 
   117     sqlite3_busy_timeout(session->key_db, BUSY_WAIT_TIME);
   118 
   119     sqlite_result = sqlite3_exec(session->key_db,
   120                                  "CREATE TABLE IF NOT EXISTS keys (\n"
   121                                  "   primary_key TEXT UNIQUE PRIMARY KEY,\n"
   122                                  "   secret BOOLEAN,\n"
   123                                  "   tpk BLOB\n"
   124                                  ");\n"
   125                                  "CREATE INDEX IF NOT EXISTS keys_index\n"
   126                                  "  ON keys (primary_key, secret)\n",
   127                                  NULL, NULL, NULL);
   128     if (sqlite_result != SQLITE_OK)
   129         ERROR_OUT(session, PEP_INIT_CANNOT_OPEN_DB,
   130                   "creating keys table: %s",
   131                   sqlite3_errmsg(session->key_db));
   132 
   133     sqlite_result = sqlite3_exec(session->key_db,
   134                                  "CREATE TABLE IF NOT EXISTS subkeys (\n"
   135                                  "   subkey TEXT NOT NULL,\n"
   136                                  "   primary_key TEXT NOT NULL,\n"
   137                                  "   UNIQUE(subkey, primary_key),\n"
   138                                  "   FOREIGN KEY (primary_key)\n"
   139                                  "       REFERENCES keys(primary_key)\n"
   140                                  "     ON DELETE CASCADE\n"
   141                                  ");\n"
   142                                  "CREATE INDEX IF NOT EXISTS subkeys_index\n"
   143                                  "  ON subkeys (subkey, primary_key)\n",
   144                                  NULL, NULL, NULL);
   145     if (sqlite_result != SQLITE_OK)
   146         ERROR_OUT(session, PEP_INIT_CANNOT_OPEN_DB,
   147                   "creating subkeys table: %s",
   148                   sqlite3_errmsg(session->key_db));
   149 
   150     sqlite_result = sqlite3_exec(session->key_db,
   151                                  "CREATE TABLE IF NOT EXISTS userids (\n"
   152                                  "   userid TEXT NOT NULL,\n"
   153                                  "   primary_key TEXT NOT NULL,\n"
   154                                  "   UNIQUE(userid, primary_key),\n"
   155                                  "   FOREIGN KEY (primary_key)\n"
   156                                  "       REFERENCES keys(primary_key)\n"
   157                                  "     ON DELETE CASCADE\n"
   158                                  ");\n"
   159                                  "CREATE INDEX IF NOT EXISTS userids_index\n"
   160                                  "  ON userids (userid, primary_key)\n",
   161                                  NULL, NULL, NULL);
   162     if (sqlite_result != SQLITE_OK)
   163         ERROR_OUT(session, PEP_INIT_CANNOT_OPEN_DB,
   164                   "creating userids table: %s",
   165                   sqlite3_errmsg(session->key_db));
   166 
   167     sqlite_result
   168         = sqlite3_prepare_v2(session->key_db, "begin transaction",
   169                              -1, &session->begin_transaction, NULL);
   170     assert(sqlite_result == SQLITE_OK);
   171 
   172     sqlite_result
   173         = sqlite3_prepare_v2(session->key_db, "commit transaction",
   174                              -1, &session->commit_transaction, NULL);
   175     assert(sqlite_result == SQLITE_OK);
   176 
   177     sqlite_result
   178         = sqlite3_prepare_v2(session->key_db, "rollback transaction",
   179                              -1, &session->rollback_transaction, NULL);
   180     assert(sqlite_result == SQLITE_OK);
   181 
   182     sqlite_result
   183         = sqlite3_prepare_v2(session->key_db,
   184                              "SELECT tpk, secret FROM keys"
   185                              " WHERE primary_key == ?",
   186                              -1, &session->tpk_find, NULL);
   187     assert(sqlite_result == SQLITE_OK);
   188 
   189     sqlite_result
   190         = sqlite3_prepare_v2(session->key_db,
   191                              "SELECT tpk, secret FROM keys"
   192                              " WHERE primary_key == ? and secret == 1",
   193                              -1, &session->tsk_find, NULL);
   194     assert(sqlite_result == SQLITE_OK);
   195 
   196     sqlite_result
   197         = sqlite3_prepare_v2(session->key_db,
   198                              "SELECT tpk, secret FROM subkeys"
   199                              " LEFT JOIN keys"
   200                              "  ON subkeys.primary_key == keys.primary_key"
   201                              " WHERE subkey == ?",
   202                              -1, &session->tpk_find_by_keyid, NULL);
   203     assert(sqlite_result == SQLITE_OK);
   204 
   205     sqlite_result
   206         = sqlite3_prepare_v2(session->key_db,
   207                              "SELECT tpk, secret FROM subkeys"
   208                              " LEFT JOIN keys"
   209                              "  ON subkeys.primary_key == keys.primary_key"
   210                              " WHERE subkey == ?",
   211                              -1, &session->tpk_find_by_keyid, NULL);
   212     assert(sqlite_result == SQLITE_OK);
   213 
   214     sqlite_result
   215         = sqlite3_prepare_v2(session->key_db,
   216                              "SELECT tpk, secret FROM subkeys"
   217                              " LEFT JOIN keys"
   218                              "  ON subkeys.primary_key == keys.primary_key"
   219                              " WHERE subkey == ? and keys.secret == 1",
   220                              -1, &session->tsk_find_by_keyid, NULL);
   221     assert(sqlite_result == SQLITE_OK);
   222 
   223     sqlite_result
   224         = sqlite3_prepare_v2(session->key_db,
   225                              "SELECT tpk, secret FROM userids"
   226                              " LEFT JOIN keys"
   227                              "  ON userids.primary_key == keys.primary_key"
   228                              " WHERE userid == ?",
   229                              -1, &session->tpk_find_by_email, NULL);
   230     assert(sqlite_result == SQLITE_OK);
   231 
   232     sqlite_result
   233         = sqlite3_prepare_v2(session->key_db,
   234                              "SELECT tpk, secret FROM userids"
   235                              " LEFT JOIN keys"
   236                              "  ON userids.primary_key == keys.primary_key"
   237                              " WHERE userid == ? and keys.secret == 1",
   238                              -1, &session->tsk_find_by_email, NULL);
   239     assert(sqlite_result == SQLITE_OK);
   240 
   241     sqlite_result
   242         = sqlite3_prepare_v2(session->key_db,
   243                              "select tpk, secret from keys",
   244                              -1, &session->tpk_all, NULL);
   245     assert(sqlite_result == SQLITE_OK);
   246 
   247     sqlite_result
   248         = sqlite3_prepare_v2(session->key_db,
   249                              "select tpk, secret from keys where secret = 1",
   250                              -1, &session->tsk_all, NULL);
   251     assert(sqlite_result == SQLITE_OK);
   252 
   253     sqlite_result
   254         = sqlite3_prepare_v2(session->key_db,
   255                              "INSERT OR REPLACE INTO keys"
   256                              "   (primary_key, secret, tpk)"
   257                              " VALUES (?, ?, ?)",
   258                              -1, &session->tpk_save_insert_primary, NULL);
   259     assert(sqlite_result == SQLITE_OK);
   260 
   261     sqlite_result
   262         = sqlite3_prepare_v2(session->key_db,
   263                              "INSERT OR REPLACE INTO subkeys"
   264                              "   (subkey, primary_key)"
   265                              " VALUES (?, ?)",
   266                              -1, &session->tpk_save_insert_subkeys, NULL);
   267     assert(sqlite_result == SQLITE_OK);
   268 
   269     sqlite_result
   270         = sqlite3_prepare_v2(session->key_db,
   271                              "INSERT OR REPLACE INTO userids"
   272                              "   (userid, primary_key)"
   273                              " VALUES (?, ?)",
   274                              -1, &session->tpk_save_insert_userids, NULL);
   275     assert(sqlite_result == SQLITE_OK);
   276 
   277  out:
   278     if (status != PEP_STATUS_OK)
   279         pgp_release(session, in_first);
   280     return status;
   281 }
   282 
   283 void pgp_release(PEP_SESSION session, bool out_last)
   284 {
   285     if (session->begin_transaction)
   286         sqlite3_finalize(session->begin_transaction);
   287     session->begin_transaction = NULL;
   288     if (session->commit_transaction)
   289         sqlite3_finalize(session->commit_transaction);
   290     session->commit_transaction = NULL;
   291     if (session->rollback_transaction)
   292         sqlite3_finalize(session->rollback_transaction);
   293     session->rollback_transaction = NULL;
   294 
   295     if (session->tpk_find)
   296         sqlite3_finalize(session->tpk_find);
   297     session->tpk_find = NULL;
   298     if (session->tsk_find)
   299         sqlite3_finalize(session->tsk_find);
   300     session->tsk_find = NULL;
   301 
   302     if (session->tpk_find_by_keyid)
   303         sqlite3_finalize(session->tpk_find_by_keyid);
   304     session->tpk_find_by_keyid = NULL;
   305     if (session->tsk_find_by_keyid)
   306         sqlite3_finalize(session->tsk_find_by_keyid);
   307     session->tsk_find_by_keyid = NULL;
   308 
   309     if (session->tpk_find_by_email)
   310         sqlite3_finalize(session->tpk_find_by_email);
   311     session->tpk_find_by_email = NULL;
   312     if (session->tsk_find_by_email)
   313         sqlite3_finalize(session->tsk_find_by_email);
   314     session->tsk_find_by_email = NULL;
   315 
   316     if (session->tpk_all)
   317         sqlite3_finalize(session->tpk_all);
   318     session->tpk_all = NULL;
   319     if (session->tsk_all)
   320         sqlite3_finalize(session->tsk_all);
   321     session->tsk_all = NULL;
   322 
   323     if (session->tpk_save_insert_primary)
   324         sqlite3_finalize(session->tpk_save_insert_primary);
   325     session->tpk_save_insert_primary = NULL;
   326     if (session->tpk_save_insert_subkeys)
   327         sqlite3_finalize(session->tpk_save_insert_subkeys);
   328     session->tpk_save_insert_subkeys = NULL;
   329     if (session->tpk_save_insert_userids)
   330         sqlite3_finalize(session->tpk_save_insert_userids);
   331     session->tpk_save_insert_userids = NULL;
   332 
   333     if (session->key_db) {
   334         int result = sqlite3_close_v2(session->key_db);
   335         if (result != 0)
   336             DUMP_ERR(session, PEP_UNKNOWN_ERROR,
   337                      "Closing key DB: sqlite3_close_v2: %s",
   338                      sqlite3_errstr(result));
   339         session->key_db = NULL;
   340     }
   341 
   342     if (session->ctx) {
   343         sq_context_free(session->ctx);
   344         session->ctx = NULL;
   345     }
   346 }
   347 
   348 // Ensures that a fingerprint is in canonical form.  A canonical
   349 // fingerprint doesn't contain any white space.
   350 //
   351 // This function does *not* consume fpr.
   352 static char *sq_fingerprint_canonicalize(const char *) __attribute__((nonnull));
   353 static char *sq_fingerprint_canonicalize(const char *fpr)
   354 {
   355     sq_fingerprint_t sq_fpr = sq_fingerprint_from_hex(fpr);
   356     char *fpr_canonicalized = sq_fingerprint_to_hex(sq_fpr);
   357     sq_fingerprint_free(sq_fpr);
   358 
   359     return fpr_canonicalized;
   360 }
   361 
   362 // Splits an OpenPGP user id into its name and email components.  A
   363 // user id looks like:
   364 //
   365 //   Name (comment) <email>
   366 //
   367 // This function takes ownership of user_id!!!
   368 //
   369 // namep and emailp may be NULL if they are not required.
   370 static void user_id_split(char *, char **, char **) __attribute__((nonnull(1)));
   371 static void user_id_split(char *user_id, char **namep, char **emailp)
   372 {
   373     if (namep)
   374         *namep = NULL;
   375     if (emailp)
   376         *emailp = NULL;
   377 
   378     char *email = strchr(user_id, '<');
   379     if (email) {
   380         // NUL terminate the string here so that user_id now points at
   381         // most to: "Name (comment)"
   382         *email = 0;
   383 
   384         if (emailp && email[1]) {
   385             email = email + 1;
   386             char *end = strchr(email, '>');
   387             if (end) {
   388                 *end = 0;
   389                 *emailp = strdup(email);
   390             }
   391         }
   392     }
   393 
   394     if (!namep)
   395         return;
   396 
   397     char *comment = strchr(user_id, '(');
   398     if (comment)
   399         *comment = 0;
   400 
   401     // Kill any trailing white space.
   402     for (size_t l = strlen(user_id); l > 0 && user_id[l - 1] == ' '; l --)
   403         user_id[l - 1] = 0;
   404 
   405     // Kill any leading whitespace.
   406     char *start = user_id;
   407     while (*start == ' ')
   408         start ++;
   409     if (start[0])
   410         *namep = strdup(start);
   411 
   412     free(user_id);
   413 }
   414 
   415 // step statement and load the tpk and secret.
   416 static PEP_STATUS key_load(PEP_SESSION, sqlite3_stmt *, sq_tpk_t *, int *)
   417     __attribute__((nonnull(1, 2)));
   418 static PEP_STATUS key_load(PEP_SESSION session, sqlite3_stmt *stmt,
   419                            sq_tpk_t *tpkp, int *secretp)
   420 {
   421     PEP_STATUS status = PEP_STATUS_OK;
   422     int sqlite_result = sqlite3_step(stmt);
   423     switch (sqlite_result) {
   424     case SQLITE_ROW:
   425         if (tpkp) {
   426             int data_len = sqlite3_column_bytes(stmt, 0);
   427             const void *data = sqlite3_column_blob(stmt, 0);
   428 
   429             *tpkp = sq_tpk_from_bytes(session->ctx, data, data_len);
   430             if (!*tpkp)
   431                 ERROR_OUT(session, PEP_GET_KEY_FAILED, "parsing TPK");
   432         }
   433 
   434         if (secretp)
   435             *secretp = sqlite3_column_int(stmt, 1);
   436 
   437         break;
   438     case SQLITE_DONE:
   439         // Got nothing.
   440         status = PEP_KEY_NOT_FOUND;
   441         break;
   442     default:
   443         ERROR_OUT(session, PEP_UNKNOWN_ERROR,
   444                   "stepping: %s", sqlite3_errmsg(session->key_db));
   445     }
   446 
   447  out:
   448     T(" -> %s", pep_status_to_string(status));
   449     return status;
   450 }
   451 
   452 // step statement until exhausted and load the tpks.
   453 static PEP_STATUS key_loadn(PEP_SESSION, sqlite3_stmt *, sq_tpk_t **, int *)
   454     __attribute__((nonnull));
   455 static PEP_STATUS key_loadn(PEP_SESSION session, sqlite3_stmt *stmt,
   456                             sq_tpk_t **tpksp, int *tpks_countp)
   457 {
   458     PEP_STATUS status = PEP_STATUS_OK;
   459     int tpks_count = 0;
   460     int tpks_capacity = 8;
   461     sq_tpk_t *tpks = calloc(tpks_capacity, sizeof(sq_tpk_t));
   462     if (!tpks)
   463         ERROR_OUT(session, PEP_OUT_OF_MEMORY, "out of memory");
   464 
   465     for (;;) {
   466         sq_tpk_t tpk = NULL;
   467         status = key_load(session, stmt, &tpk, NULL);
   468         if (status == PEP_KEY_NOT_FOUND) {
   469             status = PEP_STATUS_OK;
   470             break;
   471         }
   472         ERROR_OUT(session, status, "loading TPK");
   473 
   474         if (tpks_count == tpks_capacity) {
   475             tpks_capacity *= 2;
   476             tpks = realloc(tpks, sizeof(tpks[0]) * tpks_capacity);
   477             if (!tpks)
   478                 ERROR_OUT(session, PEP_OUT_OF_MEMORY, "tpks");
   479         }
   480         tpks[tpks_count ++] = tpk;
   481     }
   482 
   483  out:
   484     if (status != PEP_STATUS_OK) {
   485         for (int i = 0; i < tpks_count; i ++)
   486             sq_tpk_free(tpks[i]);
   487         free(tpks);
   488     } else {
   489         *tpksp = tpks;
   490         *tpks_countp = tpks_count;
   491     }
   492 
   493     T(" -> %s (%d tpks)", pep_status_to_string(status), *tpks_countp);
   494     return status;
   495 }
   496 
   497 // Returns the TPK identified by the provided fingerprint.
   498 //
   499 // This function only matches on the primary key!
   500 static PEP_STATUS tpk_find(PEP_SESSION, sq_fingerprint_t, int, sq_tpk_t *, int *)
   501     __attribute__((nonnull(1, 2)));
   502 static PEP_STATUS tpk_find(PEP_SESSION session,
   503                            sq_fingerprint_t fpr, int private_only,
   504                            sq_tpk_t *tpk, int *secret)
   505 {
   506     PEP_STATUS status = PEP_STATUS_OK;
   507     char *fpr_str = sq_fingerprint_to_hex(fpr);
   508 
   509     T("(%s, %d)", fpr_str, private_only);
   510 
   511     sqlite3_stmt *stmt = private_only ? session->tsk_find : session->tpk_find;
   512     sqlite3_bind_text(stmt, 1, fpr_str, -1, SQLITE_STATIC);
   513 
   514     status = key_load(session, stmt, tpk, secret);
   515     ERROR_OUT(session, status, "Looking up %s", fpr_str);
   516 
   517  out:
   518     sqlite3_reset(stmt);
   519     T("(%s, %d) -> %s", fpr_str, private_only, pep_status_to_string(status));
   520     free(fpr_str);
   521     return status;
   522 }
   523 
   524 // Returns the TPK identified by the provided keyid.
   525 //
   526 // This function matches on both primary keys and subkeys!
   527 //
   528 // Note: There can be multiple TPKs for a given keyid.  This can
   529 // occur, because an encryption subkey can be bound to multiple TPKs.
   530 // Also, it is possible to collide key ids.  If there are multiple key
   531 // ids for a given key, this just returns one of them.
   532 //
   533 // If private_only is set, this will only consider TPKs with some
   534 // secret key material.
   535 static PEP_STATUS tpk_find_by_keyid_hex(PEP_SESSION, const char *, int, sq_tpk_t *, int *)
   536   __attribute__((nonnull(1, 2)));
   537 static PEP_STATUS tpk_find_by_keyid_hex(
   538         PEP_SESSION session, const char *keyid_hex, int private_only,
   539         sq_tpk_t *tpkp, int *secretp)
   540 {
   541     PEP_STATUS status = PEP_STATUS_OK;
   542     T("(%s, %d)", keyid_hex, private_only);
   543 
   544     sqlite3_stmt *stmt
   545         = private_only ? session->tsk_find_by_keyid : session->tpk_find_by_keyid;
   546     sqlite3_bind_text(stmt, 1, keyid_hex, -1, SQLITE_STATIC);
   547 
   548     status = key_load(session, stmt, tpkp, secretp);
   549     ERROR_OUT(session, status, "Looking up %s", keyid_hex);
   550 
   551  out:
   552     sqlite3_reset(stmt);
   553     T("(%s, %d) -> %s", keyid_hex, private_only, pep_status_to_string(status));
   554     return status;
   555 }
   556 
   557 // See tpk_find_by_keyid_hex.
   558 PEP_STATUS tpk_find_by_keyid(PEP_SESSION, sq_keyid_t, int, sq_tpk_t *, int *)
   559     __attribute__((nonnull(1, 2)));
   560 PEP_STATUS tpk_find_by_keyid(PEP_SESSION session,
   561                              sq_keyid_t keyid, int private_only,
   562                              sq_tpk_t *tpkp, int *secretp)
   563 {
   564     char *keyid_hex = sq_keyid_to_hex(keyid);
   565     if (! keyid_hex)
   566         return PEP_OUT_OF_MEMORY;
   567     PEP_STATUS status
   568         = tpk_find_by_keyid_hex(session, keyid_hex, private_only, tpkp, secretp);
   569     free(keyid_hex);
   570     return status;
   571 }
   572 
   573 // See tpk_find_by_keyid_hex.
   574 static PEP_STATUS tpk_find_by_fpr(PEP_SESSION, sq_fingerprint_t, int,
   575                                   sq_tpk_t *, int *)
   576     __attribute__((nonnull(1, 2)));
   577 static PEP_STATUS tpk_find_by_fpr(
   578     PEP_SESSION session, sq_fingerprint_t fpr, int private_only,
   579     sq_tpk_t *tpkp, int *secretp)
   580 {
   581     sq_keyid_t keyid = sq_fingerprint_to_keyid(fpr);
   582     if (! keyid)
   583         return PEP_OUT_OF_MEMORY;
   584     PEP_STATUS status
   585         = tpk_find_by_keyid(session, keyid, private_only, tpkp, secretp);
   586     sq_keyid_free(keyid);
   587     return status;
   588 }
   589 
   590 // See tpk_find_by_keyid_hex.
   591 static PEP_STATUS tpk_find_by_fpr_hex(PEP_SESSION, const char *, int, sq_tpk_t *, int *secret)
   592     __attribute__((nonnull(1, 2)));
   593 static PEP_STATUS tpk_find_by_fpr_hex(
   594     PEP_SESSION session, const char *fpr, int private_only,
   595     sq_tpk_t *tpkp, int *secretp)
   596 {
   597     sq_fingerprint_t sq_fpr = sq_fingerprint_from_hex(fpr);
   598     if (! sq_fpr)
   599         return PEP_OUT_OF_MEMORY;
   600     PEP_STATUS status
   601         = tpk_find_by_fpr(session, sq_fpr, private_only, tpkp, secretp);
   602     sq_fingerprint_free(sq_fpr);
   603     return status;
   604 }
   605 
   606 // Returns all known TPKs.
   607 static PEP_STATUS tpk_all(PEP_SESSION, int, sq_tpk_t **, int *) __attribute__((nonnull));
   608 static PEP_STATUS tpk_all(PEP_SESSION session, int private_only,
   609                           sq_tpk_t **tpksp, int *tpks_countp) {
   610     PEP_STATUS status = PEP_STATUS_OK;
   611     sqlite3_stmt *stmt = private_only ? session->tsk_all : session->tpk_all;
   612     status = key_loadn(session, stmt, tpksp, tpks_countp);
   613     ERROR_OUT(session, status, "loading TPKs");
   614  out:
   615     sqlite3_reset(stmt);
   616     return status;
   617 }
   618 
   619 // Returns keys that have a user id that matches the specified pattern.
   620 //
   621 // The keys returned must be freed using sq_tpk_free.
   622 static PEP_STATUS tpk_find_by_email(PEP_SESSION, const char *, int, sq_tpk_t **, int *)
   623     __attribute__((nonnull));
   624 static PEP_STATUS tpk_find_by_email(PEP_SESSION session,
   625                                     const char *pattern, int private_only,
   626                                     sq_tpk_t **tpksp, int *countp)
   627 {
   628     PEP_STATUS status = PEP_STATUS_OK;
   629     T("(%s)", pattern);
   630 
   631     sqlite3_stmt *stmt
   632         = private_only ? session->tsk_find_by_email : session->tpk_find_by_email;
   633     sqlite3_bind_text(stmt, 1, pattern, -1, SQLITE_STATIC);
   634 
   635     status = key_loadn(session, stmt, tpksp, countp);
   636     ERROR_OUT(session, status, "Searching for '%s'", pattern);
   637 
   638  out:
   639     sqlite3_reset(stmt);
   640     T("(%s) -> %s (%d results)", pattern, pep_status_to_string(status), *countp);
   641     return status;
   642 }
   643 
   644 
   645 // Saves the specified TPK.
   646 //
   647 // This function takes ownership of TPK.
   648 static PEP_STATUS tpk_save(PEP_SESSION, sq_tpk_t, identity_list **)
   649     __attribute__((nonnull(1, 2)));
   650 static PEP_STATUS tpk_save(PEP_SESSION session, sq_tpk_t tpk,
   651                            identity_list **private_idents)
   652 {
   653     PEP_STATUS status = PEP_STATUS_OK;
   654     sq_fingerprint_t sq_fpr = NULL;
   655     char *fpr = NULL;
   656     void *tsk_buffer = NULL;
   657     size_t tsk_buffer_len = 0;
   658     int tried_commit = 0;
   659     sq_tpk_key_iter_t key_iter = NULL;
   660     sq_user_id_binding_iter_t user_id_iter = NULL;
   661 
   662     sq_fpr = sq_tpk_fingerprint(tpk);
   663     fpr = sq_fingerprint_to_hex(sq_fpr);
   664     T("(%s, private_idents: %s)", fpr, private_idents ? "yes" : "no");
   665 
   666     // Merge any existing data into TPK.
   667     sq_tpk_t current = NULL;
   668     status = tpk_find(session, sq_fpr, false, &current, NULL);
   669     if (status == PEP_KEY_NOT_FOUND)
   670         status = PEP_STATUS_OK;
   671     else
   672         ERROR_OUT(session, status, "Looking up %s", fpr);
   673     if (current)
   674         tpk = sq_tpk_merge(session->ctx, tpk, current);
   675 
   676     int is_tsk = sq_tpk_is_tsk(tpk);
   677 
   678     // Serialize it.
   679     sq_writer_t writer = sq_writer_alloc(&tsk_buffer, &tsk_buffer_len);
   680     if (! writer)
   681         ERROR_OUT(session, PEP_OUT_OF_MEMORY, "out of memory");
   682 
   683     sq_status_t sq_status;
   684     sq_tsk_t tsk = sq_tpk_into_tsk(tpk);
   685     sq_status = sq_tsk_serialize(session->ctx, tsk, writer);
   686     tpk = sq_tsk_into_tpk(tsk);
   687     //sq_writer_free(writer);
   688     if (sq_status != 0)
   689         ERROR_OUT(session, PEP_UNKNOWN_ERROR, "Serializing TPK");
   690 
   691 
   692     // Insert the TSK into the DB.
   693     sqlite3_stmt *stmt = session->begin_transaction;
   694     int sqlite_result = sqlite3_step(stmt);
   695     sqlite3_reset(stmt);
   696     if (sqlite_result != SQLITE_DONE)
   697         ERROR_OUT(session, PEP_UNKNOWN_ERROR,
   698                   "begin transaction failed: %s",
   699                   sqlite3_errmsg(session->key_db));
   700 
   701     stmt = session->tpk_save_insert_primary;
   702     sqlite3_bind_text(stmt, 1, fpr, -1, SQLITE_STATIC);
   703     sqlite3_bind_int(stmt, 2, is_tsk);
   704     sqlite3_bind_blob(stmt, 3, tsk_buffer, tsk_buffer_len, SQLITE_STATIC);
   705 
   706     sqlite_result = sqlite3_step(stmt);
   707     sqlite3_reset(stmt);
   708     if (sqlite_result != SQLITE_DONE)
   709         ERROR_OUT(session, PEP_UNKNOWN_ERROR,
   710                   "Saving TPK: %s", sqlite3_errmsg(session->key_db));
   711 
   712     // Insert the "subkeys" (the primary key and the subkeys).
   713     stmt = session->tpk_save_insert_subkeys;
   714     key_iter = sq_tpk_key_iter(tpk);
   715     sq_p_key_t key;
   716     while ((key = sq_tpk_key_iter_next(key_iter, NULL, NULL))) {
   717         sq_keyid_t keyid = sq_p_key_keyid(key);
   718         char *keyid_hex = sq_keyid_to_hex(keyid);
   719         sqlite3_bind_text(stmt, 1, keyid_hex, -1, SQLITE_STATIC);
   720         sqlite3_bind_text(stmt, 2, fpr, -1, SQLITE_STATIC);
   721 
   722         sqlite_result = sqlite3_step(stmt);
   723         sqlite3_reset(stmt);
   724         free(keyid_hex);
   725         sq_keyid_free(keyid);
   726         if (sqlite_result != SQLITE_DONE) {
   727             sq_tpk_key_iter_free(key_iter);
   728             ERROR_OUT(session, PEP_UNKNOWN_ERROR,
   729                       "Updating subkeys: %s", sqlite3_errmsg(session->key_db));
   730         }
   731     }
   732     sq_tpk_key_iter_free(key_iter);
   733     key_iter = NULL;
   734 
   735     // Insert the "userids".
   736     stmt = session->tpk_save_insert_userids;
   737     user_id_iter = sq_tpk_user_id_binding_iter(tpk);
   738     sq_user_id_binding_t binding;
   739     int first = 1;
   740     while ((binding = sq_user_id_binding_iter_next(user_id_iter))) {
   741         char *user_id = sq_user_id_binding_user_id(binding);
   742         if (!user_id || !*user_id)
   743             continue;
   744 
   745         // Ignore bindings with a self-revocation certificate, but no
   746         // self-signature.
   747         if (!sq_user_id_binding_selfsig(binding)) {
   748             free(user_id);
   749             continue;
   750         }
   751 
   752         char *name, *email;
   753         user_id_split(user_id, &name, &email); /* user_id is comsumed.  */
   754         // XXX: Correctly clean up name and email on error...
   755 
   756         if (email) {
   757             T("  userid: %s", email);
   758 
   759             sqlite3_bind_text(stmt, 1, email, -1, SQLITE_STATIC);
   760             sqlite3_bind_text(stmt, 2, fpr, -1, SQLITE_STATIC);
   761 
   762             sqlite_result = sqlite3_step(stmt);
   763             sqlite3_reset(stmt);
   764 
   765             if (sqlite_result != SQLITE_DONE) {
   766                 sq_user_id_binding_iter_free(user_id_iter);
   767                 free(name);
   768                 ERROR_OUT(session, PEP_UNKNOWN_ERROR,
   769                           "Updating userids: %s", sqlite3_errmsg(session->key_db));
   770             }
   771         }
   772 
   773         if (first && private_idents && is_tsk) {
   774             first = 0;
   775 
   776             // Create an identity for the primary user id.
   777             pEp_identity *ident = new_identity(email, fpr, NULL, name);
   778             if (ident == NULL)
   779                 ERROR_OUT(session, PEP_OUT_OF_MEMORY, "new_identity");
   780 
   781             *private_idents = identity_list_add(*private_idents, ident);
   782             if (*private_idents == NULL)
   783                 ERROR_OUT(session, PEP_OUT_OF_MEMORY, "identity_list_add");
   784         }
   785         free(email);
   786         free(name);
   787 
   788     }
   789     sq_user_id_binding_iter_free(user_id_iter);
   790     user_id_iter = NULL;
   791 
   792  out:
   793     // Prevent ERROR_OUT from causing an infinite loop.
   794     if (! tried_commit) {
   795         tried_commit = 1;
   796         stmt = status == PEP_STATUS_OK
   797             ? session->commit_transaction : session->rollback_transaction;
   798         int sqlite_result = sqlite3_step(stmt);
   799         sqlite3_reset(stmt);
   800         if (sqlite_result != SQLITE_DONE)
   801             ERROR_OUT(session, PEP_UNKNOWN_ERROR,
   802                       status == PEP_STATUS_OK
   803                       ? "commit failed: %s" : "rollback failed: %s",
   804                       sqlite3_errmsg(session->key_db));
   805     }
   806 
   807     T("(%s) -> %s", fpr, pep_status_to_string(status));
   808 
   809     if (user_id_iter)
   810         sq_user_id_binding_iter_free(user_id_iter);
   811     if (key_iter)
   812         sq_tpk_key_iter_free(key_iter);
   813     if (stmt)
   814       sqlite3_reset(stmt);
   815     free(tsk_buffer);
   816     if (tpk)
   817         sq_tpk_free(tpk);
   818     free(fpr);
   819     sq_fingerprint_free(sq_fpr);
   820 
   821     return status;
   822 }
   823 
   824 struct decrypt_cookie {
   825     PEP_SESSION session;
   826     int get_secret_keys_called;
   827     stringlist_t *recipient_keylist;
   828     stringlist_t *signer_keylist;
   829     int good_checksums;
   830     int missing_keys;
   831     int bad_checksums;
   832     int decrypted;
   833 };
   834 
   835 static sq_status_t
   836 get_public_keys_cb(void *cookie_raw,
   837                    sq_keyid_t *keyids, size_t keyids_len,
   838                    sq_tpk_t **tpks, size_t *tpk_len,
   839                    void (**our_free)(void *))
   840 {
   841     struct decrypt_cookie *cookie = cookie_raw;
   842     PEP_SESSION session = cookie->session;
   843 
   844     *tpks = calloc(keyids_len, sizeof(*tpks));
   845     if (!*tpks)
   846         return SQ_STATUS_UNKNOWN_ERROR;
   847     *our_free = free;
   848 
   849     int i, j;
   850     j = 0;
   851     for (i = 0; i < keyids_len; i ++) {
   852         sq_tpk_t tpk = NULL;
   853         sq_status_t status
   854             = tpk_find_by_keyid(session, keyids[i], false, &tpk, NULL);
   855         if (status == SQ_STATUS_SUCCESS)
   856             (*tpks)[j ++] = tpk;
   857     }
   858     *tpk_len = j;
   859     return SQ_STATUS_SUCCESS;
   860 }
   861 
   862 static sq_status_t
   863 get_secret_keys_cb(void *cookie_opaque,
   864                    sq_pkesk_t *pkesks, size_t pkesk_count,
   865                    sq_skesk_t *skesks, size_t skesk_count,
   866                    sq_secret_t *secret)
   867 {
   868     struct decrypt_cookie *cookie = cookie_opaque;
   869     PEP_SESSION session = cookie->session;
   870     sq_tpk_t *tsks = NULL;
   871     int tsks_count = 0;
   872     int wildcards = 0;
   873 
   874     if (cookie->get_secret_keys_called)
   875         // Prevent iterations, which isn't needed since we don't
   876         // support SKESKs.
   877         return SQ_STATUS_UNKNOWN_ERROR;
   878     cookie->get_secret_keys_called = 1;
   879 
   880     T("%zd PKESKs", pkesk_count);
   881 
   882     for (int i = 0; i < pkesk_count; i ++) {
   883         sq_pkesk_t pkesk = pkesks[i];
   884         sq_keyid_t keyid = sq_pkesk_recipient(pkesk); /* Reference. */
   885         char *keyid_str = sq_keyid_to_hex(keyid);
   886         sq_tpk_key_iter_t key_iter = NULL;
   887 
   888         T("Considering PKESK for %s", keyid_str);
   889 
   890         if (strcmp(keyid_str, "0000000000000000") == 0) {
   891             // Initially ignore wildcards.
   892             wildcards = 1;
   893             goto eol;
   894         }
   895 
   896         // Collect the recipients.  Note: we must return the primary
   897         // key's fingerprint.
   898         sq_tpk_t tpk = NULL;
   899         int is_tsk = 0;
   900         if (tpk_find_by_keyid(session, keyid, false, &tpk, &is_tsk) != PEP_STATUS_OK)
   901             goto eol;
   902 
   903         sq_fingerprint_t fp = sq_tpk_fingerprint(tpk);
   904         char *fp_string = sq_fingerprint_to_hex(fp);
   905         stringlist_add_unique(cookie->recipient_keylist, fp_string);
   906         free(fp_string);
   907         sq_fingerprint_free(fp);
   908 
   909         if (cookie->decrypted)
   910             goto eol;
   911 
   912         // See if we have the secret key.
   913         assert(is_tsk == sq_tpk_is_tsk(tpk));
   914         if (! is_tsk)
   915             goto eol;
   916 
   917         key_iter = sq_tpk_key_iter(tpk);
   918         sq_p_key_t key;
   919         while ((key = sq_tpk_key_iter_next(key_iter, NULL, NULL))) {
   920             sq_keyid_t this_keyid = sq_p_key_keyid(key);
   921             char *this_keyid_hex = sq_keyid_to_hex(this_keyid);
   922             sq_keyid_free(this_keyid);
   923 
   924             int match = strcmp(keyid_str, this_keyid_hex) == 0;
   925             free(this_keyid_hex);
   926             if (match)
   927                 break;
   928         }
   929 
   930         if (key == NULL) {
   931             assert(!"Inconsistent DB: key doesn't contain a subkey with keyid!");
   932             goto eol;
   933         }
   934 
   935         uint8_t algo;
   936         uint8_t session_key[1024];
   937         size_t session_key_len = sizeof(session_key);
   938         if (sq_pkesk_decrypt(cookie->session->ctx,
   939                              pkesk, key, &algo,
   940                              session_key, &session_key_len) != 0) {
   941             DUMP_ERR(session, PEP_UNKNOWN_ERROR, "sq_pkesk_decrypt");
   942             goto eol;
   943         }
   944 
   945         T("Decrypted PKESK for %s", keyid_str);
   946 
   947         *secret = sq_secret_cached(algo, session_key, session_key_len);
   948         cookie->decrypted = 1;
   949 
   950     eol:
   951         free(keyid_str);
   952         if (key_iter)
   953             sq_tpk_key_iter_free(key_iter);
   954         if (tpk)
   955             sq_tpk_free(tpk);
   956     }
   957 
   958     // Consider wildcard recipients.
   959     if (wildcards) for (int i = 0; i < pkesk_count && !cookie->decrypted; i ++) {
   960         sq_pkesk_t pkesk = pkesks[i];
   961         sq_keyid_t keyid = sq_pkesk_recipient(pkesk); /* Reference. */
   962         char *keyid_str = sq_keyid_to_hex(keyid);
   963         sq_tpk_key_iter_t key_iter = NULL;
   964 
   965         if (strcmp(keyid_str, "0000000000000000") != 0)
   966             goto eol2;
   967 
   968         if (!tsks) {
   969             if (tpk_all(session, true, &tsks, &tsks_count) != PEP_STATUS_OK) {
   970                 DUMP_ERR(session, PEP_UNKNOWN_ERROR, "Getting all tsks");
   971             }
   972         }
   973 
   974         for (int j = 0; j < tsks_count; j ++) {
   975             sq_tpk_t tsk = tsks[j];
   976 
   977             key_iter = sq_tpk_key_iter(tsk);
   978             sq_p_key_t key;
   979             sq_signature_t selfsig;
   980             while ((key = sq_tpk_key_iter_next(key_iter, &selfsig, NULL))) {
   981                 if (! (sq_signature_can_encrypt_at_rest(selfsig)
   982                        || sq_signature_can_encrypt_for_transport(selfsig)))
   983                     continue;
   984 
   985                 // Note: for decryption to appear to succeed, we must
   986                 // get a valid algorithm (8 of 256 values) and a
   987                 // 16-bit checksum must match.  Thus, we have about a
   988                 // 1 in 2**21 chance of having a false positive here.
   989                 uint8_t algo;
   990                 uint8_t session_key[1024];
   991                 size_t session_key_len = sizeof(session_key);
   992                 if (sq_pkesk_decrypt(cookie->session->ctx, pkesk, key,
   993                                      &algo, session_key, &session_key_len))
   994                     continue;
   995 
   996                 // Add it to the recipient list.
   997                 sq_fingerprint_t fp = sq_tpk_fingerprint(tsk);
   998                 char *fp_string = sq_fingerprint_to_hex(fp);
   999                 T("wildcard recipient appears to be %s", fp_string);
  1000                 stringlist_add_unique(cookie->recipient_keylist, fp_string);
  1001                 free(fp_string);
  1002                 sq_fingerprint_free(fp);
  1003 
  1004                 *secret = sq_secret_cached(algo, session_key, session_key_len);
  1005                 cookie->decrypted = 1;
  1006             }
  1007 
  1008             sq_tpk_key_iter_free(key_iter);
  1009             key_iter = NULL;
  1010         }
  1011     eol2:
  1012         free(keyid_str);
  1013         if (key_iter)
  1014             sq_tpk_key_iter_free(key_iter);
  1015     }
  1016 
  1017     if (tsks) {
  1018         for (int i = 0; i < tsks_count; i ++)
  1019             sq_tpk_free(tsks[i]);
  1020         free(tsks);
  1021     }
  1022 
  1023     return cookie->decrypted ? SQ_STATUS_SUCCESS : SQ_STATUS_UNKNOWN_ERROR;
  1024 }
  1025 
  1026 static sq_status_t
  1027 check_signatures_cb(void *cookie_opaque,
  1028                    sq_verification_results_t results, size_t levels)
  1029 {
  1030     struct decrypt_cookie *cookie = cookie_opaque;
  1031     PEP_SESSION session = cookie->session;
  1032 
  1033     int level;
  1034     for (level = 0; level < levels; level ++) {
  1035         sq_verification_result_t *vrs;
  1036         size_t vr_count;
  1037         sq_verification_results_at_level(results, level, &vrs, &vr_count);
  1038 
  1039         int i;
  1040         for (i = 0; i < vr_count; i ++) {
  1041             sq_tpk_t tpk = NULL;
  1042             sq_verification_result_code_t code
  1043                 = sq_verification_result_code(vrs[i]);
  1044 
  1045             if (code == SQ_VERIFICATION_RESULT_CODE_BAD_CHECKSUM) {
  1046                 cookie->bad_checksums ++;
  1047                 continue;
  1048             }
  1049             if (code == SQ_VERIFICATION_RESULT_CODE_MISSING_KEY) {
  1050                 // No key, nothing we can do.
  1051                 cookie->missing_keys ++;
  1052                 continue;
  1053             }
  1054 
  1055             // We need to add the fingerprint of the primary key to
  1056             // cookie->signer_keylist.
  1057             sq_signature_t sig = sq_verification_result_signature(vrs[i]);
  1058 
  1059             // First try looking up by the TPK using the
  1060             // IssuerFingerprint subpacket.
  1061             sq_fingerprint_t issuer_fp = sq_signature_issuer_fingerprint(sig);
  1062             if (issuer_fp) {
  1063                 sq_keyid_t issuer = sq_fingerprint_to_keyid(issuer_fp);
  1064                 if (tpk_find_by_keyid(session, issuer, false, &tpk, NULL) != PEP_STATUS_OK)
  1065                     ; // Soft error.  Ignore.
  1066                 sq_keyid_free(issuer);
  1067                 sq_fingerprint_free(issuer_fp);
  1068             }
  1069 
  1070             // If that is not available, try using the Issuer subpacket.
  1071             if (!tpk) {
  1072                 sq_keyid_t issuer = sq_signature_issuer(sig);
  1073                 if (issuer) {
  1074                     if (tpk_find_by_keyid(session, issuer, false, &tpk, NULL) != PEP_STATUS_OK)
  1075                         ; // Soft error.  Ignore.
  1076                 }
  1077                 sq_keyid_free(issuer);
  1078             }
  1079 
  1080             if (tpk) {
  1081                 // Ok, we have a TPK.
  1082                 sq_fingerprint_t fp = sq_tpk_fingerprint(tpk);
  1083                 char *fp_str = sq_fingerprint_to_hex(fp);
  1084                 stringlist_add_unique(cookie->signer_keylist, fp_str);
  1085 
  1086                 // XXX: Check that the TPK and the key used to make
  1087                 // the signature and the signature itself are alive
  1088                 // and not revoked.  Revoked =>
  1089                 // PEP_DECRYPT_SIGNATURE_DOES_NOT_MATCH; Expired key
  1090                 // or sig => PEP_DECRYPTED.
  1091                 cookie->good_checksums ++;
  1092 
  1093                 free(fp_str);
  1094                 sq_fingerprint_free(fp);
  1095                 sq_tpk_free(tpk);
  1096             } else {
  1097                 // If we get
  1098                 // SQ_VERIFICATION_RESULT_CODE_GOOD_CHECKSUM, then the
  1099                 // TPK should be available.  But, another process
  1100                 // could have deleted the key from the store in the
  1101                 // mean time, so be tolerant.
  1102                 cookie->missing_keys ++;
  1103             }
  1104         }
  1105     }
  1106 
  1107     return SQ_STATUS_SUCCESS;
  1108 }
  1109 
  1110 PEP_STATUS pgp_decrypt_and_verify(
  1111     PEP_SESSION session, const char *ctext, size_t csize,
  1112     const char *dsigtext, size_t dsigsize,
  1113     char **ptext, size_t *psize, stringlist_t **keylist,
  1114     char** filename_ptr)
  1115 {
  1116     PEP_STATUS status = PEP_STATUS_OK;
  1117     struct decrypt_cookie cookie = { session, 0, NULL, NULL, 0, 0, 0, };
  1118     sq_reader_t reader = NULL;
  1119     sq_writer_t writer = NULL;
  1120     *ptext = NULL;
  1121     *psize = 0;
  1122 
  1123     // XXX: We don't yet handle detached signatures over encrypted
  1124     // messages.
  1125     assert(!dsigtext);
  1126 
  1127     cookie.recipient_keylist = new_stringlist(NULL);
  1128     if (!cookie.recipient_keylist)
  1129         ERROR_OUT(session, PEP_OUT_OF_MEMORY, "recipient_keylist");
  1130 
  1131     cookie.signer_keylist = new_stringlist(NULL);
  1132     if (!cookie.signer_keylist)
  1133         ERROR_OUT(session, PEP_OUT_OF_MEMORY, "signer_keylist");
  1134 
  1135     reader = sq_reader_from_bytes((const uint8_t *) ctext, csize);
  1136     if (! reader)
  1137         ERROR_OUT(session, PEP_OUT_OF_MEMORY, "Creating reader");
  1138 
  1139     writer = sq_writer_alloc((void **) ptext, psize);
  1140     if (! writer)
  1141         ERROR_OUT(session, PEP_UNKNOWN_ERROR, "Creating writer");
  1142 
  1143     sq_status_t sq_status = sq_decrypt(session->ctx, reader, writer,
  1144                                        get_public_keys_cb, get_secret_keys_cb,
  1145                                        check_signatures_cb, &cookie);
  1146     if (sq_status)
  1147         ERROR_OUT(session, PEP_DECRYPT_NO_KEY, "sq_decrypt");
  1148 
  1149     if (! cookie.decrypted)
  1150         ERROR_OUT(session, PEP_DECRYPT_NO_KEY, "Decryption failed");
  1151 
  1152     // Add a terminating NUL for naive users
  1153     void *t = realloc(*ptext, *psize + 1);
  1154     if (! t)
  1155         ERROR_OUT(session, PEP_OUT_OF_MEMORY, "out of memory");
  1156     *ptext = t;
  1157     (*ptext)[*psize] = 0;
  1158 
  1159     if (! cookie.signer_keylist) {
  1160         cookie.signer_keylist = new_stringlist("");
  1161         if (! cookie.signer_keylist)
  1162             ERROR_OUT(session, PEP_OUT_OF_MEMORY, "cookie.signer_keylist");
  1163     }
  1164     if (!cookie.signer_keylist->value)
  1165         stringlist_add(cookie.signer_keylist, "");
  1166 
  1167     *keylist = cookie.signer_keylist;
  1168     stringlist_append(*keylist, cookie.recipient_keylist);
  1169 
  1170  out:
  1171     if (status == PEP_STATUS_OK) {
  1172         if (cookie.bad_checksums) {
  1173             // If there are any bad signatures, fail.
  1174             status = PEP_DECRYPT_SIGNATURE_DOES_NOT_MATCH;
  1175         } else if (cookie.good_checksums) {
  1176             // If there is at least one signature that we can verify,
  1177             // succeed.
  1178             status = PEP_DECRYPTED_AND_VERIFIED;
  1179         } else {
  1180             // We couldn't verify any signatures (possibly because we
  1181             // don't have the keys).
  1182             status = PEP_DECRYPTED;
  1183         }
  1184     } else {
  1185         free_stringlist(cookie.recipient_keylist);
  1186         free_stringlist(cookie.signer_keylist);
  1187         free(*ptext);
  1188     }
  1189 
  1190     if (reader)
  1191         sq_reader_free(reader);
  1192     if (writer)
  1193         sq_writer_free(writer);
  1194 
  1195     T("-> %s", pep_status_to_string(status));
  1196     return status;
  1197 }
  1198 
  1199 PEP_STATUS pgp_verify_text(
  1200     PEP_SESSION session, const char *text, size_t size,
  1201     const char *signature, size_t sig_size, stringlist_t **keylist)
  1202 {
  1203     PEP_STATUS status = PEP_STATUS_OK;
  1204     struct decrypt_cookie cookie = { session, 0, NULL, NULL, 0, 0, 0, };
  1205     sq_reader_t reader = NULL;
  1206     sq_reader_t dsig_reader = NULL;
  1207 
  1208     if (size == 0 || sig_size == 0)
  1209         return PEP_DECRYPT_WRONG_FORMAT;
  1210 
  1211     cookie.recipient_keylist = new_stringlist(NULL);
  1212     if (!cookie.recipient_keylist)
  1213         ERROR_OUT(session, PEP_OUT_OF_MEMORY, "out of memory");
  1214 
  1215     cookie.signer_keylist = new_stringlist(NULL);
  1216     if (!cookie.signer_keylist)
  1217         ERROR_OUT(session, PEP_OUT_OF_MEMORY, "out of memory");
  1218 
  1219     reader = sq_reader_from_bytes((const uint8_t *) text, size);
  1220     if (! reader)
  1221         ERROR_OUT(session, PEP_OUT_OF_MEMORY, "Creating reader");
  1222 
  1223     dsig_reader = NULL;
  1224     if (signature) {
  1225         dsig_reader = sq_reader_from_bytes((uint8_t *) signature, sig_size);
  1226         if (! dsig_reader)
  1227             ERROR_OUT(session, PEP_OUT_OF_MEMORY, "Creating signature reader");
  1228     }
  1229 
  1230     if (sq_verify(session->ctx, reader, dsig_reader, /* output */ NULL,
  1231                   get_public_keys_cb, check_signatures_cb, &cookie))
  1232         ERROR_OUT(session, PEP_UNKNOWN_ERROR, "sq_verify");
  1233 
  1234     if (! cookie.signer_keylist) {
  1235         cookie.signer_keylist = new_stringlist("");
  1236         if (! cookie.signer_keylist)
  1237             ERROR_OUT(session, PEP_OUT_OF_MEMORY, "cookie.signer_keylist");
  1238     }
  1239     if (!cookie.signer_keylist->value)
  1240         stringlist_add(cookie.signer_keylist, "");
  1241 
  1242     *keylist = cookie.signer_keylist;
  1243     stringlist_append(*keylist, cookie.recipient_keylist);
  1244 
  1245  out:
  1246     if (status == PEP_STATUS_OK) {
  1247         if (cookie.bad_checksums) {
  1248             // If there are any bad signatures, fail.
  1249             status = PEP_DECRYPT_SIGNATURE_DOES_NOT_MATCH;
  1250         } else if (cookie.good_checksums) {
  1251             // If there is at least one signature that we can verify,
  1252             // succeed.
  1253             status = PEP_VERIFIED;
  1254         } else {
  1255             // We couldn't verify any signatures (possibly because we
  1256             // don't have the keys).
  1257             status = PEP_UNENCRYPTED;
  1258         }
  1259     } else {
  1260         free_stringlist(cookie.recipient_keylist);
  1261         free_stringlist(cookie.signer_keylist);
  1262     }
  1263 
  1264     if (reader)
  1265         sq_reader_free(reader);
  1266     if (dsig_reader)
  1267         sq_reader_free(dsig_reader);
  1268 
  1269     T("-> %s", pep_status_to_string(status));
  1270     return status;
  1271 }
  1272 
  1273 
  1274 PEP_STATUS pgp_sign_only(
  1275     PEP_SESSION session, const char* fpr, const char *ptext,
  1276     size_t psize, char **stext, size_t *ssize)
  1277 {
  1278     assert(session);
  1279     assert(fpr && fpr[0]);
  1280     assert(ptext);
  1281     assert(psize);
  1282     assert(stext);
  1283     assert(ssize);
  1284 
  1285     PEP_STATUS status = PEP_STATUS_OK;
  1286     sq_tpk_t signer = NULL;
  1287     sq_writer_stack_t ws = NULL;
  1288 
  1289     status = tpk_find_by_fpr_hex(session, fpr, true, &signer, NULL);
  1290     ERROR_OUT(session, status, "Looking up key '%s'", fpr);
  1291 
  1292     sq_writer_t writer = sq_writer_alloc((void **) stext, ssize);
  1293     writer = sq_armor_writer_new(session->ctx, writer,
  1294                                  SQ_ARMOR_KIND_MESSAGE, NULL, 0);
  1295     if (!writer)
  1296         ERROR_OUT(session, PEP_UNKNOWN_ERROR, "Setting up armor writer");
  1297 
  1298     ws = sq_writer_stack_message(writer);
  1299 
  1300     ws = sq_signer_new_detached(session->ctx, ws, &signer, 1);
  1301     if (!ws)
  1302         ERROR_OUT(session, PEP_UNKNOWN_ERROR, "Setting up signer");
  1303 
  1304     sq_status_t write_status =
  1305         sq_writer_stack_write_all (session->ctx, ws,
  1306                                    (uint8_t *) ptext, psize);
  1307     if (write_status != 0)
  1308         ERROR_OUT(session, PEP_UNKNOWN_ERROR, "Encrypting message");
  1309 
  1310     // Add a terminating NUL for naive users
  1311     void *t = realloc(*stext, *ssize + 1);
  1312     if (! t)
  1313         ERROR_OUT(session, PEP_OUT_OF_MEMORY, "out of memory");
  1314     *stext = t;
  1315     (*stext)[*ssize] = 0;
  1316 
  1317  out:
  1318     if (ws) {
  1319         sq_status_t sq_status = sq_writer_stack_finalize (session->ctx, ws);
  1320         ws = NULL;
  1321         if (sq_status != 0)
  1322             ERROR_OUT(session, PEP_UNKNOWN_ERROR, "Flushing writer");
  1323     }
  1324 
  1325     if (signer)
  1326         sq_tpk_free(signer);
  1327 
  1328     T("(%s)-> %s", fpr, pep_status_to_string(status));
  1329     return status;
  1330 }
  1331 
  1332 static PEP_STATUS pgp_encrypt_sign_optional(
  1333     PEP_SESSION session, const stringlist_t *keylist, const char *ptext,
  1334     size_t psize, char **ctext, size_t *csize, bool sign)
  1335 {
  1336     PEP_STATUS status = PEP_STATUS_OK;
  1337     int keys_count = 0;
  1338     sq_tpk_t *keys = NULL;
  1339     sq_tpk_t signer = NULL;
  1340     sq_writer_stack_t ws = NULL;
  1341 
  1342     assert(session);
  1343     assert(keylist);
  1344     assert(ptext);
  1345     assert(psize);
  1346     assert(ctext);
  1347     assert(csize);
  1348 
  1349     *ctext = NULL;
  1350     *csize = 0;
  1351 
  1352     keys = calloc(stringlist_length(keylist), sizeof(*keys));
  1353     if (keys == NULL)
  1354         ERROR_OUT(session, PEP_OUT_OF_MEMORY, "out of memory");
  1355 
  1356     // Get the keys for the recipients.
  1357     const stringlist_t *_keylist;
  1358     for (_keylist = keylist; _keylist != NULL; _keylist = _keylist->next) {
  1359         assert(_keylist->value);
  1360         sq_fingerprint_t sq_fpr = sq_fingerprint_from_hex(_keylist->value);
  1361         status = tpk_find_by_fpr(session, sq_fpr, false, &keys[keys_count ++], NULL);
  1362         sq_fingerprint_free(sq_fpr);
  1363         ERROR_OUT(session, status, "Looking up key for recipient '%s'", _keylist->value);
  1364     }
  1365 
  1366     if (sign) {
  1367         // The first key in the keylist is the signer.
  1368         status = tpk_find_by_fpr_hex(session, keylist->value, true, &signer, NULL);
  1369         ERROR_OUT(session, status, "Looking up key for signing '%s'", keylist->value);
  1370     }
  1371 
  1372     sq_writer_t writer = sq_writer_alloc((void **) ctext, csize);
  1373     writer = sq_armor_writer_new(session->ctx, writer,
  1374                                  SQ_ARMOR_KIND_MESSAGE, NULL, 0);
  1375     if (!writer)
  1376         ERROR_OUT(session, PEP_UNKNOWN_ERROR, "Setting up armor writer");
  1377 
  1378     ws = sq_writer_stack_message(writer);
  1379     ws = sq_encryptor_new (session->ctx, ws,
  1380                            NULL, 0, keys, keys_count,
  1381                            SQ_ENCRYPTION_MODE_FOR_TRANSPORT);
  1382     if (!ws) {
  1383         sq_writer_free(writer);
  1384         ERROR_OUT(session, PEP_UNKNOWN_ERROR, "Setting up encryptor");
  1385     }
  1386 
  1387     if (sign) {
  1388         ws = sq_signer_new(session->ctx, ws, &signer, 1);
  1389         if (!ws)
  1390             ERROR_OUT(session, PEP_UNKNOWN_ERROR, "Setting up signer");
  1391     }
  1392 
  1393     ws = sq_literal_writer_new (session->ctx, ws);
  1394     if (!ws)
  1395         ERROR_OUT(session, PEP_UNKNOWN_ERROR, "Setting up literal writer");
  1396 
  1397     sq_status_t write_status =
  1398         sq_writer_stack_write_all (session->ctx, ws,
  1399                                    (uint8_t *) ptext, psize);
  1400     if (write_status != 0)
  1401         ERROR_OUT(session, PEP_UNKNOWN_ERROR, "Encrypting message");
  1402 
  1403     // Add a terminating NUL for naive users
  1404     void *t = realloc(*ctext, *csize + 1);
  1405     if (! t)
  1406         ERROR_OUT(session, PEP_OUT_OF_MEMORY, "out of memory");
  1407     *ctext = t;
  1408     (*ctext)[*csize] = 0;
  1409 
  1410  out:
  1411     if (ws) {
  1412         sq_status_t sq_status = sq_writer_stack_finalize (session->ctx, ws);
  1413         ws = NULL;
  1414         if (sq_status != 0)
  1415             ERROR_OUT(session, PEP_UNKNOWN_ERROR, "Flushing writer");
  1416     }
  1417 
  1418     if (signer)
  1419         sq_tpk_free(signer);
  1420     for (int i = 0; i < keys_count; i ++)
  1421         sq_tpk_free(keys[i]);
  1422     free(keys);
  1423 
  1424     T("-> %s", pep_status_to_string(status));
  1425     return status;
  1426 }
  1427 
  1428 PEP_STATUS pgp_encrypt_only(
  1429     PEP_SESSION session, const stringlist_t *keylist, const char *ptext,
  1430     size_t psize, char **ctext, size_t *csize)
  1431 {
  1432     return pgp_encrypt_sign_optional(session, keylist, ptext,
  1433         psize, ctext, csize, false);
  1434 }
  1435 
  1436 PEP_STATUS pgp_encrypt_and_sign(
  1437     PEP_SESSION session, const stringlist_t *keylist, const char *ptext,
  1438     size_t psize, char **ctext, size_t *csize)
  1439 {
  1440     return pgp_encrypt_sign_optional(session, keylist, ptext,
  1441         psize, ctext, csize, true);
  1442 }
  1443 
  1444 
  1445 PEP_STATUS pgp_generate_keypair(PEP_SESSION session, pEp_identity *identity)
  1446 {
  1447     PEP_STATUS status = PEP_STATUS_OK;
  1448     char *userid = NULL;
  1449     sq_tpk_t tpk = NULL;
  1450     sq_fingerprint_t sq_fpr = NULL;
  1451     char *fpr = NULL;
  1452 
  1453     assert(session);
  1454     assert(identity);
  1455     assert(identity->address);
  1456     assert(identity->fpr == NULL || identity->fpr[0] == 0);
  1457     assert(identity->username);
  1458 
  1459     asprintf(&userid, "%s <%s>", identity->username, identity->address);
  1460     if (! userid)
  1461         ERROR_OUT(session, PEP_OUT_OF_MEMORY, "asprintf");
  1462 
  1463     T("(%s)", userid);
  1464 
  1465     // Generate a key.
  1466     sq_tsk_t tsk;
  1467     sq_signature_t rev;
  1468     if (sq_tsk_new(session->ctx, userid, &tsk, &rev) != 0)
  1469         ERROR_OUT(session, PEP_CANNOT_CREATE_KEY, "Generating a key pair");
  1470 
  1471     // XXX: We should return this.
  1472     // sq_signature_free(rev);
  1473 
  1474     tpk = sq_tsk_into_tpk(tsk);
  1475 
  1476     // Get the fingerprint.
  1477     sq_fpr = sq_tpk_fingerprint(tpk);
  1478     fpr = sq_fingerprint_to_hex(sq_fpr);
  1479 
  1480     status = tpk_save(session, tpk, NULL);
  1481     tpk = NULL;
  1482     if (status != 0)
  1483         ERROR_OUT(session, PEP_CANNOT_CREATE_KEY, "saving TSK");
  1484 
  1485     free(identity->fpr);
  1486     identity->fpr = fpr;
  1487     fpr = NULL;
  1488 
  1489  out:
  1490     if (sq_fpr)
  1491         sq_fingerprint_free(sq_fpr);
  1492     free(fpr);
  1493     if (tpk)
  1494         sq_tpk_free(tpk);
  1495     free(userid);
  1496 
  1497     T("-> %s", pep_status_to_string(status));
  1498     return status;
  1499 }
  1500 
  1501 PEP_STATUS pgp_delete_keypair(PEP_SESSION session, const char *fpr_raw)
  1502 {
  1503     PEP_STATUS status = PEP_STATUS_OK;
  1504     char *fpr = sq_fingerprint_canonicalize(fpr_raw);
  1505 
  1506     T("(%s)", fpr);
  1507 
  1508     // XXX: Can also be used for deleting public keys!!!
  1509     assert(!"implement me");
  1510 
  1511     T("(%s) -> %s", fpr, pep_status_to_string(status));
  1512 
  1513     free(fpr);
  1514     return status;
  1515 }
  1516 
  1517 // XXX: This needs to handle not only TPKs, but also keyrings and
  1518 // revocation certificates.  Right now, we only import a single TPK
  1519 // and ignore everything else.
  1520 PEP_STATUS pgp_import_keydata(PEP_SESSION session, const char *key_data,
  1521                               size_t size, identity_list **private_idents)
  1522 {
  1523     PEP_STATUS status = PEP_STATUS_OK;
  1524 
  1525     if (private_idents)
  1526         *private_idents = NULL;
  1527 
  1528     T("parsing %zd bytes", size);
  1529 
  1530     sq_packet_parser_result_t ppr
  1531         = sq_packet_parser_from_bytes(session->ctx, (uint8_t *) key_data, size);
  1532     if (! ppr)
  1533         ERROR_OUT(session, PEP_UNKNOWN_ERROR, "Creating packet parser");
  1534 
  1535     sq_tag_t tag = sq_packet_parser_result_tag(ppr);
  1536     switch (tag) {
  1537     case SQ_TAG_SIGNATURE:
  1538         // XXX: Implement me.
  1539         assert(!"Have possible revocation certificate!");
  1540         break;
  1541 
  1542     case SQ_TAG_PUBLIC_KEY:
  1543     case SQ_TAG_SECRET_KEY: {
  1544         sq_tpk_t tpk = sq_tpk_from_packet_parser(session->ctx, ppr);
  1545         if (! tpk)
  1546             ERROR_OUT(session, PEP_UNKNOWN_ERROR, "parsing key data");
  1547 
  1548         // If private_idents is not NULL and there is any private key
  1549         // material, it will be saved.
  1550         status = tpk_save(session, tpk, private_idents);
  1551         ERROR_OUT(session, status, "saving TPK");
  1552 
  1553         break;
  1554     }
  1555     default:
  1556         ERROR_OUT(session, PEP_STATUS_OK,
  1557                   "Can't import %s", sq_tag_to_string(tag));
  1558         break;
  1559     }
  1560 
  1561  out:
  1562     T("-> %s", pep_status_to_string(status));
  1563     return status;
  1564 }
  1565 
  1566 PEP_STATUS pgp_export_keydata(
  1567         PEP_SESSION session, const char *fpr, char **key_data, size_t *size,
  1568         bool secret)
  1569 {
  1570     PEP_STATUS status = PEP_STATUS_OK;
  1571     sq_tpk_t secret_key = NULL;
  1572     sq_tpk_t tpk = NULL;
  1573 
  1574     assert(session);
  1575     assert(fpr);
  1576     assert(key_data);
  1577     assert(*key_data == NULL);
  1578     assert(size);
  1579 
  1580     *size = 0;
  1581 
  1582     T("(%s, %s)", fpr, secret ? "secret" : "public");
  1583 
  1584     if (secret) {
  1585         status = tpk_find_by_fpr_hex(session, fpr, true, &secret_key, NULL);
  1586         if (status == PEP_KEY_NOT_FOUND)
  1587             status = PEP_STATUS_OK;
  1588         ERROR_OUT(session, status, "Looking up TSK for %s", fpr);
  1589     }
  1590 
  1591     sq_fingerprint_t sq_fpr = sq_fingerprint_from_hex(fpr);
  1592     status = tpk_find_by_fpr(session, sq_fpr, false, &tpk, NULL);
  1593     sq_fingerprint_free(sq_fpr);
  1594     ERROR_OUT(session, status, "Looking up TPK for %s", fpr);
  1595 
  1596     if (secret_key) {
  1597         tpk = sq_tpk_merge(session->ctx, tpk, secret_key);
  1598         // sq_tpk_merge can return NULL if the primary keys don't
  1599         // match.  But, we looked up the tpk by the secret key's
  1600         // fingerprint so this should not be possible.
  1601         assert(tpk);
  1602         secret_key = NULL;
  1603     }
  1604 
  1605     sq_writer_t memory_writer = sq_writer_alloc((void **) key_data, size);
  1606     if (! memory_writer)
  1607         ERROR_OUT(session, PEP_UNKNOWN_ERROR, "creating memory writer");
  1608     sq_writer_t armor_writer = sq_armor_writer_new(session->ctx,
  1609                                                    memory_writer,
  1610                                                    SQ_ARMOR_KIND_PUBLICKEY,
  1611                                                    NULL, 0);
  1612     if (! armor_writer) {
  1613         sq_writer_free(memory_writer);
  1614         ERROR_OUT(session, PEP_UNKNOWN_ERROR, "creating armored writer");
  1615     }
  1616 
  1617     if (secret) {
  1618         sq_tsk_t tsk = sq_tpk_into_tsk(tpk);
  1619         sq_tsk_serialize(session->ctx, tsk, armor_writer);
  1620         tpk = sq_tsk_into_tpk(tsk);
  1621     } else {
  1622         sq_tpk_serialize(session->ctx, tpk, armor_writer);
  1623     }
  1624 
  1625  out:
  1626     if (tpk)
  1627         sq_tpk_free(tpk);
  1628 
  1629     if (armor_writer)
  1630         sq_writer_free(armor_writer);
  1631 
  1632     if (secret_key)
  1633         sq_tpk_free(secret_key);
  1634 
  1635     T("(%s) -> %s", fpr, pep_status_to_string(status));
  1636     return status;
  1637 }
  1638 
  1639 char* _undot_address(const char* address) {
  1640     if (!address)
  1641         return NULL;
  1642 
  1643     int addr_len = strlen(address);
  1644     const char* at = strstr(address, "@");
  1645 
  1646     if (!at)
  1647         at = address + addr_len;
  1648 
  1649     char* retval = calloc(1, addr_len + 1);
  1650 
  1651     const char* addr_curr = address;
  1652     char* retval_curr = retval;
  1653 
  1654     while (addr_curr < at) {
  1655         if (*addr_curr == '.') {
  1656             addr_curr++;
  1657             continue;
  1658         }
  1659         *retval_curr = *addr_curr;
  1660         retval_curr++;
  1661         addr_curr++;
  1662     }
  1663     if (*addr_curr == '@')
  1664         strcat(retval_curr, addr_curr);
  1665 
  1666     return retval;
  1667 }
  1668 
  1669 static stringpair_list_t *add_key(PEP_SESSION session,
  1670                                   stringpair_list_t *keyinfo_list,
  1671                                   stringlist_t* keylist,
  1672                                   sq_tpk_t tpk, sq_fingerprint_t fpr) {
  1673     bool revoked = false;
  1674     // Don't add revoked keys to the keyinfo_list.
  1675     if (keyinfo_list) {
  1676         sq_revocation_status_t rs = sq_tpk_revocation_status(tpk);
  1677         sq_revocation_status_variant_t rsv = sq_revocation_status_variant(rs);
  1678         sq_revocation_status_free(rs);
  1679         if (rsv == SQ_REVOCATION_STATUS_REVOKED)
  1680             revoked = true;
  1681     }
  1682 
  1683     if (revoked && ! keylist)
  1684         return keyinfo_list;
  1685 
  1686     int dealloc_fpr = 0;
  1687     if (!fpr) {
  1688         dealloc_fpr = 1;
  1689         fpr = sq_tpk_fingerprint(tpk);
  1690     }
  1691     char *fpr_str = sq_fingerprint_to_hex(fpr);
  1692 
  1693     if (!revoked && keyinfo_list) {
  1694         char *user_id = sq_tpk_primary_user_id(tpk);
  1695         if (user_id)
  1696             keyinfo_list = stringpair_list_add(keyinfo_list,
  1697                                                new_stringpair(fpr_str, user_id));
  1698         free(user_id);
  1699     }
  1700 
  1701     if (keylist)
  1702         keylist = stringlist_add(keylist, fpr_str);
  1703 
  1704     free(fpr_str);
  1705     if (dealloc_fpr)
  1706         sq_fingerprint_free(fpr);
  1707 
  1708     return keyinfo_list;
  1709 }
  1710 
  1711 static PEP_STATUS list_keys(PEP_SESSION session,
  1712                             const char* pattern, int private_only,
  1713                             stringpair_list_t** keyinfo_list, stringlist_t** keylist)
  1714 {
  1715     PEP_STATUS status = PEP_STATUS_OK;
  1716     sq_tpk_t tpk = NULL;
  1717     sq_fingerprint_t fpr = NULL;
  1718 
  1719     T("('%s', private: %d)", pattern, private_only);
  1720 
  1721     stringpair_list_t* _keyinfo_list = NULL;
  1722     if (keyinfo_list) {
  1723         _keyinfo_list = new_stringpair_list(NULL);
  1724         if (!_keyinfo_list)
  1725             ERROR_OUT(session, PEP_OUT_OF_MEMORY, "new_stringpair_list");
  1726     }
  1727     stringlist_t* _keylist = NULL;
  1728     if (keylist) {
  1729         _keylist = new_stringlist(NULL);
  1730         if (!_keylist)
  1731             ERROR_OUT(session, PEP_OUT_OF_MEMORY, "new_string_list");
  1732     }
  1733 
  1734     // Trim any leading space.  This also makes it easier to recognize
  1735     // a string that is only whitespace.
  1736     while (*pattern == ' ')
  1737         pattern ++;
  1738 
  1739     if (strchr(pattern, '@')) {
  1740         // Looks like a mailbox.
  1741         sq_tpk_t *tpks = NULL;
  1742         int count = 0;
  1743         status = tpk_find_by_email(session, pattern, private_only, &tpks, &count);
  1744         ERROR_OUT(session, status, "Looking up '%s'", pattern);
  1745         for (int i = 0; i < count; i ++) {
  1746             add_key(session, _keyinfo_list, _keylist, tpks[i], NULL);
  1747             sq_tpk_free(tpks[i]);
  1748         }
  1749         free(tpks);
  1750 
  1751         if (count == 0) {
  1752             // If match failed, check to see if we've got a dotted
  1753             // address in the pattern.  If so, try again without dots.
  1754             const char* dotpos = strstr(pattern, ".");
  1755             const char* atpos = strstr(pattern, "@");
  1756             if (dotpos && atpos && (dotpos < atpos)) {
  1757                 char* undotted = _undot_address(pattern);
  1758                 if (undotted) {
  1759                     PEP_STATUS status = list_keys(session, undotted, private_only,
  1760                                                   keyinfo_list, keylist);
  1761                     free(undotted);
  1762                     return status;
  1763                 }
  1764             }
  1765         }
  1766     } else if (// Only hex characters and spaces
  1767                pattern[strspn(pattern, "0123456789aAbBcCdDeEfF ")] == 0
  1768                // And a fair amount of them.
  1769                && strlen(pattern) >= 16) {
  1770         // Fingerprint.
  1771         fpr = sq_fingerprint_from_hex(pattern);
  1772         status = tpk_find_by_fpr(session, fpr, false, &tpk, NULL);
  1773         ERROR_OUT(session, status, "Looking up key");
  1774         add_key(session, _keyinfo_list, _keylist, tpk, fpr);
  1775     } else if (pattern[0] == 0) {
  1776         // Empty string.
  1777 
  1778         sq_tpk_t *tpks = NULL;
  1779         int count = 0;
  1780         status = tpk_all(session, private_only, &tpks, &count);
  1781         ERROR_OUT(session, status, "Looking up '%s'", pattern);
  1782         for (int i = 0; i < count; i ++) {
  1783             add_key(session, _keyinfo_list, _keylist, tpks[i], NULL);
  1784             sq_tpk_free(tpks[i]);
  1785         }
  1786         free(tpks);
  1787     } else {
  1788         T("unsupported pattern '%s'", pattern);
  1789     }
  1790 
  1791  out:
  1792     if (tpk)
  1793         sq_tpk_free(tpk);
  1794     if (fpr)
  1795         sq_fingerprint_free(fpr);
  1796 
  1797     if (status == PEP_KEY_NOT_FOUND)
  1798         status = PEP_STATUS_OK;
  1799 
  1800     if (status != PEP_STATUS_OK || (_keyinfo_list && !_keyinfo_list->value)) {
  1801         free_stringpair_list(_keyinfo_list);
  1802         _keyinfo_list = NULL;
  1803     }
  1804     if (keyinfo_list)
  1805         *keyinfo_list = _keyinfo_list;
  1806 
  1807     if (status != PEP_STATUS_OK || (_keylist && !_keylist->value)) {
  1808         free_stringlist(_keylist);
  1809         _keylist = NULL;
  1810     }
  1811     if (keylist)
  1812         *keylist = _keylist;
  1813 
  1814     int len = -1;
  1815     if (keylist)
  1816         len = stringlist_length(*keylist);
  1817     else if (keyinfo_list)
  1818         len = stringpair_list_length(*keyinfo_list);
  1819     T("(%s) -> %s (%d keys)", pattern, pep_status_to_string(status), len);
  1820     return status;
  1821 }
  1822 
  1823 // pattern could be empty, an fpr, or a mailbox.
  1824 //
  1825 // keyinfo_list is a list of <fpr, openpgp userid> tuples for the
  1826 // matching keys.
  1827 //
  1828 // This function filters out revoked key, but not expired keys.
  1829 PEP_STATUS pgp_list_keyinfo(PEP_SESSION session,
  1830                             const char* pattern,
  1831                             stringpair_list_t** keyinfo_list)
  1832 {
  1833     return list_keys(session, pattern, false, keyinfo_list, NULL);
  1834 }
  1835 
  1836 PEP_STATUS pgp_recv_key(PEP_SESSION session, const char *pattern)
  1837 {
  1838     assert(!"pgp_recv_key not implemented");
  1839     return PEP_UNKNOWN_ERROR;
  1840 }
  1841 
  1842 // Unlike pgp_list_keyinfo, this function returns revoked keys.
  1843 PEP_STATUS pgp_find_keys(
  1844     PEP_SESSION session, const char *pattern, stringlist_t **keylist)
  1845 {
  1846     return list_keys(session, pattern, false, NULL, keylist);
  1847 }
  1848 
  1849 // Unlike pgp_list_keyinfo, this function returns revoked keys.
  1850 PEP_STATUS pgp_find_private_keys(
  1851     PEP_SESSION session, const char *pattern, stringlist_t **keylist)
  1852 {
  1853     return list_keys(session, pattern, true, NULL, keylist);
  1854 }
  1855 
  1856 PEP_STATUS pgp_send_key(PEP_SESSION session, const char *pattern)
  1857 {
  1858     assert(!"pgp_send_key not implemented");
  1859     return PEP_UNKNOWN_ERROR;
  1860 }
  1861 
  1862 PEP_STATUS pgp_get_key_rating(
  1863     PEP_SESSION session, const char *fpr, PEP_comm_type *comm_type)
  1864 {
  1865     PEP_STATUS status = PEP_STATUS_OK;
  1866     sq_tpk_t tpk = NULL;
  1867 
  1868     assert(session);
  1869     assert(fpr);
  1870     assert(comm_type);
  1871 
  1872     *comm_type = PEP_ct_unknown;
  1873 
  1874     sq_fingerprint_t sq_fpr = sq_fingerprint_from_hex(fpr);
  1875     status = tpk_find_by_fpr(session, sq_fpr, false, &tpk, NULL);
  1876     sq_fingerprint_free(sq_fpr);
  1877     ERROR_OUT(session, status, "Looking up key: %s", fpr);
  1878 
  1879     *comm_type = PEP_ct_OpenPGP_unconfirmed;
  1880 
  1881     if (sq_tpk_expired(tpk)) {
  1882         *comm_type = PEP_ct_key_expired;
  1883         goto out;
  1884     }
  1885 
  1886     sq_revocation_status_t rs = sq_tpk_revocation_status(tpk);
  1887     sq_revocation_status_variant_t rsv = sq_revocation_status_variant(rs);
  1888     sq_revocation_status_free(rs);
  1889     if (rsv == SQ_REVOCATION_STATUS_REVOKED) {
  1890         *comm_type = PEP_ct_key_revoked;
  1891         goto out;
  1892     }
  1893 
  1894     PEP_comm_type best_enc = PEP_ct_no_encryption, best_sign = PEP_ct_no_encryption;
  1895     sq_tpk_key_iter_t key_iter = sq_tpk_key_iter(tpk);
  1896     sq_p_key_t key;
  1897     sq_signature_t sig;
  1898     sq_revocation_status_t rev;
  1899     while ((key = sq_tpk_key_iter_next(key_iter, &sig, &rev))) {
  1900         if (! sig)
  1901             continue;
  1902 
  1903         if (sq_revocation_status_variant(rev) == SQ_REVOCATION_STATUS_REVOKED)
  1904             continue;
  1905 
  1906         if (! sq_p_key_alive(key, sig))
  1907             continue;
  1908 
  1909         PEP_comm_type curr = PEP_ct_no_encryption;
  1910 
  1911         int can_enc = sq_signature_can_encrypt_for_transport(sig)
  1912             || sq_signature_can_encrypt_at_rest(sig);
  1913         int can_sign = sq_signature_can_sign(sig);
  1914 
  1915         sq_public_key_algo_t pk_algo = sq_p_key_public_key_algo(key);
  1916         if (pk_algo == SQ_PUBLIC_KEY_ALGO_RSA_ENCRYPT_SIGN
  1917             || pk_algo == SQ_PUBLIC_KEY_ALGO_RSA_ENCRYPT
  1918             || pk_algo == SQ_PUBLIC_KEY_ALGO_RSA_SIGN) {
  1919             int bits = sq_p_key_public_key_bits(key);
  1920             if (bits < 1024)
  1921                 curr = PEP_ct_key_too_short;
  1922             else if (bits == 1024)
  1923                 curr = PEP_ct_OpenPGP_weak_unconfirmed;
  1924             else
  1925                 curr = PEP_ct_OpenPGP_unconfirmed;
  1926         } else {
  1927             curr = PEP_ct_OpenPGP_unconfirmed;
  1928         }
  1929 
  1930         if (can_enc)
  1931             best_enc = _MAX(best_enc, curr);
  1932 
  1933         if (can_sign)
  1934             best_sign = _MAX(best_sign, curr);
  1935     }
  1936     sq_tpk_key_iter_free(key_iter);
  1937 
  1938     if (best_enc == PEP_ct_no_encryption || best_sign == PEP_ct_no_encryption) {
  1939         *comm_type = PEP_ct_key_b0rken;
  1940         goto out;
  1941     } else {
  1942         *comm_type = _MIN(best_enc, best_sign);
  1943     }
  1944 
  1945  out:
  1946     if (tpk)
  1947         sq_tpk_free(tpk);
  1948 
  1949     T("(%s) -> %s", fpr, pep_comm_type_to_string(*comm_type));
  1950     return status;
  1951 }
  1952 
  1953 
  1954 PEP_STATUS pgp_renew_key(
  1955     PEP_SESSION session, const char *fpr, const timestamp *ts)
  1956 {
  1957     PEP_STATUS status = PEP_STATUS_OK;
  1958     sq_tpk_t tpk = NULL;
  1959     time_t t = mktime((struct tm *) ts);
  1960 
  1961     T("(%s)", fpr);
  1962 
  1963     status = tpk_find_by_fpr_hex(session, fpr, true, &tpk, NULL);
  1964     ERROR_OUT(session, status, "Looking up '%s'", fpr);
  1965 
  1966     uint32_t creation_time = sq_p_key_creation_time(sq_tpk_primary(tpk));
  1967     if (creation_time > t)
  1968         // The creation time is after the expiration time!
  1969         ERROR_OUT(session, PEP_UNKNOWN_ERROR,
  1970                   "creation time can't be after expiration time");
  1971 
  1972     uint32_t delta = t - creation_time;
  1973     tpk = sq_tpk_set_expiry(session->ctx, tpk, delta);
  1974     if (! tpk)
  1975         ERROR_OUT(session, PEP_UNKNOWN_ERROR, "setting expiration");
  1976 
  1977     status = tpk_save(session, tpk, NULL);
  1978     tpk = NULL;
  1979     ERROR_OUT(session, status, "Saving %s", fpr);
  1980 
  1981  out:
  1982     if (tpk)
  1983         sq_tpk_free(tpk);
  1984 
  1985     T("(%s) -> %s", fpr, pep_status_to_string(status));
  1986     return status;
  1987 }
  1988 
  1989 PEP_STATUS pgp_revoke_key(
  1990     PEP_SESSION session, const char *fpr, const char *reason)
  1991 {
  1992     PEP_STATUS status = PEP_STATUS_OK;
  1993     sq_tpk_t tpk = NULL;
  1994 
  1995     T("(%s)", fpr);
  1996 
  1997     status = tpk_find_by_fpr_hex(session, fpr, true, &tpk, NULL);
  1998     ERROR_OUT(session, status, "Looking up %s", fpr);
  1999 
  2000     tpk = sq_tpk_revoke_in_place(session->ctx, tpk,
  2001                                  SQ_REASON_FOR_REVOCATION_UNSPECIFIED,
  2002                                  reason);
  2003     if (! tpk)
  2004         ERROR_OUT(session, PEP_UNKNOWN_ERROR, "setting expiration");
  2005 
  2006     assert(sq_revocation_status_variant(sq_tpk_revocation_status(tpk))
  2007            == SQ_REVOCATION_STATUS_REVOKED);
  2008 
  2009     status = tpk_save(session, tpk, NULL);
  2010     tpk = NULL;
  2011     ERROR_OUT(session, status, "Saving %s", fpr);
  2012 
  2013  out:
  2014     if (tpk)
  2015         sq_tpk_free(tpk);
  2016 
  2017     T("(%s) -> %s", fpr, pep_status_to_string(status));
  2018     return status;
  2019 }
  2020 
  2021 PEP_STATUS pgp_key_expired(PEP_SESSION session, const char *fpr,
  2022                            const time_t when, bool *expired)
  2023 {
  2024     PEP_STATUS status = PEP_STATUS_OK;
  2025     sq_tpk_t tpk = NULL;
  2026     T("(%s)", fpr);
  2027 
  2028     assert(session);
  2029     assert(fpr);
  2030     assert(expired);
  2031 
  2032     *expired = false;
  2033 
  2034     sq_fingerprint_t sq_fpr = sq_fingerprint_from_hex(fpr);
  2035     status = tpk_find_by_fpr(session, sq_fpr, false, &tpk, NULL);
  2036     sq_fingerprint_free(sq_fpr);
  2037     ERROR_OUT(session, status, "Looking up %s", fpr);
  2038 
  2039     // Is the TPK live?
  2040     *expired = !sq_tpk_alive_at(tpk, when);
  2041     if (*expired)
  2042         goto out;
  2043 
  2044     // Are there at least one certification subkey, one signing subkey
  2045     // and one encryption subkey that are live?
  2046     int can_certify = 0, can_encrypt = 0, can_sign = 0;
  2047 
  2048     sq_tpk_key_iter_t key_iter = sq_tpk_key_iter(tpk);
  2049     sq_p_key_t key;
  2050     sq_signature_t sig;
  2051     sq_revocation_status_t rev;
  2052     while ((key = sq_tpk_key_iter_next(key_iter, &sig, &rev))) {
  2053         if (! sig)
  2054             continue;
  2055 
  2056         if (sq_revocation_status_variant(rev) == SQ_REVOCATION_STATUS_REVOKED)
  2057             continue;
  2058 
  2059         if (!sq_p_key_alive_at(key, sig, when))
  2060             continue;
  2061 
  2062         if (sq_signature_can_encrypt_for_transport(sig)
  2063             || sq_signature_can_encrypt_at_rest(sig))
  2064             can_encrypt = 1;
  2065         if (sq_signature_can_sign(sig))
  2066             can_sign = 1;
  2067         if (sq_signature_can_certify(sig))
  2068             can_certify = 1;
  2069 
  2070         if (can_encrypt && can_sign && can_certify)
  2071             break;
  2072     }
  2073     sq_tpk_key_iter_free(key_iter);
  2074 
  2075     *expired = !(can_encrypt && can_sign && can_certify);
  2076 
  2077  out:
  2078     if (tpk)
  2079         sq_tpk_free(tpk);
  2080     T("(%s) -> %s", fpr, pep_status_to_string(status));
  2081     return status;
  2082 }
  2083 
  2084 PEP_STATUS pgp_key_revoked(PEP_SESSION session, const char *fpr, bool *revoked)
  2085 {
  2086     PEP_STATUS status = PEP_STATUS_OK;
  2087     sq_tpk_t tpk;
  2088 
  2089     T("(%s)", fpr);
  2090 
  2091     assert(session);
  2092     assert(fpr);
  2093     assert(revoked);
  2094 
  2095     *revoked = false;
  2096 
  2097     sq_fingerprint_t sq_fpr = sq_fingerprint_from_hex(fpr);
  2098     status = tpk_find_by_fpr(session, sq_fpr, false, &tpk, NULL);
  2099     sq_fingerprint_free(sq_fpr);
  2100     ERROR_OUT(session, status, "Looking up %s", fpr);
  2101 
  2102     sq_revocation_status_t rs = sq_tpk_revocation_status(tpk);
  2103     *revoked = sq_revocation_status_variant(rs) == SQ_REVOCATION_STATUS_REVOKED;
  2104     sq_revocation_status_free (rs);
  2105     sq_tpk_free(tpk);
  2106 
  2107  out:
  2108     T("(%s) -> %s", fpr, pep_status_to_string(status));
  2109     return status;
  2110 }
  2111 
  2112 PEP_STATUS pgp_key_created(PEP_SESSION session, const char *fpr, time_t *created)
  2113 {
  2114     PEP_STATUS status = PEP_STATUS_OK;
  2115     sq_tpk_t tpk = NULL;
  2116     T("(%s)", fpr);
  2117 
  2118     *created = 0;
  2119 
  2120     sq_fingerprint_t sq_fpr = sq_fingerprint_from_hex(fpr);
  2121     status = tpk_find_by_fpr(session, sq_fpr, false, &tpk, NULL);
  2122     sq_fingerprint_free(sq_fpr);
  2123     ERROR_OUT(session, status, "Looking up %s", fpr);
  2124 
  2125     sq_p_key_t k = sq_tpk_primary(tpk);
  2126     *created = sq_p_key_creation_time(k);
  2127     sq_tpk_free(tpk);
  2128 
  2129  out:
  2130     T("(%s) -> %s", fpr, pep_status_to_string(status));
  2131     return status;
  2132 }
  2133 
  2134 PEP_STATUS pgp_binary(const char **path)
  2135 {
  2136     return PEP_STATUS_OK;
  2137 }
  2138 
  2139 PEP_STATUS pgp_contains_priv_key(PEP_SESSION session, const char *fpr,
  2140                                  bool *has_private)
  2141 {
  2142     T("(%s)", fpr);
  2143     sq_fingerprint_t sq_fpr = sq_fingerprint_from_hex(fpr);
  2144     PEP_STATUS status = tpk_find_by_fpr(session, sq_fpr, true, NULL, NULL);
  2145     sq_fingerprint_free(sq_fpr);
  2146     if (status == PEP_STATUS_OK) {
  2147         *has_private = 1;
  2148     } else if (status == PEP_KEY_NOT_FOUND) {
  2149         *has_private = 0;
  2150         status = PEP_STATUS_OK;
  2151     }
  2152     T("(%s) -> %s", fpr, pep_status_to_string(status));
  2153     return status;
  2154 }