aboutsummaryrefslogtreecommitdiffstats
path: root/g10/pkglue.c
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2024-04-18 12:37:40 +0000
committerWerner Koch <[email protected]>2024-04-18 12:37:40 +0000
commitba3c873934c920d18399fd194f07e0159ee31ec3 (patch)
treec461e13aa42db25c096495bbb950234f6d0a73dd /g10/pkglue.c
parentgpg: Mark disabled keys and add show-ownertrust list option. (diff)
downloadgnupg-ba3c873934c920d18399fd194f07e0159ee31ec3.tar.gz
gnupg-ba3c873934c920d18399fd194f07e0159ee31ec3.zip
gpg: Prepare Kyber encryption code for more variants.
* common/openpgp-oid.c (oidtable): Add field kem_algo. (openpgp_oid_to_kem_algo): New. * g10/pkglue.c (do_encrypt_kem): Add support for Kyber1024. -- GnuPG-bug-id: 6815
Diffstat (limited to 'g10/pkglue.c')
-rw-r--r--g10/pkglue.c88
1 files changed, 66 insertions, 22 deletions
diff --git a/g10/pkglue.c b/g10/pkglue.c
index 0167e80e3..2de0e80ab 100644
--- a/g10/pkglue.c
+++ b/g10/pkglue.c
@@ -417,6 +417,11 @@ pk_verify (pubkey_algo_t pkalgo, gcry_mpi_t hash,
}
+#if GCRY_KEM_MLKEM1024_ENCAPS_LEN < GCRY_KEM_MLKEM768_ENCAPS_LEN \
+ || GCRY_KEM_MLKEM1024_SHARED_LEN < GCRY_KEM_MLKEM768_SHARED_LEN
+# error Bad Kyber constants in Libgcrypt
+#endif
+
/* Core of the encryption for KEM algorithms. See pk_decrypt for a
* description of the arguments. */
static gpg_error_t
@@ -428,6 +433,8 @@ do_encrypt_kem (PKT_public_key *pk, gcry_mpi_t data, int seskey_algo,
unsigned int nbits, n;
gcry_sexp_t s_data = NULL;
gcry_cipher_hd_t hd = NULL;
+ char *ecc_oid = NULL;
+ enum gcry_kem_algos kyber_algo, ecc_algo;
const unsigned char *ecc_pubkey;
size_t ecc_pubkey_len;
@@ -445,10 +452,9 @@ do_encrypt_kem (PKT_public_key *pk, gcry_mpi_t data, int seskey_algo,
unsigned char ecc_ss[GCRY_KEM_RAW_X25519_SHARED_LEN];
size_t ecc_ss_len = GCRY_KEM_RAW_X25519_SHARED_LEN;
- unsigned char kyber_ct[GCRY_KEM_MLKEM768_ENCAPS_LEN];
- size_t kyber_ct_len = GCRY_KEM_MLKEM768_ENCAPS_LEN;
- unsigned char kyber_ss[GCRY_KEM_MLKEM768_SHARED_LEN];
- size_t kyber_ss_len = GCRY_KEM_MLKEM768_SHARED_LEN;
+ unsigned char kyber_ct[GCRY_KEM_MLKEM1024_ENCAPS_LEN];
+ unsigned char kyber_ss[GCRY_KEM_MLKEM1024_SHARED_LEN];
+ size_t kyber_ct_len, kyber_ss_len;
char fixedinfo[1+MAX_FINGERPRINT_LEN];
int fixedlen;
@@ -463,23 +469,48 @@ do_encrypt_kem (PKT_public_key *pk, gcry_mpi_t data, int seskey_algo,
* second public key is expected. Right now we take the keys
* directly from the PK->data elements. */
- /* FIXME: This is only for cv25519 */
- ecc_pubkey = gcry_mpi_get_opaque (pk->pkey[1], &nbits);
- ecc_pubkey_len = (nbits+7)/8;
- if (ecc_pubkey_len != 33)
+ ecc_oid = openpgp_oid_to_str (pk->pkey[0]);
+ if (!ecc_oid)
+ {
+ err = gpg_error_from_syserror ();
+ log_error ("%s: error getting OID for ECC key\n", __func__);
+ goto leave;
+ }
+ ecc_algo = openpgp_oid_to_kem_algo (ecc_oid);
+ if (ecc_algo == GCRY_KEM_RAW_X25519)
+ {
+ if (!strcmp (ecc_oid, "1.3.6.1.4.1.3029.1.5.1"))
+ log_info ("Warning: "
+ "legacy OID for cv25519 accepted during develpment\n");
+ ecc_pubkey = gcry_mpi_get_opaque (pk->pkey[1], &nbits);
+ ecc_pubkey_len = (nbits+7)/8;
+ if (ecc_pubkey_len != 33)
+ {
+ if (opt.verbose)
+ log_info ("%s: ECC public key length invalid (%zu)\n",
+ __func__, ecc_pubkey_len);
+ err = gpg_error (GPG_ERR_INV_DATA);
+ goto leave;
+ }
+ ecc_pubkey++; /* Remove the 0x40 prefix. */
+ ecc_pubkey_len--;
+ }
+ else
{
if (opt.verbose)
- log_info ("%s: ECC public key length invalid (%zu)\n",
- __func__, ecc_pubkey_len);
+ log_info ("%s: ECC curve %s not supported\n", __func__, ecc_oid);
err = gpg_error (GPG_ERR_INV_DATA);
goto leave;
}
- ecc_pubkey++; /* Remove the 0x40 prefix. */
- ecc_pubkey_len--;
+
+
if (DBG_CRYPTO)
- log_printhex (ecc_pubkey, ecc_pubkey_len, "ECC pubkey:");
+ {
+ log_debug ("ECC curve: %s\n", ecc_oid);
+ log_printhex (ecc_pubkey, ecc_pubkey_len, "ECC pubkey:");
+ }
- err = gcry_kem_encap (GCRY_KEM_RAW_X25519,
+ err = gcry_kem_encap (ecc_algo,
ecc_pubkey, ecc_pubkey_len,
ecc_ct, ecc_ct_len,
ecc_ecdh, ecc_ecdh_len,
@@ -487,7 +518,8 @@ do_encrypt_kem (PKT_public_key *pk, gcry_mpi_t data, int seskey_algo,
if (err)
{
if (opt.verbose)
- log_info ("%s: gcry_kem_encap for ECC failed\n", __func__);
+ log_info ("%s: gcry_kem_encap for ECC (%s) failed\n",
+ __func__, ecc_oid);
goto leave;
}
if (DBG_CRYPTO)
@@ -509,21 +541,32 @@ do_encrypt_kem (PKT_public_key *pk, gcry_mpi_t data, int seskey_algo,
if (DBG_CRYPTO)
log_printhex (ecc_ss, ecc_ss_len, "ECC shared:");
- /* FIXME: This is only for kyber768 */
kyber_pubkey = gcry_mpi_get_opaque (pk->pkey[2], &nbits);
kyber_pubkey_len = (nbits+7)/8;
- if (kyber_pubkey_len != GCRY_KEM_MLKEM768_PUBKEY_LEN)
+ if (kyber_pubkey_len == GCRY_KEM_MLKEM768_PUBKEY_LEN)
+ {
+ kyber_algo = GCRY_KEM_MLKEM768;
+ kyber_ct_len = GCRY_KEM_MLKEM768_ENCAPS_LEN;
+ kyber_ss_len = GCRY_KEM_MLKEM768_SHARED_LEN;
+ }
+ else if (kyber_pubkey_len == GCRY_KEM_MLKEM1024_PUBKEY_LEN)
+ {
+ kyber_algo = GCRY_KEM_MLKEM1024;
+ kyber_ct_len = GCRY_KEM_MLKEM1024_ENCAPS_LEN;
+ kyber_ss_len = GCRY_KEM_MLKEM1024_SHARED_LEN;
+ }
+ else
{
if (opt.verbose)
- log_info ("%s: Kyber public key length invalid (%zu)\n",
- __func__, kyber_pubkey_len);
+ log_info ("%s: Kyber public key length invalid (%zu)\n",
+ __func__, kyber_pubkey_len);
err = gpg_error (GPG_ERR_INV_DATA);
goto leave;
}
if (DBG_CRYPTO)
log_printhex (kyber_pubkey, kyber_pubkey_len, "|!trunc|Kyber pubkey:");
- err = gcry_kem_encap (GCRY_KEM_MLKEM768,
+ err = gcry_kem_encap (kyber_algo,
kyber_pubkey, kyber_pubkey_len,
kyber_ct, kyber_ct_len,
kyber_ss, kyber_ss_len,
@@ -625,11 +668,12 @@ do_encrypt_kem (PKT_public_key *pk, gcry_mpi_t data, int seskey_algo,
wipememory (ecc_ct, ecc_ct_len);
wipememory (ecc_ecdh, ecc_ecdh_len);
wipememory (ecc_ss, ecc_ss_len);
- wipememory (kyber_ct, kyber_ct_len);
- wipememory (kyber_ss, kyber_ss_len);
+ wipememory (kyber_ct, sizeof kyber_ct);
+ wipememory (kyber_ss, sizeof kyber_ss);
wipememory (kek, kek_len);
xfree (enc_seskey);
gcry_cipher_close (hd);
+ xfree (ecc_oid);
return err;
}