mirror of
git://git.gnupg.org/gnupg.git
synced 2025-05-24 16:43:28 +02:00
gpg,agent: Clean up around using ECC KEM.
* common/util.h (gnupg_ecc_kem_kdf): Change the last two args. * common/kem.c (gnupg_ecc_kem_kdf): The last arguments are KDF_PARAMS and its length. * agent/pkdecrypt.c (composite_pgp_kem_decrypt): Follow the change. * g10/pkglue.c (do_encrypt_kem): Follow the change. * g10/ecdh.c (extract_secret_x, derive_kek): Remove. (gnupg_ecc_6637_kdf): Remove. (ecc_build_kdf_params): Rename from build_kdf_params, changing arguments. * g10/pkglue.c (do_encrypt_ecdh): Refactor by ecc_build_kdf_params and gnupg_ecc_kem_kdf. * g10/pkglue.h (pk_ecdh_decrypt, gnupg_ecc_6637_kdf): Remove. (ecc_build_kdf_params): New. * g10/pubkey-enc.c (ecdh_sexp_build): Use ecc_build_kdf_params. -- GnuPG-bug-id: 7649 Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
This commit is contained in:
parent
37bec0df7b
commit
681d754043
@ -648,7 +648,7 @@ composite_pgp_kem_decrypt (ctrl_t ctrl, const char *desc_text,
|
|||||||
ecc_shared_len = gcry_md_get_algo_dlen (ecc_hashalgo);
|
ecc_shared_len = gcry_md_get_algo_dlen (ecc_hashalgo);
|
||||||
err = gnupg_ecc_kem_kdf (ecc_ss, ecc_shared_len, ecc_hashalgo,
|
err = gnupg_ecc_kem_kdf (ecc_ss, ecc_shared_len, ecc_hashalgo,
|
||||||
ecc_ecdh, ecc_point_len, ecc_ct, ecc_point_len,
|
ecc_ecdh, ecc_point_len, ecc_ct, ecc_point_len,
|
||||||
ecc_pk, ecc_point_len, NULL);
|
ecc_pk, ecc_point_len, NULL, 0);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
if (opt.verbose)
|
if (opt.verbose)
|
||||||
@ -891,7 +891,9 @@ ecc_kem_decrypt (ctrl_t ctrl, const char *desc_text,
|
|||||||
x-component from the point. */
|
x-component from the point. */
|
||||||
ecc_ecdh + 1 : ecc_ecdh,
|
ecc_ecdh + 1 : ecc_ecdh,
|
||||||
ecc->scalar_len, ecc_ct, ecc_point_len,
|
ecc->scalar_len, ecc_ct, ecc_point_len,
|
||||||
ecc_pk, ecc_point_len, &kdf_params);
|
ecc_pk, ecc_point_len,
|
||||||
|
(char *)kdf_params.data+kdf_params.off,
|
||||||
|
kdf_params.len);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
if (opt.verbose)
|
if (opt.verbose)
|
||||||
|
@ -156,7 +156,7 @@ gnupg_ecc_kem_kdf (void *kek, size_t kek_len,
|
|||||||
int hashalgo, const void *ecdh, size_t ecdh_len,
|
int hashalgo, const void *ecdh, size_t ecdh_len,
|
||||||
const void *ecc_ct, size_t ecc_ct_len,
|
const void *ecc_ct, size_t ecc_ct_len,
|
||||||
const void *ecc_pk, size_t ecc_pk_len,
|
const void *ecc_pk, size_t ecc_pk_len,
|
||||||
gcry_buffer_t *kdf_params)
|
unsigned char *kdf_params, size_t kdf_params_len)
|
||||||
{
|
{
|
||||||
if (kdf_params)
|
if (kdf_params)
|
||||||
{
|
{
|
||||||
@ -168,8 +168,7 @@ gnupg_ecc_kem_kdf (void *kek, size_t kek_len,
|
|||||||
param[0] = kek_len;
|
param[0] = kek_len;
|
||||||
err = gcry_kdf_open (&hd, GCRY_KDF_ONESTEP_KDF, hashalgo, param, 1,
|
err = gcry_kdf_open (&hd, GCRY_KDF_ONESTEP_KDF, hashalgo, param, 1,
|
||||||
ecdh, ecdh_len, NULL, 0, NULL, 0,
|
ecdh, ecdh_len, NULL, 0, NULL, 0,
|
||||||
(char *)kdf_params->data+kdf_params->off,
|
kdf_params, kdf_params_len);
|
||||||
kdf_params->len);
|
|
||||||
if (!err)
|
if (!err)
|
||||||
{
|
{
|
||||||
gcry_kdf_compute (hd, NULL);
|
gcry_kdf_compute (hd, NULL);
|
||||||
|
@ -306,7 +306,8 @@ gpg_error_t gnupg_ecc_kem_kdf (void *kek, size_t kek_len,
|
|||||||
int hashalgo, const void *ecdh, size_t ecdh_len,
|
int hashalgo, const void *ecdh, size_t ecdh_len,
|
||||||
const void *ecc_ct, size_t ecc_ct_len,
|
const void *ecc_ct, size_t ecc_ct_len,
|
||||||
const void *ecc_pk, size_t ecc_pk_len,
|
const void *ecc_pk, size_t ecc_pk_len,
|
||||||
gcry_buffer_t *kdf_params);
|
unsigned char *kdf_params,
|
||||||
|
size_t kdf_params_len);
|
||||||
|
|
||||||
gpg_error_t gnupg_kem_combiner (void *kek, size_t kek_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_ss, size_t ecc_ss_len,
|
||||||
|
448
g10/ecdh.c
448
g10/ecdh.c
@ -79,62 +79,6 @@ pk_ecdh_default_params (unsigned int qbits)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Extract xcomponent from the point SHARED. POINT_NBYTES is the
|
|
||||||
size to represent an EC point which is determined by the public
|
|
||||||
key. SECRET_X_SIZE is the size of x component to represent an
|
|
||||||
integer which is determined by the curve. */
|
|
||||||
static gpg_error_t
|
|
||||||
extract_secret_x (byte **r_secret_x,
|
|
||||||
const char *shared, size_t nshared,
|
|
||||||
size_t point_nbytes, size_t secret_x_size)
|
|
||||||
{
|
|
||||||
byte *secret_x;
|
|
||||||
|
|
||||||
*r_secret_x = NULL;
|
|
||||||
|
|
||||||
/* Extract X from the result. It must be in the format of:
|
|
||||||
04 || X || Y
|
|
||||||
40 || X
|
|
||||||
41 || X
|
|
||||||
|
|
||||||
Since it may come with the prefix, the size of point is larger
|
|
||||||
than or equals to the size of an integer X. We also better check
|
|
||||||
that the provided shared point is not larger than the size needed
|
|
||||||
to represent the point. */
|
|
||||||
if (point_nbytes < secret_x_size)
|
|
||||||
return gpg_error (GPG_ERR_BAD_DATA);
|
|
||||||
if (point_nbytes < nshared)
|
|
||||||
return gpg_error (GPG_ERR_BAD_DATA);
|
|
||||||
|
|
||||||
/* Extract x component of the shared point: this is the actual
|
|
||||||
shared secret. */
|
|
||||||
secret_x = xtrymalloc_secure (point_nbytes);
|
|
||||||
if (!secret_x)
|
|
||||||
return gpg_error_from_syserror ();
|
|
||||||
|
|
||||||
memcpy (secret_x, shared, nshared);
|
|
||||||
|
|
||||||
/* Wrangle the provided point unless only the x-component w/o any
|
|
||||||
* prefix was provided. */
|
|
||||||
if (nshared != secret_x_size)
|
|
||||||
{
|
|
||||||
/* Remove the prefix. */
|
|
||||||
if ((point_nbytes & 1))
|
|
||||||
memmove (secret_x, secret_x+1, secret_x_size);
|
|
||||||
|
|
||||||
/* Clear the rest of data. */
|
|
||||||
if (point_nbytes - secret_x_size)
|
|
||||||
memset (secret_x+secret_x_size, 0, point_nbytes-secret_x_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (DBG_CRYPTO)
|
|
||||||
log_printhex (secret_x, secret_x_size, "ECDH shared secret X is:");
|
|
||||||
|
|
||||||
*r_secret_x = secret_x;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Build KDF parameters */
|
/* Build KDF parameters */
|
||||||
/* RFC 6637 defines the KDF parameters and its encoding in Section
|
/* RFC 6637 defines the KDF parameters and its encoding in Section
|
||||||
8. EC DH Algorighm (ECDH). Since it was written for v4 key, it
|
8. EC DH Algorighm (ECDH). Since it was written for v4 key, it
|
||||||
@ -142,375 +86,57 @@ extract_secret_x (byte **r_secret_x,
|
|||||||
master key fingerprint". For v5 key, it is considered "adequate"
|
master key fingerprint". For v5 key, it is considered "adequate"
|
||||||
(in terms of NIST SP 800 56A, see 5.8.2 FixedInfo) to use the first
|
(in terms of NIST SP 800 56A, see 5.8.2 FixedInfo) to use the first
|
||||||
20 octets of its 32 octets fingerprint. */
|
20 octets of its 32 octets fingerprint. */
|
||||||
static gpg_error_t
|
|
||||||
build_kdf_params (unsigned char kdf_params[256], size_t *r_size,
|
|
||||||
gcry_mpi_t *pkey, const byte pk_fp[MAX_FINGERPRINT_LEN])
|
|
||||||
{
|
|
||||||
IOBUF obuf;
|
|
||||||
gpg_error_t err;
|
|
||||||
|
|
||||||
*r_size = 0;
|
|
||||||
|
|
||||||
obuf = iobuf_temp();
|
|
||||||
if (!obuf)
|
|
||||||
return gpg_error_from_syserror ();
|
|
||||||
|
|
||||||
/* variable-length field 1, curve name OID */
|
|
||||||
err = gpg_mpi_write_opaque_nohdr (obuf, pkey[0]);
|
|
||||||
/* fixed-length field 2 */
|
|
||||||
iobuf_put (obuf, PUBKEY_ALGO_ECDH);
|
|
||||||
/* variable-length field 3, KDF params */
|
|
||||||
err = (err ? err : gpg_mpi_write_opaque_nohdr (obuf, pkey[2]));
|
|
||||||
/* fixed-length field 4 */
|
|
||||||
iobuf_write (obuf, "Anonymous Sender ", 20);
|
|
||||||
/* fixed-length field 5, recipient fp (or first 20 octets of fp) */
|
|
||||||
iobuf_write (obuf, pk_fp, 20);
|
|
||||||
|
|
||||||
if (!err)
|
|
||||||
*r_size = iobuf_temp_to_buffer (obuf, kdf_params, 256);
|
|
||||||
|
|
||||||
iobuf_close (obuf);
|
|
||||||
|
|
||||||
if (!err)
|
|
||||||
{
|
|
||||||
if (DBG_CRYPTO)
|
|
||||||
log_printhex (kdf_params, *r_size, "ecdh KDF message params are:");
|
|
||||||
}
|
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Derive KEK with KEK_SIZE into the memory at SECRET_X. */
|
|
||||||
static gpg_error_t
|
|
||||||
derive_kek (size_t kek_size,
|
|
||||||
int kdf_hash_algo,
|
|
||||||
byte *secret_x, int secret_x_size,
|
|
||||||
const unsigned char *kdf_params, size_t kdf_params_size)
|
|
||||||
{
|
|
||||||
gpg_error_t err;
|
|
||||||
#if 0 /* GCRYPT_VERSION_NUMBER >= 0x010b00 */
|
|
||||||
/*
|
|
||||||
* Experimental: We will remove this if/endif-conditional
|
|
||||||
* compilation when we update NEED_LIBGCRYPT_VERSION to 1.11.0.
|
|
||||||
*/
|
|
||||||
gcry_kdf_hd_t hd;
|
|
||||||
unsigned long param[1];
|
|
||||||
|
|
||||||
param[0] = kek_size;
|
|
||||||
err = gcry_kdf_open (&hd, GCRY_KDF_ONESTEP_KDF, kdf_hash_algo,
|
|
||||||
param, 1,
|
|
||||||
secret_x, secret_x_size, NULL, 0, NULL, 0,
|
|
||||||
kdf_params, kdf_params_size);
|
|
||||||
if (!err)
|
|
||||||
{
|
|
||||||
gcry_kdf_compute (hd, NULL);
|
|
||||||
gcry_kdf_final (hd, kek_size, secret_x);
|
|
||||||
gcry_kdf_close (hd);
|
|
||||||
/* Clean the tail before returning. */
|
|
||||||
memset (secret_x+kek_size, 0, secret_x_size - kek_size);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
gcry_md_hd_t h;
|
|
||||||
|
|
||||||
log_assert( gcry_md_get_algo_dlen (kdf_hash_algo) >= 32 );
|
|
||||||
|
|
||||||
err = gcry_md_open (&h, kdf_hash_algo, 0);
|
|
||||||
if (err)
|
|
||||||
{
|
|
||||||
log_error ("gcry_md_open failed for kdf_hash_algo %d: %s",
|
|
||||||
kdf_hash_algo, gpg_strerror (err));
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
gcry_md_write(h, "\x00\x00\x00\x01", 4); /* counter = 1 */
|
|
||||||
gcry_md_write(h, secret_x, secret_x_size); /* x of the point X */
|
|
||||||
gcry_md_write(h, kdf_params, kdf_params_size); /* KDF parameters */
|
|
||||||
gcry_md_final (h);
|
|
||||||
memcpy (secret_x, gcry_md_read (h, kdf_hash_algo), kek_size);
|
|
||||||
gcry_md_close (h);
|
|
||||||
/* Clean the tail before returning. */
|
|
||||||
memset (secret_x+kek_size, 0, secret_x_size - kek_size);
|
|
||||||
#endif
|
|
||||||
if (DBG_CRYPTO)
|
|
||||||
log_printhex (secret_x, kek_size, "ecdh KEK is:");
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Compute KEK for ECC with HASHALGO, ECDH result, and public key in
|
|
||||||
PK, using the method defined in RFC 6637. Note that ephemeral key
|
|
||||||
is not used to compute KEK here. */
|
|
||||||
gpg_error_t
|
gpg_error_t
|
||||||
gnupg_ecc_6637_kdf (void *kek, size_t kek_len,
|
ecc_build_kdf_params (unsigned char **r_kdf_params, size_t *r_len,
|
||||||
int hashalgo, const void *ecdh, size_t ecdh_len,
|
const unsigned char **r_kdf_params_spec,
|
||||||
PKT_public_key *pk)
|
gcry_mpi_t *pkey, const byte fp[MAX_FINGERPRINT_LEN])
|
||||||
{
|
{
|
||||||
gpg_error_t err;
|
const unsigned char *oid;
|
||||||
unsigned char kdf_params[256];
|
const unsigned char *kdf_params_spec;
|
||||||
size_t kdf_params_size;
|
|
||||||
unsigned int nbits;
|
unsigned int nbits;
|
||||||
byte *secret_x;
|
size_t oid_len;
|
||||||
int secret_x_size;
|
size_t len;
|
||||||
gcry_kdf_hd_t hd;
|
unsigned char *kdf_params = NULL;
|
||||||
unsigned long param[1];
|
int kdf_params_len = 0;
|
||||||
byte fp[MAX_FINGERPRINT_LEN];
|
|
||||||
|
|
||||||
fingerprint_from_pk (pk, fp, NULL);
|
if (!gcry_mpi_get_flag (pkey[0], GCRYMPI_FLAG_OPAQUE))
|
||||||
|
|
||||||
/* Build kdf_params. */
|
|
||||||
err = build_kdf_params (kdf_params, &kdf_params_size, pk->pkey, fp);
|
|
||||||
if (err)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
nbits = pubkey_nbits (PUBKEY_ALGO_ECDH, pk->pkey);
|
|
||||||
if (!nbits)
|
|
||||||
return gpg_error (GPG_ERR_TOO_SHORT);
|
|
||||||
|
|
||||||
secret_x_size = (nbits+7)/8;
|
|
||||||
if (kek_len > secret_x_size)
|
|
||||||
return gpg_error (GPG_ERR_BAD_PUBKEY);
|
return gpg_error (GPG_ERR_BAD_PUBKEY);
|
||||||
|
|
||||||
err = extract_secret_x (&secret_x, ecdh, ecdh_len,
|
oid = gcry_mpi_get_opaque (pkey[0], &nbits);
|
||||||
/* pk->pkey[1] is the public point */
|
oid_len = (nbits+7)/8;
|
||||||
(mpi_get_nbits (pk->pkey[1])+7)/8,
|
|
||||||
secret_x_size);
|
|
||||||
if (err)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
param[0] = kek_len;
|
|
||||||
err = gcry_kdf_open (&hd, GCRY_KDF_ONESTEP_KDF, hashalgo, param, 1,
|
|
||||||
secret_x, secret_x_size, NULL, 0, NULL, 0,
|
|
||||||
kdf_params, kdf_params_size);
|
|
||||||
if (!err)
|
|
||||||
{
|
|
||||||
gcry_kdf_compute (hd, NULL);
|
|
||||||
gcry_kdf_final (hd, kek_len, secret_x);
|
|
||||||
gcry_kdf_close (hd);
|
|
||||||
memcpy (kek, secret_x, kek_len);
|
|
||||||
/* Clean the tail before returning. */
|
|
||||||
memset (secret_x+kek_len, 0, secret_x_size - kek_len);
|
|
||||||
xfree (secret_x);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
xfree (secret_x);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Prepare ECDH using SHARED, PK_FP fingerprint, and PKEY array.
|
|
||||||
Returns the cipher handle in R_HD, which needs to be closed by
|
|
||||||
the caller. */
|
|
||||||
static gpg_error_t
|
|
||||||
prepare_ecdh_with_shared_point (const char *shared, size_t nshared,
|
|
||||||
const byte pk_fp[MAX_FINGERPRINT_LEN],
|
|
||||||
gcry_mpi_t *pkey, gcry_cipher_hd_t *r_hd)
|
|
||||||
{
|
|
||||||
gpg_error_t err;
|
|
||||||
byte *secret_x;
|
|
||||||
int secret_x_size;
|
|
||||||
unsigned int nbits;
|
|
||||||
const unsigned char *kek_params;
|
|
||||||
size_t kek_params_size;
|
|
||||||
int kdf_hash_algo;
|
|
||||||
int kdf_encr_algo;
|
|
||||||
unsigned char kdf_params[256];
|
|
||||||
size_t kdf_params_size;
|
|
||||||
size_t kek_size;
|
|
||||||
gcry_cipher_hd_t hd;
|
|
||||||
|
|
||||||
*r_hd = NULL;
|
|
||||||
|
|
||||||
|
/* In the public key part, 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 (pkey[2], GCRYMPI_FLAG_OPAQUE))
|
if (!gcry_mpi_get_flag (pkey[2], GCRYMPI_FLAG_OPAQUE))
|
||||||
return gpg_error (GPG_ERR_BUG);
|
return gpg_error (GPG_ERR_BAD_PUBKEY);
|
||||||
|
|
||||||
kek_params = gcry_mpi_get_opaque (pkey[2], &nbits);
|
kdf_params_spec = gcry_mpi_get_opaque (pkey[2], &nbits);
|
||||||
kek_params_size = (nbits+7)/8;
|
len = (nbits+7)/8;
|
||||||
|
|
||||||
if (DBG_CRYPTO)
|
|
||||||
log_printhex (kek_params, kek_params_size, "ecdh KDF params:");
|
|
||||||
|
|
||||||
/* Expect 4 bytes 03 01 hash_alg symm_alg. */
|
/* Expect 4 bytes 03 01 hash_alg symm_alg. */
|
||||||
if (kek_params_size != 4 || kek_params[0] != 3 || kek_params[1] != 1)
|
if (len != 4 || kdf_params_spec[0] != 3 || kdf_params_spec[1] != 1)
|
||||||
return gpg_error (GPG_ERR_BAD_PUBKEY);
|
return gpg_error (GPG_ERR_BAD_PUBKEY);
|
||||||
|
|
||||||
kdf_hash_algo = kek_params[2];
|
kdf_params_len = oid_len + 1 + 4 + 20 + 20;
|
||||||
kdf_encr_algo = kek_params[3];
|
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)
|
if (DBG_CRYPTO)
|
||||||
log_debug ("ecdh KDF algorithms %s+%s with aeswrap\n",
|
log_printhex (kdf_params, kdf_params_len,
|
||||||
openpgp_md_algo_name (kdf_hash_algo),
|
"ecdh KDF message params are:");
|
||||||
openpgp_cipher_algo_name (kdf_encr_algo));
|
|
||||||
|
|
||||||
if (kdf_hash_algo != GCRY_MD_SHA256
|
*r_kdf_params = kdf_params;
|
||||||
&& kdf_hash_algo != GCRY_MD_SHA384
|
*r_len = kdf_params_len;
|
||||||
&& kdf_hash_algo != GCRY_MD_SHA512)
|
if (r_kdf_params_spec)
|
||||||
return gpg_error (GPG_ERR_BAD_PUBKEY);
|
*r_kdf_params_spec = kdf_params_spec;
|
||||||
|
return 0;
|
||||||
if (kdf_encr_algo != CIPHER_ALGO_AES
|
|
||||||
&& kdf_encr_algo != CIPHER_ALGO_AES192
|
|
||||||
&& kdf_encr_algo != CIPHER_ALGO_AES256)
|
|
||||||
return gpg_error (GPG_ERR_BAD_PUBKEY);
|
|
||||||
|
|
||||||
kek_size = gcry_cipher_get_algo_keylen (kdf_encr_algo);
|
|
||||||
if (kek_size > gcry_md_get_algo_dlen (kdf_hash_algo))
|
|
||||||
return gpg_error (GPG_ERR_BAD_PUBKEY);
|
|
||||||
|
|
||||||
/* Build kdf_params. */
|
|
||||||
err = build_kdf_params (kdf_params, &kdf_params_size, pkey, pk_fp);
|
|
||||||
if (err)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
nbits = pubkey_nbits (PUBKEY_ALGO_ECDH, pkey);
|
|
||||||
if (!nbits)
|
|
||||||
return gpg_error (GPG_ERR_TOO_SHORT);
|
|
||||||
|
|
||||||
secret_x_size = (nbits+7)/8;
|
|
||||||
if (kek_size > secret_x_size)
|
|
||||||
return gpg_error (GPG_ERR_BAD_PUBKEY);
|
|
||||||
|
|
||||||
err = extract_secret_x (&secret_x, shared, nshared,
|
|
||||||
/* pkey[1] is the public point */
|
|
||||||
(mpi_get_nbits (pkey[1])+7)/8,
|
|
||||||
secret_x_size);
|
|
||||||
if (err)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
/*** We have now the shared secret bytes in secret_x. ***/
|
|
||||||
|
|
||||||
/* At this point we are done with PK encryption and the rest of the
|
|
||||||
* function uses symmetric key encryption techniques to protect the
|
|
||||||
* input DATA. The following two sections will simply replace
|
|
||||||
* current secret_x with a value derived from it. This will become
|
|
||||||
* a KEK.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Derive a KEK (key wrapping key) using SECRET_X and KDF_PARAMS. */
|
|
||||||
err = derive_kek (kek_size, kdf_hash_algo, secret_x,
|
|
||||||
secret_x_size, kdf_params, kdf_params_size);
|
|
||||||
if (err)
|
|
||||||
{
|
|
||||||
xfree (secret_x);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* And, finally, aeswrap with key secret_x. */
|
|
||||||
err = gcry_cipher_open (&hd, kdf_encr_algo, GCRY_CIPHER_MODE_AESWRAP, 0);
|
|
||||||
if (err)
|
|
||||||
{
|
|
||||||
log_error ("ecdh failed to initialize AESWRAP: %s\n",
|
|
||||||
gpg_strerror (err));
|
|
||||||
xfree (secret_x);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = gcry_cipher_setkey (hd, secret_x, kek_size);
|
|
||||||
xfree (secret_x);
|
|
||||||
secret_x = NULL;
|
|
||||||
if (err)
|
|
||||||
{
|
|
||||||
gcry_cipher_close (hd);
|
|
||||||
log_error ("ecdh failed in gcry_cipher_setkey: %s\n",
|
|
||||||
gpg_strerror (err));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
*r_hd = hd;
|
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Perform ECDH decryption. */
|
|
||||||
int
|
|
||||||
pk_ecdh_decrypt (gcry_mpi_t *r_result, const byte sk_fp[MAX_FINGERPRINT_LEN],
|
|
||||||
gcry_mpi_t data,
|
|
||||||
const byte *shared, size_t nshared, gcry_mpi_t * skey)
|
|
||||||
{
|
|
||||||
gpg_error_t err;
|
|
||||||
gcry_cipher_hd_t hd;
|
|
||||||
size_t nbytes;
|
|
||||||
byte *data_buf;
|
|
||||||
int data_buf_size;
|
|
||||||
const unsigned char *p;
|
|
||||||
unsigned int nbits;
|
|
||||||
|
|
||||||
*r_result = NULL;
|
|
||||||
|
|
||||||
err = prepare_ecdh_with_shared_point (shared, nshared, sk_fp, skey, &hd);
|
|
||||||
if (err)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
p = gcry_mpi_get_opaque (data, &nbits);
|
|
||||||
nbytes = (nbits+7)/8;
|
|
||||||
|
|
||||||
data_buf_size = nbytes;
|
|
||||||
if ((data_buf_size & 7) != 1 || data_buf_size <= 1 + 8)
|
|
||||||
{
|
|
||||||
log_error ("can't use a shared secret of %d bytes for ecdh\n",
|
|
||||||
data_buf_size);
|
|
||||||
gcry_cipher_close (hd);
|
|
||||||
return gpg_error (GPG_ERR_BAD_DATA);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The first octet is for length. It's longer than the result
|
|
||||||
because of one additional block of AESWRAP. */
|
|
||||||
data_buf_size -= 1 + 8;
|
|
||||||
data_buf = xtrymalloc_secure (data_buf_size);
|
|
||||||
if (!data_buf)
|
|
||||||
{
|
|
||||||
err = gpg_error_from_syserror ();
|
|
||||||
gcry_cipher_close (hd);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!p)
|
|
||||||
{
|
|
||||||
xfree (data_buf);
|
|
||||||
gcry_cipher_close (hd);
|
|
||||||
return gpg_error (GPG_ERR_BAD_MPI);
|
|
||||||
}
|
|
||||||
if (p[0] != nbytes-1)
|
|
||||||
{
|
|
||||||
log_error ("ecdh inconsistent size\n");
|
|
||||||
xfree (data_buf);
|
|
||||||
gcry_cipher_close (hd);
|
|
||||||
return gpg_error (GPG_ERR_BAD_MPI);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (DBG_CRYPTO)
|
|
||||||
log_printhex (p+1, nbytes-1, "ecdh decrypting :");
|
|
||||||
|
|
||||||
err = gcry_cipher_decrypt (hd, data_buf, data_buf_size, p+1, nbytes-1);
|
|
||||||
gcry_cipher_close (hd);
|
|
||||||
if (err)
|
|
||||||
{
|
|
||||||
log_error ("ecdh failed in gcry_cipher_decrypt: %s\n",
|
|
||||||
gpg_strerror (err));
|
|
||||||
xfree (data_buf);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (DBG_CRYPTO)
|
|
||||||
log_printhex (data_buf, data_buf_size, "ecdh decrypted to :");
|
|
||||||
|
|
||||||
/* Padding is removed later. */
|
|
||||||
/* if (in[data_buf_size-1] > 8 ) */
|
|
||||||
/* { */
|
|
||||||
/* log_error ("ecdh failed at decryption: invalid padding." */
|
|
||||||
/* " 0x%02x > 8\n", in[data_buf_size-1] ); */
|
|
||||||
/* return gpg_error (GPG_ERR_BAD_KEY); */
|
|
||||||
/* } */
|
|
||||||
|
|
||||||
err = gcry_mpi_scan (r_result, GCRYMPI_FMT_USG, data_buf,
|
|
||||||
data_buf_size, NULL);
|
|
||||||
xfree (data_buf);
|
|
||||||
if (err)
|
|
||||||
{
|
|
||||||
log_error ("ecdh failed to create a plain text MPI: %s\n",
|
|
||||||
gpg_strerror (err));
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
70
g10/pkglue.c
70
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_hash_algo,
|
||||||
ecc_ecdh, ecc_ecdh_len,
|
ecc_ecdh, ecc_ecdh_len,
|
||||||
ecc_ct, ecc_ct_len,
|
ecc_ct, ecc_ct_len,
|
||||||
ecc_pubkey, ecc_pubkey_len, NULL);
|
ecc_pubkey, ecc_pubkey_len, NULL, 0);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
if (opt.verbose)
|
if (opt.verbose)
|
||||||
@ -766,14 +766,19 @@ do_encrypt_ecdh (PKT_public_key *pk, gcry_mpi_t data, gcry_mpi_t *resarr)
|
|||||||
unsigned char ecc_ct[ECC_POINT_LEN_MAX];
|
unsigned char ecc_ct[ECC_POINT_LEN_MAX];
|
||||||
unsigned char ecc_ecdh[ECC_POINT_LEN_MAX];
|
unsigned char ecc_ecdh[ECC_POINT_LEN_MAX];
|
||||||
size_t ecc_ct_len, ecc_ecdh_len;
|
size_t ecc_ct_len, ecc_ecdh_len;
|
||||||
|
int is_weierstrass;
|
||||||
|
|
||||||
unsigned char *kek = NULL;
|
unsigned char *kek = NULL;
|
||||||
size_t kek_len;
|
size_t kek_len;
|
||||||
|
|
||||||
const unsigned char *kek_params;
|
const unsigned char *kdf_params_spec;
|
||||||
size_t kek_params_size;
|
byte fp[MAX_FINGERPRINT_LEN];
|
||||||
|
int keywrap_cipher_algo;
|
||||||
int kdf_hash_algo;
|
int kdf_hash_algo;
|
||||||
int kdf_encr_algo;
|
unsigned char *kdf_params = NULL;
|
||||||
|
size_t kdf_params_len = 0;
|
||||||
|
|
||||||
|
fingerprint_from_pk (pk, fp, NULL);
|
||||||
|
|
||||||
ecc_oid = openpgp_oid_to_str (pk->pkey[0]);
|
ecc_oid = openpgp_oid_to_str (pk->pkey[0]);
|
||||||
if (!ecc_oid)
|
if (!ecc_oid)
|
||||||
@ -802,6 +807,7 @@ do_encrypt_ecdh (PKT_public_key *pk, gcry_mpi_t data, gcry_mpi_t *resarr)
|
|||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
ecc_ct_len = ecc_ecdh_len = 32;
|
ecc_ct_len = ecc_ecdh_len = 32;
|
||||||
|
is_weierstrass = 0;
|
||||||
}
|
}
|
||||||
else if (ecc_algo == GCRY_KEM_RAW_X448)
|
else if (ecc_algo == GCRY_KEM_RAW_X448)
|
||||||
{
|
{
|
||||||
@ -816,6 +822,7 @@ do_encrypt_ecdh (PKT_public_key *pk, gcry_mpi_t data, gcry_mpi_t *resarr)
|
|||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
ecc_ct_len = ecc_ecdh_len = 56;
|
ecc_ct_len = ecc_ecdh_len = 56;
|
||||||
|
is_weierstrass = 0;
|
||||||
}
|
}
|
||||||
else if (ecc_algo == GCRY_KEM_RAW_BP256)
|
else if (ecc_algo == GCRY_KEM_RAW_BP256)
|
||||||
{
|
{
|
||||||
@ -830,6 +837,7 @@ do_encrypt_ecdh (PKT_public_key *pk, gcry_mpi_t data, gcry_mpi_t *resarr)
|
|||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
ecc_ct_len = ecc_ecdh_len = 65;
|
ecc_ct_len = ecc_ecdh_len = 65;
|
||||||
|
is_weierstrass = 1;
|
||||||
}
|
}
|
||||||
else if (ecc_algo == GCRY_KEM_RAW_BP384)
|
else if (ecc_algo == GCRY_KEM_RAW_BP384)
|
||||||
{
|
{
|
||||||
@ -844,6 +852,7 @@ do_encrypt_ecdh (PKT_public_key *pk, gcry_mpi_t data, gcry_mpi_t *resarr)
|
|||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
ecc_ct_len = ecc_ecdh_len = 97;
|
ecc_ct_len = ecc_ecdh_len = 97;
|
||||||
|
is_weierstrass = 1;
|
||||||
}
|
}
|
||||||
else if (ecc_algo == GCRY_KEM_RAW_BP512)
|
else if (ecc_algo == GCRY_KEM_RAW_BP512)
|
||||||
{
|
{
|
||||||
@ -858,6 +867,7 @@ do_encrypt_ecdh (PKT_public_key *pk, gcry_mpi_t data, gcry_mpi_t *resarr)
|
|||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
ecc_ct_len = ecc_ecdh_len = 129;
|
ecc_ct_len = ecc_ecdh_len = 129;
|
||||||
|
is_weierstrass = 1;
|
||||||
}
|
}
|
||||||
else if (ecc_algo == GCRY_KEM_RAW_P256R1)
|
else if (ecc_algo == GCRY_KEM_RAW_P256R1)
|
||||||
{
|
{
|
||||||
@ -872,6 +882,7 @@ do_encrypt_ecdh (PKT_public_key *pk, gcry_mpi_t data, gcry_mpi_t *resarr)
|
|||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
ecc_ct_len = ecc_ecdh_len = 65;
|
ecc_ct_len = ecc_ecdh_len = 65;
|
||||||
|
is_weierstrass = 1;
|
||||||
}
|
}
|
||||||
else if (ecc_algo == GCRY_KEM_RAW_P384R1)
|
else if (ecc_algo == GCRY_KEM_RAW_P384R1)
|
||||||
{
|
{
|
||||||
@ -886,6 +897,7 @@ do_encrypt_ecdh (PKT_public_key *pk, gcry_mpi_t data, gcry_mpi_t *resarr)
|
|||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
ecc_ct_len = ecc_ecdh_len = 97;
|
ecc_ct_len = ecc_ecdh_len = 97;
|
||||||
|
is_weierstrass = 1;
|
||||||
}
|
}
|
||||||
else if (ecc_algo == GCRY_KEM_RAW_P521R1)
|
else if (ecc_algo == GCRY_KEM_RAW_P521R1)
|
||||||
{
|
{
|
||||||
@ -900,6 +912,7 @@ do_encrypt_ecdh (PKT_public_key *pk, gcry_mpi_t data, gcry_mpi_t *resarr)
|
|||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
ecc_ct_len = ecc_ecdh_len = 133;
|
ecc_ct_len = ecc_ecdh_len = 133;
|
||||||
|
is_weierstrass = 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -933,32 +946,18 @@ do_encrypt_ecdh (PKT_public_key *pk, gcry_mpi_t data, gcry_mpi_t *resarr)
|
|||||||
log_printhex (ecc_ecdh, ecc_ecdh_len, "ECC ecdh:");
|
log_printhex (ecc_ecdh, ecc_ecdh_len, "ECC ecdh:");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!gcry_mpi_get_flag (pk->pkey[2], GCRYMPI_FLAG_OPAQUE))
|
err = ecc_build_kdf_params (&kdf_params, &kdf_params_len,
|
||||||
{
|
&kdf_params_spec, pk->pkey, fp);
|
||||||
err = gpg_error (GPG_ERR_BUG);
|
if (err)
|
||||||
goto leave;
|
return err;
|
||||||
}
|
|
||||||
|
|
||||||
kek_params = gcry_mpi_get_opaque (pk->pkey[2], &nbits);
|
keywrap_cipher_algo = kdf_params_spec[3];
|
||||||
kek_params_size = (nbits+7)/8;
|
kdf_hash_algo = kdf_params_spec[2];
|
||||||
|
|
||||||
if (DBG_CRYPTO)
|
|
||||||
log_printhex (kek_params, kek_params_size, "ecdh KDF params:");
|
|
||||||
|
|
||||||
/* Expect 4 bytes 03 01 hash_alg symm_alg. */
|
|
||||||
if (kek_params_size != 4 || kek_params[0] != 3 || kek_params[1] != 1)
|
|
||||||
{
|
|
||||||
err = gpg_error (GPG_ERR_BAD_PUBKEY);
|
|
||||||
goto leave;
|
|
||||||
}
|
|
||||||
|
|
||||||
kdf_hash_algo = kek_params[2];
|
|
||||||
kdf_encr_algo = kek_params[3];
|
|
||||||
|
|
||||||
if (DBG_CRYPTO)
|
if (DBG_CRYPTO)
|
||||||
log_debug ("ecdh KDF algorithms %s+%s with aeswrap\n",
|
log_debug ("ecdh KDF algorithms %s+%s with aeswrap\n",
|
||||||
openpgp_md_algo_name (kdf_hash_algo),
|
openpgp_md_algo_name (kdf_hash_algo),
|
||||||
openpgp_cipher_algo_name (kdf_encr_algo));
|
openpgp_cipher_algo_name (keywrap_cipher_algo));
|
||||||
|
|
||||||
if (kdf_hash_algo != GCRY_MD_SHA256
|
if (kdf_hash_algo != GCRY_MD_SHA256
|
||||||
&& kdf_hash_algo != GCRY_MD_SHA384
|
&& kdf_hash_algo != GCRY_MD_SHA384
|
||||||
@ -968,15 +967,15 @@ do_encrypt_ecdh (PKT_public_key *pk, gcry_mpi_t data, gcry_mpi_t *resarr)
|
|||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (kdf_encr_algo != CIPHER_ALGO_AES
|
if (keywrap_cipher_algo != CIPHER_ALGO_AES
|
||||||
&& kdf_encr_algo != CIPHER_ALGO_AES192
|
&& keywrap_cipher_algo != CIPHER_ALGO_AES192
|
||||||
&& kdf_encr_algo != CIPHER_ALGO_AES256)
|
&& keywrap_cipher_algo != CIPHER_ALGO_AES256)
|
||||||
{
|
{
|
||||||
err = gpg_error (GPG_ERR_BAD_PUBKEY);
|
err = gpg_error (GPG_ERR_BAD_PUBKEY);
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
kek_len = gcry_cipher_get_algo_keylen (kdf_encr_algo);
|
kek_len = gcry_cipher_get_algo_keylen (keywrap_cipher_algo);
|
||||||
if (kek_len > gcry_md_get_algo_dlen (kdf_hash_algo))
|
if (kek_len > gcry_md_get_algo_dlen (kdf_hash_algo))
|
||||||
{
|
{
|
||||||
err = gpg_error (GPG_ERR_BAD_PUBKEY);
|
err = gpg_error (GPG_ERR_BAD_PUBKEY);
|
||||||
@ -990,8 +989,14 @@ do_encrypt_ecdh (PKT_public_key *pk, gcry_mpi_t data, gcry_mpi_t *resarr)
|
|||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = gnupg_ecc_6637_kdf (kek, kek_len, kdf_hash_algo,
|
err = gnupg_ecc_kem_kdf (kek, kek_len, kdf_hash_algo,
|
||||||
ecc_ecdh, ecc_ecdh_len, pk);
|
is_weierstrass ?
|
||||||
|
ecc_ecdh + 1 : ecc_ecdh,
|
||||||
|
is_weierstrass ?
|
||||||
|
(ecc_ecdh_len - 1) / 2 : ecc_ecdh_len,
|
||||||
|
NULL, 0, NULL, 0,
|
||||||
|
kdf_params, kdf_params_len);
|
||||||
|
xfree (kdf_params);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
if (opt.verbose)
|
if (opt.verbose)
|
||||||
@ -1002,7 +1007,8 @@ do_encrypt_ecdh (PKT_public_key *pk, gcry_mpi_t data, gcry_mpi_t *resarr)
|
|||||||
if (DBG_CRYPTO)
|
if (DBG_CRYPTO)
|
||||||
log_printhex (kek, kek_len, "KEK:");
|
log_printhex (kek, kek_len, "KEK:");
|
||||||
|
|
||||||
err = gcry_cipher_open (&hd, kdf_encr_algo, GCRY_CIPHER_MODE_AESWRAP, 0);
|
err = gcry_cipher_open (&hd, keywrap_cipher_algo,
|
||||||
|
GCRY_CIPHER_MODE_AESWRAP, 0);
|
||||||
if (!err)
|
if (!err)
|
||||||
err = gcry_cipher_setkey (hd, kek, kek_len);
|
err = gcry_cipher_setkey (hd, kek, kek_len);
|
||||||
if (err)
|
if (err)
|
||||||
|
10
g10/pkglue.h
10
g10/pkglue.h
@ -38,12 +38,10 @@ int pk_check_secret_key (pubkey_algo_t algo, gcry_mpi_t *skey);
|
|||||||
|
|
||||||
/*-- ecdh.c --*/
|
/*-- ecdh.c --*/
|
||||||
gcry_mpi_t pk_ecdh_default_params (unsigned int qbits);
|
gcry_mpi_t pk_ecdh_default_params (unsigned int qbits);
|
||||||
int pk_ecdh_decrypt (gcry_mpi_t *result, const byte sk_fp[MAX_FINGERPRINT_LEN],
|
|
||||||
gcry_mpi_t data,
|
|
||||||
const byte *frame, size_t nframe,
|
|
||||||
gcry_mpi_t * skey);
|
|
||||||
|
|
||||||
gpg_error_t gnupg_ecc_6637_kdf (void *kek, size_t kek_len, int hashalgo,
|
gpg_error_t ecc_build_kdf_params (unsigned char **r_kdf_params, size_t *r_len,
|
||||||
const void *ecdh, size_t ecdh_len, PKT_public_key *pk);
|
const unsigned char **r_kdf_params_spec,
|
||||||
|
gcry_mpi_t *pkey,
|
||||||
|
const byte fp[MAX_FINGERPRINT_LEN]);
|
||||||
|
|
||||||
#endif /*GNUPG_G10_PKGLUE_H*/
|
#endif /*GNUPG_G10_PKGLUE_H*/
|
||||||
|
@ -194,54 +194,19 @@ ecdh_sexp_build (gcry_sexp_t *r_s_data, struct pubkey_enc_list *enc,
|
|||||||
PKT_public_key *sk)
|
PKT_public_key *sk)
|
||||||
{
|
{
|
||||||
gpg_error_t err;
|
gpg_error_t err;
|
||||||
const unsigned char *oid;
|
|
||||||
const unsigned char *kdf_params_spec;
|
const unsigned char *kdf_params_spec;
|
||||||
unsigned int nbits;
|
|
||||||
size_t len;
|
|
||||||
size_t oid_len;
|
|
||||||
byte fp[MAX_FINGERPRINT_LEN];
|
byte fp[MAX_FINGERPRINT_LEN];
|
||||||
int keywrap_cipher_algo;
|
int keywrap_cipher_algo;
|
||||||
int kdf_hash_algo;
|
int kdf_hash_algo;
|
||||||
unsigned char *kdf_params = NULL;
|
unsigned char *kdf_params = NULL;
|
||||||
int kdf_params_len = 0;
|
size_t 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);
|
fingerprint_from_pk (sk, fp, NULL);
|
||||||
|
|
||||||
/* Expect 4 bytes 03 01 hash_alg symm_alg. */
|
err = ecc_build_kdf_params (&kdf_params, &kdf_params_len,
|
||||||
if (len != 4 || kdf_params_spec[0] != 3 || kdf_params_spec[1] != 1)
|
&kdf_params_spec, sk->pkey, fp);
|
||||||
return gpg_error (GPG_ERR_BAD_PUBKEY);
|
if (err)
|
||||||
|
return err;
|
||||||
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];
|
keywrap_cipher_algo = kdf_params_spec[3];
|
||||||
kdf_hash_algo = kdf_params_spec[2];
|
kdf_hash_algo = kdf_params_spec[2];
|
||||||
@ -256,7 +221,7 @@ ecdh_sexp_build (gcry_sexp_t *r_s_data, struct pubkey_enc_list *enc,
|
|||||||
"(enc-val(ecc(c%d)(h%d)(e%m)(s%m)(kdf-params%b)))",
|
"(enc-val(ecc(c%d)(h%d)(e%m)(s%m)(kdf-params%b)))",
|
||||||
keywrap_cipher_algo, kdf_hash_algo,
|
keywrap_cipher_algo, kdf_hash_algo,
|
||||||
enc->d.data[0], enc->d.data[1],
|
enc->d.data[0], enc->d.data[1],
|
||||||
kdf_params_len, kdf_params);
|
(int)kdf_params_len, kdf_params);
|
||||||
xfree (kdf_params);
|
xfree (kdf_params);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user