Merged in sequoia changes Release_2.1 Release_2.1.2
authorKrista 'DarthMama' Bennett <krista@pep.foundation>
Mon, 12 Oct 2020 15:37:10 +0200
branchRelease_2.1
changeset 5097c01b89092117
parent 5096 d97ad58c2548
parent 5095 18a023639e7c
child 5101 b98dbc54f80c
Merged in sequoia changes
     1.1 --- a/src/pgp_sequoia.c	Mon Oct 12 15:35:05 2020 +0200
     1.2 +++ b/src/pgp_sequoia.c	Mon Oct 12 15:37:10 2020 +0200
     1.3 @@ -231,82 +231,120 @@
     1.4      return result;
     1.5  }
     1.6  
     1.7 +// Decrypts the key.
     1.8 +//
     1.9 +// This function takes ownership of key (key must be owned; not a
    1.10 +// reference).
    1.11 +//
    1.12 +// On success, it sets *decrypt_key to the decrypted key, which the
    1.13 +// caller owns, and returns PEP_STATUS_OK.  On failure, key is freed,
    1.14 +// *decrypted_key is set to NULL, and an error is returned.
    1.15  static PEP_STATUS _pgp_get_decrypted_key(PEP_SESSION session,
    1.16 -                                         pgp_cert_valid_key_iter_t iter,
    1.17 +                                         pgp_key_t key,
    1.18                                           pgp_key_t* decrypted_key) {
    1.19 -
    1.20 +    PEP_STATUS status = PEP_STATUS_OK;
    1.21 +    pgp_error_t err = NULL;
    1.22 +
    1.23 +    pgp_fingerprint_t pgp_fpr = pgp_key_fingerprint(key);
    1.24 +    char *fpr = pgp_fingerprint_to_hex(pgp_fpr);
    1.25 +    T("(%s)", fpr);
    1.26 +
    1.27 +    if (!decrypted_key)
    1.28 +        ERROR_OUT (err, PEP_ILLEGAL_VALUE, "missing decrypted_key parameter");
    1.29 +    *decrypted_key = NULL;
    1.30 +    if (!key)
    1.31 +        ERROR_OUT (err, PEP_ILLEGAL_VALUE, "missing key parameter");
    1.32 +
    1.33 +    if (pgp_key_has_unencrypted_secret(key)) {
    1.34 +        // In case key is a reference (and not an owned value), we
    1.35 +        // clone it.
    1.36 +        *decrypted_key = key;
    1.37 +        key = NULL;
    1.38 +    } else {
    1.39 +        const char* pass = session->curr_passphrase;
    1.40 +        if (pass && pass[0]) {
    1.41 +            *decrypted_key = pgp_key_decrypt_secret(&err, key,
    1.42 +                                                    (uint8_t*)pass,
    1.43 +                                                    strlen(pass));
    1.44 +            key = NULL;
    1.45 +            if (!*decrypted_key) {
    1.46 +                ERROR_OUT (err, PEP_WRONG_PASSPHRASE, "wrong passphrase");
    1.47 +            }
    1.48 +        } else {
    1.49 +            ERROR_OUT (err, PEP_PASSPHRASE_REQUIRED, "passphrase required");
    1.50 +        }
    1.51 +    }
    1.52 +
    1.53 +out:
    1.54 +    T("(%s) -> %s", fpr, pEp_status_to_string(status));
    1.55 +    pgp_key_free (key);
    1.56 +    pgp_fingerprint_free (pgp_fpr);
    1.57 +    free (fpr);
    1.58 +    return status;
    1.59 +}
    1.60 +
    1.61 +// Returns the first key in iter that is already decrypted or can be
    1.62 +// decrypted using the stored passphrase.
    1.63 +//
    1.64 +// This function does not take ownership of iter (the caller must
    1.65 +// still free it).
    1.66 +//
    1.67 +// On success, it sets *decrypt_key to the decrypted key and returns
    1.68 +// PEP_STATUS_OK.  On failure, key is freed, *decrypted_key is set to
    1.69 +// NULL, and an error is returned.
    1.70 +static PEP_STATUS _pgp_get_decrypted_key_iter(PEP_SESSION session,
    1.71 +                                              pgp_cert_valid_key_iter_t iter,
    1.72 +                                              pgp_key_t* decrypted_key) {
    1.73 +
    1.74 +    PEP_STATUS status = PEP_STATUS_OK;
    1.75 +    pgp_error_t err = NULL;
    1.76 +
    1.77 +    if (!decrypted_key)
    1.78 +        ERROR_OUT (err, PEP_ILLEGAL_VALUE, "missing decrypt_key parameter");
    1.79 +    *decrypted_key = NULL;
    1.80      if (!iter)
    1.81 -        return PEP_UNKNOWN_ERROR; // ???
    1.82 -    
    1.83 -    if (!decrypted_key)
    1.84 -        return PEP_ILLEGAL_VALUE;
    1.85 -        
    1.86 -    PEP_STATUS status = PEP_STATUS_OK;
    1.87 -    
    1.88 -    pgp_error_t err = NULL;    
    1.89 +        ERROR_OUT (err, PEP_ILLEGAL_VALUE, "missing iter parameter");
    1.90 +
    1.91      bool bad_pass = false;
    1.92      bool missing_pass = false;
    1.93      pgp_key_t key = NULL;
    1.94 -    *decrypted_key = NULL;
    1.95 -
    1.96 -    pgp_valid_key_amalgamation_t ka = pgp_cert_valid_key_iter_next (iter, NULL, NULL);
    1.97 -
    1.98 +
    1.99 +    pgp_valid_key_amalgamation_t ka
   1.100 +        = pgp_cert_valid_key_iter_next (iter, NULL, NULL);
   1.101      // FIXME: better error!!!
   1.102      if (! ka)
   1.103 -        ERROR_OUT (err, PEP_UNKNOWN_ERROR,
   1.104 -                   "%s has no capable key", fpr);
   1.105 -
   1.106 -    // pgp_key_into_key_pair needs to own the key, but here we
   1.107 -    // only get a reference (which we still need to free).
   1.108 -    
   1.109 -    for ( ; ka ; (ka = pgp_cert_valid_key_iter_next(iter, NULL, NULL))) {                       
   1.110 -        // pgp_key_into_key_pair needs to own the key, but here we
   1.111 -        // only get a reference (which we still need to free).
   1.112 -        key = pgp_valid_key_amalgamation_key (ka);
   1.113 -
   1.114 -        if (pgp_key_has_unencrypted_secret(key)) 
   1.115 +        ERROR_OUT (err, PEP_UNKNOWN_ERROR, "no matching key");
   1.116 +
   1.117 +    for ( ; ka ; (ka = pgp_cert_valid_key_iter_next(iter, NULL, NULL))) {
   1.118 +        // _pgp_get_decrypted_key takes an owned key, but here we only
   1.119 +        // get a reference (which we still need to free).
   1.120 +        pgp_key_t keyref = pgp_valid_key_amalgamation_key (ka);
   1.121 +        key = pgp_key_clone (keyref);
   1.122 +        pgp_key_free (keyref);
   1.123 +
   1.124 +        pgp_valid_key_amalgamation_free (ka);
   1.125 +
   1.126 +        status = _pgp_get_decrypted_key(session, key, decrypted_key);
   1.127 +        if (status == PEP_STATUS_OK)
   1.128              break;
   1.129 -        else {
   1.130 -            const char* pass = session->curr_passphrase;
   1.131 -            if (pass && pass[0]) {
   1.132 -                pgp_key_t decrypted_key = NULL;
   1.133 -                decrypted_key = pgp_key_decrypt_secret(&err, pgp_key_clone(key), (uint8_t*)session->curr_passphrase,
   1.134 -                                                        strlen(session->curr_passphrase));                             
   1.135 -                pgp_key_free(key);
   1.136 -                key = NULL;
   1.137 -                
   1.138 -                if (!decrypted_key) {                               
   1.139 -                    bad_pass = true;
   1.140 -                    continue;
   1.141 -                }    
   1.142 -                else {
   1.143 -                    key = decrypted_key;
   1.144 -                    break;
   1.145 -                }
   1.146 -            }
   1.147 -            else {
   1.148 -                pgp_key_free(key);
   1.149 -                key = NULL;
   1.150 -                missing_pass = true;
   1.151 -                continue;
   1.152 -            }
   1.153 -        }
   1.154 +        else if (status == PEP_WRONG_PASSPHRASE)
   1.155 +            bad_pass = true;
   1.156 +        else if (status == PEP_PASSPHRASE_REQUIRED)
   1.157 +            missing_pass = true;
   1.158      }
   1.159 -    if (!key) {
   1.160 +
   1.161 +    if (!*decrypted_key) {
   1.162          if (bad_pass)
   1.163              ERROR_OUT(err, PEP_WRONG_PASSPHRASE, "pgp_key_decrypt_secret");
   1.164 -        else if (missing_pass)    
   1.165 +        else if (missing_pass)
   1.166              ERROR_OUT(err, PEP_PASSPHRASE_REQUIRED, "pgp_key_decrypt_secret");
   1.167 -        else        
   1.168 -            ERROR_OUT(err, PEP_UNKNOWN_ERROR, "pgp_valid_key_amalgamation_key");            
   1.169 -    }   
   1.170 -    
   1.171 +        else
   1.172 +            ERROR_OUT(err, PEP_UNKNOWN_ERROR, "pgp_valid_key_amalgamation_key");
   1.173 +    }
   1.174 +
   1.175  out:
   1.176 -    pgp_valid_key_amalgamation_free (ka);
   1.177 -    *decrypted_key = key;
   1.178 -
   1.179 -    T("(%s)-> %s", fpr, pEp_status_to_string(status));
   1.180 -    return status;                                                 
   1.181 +    T(" -> %s", pEp_status_to_string(status));
   1.182 +    return status;
   1.183  }
   1.184  
   1.185  PEP_STATUS pgp_init(PEP_SESSION session, bool in_first)
   1.186 @@ -1938,7 +1976,7 @@
   1.187      pgp_cert_valid_key_iter_for_signing (iter);
   1.188  
   1.189      pgp_key_t key = NULL;
   1.190 -    status = _pgp_get_decrypted_key(session, iter, &key);
   1.191 +    status = _pgp_get_decrypted_key_iter(session, iter, &key);
   1.192  
   1.193      if (!key || status != PEP_STATUS_OK) {
   1.194          ERROR_OUT (err, status,
   1.195 @@ -2139,7 +2177,7 @@
   1.196      ws = pgp_writer_stack_message(writer);
   1.197      ws = pgp_encryptor_new (&err, ws,
   1.198                              NULL, 0, recipients, recipient_count,
   1.199 -                            0, 0);
   1.200 +                            0);
   1.201      // pgp_encrypt_new consumes the recipients (but not the keys).
   1.202      // This seems to still happen even if it failed, so we need to be sure
   1.203      // not to try to free them if we bail.
   1.204 @@ -2157,16 +2195,15 @@
   1.205          pgp_cert_valid_key_iter_for_signing (iter);
   1.206  
   1.207          pgp_key_t key = NULL;
   1.208 -        status = _pgp_get_decrypted_key(session, iter, &key);
   1.209 +        status = _pgp_get_decrypted_key_iter(session, iter, &key);
   1.210  
   1.211          if (!key || status != PEP_STATUS_OK) {
   1.212              ERROR_OUT (err, status,
   1.213 -                       "%s has no signing capable key", fpr);
   1.214 +                       "no signing capable key");
   1.215          }               
   1.216                  
   1.217                      
   1.218 -        signing_keypair = pgp_key_into_key_pair (NULL, pgp_key_clone (key));
   1.219 -        pgp_key_free (key);
   1.220 +        signing_keypair = pgp_key_into_key_pair (NULL, key);
   1.221          if (! signing_keypair)
   1.222              ERROR_OUT (err, PEP_UNKNOWN_ERROR, "Creating a keypair");
   1.223  
   1.224 @@ -2555,7 +2592,7 @@
   1.225          if (cert) {
   1.226              T("Merging packet: %s", pgp_packet_debug(packet));
   1.227  
   1.228 -            cert = pgp_cert_merge_packets (&err, cert, &packet, 1);
   1.229 +            cert = pgp_cert_insert_packets (&err, cert, &packet, 1);
   1.230              if (! cert)
   1.231                  ERROR_OUT(err, PEP_UNKNOWN_ERROR, "Merging signature");
   1.232  
   1.233 @@ -3034,9 +3071,12 @@
   1.234      pgp_error_t err = NULL;
   1.235      pgp_cert_t cert = NULL;
   1.236      pgp_cert_valid_key_iter_t iter = NULL;
   1.237 -    pgp_valid_key_amalgamation_t primary = NULL;
   1.238 +    pgp_key_t key = NULL;
   1.239      pgp_key_pair_t keypair = NULL;
   1.240      pgp_signer_t signer = NULL;
   1.241 +    pgp_key_t subkey = NULL;
   1.242 +    pgp_key_pair_t subkey_keypair = NULL;
   1.243 +    pgp_signer_t subkey_signer = NULL;
   1.244      time_t t = timegm((timestamp *) ts); // timestamp because of Windows
   1.245      pgp_cert_valid_key_iter_t key_iter = NULL;
   1.246      pgp_valid_key_amalgamation_t ka = NULL;
   1.247 @@ -3059,37 +3099,75 @@
   1.248      pgp_cert_valid_key_iter_for_certification (iter);
   1.249      pgp_cert_valid_key_iter_revoked(iter, false);
   1.250  
   1.251 -    pgp_key_t key = NULL;
   1.252 -    status = _pgp_get_decrypted_key(session, iter, &key);
   1.253 -
   1.254 +    status = _pgp_get_decrypted_key_iter(session, iter, &key);
   1.255      if (!key || status != PEP_STATUS_OK) {
   1.256          ERROR_OUT (err, status,
   1.257 -                   "%s has no signing capable key", fpr);
   1.258 -    }               
   1.259 -
   1.260 -    // pgp_key_into_key_pair needs to own the key, but here we
   1.261 -    // only get a reference (which we still need to free).
   1.262 -    keypair = pgp_key_into_key_pair (NULL, pgp_key_clone (key));
   1.263 -    pgp_key_free (key);
   1.264 +                   "%s: decrypting primary key's secret key", fpr);
   1.265 +    }
   1.266 +
   1.267 +    // pgp_key_into_key_pair takes ownership of key.
   1.268 +    keypair = pgp_key_into_key_pair (&err, key);
   1.269 +    key = NULL;
   1.270      if (! keypair)
   1.271          ERROR_OUT (err, PEP_UNKNOWN_ERROR, "Creating a keypair");
   1.272  
   1.273 +    // signer references keypair.
   1.274      signer = pgp_key_pair_as_signer (keypair);
   1.275      if (! signer)
   1.276          ERROR_OUT (err, PEP_UNKNOWN_ERROR, "Creating a signer");
   1.277  
   1.278 +
   1.279      // Set the expiration for all non-revoked keys.
   1.280      key_iter = pgp_cert_valid_key_iter(cert, session->policy, 0);
   1.281      pgp_cert_valid_key_iter_revoked(key_iter, false);
   1.282  
   1.283 +    // The first key is guaranteed to be the primary key.
   1.284 +    bool is_primary = true;
   1.285      while ((ka = pgp_cert_valid_key_iter_next(key_iter, NULL, NULL))) {
   1.286          pgp_status_t sq_status;
   1.287 -        pgp_error_t err;
   1.288          pgp_signature_t *sigs = NULL;
   1.289          size_t sig_count = 0;
   1.290  
   1.291 +        // Arrange for a backsig, if needed.
   1.292 +        if (! is_primary
   1.293 +            && (pgp_valid_key_amalgamation_for_certification(ka)
   1.294 +                || pgp_valid_key_amalgamation_for_signing(ka)
   1.295 +                || pgp_valid_key_amalgamation_for_authentication(ka))) {
   1.296 +            // _pgp_get_decrypted_key takes an owned key, but here we only
   1.297 +            // get a reference (which we still need to free).
   1.298 +            pgp_key_t subkeyref = pgp_valid_key_amalgamation_key (ka);
   1.299 +            subkey = pgp_key_clone (subkeyref);
   1.300 +            pgp_key_free (subkeyref);
   1.301 +
   1.302 +            status = _pgp_get_decrypted_key(session, subkey, &subkey);
   1.303 +            if (!subkey || status != PEP_STATUS_OK) {
   1.304 +                ERROR_OUT (err, status,
   1.305 +                           "%s: failed to get secret key material", fpr);
   1.306 +            }
   1.307 +
   1.308 +            // pgp_key_into_key_pair takes ownership of subkey.
   1.309 +            subkey_keypair = pgp_key_into_key_pair (&err, subkey);
   1.310 +            subkey = NULL;
   1.311 +            if (! subkey_keypair)
   1.312 +                ERROR_OUT (err, PEP_UNKNOWN_ERROR, "Creating a keypair");
   1.313 +
   1.314 +            // subkey_signer references subkey_keypair.
   1.315 +            subkey_signer = pgp_key_pair_as_signer (subkey_keypair);
   1.316 +            if (! signer)
   1.317 +                ERROR_OUT (err, PEP_UNKNOWN_ERROR, "Creating a signer");
   1.318 +        }
   1.319 +        is_primary = false;
   1.320 +
   1.321          sq_status = pgp_valid_key_amalgamation_set_expiration_time
   1.322 -            (&err, ka, signer, t, &sigs, &sig_count);
   1.323 +            (&err, ka, signer, subkey_signer, t, &sigs, &sig_count);
   1.324 +        pgp_signer_free (subkey_signer);
   1.325 +        subkey_signer = NULL;
   1.326 +        // XXX: pgp_key_pair_as_signer is only supposed to reference
   1.327 +        // signing_keypair, but it consumes it.  If this is fixed,
   1.328 +        // this will become a leak.
   1.329 +        //
   1.330 +        //pgp_key_pair_free (subkey_keypair);
   1.331 +        subkey_keypair = NULL;
   1.332          if (sq_status)
   1.333              ERROR_OUT(err, PEP_UNKNOWN_ERROR,
   1.334                        "setting expiration (generating self signatures)");
   1.335 @@ -3128,7 +3206,7 @@
   1.336      pgp_cert_valid_key_iter_free (key_iter);
   1.337      key_iter = NULL;
   1.338  
   1.339 -    cert = pgp_cert_merge_packets (&err, cert, packets, packet_count);
   1.340 +    cert = pgp_cert_insert_packets (&err, cert, packets, packet_count);
   1.341      // The packets (but not the array) are now owned by cert.
   1.342      packet_count = 0;
   1.343      if (! cert)
   1.344 @@ -3148,13 +3226,16 @@
   1.345  
   1.346      pgp_valid_key_amalgamation_free (ka);
   1.347      pgp_cert_valid_key_iter_free (key_iter);
   1.348 -    pgp_signer_free (signer);
   1.349 +    pgp_signer_free (subkey_signer);
   1.350      // XXX: pgp_key_pair_as_signer is only supposed to reference
   1.351      // signing_keypair, but it consumes it.  If this is fixed, this
   1.352      // will become a leak.
   1.353      //
   1.354 -    pgp_key_pair_free (keypair);
   1.355 -    pgp_valid_key_amalgamation_free (primary);
   1.356 +    //pgp_key_pair_free (subkey_keypair);
   1.357 +    pgp_key_free (subkey);
   1.358 +    pgp_signer_free (signer);
   1.359 +    //pgp_key_pair_free (keypair);
   1.360 +    pgp_key_free (key);
   1.361      pgp_cert_valid_key_iter_free (iter);
   1.362      pgp_cert_free(cert);
   1.363  
   1.364 @@ -3186,7 +3267,7 @@
   1.365      // pgp_key_into_key_pair needs to own the key, but here we
   1.366      // only get a reference (which we still need to free).    
   1.367      pgp_key_t key = NULL;
   1.368 -    status = _pgp_get_decrypted_key(session, iter, &key);
   1.369 +    status = _pgp_get_decrypted_key_iter(session, iter, &key);
   1.370  
   1.371      if (!key || status != PEP_STATUS_OK) {
   1.372          ERROR_OUT (err, (status != PEP_STATUS_OK ? status : PEP_UNKNOWN_ERROR),