EVP_MAC: Add HMAC implementation

Reviewed-by: Paul Dale <paul.dale@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/7483)
This commit is contained in:
Richard Levitte 2018-10-24 21:20:00 +02:00
parent 56adb7d937
commit 6723f86746
7 changed files with 250 additions and 2 deletions

View file

@ -15,4 +15,5 @@ void openssl_add_all_macs_int(void)
#ifndef OPENSSL_NO_CMAC
EVP_add_mac(&cmac_meth);
#endif
EVP_add_mac(&hmac_meth);
}

View file

@ -1,3 +1,3 @@
LIBS=../../libcrypto
SOURCE[../../libcrypto]=\
hmac.c hm_ameth.c hm_pmeth.c
hmac.c hm_ameth.c hm_pmeth.c hm_meth.c

173
crypto/hmac/hm_meth.c Normal file
View file

@ -0,0 +1,173 @@
/*
* Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <string.h>
#include <openssl/err.h>
#include <openssl/ossl_typ.h>
#include <openssl/asn1.h>
#include <openssl/hmac.h>
#include "internal/evp_int.h"
/* local HMAC context structure */
/* typedef EVP_MAC_IMPL */
struct evp_mac_impl_st {
/* tmpmd and tmpengine are set to NULL after a CMAC_Init call */
const EVP_MD *tmpmd; /* HMAC digest */
const ENGINE *tmpengine; /* HMAC digest engine */
HMAC_CTX *ctx; /* HMAC context */
};
static EVP_MAC_IMPL *hmac_new(void)
{
EVP_MAC_IMPL *hctx;
if ((hctx = OPENSSL_zalloc(sizeof(*hctx))) == NULL
|| (hctx->ctx = HMAC_CTX_new()) == NULL) {
OPENSSL_free(hctx);
return NULL;
}
return hctx;
}
static void hmac_free(EVP_MAC_IMPL *hctx)
{
if (hctx != NULL) {
HMAC_CTX_free(hctx->ctx);
OPENSSL_free(hctx);
}
}
static int hmac_copy(EVP_MAC_IMPL *hdst, EVP_MAC_IMPL *hsrc)
{
if (!HMAC_CTX_copy(hdst->ctx, hsrc->ctx))
return 0;
hdst->tmpengine = hsrc->tmpengine;
hdst->tmpmd = hsrc->tmpmd;
return 1;
}
static size_t hmac_size(EVP_MAC_IMPL *hctx)
{
return HMAC_size(hctx->ctx);
}
static int hmac_init(EVP_MAC_IMPL *hctx)
{
int rv = 1;
/* HMAC_Init_ex doesn't tolerate all zero params, so we must be careful */
if (hctx->tmpmd != NULL)
rv = HMAC_Init_ex(hctx->ctx, NULL, 0, hctx->tmpmd,
(ENGINE * )hctx->tmpengine);
hctx->tmpengine = NULL;
hctx->tmpmd = NULL;
return rv;
}
static int hmac_update(EVP_MAC_IMPL *hctx, const unsigned char *data,
size_t datalen)
{
return HMAC_Update(hctx->ctx, data, datalen);
}
static int hmac_final(EVP_MAC_IMPL *hctx, unsigned char *out)
{
unsigned int hlen;
return HMAC_Final(hctx->ctx, out, &hlen);
}
static int hmac_ctrl(EVP_MAC_IMPL *hctx, int cmd, va_list args)
{
switch (cmd) {
case EVP_MAC_CTRL_SET_FLAGS:
{
unsigned long flags = va_arg(args, unsigned long);
HMAC_CTX_set_flags(hctx->ctx, flags);
}
break;
case EVP_MAC_CTRL_SET_KEY:
{
const unsigned char *key = va_arg(args, const unsigned char *);
size_t keylen = va_arg(args, size_t);
int rv = HMAC_Init_ex(hctx->ctx, key, keylen, hctx->tmpmd,
(ENGINE *)hctx->tmpengine);
hctx->tmpengine = NULL;
hctx->tmpmd = NULL;
return rv;
}
break;
case EVP_MAC_CTRL_SET_MD:
hctx->tmpmd = va_arg(args, const EVP_MD *);
break;
case EVP_MAC_CTRL_SET_ENGINE:
hctx->tmpengine = va_arg(args, const ENGINE *);
break;
default:
return -2;
}
return 1;
}
static int hmac_ctrl_int(EVP_MAC_IMPL *hctx, int cmd, ...)
{
int rv;
va_list args;
va_start(args, cmd);
rv = hmac_ctrl(hctx, cmd, args);
va_end(args);
return rv;
}
static int hmac_ctrl_str_cb(void *hctx, int cmd, void *buf, size_t buflen)
{
return hmac_ctrl_int(hctx, cmd, buf, buflen);
}
static int hmac_ctrl_str(EVP_MAC_IMPL *hctx, const char *type,
const char *value)
{
if (!value)
return 0;
if (strcmp(type, "digest") == 0) {
const EVP_MD *d = EVP_get_digestbyname(value);
if (d == NULL)
return 0;
return hmac_ctrl_int(hctx, EVP_MAC_CTRL_SET_MD, d);
}
if (strcmp(type, "key") == 0)
return EVP_str2ctrl(hmac_ctrl_str_cb, hctx, EVP_MAC_CTRL_SET_KEY,
value);
if (strcmp(type, "hexkey") == 0)
return EVP_hex2ctrl(hmac_ctrl_str_cb, hctx, EVP_MAC_CTRL_SET_KEY,
value);
return -2;
}
const EVP_MAC hmac_meth = {
EVP_MAC_HMAC,
hmac_new,
hmac_copy,
hmac_free,
hmac_size,
hmac_init,
hmac_update,
hmac_final,
hmac_ctrl,
hmac_ctrl_str
};

