mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
common,agent: Factor out KEM functions into common/kem.c.
* common/util.h (compute_kmac256): Remove. (gnupg_ecc_kem_kdf, gnupg_kem_combiner): New. * common/kmac.c (compute_kmac256): Don't expose. (gnupg_ecc_kem_kdf, gnupg_kem_combiner): New. * agent/pkdecrypt.c (agent_hybrid_pgp_kem_decrypt): Use gnupg_ecc_kem_kdf and gnupg_kem_combiner. -- Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
This commit is contained in:
parent
52c4b09080
commit
04b81ec236
@ -198,30 +198,28 @@ agent_hybrid_pgp_kem_decrypt (ctrl_t ctrl, const char *desc_text,
|
|||||||
const unsigned char *p;
|
const unsigned char *p;
|
||||||
size_t len;
|
size_t len;
|
||||||
|
|
||||||
gcry_mpi_t encrypted_sessionkey_mpi;
|
gcry_mpi_t encrypted_sessionkey_mpi = NULL;
|
||||||
const unsigned char *encrypted_sessionkey;
|
const unsigned char *encrypted_sessionkey;
|
||||||
size_t encrypted_sessionkey_len;
|
size_t encrypted_sessionkey_len;
|
||||||
|
|
||||||
gcry_mpi_t ecc_sk_mpi;
|
gcry_mpi_t ecc_sk_mpi = NULL;
|
||||||
unsigned char ecc_sk[32];
|
unsigned char ecc_sk[32];
|
||||||
gcry_mpi_t ecc_pk_mpi;
|
gcry_mpi_t ecc_pk_mpi = NULL;
|
||||||
unsigned char ecc_pk[32];
|
unsigned char ecc_pk[32];
|
||||||
gcry_mpi_t ecc_ct_mpi;
|
gcry_mpi_t ecc_ct_mpi = NULL;
|
||||||
const unsigned char *ecc_ct;
|
const unsigned char *ecc_ct;
|
||||||
size_t ecc_ct_len;
|
size_t ecc_ct_len;
|
||||||
unsigned char ecc_ecdh[32];
|
unsigned char ecc_ecdh[32];
|
||||||
unsigned char ecc_ss[32];
|
unsigned char ecc_ss[32];
|
||||||
|
|
||||||
gcry_mpi_t mlkem_sk_mpi;
|
gcry_mpi_t mlkem_sk_mpi = NULL;
|
||||||
gcry_mpi_t mlkem_ct_mpi;
|
gcry_mpi_t mlkem_ct_mpi = NULL;
|
||||||
const unsigned char *mlkem_sk;
|
const unsigned char *mlkem_sk;
|
||||||
const unsigned char *mlkem_ct;
|
const unsigned char *mlkem_ct;
|
||||||
unsigned char mlkem_ss[GCRY_KEM_MLKEM768_SHARED_LEN];
|
unsigned char mlkem_ss[GCRY_KEM_MLKEM768_SHARED_LEN];
|
||||||
|
|
||||||
gcry_buffer_t iov[6];
|
unsigned char kek[32];
|
||||||
|
size_t kek_len = 32; /* AES-256 is mandatory */
|
||||||
unsigned char kekkey[32];
|
|
||||||
size_t kekkeylen = 32; /* AES-256 is mandatory */
|
|
||||||
|
|
||||||
gcry_cipher_hd_t hd;
|
gcry_cipher_hd_t hd;
|
||||||
unsigned char sessionkey[256];
|
unsigned char sessionkey[256];
|
||||||
@ -290,6 +288,8 @@ agent_hybrid_pgp_kem_decrypt (ctrl_t ctrl, const char *desc_text,
|
|||||||
reverse_buffer (ecc_sk, 32);
|
reverse_buffer (ecc_sk, 32);
|
||||||
mpi_release (ecc_pk_mpi);
|
mpi_release (ecc_pk_mpi);
|
||||||
mpi_release (ecc_sk_mpi);
|
mpi_release (ecc_sk_mpi);
|
||||||
|
ecc_pk_mpi = NULL;
|
||||||
|
ecc_sk_mpi = NULL;
|
||||||
|
|
||||||
ecc_ct = gcry_mpi_get_opaque (ecc_ct_mpi, &nbits);
|
ecc_ct = gcry_mpi_get_opaque (ecc_ct_mpi, &nbits);
|
||||||
ecc_ct_len = (nbits+7)/8;
|
ecc_ct_len = (nbits+7)/8;
|
||||||
@ -302,16 +302,14 @@ agent_hybrid_pgp_kem_decrypt (ctrl_t ctrl, const char *desc_text,
|
|||||||
err = gcry_kem_decap (GCRY_KEM_RAW_X25519, ecc_sk, 32, ecc_ct, ecc_ct_len,
|
err = gcry_kem_decap (GCRY_KEM_RAW_X25519, ecc_sk, 32, ecc_ct, ecc_ct_len,
|
||||||
ecc_ecdh, 32, NULL, 0);
|
ecc_ecdh, 32, NULL, 0);
|
||||||
|
|
||||||
iov[0].data = ecc_ecdh;
|
if (err)
|
||||||
iov[0].off = 0;
|
goto leave;
|
||||||
iov[0].len = 32;
|
|
||||||
iov[1].data = (unsigned char *)ecc_ct;
|
err = gnupg_ecc_kem_kdf (ecc_ss, 32, GCRY_MD_SHA3_256,
|
||||||
iov[1].off = 0;
|
ecc_ecdh, 32, ecc_ct, 32, ecc_pk, 32);
|
||||||
iov[1].len = 32;
|
|
||||||
iov[2].data = ecc_pk;
|
if (err)
|
||||||
iov[2].off = 0;
|
goto leave;
|
||||||
iov[2].len = 32;
|
|
||||||
gcry_md_hash_buffers (GCRY_MD_SHA3_256, 0, ecc_ss, iov, 3);
|
|
||||||
|
|
||||||
/* Secondly, PQC part. For now, we assume ML-KEM. */
|
/* Secondly, PQC part. For now, we assume ML-KEM. */
|
||||||
gcry_sexp_extract_param (s_skey1, NULL, "/s", &mlkem_sk_mpi, NULL);
|
gcry_sexp_extract_param (s_skey1, NULL, "/s", &mlkem_sk_mpi, NULL);
|
||||||
@ -334,45 +332,32 @@ agent_hybrid_pgp_kem_decrypt (ctrl_t ctrl, const char *desc_text,
|
|||||||
mlkem_ct, GCRY_KEM_MLKEM768_CIPHER_LEN,
|
mlkem_ct, GCRY_KEM_MLKEM768_CIPHER_LEN,
|
||||||
mlkem_ss, GCRY_KEM_MLKEM768_SHARED_LEN,
|
mlkem_ss, GCRY_KEM_MLKEM768_SHARED_LEN,
|
||||||
NULL, 0);
|
NULL, 0);
|
||||||
|
if (err)
|
||||||
|
goto leave;
|
||||||
|
|
||||||
mpi_release (mlkem_sk_mpi);
|
mpi_release (mlkem_sk_mpi);
|
||||||
|
mlkem_sk_mpi = NULL;
|
||||||
|
|
||||||
/* Then, combine two shared secrets into one */
|
/* Then, combine two shared secrets and ciphertexts into one KEK */
|
||||||
|
err = gnupg_kem_combiner (kek, kek_len,
|
||||||
iov[0].data = "\x00\x00\x00\x01"; /* Counter */
|
ecc_ss, 32, ecc_ct, 32,
|
||||||
iov[0].off = 0;
|
mlkem_ss, GCRY_KEM_MLKEM768_SHARED_LEN,
|
||||||
iov[0].len = 4;
|
mlkem_ct, GCRY_KEM_MLKEM768_CIPHER_LEN,
|
||||||
|
fixedinfo, 1);
|
||||||
iov[1].data = ecc_ss;
|
if (err)
|
||||||
iov[1].off = 0;
|
{
|
||||||
iov[1].len = 32;
|
log_error ("KEM combiner failed: %s\n", gpg_strerror (err));
|
||||||
|
goto leave;
|
||||||
iov[2].data = (unsigned char *)ecc_ct;
|
}
|
||||||
iov[2].off = 0;
|
|
||||||
iov[2].len = 32;
|
|
||||||
|
|
||||||
iov[3].data = mlkem_ss;
|
|
||||||
iov[3].off = 0;
|
|
||||||
iov[3].len = GCRY_KEM_MLKEM768_SHARED_LEN;
|
|
||||||
|
|
||||||
iov[4].data = (unsigned char *)mlkem_ct;
|
|
||||||
iov[4].off = 0;
|
|
||||||
iov[4].len = GCRY_KEM_MLKEM768_ENCAPS_LEN;
|
|
||||||
|
|
||||||
iov[5].data = (unsigned char *)fixedinfo;
|
|
||||||
iov[5].off = 0;
|
|
||||||
iov[5].len = 1;
|
|
||||||
|
|
||||||
err = compute_kmac256 (kekkey, kekkeylen,
|
|
||||||
"OpenPGPCompositeKeyDerivationFunction", 37,
|
|
||||||
"KDF", 3, iov, 6);
|
|
||||||
|
|
||||||
mpi_release (ecc_ct_mpi);
|
mpi_release (ecc_ct_mpi);
|
||||||
mpi_release (mlkem_ct_mpi);
|
mpi_release (mlkem_ct_mpi);
|
||||||
|
ecc_ct_mpi = NULL;
|
||||||
|
mlkem_ct_mpi = NULL;
|
||||||
|
|
||||||
if (DBG_CRYPTO)
|
if (DBG_CRYPTO)
|
||||||
{
|
{
|
||||||
log_printhex (kekkey, kekkeylen, "KEK key: ");
|
log_printhex (kek, kek_len, "KEK key: ");
|
||||||
}
|
}
|
||||||
|
|
||||||
err = gcry_cipher_open (&hd, GCRY_CIPHER_AES256,
|
err = gcry_cipher_open (&hd, GCRY_CIPHER_AES256,
|
||||||
@ -381,11 +366,10 @@ agent_hybrid_pgp_kem_decrypt (ctrl_t ctrl, const char *desc_text,
|
|||||||
{
|
{
|
||||||
log_error ("ecdh failed to initialize AESWRAP: %s\n",
|
log_error ("ecdh failed to initialize AESWRAP: %s\n",
|
||||||
gpg_strerror (err));
|
gpg_strerror (err));
|
||||||
mpi_release (encrypted_sessionkey_mpi);
|
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = gcry_cipher_setkey (hd, kekkey, kekkeylen);
|
err = gcry_cipher_setkey (hd, kek, kek_len);
|
||||||
|
|
||||||
sessionkey_len = encrypted_sessionkey_len - 8;
|
sessionkey_len = encrypted_sessionkey_len - 8;
|
||||||
err = gcry_cipher_decrypt (hd, sessionkey, sessionkey_len,
|
err = gcry_cipher_decrypt (hd, sessionkey, sessionkey_len,
|
||||||
@ -393,6 +377,7 @@ agent_hybrid_pgp_kem_decrypt (ctrl_t ctrl, const char *desc_text,
|
|||||||
gcry_cipher_close (hd);
|
gcry_cipher_close (hd);
|
||||||
|
|
||||||
mpi_release (encrypted_sessionkey_mpi);
|
mpi_release (encrypted_sessionkey_mpi);
|
||||||
|
encrypted_sessionkey_mpi = NULL;
|
||||||
|
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
@ -406,6 +391,12 @@ agent_hybrid_pgp_kem_decrypt (ctrl_t ctrl, const char *desc_text,
|
|||||||
put_membuf (outbuf, ")", 2);
|
put_membuf (outbuf, ")", 2);
|
||||||
|
|
||||||
leave:
|
leave:
|
||||||
|
mpi_release (mlkem_sk_mpi);
|
||||||
|
mpi_release (ecc_pk_mpi);
|
||||||
|
mpi_release (ecc_sk_mpi);
|
||||||
|
mpi_release (ecc_ct_mpi);
|
||||||
|
mpi_release (mlkem_ct_mpi);
|
||||||
|
mpi_release (encrypted_sessionkey_mpi);
|
||||||
gcry_sexp_release (s_skey0);
|
gcry_sexp_release (s_skey0);
|
||||||
gcry_sexp_release (s_skey1);
|
gcry_sexp_release (s_skey1);
|
||||||
return err;
|
return err;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* kmac.c - Keccak based MAC
|
/* kem.c - KEM helper functions
|
||||||
* Copyright (C) 2024 g10 Code GmbH.
|
* Copyright (C) 2024 g10 Code GmbH.
|
||||||
*
|
*
|
||||||
* This file is part of GnuPG.
|
* This file is part of GnuPG.
|
||||||
@ -36,7 +36,7 @@
|
|||||||
#include "mischelp.h"
|
#include "mischelp.h"
|
||||||
|
|
||||||
#define KECCAK512_BLOCKSIZE 136
|
#define KECCAK512_BLOCKSIZE 136
|
||||||
gpg_error_t
|
static gpg_error_t
|
||||||
compute_kmac256 (void *digest, size_t digestlen,
|
compute_kmac256 (void *digest, size_t digestlen,
|
||||||
const void *key, size_t keylen,
|
const void *key, size_t keylen,
|
||||||
const void *custom, size_t customlen,
|
const void *custom, size_t customlen,
|
||||||
@ -134,3 +134,76 @@ compute_kmac256 (void *digest, size_t digestlen,
|
|||||||
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
|
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Compute KEK (shared secret) for ECC with HASHALGO, ECDH result,
|
||||||
|
ciphertext in ECC_CT, public key in ECC_PK. */
|
||||||
|
gpg_error_t
|
||||||
|
gnupg_ecc_kem_kdf (void *kek, size_t kek_len,
|
||||||
|
int hashalgo, const void *ecdh, size_t ecdh_len,
|
||||||
|
const void *ecc_ct, size_t ecc_ct_len,
|
||||||
|
const void *ecc_pk, size_t ecc_pk_len)
|
||||||
|
{
|
||||||
|
gcry_buffer_t iov[3];
|
||||||
|
unsigned int dlen;
|
||||||
|
|
||||||
|
dlen = gcry_md_get_algo_dlen (hashalgo);
|
||||||
|
if (kek_len != dlen)
|
||||||
|
return gpg_error (GPG_ERR_INV_LENGTH);
|
||||||
|
|
||||||
|
memset (iov, 0, sizeof (iov));
|
||||||
|
|
||||||
|
iov[0].data = (unsigned char *)ecdh;
|
||||||
|
iov[0].len = ecdh_len;
|
||||||
|
iov[1].data = (unsigned char *)ecc_ct;
|
||||||
|
iov[1].len = ecc_ct_len;
|
||||||
|
iov[2].data = (unsigned char *)ecc_pk;
|
||||||
|
iov[2].len = ecc_pk_len;
|
||||||
|
gcry_md_hash_buffers (hashalgo, 0, kek, iov, 3);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* domSeperation */
|
||||||
|
#define KMAC_KEY "OpenPGPCompositeKeyDerivationFunction"
|
||||||
|
|
||||||
|
/* customizationString */
|
||||||
|
#define KMAC_CUSTOM "KDF"
|
||||||
|
|
||||||
|
/* Compute KEK by combining two KEMs. */
|
||||||
|
gpg_error_t
|
||||||
|
gnupg_kem_combiner (void *kek, size_t kek_len,
|
||||||
|
const void *ecc_ss, size_t ecc_ss_len,
|
||||||
|
const void *ecc_ct, size_t ecc_ct_len,
|
||||||
|
const void *mlkem_ss, size_t mlkem_ss_len,
|
||||||
|
const void *mlkem_ct, size_t mlkem_ct_len,
|
||||||
|
const void *fixedinfo, size_t fixedinfo_len)
|
||||||
|
{
|
||||||
|
gpg_error_t err;
|
||||||
|
gcry_buffer_t iov[6];
|
||||||
|
|
||||||
|
memset (iov, 0, sizeof (iov));
|
||||||
|
|
||||||
|
iov[0].data = "\x00\x00\x00\x01"; /* Counter */
|
||||||
|
iov[0].len = 4;
|
||||||
|
|
||||||
|
iov[1].data = (unsigned char *)ecc_ss;
|
||||||
|
iov[1].len = ecc_ss_len;
|
||||||
|
|
||||||
|
iov[2].data = (unsigned char *)ecc_ct;
|
||||||
|
iov[2].len = ecc_ct_len;
|
||||||
|
|
||||||
|
iov[3].data = (unsigned char *)mlkem_ss;
|
||||||
|
iov[3].len = mlkem_ss_len;
|
||||||
|
|
||||||
|
iov[4].data = (unsigned char *)mlkem_ct;
|
||||||
|
iov[4].len = mlkem_ct_len;
|
||||||
|
|
||||||
|
iov[5].data = (unsigned char *)fixedinfo;
|
||||||
|
iov[5].len = fixedinfo_len;
|
||||||
|
|
||||||
|
err = compute_kmac256 (kek, kek_len,
|
||||||
|
KMAC_KEY, strlen (KMAC_KEY),
|
||||||
|
KMAC_CUSTOM, strlen (KMAC_CUSTOM), iov, 6);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
@ -299,11 +299,18 @@ char *gnupg_get_help_string (const char *key, int only_current_locale);
|
|||||||
/*-- localename.c --*/
|
/*-- localename.c --*/
|
||||||
const char *gnupg_messages_locale_name (void);
|
const char *gnupg_messages_locale_name (void);
|
||||||
|
|
||||||
/*-- kmac.c --*/
|
/*-- kem.c --*/
|
||||||
gpg_error_t compute_kmac256 (void *digest, size_t digestlen,
|
gpg_error_t gnupg_ecc_kem_kdf (void *kek, size_t kek_len,
|
||||||
const void *key, size_t keylen,
|
int hashalgo, const void *ecdh, size_t ecdh_len,
|
||||||
const void *custom, size_t customlen,
|
const void *ecc_ct, size_t ecc_ct_len,
|
||||||
gcry_buffer_t *data_iov, int data_iovlen);
|
const void *ecc_pk, size_t ecc_pk_len);
|
||||||
|
|
||||||
|
gpg_error_t gnupg_kem_combiner (void *kek, size_t kek_len,
|
||||||
|
const void *ecc_ss, size_t ecc_ss_len,
|
||||||
|
const void *ecc_ct, size_t ecc_ct_len,
|
||||||
|
const void *mlkem_ss, size_t mlkem_ss_len,
|
||||||
|
const void *mlkem_ct, size_t mlkem_ct_len,
|
||||||
|
const void *fixedinfo, size_t fixedinfo_len);
|
||||||
|
|
||||||
/*-- miscellaneous.c --*/
|
/*-- miscellaneous.c --*/
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user