1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 2018-2021 The OpenSSL Project Authors. All Rights Reserved. 3e1051a39Sopenharmony_ci * 4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 5e1051a39Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at 7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html 8e1051a39Sopenharmony_ci */ 9e1051a39Sopenharmony_ci 10e1051a39Sopenharmony_ci/* 11e1051a39Sopenharmony_ci * See SP800-185 "Appendix A - KMAC, .... in Terms of Keccak[c]" 12e1051a39Sopenharmony_ci * 13e1051a39Sopenharmony_ci * Inputs are: 14e1051a39Sopenharmony_ci * K = Key (len(K) < 2^2040 bits) 15e1051a39Sopenharmony_ci * X = Input 16e1051a39Sopenharmony_ci * L = Output length (0 <= L < 2^2040 bits) 17e1051a39Sopenharmony_ci * S = Customization String Default="" (len(S) < 2^2040 bits) 18e1051a39Sopenharmony_ci * 19e1051a39Sopenharmony_ci * KMAC128(K, X, L, S) 20e1051a39Sopenharmony_ci * { 21e1051a39Sopenharmony_ci * newX = bytepad(encode_string(K), 168) || X || right_encode(L). 22e1051a39Sopenharmony_ci * T = bytepad(encode_string("KMAC") || encode_string(S), 168). 23e1051a39Sopenharmony_ci * return KECCAK[256](T || newX || 00, L). 24e1051a39Sopenharmony_ci * } 25e1051a39Sopenharmony_ci * 26e1051a39Sopenharmony_ci * KMAC256(K, X, L, S) 27e1051a39Sopenharmony_ci * { 28e1051a39Sopenharmony_ci * newX = bytepad(encode_string(K), 136) || X || right_encode(L). 29e1051a39Sopenharmony_ci * T = bytepad(encode_string("KMAC") || encode_string(S), 136). 30e1051a39Sopenharmony_ci * return KECCAK[512](T || newX || 00, L). 31e1051a39Sopenharmony_ci * } 32e1051a39Sopenharmony_ci * 33e1051a39Sopenharmony_ci * KMAC128XOF(K, X, L, S) 34e1051a39Sopenharmony_ci * { 35e1051a39Sopenharmony_ci * newX = bytepad(encode_string(K), 168) || X || right_encode(0). 36e1051a39Sopenharmony_ci * T = bytepad(encode_string("KMAC") || encode_string(S), 168). 37e1051a39Sopenharmony_ci * return KECCAK[256](T || newX || 00, L). 38e1051a39Sopenharmony_ci * } 39e1051a39Sopenharmony_ci * 40e1051a39Sopenharmony_ci * KMAC256XOF(K, X, L, S) 41e1051a39Sopenharmony_ci * { 42e1051a39Sopenharmony_ci * newX = bytepad(encode_string(K), 136) || X || right_encode(0). 43e1051a39Sopenharmony_ci * T = bytepad(encode_string("KMAC") || encode_string(S), 136). 44e1051a39Sopenharmony_ci * return KECCAK[512](T || newX || 00, L). 45e1051a39Sopenharmony_ci * } 46e1051a39Sopenharmony_ci * 47e1051a39Sopenharmony_ci */ 48e1051a39Sopenharmony_ci 49e1051a39Sopenharmony_ci#include <stdlib.h> 50e1051a39Sopenharmony_ci#include <string.h> 51e1051a39Sopenharmony_ci#include <openssl/core_dispatch.h> 52e1051a39Sopenharmony_ci#include <openssl/core_names.h> 53e1051a39Sopenharmony_ci#include <openssl/params.h> 54e1051a39Sopenharmony_ci#include <openssl/evp.h> 55e1051a39Sopenharmony_ci#include <openssl/err.h> 56e1051a39Sopenharmony_ci#include <openssl/proverr.h> 57e1051a39Sopenharmony_ci 58e1051a39Sopenharmony_ci#include "prov/implementations.h" 59e1051a39Sopenharmony_ci#include "prov/provider_ctx.h" 60e1051a39Sopenharmony_ci#include "prov/provider_util.h" 61e1051a39Sopenharmony_ci#include "prov/providercommon.h" 62e1051a39Sopenharmony_ci#include "internal/cryptlib.h" /* ossl_assert */ 63e1051a39Sopenharmony_ci 64e1051a39Sopenharmony_ci/* 65e1051a39Sopenharmony_ci * Forward declaration of everything implemented here. This is not strictly 66e1051a39Sopenharmony_ci * necessary for the compiler, but provides an assurance that the signatures 67e1051a39Sopenharmony_ci * of the functions in the dispatch table are correct. 68e1051a39Sopenharmony_ci */ 69e1051a39Sopenharmony_cistatic OSSL_FUNC_mac_newctx_fn kmac128_new; 70e1051a39Sopenharmony_cistatic OSSL_FUNC_mac_newctx_fn kmac256_new; 71e1051a39Sopenharmony_cistatic OSSL_FUNC_mac_dupctx_fn kmac_dup; 72e1051a39Sopenharmony_cistatic OSSL_FUNC_mac_freectx_fn kmac_free; 73e1051a39Sopenharmony_cistatic OSSL_FUNC_mac_gettable_ctx_params_fn kmac_gettable_ctx_params; 74e1051a39Sopenharmony_cistatic OSSL_FUNC_mac_get_ctx_params_fn kmac_get_ctx_params; 75e1051a39Sopenharmony_cistatic OSSL_FUNC_mac_settable_ctx_params_fn kmac_settable_ctx_params; 76e1051a39Sopenharmony_cistatic OSSL_FUNC_mac_set_ctx_params_fn kmac_set_ctx_params; 77e1051a39Sopenharmony_cistatic OSSL_FUNC_mac_init_fn kmac_init; 78e1051a39Sopenharmony_cistatic OSSL_FUNC_mac_update_fn kmac_update; 79e1051a39Sopenharmony_cistatic OSSL_FUNC_mac_final_fn kmac_final; 80e1051a39Sopenharmony_ci 81e1051a39Sopenharmony_ci#define KMAC_MAX_BLOCKSIZE ((1600 - 128 * 2) / 8) /* 168 */ 82e1051a39Sopenharmony_ci 83e1051a39Sopenharmony_ci/* 84e1051a39Sopenharmony_ci * Length encoding will be a 1 byte size + length in bits (3 bytes max) 85e1051a39Sopenharmony_ci * This gives a range of 0..0XFFFFFF bits = 2097151 bytes). 86e1051a39Sopenharmony_ci */ 87e1051a39Sopenharmony_ci#define KMAC_MAX_OUTPUT_LEN (0xFFFFFF / 8) 88e1051a39Sopenharmony_ci#define KMAC_MAX_ENCODED_HEADER_LEN (1 + 3) 89e1051a39Sopenharmony_ci 90e1051a39Sopenharmony_ci/* 91e1051a39Sopenharmony_ci * Restrict the maximum length of the customisation string. This must not 92e1051a39Sopenharmony_ci * exceed 64 bits = 8k bytes. 93e1051a39Sopenharmony_ci */ 94e1051a39Sopenharmony_ci#define KMAC_MAX_CUSTOM 512 95e1051a39Sopenharmony_ci 96e1051a39Sopenharmony_ci/* Maximum size of encoded custom string */ 97e1051a39Sopenharmony_ci#define KMAC_MAX_CUSTOM_ENCODED (KMAC_MAX_CUSTOM + KMAC_MAX_ENCODED_HEADER_LEN) 98e1051a39Sopenharmony_ci 99e1051a39Sopenharmony_ci/* Maximum key size in bytes = 512 (4096 bits) */ 100e1051a39Sopenharmony_ci#define KMAC_MAX_KEY 512 101e1051a39Sopenharmony_ci#define KMAC_MIN_KEY 4 102e1051a39Sopenharmony_ci 103e1051a39Sopenharmony_ci/* 104e1051a39Sopenharmony_ci * Maximum Encoded Key size will be padded to a multiple of the blocksize 105e1051a39Sopenharmony_ci * i.e KMAC_MAX_KEY + KMAC_MAX_ENCODED_HEADER_LEN = 512 + 4 106e1051a39Sopenharmony_ci * Padded to a multiple of KMAC_MAX_BLOCKSIZE 107e1051a39Sopenharmony_ci */ 108e1051a39Sopenharmony_ci#define KMAC_MAX_KEY_ENCODED (KMAC_MAX_BLOCKSIZE * 4) 109e1051a39Sopenharmony_ci 110e1051a39Sopenharmony_ci/* Fixed value of encode_string("KMAC") */ 111e1051a39Sopenharmony_cistatic const unsigned char kmac_string[] = { 112e1051a39Sopenharmony_ci 0x01, 0x20, 0x4B, 0x4D, 0x41, 0x43 113e1051a39Sopenharmony_ci}; 114e1051a39Sopenharmony_ci 115e1051a39Sopenharmony_ci#define KMAC_FLAG_XOF_MODE 1 116e1051a39Sopenharmony_ci 117e1051a39Sopenharmony_cistruct kmac_data_st { 118e1051a39Sopenharmony_ci void *provctx; 119e1051a39Sopenharmony_ci EVP_MD_CTX *ctx; 120e1051a39Sopenharmony_ci PROV_DIGEST digest; 121e1051a39Sopenharmony_ci size_t out_len; 122e1051a39Sopenharmony_ci size_t key_len; 123e1051a39Sopenharmony_ci size_t custom_len; 124e1051a39Sopenharmony_ci /* If xof_mode = 1 then we use right_encode(0) */ 125e1051a39Sopenharmony_ci int xof_mode; 126e1051a39Sopenharmony_ci /* key and custom are stored in encoded form */ 127e1051a39Sopenharmony_ci unsigned char key[KMAC_MAX_KEY_ENCODED]; 128e1051a39Sopenharmony_ci unsigned char custom[KMAC_MAX_CUSTOM_ENCODED]; 129e1051a39Sopenharmony_ci}; 130e1051a39Sopenharmony_ci 131e1051a39Sopenharmony_cistatic int encode_string(unsigned char *out, size_t out_max_len, size_t *out_len, 132e1051a39Sopenharmony_ci const unsigned char *in, size_t in_len); 133e1051a39Sopenharmony_cistatic int right_encode(unsigned char *out, size_t out_max_len, size_t *out_len, 134e1051a39Sopenharmony_ci size_t bits); 135e1051a39Sopenharmony_cistatic int bytepad(unsigned char *out, size_t *out_len, 136e1051a39Sopenharmony_ci const unsigned char *in1, size_t in1_len, 137e1051a39Sopenharmony_ci const unsigned char *in2, size_t in2_len, 138e1051a39Sopenharmony_ci size_t w); 139e1051a39Sopenharmony_cistatic int kmac_bytepad_encode_key(unsigned char *out, size_t out_max_len, 140e1051a39Sopenharmony_ci size_t *out_len, 141e1051a39Sopenharmony_ci const unsigned char *in, size_t in_len, 142e1051a39Sopenharmony_ci size_t w); 143e1051a39Sopenharmony_ci 144e1051a39Sopenharmony_cistatic void kmac_free(void *vmacctx) 145e1051a39Sopenharmony_ci{ 146e1051a39Sopenharmony_ci struct kmac_data_st *kctx = vmacctx; 147e1051a39Sopenharmony_ci 148e1051a39Sopenharmony_ci if (kctx != NULL) { 149e1051a39Sopenharmony_ci EVP_MD_CTX_free(kctx->ctx); 150e1051a39Sopenharmony_ci ossl_prov_digest_reset(&kctx->digest); 151e1051a39Sopenharmony_ci OPENSSL_cleanse(kctx->key, kctx->key_len); 152e1051a39Sopenharmony_ci OPENSSL_cleanse(kctx->custom, kctx->custom_len); 153e1051a39Sopenharmony_ci OPENSSL_free(kctx); 154e1051a39Sopenharmony_ci } 155e1051a39Sopenharmony_ci} 156e1051a39Sopenharmony_ci 157e1051a39Sopenharmony_ci/* 158e1051a39Sopenharmony_ci * We have KMAC implemented as a hash, which we can use instead of 159e1051a39Sopenharmony_ci * reimplementing the EVP functionality with direct use of 160e1051a39Sopenharmony_ci * keccak_mac_init() and friends. 161e1051a39Sopenharmony_ci */ 162e1051a39Sopenharmony_cistatic struct kmac_data_st *kmac_new(void *provctx) 163e1051a39Sopenharmony_ci{ 164e1051a39Sopenharmony_ci struct kmac_data_st *kctx; 165e1051a39Sopenharmony_ci 166e1051a39Sopenharmony_ci if (!ossl_prov_is_running()) 167e1051a39Sopenharmony_ci return NULL; 168e1051a39Sopenharmony_ci 169e1051a39Sopenharmony_ci if ((kctx = OPENSSL_zalloc(sizeof(*kctx))) == NULL 170e1051a39Sopenharmony_ci || (kctx->ctx = EVP_MD_CTX_new()) == NULL) { 171e1051a39Sopenharmony_ci kmac_free(kctx); 172e1051a39Sopenharmony_ci return NULL; 173e1051a39Sopenharmony_ci } 174e1051a39Sopenharmony_ci kctx->provctx = provctx; 175e1051a39Sopenharmony_ci return kctx; 176e1051a39Sopenharmony_ci} 177e1051a39Sopenharmony_ci 178e1051a39Sopenharmony_cistatic void *kmac_fetch_new(void *provctx, const OSSL_PARAM *params) 179e1051a39Sopenharmony_ci{ 180e1051a39Sopenharmony_ci struct kmac_data_st *kctx = kmac_new(provctx); 181e1051a39Sopenharmony_ci 182e1051a39Sopenharmony_ci if (kctx == NULL) 183e1051a39Sopenharmony_ci return 0; 184e1051a39Sopenharmony_ci if (!ossl_prov_digest_load_from_params(&kctx->digest, params, 185e1051a39Sopenharmony_ci PROV_LIBCTX_OF(provctx))) { 186e1051a39Sopenharmony_ci kmac_free(kctx); 187e1051a39Sopenharmony_ci return 0; 188e1051a39Sopenharmony_ci } 189e1051a39Sopenharmony_ci 190e1051a39Sopenharmony_ci kctx->out_len = EVP_MD_get_size(ossl_prov_digest_md(&kctx->digest)); 191e1051a39Sopenharmony_ci return kctx; 192e1051a39Sopenharmony_ci} 193e1051a39Sopenharmony_ci 194e1051a39Sopenharmony_cistatic void *kmac128_new(void *provctx) 195e1051a39Sopenharmony_ci{ 196e1051a39Sopenharmony_ci static const OSSL_PARAM kmac128_params[] = { 197e1051a39Sopenharmony_ci OSSL_PARAM_utf8_string("digest", OSSL_DIGEST_NAME_KECCAK_KMAC128, 198e1051a39Sopenharmony_ci sizeof(OSSL_DIGEST_NAME_KECCAK_KMAC128)), 199e1051a39Sopenharmony_ci OSSL_PARAM_END 200e1051a39Sopenharmony_ci }; 201e1051a39Sopenharmony_ci return kmac_fetch_new(provctx, kmac128_params); 202e1051a39Sopenharmony_ci} 203e1051a39Sopenharmony_ci 204e1051a39Sopenharmony_cistatic void *kmac256_new(void *provctx) 205e1051a39Sopenharmony_ci{ 206e1051a39Sopenharmony_ci static const OSSL_PARAM kmac256_params[] = { 207e1051a39Sopenharmony_ci OSSL_PARAM_utf8_string("digest", OSSL_DIGEST_NAME_KECCAK_KMAC256, 208e1051a39Sopenharmony_ci sizeof(OSSL_DIGEST_NAME_KECCAK_KMAC256)), 209e1051a39Sopenharmony_ci OSSL_PARAM_END 210e1051a39Sopenharmony_ci }; 211e1051a39Sopenharmony_ci return kmac_fetch_new(provctx, kmac256_params); 212e1051a39Sopenharmony_ci} 213e1051a39Sopenharmony_ci 214e1051a39Sopenharmony_cistatic void *kmac_dup(void *vsrc) 215e1051a39Sopenharmony_ci{ 216e1051a39Sopenharmony_ci struct kmac_data_st *src = vsrc; 217e1051a39Sopenharmony_ci struct kmac_data_st *dst; 218e1051a39Sopenharmony_ci 219e1051a39Sopenharmony_ci if (!ossl_prov_is_running()) 220e1051a39Sopenharmony_ci return NULL; 221e1051a39Sopenharmony_ci 222e1051a39Sopenharmony_ci dst = kmac_new(src->provctx); 223e1051a39Sopenharmony_ci if (dst == NULL) 224e1051a39Sopenharmony_ci return NULL; 225e1051a39Sopenharmony_ci 226e1051a39Sopenharmony_ci if (!EVP_MD_CTX_copy(dst->ctx, src->ctx) 227e1051a39Sopenharmony_ci || !ossl_prov_digest_copy(&dst->digest, &src->digest)) { 228e1051a39Sopenharmony_ci kmac_free(dst); 229e1051a39Sopenharmony_ci return NULL; 230e1051a39Sopenharmony_ci } 231e1051a39Sopenharmony_ci 232e1051a39Sopenharmony_ci dst->out_len = src->out_len; 233e1051a39Sopenharmony_ci dst->key_len = src->key_len; 234e1051a39Sopenharmony_ci dst->custom_len = src->custom_len; 235e1051a39Sopenharmony_ci dst->xof_mode = src->xof_mode; 236e1051a39Sopenharmony_ci memcpy(dst->key, src->key, src->key_len); 237e1051a39Sopenharmony_ci memcpy(dst->custom, src->custom, dst->custom_len); 238e1051a39Sopenharmony_ci 239e1051a39Sopenharmony_ci return dst; 240e1051a39Sopenharmony_ci} 241e1051a39Sopenharmony_ci 242e1051a39Sopenharmony_cistatic int kmac_setkey(struct kmac_data_st *kctx, const unsigned char *key, 243e1051a39Sopenharmony_ci size_t keylen) 244e1051a39Sopenharmony_ci{ 245e1051a39Sopenharmony_ci const EVP_MD *digest = ossl_prov_digest_md(&kctx->digest); 246e1051a39Sopenharmony_ci int w = EVP_MD_get_block_size(digest); 247e1051a39Sopenharmony_ci 248e1051a39Sopenharmony_ci if (keylen < KMAC_MIN_KEY || keylen > KMAC_MAX_KEY) { 249e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH); 250e1051a39Sopenharmony_ci return 0; 251e1051a39Sopenharmony_ci } 252e1051a39Sopenharmony_ci if (w < 0) { 253e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST_LENGTH); 254e1051a39Sopenharmony_ci return 0; 255e1051a39Sopenharmony_ci } 256e1051a39Sopenharmony_ci if (!kmac_bytepad_encode_key(kctx->key, sizeof(kctx->key), &kctx->key_len, 257e1051a39Sopenharmony_ci key, keylen, (size_t)w)) 258e1051a39Sopenharmony_ci return 0; 259e1051a39Sopenharmony_ci return 1; 260e1051a39Sopenharmony_ci} 261e1051a39Sopenharmony_ci 262e1051a39Sopenharmony_ci/* 263e1051a39Sopenharmony_ci * The init() assumes that any ctrl methods are set beforehand for 264e1051a39Sopenharmony_ci * md, key and custom. Setting the fields afterwards will have no 265e1051a39Sopenharmony_ci * effect on the output mac. 266e1051a39Sopenharmony_ci */ 267e1051a39Sopenharmony_cistatic int kmac_init(void *vmacctx, const unsigned char *key, 268e1051a39Sopenharmony_ci size_t keylen, const OSSL_PARAM params[]) 269e1051a39Sopenharmony_ci{ 270e1051a39Sopenharmony_ci struct kmac_data_st *kctx = vmacctx; 271e1051a39Sopenharmony_ci EVP_MD_CTX *ctx = kctx->ctx; 272e1051a39Sopenharmony_ci unsigned char *out; 273e1051a39Sopenharmony_ci size_t out_len, block_len; 274e1051a39Sopenharmony_ci int res, t; 275e1051a39Sopenharmony_ci 276e1051a39Sopenharmony_ci if (!ossl_prov_is_running() || !kmac_set_ctx_params(kctx, params)) 277e1051a39Sopenharmony_ci return 0; 278e1051a39Sopenharmony_ci 279e1051a39Sopenharmony_ci if (key != NULL) { 280e1051a39Sopenharmony_ci if (!kmac_setkey(kctx, key, keylen)) 281e1051a39Sopenharmony_ci return 0; 282e1051a39Sopenharmony_ci } else if (kctx->key_len == 0) { 283e1051a39Sopenharmony_ci /* Check key has been set */ 284e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PROV, PROV_R_NO_KEY_SET); 285e1051a39Sopenharmony_ci return 0; 286e1051a39Sopenharmony_ci } 287e1051a39Sopenharmony_ci if (!EVP_DigestInit_ex(kctx->ctx, ossl_prov_digest_md(&kctx->digest), 288e1051a39Sopenharmony_ci NULL)) 289e1051a39Sopenharmony_ci return 0; 290e1051a39Sopenharmony_ci 291e1051a39Sopenharmony_ci t = EVP_MD_get_block_size(ossl_prov_digest_md(&kctx->digest)); 292e1051a39Sopenharmony_ci if (t < 0) { 293e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST_LENGTH); 294e1051a39Sopenharmony_ci return 0; 295e1051a39Sopenharmony_ci } 296e1051a39Sopenharmony_ci block_len = t; 297e1051a39Sopenharmony_ci 298e1051a39Sopenharmony_ci /* Set default custom string if it is not already set */ 299e1051a39Sopenharmony_ci if (kctx->custom_len == 0) { 300e1051a39Sopenharmony_ci const OSSL_PARAM cparams[] = { 301e1051a39Sopenharmony_ci OSSL_PARAM_octet_string(OSSL_MAC_PARAM_CUSTOM, "", 0), 302e1051a39Sopenharmony_ci OSSL_PARAM_END 303e1051a39Sopenharmony_ci }; 304e1051a39Sopenharmony_ci (void)kmac_set_ctx_params(kctx, cparams); 305e1051a39Sopenharmony_ci } 306e1051a39Sopenharmony_ci 307e1051a39Sopenharmony_ci if (!bytepad(NULL, &out_len, kmac_string, sizeof(kmac_string), 308e1051a39Sopenharmony_ci kctx->custom, kctx->custom_len, block_len)) { 309e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); 310e1051a39Sopenharmony_ci return 0; 311e1051a39Sopenharmony_ci } 312e1051a39Sopenharmony_ci out = OPENSSL_malloc(out_len); 313e1051a39Sopenharmony_ci if (out == NULL) { 314e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); 315e1051a39Sopenharmony_ci return 0; 316e1051a39Sopenharmony_ci } 317e1051a39Sopenharmony_ci res = bytepad(out, NULL, kmac_string, sizeof(kmac_string), 318e1051a39Sopenharmony_ci kctx->custom, kctx->custom_len, block_len) 319e1051a39Sopenharmony_ci && EVP_DigestUpdate(ctx, out, out_len) 320e1051a39Sopenharmony_ci && EVP_DigestUpdate(ctx, kctx->key, kctx->key_len); 321e1051a39Sopenharmony_ci OPENSSL_free(out); 322e1051a39Sopenharmony_ci return res; 323e1051a39Sopenharmony_ci} 324e1051a39Sopenharmony_ci 325e1051a39Sopenharmony_cistatic int kmac_update(void *vmacctx, const unsigned char *data, 326e1051a39Sopenharmony_ci size_t datalen) 327e1051a39Sopenharmony_ci{ 328e1051a39Sopenharmony_ci struct kmac_data_st *kctx = vmacctx; 329e1051a39Sopenharmony_ci 330e1051a39Sopenharmony_ci return EVP_DigestUpdate(kctx->ctx, data, datalen); 331e1051a39Sopenharmony_ci} 332e1051a39Sopenharmony_ci 333e1051a39Sopenharmony_cistatic int kmac_final(void *vmacctx, unsigned char *out, size_t *outl, 334e1051a39Sopenharmony_ci size_t outsize) 335e1051a39Sopenharmony_ci{ 336e1051a39Sopenharmony_ci struct kmac_data_st *kctx = vmacctx; 337e1051a39Sopenharmony_ci EVP_MD_CTX *ctx = kctx->ctx; 338e1051a39Sopenharmony_ci size_t lbits, len; 339e1051a39Sopenharmony_ci unsigned char encoded_outlen[KMAC_MAX_ENCODED_HEADER_LEN]; 340e1051a39Sopenharmony_ci int ok; 341e1051a39Sopenharmony_ci 342e1051a39Sopenharmony_ci if (!ossl_prov_is_running()) 343e1051a39Sopenharmony_ci return 0; 344e1051a39Sopenharmony_ci 345e1051a39Sopenharmony_ci /* KMAC XOF mode sets the encoded length to 0 */ 346e1051a39Sopenharmony_ci lbits = (kctx->xof_mode ? 0 : (kctx->out_len * 8)); 347e1051a39Sopenharmony_ci 348e1051a39Sopenharmony_ci ok = right_encode(encoded_outlen, sizeof(encoded_outlen), &len, lbits) 349e1051a39Sopenharmony_ci && EVP_DigestUpdate(ctx, encoded_outlen, len) 350e1051a39Sopenharmony_ci && EVP_DigestFinalXOF(ctx, out, kctx->out_len); 351e1051a39Sopenharmony_ci *outl = kctx->out_len; 352e1051a39Sopenharmony_ci return ok; 353e1051a39Sopenharmony_ci} 354e1051a39Sopenharmony_ci 355e1051a39Sopenharmony_cistatic const OSSL_PARAM known_gettable_ctx_params[] = { 356e1051a39Sopenharmony_ci OSSL_PARAM_size_t(OSSL_MAC_PARAM_SIZE, NULL), 357e1051a39Sopenharmony_ci OSSL_PARAM_size_t(OSSL_MAC_PARAM_BLOCK_SIZE, NULL), 358e1051a39Sopenharmony_ci OSSL_PARAM_END 359e1051a39Sopenharmony_ci}; 360e1051a39Sopenharmony_cistatic const OSSL_PARAM *kmac_gettable_ctx_params(ossl_unused void *ctx, 361e1051a39Sopenharmony_ci ossl_unused void *provctx) 362e1051a39Sopenharmony_ci{ 363e1051a39Sopenharmony_ci return known_gettable_ctx_params; 364e1051a39Sopenharmony_ci} 365e1051a39Sopenharmony_ci 366e1051a39Sopenharmony_cistatic int kmac_get_ctx_params(void *vmacctx, OSSL_PARAM params[]) 367e1051a39Sopenharmony_ci{ 368e1051a39Sopenharmony_ci struct kmac_data_st *kctx = vmacctx; 369e1051a39Sopenharmony_ci OSSL_PARAM *p; 370e1051a39Sopenharmony_ci int sz; 371e1051a39Sopenharmony_ci 372e1051a39Sopenharmony_ci if ((p = OSSL_PARAM_locate(params, OSSL_MAC_PARAM_SIZE)) != NULL 373e1051a39Sopenharmony_ci && !OSSL_PARAM_set_size_t(p, kctx->out_len)) 374e1051a39Sopenharmony_ci return 0; 375e1051a39Sopenharmony_ci 376e1051a39Sopenharmony_ci if ((p = OSSL_PARAM_locate(params, OSSL_MAC_PARAM_BLOCK_SIZE)) != NULL) { 377e1051a39Sopenharmony_ci sz = EVP_MD_block_size(ossl_prov_digest_md(&kctx->digest)); 378e1051a39Sopenharmony_ci if (!OSSL_PARAM_set_int(p, sz)) 379e1051a39Sopenharmony_ci return 0; 380e1051a39Sopenharmony_ci } 381e1051a39Sopenharmony_ci 382e1051a39Sopenharmony_ci return 1; 383e1051a39Sopenharmony_ci} 384e1051a39Sopenharmony_ci 385e1051a39Sopenharmony_cistatic const OSSL_PARAM known_settable_ctx_params[] = { 386e1051a39Sopenharmony_ci OSSL_PARAM_int(OSSL_MAC_PARAM_XOF, NULL), 387e1051a39Sopenharmony_ci OSSL_PARAM_size_t(OSSL_MAC_PARAM_SIZE, NULL), 388e1051a39Sopenharmony_ci OSSL_PARAM_octet_string(OSSL_MAC_PARAM_KEY, NULL, 0), 389e1051a39Sopenharmony_ci OSSL_PARAM_octet_string(OSSL_MAC_PARAM_CUSTOM, NULL, 0), 390e1051a39Sopenharmony_ci OSSL_PARAM_END 391e1051a39Sopenharmony_ci}; 392e1051a39Sopenharmony_cistatic const OSSL_PARAM *kmac_settable_ctx_params(ossl_unused void *ctx, 393e1051a39Sopenharmony_ci ossl_unused void *provctx) 394e1051a39Sopenharmony_ci{ 395e1051a39Sopenharmony_ci return known_settable_ctx_params; 396e1051a39Sopenharmony_ci} 397e1051a39Sopenharmony_ci 398e1051a39Sopenharmony_ci/* 399e1051a39Sopenharmony_ci * The following params can be set any time before final(): 400e1051a39Sopenharmony_ci * - "outlen" or "size": The requested output length. 401e1051a39Sopenharmony_ci * - "xof": If set, this indicates that right_encoded(0) 402e1051a39Sopenharmony_ci * is part of the digested data, otherwise it 403e1051a39Sopenharmony_ci * uses right_encoded(requested output length). 404e1051a39Sopenharmony_ci * 405e1051a39Sopenharmony_ci * All other params should be set before init(). 406e1051a39Sopenharmony_ci */ 407e1051a39Sopenharmony_cistatic int kmac_set_ctx_params(void *vmacctx, const OSSL_PARAM *params) 408e1051a39Sopenharmony_ci{ 409e1051a39Sopenharmony_ci struct kmac_data_st *kctx = vmacctx; 410e1051a39Sopenharmony_ci const OSSL_PARAM *p; 411e1051a39Sopenharmony_ci 412e1051a39Sopenharmony_ci if (params == NULL) 413e1051a39Sopenharmony_ci return 1; 414e1051a39Sopenharmony_ci 415e1051a39Sopenharmony_ci if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_XOF)) != NULL 416e1051a39Sopenharmony_ci && !OSSL_PARAM_get_int(p, &kctx->xof_mode)) 417e1051a39Sopenharmony_ci return 0; 418e1051a39Sopenharmony_ci if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_SIZE)) != NULL) { 419e1051a39Sopenharmony_ci size_t sz = 0; 420e1051a39Sopenharmony_ci 421e1051a39Sopenharmony_ci if (!OSSL_PARAM_get_size_t(p, &sz)) 422e1051a39Sopenharmony_ci return 0; 423e1051a39Sopenharmony_ci if (sz > KMAC_MAX_OUTPUT_LEN) { 424e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_OUTPUT_LENGTH); 425e1051a39Sopenharmony_ci return 0; 426e1051a39Sopenharmony_ci } 427e1051a39Sopenharmony_ci kctx->out_len = sz; 428e1051a39Sopenharmony_ci } 429e1051a39Sopenharmony_ci if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_KEY)) != NULL 430e1051a39Sopenharmony_ci && !kmac_setkey(kctx, p->data, p->data_size)) 431e1051a39Sopenharmony_ci return 0; 432e1051a39Sopenharmony_ci if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_CUSTOM)) 433e1051a39Sopenharmony_ci != NULL) { 434e1051a39Sopenharmony_ci if (p->data_size > KMAC_MAX_CUSTOM) { 435e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_CUSTOM_LENGTH); 436e1051a39Sopenharmony_ci return 0; 437e1051a39Sopenharmony_ci } 438e1051a39Sopenharmony_ci if (!encode_string(kctx->custom, sizeof(kctx->custom), &kctx->custom_len, 439e1051a39Sopenharmony_ci p->data, p->data_size)) 440e1051a39Sopenharmony_ci return 0; 441e1051a39Sopenharmony_ci } 442e1051a39Sopenharmony_ci return 1; 443e1051a39Sopenharmony_ci} 444e1051a39Sopenharmony_ci 445e1051a39Sopenharmony_ci/* Encoding/Padding Methods. */ 446e1051a39Sopenharmony_ci 447e1051a39Sopenharmony_ci/* Returns the number of bytes required to store 'bits' into a byte array */ 448e1051a39Sopenharmony_cistatic unsigned int get_encode_size(size_t bits) 449e1051a39Sopenharmony_ci{ 450e1051a39Sopenharmony_ci unsigned int cnt = 0, sz = sizeof(size_t); 451e1051a39Sopenharmony_ci 452e1051a39Sopenharmony_ci while (bits && (cnt < sz)) { 453e1051a39Sopenharmony_ci ++cnt; 454e1051a39Sopenharmony_ci bits >>= 8; 455e1051a39Sopenharmony_ci } 456e1051a39Sopenharmony_ci /* If bits is zero 1 byte is required */ 457e1051a39Sopenharmony_ci if (cnt == 0) 458e1051a39Sopenharmony_ci cnt = 1; 459e1051a39Sopenharmony_ci return cnt; 460e1051a39Sopenharmony_ci} 461e1051a39Sopenharmony_ci 462e1051a39Sopenharmony_ci/* 463e1051a39Sopenharmony_ci * Convert an integer into bytes . The number of bytes is appended 464e1051a39Sopenharmony_ci * to the end of the buffer. Returns an array of bytes 'out' of size 465e1051a39Sopenharmony_ci * *out_len. 466e1051a39Sopenharmony_ci * 467e1051a39Sopenharmony_ci * e.g if bits = 32, out[2] = { 0x20, 0x01 } 468e1051a39Sopenharmony_ci */ 469e1051a39Sopenharmony_cistatic int right_encode(unsigned char *out, size_t out_max_len, size_t *out_len, 470e1051a39Sopenharmony_ci size_t bits) 471e1051a39Sopenharmony_ci{ 472e1051a39Sopenharmony_ci unsigned int len = get_encode_size(bits); 473e1051a39Sopenharmony_ci int i; 474e1051a39Sopenharmony_ci 475e1051a39Sopenharmony_ci if (len >= out_max_len) { 476e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PROV, PROV_R_LENGTH_TOO_LARGE); 477e1051a39Sopenharmony_ci return 0; 478e1051a39Sopenharmony_ci } 479e1051a39Sopenharmony_ci 480e1051a39Sopenharmony_ci /* MSB's are at the start of the bytes array */ 481e1051a39Sopenharmony_ci for (i = len - 1; i >= 0; --i) { 482e1051a39Sopenharmony_ci out[i] = (unsigned char)(bits & 0xFF); 483e1051a39Sopenharmony_ci bits >>= 8; 484e1051a39Sopenharmony_ci } 485e1051a39Sopenharmony_ci /* Tack the length onto the end */ 486e1051a39Sopenharmony_ci out[len] = (unsigned char)len; 487e1051a39Sopenharmony_ci 488e1051a39Sopenharmony_ci /* The Returned length includes the tacked on byte */ 489e1051a39Sopenharmony_ci *out_len = len + 1; 490e1051a39Sopenharmony_ci return 1; 491e1051a39Sopenharmony_ci} 492e1051a39Sopenharmony_ci 493e1051a39Sopenharmony_ci/* 494e1051a39Sopenharmony_ci * Encodes a string with a left encoded length added. Note that the 495e1051a39Sopenharmony_ci * in_len is converted to bits (*8). 496e1051a39Sopenharmony_ci * 497e1051a39Sopenharmony_ci * e.g- in="KMAC" gives out[6] = { 0x01, 0x20, 0x4B, 0x4D, 0x41, 0x43 } 498e1051a39Sopenharmony_ci * len bits K M A C 499e1051a39Sopenharmony_ci */ 500e1051a39Sopenharmony_cistatic int encode_string(unsigned char *out, size_t out_max_len, size_t *out_len, 501e1051a39Sopenharmony_ci const unsigned char *in, size_t in_len) 502e1051a39Sopenharmony_ci{ 503e1051a39Sopenharmony_ci if (in == NULL) { 504e1051a39Sopenharmony_ci *out_len = 0; 505e1051a39Sopenharmony_ci } else { 506e1051a39Sopenharmony_ci size_t i, bits, len, sz; 507e1051a39Sopenharmony_ci 508e1051a39Sopenharmony_ci bits = 8 * in_len; 509e1051a39Sopenharmony_ci len = get_encode_size(bits); 510e1051a39Sopenharmony_ci sz = 1 + len + in_len; 511e1051a39Sopenharmony_ci 512e1051a39Sopenharmony_ci if (sz > out_max_len) { 513e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PROV, PROV_R_LENGTH_TOO_LARGE); 514e1051a39Sopenharmony_ci return 0; 515e1051a39Sopenharmony_ci } 516e1051a39Sopenharmony_ci 517e1051a39Sopenharmony_ci out[0] = (unsigned char)len; 518e1051a39Sopenharmony_ci for (i = len; i > 0; --i) { 519e1051a39Sopenharmony_ci out[i] = (bits & 0xFF); 520e1051a39Sopenharmony_ci bits >>= 8; 521e1051a39Sopenharmony_ci } 522e1051a39Sopenharmony_ci memcpy(out + len + 1, in, in_len); 523e1051a39Sopenharmony_ci *out_len = sz; 524e1051a39Sopenharmony_ci } 525e1051a39Sopenharmony_ci return 1; 526e1051a39Sopenharmony_ci} 527e1051a39Sopenharmony_ci 528e1051a39Sopenharmony_ci/* 529e1051a39Sopenharmony_ci * Returns a zero padded encoding of the inputs in1 and an optional 530e1051a39Sopenharmony_ci * in2 (can be NULL). The padded output must be a multiple of the blocksize 'w'. 531e1051a39Sopenharmony_ci * The value of w is in bytes (< 256). 532e1051a39Sopenharmony_ci * 533e1051a39Sopenharmony_ci * The returned output is: 534e1051a39Sopenharmony_ci * zero_padded(multiple of w, (left_encode(w) || in1 [|| in2]) 535e1051a39Sopenharmony_ci */ 536e1051a39Sopenharmony_cistatic int bytepad(unsigned char *out, size_t *out_len, 537e1051a39Sopenharmony_ci const unsigned char *in1, size_t in1_len, 538e1051a39Sopenharmony_ci const unsigned char *in2, size_t in2_len, size_t w) 539e1051a39Sopenharmony_ci{ 540e1051a39Sopenharmony_ci int len; 541e1051a39Sopenharmony_ci unsigned char *p = out; 542e1051a39Sopenharmony_ci int sz = w; 543e1051a39Sopenharmony_ci 544e1051a39Sopenharmony_ci if (out == NULL) { 545e1051a39Sopenharmony_ci if (out_len == NULL) { 546e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER); 547e1051a39Sopenharmony_ci return 0; 548e1051a39Sopenharmony_ci } 549e1051a39Sopenharmony_ci sz = 2 + in1_len + (in2 != NULL ? in2_len : 0); 550e1051a39Sopenharmony_ci *out_len = (sz + w - 1) / w * w; 551e1051a39Sopenharmony_ci return 1; 552e1051a39Sopenharmony_ci } 553e1051a39Sopenharmony_ci 554e1051a39Sopenharmony_ci if (!ossl_assert(w <= 255)) 555e1051a39Sopenharmony_ci return 0; 556e1051a39Sopenharmony_ci 557e1051a39Sopenharmony_ci /* Left encoded w */ 558e1051a39Sopenharmony_ci *p++ = 1; 559e1051a39Sopenharmony_ci *p++ = (unsigned char)w; 560e1051a39Sopenharmony_ci /* || in1 */ 561e1051a39Sopenharmony_ci memcpy(p, in1, in1_len); 562e1051a39Sopenharmony_ci p += in1_len; 563e1051a39Sopenharmony_ci /* [ || in2 ] */ 564e1051a39Sopenharmony_ci if (in2 != NULL && in2_len > 0) { 565e1051a39Sopenharmony_ci memcpy(p, in2, in2_len); 566e1051a39Sopenharmony_ci p += in2_len; 567e1051a39Sopenharmony_ci } 568e1051a39Sopenharmony_ci /* Figure out the pad size (divisible by w) */ 569e1051a39Sopenharmony_ci len = p - out; 570e1051a39Sopenharmony_ci sz = (len + w - 1) / w * w; 571e1051a39Sopenharmony_ci /* zero pad the end of the buffer */ 572e1051a39Sopenharmony_ci if (sz != len) 573e1051a39Sopenharmony_ci memset(p, 0, sz - len); 574e1051a39Sopenharmony_ci if (out_len != NULL) 575e1051a39Sopenharmony_ci *out_len = sz; 576e1051a39Sopenharmony_ci return 1; 577e1051a39Sopenharmony_ci} 578e1051a39Sopenharmony_ci 579e1051a39Sopenharmony_ci/* Returns out = bytepad(encode_string(in), w) */ 580e1051a39Sopenharmony_cistatic int kmac_bytepad_encode_key(unsigned char *out, size_t out_max_len, 581e1051a39Sopenharmony_ci size_t *out_len, 582e1051a39Sopenharmony_ci const unsigned char *in, size_t in_len, 583e1051a39Sopenharmony_ci size_t w) 584e1051a39Sopenharmony_ci{ 585e1051a39Sopenharmony_ci unsigned char tmp[KMAC_MAX_KEY + KMAC_MAX_ENCODED_HEADER_LEN]; 586e1051a39Sopenharmony_ci size_t tmp_len; 587e1051a39Sopenharmony_ci 588e1051a39Sopenharmony_ci if (!encode_string(tmp, sizeof(tmp), &tmp_len, in, in_len)) 589e1051a39Sopenharmony_ci return 0; 590e1051a39Sopenharmony_ci if (!bytepad(NULL, out_len, tmp, tmp_len, NULL, 0, w)) 591e1051a39Sopenharmony_ci return 0; 592e1051a39Sopenharmony_ci if (!ossl_assert(*out_len <= out_max_len)) 593e1051a39Sopenharmony_ci return 0; 594e1051a39Sopenharmony_ci return bytepad(out, NULL, tmp, tmp_len, NULL, 0, w); 595e1051a39Sopenharmony_ci} 596e1051a39Sopenharmony_ci 597e1051a39Sopenharmony_ciconst OSSL_DISPATCH ossl_kmac128_functions[] = { 598e1051a39Sopenharmony_ci { OSSL_FUNC_MAC_NEWCTX, (void (*)(void))kmac128_new }, 599e1051a39Sopenharmony_ci { OSSL_FUNC_MAC_DUPCTX, (void (*)(void))kmac_dup }, 600e1051a39Sopenharmony_ci { OSSL_FUNC_MAC_FREECTX, (void (*)(void))kmac_free }, 601e1051a39Sopenharmony_ci { OSSL_FUNC_MAC_INIT, (void (*)(void))kmac_init }, 602e1051a39Sopenharmony_ci { OSSL_FUNC_MAC_UPDATE, (void (*)(void))kmac_update }, 603e1051a39Sopenharmony_ci { OSSL_FUNC_MAC_FINAL, (void (*)(void))kmac_final }, 604e1051a39Sopenharmony_ci { OSSL_FUNC_MAC_GETTABLE_CTX_PARAMS, 605e1051a39Sopenharmony_ci (void (*)(void))kmac_gettable_ctx_params }, 606e1051a39Sopenharmony_ci { OSSL_FUNC_MAC_GET_CTX_PARAMS, (void (*)(void))kmac_get_ctx_params }, 607e1051a39Sopenharmony_ci { OSSL_FUNC_MAC_SETTABLE_CTX_PARAMS, 608e1051a39Sopenharmony_ci (void (*)(void))kmac_settable_ctx_params }, 609e1051a39Sopenharmony_ci { OSSL_FUNC_MAC_SET_CTX_PARAMS, (void (*)(void))kmac_set_ctx_params }, 610e1051a39Sopenharmony_ci { 0, NULL } 611e1051a39Sopenharmony_ci}; 612e1051a39Sopenharmony_ci 613e1051a39Sopenharmony_ciconst OSSL_DISPATCH ossl_kmac256_functions[] = { 614e1051a39Sopenharmony_ci { OSSL_FUNC_MAC_NEWCTX, (void (*)(void))kmac256_new }, 615e1051a39Sopenharmony_ci { OSSL_FUNC_MAC_DUPCTX, (void (*)(void))kmac_dup }, 616e1051a39Sopenharmony_ci { OSSL_FUNC_MAC_FREECTX, (void (*)(void))kmac_free }, 617e1051a39Sopenharmony_ci { OSSL_FUNC_MAC_INIT, (void (*)(void))kmac_init }, 618e1051a39Sopenharmony_ci { OSSL_FUNC_MAC_UPDATE, (void (*)(void))kmac_update }, 619e1051a39Sopenharmony_ci { OSSL_FUNC_MAC_FINAL, (void (*)(void))kmac_final }, 620e1051a39Sopenharmony_ci { OSSL_FUNC_MAC_GETTABLE_CTX_PARAMS, 621e1051a39Sopenharmony_ci (void (*)(void))kmac_gettable_ctx_params }, 622e1051a39Sopenharmony_ci { OSSL_FUNC_MAC_GET_CTX_PARAMS, (void (*)(void))kmac_get_ctx_params }, 623e1051a39Sopenharmony_ci { OSSL_FUNC_MAC_SETTABLE_CTX_PARAMS, 624e1051a39Sopenharmony_ci (void (*)(void))kmac_settable_ctx_params }, 625e1051a39Sopenharmony_ci { OSSL_FUNC_MAC_SET_CTX_PARAMS, (void (*)(void))kmac_set_ctx_params }, 626e1051a39Sopenharmony_ci { 0, NULL } 627e1051a39Sopenharmony_ci}; 628