openssl: add openssl_hmac_many()

Add function to perform HMAC on multiple buffers.

Also update test-openssl with associated testing, and replace some memcmp()
with memcmp_nn().
This commit is contained in:
Dan Streetman
2023-09-28 16:44:42 -04:00
parent 11f7bc5e9c
commit a95e8fa2a3
3 changed files with 197 additions and 8 deletions
+97
View File
@@ -139,6 +139,103 @@ int openssl_digest_many(
return 0;
}
/* Calculate the HMAC digest hash value for the provided data, using the provided key and specified digest
* algorithm. Returns 0 on success, -EOPNOTSUPP if the digest algorithm is not supported, or < 0 for any
* other error. */
int openssl_hmac_many(
const char *digest_alg,
const void *key,
size_t key_size,
const struct iovec data[],
size_t n_data,
void **ret_digest,
size_t *ret_digest_size) {
assert(digest_alg);
assert(key);
assert(data || n_data == 0);
assert(ret_digest);
/* ret_digest_size is optional, as caller may already know the digest size */
#if OPENSSL_VERSION_MAJOR >= 3
_cleanup_(EVP_MD_freep) EVP_MD *md = EVP_MD_fetch(NULL, digest_alg, NULL);
#else
const EVP_MD *md = EVP_get_digestbyname(digest_alg);
#endif
if (!md)
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
"Digest algorithm '%s' not supported.", digest_alg);
#if OPENSSL_VERSION_MAJOR >= 3
_cleanup_(EVP_MAC_freep) EVP_MAC *mac = EVP_MAC_fetch(NULL, "HMAC", NULL);
if (!mac)
return log_openssl_errors("Failed to create new EVP_MAC");
_cleanup_(EVP_MAC_CTX_freep) EVP_MAC_CTX *ctx = EVP_MAC_CTX_new(mac);
if (!ctx)
return log_openssl_errors("Failed to create new EVP_MAC_CTX");
_cleanup_(OSSL_PARAM_BLD_freep) OSSL_PARAM_BLD *bld = OSSL_PARAM_BLD_new();
if (!bld)
return log_openssl_errors("Failed to create new OSSL_PARAM_BLD");
if (!OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_MAC_PARAM_DIGEST, (char*) digest_alg, 0))
return log_openssl_errors("Failed to set HMAC OSSL_MAC_PARAM_DIGEST");
_cleanup_(OSSL_PARAM_freep) OSSL_PARAM *params = OSSL_PARAM_BLD_to_param(bld);
if (!params)
return log_openssl_errors("Failed to build HMAC OSSL_PARAM");
if (!EVP_MAC_init(ctx, key, key_size, params))
return log_openssl_errors("Failed to initializate EVP_MAC_CTX");
#else
_cleanup_(HMAC_CTX_freep) HMAC_CTX *ctx = HMAC_CTX_new();
if (!ctx)
return log_openssl_errors("Failed to create new HMAC_CTX");
if (!HMAC_Init_ex(ctx, key, key_size, md, NULL))
return log_openssl_errors("Failed to initialize HMAC_CTX");
#endif
for (size_t i = 0; i < n_data; i++)
#if OPENSSL_VERSION_MAJOR >= 3
if (!EVP_MAC_update(ctx, data[i].iov_base, data[i].iov_len))
#else
if (!HMAC_Update(ctx, data[i].iov_base, data[i].iov_len))
#endif
return log_openssl_errors("Failed to update HMAC");
size_t digest_size;
#if OPENSSL_VERSION_MAJOR >= 3
digest_size = EVP_MAC_CTX_get_mac_size(ctx);
#else
digest_size = HMAC_size(ctx);
#endif
if (digest_size == 0)
return log_openssl_errors("Failed to get HMAC digest size");
_cleanup_free_ void *buf = malloc(digest_size);
if (!buf)
return log_oom_debug();
#if OPENSSL_VERSION_MAJOR >= 3
size_t size;
if (!EVP_MAC_final(ctx, buf, &size, digest_size))
#else
unsigned int size;
if (!HMAC_Final(ctx, buf, &size))
#endif
return log_openssl_errors("Failed to finalize HMAC");
assert(size == digest_size);
*ret_digest = TAKE_PTR(buf);
if (ret_digest_size)
*ret_digest_size = size;
return 0;
}
int rsa_encrypt_bytes(
EVP_PKEY *pkey,
const void *decrypted_key,
+9
View File
@@ -40,11 +40,14 @@ DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(SSL*, SSL_free, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(BIO*, BIO_free, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EVP_MD_CTX*, EVP_MD_CTX_free, NULL);
#if OPENSSL_VERSION_MAJOR >= 3
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EVP_MAC*, EVP_MAC_free, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EVP_MAC_CTX*, EVP_MAC_CTX_free, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EVP_MD*, EVP_MD_free, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(OSSL_PARAM*, OSSL_PARAM_free, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(OSSL_PARAM_BLD*, OSSL_PARAM_BLD_free, NULL);
#else
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EC_KEY*, EC_KEY_free, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(HMAC_CTX*, HMAC_CTX_free, NULL);
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(RSA*, RSA_free, NULL);
#endif
@@ -65,6 +68,12 @@ static inline int openssl_digest(const char *digest_alg, const void *buf, size_t
return openssl_digest_many(digest_alg, &IOVEC_MAKE((void*) buf, len), 1, ret_digest, ret_digest_size);
}
int openssl_hmac_many(const char *digest_alg, const void *key, size_t key_size, const struct iovec data[], size_t n_data, void **ret_digest, size_t *ret_digest_size);
static inline int openssl_hmac(const char *digest_alg, const void *key, size_t key_size, const void *buf, size_t len, void **ret_digest, size_t *ret_digest_size) {
return openssl_hmac_many(digest_alg, key, key_size, &IOVEC_MAKE((void*) buf, len), 1, ret_digest, ret_digest_size);
}
int rsa_encrypt_bytes(EVP_PKEY *pkey, const void *decrypted_key, size_t decrypted_key_size, void **ret_encrypt_key, size_t *ret_encrypt_key_size);
int rsa_pkey_to_suitable_key_size(EVP_PKEY *pkey, size_t *ret_suitable_key_size);