diff options
author | Nikos Mavrogiannopoulos <nmav@redhat.com> | 2016-08-24 13:32:04 +0200 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@redhat.com> | 2016-08-24 14:09:43 +0200 |
commit | 13893550aa266d55bd5ec6ef395ae48f528b24d5 (patch) | |
tree | ec554ab959107a20917924b9e5b45590e2ba42b1 | |
parent | dfbe6a74d8172fd69676987e2566b3f521101d3f (diff) | |
download | gnutls-13893550aa266d55bd5ec6ef395ae48f528b24d5.tar.gz |
Added support for decrypting PKCS#8 files which use HMAC-SHA256 as PRF
This improves compatibility with new openssl versions.
-rw-r--r-- | NEWS | 4 | ||||
-rw-r--r-- | lib/algorithms.h | 2 | ||||
-rw-r--r-- | lib/algorithms/mac.c | 69 | ||||
-rw-r--r-- | lib/gnutls_int.h | 1 | ||||
-rw-r--r-- | lib/includes/gnutls/gnutls.h.in | 2 | ||||
-rw-r--r-- | lib/libgnutls.map | 1 | ||||
-rw-r--r-- | lib/x509/pkcs12.c | 4 | ||||
-rw-r--r-- | lib/x509/privkey_pkcs8.c | 42 | ||||
-rw-r--r-- | lib/x509/x509_int.h | 1 |
9 files changed, 95 insertions, 31 deletions
@@ -7,11 +7,15 @@ See the end for copying conditions. ** libgnutls: Added support for IP name constraints. Patch by Martin Ukrop. +** libgnutls: Added support for decrypting PKCS#8 files which use HMAC-SHA256 + as PRF. + ** gnutls-cli: Fixed starttls regression from 3.5.3. ** API and ABI modifications: GNUTLS_E_MALFORMED_CIDR: Added gnutls_x509_cidr_to_rfc5280: Added +gnutls_oid_to_mac: Added * Version 3.5.3 (released 2016-08-09) diff --git a/lib/algorithms.h b/lib/algorithms.h index 5ab350b098..819f3c8035 100644 --- a/lib/algorithms.h +++ b/lib/algorithms.h @@ -142,8 +142,6 @@ inline static int _gnutls_mac_get_key_size(const mac_entry_st * e) return e->key_size; } -#define _gnutls_x509_oid_to_mac(oid) (gnutls_mac_algorithm_t)gnutls_oid_to_digest(oid) - /* Functions for digests. */ #define _gnutls_x509_digest_to_oid _gnutls_x509_mac_to_oid #define _gnutls_digest_get_name _gnutls_mac_get_name diff --git a/lib/algorithms/mac.c b/lib/algorithms/mac.c index 8a8ea4f312..f0882549c9 100644 --- a/lib/algorithms/mac.c +++ b/lib/algorithms/mac.c @@ -25,33 +25,39 @@ #include "errors.h" #include <x509/common.h> +#define MAC_OID_SHA1 "1.2.840.113549.2.7" +#define MAC_OID_SHA224 "1.2.840.113549.2.8" +#define MAC_OID_SHA256 "1.2.840.113549.2.9" +#define MAC_OID_SHA384 "1.2.840.113549.2.10" +#define MAC_OID_SHA512 "1.2.840.113549.2.11" + static const mac_entry_st hash_algorithms[] = { - {"SHA1", HASH_OID_SHA1, GNUTLS_MAC_SHA1, 20, 20, 0, 0, 1, 64}, - {"MD5", HASH_OID_MD5, GNUTLS_MAC_MD5, 16, 16, 0, 0, 0, 64}, - {"SHA256", HASH_OID_SHA256, GNUTLS_MAC_SHA256, 32, 32, 0, 0, 1, + {"SHA1", HASH_OID_SHA1, MAC_OID_SHA1, GNUTLS_MAC_SHA1, 20, 20, 0, 0, 1, 64}, + {"MD5", HASH_OID_MD5, NULL, GNUTLS_MAC_MD5, 16, 16, 0, 0, 0, 64}, + {"SHA256", HASH_OID_SHA256, MAC_OID_SHA256, GNUTLS_MAC_SHA256, 32, 32, 0, 0, 1, 64}, - {"SHA384", HASH_OID_SHA384, GNUTLS_MAC_SHA384, 48, 48, 0, 0, 1, + {"SHA384", HASH_OID_SHA384, MAC_OID_SHA384, GNUTLS_MAC_SHA384, 48, 48, 0, 0, 1, 64}, - {"SHA512", HASH_OID_SHA512, GNUTLS_MAC_SHA512, 64, 64, 0, 0, 1, + {"SHA512", HASH_OID_SHA512, MAC_OID_SHA512, GNUTLS_MAC_SHA512, 64, 64, 0, 0, 1, 64}, - {"SHA224", HASH_OID_SHA224, GNUTLS_MAC_SHA224, 28, 28, 0, 0, 1, + {"SHA224", HASH_OID_SHA224, MAC_OID_SHA224, GNUTLS_MAC_SHA224, 28, 28, 0, 0, 1, 64}, - {"SHA3-256", HASH_OID_SHA3_256, GNUTLS_MAC_SHA3_256, 32, 32, 0, 0, 1, + {"SHA3-256", HASH_OID_SHA3_256, NULL, GNUTLS_MAC_SHA3_256, 32, 32, 0, 0, 1, 136}, - {"SHA3-384", HASH_OID_SHA3_384, GNUTLS_MAC_SHA3_384, 48, 48, 0, 0, 1, + {"SHA3-384", HASH_OID_SHA3_384, NULL, GNUTLS_MAC_SHA3_384, 48, 48, 0, 0, 1, 104}, - {"SHA3-512", HASH_OID_SHA3_512, GNUTLS_MAC_SHA3_512, 64, 64, 0, 0, 1, + {"SHA3-512", HASH_OID_SHA3_512, NULL, GNUTLS_MAC_SHA3_512, 64, 64, 0, 0, 1, 72}, - {"SHA3-224", HASH_OID_SHA3_224, GNUTLS_MAC_SHA3_224, 28, 28, 0, 0, 1, + {"SHA3-224", HASH_OID_SHA3_224, NULL, GNUTLS_MAC_SHA3_224, 28, 28, 0, 0, 1, 144}, - {"UMAC-96", NULL, GNUTLS_MAC_UMAC_96, 12, 16, 8, 0, 1, 0}, - {"UMAC-128", NULL, GNUTLS_MAC_UMAC_128, 16, 16, 8, 0, 1, 0}, - {"AEAD", NULL, GNUTLS_MAC_AEAD, 0, 0, 0, 1, 1, 0}, - {"MD2", HASH_OID_MD2, GNUTLS_MAC_MD2, 0, 0, 0, 0, 0, 0}, /* not used as MAC */ - {"RIPEMD160", HASH_OID_RMD160, GNUTLS_MAC_RMD160, 20, 20, 0, 0, 1, + {"UMAC-96", NULL, NULL, GNUTLS_MAC_UMAC_96, 12, 16, 8, 0, 1, 0}, + {"UMAC-128", NULL, NULL, GNUTLS_MAC_UMAC_128, 16, 16, 8, 0, 1, 0}, + {"AEAD", NULL, NULL, GNUTLS_MAC_AEAD, 0, 0, 0, 1, 1, 0}, + {"MD2", HASH_OID_MD2, NULL, GNUTLS_MAC_MD2, 0, 0, 0, 0, 0, 0}, /* not used as MAC */ + {"RIPEMD160", HASH_OID_RMD160, NULL, GNUTLS_MAC_RMD160, 20, 20, 0, 0, 1, 64}, - {"MAC-NULL", NULL, GNUTLS_MAC_NULL, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0} + {"MAC-NULL", NULL, NULL, GNUTLS_MAC_NULL, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0, 0} }; @@ -301,6 +307,35 @@ gnutls_digest_algorithm_t gnutls_oid_to_digest(const char *oid) } /** + * gnutls_oid_to_mac: + * @oid: is an object identifier + * + * Converts a textual object identifier typically from PKCS#5 values to a #gnutls_mac_algorithm_t value. + * + * Returns: a #gnutls_mac_algorithm_t id of the specified digest + * algorithm, or %GNUTLS_MAC_UNKNOWN on failure. + * + * Since: 3.5.4 + **/ +gnutls_mac_algorithm_t gnutls_oid_to_mac(const char *oid) +{ + gnutls_digest_algorithm_t ret = 0; + + GNUTLS_HASH_LOOP( + if (p->mac_oid && strcmp(oid, p->mac_oid) == 0) { + if (_gnutls_mac_exists(p->id)) { + ret = p->id; + } + break; + } + ); + + if (ret == 0) + return GNUTLS_MAC_UNKNOWN; + return ret; +} + +/** * gnutls_digest_get_oid: * @algorithm: is a digest algorithm * diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h index f7739aedab..a984b49c7f 100644 --- a/lib/gnutls_int.h +++ b/lib/gnutls_int.h @@ -469,6 +469,7 @@ typedef struct gnutls_cipher_suite_entry_st { typedef struct mac_entry_st { const char *name; const char *oid; /* OID of the hash - if it is a hash */ + const char *mac_oid; /* OID of the MAC algorithm - if it is a MAC */ gnutls_mac_algorithm_t id; unsigned output_size; unsigned key_size; diff --git a/lib/includes/gnutls/gnutls.h.in b/lib/includes/gnutls/gnutls.h.in index 5cda33fcaa..20a13c9aca 100644 --- a/lib/includes/gnutls/gnutls.h.in +++ b/lib/includes/gnutls/gnutls.h.in @@ -1018,6 +1018,8 @@ gnutls_pk_algorithm_t gnutls_ecc_curve_get_pk(gnutls_ecc_curve_t curve) __GNUTLS gnutls_digest_algorithm_t gnutls_oid_to_digest(const char *oid) __GNUTLS_CONST__; +gnutls_mac_algorithm_t + gnutls_oid_to_mac(const char *oid) __GNUTLS_CONST__; gnutls_pk_algorithm_t gnutls_oid_to_pk(const char *oid) __GNUTLS_CONST__; gnutls_sign_algorithm_t diff --git a/lib/libgnutls.map b/lib/libgnutls.map index de2d0f6d2b..ef802043c6 100644 --- a/lib/libgnutls.map +++ b/lib/libgnutls.map @@ -1103,6 +1103,7 @@ GNUTLS_3_4 gnutls_x509_crq_set_extension_by_oid; gnutls_x509_dn_set_str; gnutls_transport_set_fastopen; + gnutls_oid_to_mac; local: *; }; diff --git a/lib/x509/pkcs12.c b/lib/x509/pkcs12.c index e39dcde790..053df4543d 100644 --- a/lib/x509/pkcs12.c +++ b/lib/x509/pkcs12.c @@ -1043,7 +1043,7 @@ int gnutls_pkcs12_verify_mac(gnutls_pkcs12_t pkcs12, const char *pass) return _gnutls_asn2err(result); } - algo = _gnutls_x509_oid_to_mac(oid); + algo = gnutls_oid_to_digest(oid); if (algo == GNUTLS_MAC_UNKNOWN) { unknown_mac: gnutls_assert(); @@ -1866,7 +1866,7 @@ gnutls_pkcs12_mac_info(gnutls_pkcs12_t pkcs12, unsigned int *mac, *oid = (char*)tmp.data; } - algo = _gnutls_x509_oid_to_mac((char*)tmp.data); + algo = gnutls_oid_to_digest((char*)tmp.data); if (algo == GNUTLS_MAC_UNKNOWN || mac_to_entry(algo) == NULL) { gnutls_assert(); return GNUTLS_E_UNKNOWN_HASH_ALGORITHM; diff --git a/lib/x509/privkey_pkcs8.c b/lib/x509/privkey_pkcs8.c index f84d913e87..f5a5d64820 100644 --- a/lib/x509/privkey_pkcs8.c +++ b/lib/x509/privkey_pkcs8.c @@ -866,14 +866,12 @@ read_pkcs_schema_params(schema_id * schema, const char *password, result = read_pbkdf2_params(pbes2_asn, &tmp, kdf_params); if (result < 0) { gnutls_assert(); - result = _gnutls_asn2err(result); goto error; } result = read_pbe_enc_params(pbes2_asn, &tmp, enc_params); if (result < 0) { gnutls_assert(); - result = _gnutls_asn2err(result); goto error; } @@ -1543,6 +1541,8 @@ read_pbkdf2_params(ASN1_TYPE pbes2_asn, memset(params, 0, sizeof(*params)); + params->mac = GNUTLS_MAC_SHA1; + /* Check the key derivation algorithm */ len = sizeof(oid); @@ -1626,8 +1626,23 @@ read_pbkdf2_params(ASN1_TYPE pbes2_asn, } _gnutls_hard_log("keyLength: %d\n", params->key_size); - /* We don't read the PRF. We only use the default. - */ + len = sizeof(oid); + result = + asn1_read_value(pbkdf2_asn, "prf.algorithm", + oid, &len); + if (result != ASN1_SUCCESS) { + /* use the default MAC */ + result = 0; + goto error; + } + + params->mac = gnutls_oid_to_mac(oid); + if (params->mac == GNUTLS_MAC_UNKNOWN) { + gnutls_assert(); + _gnutls_debug_log("Unsupported hash algorithm: %s\n", oid); + result = GNUTLS_E_UNKNOWN_HASH_ALGORITHM; + goto error; + } result = 0; @@ -1738,13 +1753,13 @@ read_pbe_enc_params(ASN1_TYPE pbes2_asn, &len); if (result != ASN1_SUCCESS) { gnutls_assert(); - goto error; + return _gnutls_asn2err(result); } _gnutls_hard_log("encryptionScheme.algorithm: %s\n", oid); if ((result = pbes2_oid_to_cipher(oid, ¶ms->cipher)) < 0) { gnutls_assert(); - goto error; + return result; } result = @@ -1842,10 +1857,17 @@ decrypt_data(schema_id schema, ASN1_TYPE pkcs8_asn, p = pbes2_schema_get(schema); if (p != NULL && p->pbes2 != 0) { /* PBES2 */ - pbkdf2_hmac_sha1(pass_len, (uint8_t*)password, - kdf_params->iter_count, - kdf_params->salt_size, kdf_params->salt, - key_size, key); + if (kdf_params->mac == GNUTLS_MAC_SHA1) + pbkdf2_hmac_sha1(pass_len, (uint8_t*)password, + kdf_params->iter_count, + kdf_params->salt_size, kdf_params->salt, + key_size, key); + else if (kdf_params->mac == GNUTLS_MAC_SHA256) + pbkdf2_hmac_sha256(pass_len, (uint8_t*)password, + kdf_params->iter_count, + kdf_params->salt_size, kdf_params->salt, + key_size, key); + else return gnutls_assert_val(GNUTLS_E_UNKNOWN_HASH_ALGORITHM); } else if (p != NULL) { /* PKCS 12 schema */ result = _gnutls_pkcs12_string_to_key(mac_to_entry(GNUTLS_MAC_SHA1), diff --git a/lib/x509/x509_int.h b/lib/x509/x509_int.h index eece7bcc42..3eced08b5d 100644 --- a/lib/x509/x509_int.h +++ b/lib/x509/x509_int.h @@ -114,6 +114,7 @@ struct pbkdf2_params { int salt_size; unsigned int iter_count; unsigned int key_size; + gnutls_mac_algorithm_t mac; }; typedef struct gnutls_x509_privkey_int { |