diff options
Diffstat (limited to 'crypto/blake2/blake2s_mac.c')
-rw-r--r-- | crypto/blake2/blake2s_mac.c | 190 |
1 files changed, 190 insertions, 0 deletions
diff --git a/crypto/blake2/blake2s_mac.c b/crypto/blake2/blake2s_mac.c new file mode 100644 index 0000000000..d40778cb12 --- /dev/null +++ b/crypto/blake2/blake2s_mac.c @@ -0,0 +1,190 @@ +/* + * Copyright 2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (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 + */ + +#ifndef OPENSSL_NO_BLAKE2 + +# include <openssl/evp.h> +# include "blake2_locl.h" +# include "internal/cryptlib.h" +# include "internal/evp_int.h" + +/* typedef EVP_MAC_IMPL */ +struct evp_mac_impl_st { + BLAKE2S_CTX ctx; + BLAKE2S_PARAM params; + unsigned char key[BLAKE2S_KEYBYTES]; +}; + +static EVP_MAC_IMPL *blake2s_mac_new(void) +{ + EVP_MAC_IMPL *macctx = OPENSSL_zalloc(sizeof(*macctx)); + if (macctx != NULL) { + blake2s_param_init(&macctx->params); + /* ctx initialization is deferred to BLAKE2s_Init() */ + } + return macctx; +} + +static void blake2s_mac_free(EVP_MAC_IMPL *macctx) +{ + if (macctx != NULL) { + OPENSSL_cleanse(macctx->key, sizeof(macctx->key)); + OPENSSL_free(macctx); + } +} + +static int blake2s_mac_copy(EVP_MAC_IMPL *dst, EVP_MAC_IMPL *src) +{ + *dst = *src; + return 1; +} + +static int blake2s_mac_init(EVP_MAC_IMPL *macctx) +{ + /* Check key has been set */ + if (macctx->params.key_length == 0) { + EVPerr(EVP_F_BLAKE2S_MAC_INIT, EVP_R_NO_KEY_SET); + return 0; + } + + return BLAKE2s_Init_key(&macctx->ctx, &macctx->params, macctx->key); +} + +static int blake2s_mac_update(EVP_MAC_IMPL *macctx, const unsigned char *data, + size_t datalen) +{ + return BLAKE2s_Update(&macctx->ctx, data, datalen); +} + +static int blake2s_mac_final(EVP_MAC_IMPL *macctx, unsigned char *out) +{ + return BLAKE2s_Final(out, &macctx->ctx); +} + +/* + * ALL Ctrl functions should be set before init(). + */ +static int blake2s_mac_ctrl(EVP_MAC_IMPL *macctx, int cmd, va_list args) +{ + const unsigned char *p; + size_t len; + size_t size; + + switch (cmd) { + case EVP_MAC_CTRL_SET_SIZE: + size = va_arg(args, size_t); + if (size < 1 || size > BLAKE2S_OUTBYTES) { + EVPerr(EVP_F_BLAKE2S_MAC_CTRL, EVP_R_NOT_XOF_OR_INVALID_LENGTH); + return 0; + } + blake2s_param_set_digest_length(&macctx->params, (uint8_t)size); + return 1; + + case EVP_MAC_CTRL_SET_KEY: + p = va_arg(args, const unsigned char *); + len = va_arg(args, size_t); + if (len < 1 || len > BLAKE2S_KEYBYTES) { + EVPerr(EVP_F_BLAKE2S_MAC_CTRL, EVP_R_INVALID_KEY_LENGTH); + return 0; + } + blake2s_param_set_key_length(&macctx->params, (uint8_t)len); + memcpy(macctx->key, p, len); + memset(macctx->key + len, 0, BLAKE2S_KEYBYTES - len); + return 1; + + case EVP_MAC_CTRL_SET_CUSTOM: + p = va_arg(args, const unsigned char *); + len = va_arg(args, size_t); + if (len > BLAKE2S_PERSONALBYTES) { + EVPerr(EVP_F_BLAKE2S_MAC_CTRL, EVP_R_INVALID_CUSTOM_LENGTH); + return 0; + } + blake2s_param_set_personal(&macctx->params, p, len); + return 1; + + case EVP_MAC_CTRL_SET_SALT: + p = va_arg(args, const unsigned char *); + len = va_arg(args, size_t); + if (len > BLAKE2S_SALTBYTES) { + EVPerr(EVP_F_BLAKE2S_MAC_CTRL, EVP_R_INVALID_SALT_LENGTH); + return 0; + } + blake2s_param_set_salt(&macctx->params, p, len); + return 1; + + default: + return -2; + } +} + +static int blake2s_mac_ctrl_int(EVP_MAC_IMPL *macctx, int cmd, ...) +{ + int rv; + va_list args; + + va_start(args, cmd); + rv = blake2s_mac_ctrl(macctx, cmd, args); + va_end(args); + + return rv; +} + +static int blake2s_mac_ctrl_str_cb(void *macctx, int cmd, void *buf, size_t buflen) +{ + return blake2s_mac_ctrl_int(macctx, cmd, buf, buflen); +} + +static int blake2s_mac_ctrl_str(EVP_MAC_IMPL *macctx, const char *type, + const char *value) +{ + if (value == NULL) + return 0; + + if (strcmp(type, "outlen") == 0) + return blake2s_mac_ctrl_int(macctx, EVP_MAC_CTRL_SET_SIZE, (size_t)atoi(value)); + if (strcmp(type, "key") == 0) + return EVP_str2ctrl(blake2s_mac_ctrl_str_cb, macctx, EVP_MAC_CTRL_SET_KEY, + value); + if (strcmp(type, "hexkey") == 0) + return EVP_hex2ctrl(blake2s_mac_ctrl_str_cb, macctx, EVP_MAC_CTRL_SET_KEY, + value); + if (strcmp(type, "custom") == 0) + return EVP_str2ctrl(blake2s_mac_ctrl_str_cb, macctx, EVP_MAC_CTRL_SET_CUSTOM, + value); + if (strcmp(type, "hexcustom") == 0) + return EVP_hex2ctrl(blake2s_mac_ctrl_str_cb, macctx, EVP_MAC_CTRL_SET_CUSTOM, + value); + if (strcmp(type, "salt") == 0) + return EVP_str2ctrl(blake2s_mac_ctrl_str_cb, macctx, EVP_MAC_CTRL_SET_SALT, + value); + if (strcmp(type, "hexsalt") == 0) + return EVP_hex2ctrl(blake2s_mac_ctrl_str_cb, macctx, EVP_MAC_CTRL_SET_SALT, + value); + return -2; +} + +static size_t blake2s_mac_size(EVP_MAC_IMPL *macctx) +{ + return macctx->params.digest_length; +} + +const EVP_MAC blake2s_mac_meth = { + EVP_MAC_BLAKE2S, + blake2s_mac_new, + blake2s_mac_copy, + blake2s_mac_free, + blake2s_mac_size, + blake2s_mac_init, + blake2s_mac_update, + blake2s_mac_final, + blake2s_mac_ctrl, + blake2s_mac_ctrl_str +}; + +#endif |