From 6f711afc06bc7d1a1b291bd0a03852cfc7ce99d4 Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos Date: Mon, 11 Aug 2014 10:00:52 +0200 Subject: pkcs11: Allow verification with structures that support other than HMAC-SHA1 MACs. --- lib/algorithms.h | 1 + lib/x509/pkcs12.c | 49 +++++++++++++++++++++++++++++++++++------------- lib/x509/pkcs12_encr.c | 15 +++++++++------ lib/x509/privkey_pkcs8.c | 8 ++++---- lib/x509/x509_int.h | 2 +- 5 files changed, 51 insertions(+), 24 deletions(-) diff --git a/lib/algorithms.h b/lib/algorithms.h index ee88e8c305..5cb9818d2d 100644 --- a/lib/algorithms.h +++ b/lib/algorithms.h @@ -50,6 +50,7 @@ int _gnutls_version_has_explicit_iv (gnutls_protocol_t version); /* Functions for MACs. */ int _gnutls_mac_is_ok (gnutls_mac_algorithm_t algorithm); +#define _gnutls_x509_oid_to_mac(oid) (gnutls_mac_algorithm_t)_gnutls_x509_oid_to_digest(oid) gnutls_digest_algorithm_t _gnutls_x509_oid_to_digest (const char *oid); const char *_gnutls_x509_mac_to_oid (gnutls_mac_algorithm_t mac); diff --git a/lib/x509/pkcs12.c b/lib/x509/pkcs12.c index a7218ca93b..db0f6e3802 100644 --- a/lib/x509/pkcs12.c +++ b/lib/x509/pkcs12.c @@ -918,7 +918,7 @@ gnutls_pkcs12_generate_mac (gnutls_pkcs12_t pkcs12, const char *pass) /* Generate the key. */ - result = _gnutls_pkcs12_string_to_key (3 /*MAC*/, salt, sizeof (salt), + result = _gnutls_pkcs12_string_to_key (GNUTLS_MAC_SHA1, 3 /*MAC*/, salt, sizeof (salt), iter, pass, sizeof (key), key); if (result < 0) { @@ -1001,7 +1001,8 @@ cleanup: int gnutls_pkcs12_verify_mac (gnutls_pkcs12_t pkcs12, const char *pass) { - uint8_t key[20]; + uint8_t key[MAX_HASH_SIZE]; + char oid[MAX_OID_SIZE]; int result; unsigned int iter; int len; @@ -1009,8 +1010,11 @@ gnutls_pkcs12_verify_mac (gnutls_pkcs12_t pkcs12, const char *pass) gnutls_datum_t tmp = { NULL, 0 }, salt = { NULL, 0}; - uint8_t sha_mac[20]; - uint8_t sha_mac_orig[20]; + uint8_t mac_output[MAX_HASH_SIZE]; + uint8_t mac_output_orig[MAX_HASH_SIZE]; + gnutls_mac_algorithm_t algo; + unsigned mac_len, key_len; + if (pkcs12 == NULL) { @@ -1028,22 +1032,40 @@ gnutls_pkcs12_verify_mac (gnutls_pkcs12_t pkcs12, const char *pass) iter = 1; /* the default */ } + len = sizeof(oid); + result = + asn1_read_value(pkcs12->pkcs12, "macData.mac.digestAlgorithm.algorithm", + oid, &len); + if (result != ASN1_SUCCESS) + { + gnutls_assert(); + return _gnutls_asn2err(result); + } + + algo = _gnutls_x509_oid_to_mac(oid); + if (algo == GNUTLS_MAC_UNKNOWN) + { + gnutls_assert(); + return GNUTLS_E_UNKNOWN_HASH_ALGORITHM; + } + + mac_len = _gnutls_hmac_get_algo_len(algo); + key_len = mac_len; /* Read the salt from the structure. */ result = _gnutls_x509_read_value (pkcs12->pkcs12, "macData.macSalt", &salt); - if (result != ASN1_SUCCESS) + if (result < 0) { gnutls_assert (); - result = _gnutls_asn2err (result); goto cleanup; } /* Generate the key. */ - result = _gnutls_pkcs12_string_to_key (3 /*MAC*/, salt.data, salt.size, - iter, pass, sizeof (key), key); + result = _gnutls_pkcs12_string_to_key (algo, 3 /*MAC*/, salt.data, salt.size, + iter, pass, key_len, key); if (result < 0) { gnutls_assert (); @@ -1063,7 +1085,7 @@ gnutls_pkcs12_verify_mac (gnutls_pkcs12_t pkcs12, const char *pass) /* MAC the data */ - result = _gnutls_hmac_init (&td1, GNUTLS_MAC_SHA1, key, sizeof (key)); + result = _gnutls_hmac_init (&td1, algo, key, key_len); if (result < 0) { gnutls_assert (); @@ -1073,11 +1095,11 @@ gnutls_pkcs12_verify_mac (gnutls_pkcs12_t pkcs12, const char *pass) _gnutls_hmac (&td1, tmp.data, tmp.size); _gnutls_free_datum (&tmp); - _gnutls_hmac_deinit (&td1, sha_mac); + _gnutls_hmac_deinit (&td1, mac_output); - len = sizeof (sha_mac_orig); + len = sizeof (mac_output_orig); result = - asn1_read_value (pkcs12->pkcs12, "macData.mac.digest", sha_mac_orig, + asn1_read_value (pkcs12->pkcs12, "macData.mac.digest", mac_output_orig, &len); if (result != ASN1_SUCCESS) { @@ -1086,7 +1108,8 @@ gnutls_pkcs12_verify_mac (gnutls_pkcs12_t pkcs12, const char *pass) goto cleanup; } - if (memcmp (sha_mac_orig, sha_mac, sizeof (sha_mac)) != 0) + if ((unsigned)len != mac_len || + memcmp (mac_output_orig, mac_output, len) != 0) { gnutls_assert (); return GNUTLS_E_MAC_VERIFY_FAILED; diff --git a/lib/x509/pkcs12_encr.c b/lib/x509/pkcs12_encr.c index cdb86f6fee..86e5bf0b71 100644 --- a/lib/x509/pkcs12_encr.c +++ b/lib/x509/pkcs12_encr.c @@ -55,7 +55,8 @@ _pkcs12_check_pass (const char *pass, size_t plen) * NULL password, and for the password with zero length. */ int -_gnutls_pkcs12_string_to_key (unsigned int id, const uint8_t * salt, +_gnutls_pkcs12_string_to_key (gnutls_mac_algorithm_t algo, + unsigned int id, const uint8_t * salt, unsigned int salt_size, unsigned int iter, const char *pw, unsigned int req_keylen, uint8_t * keybuf) @@ -66,10 +67,11 @@ _gnutls_pkcs12_string_to_key (unsigned int id, const uint8_t * salt, bigint_t num_b1 = NULL, num_ij = NULL; bigint_t mpi512 = NULL; unsigned int pwlen; - uint8_t hash[20], buf_b[64], buf_i[MAX_PASS_LEN*2+64], *p; + uint8_t hash[MAX_HASH_SIZE], buf_b[64], buf_i[MAX_PASS_LEN*2+64], *p; uint8_t d[64]; size_t cur_keylen; size_t n, m, p_size, i_size; + unsigned mac_len; const uint8_t buf_512[] = /* 2^64 */ { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -129,10 +131,11 @@ _gnutls_pkcs12_string_to_key (unsigned int id, const uint8_t * salt, memset (p, 0, p_size); i_size = 64+p_size; + mac_len = _gnutls_hmac_get_algo_len(algo); for (;;) { - rc = _gnutls_hash_init (&md, GNUTLS_MAC_SHA1); + rc = _gnutls_hash_init (&md, algo); if (rc < 0) { gnutls_assert (); @@ -144,14 +147,14 @@ _gnutls_pkcs12_string_to_key (unsigned int id, const uint8_t * salt, _gnutls_hash_deinit (&md, hash); for (i = 1; i < iter; i++) { - rc = _gnutls_hash_fast (GNUTLS_MAC_SHA1, hash, 20, hash); + rc = _gnutls_hash_fast (algo, hash, mac_len, hash); if (rc < 0) { gnutls_assert (); goto cleanup; } } - for (i = 0; i < 20 && cur_keylen < req_keylen; i++) + for (i = 0; i < mac_len && cur_keylen < req_keylen; i++) keybuf[cur_keylen++] = hash[i]; if (cur_keylen == req_keylen) { @@ -161,7 +164,7 @@ _gnutls_pkcs12_string_to_key (unsigned int id, const uint8_t * salt, /* need more bytes. */ for (i = 0; i < 64; i++) - buf_b[i] = hash[i % 20]; + buf_b[i] = hash[i % mac_len]; n = 64; rc = _gnutls_mpi_scan (&num_b1, buf_b, n); if (rc < 0) diff --git a/lib/x509/privkey_pkcs8.c b/lib/x509/privkey_pkcs8.c index 205b74c00a..bba8f47114 100644 --- a/lib/x509/privkey_pkcs8.c +++ b/lib/x509/privkey_pkcs8.c @@ -873,7 +873,7 @@ read_pkcs_schema_params (schema_id * schema, const char *password, if (enc_params->iv_size) { result = - _gnutls_pkcs12_string_to_key (2 /*IV*/, kdf_params->salt, + _gnutls_pkcs12_string_to_key (GNUTLS_MAC_SHA1, 2 /*IV*/, kdf_params->salt, kdf_params->salt_size, kdf_params->iter_count, password, enc_params->iv_size, @@ -1767,7 +1767,7 @@ decrypt_data (schema_id schema, ASN1_TYPE pkcs8_asn, break; default: result = - _gnutls_pkcs12_string_to_key (1 /*KEY*/, kdf_params->salt, + _gnutls_pkcs12_string_to_key (GNUTLS_MAC_SHA1, 1 /*KEY*/, kdf_params->salt, kdf_params->salt_size, kdf_params->iter_count, password, key_size, key); @@ -2113,7 +2113,7 @@ generate_key (schema_id schema, default: ret = - _gnutls_pkcs12_string_to_key (1 /*KEY*/, kdf_params->salt, + _gnutls_pkcs12_string_to_key (GNUTLS_MAC_SHA1, 1 /*KEY*/, kdf_params->salt, kdf_params->salt_size, kdf_params->iter_count, password, kdf_params->key_size, key->data); @@ -2128,7 +2128,7 @@ generate_key (schema_id schema, if (enc_params->iv_size) { ret = - _gnutls_pkcs12_string_to_key (2 /*IV*/, kdf_params->salt, + _gnutls_pkcs12_string_to_key (GNUTLS_MAC_SHA1, 2 /*IV*/, kdf_params->salt, kdf_params->salt_size, kdf_params->iter_count, password, enc_params->iv_size, diff --git a/lib/x509/x509_int.h b/lib/x509/x509_int.h index 8d6f766067..11f4711292 100644 --- a/lib/x509/x509_int.h +++ b/lib/x509/x509_int.h @@ -322,7 +322,7 @@ typedef struct gnutls_pkcs12_bag_int #define KEY_ID_OID "1.2.840.113549.1.9.21" int -_gnutls_pkcs12_string_to_key (unsigned int id, const uint8_t * salt, +_gnutls_pkcs12_string_to_key (gnutls_mac_algorithm_t, unsigned int id, const uint8_t * salt, unsigned int salt_size, unsigned int iter, const char *pw, unsigned int req_keylen, uint8_t * keybuf); -- cgit v1.2.1