diff options
Diffstat (limited to 'g10')
-rw-r--r-- | g10/call-agent.c | 10 | ||||
-rw-r--r-- | g10/pkglue.c | 2 | ||||
-rw-r--r-- | g10/pubkey-enc.c | 102 |
3 files changed, 84 insertions, 30 deletions
diff --git a/g10/call-agent.c b/g10/call-agent.c index bdde9b053..bba6fa833 100644 --- a/g10/call-agent.c +++ b/g10/call-agent.c @@ -2909,6 +2909,7 @@ agent_pkdecrypt (ctrl_t ctrl, const char *keygrip, const char *desc, char *p, *buf, *endp; const char *keygrip2 = NULL; struct default_inq_parm_s dfltparm; + const char *cmdline; memset (&dfltparm, 0, sizeof dfltparm); dfltparm.ctrl = ctrl; @@ -2935,6 +2936,12 @@ agent_pkdecrypt (ctrl_t ctrl, const char *keygrip, const char *desc, return gpg_error (GPG_ERR_INV_VALUE); } + if (*keygrip2) + cmdline = "PKDECRYPT --kem=PQC-PGP"; + else if (pubkey_algo == PUBKEY_ALGO_ECDH) + cmdline = "PKDECRYPT --kem=PGP"; + else + cmdline = "PKDECRYPT"; err = start_agent (ctrl, 0); if (err) @@ -2977,8 +2984,7 @@ agent_pkdecrypt (ctrl_t ctrl, const char *keygrip, const char *desc, err = make_canon_sexp (s_ciphertext, &parm.ciphertext, &parm.ciphertextlen); if (err) return err; - err = assuan_transact (agent_ctx, - *keygrip2? "PKDECRYPT --kem=PQC-PGP":"PKDECRYPT", + err = assuan_transact (agent_ctx, cmdline, put_membuf_cb, &data, inq_ciphertext_cb, &parm, padding_info_cb, r_padding); diff --git a/g10/pkglue.c b/g10/pkglue.c index 307e39e0c..240f50846 100644 --- a/g10/pkglue.c +++ b/g10/pkglue.c @@ -598,7 +598,7 @@ do_encrypt_kem (PKT_public_key *pk, gcry_mpi_t data, int seskey_algo, ecc_hash_algo, ecc_ecdh, ecc_ecdh_len, ecc_ct, ecc_ct_len, - ecc_pubkey, ecc_pubkey_len); + ecc_pubkey, ecc_pubkey_len, NULL); if (err) { if (opt.verbose) diff --git a/g10/pubkey-enc.c b/g10/pubkey-enc.c index 3cbd5624a..d9c4cdb60 100644 --- a/g10/pubkey-enc.c +++ b/g10/pubkey-enc.c @@ -188,6 +188,80 @@ get_session_key (ctrl_t ctrl, struct pubkey_enc_list *list, DEK *dek) } +/* Build an SEXP to gpg-agent, for PKDECRYPT command. */ +static gpg_error_t +ecdh_sexp_build (gcry_sexp_t *r_s_data, struct pubkey_enc_list *enc, + PKT_public_key *sk) +{ + gpg_error_t err; + const unsigned char *oid; + const unsigned char *kdf_params_spec; + unsigned int nbits; + size_t len; + size_t oid_len; + byte fp[MAX_FINGERPRINT_LEN]; + int keywrap_cipher_algo; + int kdf_hash_algo; + unsigned char *kdf_params = NULL; + int kdf_params_len = 0; + + if (!gcry_mpi_get_flag (sk->pkey[0], GCRYMPI_FLAG_OPAQUE)) + return gpg_error (GPG_ERR_BAD_PUBKEY); + + oid = gcry_mpi_get_opaque (sk->pkey[0], &nbits); + oid_len = (nbits+7)/8; + + /* In the public key part of SK, there is a specifier of KDF + parameters (namely, hash algo for KDF and symmetric algo for + wrapping key). Using this specifier (together with curve OID + of the public key and the fingerprint), we build _the_ KDF + parameters. */ + if (!gcry_mpi_get_flag (sk->pkey[2], GCRYMPI_FLAG_OPAQUE)) + return gpg_error (GPG_ERR_BAD_PUBKEY); + + kdf_params_spec = gcry_mpi_get_opaque (sk->pkey[2], &nbits); + len = (nbits+7)/8; + + fingerprint_from_pk (sk, fp, NULL); + + /* Expect 4 bytes 03 01 hash_alg symm_alg. */ + if (len != 4 || kdf_params_spec[0] != 3 || kdf_params_spec[1] != 1) + return gpg_error (GPG_ERR_BAD_PUBKEY); + + kdf_params_len = oid_len + 1 + 4 + 20 + 20; + kdf_params = xtrymalloc (kdf_params_len); + if (!kdf_params) + return gpg_error_from_syserror (); + + memcpy (kdf_params, oid, oid_len); + kdf_params[oid_len] = PUBKEY_ALGO_ECDH; + memcpy (kdf_params + oid_len + 1, kdf_params_spec, 4); + memcpy (kdf_params + oid_len + 1 + 4, "Anonymous Sender ", 20); + memcpy (kdf_params + oid_len + 1 + 4 + 20, fp, 20); + + if (DBG_CRYPTO) + log_printhex (kdf_params, kdf_params_len, + "ecdh KDF message params are:"); + + keywrap_cipher_algo = kdf_params_spec[3]; + kdf_hash_algo = kdf_params_spec[2]; + + if (!enc->d.data[0] || !enc->d.data[1]) + { + xfree (kdf_params); + return gpg_error (GPG_ERR_BAD_MPI); + } + + err = gcry_sexp_build (r_s_data, NULL, + "(enc-val(ecc(c%d)(h%d)(e%m)(s%m)(kdf-params%b)))", + keywrap_cipher_algo, kdf_hash_algo, + enc->d.data[0], enc->d.data[1], + kdf_params_len, kdf_params); + xfree (kdf_params); + return err; +} + + static gpg_error_t get_it (ctrl_t ctrl, struct pubkey_enc_list *enc, DEK *dek, PKT_public_key *sk, u32 *keyid) @@ -201,7 +275,6 @@ get_it (ctrl_t ctrl, gcry_sexp_t s_data; char *desc; char *keygrip; - byte fp[MAX_FINGERPRINT_LEN]; if (DBG_CLOCK) log_clock ("decryption start"); @@ -231,13 +304,7 @@ get_it (ctrl_t ctrl, enc->d.data[0]); } else if (sk->pubkey_algo == PUBKEY_ALGO_ECDH) - { - if (!enc->d.data[0] || !enc->d.data[1]) - err = gpg_error (GPG_ERR_BAD_MPI); - else - err = gcry_sexp_build (&s_data, NULL, "(enc-val(ecdh(s%m)(e%m)))", - enc->d.data[1], enc->d.data[0]); - } + err = ecdh_sexp_build (&s_data, enc, sk); else if (sk->pubkey_algo == PUBKEY_ALGO_KYBER) { char fixedinfo[1+MAX_FINGERPRINT_LEN]; @@ -270,9 +337,6 @@ get_it (ctrl_t ctrl, if (err) goto leave; - if (sk->pubkey_algo == PUBKEY_ALGO_ECDH) - fingerprint_from_pk (sk, fp, NULL); - /* Decrypt. */ desc = gpg_format_keydesc (ctrl, sk, FORMAT_KEYDESC_NORMAL, 1); @@ -316,22 +380,6 @@ get_it (ctrl_t ctrl, } else if (sk->pubkey_algo == PUBKEY_ALGO_ECDH) { - gcry_mpi_t decoded; - - /* At the beginning the frame are the bytes of shared point MPI. */ - err = pk_ecdh_decrypt (&decoded, fp, - enc->d.data[1], /*encr data as an MPI*/ - frame, nframe, - sk->pkey); - if(err) - goto leave; - - xfree (frame); - err = gcry_mpi_aprint (GCRYMPI_FMT_USG, &frame, &nframe, decoded); - mpi_release (decoded); - if (err) - goto leave; - /* Now the frame are the bytes decrypted but padded session key. */ if (!nframe || nframe <= 8 || frame[nframe-1] > nframe) |