sequoia: Select keys more carefully. sync
authorNeal H. Walfield <neal@pep.foundation>
Wed, 20 Mar 2019 19:32:56 +0100
branchsync
changeset 3356e705998bf59c
parent 3355 dd4033892b54
child 3357 9f3cca6deda9
sequoia: Select keys more carefully.
src/pgp_sequoia.c
     1.1 --- a/src/pgp_sequoia.c	Wed Mar 20 18:39:00 2019 +0100
     1.2 +++ b/src/pgp_sequoia.c	Wed Mar 20 19:32:56 2019 +0100
     1.3 @@ -1249,12 +1249,35 @@
     1.4  
     1.5      PEP_STATUS status = PEP_STATUS_OK;
     1.6      pgp_error_t err = NULL;
     1.7 -    pgp_tpk_t signer = NULL;
     1.8 +    pgp_tpk_t signer_tpk = NULL;
     1.9 +    pgp_tpk_key_iter_t iter = NULL;
    1.10 +    pgp_key_pair_t signing_keypair = NULL;
    1.11 +    pgp_signer_t signer = NULL;
    1.12      pgp_writer_stack_t ws = NULL;
    1.13  
    1.14 -    status = tpk_find_by_fpr_hex(session, fpr, true, &signer, NULL);
    1.15 +    status = tpk_find_by_fpr_hex(session, fpr, true, &signer_tpk, NULL);
    1.16      ERROR_OUT(NULL, status, "Looking up key '%s'", fpr);
    1.17  
    1.18 +    iter = pgp_tpk_key_iter_valid(signer_tpk);
    1.19 +    pgp_tpk_key_iter_signing_capable (iter);
    1.20 +    pgp_tpk_key_iter_unencrypted_secret (iter, true);
    1.21 +
    1.22 +    // If there are multiple signing capable subkeys, we just take
    1.23 +    // the first one, whichever one that happens to be.
    1.24 +    pgp_key_t key = pgp_tpk_key_iter_next (iter, NULL, NULL);
    1.25 +    if (! key)
    1.26 +        ERROR_OUT (err, PEP_UNKNOWN_ERROR,
    1.27 +                   "%s has no signing capable key", fpr);
    1.28 +
    1.29 +    signing_keypair = pgp_key_into_key_pair (NULL, pgp_key_clone (key));
    1.30 +    if (! signing_keypair)
    1.31 +        ERROR_OUT (err, PEP_UNKNOWN_ERROR, "Creating a keypair");
    1.32 +
    1.33 +    signer = pgp_key_pair_as_signer (signing_keypair);
    1.34 +    if (! signer)
    1.35 +        ERROR_OUT (err, PEP_UNKNOWN_ERROR, "Creating a signer");
    1.36 +
    1.37 +
    1.38      pgp_writer_t writer = pgp_writer_alloc((void **) stext, ssize);
    1.39      writer = pgp_armor_writer_new(&err, writer,
    1.40                                    PGP_ARMOR_KIND_MESSAGE, NULL, 0);
    1.41 @@ -1289,7 +1312,13 @@
    1.42      }
    1.43  
    1.44      if (signer)
    1.45 -        pgp_tpk_free(signer);
    1.46 +        pgp_signer_free (signer);
    1.47 +    if (signing_keypair)
    1.48 +        pgp_key_pair_free (signing_keypair);
    1.49 +    if (iter)
    1.50 +        pgp_tpk_key_iter_free (iter);
    1.51 +    if (signer_tpk)
    1.52 +        pgp_tpk_free(signer_tpk);
    1.53  
    1.54      T("(%s)-> %s", fpr, pep_status_to_string(status));
    1.55      return status;
    1.56 @@ -1303,8 +1332,11 @@
    1.57      pgp_error_t err = NULL;
    1.58      int keys_count = 0;
    1.59      pgp_tpk_t *keys = NULL;
    1.60 -    pgp_tpk_t signer = NULL;
    1.61 +    pgp_tpk_t signer_tpk = NULL;
    1.62      pgp_writer_stack_t ws = NULL;
    1.63 +    pgp_tpk_key_iter_t iter = NULL;
    1.64 +    pgp_key_pair_t signing_keypair = NULL;
    1.65 +    pgp_signer_t signer = NULL;
    1.66  
    1.67      assert(session);
    1.68      assert(keylist);
    1.69 @@ -1332,7 +1364,7 @@
    1.70  
    1.71      if (sign) {
    1.72          // The first key in the keylist is the signer.
    1.73 -        status = tpk_find_by_fpr_hex(session, keylist->value, true, &signer, NULL);
    1.74 +        status = tpk_find_by_fpr_hex(session, keylist->value, true, &signer_tpk, NULL);
    1.75          ERROR_OUT(NULL, status, "Looking up key for signing '%s'", keylist->value);
    1.76      }
    1.77  
    1.78 @@ -1352,12 +1384,24 @@
    1.79      }
    1.80  
    1.81      if (sign) {
    1.82 -        pgp_key_t primary_key = pgp_tpk_primary (signer);
    1.83 -        pgp_key_pair_t primary_keypair
    1.84 -            = pgp_key_into_key_pair (NULL, pgp_key_clone (primary_key));
    1.85 -        pgp_key_free (primary_key);
    1.86 -        assert (primary_keypair);
    1.87 -        pgp_signer_t primary_signer = pgp_key_pair_as_signer (primary_keypair);
    1.88 +        iter = pgp_tpk_key_iter_valid(signer_tpk);
    1.89 +        pgp_tpk_key_iter_signing_capable (iter);
    1.90 +        pgp_tpk_key_iter_unencrypted_secret (iter, true);
    1.91 +
    1.92 +        // If there are multiple signing capable subkeys, we just take
    1.93 +        // the first one, whichever one that happens to be.
    1.94 +        pgp_key_t key = pgp_tpk_key_iter_next (iter, NULL, NULL);
    1.95 +        if (! key)
    1.96 +            ERROR_OUT (err, PEP_UNKNOWN_ERROR,
    1.97 +                       "%s has no signing capable key", keylist->value);
    1.98 +
    1.99 +        signing_keypair = pgp_key_into_key_pair (NULL, pgp_key_clone (key));
   1.100 +        if (! signing_keypair)
   1.101 +            ERROR_OUT (err, PEP_UNKNOWN_ERROR, "Creating a keypair");
   1.102 +
   1.103 +        signer = pgp_key_pair_as_signer (signing_keypair);
   1.104 +        if (! signer)
   1.105 +            ERROR_OUT (err, PEP_UNKNOWN_ERROR, "Creating a signer");
   1.106  
   1.107          ws = pgp_signer_new(&err, ws, &signer, 1);
   1.108          if (!ws)
   1.109 @@ -1390,7 +1434,14 @@
   1.110      }
   1.111  
   1.112      if (signer)
   1.113 -        pgp_tpk_free(signer);
   1.114 +        pgp_signer_free (signer);
   1.115 +    if (signing_keypair)
   1.116 +        pgp_key_pair_free (signing_keypair);
   1.117 +    if (iter)
   1.118 +        pgp_tpk_key_iter_free (iter);
   1.119 +    if (signer_tpk)
   1.120 +        pgp_tpk_free(signer_tpk);
   1.121 +
   1.122      for (int i = 0; i < keys_count; i ++)
   1.123          pgp_tpk_free(keys[i]);
   1.124      free(keys);
   1.125 @@ -1939,6 +1990,9 @@
   1.126      PEP_STATUS status = PEP_STATUS_OK;
   1.127      pgp_error_t err = NULL;
   1.128      pgp_tpk_t tpk = NULL;
   1.129 +    pgp_tpk_key_iter_t iter = NULL;
   1.130 +    pgp_key_pair_t keypair = NULL;
   1.131 +    pgp_signer_t signer = NULL;
   1.132      time_t t = mktime((struct tm *) ts);
   1.133  
   1.134      T("(%s)", fpr);
   1.135 @@ -1953,7 +2007,28 @@
   1.136                    "creation time can't be after expiration time");
   1.137  
   1.138      uint32_t delta = t - creation_time;
   1.139 -    tpk = pgp_tpk_set_expiry(&err, tpk, delta);
   1.140 +
   1.141 +
   1.142 +    iter = pgp_tpk_key_iter_valid(tpk);
   1.143 +    pgp_tpk_key_iter_certification_capable (iter);
   1.144 +    pgp_tpk_key_iter_unencrypted_secret (iter, true);
   1.145 +
   1.146 +    // If there are multiple certification capable subkeys, we just
   1.147 +    // take the first one, whichever one that happens to be.
   1.148 +    pgp_key_t key = pgp_tpk_key_iter_next (iter, NULL, NULL);
   1.149 +    if (! key)
   1.150 +        ERROR_OUT (err, PEP_UNKNOWN_ERROR,
   1.151 +                   "%s has no usable certification capable key", fpr);
   1.152 +
   1.153 +    keypair = pgp_key_into_key_pair (NULL, pgp_key_clone (key));
   1.154 +    if (! keypair)
   1.155 +        ERROR_OUT (err, PEP_UNKNOWN_ERROR, "Creating a keypair");
   1.156 +
   1.157 +    signer = pgp_key_pair_as_signer (keypair);
   1.158 +    if (! signer)
   1.159 +        ERROR_OUT (err, PEP_UNKNOWN_ERROR, "Creating a signer");
   1.160 +
   1.161 +    tpk = pgp_tpk_set_expiry(&err, tpk, signer, delta);
   1.162      if (! tpk)
   1.163          ERROR_OUT(err, PEP_UNKNOWN_ERROR, "setting expiration");
   1.164  
   1.165 @@ -1962,6 +2037,12 @@
   1.166      ERROR_OUT(NULL, status, "Saving %s", fpr);
   1.167  
   1.168   out:
   1.169 +    if (signer)
   1.170 +        pgp_signer_free (signer);
   1.171 +    if (keypair)
   1.172 +        pgp_key_pair_free (keypair);
   1.173 +    if (iter)
   1.174 +        pgp_tpk_key_iter_free (iter);
   1.175      if (tpk)
   1.176          pgp_tpk_free(tpk);
   1.177  
   1.178 @@ -1975,24 +2056,37 @@
   1.179      PEP_STATUS status = PEP_STATUS_OK;
   1.180      pgp_error_t err = NULL;
   1.181      pgp_tpk_t tpk = NULL;
   1.182 +    pgp_tpk_key_iter_t iter = NULL;
   1.183 +    pgp_key_pair_t keypair = NULL;
   1.184 +    pgp_signer_t signer = NULL;
   1.185  
   1.186      T("(%s)", fpr);
   1.187  
   1.188      status = tpk_find_by_fpr_hex(session, fpr, true, &tpk, NULL);
   1.189      ERROR_OUT(NULL, status, "Looking up %s", fpr);
   1.190  
   1.191 -    pgp_key_t primary_key = pgp_tpk_primary (tpk);
   1.192 -    pgp_key_pair_t primary_keypair
   1.193 -        = pgp_key_into_key_pair (NULL, pgp_key_clone (primary_key));
   1.194 -    pgp_key_free (primary_key);
   1.195 -    assert (primary_keypair);
   1.196 -    pgp_signer_t primary_signer = pgp_key_pair_as_signer (primary_keypair);
   1.197 +    iter = pgp_tpk_key_iter_valid(tpk);
   1.198 +    pgp_tpk_key_iter_certification_capable (iter);
   1.199 +    pgp_tpk_key_iter_unencrypted_secret (iter, true);
   1.200  
   1.201 -    tpk = pgp_tpk_revoke_in_place(&err, tpk, primary_signer,
   1.202 +    // If there are multiple certification capable subkeys, we just
   1.203 +    // take the first one, whichever one that happens to be.
   1.204 +    pgp_key_t key = pgp_tpk_key_iter_next (iter, NULL, NULL);
   1.205 +    if (! key)
   1.206 +        ERROR_OUT (err, PEP_UNKNOWN_ERROR,
   1.207 +                   "%s has no usable certification capable key", fpr);
   1.208 +
   1.209 +    keypair = pgp_key_into_key_pair (NULL, pgp_key_clone (key));
   1.210 +    if (! keypair)
   1.211 +        ERROR_OUT (err, PEP_UNKNOWN_ERROR, "Creating a keypair");
   1.212 +
   1.213 +    signer = pgp_key_pair_as_signer (keypair);
   1.214 +    if (! signer)
   1.215 +        ERROR_OUT (err, PEP_UNKNOWN_ERROR, "Creating a signer");
   1.216 +
   1.217 +    tpk = pgp_tpk_revoke_in_place(&err, tpk, signer,
   1.218                                    PGP_REASON_FOR_REVOCATION_UNSPECIFIED,
   1.219                                    reason);
   1.220 -    pgp_signer_free (primary_signer);
   1.221 -    pgp_key_pair_free (primary_keypair);
   1.222      if (! tpk)
   1.223          ERROR_OUT(err, PEP_UNKNOWN_ERROR, "setting expiration");
   1.224  
   1.225 @@ -2004,6 +2098,12 @@
   1.226      ERROR_OUT(NULL, status, "Saving %s", fpr);
   1.227  
   1.228   out:
   1.229 +    if (signer)
   1.230 +        pgp_signer_free (signer);
   1.231 +    if (keypair)
   1.232 +        pgp_key_pair_free (keypair);
   1.233 +    if (iter)
   1.234 +        pgp_tpk_key_iter_free (iter);
   1.235      if (tpk)
   1.236          pgp_tpk_free(tpk);
   1.237