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:
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user