mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-21 10:09:57 +01:00
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
This commit is contained in:
parent
61717fb0a7
commit
813f8d1b8e
@ -982,6 +982,11 @@ do_pubkey_enc( IOBUF out, int ctb, PKT_pubkey_enc *enc )
|
||||
|
||||
for (i=0; i < n && !rc ; i++ )
|
||||
{
|
||||
/* For Kyber we need to insert the algo before the final data
|
||||
* element because it is not stored in the data array. */
|
||||
if (enc->pubkey_algo == PUBKEY_ALGO_KYBER && i == 2)
|
||||
iobuf_put (a, enc->seskey_algo);
|
||||
|
||||
if (enc->pubkey_algo == PUBKEY_ALGO_ECDH && i == 1)
|
||||
rc = gpg_mpi_write_opaque_nohdr (a, enc->data[i]);
|
||||
else if (enc->pubkey_algo == PUBKEY_ALGO_ECDH)
|
||||
|
@ -1122,6 +1122,7 @@ write_pubkey_enc (ctrl_t ctrl,
|
||||
enc->pubkey_algo = pk->pubkey_algo;
|
||||
keyid_from_pk( pk, enc->keyid );
|
||||
enc->throw_keyid = throw_keyid;
|
||||
enc->seskey_algo = dek->algo; /* (Used only by PUBKEY_ALGO_KYBER.) */
|
||||
|
||||
/* Okay, what's going on: We have the session key somewhere in
|
||||
* the structure DEK and want to encode this session key in an
|
||||
|
@ -529,6 +529,7 @@ proc_pubkey_enc (CTX c, PACKET *pkt)
|
||||
x->keyid[1] = enc->keyid[1];
|
||||
x->pubkey_algo = enc->pubkey_algo;
|
||||
x->result = -1;
|
||||
x->seskey_algo = enc->seskey_algo;
|
||||
x->data[0] = x->data[1] = x->data[2] = x->data[3] = NULL;
|
||||
if (enc->data[0])
|
||||
{
|
||||
|
@ -1786,7 +1786,7 @@ pubkey_get_nenc (pubkey_algo_t algo)
|
||||
case PUBKEY_ALGO_ECDSA: return 0;
|
||||
case PUBKEY_ALGO_ELGAMAL: return 2;
|
||||
case PUBKEY_ALGO_EDDSA: return 0;
|
||||
case PUBKEY_ALGO_KYBER: return 4;
|
||||
case PUBKEY_ALGO_KYBER: return 3;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
@ -137,6 +137,8 @@ typedef struct {
|
||||
byte version;
|
||||
/* The algorithm used for the public key encryption scheme. */
|
||||
byte pubkey_algo;
|
||||
/* The session key algorithm used by some pubkey algos. */
|
||||
byte seskey_algo;
|
||||
/* Whether to hide the key id. This value is not directly
|
||||
serialized. */
|
||||
byte throw_keyid;
|
||||
@ -151,6 +153,7 @@ struct pubkey_enc_list
|
||||
struct pubkey_enc_list *next;
|
||||
u32 keyid[2];
|
||||
int pubkey_algo;
|
||||
int seskey_algo;
|
||||
int result;
|
||||
gcry_mpi_t data[PUBKEY_MAX_NENC];
|
||||
};
|
||||
|
@ -1513,7 +1513,7 @@ parse_pubkeyenc (IOBUF inp, int pkttype, unsigned long pktlen,
|
||||
}
|
||||
else if (k->pubkey_algo == PUBKEY_ALGO_KYBER)
|
||||
{
|
||||
log_assert (ndata == 4);
|
||||
log_assert (ndata == 3);
|
||||
/* Get the ephemeral public key. */
|
||||
n = pktlen;
|
||||
k->data[0] = sos_read (inp, &n, 0);
|
||||
@ -1527,12 +1527,16 @@ parse_pubkeyenc (IOBUF inp, int pkttype, unsigned long pktlen,
|
||||
rc = read_octet_string (inp, &pktlen, 4, 0, 0, k->data + 1);
|
||||
if (rc)
|
||||
goto leave;
|
||||
/* Get the algorithm id. */
|
||||
rc = read_octet_string (inp, &pktlen, 0, 1, 0, k->data + 2);
|
||||
if (rc)
|
||||
goto leave;
|
||||
/* Get the wrapped symmetric key. */
|
||||
rc = read_sized_octet_string (inp, &pktlen, k->data + 3);
|
||||
/* Get the algorithm id for the session key. */
|
||||
if (!pktlen)
|
||||
{
|
||||
rc = gpg_error (GPG_ERR_INV_PACKET);
|
||||
goto leave;
|
||||
}
|
||||
k->seskey_algo = iobuf_get_noeof (inp);
|
||||
pktlen--;
|
||||
/* Get the encrypted symmetric key. */
|
||||
rc = read_octet_string (inp, &pktlen, 1, 0, 0, k->data + 2);
|
||||
if (rc)
|
||||
goto leave;
|
||||
}
|
||||
@ -1551,6 +1555,8 @@ parse_pubkeyenc (IOBUF inp, int pkttype, unsigned long pktlen,
|
||||
}
|
||||
if (list_mode)
|
||||
{
|
||||
if (k->seskey_algo)
|
||||
es_fprintf (listfp, "\tsession key algo: %d\n", k->seskey_algo);
|
||||
for (i = 0; i < ndata; i++)
|
||||
{
|
||||
es_fprintf (listfp, "\tdata: ");
|
||||
|
@ -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 (frameidx + 4 > nframe)
|
||||
{
|
||||
err = gpg_error (GPG_ERR_WRONG_SECKEY);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
dek->keylen = nframe - (frameidx + 1) - 2;
|
||||
dek->algo = frame[frameidx++];
|
||||
}
|
||||
|
||||
if (n + 4 > nframe)
|
||||
{
|
||||
err = gpg_error (GPG_ERR_WRONG_SECKEY);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
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)
|
||||
|
20
g10/seskey.c
20
g10/seskey.c
@ -86,15 +86,29 @@ encode_session_key (int openpgp_pk_algo, DEK *dek, unsigned int nbits)
|
||||
if (DBG_CRYPTO)
|
||||
log_debug ("encode_session_key: encoding %d byte DEK", dek->keylen);
|
||||
|
||||
if (openpgp_pk_algo == PUBKEY_ALGO_KYBER)
|
||||
{
|
||||
/* Straightforward encoding w/o extra checksum as used by ECDH. */
|
||||
nframe = dek->keylen;
|
||||
log_assert (nframe > 4); /*(for the log_debug)*/
|
||||
frame = xmalloc_secure (nframe);
|
||||
memcpy (frame, dek->key, nframe);
|
||||
if (DBG_CRYPTO)
|
||||
log_debug ("encode_session_key: "
|
||||
"[%d] %02x %02x %02x ... %02x %02x %02x\n",
|
||||
(int) dek->keylen, frame[0], frame[1], frame[2],
|
||||
frame[nframe-3], frame[nframe-2], frame[nframe-1]);
|
||||
|
||||
return gcry_mpi_set_opaque (NULL, frame, 8*nframe);
|
||||
}
|
||||
|
||||
csum = 0;
|
||||
for (p = dek->key, i=0; i < dek->keylen; i++)
|
||||
csum += *p++;
|
||||
|
||||
/* Shortcut for ECDH. It's padding is minimal to simply make the
|
||||
output be a multiple of 8 bytes. */
|
||||
/* FIXME: We use the ECDH also for Kyber for now. */
|
||||
if (openpgp_pk_algo == PUBKEY_ALGO_ECDH
|
||||
|| openpgp_pk_algo == PUBKEY_ALGO_KYBER)
|
||||
if (openpgp_pk_algo == PUBKEY_ALGO_ECDH)
|
||||
{
|
||||
/* Pad to 8 byte granularity; the padding byte is the number of
|
||||
* padded bytes.
|
||||
|
Loading…
x
Reference in New Issue
Block a user