aboutsummaryrefslogtreecommitdiffstats
path: root/g10/pubkey-enc.c
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2024-04-11 13:56:21 +0000
committerWerner Koch <[email protected]>2024-04-11 13:56:21 +0000
commit813f8d1b8e4b6c4365f0bd2a5305bdbe1e049d05 (patch)
treee8c88bf44d695c7d1e3d8186e52324f9b12c9aaf /g10/pubkey-enc.c
parentagent: Add more diagnostics to PQC decryption. (diff)
downloadgnupg-813f8d1b8e4b6c4365f0bd2a5305bdbe1e049d05.tar.gz
gnupg-813f8d1b8e4b6c4365f0bd2a5305bdbe1e049d05.zip
gpg: Changed internal data format for Kyber.
* g10/packet.h (PKT_pubkey_enc): Add field seskey_algo. (struct pubkey_enc_list): Ditto. * g10/misc.c (pubkey_get_nenc): Change value for Kyber from 4 to 3. * g10/parse-packet.c (parse_pubkeyenc): Store the Kyber algo in the new field and adjust data. Do not store the length byte in data[2]. * g10/build-packet.c (do_pubkey_enc): Take the session algo for Kyber from the new field. * g10/encrypt.c (write_pubkey_enc): Ses the seskey_algo. * g10/mainproc.c (proc_pubkey_enc): Copy it. * g10/pubkey-enc.c (get_it): Support Kyber decryption. * g10/seskey.c (encode_session_key): Handle Kyber different from ECDH. -- Having always the single byte in the packet data than to store and retrieve it from an MPI is much easier. Thus this patch changes the original internal format. With this chnages decryption of the slighly modified test data works now. See the bug tracker for test data. GnuPG-bug-id: 6815
Diffstat (limited to 'g10/pubkey-enc.c')
-rw-r--r--g10/pubkey-enc.c92
1 files changed, 62 insertions, 30 deletions
diff --git a/g10/pubkey-enc.c b/g10/pubkey-enc.c
index 873b864b5..da32ebc7b 100644
--- a/g10/pubkey-enc.c
+++ b/g10/pubkey-enc.c
@@ -194,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;
@@ -240,13 +240,15 @@ get_it (ctrl_t ctrl,
}
else if (sk->pubkey_algo == PUBKEY_ALGO_KYBER)
{
- if (!enc->data[0] || !enc->data[1] || !enc->data[2] || !enc->data[3])
+ log_debug ("seskey_algo: %d\n", enc->seskey_algo);
+ 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)(fixed-info%s)))",
- enc->data[0], enc->data[1], enc->data[3],
- "\x1d" /*PUBKEY_ALGO_KYBER*/);
+ "(enc-val(pqc(e%m)(k%m)(s%m)(c%d)(fixed-info%s)))",
+ enc->data[0], enc->data[1], enc->data[2],
+ enc->seskey_algo,
+ "\x69");
}
else
err = gpg_error (GPG_ERR_BUG);
@@ -287,9 +289,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;
@@ -313,13 +328,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;
@@ -331,34 +354,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)
{
@@ -377,16 +404,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)