Add poly1305 MAC support

This is based on the latest EVP MAC interface introduced in PR #7393.

Reviewed-by: Richard Levitte <levitte@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/7459)
This commit is contained in:
Paul Yang 2018-10-22 14:54:24 +08:00
parent 748099b9e9
commit c1da4b2afe
13 changed files with 260 additions and 196 deletions

View file

@ -810,6 +810,7 @@ EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN:164:PKCS5_v2_PBKDF2_keyivgen
EVP_F_PKCS5_V2_SCRYPT_KEYIVGEN:180:PKCS5_v2_scrypt_keyivgen
EVP_F_PKEY_MAC_INIT:214:pkey_mac_init
EVP_F_PKEY_SET_TYPE:158:pkey_set_type
EVP_F_POLY1305_CTRL:215:poly1305_ctrl
EVP_F_RC2_MAGIC_TO_METH:109:rc2_magic_to_meth
EVP_F_RC5_CTRL:125:rc5_ctrl
EVP_F_S390X_AES_GCM_CTRL:201:s390x_aes_gcm_ctrl

View file

@ -20,4 +20,7 @@ void openssl_add_all_macs_int(void)
#ifndef OPENSSL_NO_SIPHASH
EVP_add_mac(&siphash_meth);
#endif
#ifndef OPENSSL_NO_POLY1305
EVP_add_mac(&poly1305_meth);
#endif
}

View file

@ -153,6 +153,7 @@ static const ERR_STRING_DATA EVP_str_functs[] = {
"PKCS5_v2_scrypt_keyivgen"},
{ERR_PACK(ERR_LIB_EVP, EVP_F_PKEY_MAC_INIT, 0), "pkey_mac_init"},
{ERR_PACK(ERR_LIB_EVP, EVP_F_PKEY_SET_TYPE, 0), "pkey_set_type"},
{ERR_PACK(ERR_LIB_EVP, EVP_F_POLY1305_CTRL, 0), "poly1305_ctrl"},
{ERR_PACK(ERR_LIB_EVP, EVP_F_RC2_MAGIC_TO_METH, 0), "rc2_magic_to_meth"},
{ERR_PACK(ERR_LIB_EVP, EVP_F_RC5_CTRL, 0), "rc5_ctrl"},
{ERR_PACK(ERR_LIB_EVP, EVP_F_S390X_AES_GCM_CTRL, 0), "s390x_aes_gcm_ctrl"},

View file

@ -425,3 +425,36 @@ const EVP_PKEY_METHOD siphash_pkey_meth = {
pkey_mac_ctrl,
pkey_mac_ctrl_str
};
const EVP_PKEY_METHOD poly1305_pkey_meth = {
EVP_PKEY_POLY1305,
EVP_PKEY_FLAG_SIGCTX_CUSTOM,
pkey_mac_init,
pkey_mac_copy,
pkey_mac_cleanup,
0, 0,
0,
pkey_mac_keygen,
0, 0,
0, 0,
0, 0,
pkey_mac_signctx_init,
pkey_mac_signctx,
0, 0,
0, 0,
0, 0,
0, 0,
pkey_mac_ctrl,
pkey_mac_ctrl_str
};

View file

