diff options
Diffstat (limited to 'g10/pubkey-enc.c')
-rw-r--r-- | g10/pubkey-enc.c | 113 |
1 files changed, 87 insertions, 26 deletions
diff --git a/g10/pubkey-enc.c b/g10/pubkey-enc.c index 6e1b0898e..563077803 100644 --- a/g10/pubkey-enc.c +++ b/g10/pubkey-enc.c @@ -117,6 +117,7 @@ get_session_key (ctrl_t ctrl, struct pubkey_enc_list *list, DEK *dek) { if (!(k->pubkey_algo == PUBKEY_ALGO_ELGAMAL_E || k->pubkey_algo == PUBKEY_ALGO_ECDH + || k->pubkey_algo == PUBKEY_ALGO_KYBER || k->pubkey_algo == PUBKEY_ALGO_RSA || k->pubkey_algo == PUBKEY_ALGO_RSA_E || k->pubkey_algo == PUBKEY_ALGO_ELGAMAL)) @@ -193,7 +194,7 @@ get_it (ctrl_t ctrl, { gpg_error_t err; byte *frame = NULL; - unsigned int n; + unsigned int frameidx; size_t nframe; u16 csum, csum2; int padding; @@ -237,6 +238,32 @@ get_it (ctrl_t ctrl, err = gcry_sexp_build (&s_data, NULL, "(enc-val(ecdh(s%m)(e%m)))", enc->data[1], enc->data[0]); } + else if (sk->pubkey_algo == PUBKEY_ALGO_KYBER) + { + char fixedinfo[1+MAX_FINGERPRINT_LEN]; + int fixedlen; + + if ((opt.compat_flags & COMPAT_T7014_OLD)) + { + /* Temporary use for tests with original test vectors. */ + fixedinfo[0] = 0x69; + fixedlen = 1; + } + else + { + fixedinfo[0] = enc->seskey_algo; + v5_fingerprint_from_pk (sk, fixedinfo+1, NULL); + fixedlen = 33; + } + + if (!enc->data[0] || !enc->data[1] || !enc->data[2]) + err = gpg_error (GPG_ERR_BAD_MPI); + else + err = gcry_sexp_build (&s_data, NULL, + "(enc-val(pqc(e%m)(k%m)(s%m)(c%d)(fixed-info%b)))", + enc->data[0], enc->data[1], enc->data[2], + enc->seskey_algo, fixedlen, fixedinfo); + } else err = gpg_error (GPG_ERR_BUG); @@ -248,6 +275,7 @@ get_it (ctrl_t ctrl, /* Decrypt. */ desc = gpg_format_keydesc (ctrl, sk, FORMAT_KEYDESC_NORMAL, 1); + err = agent_pkdecrypt (NULL, keygrip, desc, sk->keyid, sk->main_keyid, sk->pubkey_algo, s_data, &frame, &nframe, &padding); @@ -275,9 +303,22 @@ get_it (ctrl_t ctrl, */ if (DBG_CRYPTO) log_printhex (frame, nframe, "DEK frame:"); - n = 0; + frameidx = 0; - if (sk->pubkey_algo == PUBKEY_ALGO_ECDH) + if (sk->pubkey_algo == PUBKEY_ALGO_KYBER) + { + /* We expect a 32 byte session key. We should not see this + * error here because due to the KEM mode the agent_pkdecrypt + * should have already failed. */ + if (nframe != 32) + { + err = gpg_error (GPG_ERR_WRONG_SECKEY); + goto leave; + } + dek->keylen = nframe; + dek->algo = enc->seskey_algo; + } + else if (sk->pubkey_algo == PUBKEY_ALGO_ECDH) { gcry_mpi_t decoded; @@ -301,13 +342,21 @@ get_it (ctrl_t ctrl, goto leave; } nframe -= frame[nframe-1]; /* Remove padding. */ - log_assert (!n); /* (used just below) */ + if (4 > nframe) + { + err = gpg_error (GPG_ERR_WRONG_SECKEY); + goto leave; + } + + dek->keylen = nframe - 3; + dek->algo = frame[0]; + frameidx = 1; } else { if (padding) { - if (n + 7 > nframe) + if (7 > nframe) { err = gpg_error (GPG_ERR_WRONG_SECKEY); goto leave; @@ -319,34 +368,38 @@ get_it (ctrl_t ctrl, * using a Smartcard we are doing it the right way and * therefore we have to skip the zero. This should be fixed * in gpg-agent of course. */ - if (!frame[n]) - n++; + frameidx = 0; + if (!frame[frameidx]) + frameidx++; - if (frame[n] == 1 && frame[nframe - 1] == 2) + if (frame[frameidx] == 1 && frame[nframe - 1] == 2) { log_info (_("old encoding of the DEK is not supported\n")); err = gpg_error (GPG_ERR_CIPHER_ALGO); goto leave; } - if (frame[n] != 2) /* Something went wrong. */ + if (frame[frameidx] != 2) /* Something went wrong. */ { err = gpg_error (GPG_ERR_WRONG_SECKEY); goto leave; } - for (n++; n < nframe && frame[n]; n++) /* Skip the random bytes. */ + /* Skip the random bytes. */ + for (frameidx++; frameidx < nframe && frame[frameidx]; frameidx++) ; - n++; /* Skip the zero byte. */ + frameidx++; /* Skip the zero byte. */ } - } - if (n + 4 > nframe) - { - err = gpg_error (GPG_ERR_WRONG_SECKEY); - goto leave; + if (frameidx + 4 > nframe) + { + err = gpg_error (GPG_ERR_WRONG_SECKEY); + goto leave; + } + + dek->keylen = nframe - (frameidx + 1) - 2; + dek->algo = frame[frameidx++]; } - dek->keylen = nframe - (n + 1) - 2; - dek->algo = frame[n++]; + /* Check whether we support the ago. */ err = openpgp_cipher_test_algo (dek->algo); if (err) { @@ -365,16 +418,21 @@ get_it (ctrl_t ctrl, goto leave; } - /* Copy the key to DEK and compare the checksum. */ - csum = buf16_to_u16 (frame+nframe-2); - memcpy (dek->key, frame + n, dek->keylen); - for (csum2 = 0, n = 0; n < dek->keylen; n++) - csum2 += dek->key[n]; - if (csum != csum2) + /* Copy the key to DEK and compare the checksum if needed. */ + /* We use the frameidx as flag for the need of a checksum. */ + memcpy (dek->key, frame + frameidx, dek->keylen); + if (frameidx) { - err = gpg_error (GPG_ERR_WRONG_SECKEY); - goto leave; + csum = buf16_to_u16 (frame+nframe-2); + for (csum2 = 0, frameidx = 0; frameidx < dek->keylen; frameidx++) + csum2 += dek->key[frameidx]; + if (csum != csum2) + { + err = gpg_error (GPG_ERR_WRONG_SECKEY); + goto leave; + } } + if (DBG_CLOCK) log_clock ("decryption ready"); if (DBG_CRYPTO) @@ -399,6 +457,9 @@ get_it (ctrl_t ctrl, log_info (_("WARNING: cipher algorithm %s not found in recipient" " preferences\n"), openpgp_cipher_algo_name (dek->algo)); + /* if (!err && 25519 && openpgp_oidbuf_is_ed25519 (curve, len)) */ + /* log_info ("Note: legacy OID was used for cv25519\n"); */ + if (!err) { kbnode_t k; |