src/pgp_sequoia.c
author us@chu.huenfield.org
Tue, 25 Dec 2018 14:46:45 +0100
branchsync
changeset 3209 c15b4ca2b52a
parent 3197 6eb348201d7f
child 3211 8ca54e726b3c
permissions -rw-r--r--
Replace use of Sequoia's backend with a custom key store.

- Sequoia's key store doesn't meet pep's needs (in particular, the
ability to search on a key's user id) and trying to shoehorn pep's
needs onto Sequoia's key store abstractions is just introducing
overhead with no appreciable gain in functionality.

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