summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@redhat.com>2016-08-24 13:32:04 +0200
committerNikos Mavrogiannopoulos <nmav@redhat.com>2016-08-24 14:09:43 +0200
commit13893550aa266d55bd5ec6ef395ae48f528b24d5 (patch)
treeec554ab959107a20917924b9e5b45590e2ba42b1
parentdfbe6a74d8172fd69676987e2566b3f521101d3f (diff)
downloadgnutls-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--NEWS4
-rw-r--r--lib/algorithms.h2
-rw-r--r--lib/algorithms/mac.c69
-rw-r--r--lib/gnutls_int.h1
-rw-r--r--lib/includes/gnutls/gnutls.h.in2
-rw-r--r--lib/libgnutls.map1
-rw-r--r--lib/x509/pkcs12.c4
-rw-r--r--lib/x509/privkey_pkcs8.c42
-rw-r--r--lib/x509/x509_int.h1
9 files changed, 95 insertions, 31 deletions
diff --git a/NEWS b/NEWS
index 6a09ac6ab1..0947290816 100644
--- a/NEWS
+++ b/NEWS
@@ -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, &params->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 {