aboutsummaryrefslogtreecommitdiffstats
path: root/sm/encrypt.c
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2020-05-08 16:08:50 +0000
committerWerner Koch <[email protected]>2020-05-08 16:08:50 +0000
commit68b857df13c8a4e6cae5e3a29fd065bf90764547 (patch)
treefe3884661130ed2968406b4d391db93df3caf5e6 /sm/encrypt.c
parentsm: Print algorithm infos in data decryption mode. (diff)
downloadgnupg-68b857df13c8a4e6cae5e3a29fd065bf90764547.tar.gz
gnupg-68b857df13c8a4e6cae5e3a29fd065bf90764547.zip
sm: Allow decryption using dhSinglePass-stdDH-sha1kdf-scheme.
* sm/decrypt.c (ecdh_decrypt): Support dhSinglePass-stdDH-sha1kdf-scheme. Factor key derive code out to ... (ecdh_derive_kek): new global function. Allow for hashs shorter than the key. (hash_ecc_cms_shared_info): Make file-only. * sm/encrypt.c (ecdh_encrypt): Replace derive code by a call to the new ecdh_derive_kek. Add test code to create data using dhSinglePass-stdDH-sha1kdf-scheme. * sm/gpgsm.h (opt): Add member force_ecdh_sha1kdf. * sm/gpgsm.c: Add option --debug-force-ecdh-sha1kdf. -- I did some test against Governikus_Signer: 2.9.2.0 MCard security Provider: 2.4.0 Algorithm catalog from: 05.12.2019 using a Signature Card v2.0 and a nistp256 certificate. Encrypting with Governikus used the stdDH-sha1kdf scheme which we can now decrypt. Encrypting with GPGSM uses for that curve the recommended scheme sha256kdf but Governikus was not able to decrypt this (no usable error message). Encrypting using stdDH-sha1kdf with GPGSM by using the new --debug-force-ecdh-sha1kdf option showed that Governikus was able to decrypt this. FWIW: RFC5753 (Use of Elliptic Curve Cryptography (ECC) Algorithms) has this requirement: Implementations that support EnvelopedData with the ephemeral-static ECDH standard primitive: - MUST support the dhSinglePass-stdDH-sha256kdf-scheme key agreement algorithm, the id-aes128-wrap key wrap algorithm, and the id-aes128-cbc content encryption algorithm; and which Governikus seems not to fulfill. GnuPG-bug-id: 4098 Signed-off-by: Werner Koch <[email protected]>
Diffstat (limited to 'sm/encrypt.c')
-rw-r--r--sm/encrypt.c46
1 files changed, 15 insertions, 31 deletions
diff --git a/sm/encrypt.c b/sm/encrypt.c
index 865b103c1..76bcfa23f 100644
--- a/sm/encrypt.c
+++ b/sm/encrypt.c
@@ -185,7 +185,7 @@ ecdh_encrypt (DEK dek, gcry_sexp_t s_pkey, gcry_sexp_t *r_encval)
const char *encr_algo_str;
const char *wrap_algo_str;
int hash_algo, cipher_algo;
- unsigned int keylen, hashlen;
+ unsigned int keylen;
unsigned char key[32];
gcry_sexp_t s_data = NULL;
gcry_sexp_t s_encr = NULL;
@@ -230,20 +230,28 @@ ecdh_encrypt (DEK dek, gcry_sexp_t s_pkey, gcry_sexp_t *r_encval)
curvebuf = NULL;
/* Our mapping matches the recommended algorithms from RFC-5753 but
- * not supporing the short curves which would require 3DES. */
+ * not supporting the short curves which would require 3DES. */
if (curvebits < 255)
{
err = gpg_error (GPG_ERR_UNKNOWN_CURVE);
log_error ("%s: curve '%s' is not supported\n", __func__, curve);
goto leave;
}
+ else if (opt.force_ecdh_sha1kdf)
+ {
+ /* dhSinglePass-stdDH-sha1kdf-scheme */
+ encr_algo_str = "1.3.133.16.840.63.0.2";
+ wrap_algo_str = "2.16.840.1.101.3.4.1.45";
+ hash_algo = GCRY_MD_SHA1;
+ cipher_algo = GCRY_CIPHER_AES256;
+ keylen = 32;
+ }
else if (curvebits <= 256)
{
/* dhSinglePass-stdDH-sha256kdf-scheme */
encr_algo_str = "1.3.132.1.11.1";
wrap_algo_str = "2.16.840.1.101.3.4.1.5";
hash_algo = GCRY_MD_SHA256;
- hashlen = 32;
cipher_algo = GCRY_CIPHER_AES128;
keylen = 16;
}
@@ -253,7 +261,6 @@ ecdh_encrypt (DEK dek, gcry_sexp_t s_pkey, gcry_sexp_t *r_encval)
encr_algo_str = "1.3.132.1.11.2";
wrap_algo_str = "2.16.840.1.101.3.4.1.25";
hash_algo = GCRY_MD_SHA384;
- hashlen = 48;
cipher_algo = GCRY_CIPHER_AES256;
keylen = 24;
}
@@ -263,7 +270,6 @@ ecdh_encrypt (DEK dek, gcry_sexp_t s_pkey, gcry_sexp_t *r_encval)
encr_algo_str = "1.3.132.1.11.3";
wrap_algo_str = "2.16.840.1.101.3.4.1.45";
hash_algo = GCRY_MD_SHA512;
- hashlen = 64;
cipher_algo = GCRY_CIPHER_AES256;
keylen = 32;
}
@@ -338,32 +344,10 @@ ecdh_encrypt (DEK dek, gcry_sexp_t s_pkey, gcry_sexp_t *r_encval)
if (DBG_CRYPTO)
log_printhex (secret, secretlen, "ECDH X ..:");
- /* Derive a KEK (key wrapping key) using MESSAGE and SECRET_X.
- * According to SEC1 3.6.1 we should check that
- * SECRETLEN + UKMLEN + 4 < maxhashlen
- * However, we have no practical limit on the hash length and thus
- * there is no point in checking this. The second check that
- * KEYLEN < hashlen*(2^32-1)
- * is obviously also not needed. Because with our allowed
- * parameters KEYLEN is always less or equal to HASHLEN so that we
- * do not need to iterate at all.
- */
- log_assert (gcry_md_get_algo_dlen (hash_algo) == hashlen);
- {
- gcry_md_hd_t hash_hd;
- err = gcry_md_open (&hash_hd, hash_algo, 0);
- if (err)
- goto leave;
- gcry_md_write(hash_hd, secret, secretlen);
- gcry_md_write(hash_hd, "\x00\x00\x00\x01", 4); /* counter */
- err = hash_ecc_cms_shared_info (hash_hd, wrap_algo_str, keylen, NULL, 0);
- gcry_md_final (hash_hd);
- log_assert (keylen <= sizeof key && keylen <= hashlen);
- memcpy (key, gcry_md_read (hash_hd, 0), keylen);
- gcry_md_close (hash_hd);
- if (err)
- goto leave;
- }
+ err = ecdh_derive_kek (key, keylen, hash_algo, wrap_algo_str,
+ secret, secretlen, NULL, 0);
+ if (err)
+ goto leave;
if (DBG_CRYPTO)
log_printhex (key, keylen, "KEK .....:");