aboutsummaryrefslogtreecommitdiffstats
path: root/agent/pkdecrypt.c
diff options
context:
space:
mode:
authorNIIBE Yutaka <[email protected]>2024-04-10 03:52:13 +0000
committerNIIBE Yutaka <[email protected]>2024-04-10 03:52:13 +0000
commitc21237ac27220a834f47888ff2b4d3b570eb2dc0 (patch)
tree7a8c5a008372e549b9f10ef20d66dc60879cb072 /agent/pkdecrypt.c
parentcommon: Rename to kem.c from kmac.c. (diff)
downloadgnupg-c21237ac27220a834f47888ff2b4d3b570eb2dc0.tar.gz
gnupg-c21237ac27220a834f47888ff2b4d3b570eb2dc0.zip
agent:kem: Externalize FIXED_INFO.
* agent/pkdecrypt.c (agent_hybrid_pgp_kem_decrypt): Don't hard code the value of FIXED_INFO. Get it from frontend. -- Signed-off-by: NIIBE Yutaka <[email protected]>
Diffstat (limited to 'agent/pkdecrypt.c')
-rw-r--r--agent/pkdecrypt.c69
1 files changed, 51 insertions, 18 deletions
diff --git a/agent/pkdecrypt.c b/agent/pkdecrypt.c
index 3848bcefc..24ba1fd64 100644
--- a/agent/pkdecrypt.c
+++ b/agent/pkdecrypt.c
@@ -177,12 +177,13 @@ reverse_buffer (unsigned char *buffer, unsigned int length)
First keygrip is for ECC, second keygrip is for PQC. CIPHERTEXT
should follow the format of:
- (enc-val(pqc(s%m)(e%m)(k%m))))
- s: encrypted session key
+ (enc-val(pqc(e%m)(k%m)(s%m)(fixed-info&)))
e: ECDH ciphertext
k: ML-KEM ciphertext
+ s: encrypted session key
+ fixed-info: A buffer with the fixed info.
- FIXME: For now, possibile keys on smartcard are not supported.
+ FIXME: For now, possible keys on smartcard are not supported.
*/
static gpg_error_t
agent_hybrid_pgp_kem_decrypt (ctrl_t ctrl, const char *desc_text,
@@ -224,7 +225,10 @@ agent_hybrid_pgp_kem_decrypt (ctrl_t ctrl, const char *desc_text,
gcry_cipher_hd_t hd;
unsigned char sessionkey[256];
size_t sessionkey_len;
- const unsigned char fixedinfo[1] = { 105 };
+ gcry_buffer_t fixed_info = { 0, 0, 0, NULL };
+
+ gcry_sexp_t curve = NULL;
+ const char *curve_name;
err = agent_key_from_file (ctrl, NULL, desc_text,
ctrl->keygrip, &shadow_info,
@@ -246,33 +250,62 @@ agent_hybrid_pgp_kem_decrypt (ctrl_t ctrl, const char *desc_text,
/* Here assumes no smartcard, but private keys */
- gcry_sexp_extract_param (s_cipher, NULL, "/e/k/s",
+ gcry_sexp_extract_param (s_cipher, NULL, "/eks&'fixed-info'",
&ecc_ct_mpi,
&mlkem_ct_mpi,
- &encrypted_sessionkey_mpi, NULL);
+ &encrypted_sessionkey_mpi,
+ &fixed_info, NULL);
+ if (err)
+ goto leave;
encrypted_sessionkey = gcry_mpi_get_opaque (encrypted_sessionkey_mpi, &nbits);
encrypted_sessionkey_len = (nbits+7)/8;
- encrypted_sessionkey_len--;
+ if (encrypted_sessionkey_len < 1+1+8)
+ {
+ /* Fixme: This is a basic check but we should better test
+ * against the expected length and something which
+ * is required to avoid an underflow. */
+ err = gpg_error (GPG_ERR_INV_DATA);
+ goto leave;
+ }
+ encrypted_sessionkey_len--;
if (encrypted_sessionkey[0] != encrypted_sessionkey_len)
{
- err = GPG_ERR_INV_DATA;
+ err = gpg_error (GPG_ERR_INV_DATA);
goto leave;
}
encrypted_sessionkey++; /* Skip the length. */
if (encrypted_sessionkey[0] != CIPHER_ALGO_AES256)
{
- err = GPG_ERR_INV_DATA;
+ err = gpg_error (GPG_ERR_INV_DATA);
goto leave;
}
+
encrypted_sessionkey_len--;
encrypted_sessionkey++; /* Skip the sym algo */
/* Fistly, ECC part. FIXME: For now, we assume X25519. */
- gcry_sexp_extract_param (s_skey0, NULL, "/q/d",
- &ecc_pk_mpi, &ecc_sk_mpi, NULL);
+ curve = gcry_sexp_find_token (s_skey0, "curve", 0);
+ if (!curve)
+ {
+ err = gpg_error (GPG_ERR_BAD_SECKEY);
+ goto leave;
+ }
+
+ curve_name = gcry_sexp_nth_data (curve, 1, &len);
+ if (len != 10 || memcmp (curve_name, "Curve25519", len))
+ {
+ err = gpg_error (GPG_ERR_BAD_SECKEY);
+ goto leave;
+ }
+
+ err = gcry_sexp_extract_param (s_skey0, NULL, "/q/d",
+ &ecc_pk_mpi, &ecc_sk_mpi, NULL);
+ if (err)
+ goto leave;
+
p = gcry_mpi_get_opaque (ecc_pk_mpi, &nbits);
len = (nbits+7)/8;
memcpy (ecc_pk, p+1, 32); /* Remove the 0x40 prefix */
@@ -280,7 +313,7 @@ agent_hybrid_pgp_kem_decrypt (ctrl_t ctrl, const char *desc_text,
len = (nbits+7)/8;
if (len > 32)
{
- err = GPG_ERR_INV_DATA;
+ err = gpg_error (GPG_ERR_INV_DATA);
goto leave;
}
memset (ecc_sk, 0, 32);
@@ -295,19 +328,17 @@ agent_hybrid_pgp_kem_decrypt (ctrl_t ctrl, const char *desc_text,
ecc_ct_len = (nbits+7)/8;
if (ecc_ct_len != 32)
{
- err = GPG_ERR_INV_DATA;
+ err = gpg_error (GPG_ERR_INV_DATA);
goto leave;
}
err = gcry_kem_decap (GCRY_KEM_RAW_X25519, ecc_sk, 32, ecc_ct, ecc_ct_len,
ecc_ecdh, 32, NULL, 0);
-
if (err)
goto leave;
err = gnupg_ecc_kem_kdf (ecc_ss, 32, GCRY_MD_SHA3_256,
ecc_ecdh, 32, ecc_ct, 32, ecc_pk, 32);
-
if (err)
goto leave;
@@ -317,14 +348,14 @@ agent_hybrid_pgp_kem_decrypt (ctrl_t ctrl, const char *desc_text,
len = (nbits+7)/8;
if (len != GCRY_KEM_MLKEM768_SECKEY_LEN)
{
- err = GPG_ERR_INV_DATA;
+ err = gpg_error (GPG_ERR_INV_DATA);
goto leave;
}
mlkem_ct = gcry_mpi_get_opaque (mlkem_ct_mpi, &nbits);
len = (nbits+7)/8;
if (len != GCRY_KEM_MLKEM768_CIPHER_LEN)
{
- err = GPG_ERR_INV_DATA;
+ err = gpg_error (GPG_ERR_INV_DATA);
goto leave;
}
err = gcry_kem_decap (GCRY_KEM_MLKEM768,
@@ -343,7 +374,7 @@ agent_hybrid_pgp_kem_decrypt (ctrl_t ctrl, const char *desc_text,
ecc_ss, 32, ecc_ct, 32,
mlkem_ss, GCRY_KEM_MLKEM768_SHARED_LEN,
mlkem_ct, GCRY_KEM_MLKEM768_CIPHER_LEN,
- fixedinfo, 1);
+ fixed_info.data, fixed_info.size);
if (err)
{
log_error ("KEM combiner failed: %s\n", gpg_strerror (err));
@@ -397,6 +428,8 @@ agent_hybrid_pgp_kem_decrypt (ctrl_t ctrl, const char *desc_text,
mpi_release (ecc_ct_mpi);
mpi_release (mlkem_ct_mpi);
mpi_release (encrypted_sessionkey_mpi);
+ gcry_free (fixed_info.data);
+ gcry_sexp_release (curve);
gcry_sexp_release (s_skey0);
gcry_sexp_release (s_skey1);
return err;