View file

@ -129,6 +129,7 @@ struct evp_mac_st {
};
extern const EVP_MAC cmac_meth;
extern const EVP_MAC hmac_meth;
/*
* This function is internal for now, but can be made external when needed.

View file

@ -326,7 +326,8 @@ F<./foo>)
=head1 SEE ALSO
L<EVP_MAC_CMAC(7)>
L<EVP_MAC_CMAC(7)>,
L<EVP_MAC_HMAC(7)>
=head1 COPYRIGHT

71
doc/man7/EVP_MAC_HMAC.pod Normal file
View file

@ -0,0 +1,71 @@
=pod
=head1 NAME
EVP_MAC_HMAC - The HMAC EVP_MAC implementation
=head1 DESCRIPTION
Support for computing HMAC MACs through the B<EVP_MAC> API.
=head2 Numeric identity
B<EVP_MAC_HMAC> is the numeric identity for this implementation, and
can be used in functions like EVP_MAC_CTX_new_id() and
EVP_get_macbynid().
=head2 Supported controls
The supported controls are:
=over 4
=item B<EVP_MAC_CTRL_SET_KEY>
EVP_MAC_ctrl_str() takes to type string for this control:
=over 4
=item "key"
The value string is used as is.
=item "hexkey"
The value string is expected to be a hexadecimal number, which will be
decoded before passing on as control value.
=back
=item B<EVP_MAC_CTRL_SET_FLAGS>
Sets HMAC flags. This is passed directly to HMAC_CTX_set_flags().
There are no corresponding string control types.
=item B<EVP_MAC_CTRL_SET_ENGINE>
=item B<EVP_MAC_CTRL_SET_MD>
These work as described in L<EVP_MAC(3)/CONTROLS>.
EVP_MAC_ctrl_str() type string for B<EVP_MAC_CTRL_SET_DIGEST>: "digest"
The value is expected to be the name of a cipher.
=back
=head1 SEE ALSO
L<EVP_MAC_ctrl(3)>, L<EVP_MAC(3)/CONTROLS>
=head1 COPYRIGHT
Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the OpenSSL license (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
=cut

View file

@ -988,6 +988,7 @@ void EVP_MD_do_all_sorted(void (*fn)
/* MAC stuff */
# define EVP_MAC_CMAC NID_cmac
# define EVP_MAC_HMAC NID_hmac
EVP_MAC_CTX *EVP_MAC_CTX_new(const EVP_MAC *mac);
EVP_MAC_CTX *EVP_MAC_CTX_new_id(int nid);