@ -132,6 +132,7 @@ extern const EVP_MAC cmac_meth;
extern const EVP_MAC gmac_meth;
extern const EVP_MAC hmac_meth;
extern const EVP_MAC siphash_meth;
extern const EVP_MAC poly1305_meth;
/*
* This function is internal for now, but can be made external when needed.

View file

@ -1,7 +1,7 @@
LIBS=../../libcrypto
SOURCE[../../libcrypto]=\
poly1305_pmeth.c \
poly1305_ameth.c \
poly1305_meth.c \
poly1305.c {- $target{poly1305_asm_src} -}
GENERATE[poly1305-sparcv9.S]=asm/poly1305-sparcv9.pl $(PERLASM_SCHEME)

View file

@ -0,0 +1,141 @@
/*
* 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 <openssl/evp.h>
#include "internal/evp_int.h"
#include "internal/poly1305.h"
#include "internal/cryptlib.h"
#include "poly1305_local.h"
/* typedef EVP_MAC_IMPL */
struct evp_mac_impl_st {
POLY1305 *ctx; /* poly1305 context */
};
static EVP_MAC_IMPL *poly1305_new(void)
{
EVP_MAC_IMPL *ctx;
if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL
|| (ctx->ctx = OPENSSL_zalloc(sizeof(POLY1305))) == NULL) {
OPENSSL_free(ctx);
return 0;
}
return ctx;
}
static void poly1305_free(EVP_MAC_IMPL *ctx)
{
if (ctx != NULL) {
OPENSSL_free(ctx->ctx);
OPENSSL_free(ctx);
}
}
static int poly1305_copy(EVP_MAC_IMPL *dst, EVP_MAC_IMPL *src)
{
*dst->ctx = *src->ctx;
return 1;
}
static size_t poly1305_size(EVP_MAC_IMPL *ctx)
{
return POLY1305_DIGEST_SIZE;
}
static int poly1305_init(EVP_MAC_IMPL *ctx)
{
/* initialize the context in MAC_ctrl function */
return 1;
}
static int poly1305_update(EVP_MAC_IMPL *ctx, const unsigned char *data,
size_t datalen)
{
POLY1305 *poly_ctx = ctx->ctx;
/* poly1305 has nothing to return in its update function */
Poly1305_Update(poly_ctx, data, datalen);
return 1;
}
static int poly1305_final(EVP_MAC_IMPL *ctx, unsigned char *out)
{
POLY1305 *poly_ctx = ctx->ctx;
Poly1305_Final(poly_ctx, out);
return 1;
}
static int poly1305_ctrl(EVP_MAC_IMPL *ctx, int cmd, va_list args)
{
POLY1305 *poly_ctx = ctx->ctx;
unsigned char *key;
size_t keylen;
switch (cmd) {
case EVP_MAC_CTRL_SET_KEY:
key = va_arg(args, unsigned char *);
keylen = va_arg(args, size_t);
if (keylen != POLY1305_KEY_SIZE) {
EVPerr(EVP_F_POLY1305_CTRL, EVP_R_INVALID_KEY_LENGTH);
return 0;
}
Poly1305_Init(poly_ctx, key);
return 1;
default:
return -2;
}
return 1;
}
static int poly1305_ctrl_int(EVP_MAC_IMPL *ctx, int cmd, ...)
{
int rv;
va_list args;
va_start(args, cmd);
rv = poly1305_ctrl(ctx, cmd, args);
va_end(args);
return rv;
}
static int poly1305_ctrl_str_cb(void *ctx, int cmd, void *buf, size_t buflen)
{
return poly1305_ctrl_int(ctx, cmd, buf, buflen);
}
static int poly1305_ctrl_str(EVP_MAC_IMPL *ctx,
const char *type, const char *value)
{
if (value == NULL)
return 0;
if (strcmp(type, "key") == 0)
return EVP_str2ctrl(poly1305_ctrl_str_cb, ctx, EVP_MAC_CTRL_SET_KEY,
value);
if (strcmp(type, "hexkey") == 0)
return EVP_hex2ctrl(poly1305_ctrl_str_cb, ctx, EVP_MAC_CTRL_SET_KEY,
value);
return -2;
}
const EVP_MAC poly1305_meth = {
EVP_MAC_POLY1305,
poly1305_new,
poly1305_copy,
poly1305_free,
poly1305_size,
poly1305_init,
poly1305_update,
poly1305_final,
poly1305_ctrl,
poly1305_ctrl_str
};

View file

