src/pgp_sequoia.c
author Neal H. Walfield <neal@pep.foundation>
Fri, 28 Dec 2018 12:47:31 +0100
branchsync
changeset 3213 e56efa502f08
parent 3212 fb4124923112
child 3272 4d6c07372e3e
permissions -rw-r--r--
Enable secure_delete and foreign_keys on the Sequoia key DB.

- Secure delete is important since we are storing private keys.

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