EVP_MAC: Add CMAC implementation

Reviewed-by: Paul Dale <paul.dale@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/7484)
This commit is contained in:
Richard Levitte 2018-10-24 21:30:00 +02:00
parent cf4eea1204
commit f71faf2753
7 changed files with 237 additions and 9 deletions

View file

@ -1,2 +1,2 @@
LIBS=../../libcrypto
SOURCE[../../libcrypto]=cmac.c cm_ameth.c cm_pmeth.c
SOURCE[../../libcrypto]=cmac.c cm_ameth.c cm_pmeth.c cm_meth.c

164
crypto/cmac/cm_meth.c Normal file
View file

@ -0,0 +1,164 @@
/*
* 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 <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include <openssl/evp.h>
#include <openssl/cmac.h>
#include "internal/evp_int.h"
/* local CMAC pkey structure */
/* typedef EVP_MAC_IMPL */
struct evp_mac_impl_st {
/* tmpcipher and tmpengine are set to NULL after a CMAC_Init call */
const EVP_CIPHER *tmpcipher; /* cached CMAC cipher */
const ENGINE *tmpengine; /* cached CMAC cipher engine */
CMAC_CTX *ctx;
};
static EVP_MAC_IMPL *cmac_new(void)
{
EVP_MAC_IMPL *cctx;
if ((cctx = OPENSSL_zalloc(sizeof(*cctx))) == NULL
|| (cctx->ctx = CMAC_CTX_new()) == NULL) {
OPENSSL_free(cctx);
cctx = NULL;
}
return cctx;
}
static void cmac_free(EVP_MAC_IMPL *cctx)
{
if (cctx != NULL) {
CMAC_CTX_free(cctx->ctx);
OPENSSL_free(cctx);
}
}
static int cmac_copy(EVP_MAC_IMPL *cdst, EVP_MAC_IMPL *csrc)
{
if (!CMAC_CTX_copy(cdst->ctx, csrc->ctx))
return 0;
cdst->tmpengine = csrc->tmpengine;
cdst->tmpcipher = csrc->tmpcipher;
return 1;
}
static size_t cmac_size(EVP_MAC_IMPL *cctx)
{
return EVP_CIPHER_CTX_block_size(CMAC_CTX_get0_cipher_ctx(cctx->ctx));
}
static int cmac_init(EVP_MAC_IMPL *cctx)
{
int rv = CMAC_Init(cctx->ctx, NULL, 0, cctx->tmpcipher,
(ENGINE *)cctx->tmpengine);
cctx->tmpcipher = NULL;
cctx->tmpengine = NULL;
return rv;
}
static int cmac_update(EVP_MAC_IMPL *cctx, const unsigned char *data,
size_t datalen)
{
return CMAC_Update(cctx->ctx, data, datalen);
}
static int cmac_final(EVP_MAC_IMPL *cctx, unsigned char *out)
{
size_t hlen;
return CMAC_Final(cctx->ctx, out, &hlen);
}
static int cmac_ctrl(EVP_MAC_IMPL *cctx, int cmd, va_list args)
{
switch (cmd) {
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 = CMAC_Init(cctx->ctx, key, keylen, cctx->tmpcipher,
(ENGINE *)cctx->tmpengine);
cctx->tmpcipher = NULL;
cctx->tmpengine = NULL;
return rv;
}
break;
case EVP_MAC_CTRL_SET_CIPHER:
cctx->tmpcipher = va_arg(args, const EVP_CIPHER *);
break;
case EVP_MAC_CTRL_SET_ENGINE:
cctx->tmpengine = va_arg(args, const ENGINE *);
break;
default:
return -2;
}
return 1;
}
static int cmac_ctrl_int(EVP_MAC_IMPL *hctx, int cmd, ...)
{
int rv;
va_list args;
va_start(args, cmd);
rv = cmac_ctrl(hctx, cmd, args);
va_end(args);
return rv;
}
static int cmac_ctrl_str_cb(void *hctx, int cmd, void *buf, size_t buflen)
{
return cmac_ctrl_int(hctx, cmd, buf, buflen);
}
static int cmac_ctrl_str(EVP_MAC_IMPL *cctx, const char *type,
const char *value)
{
if (!value)
return 0;
if (strcmp(type, "cipher") == 0) {
const EVP_CIPHER *c = EVP_get_cipherbyname(value);
if (c == NULL)
return 0;
return cmac_ctrl_int(cctx, EVP_MAC_CTRL_SET_CIPHER, c);
}
if (strcmp(type, "key") == 0)
return EVP_str2ctrl(cmac_ctrl_str_cb, cctx, EVP_MAC_CTRL_SET_KEY,
value);
if (strcmp(type, "hexkey") == 0)
return EVP_hex2ctrl(cmac_ctrl_str_cb, cctx, EVP_MAC_CTRL_SET_KEY,
value);
return -2;
}
const EVP_MAC cmac_meth = {
EVP_MAC_CMAC,
cmac_new,
cmac_copy,
cmac_free,
cmac_size,
cmac_init,
cmac_update,
cmac_final,
cmac_ctrl,
cmac_ctrl_str
};

View file

@ -12,4 +12,7 @@
void openssl_add_all_macs_int(void)
{
#ifndef OPENSSL_NO_CMAC
EVP_add_mac(&cmac_meth);
#endif
}

View file

@ -128,6 +128,8 @@ struct evp_mac_st {
int (*ctrl_str) (EVP_MAC_IMPL *macctx, const char *type, const char *value);
};
extern const EVP_MAC cmac_meth;
/*
* This function is internal for now, but can be made external when needed.
* The documentation would read:

View file

@ -326,16 +326,8 @@ F<./foo>)
=head1 SEE ALSO
=begin comment
Add links to existing implementations in this form:
L<EVP_MAC_CMAC(7)>
Make sure the documentation exists in doc/man7/
=end comment
=head1 COPYRIGHT
Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.

65
doc/man7/EVP_MAC_CMAC.pod Normal file
View file

@ -0,0 +1,65 @@
=pod
=head1 NAME
EVP_MAC_CMAC - The CMAC EVP_MAC implementation
=head1 DESCRIPTION
Support for computing CMAC MACs through the B<EVP_MAC> API.
=head2 Numeric identity
B<EVP_MAC_CMAC> 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_ENGINE>
=item B<EVP_MAC_CTRL_SET_CIPHER>
These work as described in L<EVP_MAC(3)/CONTROLS>.
EVP_MAC_ctrl_str() type string for B<EVP_MAC_CTRL_SET_CIPHER>: "cipher"
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

@ -987,6 +987,8 @@ void EVP_MD_do_all_sorted(void (*fn)
/* MAC stuff */
# define EVP_MAC_CMAC NID_cmac
EVP_MAC_CTX *EVP_MAC_CTX_new(const EVP_MAC *mac);
EVP_MAC_CTX *EVP_MAC_CTX_new_id(int nid);
void EVP_MAC_CTX_free(EVP_MAC_CTX *ctx);