static inline int mac_init (digest_hd_st * td, gnutls_mac_algorithm_t mac, opaque * secret, int secret_size, int ver) { int ret = 0; if (mac == GNUTLS_MAC_NULL) { return GNUTLS_E_HASH_FAILED; } if (ver == GNUTLS_SSL3) { /* SSL 3.0 */ ret = _gnutls_mac_init_ssl3 (td, mac, secret, secret_size); } else { /* TLS 1.x */ ret = _gnutls_hmac_init (td, mac, secret, secret_size); } return ret; }
/** * gnutls_pkcs12_verify_mac: * @pkcs12: should contain a gnutls_pkcs12_t structure * @pass: The password for the MAC * * This function will verify the MAC for the PKCS12 structure. * * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a * negative error value. **/ int gnutls_pkcs12_verify_mac (gnutls_pkcs12_t pkcs12, const char *pass) { opaque key[20]; int result; unsigned int iter; int len; digest_hd_st td1; gnutls_datum_t tmp = { NULL, 0 }, salt = { NULL, 0}; opaque sha_mac[20]; opaque sha_mac_orig[20]; if (pkcs12 == NULL) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } /* read the iterations */ result = _gnutls_x509_read_uint (pkcs12->pkcs12, "macData.iterations", &iter); if (result < 0) { iter = 1; /* the default */ } /* Read the salt from the structure. */ result = _gnutls_x509_read_value (pkcs12->pkcs12, "macData.macSalt", &salt, 0); if (result != ASN1_SUCCESS) { 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); if (result < 0) { gnutls_assert (); goto cleanup; } _gnutls_free_datum (&salt); /* Get the data to be MACed */ result = _decode_pkcs12_auth_safe (pkcs12->pkcs12, NULL, &tmp); if (result < 0) { gnutls_assert (); goto cleanup; } /* MAC the data */ result = _gnutls_hmac_init (&td1, GNUTLS_MAC_SHA1, key, sizeof (key)); if (result < 0) { gnutls_assert (); goto cleanup; } _gnutls_hmac (&td1, tmp.data, tmp.size); _gnutls_free_datum (&tmp); _gnutls_hmac_deinit (&td1, sha_mac); len = sizeof (sha_mac_orig); result = asn1_read_value (pkcs12->pkcs12, "macData.mac.digest", sha_mac_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) { gnutls_assert (); return GNUTLS_E_MAC_VERIFY_FAILED; } return 0; cleanup: _gnutls_free_datum (&tmp); _gnutls_free_datum (&salt); return result; }
/** * gnutls_pkcs12_generate_mac: * @pkcs12: should contain a gnutls_pkcs12_t structure * @pass: The password for the MAC * * This function will generate a MAC for the PKCS12 structure. * * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a * negative error value. **/ int gnutls_pkcs12_generate_mac (gnutls_pkcs12_t pkcs12, const char *pass) { opaque salt[8], key[20]; int result; const int iter = 1; digest_hd_st td1; gnutls_datum_t tmp = { NULL, 0 }; opaque sha_mac[20]; if (pkcs12 == NULL) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } /* Generate the salt. */ result = _gnutls_rnd (GNUTLS_RND_NONCE, salt, sizeof (salt)); if (result < 0) { gnutls_assert (); return result; } /* Write the salt into the structure. */ result = asn1_write_value (pkcs12->pkcs12, "macData.macSalt", salt, sizeof (salt)); if (result != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } /* write the iterations */ if (iter > 1) { result = _gnutls_x509_write_uint32 (pkcs12->pkcs12, "macData.iterations", iter); if (result < 0) { gnutls_assert (); goto cleanup; } } /* Generate the key. */ result = _gnutls_pkcs12_string_to_key (3 /*MAC*/, salt, sizeof (salt), iter, pass, sizeof (key), key); if (result < 0) { gnutls_assert (); goto cleanup; } /* Get the data to be MACed */ result = _decode_pkcs12_auth_safe (pkcs12->pkcs12, NULL, &tmp); if (result < 0) { gnutls_assert (); goto cleanup; } /* MAC the data */ result = _gnutls_hmac_init (&td1, GNUTLS_MAC_SHA1, key, sizeof (key)); if (result < 0) { gnutls_assert (); goto cleanup; } _gnutls_hmac (&td1, tmp.data, tmp.size); _gnutls_free_datum (&tmp); _gnutls_hmac_deinit (&td1, sha_mac); result = asn1_write_value (pkcs12->pkcs12, "macData.mac.digest", sha_mac, sizeof (sha_mac)); if (result != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } result = asn1_write_value (pkcs12->pkcs12, "macData.mac.digestAlgorithm.parameters", NULL, 0); if (result != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } result = asn1_write_value (pkcs12->pkcs12, "macData.mac.digestAlgorithm.algorithm", HASH_OID_SHA1, 1); if (result != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } return 0; cleanup: _gnutls_free_datum (&tmp); return result; }