summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2014-08-10 10:28:57 +0200
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2014-08-10 13:28:29 +0200
commitd9eff7f6010f8237f3549e304bf62823807b64d6 (patch)
tree6b68dd71c0190afdb245477031ee92991f19d03b
parent46d911df71019294893c0767a21b1be129b3edf4 (diff)
downloadgnutls-d9eff7f6010f8237f3549e304bf62823807b64d6.tar.gz
pkcs12: Allow verification with structures that support other than HMAC-SHA1 MACs.
Conflicts: lib/x509/pkcs12_encr.c
-rw-r--r--lib/algorithms.h1
-rw-r--r--lib/x509/pkcs12.c57
-rw-r--r--lib/x509/pkcs12_encr.c16
-rw-r--r--lib/x509/privkey_pkcs8.c12
-rw-r--r--lib/x509/x509_int.h3
5 files changed, 61 insertions, 28 deletions
diff --git a/lib/algorithms.h b/lib/algorithms.h
index d57e48fd3f..af102cf3a2 100644
--- a/lib/algorithms.h
+++ b/lib/algorithms.h
@@ -134,6 +134,7 @@ 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_x509_oid_to_digest(oid)
gnutls_digest_algorithm_t _gnutls_x509_oid_to_digest(const char *oid);
/* Functions for digests. */
diff --git a/lib/x509/pkcs12.c b/lib/x509/pkcs12.c
index fa86bde000..378eaf0f46 100644
--- a/lib/x509/pkcs12.c
+++ b/lib/x509/pkcs12.c
@@ -840,6 +840,7 @@ int gnutls_pkcs12_generate_mac(gnutls_pkcs12_t pkcs12, const char *pass)
mac_hd_st td1;
gnutls_datum_t tmp = { NULL, 0 };
uint8_t sha_mac[20];
+ const mac_entry_st *me = mac_to_entry(GNUTLS_MAC_SHA1);
if (pkcs12 == NULL) {
gnutls_assert();
@@ -881,7 +882,7 @@ int 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),
+ _gnutls_pkcs12_string_to_key(me, 3 /*MAC*/, salt, sizeof(salt),
iter, pass, sizeof(key), key);
if (result < 0) {
gnutls_assert();
@@ -898,7 +899,7 @@ int gnutls_pkcs12_generate_mac(gnutls_pkcs12_t pkcs12, const char *pass)
/* MAC the data
*/
- result = _gnutls_mac_init(&td1, mac_to_entry(GNUTLS_MAC_SHA1),
+ result = _gnutls_mac_init(&td1, me,
key, sizeof(key));
if (result < 0) {
gnutls_assert();
@@ -959,15 +960,19 @@ int gnutls_pkcs12_generate_mac(gnutls_pkcs12_t pkcs12, const char *pass)
**/
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;
mac_hd_st td1;
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;
+ const mac_entry_st *entry;
if (pkcs12 == NULL) {
gnutls_assert();
@@ -976,7 +981,6 @@ int gnutls_pkcs12_verify_mac(gnutls_pkcs12_t pkcs12, const char *pass)
/* read the iterations
*/
-
result =
_gnutls_x509_read_uint(pkcs12->pkcs12, "macData.iterations",
&iter);
@@ -984,23 +988,44 @@ int 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) {
+ unknown_mac:
+ gnutls_assert();
+ return GNUTLS_E_UNKNOWN_HASH_ALGORITHM;
+ }
+
+ entry = mac_to_entry(algo);
+ if (entry == NULL)
+ goto unknown_mac;
+
+ mac_len = _gnutls_mac_get_algo_len(entry);
+ 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);
+ _gnutls_pkcs12_string_to_key(entry, 3 /*MAC*/, salt.data, salt.size,
+ iter, pass, key_len, key);
if (result < 0) {
gnutls_assert();
goto cleanup;
@@ -1018,8 +1043,7 @@ int gnutls_pkcs12_verify_mac(gnutls_pkcs12_t pkcs12, const char *pass)
/* MAC the data
*/
- result = _gnutls_mac_init(&td1, mac_to_entry(GNUTLS_MAC_SHA1),
- key, sizeof(key));
+ result = _gnutls_mac_init(&td1, entry, key, key_len);
if (result < 0) {
gnutls_assert();
goto cleanup;
@@ -1028,19 +1052,20 @@ int gnutls_pkcs12_verify_mac(gnutls_pkcs12_t pkcs12, const char *pass)
_gnutls_mac(&td1, tmp.data, tmp.size);
_gnutls_free_datum(&tmp);
- _gnutls_mac_deinit(&td1, sha_mac);
+ _gnutls_mac_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, &len);
+ mac_output_orig, &len);
if (result != ASN1_SUCCESS) {
gnutls_assert();
result = _gnutls_asn2err(result);
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 e194ca4884..481189ffb4 100644
--- a/lib/x509/pkcs12_encr.c
+++ b/lib/x509/pkcs12_encr.c
@@ -54,7 +54,8 @@ static int _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(const mac_entry_st * me,
+ unsigned int id, const uint8_t * salt,
unsigned int salt_size, unsigned int iter,
const char *pw, unsigned int req_keylen,
uint8_t * keybuf)
@@ -65,10 +66,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,
@@ -122,9 +124,10 @@ _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_mac_get_algo_len(me);
for (;;) {
- rc = _gnutls_hash_init(&md, mac_to_entry(GNUTLS_MAC_SHA1));
+ rc = _gnutls_hash_init(&md, me);
if (rc < 0) {
gnutls_assert();
goto cleanup;
@@ -134,14 +137,13 @@ _gnutls_pkcs12_string_to_key(unsigned int id, const uint8_t * salt,
_gnutls_hash(&md, buf_i, pw ? i_size : 64);
_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(me->id, 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) {
rc = 0; /* ready */
@@ -150,7 +152,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 53838ca8d5..81c1c09dd8 100644
--- a/lib/x509/privkey_pkcs8.c
+++ b/lib/x509/privkey_pkcs8.c
@@ -829,7 +829,8 @@ read_pkcs_schema_params(schema_id * schema, const char *password,
if (enc_params->iv_size) {
result =
- _gnutls_pkcs12_string_to_key(2 /*IV*/,
+ _gnutls_pkcs12_string_to_key(mac_to_entry(GNUTLS_MAC_SHA1),
+ 2 /*IV*/,
kdf_params->salt,
kdf_params->
salt_size,
@@ -1684,7 +1685,8 @@ decrypt_data(schema_id schema, ASN1_TYPE pkcs8_asn,
break;
default:
result =
- _gnutls_pkcs12_string_to_key(1 /*KEY*/,
+ _gnutls_pkcs12_string_to_key(mac_to_entry(GNUTLS_MAC_SHA1),
+ 1 /*KEY*/,
kdf_params->salt,
kdf_params->salt_size,
kdf_params->iter_count,
@@ -2016,7 +2018,8 @@ generate_key(schema_id schema,
default:
ret =
- _gnutls_pkcs12_string_to_key(1 /*KEY*/,
+ _gnutls_pkcs12_string_to_key(mac_to_entry(GNUTLS_MAC_SHA1),
+ 1 /*KEY*/,
kdf_params->salt,
kdf_params->salt_size,
kdf_params->iter_count,
@@ -2032,7 +2035,8 @@ generate_key(schema_id schema,
*/
if (enc_params->iv_size) {
ret =
- _gnutls_pkcs12_string_to_key(2 /*IV*/,
+ _gnutls_pkcs12_string_to_key(mac_to_entry(GNUTLS_MAC_SHA1),
+ 2 /*IV*/,
kdf_params->salt,
kdf_params->
salt_size,
diff --git a/lib/x509/x509_int.h b/lib/x509/x509_int.h
index 9011869b8e..1648dcdb2a 100644
--- a/lib/x509/x509_int.h
+++ b/lib/x509/x509_int.h
@@ -320,7 +320,8 @@ 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(const mac_entry_st * me,
+ unsigned int id, const uint8_t * salt,
unsigned int salt_size, unsigned int iter,
const char *pw, unsigned int req_keylen,
uint8_t * keybuf);