@ -1,194 +0,0 @@
/*
* Copyright 2007-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/err.h>
#include "internal/poly1305.h"
#include "poly1305_local.h"
#include "internal/evp_int.h"
/* POLY1305 pkey context structure */
typedef struct {
ASN1_OCTET_STRING ktmp; /* Temp storage for key */
POLY1305 ctx;
} POLY1305_PKEY_CTX;
static int pkey_poly1305_init(EVP_PKEY_CTX *ctx)
{
POLY1305_PKEY_CTX *pctx;
if ((pctx = OPENSSL_zalloc(sizeof(*pctx))) == NULL) {
CRYPTOerr(CRYPTO_F_PKEY_POLY1305_INIT, ERR_R_MALLOC_FAILURE);
return 0;
}
pctx->ktmp.type = V_ASN1_OCTET_STRING;
EVP_PKEY_CTX_set_data(ctx, pctx);
EVP_PKEY_CTX_set0_keygen_info(ctx, NULL, 0);
return 1;
}
static void pkey_poly1305_cleanup(EVP_PKEY_CTX *ctx)
{
POLY1305_PKEY_CTX *pctx = EVP_PKEY_CTX_get_data(ctx);
if (pctx != NULL) {
OPENSSL_clear_free(pctx->ktmp.data, pctx->ktmp.length);
OPENSSL_clear_free(pctx, sizeof(*pctx));
EVP_PKEY_CTX_set_data(ctx, NULL);
}
}
static int pkey_poly1305_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
{
POLY1305_PKEY_CTX *sctx, *dctx;
/* allocate memory for dst->data and a new POLY1305_CTX in dst->data->ctx */
if (!pkey_poly1305_init(dst))
return 0;
sctx = EVP_PKEY_CTX_get_data(src);
dctx = EVP_PKEY_CTX_get_data(dst);
if (ASN1_STRING_get0_data(&sctx->ktmp) != NULL &&
!ASN1_STRING_copy(&dctx->ktmp, &sctx->ktmp)) {
/* cleanup and free the POLY1305_PKEY_CTX in dst->data */
pkey_poly1305_cleanup(dst);
return 0;
}
memcpy(&dctx->ctx, &sctx->ctx, sizeof(POLY1305));
return 1;
}
static int pkey_poly1305_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
{
ASN1_OCTET_STRING *key;
POLY1305_PKEY_CTX *pctx = EVP_PKEY_CTX_get_data(ctx);
if (ASN1_STRING_get0_data(&pctx->ktmp) == NULL)
return 0;
key = ASN1_OCTET_STRING_dup(&pctx->ktmp);
if (key == NULL)
return 0;
return EVP_PKEY_assign_POLY1305(pkey, key);
}
static int int_update(EVP_MD_CTX *ctx, const void *data, size_t count)
{
POLY1305_PKEY_CTX *pctx = EVP_PKEY_CTX_get_data(EVP_MD_CTX_pkey_ctx(ctx));
Poly1305_Update(&pctx->ctx, data, count);
return 1;
}
static int poly1305_signctx_init(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx)
{
POLY1305_PKEY_CTX *pctx = ctx->data;
ASN1_OCTET_STRING *key = (ASN1_OCTET_STRING *)ctx->pkey->pkey.ptr;
if (key->length != POLY1305_KEY_SIZE)
return 0;
EVP_MD_CTX_set_flags(mctx, EVP_MD_CTX_FLAG_NO_INIT);
EVP_MD_CTX_set_update_fn(mctx, int_update);
Poly1305_Init(&pctx->ctx, key->data);
return 1;
}
static int poly1305_signctx(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
EVP_MD_CTX *mctx)
{
POLY1305_PKEY_CTX *pctx = ctx->data;
*siglen = POLY1305_DIGEST_SIZE;
if (sig != NULL)
Poly1305_Final(&pctx->ctx, sig);
return 1;
}
static int pkey_poly1305_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
{
POLY1305_PKEY_CTX *pctx = EVP_PKEY_CTX_get_data(ctx);
const unsigned char *key;
size_t len;
switch (type) {
case EVP_PKEY_CTRL_MD:
/* ignore */
break;
case EVP_PKEY_CTRL_SET_MAC_KEY:
case EVP_PKEY_CTRL_DIGESTINIT:
if (type == EVP_PKEY_CTRL_SET_MAC_KEY) {
/* user explicitly setting the key */
key = p2;
len = p1;
} else {
/* user indirectly setting the key via EVP_DigestSignInit */
key = EVP_PKEY_get0_poly1305(EVP_PKEY_CTX_get0_pkey(ctx), &len);
}
if (key == NULL || len != POLY1305_KEY_SIZE ||
!ASN1_OCTET_STRING_set(&pctx->ktmp, key, len))
return 0;
Poly1305_Init(&pctx->ctx, ASN1_STRING_get0_data(&pctx->ktmp));
break;
default:
return -2;
}
return 1;
}
static int pkey_poly1305_ctrl_str(EVP_PKEY_CTX *ctx,
const char *type, const char *value)
{
if (value == NULL)
return 0;
if (strcmp(type, "key") == 0)
return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY, value);
if (strcmp(type, "hexkey") == 0)
return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY, value);
return -2;
}
const EVP_PKEY_METHOD poly1305_pkey_meth = {
EVP_PKEY_POLY1305,
EVP_PKEY_FLAG_SIGCTX_CUSTOM, /* we don't deal with a separate MD */
pkey_poly1305_init,
pkey_poly1305_copy,
pkey_poly1305_cleanup,
0, 0,
0,
pkey_poly1305_keygen,
0, 0,
0, 0,
0, 0,
poly1305_signctx_init,
poly1305_signctx,
0, 0,
0, 0,
0, 0,
0, 0,
pkey_poly1305_ctrl,
pkey_poly1305_ctrl_str
};

View file

@ -335,7 +335,8 @@ F<./foo>)
L<EVP_MAC_CMAC(7)>,
L<EVP_MAC_GMAC(7)>,
L<EVP_MAC_HMAC(7)>,
L<EVP_MAC_SIPHASH(7)>
L<EVP_MAC_SIPHASH(7)>,
L<EVP_MAC_POLY1305(7)>
=head1 COPYRIGHT

