]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
pkcs12: Allow verification with structures that support other than HMAC-SHA1 MACs.
authorNikos Mavrogiannopoulos <nmav@gnutls.org>
Sun, 10 Aug 2014 08:28:57 +0000 (10:28 +0200)
committerNikos Mavrogiannopoulos <nmav@gnutls.org>
Sun, 10 Aug 2014 10:08:07 +0000 (12:08 +0200)
lib/algorithms.h
lib/x509/pkcs12.c
lib/x509/pkcs12_encr.c
lib/x509/privkey_pkcs8.c
lib/x509/x509_int.h

index ae7bbae61971b67bf2e565d32669fea10c1b0406..93062fc9b76953440b23dfaae4a7a3050e9f1172 100644 (file)
@@ -135,6 +135,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. */
index 2303166f8c86f1790695c9d559b1d6eb58a78d9d..e7d1e32105e12de0c48732a78e6f04f0a9bfa97c 100644 (file)
@@ -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;
        }
index c7ac7fb810f06e4b4c794e65dd4cfc4e129579c2..85cd3f228fa22cf52435628d0df0a02fce0195df 100644 (file)
@@ -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,14 @@ _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_DIG_SHA1, hash, 20,
+                       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 +153,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_init_scan(&num_b1, buf_b, n);
                if (rc < 0) {
index 753a239168623cde0ebdbdb048fb1d9ec5850da6..20db7218786dd33a5869a5ac9c14041bafcd967a 100644 (file)
@@ -926,7 +926,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,
@@ -1833,7 +1834,8 @@ decrypt_data(schema_id schema, ASN1_TYPE pkcs8_asn,
                                 key_size, key);
        } else if (p != NULL) { /* PKCS 12 schema */
                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,
@@ -2139,7 +2141,8 @@ generate_key(schema_id schema,
                }
        } else { /* PKCS 12 schema */
                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,
@@ -2155,7 +2158,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,
index 69f1348e58eaa9b7b98e2148a15f377e58b496ba..820b62c1f2630dc99b5142f2f8380e137632d898 100644 (file)
@@ -334,7 +334,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);