View file

@ -0,0 +1,55 @@
=pod
=head1 NAME
EVP_MAC_POLY1305 - The Poly1305 EVP_MAC implementation
=head1 DESCRIPTION
Support for computing Poly1305 MACs through the B<EVP_MAC> API.
=head2 Numeric identity
B<EVP_MAC_POLY1305> 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 two type strings 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
=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

@ -991,6 +991,7 @@ void EVP_MD_do_all_sorted(void (*fn)
# define EVP_MAC_GMAC NID_gmac
# define EVP_MAC_HMAC NID_hmac
# define EVP_MAC_SIPHASH NID_siphash
# define EVP_MAC_POLY1305 NID_poly1305
EVP_MAC_CTX *EVP_MAC_CTX_new(const EVP_MAC *mac);
EVP_MAC_CTX *EVP_MAC_CTX_new_id(int nid);

View file

@ -120,6 +120,7 @@ int ERR_load_EVP_strings(void);
# define EVP_F_PKCS5_V2_SCRYPT_KEYIVGEN 180
# define EVP_F_PKEY_MAC_INIT 214
# define EVP_F_PKEY_SET_TYPE 158
# define EVP_F_POLY1305_CTRL 215
# define EVP_F_RC2_MAGIC_TO_METH 109
# define EVP_F_RC5_CTRL 125
# define EVP_F_S390X_AES_GCM_CTRL 201

View file

@ -710,3 +710,23 @@ Input = e33594d7505e43b900000000000000003394d7505e4379cd010000000000000000000000
Key = 0100000000000000040000000000000000000000000000000000000000000000
Output = 13000000000000000000000000000000
# Here are 4 duplicated cases for Poly1305 by EVP_PKEY
MAC = Poly1305 by EVP_PKEY
Key = 0000000000000000000000000000000000000000000000000000000000000000
Input = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Output = 00000000000000000000000000000000
MAC = Poly1305 by EVP_PKEY
Key = 0000000000000000000000000000000036e5f6b5c5e06070f0efca96227a863e
Input = 416e79207375626d697373696f6e20746f20746865204945544620696e74656e6465642062792074686520436f6e7472696275746f7220666f72207075626c69636174696f6e20617320616c6c206f722070617274206f6620616e204945544620496e7465726e65742d4472616674206f722052464320616e6420616e792073746174656d656e74206d6164652077697468696e2074686520636f6e74657874206f6620616e204945544620616374697669747920697320636f6e7369646572656420616e20224945544620436f6e747269627574696f6e222e20537563682073746174656d656e747320696e636c756465206f72616c2073746174656d656e747320696e20494554462073657373696f6e732c2061732077656c6c206173207772697474656e20616e6420656c656374726f6e696320636f6d6d756e69636174696f6e73206d61646520617420616e792074696d65206f7220706c6163652c207768696368206172652061646472657373656420746f
Output = 36e5f6b5c5e06070f0efca96227a863e
MAC = Poly1305 by EVP_PKEY
Key = 36e5f6b5c5e06070f0efca96227a863e00000000000000000000000000000000
Input = 416e79207375626d697373696f6e20746f20746865204945544620696e74656e6465642062792074686520436f6e7472696275746f7220666f72207075626c69636174696f6e20617320616c6c206f722070617274206f6620616e204945544620496e7465726e65742d4472616674206f722052464320616e6420616e792073746174656d656e74206d6164652077697468696e2074686520636f6e74657874206f6620616e204945544620616374697669747920697320636f6e7369646572656420616e20224945544620436f6e747269627574696f6e222e20537563682073746174656d656e747320696e636c756465206f72616c2073746174656d656e747320696e20494554462073657373696f6e732c2061732077656c6c206173207772697474656e20616e6420656c656374726f6e696320636f6d6d756e69636174696f6e73206d61646520617420616e792074696d65206f7220706c6163652c207768696368206172652061646472657373656420746f
Output = f3477e7cd95417af89a6b8794c310cf0
MAC = Poly1305 by EVP_PKEY
Key = 1c9240a5eb55d38af333888604f6b5f0473917c1402b80099dca5cbc207075c0
Input = 2754776173206272696c6c69672c20616e642074686520736c6974687920746f7665730a446964206779726520616e642067696d626c6520696e2074686520776162653a0a416c6c206d696d737920776572652074686520626f726f676f7665732c0a416e6420746865206d6f6d65207261746873206f757467726162652e
Output = 4541669a7eaaee61e708dc7cbcc5eb62