From: Richard Levitte Date: Fri, 4 Oct 2019 08:24:09 +0000 (+0200) Subject: Providers: move common exchange,kdfs,keymgmt,macs,signature X-Git-Tag: openssl-3.0.0-alpha1~1172 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=5687e357c60b31dc274c6d14f1cd623d0cff469b;p=oweals%2Fopenssl.git Providers: move common exchange,kdfs,keymgmt,macs,signature From providers/common/ to providers/implementations/ Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/10088) --- diff --git a/providers/build.info b/providers/build.info index e951c6229d..973adac5c7 100644 --- a/providers/build.info +++ b/providers/build.info @@ -28,7 +28,7 @@ # FIPS_MODE undefined. The default and legacy # providers use this. -SUBDIRS=common default +SUBDIRS=common default implementations INCLUDE[../libcrypto]=common/include diff --git a/providers/common/build.info b/providers/common/build.info index 95c2fd107e..4e662eb97a 100644 --- a/providers/common/build.info +++ b/providers/common/build.info @@ -1,4 +1,4 @@ -SUBDIRS=digests ciphers macs kdfs exchange keymgmt signature +SUBDIRS=digests ciphers SOURCE[../libcommon.a]=provider_err.c provlib.c $FIPSCOMMON=provider_util.c diff --git a/providers/common/exchange/build.info b/providers/common/exchange/build.info deleted file mode 100644 index 90ea0c9a02..0000000000 --- a/providers/common/exchange/build.info +++ /dev/null @@ -1,5 +0,0 @@ -$GOAL=../../libimplementations.a - -IF[{- !$disabled{dh} -}] - SOURCE[$GOAL]=dh_exch.c -ENDIF diff --git a/providers/common/exchange/dh_exch.c b/providers/common/exchange/dh_exch.c deleted file mode 100644 index cfbda43fb8..0000000000 --- a/providers/common/exchange/dh_exch.c +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright 2019 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 - */ - -#include -#include -#include -#include -#include -#include "internal/provider_algs.h" - -static OSSL_OP_keyexch_newctx_fn dh_newctx; -static OSSL_OP_keyexch_init_fn dh_init; -static OSSL_OP_keyexch_set_peer_fn dh_set_peer; -static OSSL_OP_keyexch_derive_fn dh_derive; -static OSSL_OP_keyexch_freectx_fn dh_freectx; -static OSSL_OP_keyexch_dupctx_fn dh_dupctx; -static OSSL_OP_keyexch_set_ctx_params_fn dh_set_ctx_params; -static OSSL_OP_keyexch_settable_ctx_params_fn dh_settable_ctx_params; - -/* - * What's passed as an actual key is defined by the KEYMGMT interface. - * We happen to know that our KEYMGMT simply passes DH structures, so - * we use that here too. - */ - -typedef struct { - DH *dh; - DH *dhpeer; - unsigned int pad : 1; -} PROV_DH_CTX; - -static void *dh_newctx(void *provctx) -{ - return OPENSSL_zalloc(sizeof(PROV_DH_CTX)); -} - -static int dh_init(void *vpdhctx, void *vdh) -{ - PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx; - - if (pdhctx == NULL || vdh == NULL || !DH_up_ref(vdh)) - return 0; - DH_free(pdhctx->dh); - pdhctx->dh = vdh; - return 1; -} - -static int dh_set_peer(void *vpdhctx, void *vdh) -{ - PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx; - - if (pdhctx == NULL || vdh == NULL || !DH_up_ref(vdh)) - return 0; - DH_free(pdhctx->dhpeer); - pdhctx->dhpeer = vdh; - return 1; -} - -static int dh_derive(void *vpdhctx, unsigned char *secret, size_t *secretlen, - size_t outlen) -{ - PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx; - int ret; - size_t dhsize; - const BIGNUM *pub_key = NULL; - - /* TODO(3.0): Add errors to stack */ - if (pdhctx->dh == NULL || pdhctx->dhpeer == NULL) - return 0; - - dhsize = (size_t)DH_size(pdhctx->dh); - if (secret == NULL) { - *secretlen = dhsize; - return 1; - } - if (outlen < dhsize) - return 0; - - DH_get0_key(pdhctx->dhpeer, &pub_key, NULL); - ret = (pdhctx->pad) ? DH_compute_key_padded(secret, pub_key, pdhctx->dh) - : DH_compute_key(secret, pub_key, pdhctx->dh); - if (ret <= 0) - return 0; - - *secretlen = ret; - return 1; -} - -static void dh_freectx(void *vpdhctx) -{ - PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx; - - DH_free(pdhctx->dh); - DH_free(pdhctx->dhpeer); - - OPENSSL_free(pdhctx); -} - -static void *dh_dupctx(void *vpdhctx) -{ - PROV_DH_CTX *srcctx = (PROV_DH_CTX *)vpdhctx; - PROV_DH_CTX *dstctx; - - dstctx = OPENSSL_zalloc(sizeof(*srcctx)); - if (dstctx == NULL) - return NULL; - - *dstctx = *srcctx; - if (dstctx->dh != NULL && !DH_up_ref(dstctx->dh)) { - OPENSSL_free(dstctx); - return NULL; - } - - if (dstctx->dhpeer != NULL && !DH_up_ref(dstctx->dhpeer)) { - DH_free(dstctx->dh); - OPENSSL_free(dstctx); - return NULL; - } - - return dstctx; -} - -static int dh_set_ctx_params(void *vpdhctx, const OSSL_PARAM params[]) -{ - PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx; - const OSSL_PARAM *p; - unsigned int pad; - - if (pdhctx == NULL || params == NULL) - return 0; - - p = OSSL_PARAM_locate_const(params, OSSL_EXCHANGE_PARAM_PAD); - if (p == NULL || !OSSL_PARAM_get_uint(p, &pad)) - return 0; - pdhctx->pad = pad ? 1 : 0; - return 1; -} - -static const OSSL_PARAM known_settable_ctx_params[] = { - OSSL_PARAM_int(OSSL_EXCHANGE_PARAM_PAD, NULL), - OSSL_PARAM_END -}; - -static const OSSL_PARAM *dh_settable_ctx_params(void) -{ - return known_settable_ctx_params; -} - -const OSSL_DISPATCH dh_keyexch_functions[] = { - { OSSL_FUNC_KEYEXCH_NEWCTX, (void (*)(void))dh_newctx }, - { OSSL_FUNC_KEYEXCH_INIT, (void (*)(void))dh_init }, - { OSSL_FUNC_KEYEXCH_DERIVE, (void (*)(void))dh_derive }, - { OSSL_FUNC_KEYEXCH_SET_PEER, (void (*)(void))dh_set_peer }, - { OSSL_FUNC_KEYEXCH_FREECTX, (void (*)(void))dh_freectx }, - { OSSL_FUNC_KEYEXCH_DUPCTX, (void (*)(void))dh_dupctx }, - { OSSL_FUNC_KEYEXCH_SET_CTX_PARAMS, (void (*)(void))dh_set_ctx_params }, - { OSSL_FUNC_KEYEXCH_SETTABLE_CTX_PARAMS, - (void (*)(void))dh_settable_ctx_params }, - { 0, NULL } -}; diff --git a/providers/common/kdfs/build.info b/providers/common/kdfs/build.info deleted file mode 100644 index b2b354dc34..0000000000 --- a/providers/common/kdfs/build.info +++ /dev/null @@ -1,5 +0,0 @@ -$GOAL=../../libimplementations.a - -SOURCE[$GOAL]=tls1_prf.c hkdf.c kbkdf.c pbkdf2.c sskdf.c -SOURCE[../../libfips.a]=pbkdf2_fips.c -SOURCE[../../libnonfips.a]=pbkdf2_fips.c diff --git a/providers/common/kdfs/hkdf.c b/providers/common/kdfs/hkdf.c deleted file mode 100644 index 041811f0e1..0000000000 --- a/providers/common/kdfs/hkdf.c +++ /dev/null @@ -1,463 +0,0 @@ -/* - * Copyright 2016-2019 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 - */ - -#include -#include -#include -#include -#include -#include -#include -#include "internal/cryptlib.h" -#include "internal/numbers.h" -#include "crypto/evp.h" -#include "internal/provider_ctx.h" -#include "internal/providercommonerr.h" -#include "internal/provider_algs.h" -#include "internal/provider_util.h" -#include "e_os.h" - -#define HKDF_MAXBUF 1024 - -static OSSL_OP_kdf_newctx_fn kdf_hkdf_new; -static OSSL_OP_kdf_freectx_fn kdf_hkdf_free; -static OSSL_OP_kdf_reset_fn kdf_hkdf_reset; -static OSSL_OP_kdf_derive_fn kdf_hkdf_derive; -static OSSL_OP_kdf_settable_ctx_params_fn kdf_hkdf_settable_ctx_params; -static OSSL_OP_kdf_set_ctx_params_fn kdf_hkdf_set_ctx_params; -static OSSL_OP_kdf_gettable_ctx_params_fn kdf_hkdf_gettable_ctx_params; -static OSSL_OP_kdf_get_ctx_params_fn kdf_hkdf_get_ctx_params; - -static int HKDF(const EVP_MD *evp_md, - const unsigned char *salt, size_t salt_len, - const unsigned char *key, size_t key_len, - const unsigned char *info, size_t info_len, - unsigned char *okm, size_t okm_len); -static int HKDF_Extract(const EVP_MD *evp_md, - const unsigned char *salt, size_t salt_len, - const unsigned char *ikm, size_t ikm_len, - unsigned char *prk, size_t prk_len); -static int HKDF_Expand(const EVP_MD *evp_md, - const unsigned char *prk, size_t prk_len, - const unsigned char *info, size_t info_len, - unsigned char *okm, size_t okm_len); - -typedef struct { - void *provctx; - int mode; - PROV_DIGEST digest; - unsigned char *salt; - size_t salt_len; - unsigned char *key; - size_t key_len; - unsigned char info[HKDF_MAXBUF]; - size_t info_len; -} KDF_HKDF; - -static void *kdf_hkdf_new(void *provctx) -{ - KDF_HKDF *ctx; - - if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) - ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); - else - ctx->provctx = provctx; - return ctx; -} - -static void kdf_hkdf_free(void *vctx) -{ - KDF_HKDF *ctx = (KDF_HKDF *)vctx; - - kdf_hkdf_reset(ctx); - OPENSSL_free(ctx); -} - -static void kdf_hkdf_reset(void *vctx) -{ - KDF_HKDF *ctx = (KDF_HKDF *)vctx; - - ossl_prov_digest_reset(&ctx->digest); - OPENSSL_free(ctx->salt); - OPENSSL_clear_free(ctx->key, ctx->key_len); - OPENSSL_cleanse(ctx->info, ctx->info_len); - memset(ctx, 0, sizeof(*ctx)); -} - -static size_t kdf_hkdf_size(KDF_HKDF *ctx) -{ - int sz; - const EVP_MD *md = ossl_prov_digest_md(&ctx->digest); - - if (ctx->mode != EVP_KDF_HKDF_MODE_EXTRACT_ONLY) - return SIZE_MAX; - - if (md == NULL) { - ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST); - return 0; - } - sz = EVP_MD_size(md); - if (sz < 0) - return 0; - - return sz; -} - -static int kdf_hkdf_derive(void *vctx, unsigned char *key, size_t keylen) -{ - KDF_HKDF *ctx = (KDF_HKDF *)vctx; - const EVP_MD *md = ossl_prov_digest_md(&ctx->digest); - - if (md == NULL) { - ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST); - return 0; - } - if (ctx->key == NULL) { - ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_KEY); - return 0; - } - - switch (ctx->mode) { - case EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND: - return HKDF(md, ctx->salt, ctx->salt_len, ctx->key, - ctx->key_len, ctx->info, ctx->info_len, key, - keylen); - - case EVP_KDF_HKDF_MODE_EXTRACT_ONLY: - return HKDF_Extract(md, ctx->salt, ctx->salt_len, ctx->key, - ctx->key_len, key, keylen); - - case EVP_KDF_HKDF_MODE_EXPAND_ONLY: - return HKDF_Expand(md, ctx->key, ctx->key_len, ctx->info, - ctx->info_len, key, keylen); - - default: - return 0; - } -} - -static int kdf_hkdf_set_ctx_params(void *vctx, const OSSL_PARAM params[]) -{ - const OSSL_PARAM *p; - KDF_HKDF *ctx = vctx; - OPENSSL_CTX *provctx = PROV_LIBRARY_CONTEXT_OF(ctx->provctx); - int n; - - if (!ossl_prov_digest_load_from_params(&ctx->digest, params, provctx)) - return 0; - - if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_MODE)) != NULL) { - if (p->data_type == OSSL_PARAM_UTF8_STRING) { - if (strcasecmp(p->data, "EXTRACT_AND_EXPAND") == 0) { - ctx->mode = EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND; - } else if (strcasecmp(p->data, "EXTRACT_ONLY") == 0) { - ctx->mode = EVP_KDF_HKDF_MODE_EXTRACT_ONLY; - } else if (strcasecmp(p->data, "EXPAND_ONLY") == 0) { - ctx->mode = EVP_KDF_HKDF_MODE_EXPAND_ONLY; - } else { - ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_MODE); - return 0; - } - } else if (OSSL_PARAM_get_int(p, &n)) { - if (n != EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND - && n != EVP_KDF_HKDF_MODE_EXTRACT_ONLY - && n != EVP_KDF_HKDF_MODE_EXPAND_ONLY) { - ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_MODE); - return 0; - } - ctx->mode = n; - } else { - ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_MODE); - return 0; - } - } - - if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_KEY)) != NULL) { - OPENSSL_clear_free(ctx->key, ctx->key_len); - ctx->key = NULL; - if (!OSSL_PARAM_get_octet_string(p, (void **)&ctx->key, 0, - &ctx->key_len)) - return 0; - } - - if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SALT)) != NULL) { - if (p->data_size != 0 && p->data != NULL) { - OPENSSL_free(ctx->salt); - ctx->salt = NULL; - if (!OSSL_PARAM_get_octet_string(p, (void **)&ctx->salt, 0, - &ctx->salt_len)) - return 0; - } - } - /* The info fields concatenate, so process them all */ - if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_INFO)) != NULL) { - ctx->info_len = 0; - for (; p != NULL; p = OSSL_PARAM_locate_const(p + 1, - OSSL_KDF_PARAM_INFO)) { - const void *q = ctx->info + ctx->info_len; - size_t sz = 0; - - if (p->data_size != 0 - && p->data != NULL - && !OSSL_PARAM_get_octet_string(p, (void **)&q, - HKDF_MAXBUF - ctx->info_len, - &sz)) - return 0; - ctx->info_len += sz; - } - } - return 1; -} - -static const OSSL_PARAM *kdf_hkdf_settable_ctx_params(void) -{ - static const OSSL_PARAM known_settable_ctx_params[] = { - OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_MODE, NULL, 0), - OSSL_PARAM_int(OSSL_KDF_PARAM_MODE, NULL), - OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES, NULL, 0), - OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_DIGEST, NULL, 0), - OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SALT, NULL, 0), - OSSL_PARAM_octet_string(OSSL_KDF_PARAM_KEY, NULL, 0), - OSSL_PARAM_octet_string(OSSL_KDF_PARAM_INFO, NULL, 0), - OSSL_PARAM_END - }; - return known_settable_ctx_params; -} - -static int kdf_hkdf_get_ctx_params(void *vctx, OSSL_PARAM params[]) -{ - KDF_HKDF *ctx = (KDF_HKDF *)vctx; - OSSL_PARAM *p; - - if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE)) != NULL) - return OSSL_PARAM_set_size_t(p, kdf_hkdf_size(ctx)); - return -2; -} - -static const OSSL_PARAM *kdf_hkdf_gettable_ctx_params(void) -{ - static const OSSL_PARAM known_gettable_ctx_params[] = { - OSSL_PARAM_size_t(OSSL_KDF_PARAM_SIZE, NULL), - OSSL_PARAM_END - }; - return known_gettable_ctx_params; -} - -const OSSL_DISPATCH kdf_hkdf_functions[] = { - { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))kdf_hkdf_new }, - { OSSL_FUNC_KDF_FREECTX, (void(*)(void))kdf_hkdf_free }, - { OSSL_FUNC_KDF_RESET, (void(*)(void))kdf_hkdf_reset }, - { OSSL_FUNC_KDF_DERIVE, (void(*)(void))kdf_hkdf_derive }, - { OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS, - (void(*)(void))kdf_hkdf_settable_ctx_params }, - { OSSL_FUNC_KDF_SET_CTX_PARAMS, (void(*)(void))kdf_hkdf_set_ctx_params }, - { OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS, - (void(*)(void))kdf_hkdf_gettable_ctx_params }, - { OSSL_FUNC_KDF_GET_CTX_PARAMS, (void(*)(void))kdf_hkdf_get_ctx_params }, - { 0, NULL } -}; - -/* - * Refer to "HMAC-based Extract-and-Expand Key Derivation Function (HKDF)" - * Section 2 (https://tools.ietf.org/html/rfc5869#section-2) and - * "Cryptographic Extraction and Key Derivation: The HKDF Scheme" - * Section 4.2 (https://eprint.iacr.org/2010/264.pdf). - * - * From the paper: - * The scheme HKDF is specified as: - * HKDF(XTS, SKM, CTXinfo, L) = K(1) | K(2) | ... | K(t) - * - * where: - * SKM is source key material - * XTS is extractor salt (which may be null or constant) - * CTXinfo is context information (may be null) - * L is the number of key bits to be produced by KDF - * k is the output length in bits of the hash function used with HMAC - * t = ceil(L/k) - * the value K(t) is truncated to its first d = L mod k bits. - * - * From RFC 5869: - * 2.2. Step 1: Extract - * HKDF-Extract(salt, IKM) -> PRK - * 2.3. Step 2: Expand - * HKDF-Expand(PRK, info, L) -> OKM - */ -static int HKDF(const EVP_MD *evp_md, - const unsigned char *salt, size_t salt_len, - const unsigned char *ikm, size_t ikm_len, - const unsigned char *info, size_t info_len, - unsigned char *okm, size_t okm_len) -{ - unsigned char prk[EVP_MAX_MD_SIZE]; - int ret, sz; - size_t prk_len; - - sz = EVP_MD_size(evp_md); - if (sz < 0) - return 0; - prk_len = (size_t)sz; - - /* Step 1: HKDF-Extract(salt, IKM) -> PRK */ - if (!HKDF_Extract(evp_md, salt, salt_len, ikm, ikm_len, prk, prk_len)) - return 0; - - /* Step 2: HKDF-Expand(PRK, info, L) -> OKM */ - ret = HKDF_Expand(evp_md, prk, prk_len, info, info_len, okm, okm_len); - OPENSSL_cleanse(prk, sizeof(prk)); - - return ret; -} - -/* - * Refer to "HMAC-based Extract-and-Expand Key Derivation Function (HKDF)" - * Section 2.2 (https://tools.ietf.org/html/rfc5869#section-2.2). - * - * 2.2. Step 1: Extract - * - * HKDF-Extract(salt, IKM) -> PRK - * - * Options: - * Hash a hash function; HashLen denotes the length of the - * hash function output in octets - * - * Inputs: - * salt optional salt value (a non-secret random value); - * if not provided, it is set to a string of HashLen zeros. - * IKM input keying material - * - * Output: - * PRK a pseudorandom key (of HashLen octets) - * - * The output PRK is calculated as follows: - * - * PRK = HMAC-Hash(salt, IKM) - */ -static int HKDF_Extract(const EVP_MD *evp_md, - const unsigned char *salt, size_t salt_len, - const unsigned char *ikm, size_t ikm_len, - unsigned char *prk, size_t prk_len) -{ - int sz = EVP_MD_size(evp_md); - - if (sz < 0) - return 0; - if (prk_len != (size_t)sz) { - ERR_raise(ERR_LIB_PROV, PROV_R_WRONG_OUTPUT_BUFFER_SIZE); - return 0; - } - /* calc: PRK = HMAC-Hash(salt, IKM) */ - return HMAC(evp_md, salt, salt_len, ikm, ikm_len, prk, NULL) != NULL; -} - -/* - * Refer to "HMAC-based Extract-and-Expand Key Derivation Function (HKDF)" - * Section 2.3 (https://tools.ietf.org/html/rfc5869#section-2.3). - * - * 2.3. Step 2: Expand - * - * HKDF-Expand(PRK, info, L) -> OKM - * - * Options: - * Hash a hash function; HashLen denotes the length of the - * hash function output in octets - * - * Inputs: - * PRK a pseudorandom key of at least HashLen octets - * (usually, the output from the extract step) - * info optional context and application specific information - * (can be a zero-length string) - * L length of output keying material in octets - * (<= 255*HashLen) - * - * Output: - * OKM output keying material (of L octets) - * - * The output OKM is calculated as follows: - * - * N = ceil(L/HashLen) - * T = T(1) | T(2) | T(3) | ... | T(N) - * OKM = first L octets of T - * - * where: - * T(0) = empty string (zero length) - * T(1) = HMAC-Hash(PRK, T(0) | info | 0x01) - * T(2) = HMAC-Hash(PRK, T(1) | info | 0x02) - * T(3) = HMAC-Hash(PRK, T(2) | info | 0x03) - * ... - * - * (where the constant concatenated to the end of each T(n) is a - * single octet.) - */ -static int HKDF_Expand(const EVP_MD *evp_md, - const unsigned char *prk, size_t prk_len, - const unsigned char *info, size_t info_len, - unsigned char *okm, size_t okm_len) -{ - HMAC_CTX *hmac; - int ret = 0, sz; - unsigned int i; - unsigned char prev[EVP_MAX_MD_SIZE]; - size_t done_len = 0, dig_len, n; - - sz = EVP_MD_size(evp_md); - if (sz <= 0) - return 0; - dig_len = (size_t)sz; - - /* calc: N = ceil(L/HashLen) */ - n = okm_len / dig_len; - if (okm_len % dig_len) - n++; - - if (n > 255 || okm == NULL) - return 0; - - if ((hmac = HMAC_CTX_new()) == NULL) - return 0; - - if (!HMAC_Init_ex(hmac, prk, prk_len, evp_md, NULL)) - goto err; - - for (i = 1; i <= n; i++) { - size_t copy_len; - const unsigned char ctr = i; - - /* calc: T(i) = HMAC-Hash(PRK, T(i - 1) | info | i) */ - if (i > 1) { - if (!HMAC_Init_ex(hmac, NULL, 0, NULL, NULL)) - goto err; - - if (!HMAC_Update(hmac, prev, dig_len)) - goto err; - } - - if (!HMAC_Update(hmac, info, info_len)) - goto err; - - if (!HMAC_Update(hmac, &ctr, 1)) - goto err; - - if (!HMAC_Final(hmac, prev, NULL)) - goto err; - - copy_len = (done_len + dig_len > okm_len) ? - okm_len - done_len : - dig_len; - - memcpy(okm + done_len, prev, copy_len); - - done_len += copy_len; - } - ret = 1; - - err: - OPENSSL_cleanse(prev, sizeof(prev)); - HMAC_CTX_free(hmac); - return ret; -} diff --git a/providers/common/kdfs/kbkdf.c b/providers/common/kdfs/kbkdf.c deleted file mode 100644 index ffffef0b17..0000000000 --- a/providers/common/kdfs/kbkdf.c +++ /dev/null @@ -1,303 +0,0 @@ -/* - * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. - * Copyright 2019 Red Hat, Inc. - * - * 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 - */ - -/* - * This implements https://csrc.nist.gov/publications/detail/sp/800-108/final - * section 5.1 ("counter mode") in HMAC only. That document does not name the - * KDFs it defines; the name is derived from - * https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/Key-Derivation - * - * Note that sections 5.2 ("feedback mode") and 5.3 ("double-pipeline mode") - * are not implemented, though it would be possible to do so in the future. - * CMAC mode is also not implemented; some plumbing would be required. - * - * These versions all assume the counter is used. It would be relatively - * straightforward to expose a configuration handle should the need arise. - * - * Variable names attempt to match those of SP800-108. - */ - -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "internal/cryptlib.h" -#include "crypto/evp.h" -#include "internal/numbers.h" -#include "internal/provider_algs.h" -#include "internal/provider_ctx.h" -#include "internal/provider_util.h" -#include "internal/providercommonerr.h" - -#include "e_os.h" - -#define MIN(a, b) ((a) < (b)) ? (a) : (b) - -/* Our context structure. */ -typedef struct { - void *provctx; - EVP_MAC_CTX *ctx_init; - - /* Names are lowercased versions of those found in SP800-108. */ - unsigned char *ki; - size_t ki_len; - unsigned char *label; - size_t label_len; - unsigned char *context; - size_t context_len; -} KBKDF; - -/* Definitions needed for typechecking. */ -static OSSL_OP_kdf_newctx_fn kbkdf_new; -static OSSL_OP_kdf_freectx_fn kbkdf_free; -static OSSL_OP_kdf_reset_fn kbkdf_reset; -static OSSL_OP_kdf_derive_fn kbkdf_derive; -static OSSL_OP_kdf_settable_ctx_params_fn kbkdf_settable_ctx_params; -static OSSL_OP_kdf_set_ctx_params_fn kbkdf_set_ctx_params; - -/* Not all platforms have htobe32(). */ -static uint32_t be32(uint32_t host) -{ - uint32_t big = 0; - const union { - long one; - char little; - } is_endian = { 1 }; - - if (!is_endian.little) - return host; - - big |= (host & 0xff000000) >> 24; - big |= (host & 0x00ff0000) >> 8; - big |= (host & 0x0000ff00) << 8; - big |= (host & 0x000000ff) << 24; - return big; -} - -static void *kbkdf_new(void *provctx) -{ - KBKDF *ctx; - - ctx = OPENSSL_zalloc(sizeof(*ctx)); - if (ctx == NULL) { - ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); - return NULL; - } - - ctx->provctx = provctx; - return ctx; -} - -static void kbkdf_free(void *vctx) -{ - KBKDF *ctx = (KBKDF *)vctx; - - kbkdf_reset(ctx); - OPENSSL_free(ctx); -} - -static void kbkdf_reset(void *vctx) -{ - KBKDF *ctx = (KBKDF *)vctx; - - EVP_MAC_CTX_free(ctx->ctx_init); - OPENSSL_clear_free(ctx->context, ctx->context_len); - OPENSSL_clear_free(ctx->label, ctx->label_len); - OPENSSL_clear_free(ctx->ki, ctx->ki_len); - memset(ctx, 0, sizeof(*ctx)); -} - -/* SP800-108 section 5.1. */ -static int kbkdf_derive_counter(EVP_MAC_CTX *ctx_init, - unsigned char *label, size_t label_len, - unsigned char *context, size_t context_len, - unsigned char *k_i, size_t h, uint32_t l, - unsigned char *ko, size_t ko_len) -{ - int ret = 0; - EVP_MAC_CTX *ctx = NULL; - size_t written = 0, to_write; - const unsigned char zero = 0; - uint32_t counter, i; - - for (counter = 1; written < ko_len; counter++) { - i = be32(counter); - - ctx = EVP_MAC_CTX_dup(ctx_init); - if (ctx == NULL) - goto done; - - if (!EVP_MAC_update(ctx, (unsigned char *)&i, 4) - || !EVP_MAC_update(ctx, label, label_len) - || !EVP_MAC_update(ctx, &zero, 1) - || !EVP_MAC_update(ctx, context, context_len) - || !EVP_MAC_update(ctx, (unsigned char *)&l, 4) - || !EVP_MAC_final(ctx, k_i, NULL, h)) - goto done; - - to_write = ko_len - written; - memcpy(ko + written, k_i, MIN(to_write, h)); - written += h; - - EVP_MAC_CTX_free(ctx); - ctx = NULL; - } - - ret = 1; -done: - EVP_MAC_CTX_free(ctx); - return ret; -} - -static int kbkdf_derive(void *vctx, unsigned char *key, size_t keylen) -{ - KBKDF *ctx = (KBKDF *)vctx; - int ret = 0; - unsigned char *k_i = NULL; - uint32_t l = be32(keylen * 8); - size_t h = 0; - - /* Label and Context are permitted to be empty. Check everything else. */ - if (ctx->ctx_init == NULL) { - if (ctx->ki_len == 0 || ctx->ki == NULL) { - ERR_raise(ERR_LIB_PROV, PROV_R_NO_KEY_SET); - return 0; - } - /* Could either be missing MAC or missing message digest - - * arbitrarily, I pick this one. */ - ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MAC); - return 0; - } - - h = EVP_MAC_size(ctx->ctx_init); - if (h == 0) - goto done; - - k_i = OPENSSL_zalloc(h); - if (k_i == NULL) - goto done; - - ret = kbkdf_derive_counter( - ctx->ctx_init, ctx->label, ctx->label_len, ctx->context, - ctx->context_len, k_i, h, l, key, keylen); -done: - if (ret != 1) - OPENSSL_cleanse(key, keylen); - OPENSSL_clear_free(k_i, h); - return ret; -} - -static int kbkdf_set_buffer(unsigned char **out, size_t *out_len, - const OSSL_PARAM *p) -{ - if (p->data == NULL || p->data_size == 0) - return 1; - - OPENSSL_clear_free(*out, *out_len); - *out = NULL; - return OSSL_PARAM_get_octet_string(p, (void **)out, 0, out_len); -} - -static int kbkdf_set_ctx_params(void *vctx, const OSSL_PARAM params[]) -{ - KBKDF *ctx = (KBKDF *)vctx; - OPENSSL_CTX *libctx = PROV_LIBRARY_CONTEXT_OF(ctx->provctx); - const OSSL_PARAM *p; - OSSL_PARAM mparams[2]; - - if (!ossl_prov_macctx_load_from_params(&ctx->ctx_init, params, NULL, - NULL, NULL, libctx)) - return 0; - else if (ctx->ctx_init != NULL - && !EVP_MAC_is_a(EVP_MAC_CTX_mac(ctx->ctx_init), - OSSL_MAC_NAME_HMAC)) { - ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_MAC); - return 0; - } - - p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_KEY); - if (p != NULL && !kbkdf_set_buffer(&ctx->ki, &ctx->ki_len, p)) - return 0; - - p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SALT); - if (p != NULL && !kbkdf_set_buffer(&ctx->label, &ctx->label_len, p)) - return 0; - - p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_INFO); - if (p != NULL && !kbkdf_set_buffer(&ctx->context, &ctx->context_len, p)) - return 0; - - /* Set up digest context, if we can. */ - if (ctx->ctx_init != NULL && ctx->ki_len != 0) { - mparams[0] = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY, - ctx->ki, ctx->ki_len); - mparams[1] = OSSL_PARAM_construct_end(); - - if (!EVP_MAC_CTX_set_params(ctx->ctx_init, mparams) - || !EVP_MAC_init(ctx->ctx_init)) - return 0; - } - - return 1; -} - -static const OSSL_PARAM *kbkdf_settable_ctx_params(void) -{ - static const OSSL_PARAM known_settable_ctx_params[] = { - OSSL_PARAM_octet_string(OSSL_KDF_PARAM_INFO, NULL, 0), - OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SALT, NULL, 0), - OSSL_PARAM_octet_string(OSSL_KDF_PARAM_KEY, NULL, 0), - OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_DIGEST, NULL, 0), - OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_MAC, NULL, 0), - - OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES, NULL, 0), - OSSL_PARAM_END, - }; - return known_settable_ctx_params; -} - -static int kbkdf_get_ctx_params(void *vctx, OSSL_PARAM params[]) -{ - OSSL_PARAM *p; - - p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE); - if (p == NULL) - return -2; - - /* KBKDF can produce results as large as you like. */ - return OSSL_PARAM_set_size_t(p, SIZE_MAX); -} - -static const OSSL_PARAM *kbkdf_gettable_ctx_params(void) -{ - static const OSSL_PARAM known_gettable_ctx_params[] = - { OSSL_PARAM_size_t(OSSL_KDF_PARAM_SIZE, NULL), OSSL_PARAM_END }; - return known_gettable_ctx_params; -} - -const OSSL_DISPATCH kdf_kbkdf_functions[] = { - { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))kbkdf_new }, - { OSSL_FUNC_KDF_FREECTX, (void(*)(void))kbkdf_free }, - { OSSL_FUNC_KDF_RESET, (void(*)(void))kbkdf_reset }, - { OSSL_FUNC_KDF_DERIVE, (void(*)(void))kbkdf_derive }, - { OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS, - (void(*)(void))kbkdf_settable_ctx_params }, - { OSSL_FUNC_KDF_SET_CTX_PARAMS, (void(*)(void))kbkdf_set_ctx_params }, - { OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS, - (void(*)(void))kbkdf_gettable_ctx_params }, - { OSSL_FUNC_KDF_GET_CTX_PARAMS, (void(*)(void))kbkdf_get_ctx_params }, - { 0, NULL }, -}; diff --git a/providers/common/kdfs/pbkdf2.c b/providers/common/kdfs/pbkdf2.c deleted file mode 100644 index 68aa0aa7c4..0000000000 --- a/providers/common/kdfs/pbkdf2.c +++ /dev/null @@ -1,336 +0,0 @@ -/* - * Copyright 2018-2019 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 - */ - -#include -#include -#include -#include -#include -#include -#include -#include "internal/cryptlib.h" -#include "internal/numbers.h" -#include "crypto/evp.h" -#include "internal/provider_ctx.h" -#include "internal/providercommonerr.h" -#include "internal/provider_algs.h" -#include "internal/provider_util.h" -#include "pbkdf2.h" - -/* Constants specified in SP800-132 */ -#define KDF_PBKDF2_MIN_KEY_LEN_BITS 112 -#define KDF_PBKDF2_MAX_KEY_LEN_DIGEST_RATIO 0xFFFFFFFF -#define KDF_PBKDF2_MIN_ITERATIONS 1000 -#define KDF_PBKDF2_MIN_SALT_LEN (128 / 8) - -static OSSL_OP_kdf_newctx_fn kdf_pbkdf2_new; -static OSSL_OP_kdf_freectx_fn kdf_pbkdf2_free; -static OSSL_OP_kdf_reset_fn kdf_pbkdf2_reset; -static OSSL_OP_kdf_derive_fn kdf_pbkdf2_derive; -static OSSL_OP_kdf_settable_ctx_params_fn kdf_pbkdf2_settable_ctx_params; -static OSSL_OP_kdf_set_ctx_params_fn kdf_pbkdf2_set_ctx_params; - -static int pbkdf2_derive(const char *pass, size_t passlen, - const unsigned char *salt, int saltlen, uint64_t iter, - const EVP_MD *digest, unsigned char *key, - size_t keylen, int extra_checks); - -typedef struct { - void *provctx; - unsigned char *pass; - size_t pass_len; - unsigned char *salt; - size_t salt_len; - uint64_t iter; - PROV_DIGEST digest; - int lower_bound_checks; -} KDF_PBKDF2; - -static void kdf_pbkdf2_init(KDF_PBKDF2 *ctx); - -static void *kdf_pbkdf2_new(void *provctx) -{ - KDF_PBKDF2 *ctx; - - ctx = OPENSSL_zalloc(sizeof(*ctx)); - if (ctx == NULL) { - ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); - return NULL; - } - ctx->provctx = provctx; - kdf_pbkdf2_init(ctx); - return ctx; -} - -static void kdf_pbkdf2_cleanup(KDF_PBKDF2 *ctx) -{ - ossl_prov_digest_reset(&ctx->digest); - OPENSSL_free(ctx->salt); - OPENSSL_clear_free(ctx->pass, ctx->pass_len); - memset(ctx, 0, sizeof(*ctx)); -} - -static void kdf_pbkdf2_free(void *vctx) -{ - KDF_PBKDF2 *ctx = (KDF_PBKDF2 *)vctx; - - kdf_pbkdf2_cleanup(ctx); - OPENSSL_free(ctx); -} - -static void kdf_pbkdf2_reset(void *vctx) -{ - KDF_PBKDF2 *ctx = (KDF_PBKDF2 *)vctx; - - kdf_pbkdf2_cleanup(ctx); - kdf_pbkdf2_init(ctx); -} - -static void kdf_pbkdf2_init(KDF_PBKDF2 *ctx) -{ - OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END }; - OPENSSL_CTX *provctx = PROV_LIBRARY_CONTEXT_OF(ctx->provctx); - - params[0] = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST, - SN_sha1, 0); - if (!ossl_prov_digest_load_from_params(&ctx->digest, params, provctx)) - /* This is an error, but there is no way to indicate such directly */ - ossl_prov_digest_reset(&ctx->digest); - ctx->iter = PKCS5_DEFAULT_ITER; - ctx->lower_bound_checks = kdf_pbkdf2_default_checks; -} - -static int pbkdf2_set_membuf(unsigned char **buffer, size_t *buflen, - const OSSL_PARAM *p) -{ - OPENSSL_clear_free(*buffer, *buflen); - if (p->data_size == 0) { - if ((*buffer = OPENSSL_malloc(1)) == NULL) { - ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); - return 0; - } - } else if (p->data != NULL) { - *buffer = NULL; - if (!OSSL_PARAM_get_octet_string(p, (void **)buffer, 0, buflen)) - return 0; - } - return 1; -} - -static int kdf_pbkdf2_derive(void *vctx, unsigned char *key, - size_t keylen) -{ - KDF_PBKDF2 *ctx = (KDF_PBKDF2 *)vctx; - const EVP_MD *md = ossl_prov_digest_md(&ctx->digest); - - if (ctx->pass == NULL) { - ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_PASS); - return 0; - } - - if (ctx->salt == NULL) { - ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_SALT); - return 0; - } - - return pbkdf2_derive((char *)ctx->pass, ctx->pass_len, - ctx->salt, ctx->salt_len, ctx->iter, - md, key, keylen, ctx->lower_bound_checks); -} - -static int kdf_pbkdf2_set_ctx_params(void *vctx, const OSSL_PARAM params[]) -{ - const OSSL_PARAM *p; - KDF_PBKDF2 *ctx = vctx; - OPENSSL_CTX *provctx = PROV_LIBRARY_CONTEXT_OF(ctx->provctx); - int pkcs5; - uint64_t iter, min_iter; - - if (!ossl_prov_digest_load_from_params(&ctx->digest, params, provctx)) - return 0; - - if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PKCS5)) != NULL) { - if (!OSSL_PARAM_get_int(p, &pkcs5)) - return 0; - ctx->lower_bound_checks = pkcs5 == 0; - } - - if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PASSWORD)) != NULL) - if (!pbkdf2_set_membuf(&ctx->pass, &ctx->pass_len, p)) - return 0; - - if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SALT)) != NULL) { - if (ctx->lower_bound_checks != 0 - && p->data_size < KDF_PBKDF2_MIN_SALT_LEN) { - ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_SALT_LENGTH); - return 0; - } - if (!pbkdf2_set_membuf(&ctx->salt, &ctx->salt_len,p)) - return 0; - } - - if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_ITER)) != NULL) { - if (!OSSL_PARAM_get_uint64(p, &iter)) - return 0; - min_iter = ctx->lower_bound_checks != 0 ? KDF_PBKDF2_MIN_ITERATIONS : 1; - if (iter < min_iter) { - ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_ITERATION_COUNT); - return 0; - } - ctx->iter = iter; - } - return 1; -} - -static const OSSL_PARAM *kdf_pbkdf2_settable_ctx_params(void) -{ - static const OSSL_PARAM known_settable_ctx_params[] = { - OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES, NULL, 0), - OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_DIGEST, NULL, 0), - OSSL_PARAM_octet_string(OSSL_KDF_PARAM_PASSWORD, NULL, 0), - OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SALT, NULL, 0), - OSSL_PARAM_uint64(OSSL_KDF_PARAM_ITER, NULL), - OSSL_PARAM_int(OSSL_KDF_PARAM_PKCS5, NULL), - OSSL_PARAM_END - }; - return known_settable_ctx_params; -} - -static int kdf_pbkdf2_get_ctx_params(void *vctx, OSSL_PARAM params[]) -{ - OSSL_PARAM *p; - - if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE)) != NULL) - return OSSL_PARAM_set_size_t(p, SIZE_MAX); - return -2; -} - -static const OSSL_PARAM *kdf_pbkdf2_gettable_ctx_params(void) -{ - static const OSSL_PARAM known_gettable_ctx_params[] = { - OSSL_PARAM_size_t(OSSL_KDF_PARAM_SIZE, NULL), - OSSL_PARAM_END - }; - return known_gettable_ctx_params; -} - -const OSSL_DISPATCH kdf_pbkdf2_functions[] = { - { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))kdf_pbkdf2_new }, - { OSSL_FUNC_KDF_FREECTX, (void(*)(void))kdf_pbkdf2_free }, - { OSSL_FUNC_KDF_RESET, (void(*)(void))kdf_pbkdf2_reset }, - { OSSL_FUNC_KDF_DERIVE, (void(*)(void))kdf_pbkdf2_derive }, - { OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS, - (void(*)(void))kdf_pbkdf2_settable_ctx_params }, - { OSSL_FUNC_KDF_SET_CTX_PARAMS, (void(*)(void))kdf_pbkdf2_set_ctx_params }, - { OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS, - (void(*)(void))kdf_pbkdf2_gettable_ctx_params }, - { OSSL_FUNC_KDF_GET_CTX_PARAMS, (void(*)(void))kdf_pbkdf2_get_ctx_params }, - { 0, NULL } -}; - -/* - * This is an implementation of PKCS#5 v2.0 password based encryption key - * derivation function PBKDF2. SHA1 version verified against test vectors - * posted by Peter Gutmann to the PKCS-TNG mailing list. - * - * The constraints specified by SP800-132 have been added i.e. - * - Check the range of the key length. - * - Minimum iteration count of 1000. - * - Randomly-generated portion of the salt shall be at least 128 bits. - */ -static int pbkdf2_derive(const char *pass, size_t passlen, - const unsigned char *salt, int saltlen, uint64_t iter, - const EVP_MD *digest, unsigned char *key, - size_t keylen, int lower_bound_checks) -{ - int ret = 0; - unsigned char digtmp[EVP_MAX_MD_SIZE], *p, itmp[4]; - int cplen, k, tkeylen, mdlen; - uint64_t j; - unsigned long i = 1; - HMAC_CTX *hctx_tpl = NULL, *hctx = NULL; - - mdlen = EVP_MD_size(digest); - if (mdlen <= 0) - return 0; - - /* - * This check should always be done because keylen / mdlen >= (2^32 - 1) - * results in an overflow of the loop counter 'i'. - */ - if ((keylen / mdlen) >= KDF_PBKDF2_MAX_KEY_LEN_DIGEST_RATIO) { - ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LEN); - return 0; - } - - if (lower_bound_checks) { - if ((keylen * 8) < KDF_PBKDF2_MIN_KEY_LEN_BITS) { - ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LEN); - return 0; - } - if (saltlen < KDF_PBKDF2_MIN_SALT_LEN) { - ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_SALT_LENGTH); - return 0; - } - if (iter < KDF_PBKDF2_MIN_ITERATIONS) { - ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_ITERATION_COUNT); - return 0; - } - } - - hctx_tpl = HMAC_CTX_new(); - if (hctx_tpl == NULL) - return 0; - p = key; - tkeylen = keylen; - if (!HMAC_Init_ex(hctx_tpl, pass, passlen, digest, NULL)) - goto err; - hctx = HMAC_CTX_new(); - if (hctx == NULL) - goto err; - while (tkeylen) { - if (tkeylen > mdlen) - cplen = mdlen; - else - cplen = tkeylen; - /* - * We are unlikely to ever use more than 256 blocks (5120 bits!) but - * just in case... - */ - itmp[0] = (unsigned char)((i >> 24) & 0xff); - itmp[1] = (unsigned char)((i >> 16) & 0xff); - itmp[2] = (unsigned char)((i >> 8) & 0xff); - itmp[3] = (unsigned char)(i & 0xff); - if (!HMAC_CTX_copy(hctx, hctx_tpl)) - goto err; - if (!HMAC_Update(hctx, salt, saltlen) - || !HMAC_Update(hctx, itmp, 4) - || !HMAC_Final(hctx, digtmp, NULL)) - goto err; - memcpy(p, digtmp, cplen); - for (j = 1; j < iter; j++) { - if (!HMAC_CTX_copy(hctx, hctx_tpl)) - goto err; - if (!HMAC_Update(hctx, digtmp, mdlen) - || !HMAC_Final(hctx, digtmp, NULL)) - goto err; - for (k = 0; k < cplen; k++) - p[k] ^= digtmp[k]; - } - tkeylen -= cplen; - i++; - p += cplen; - } - ret = 1; - -err: - HMAC_CTX_free(hctx); - HMAC_CTX_free(hctx_tpl); - return ret; -} diff --git a/providers/common/kdfs/pbkdf2.h b/providers/common/kdfs/pbkdf2.h deleted file mode 100644 index c8c2e5b8a7..0000000000 --- a/providers/common/kdfs/pbkdf2.h +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright 2019 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 - */ - -/* - * Available in pbkdfe_fips.c, and compiled with different values depending - * on we're in the FIPS module or not. - */ -extern const int kdf_pbkdf2_default_checks; diff --git a/providers/common/kdfs/pbkdf2_fips.c b/providers/common/kdfs/pbkdf2_fips.c deleted file mode 100644 index d33782b24c..0000000000 --- a/providers/common/kdfs/pbkdf2_fips.c +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2019 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 - */ - -#include "pbkdf2.h" - -/* - * For backwards compatibility reasons, - * Extra checks are done by default in fips mode only. - */ -#ifdef FIPS_MODE -const int kdf_pbkdf2_default_checks = 1; -#else -const int kdf_pbkdf2_default_checks = 0; -#endif /* FIPS_MODE */ diff --git a/providers/common/kdfs/sskdf.c b/providers/common/kdfs/sskdf.c deleted file mode 100644 index 1e538a9c0a..0000000000 --- a/providers/common/kdfs/sskdf.c +++ /dev/null @@ -1,538 +0,0 @@ -/* - * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. - * Copyright (c) 2019, Oracle and/or its affiliates. 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 - */ - -/* - * Refer to https://csrc.nist.gov/publications/detail/sp/800-56c/rev-1/final - * Section 4.1. - * - * The Single Step KDF algorithm is given by: - * - * Result(0) = empty bit string (i.e., the null string). - * For i = 1 to reps, do the following: - * Increment counter by 1. - * Result(i) = Result(i - 1) || H(counter || Z || FixedInfo). - * DKM = LeftmostBits(Result(reps), L)) - * - * NOTES: - * Z is a shared secret required to produce the derived key material. - * counter is a 4 byte buffer. - * FixedInfo is a bit string containing context specific data. - * DKM is the output derived key material. - * L is the required size of the DKM. - * reps = [L / H_outputBits] - * H(x) is the auxiliary function that can be either a hash, HMAC or KMAC. - * H_outputBits is the length of the output of the auxiliary function H(x). - * - * Currently there is not a comprehensive list of test vectors for this - * algorithm, especially for H(x) = HMAC and H(x) = KMAC. - * Test vectors for H(x) = Hash are indirectly used by CAVS KAS tests. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include "internal/cryptlib.h" -#include "internal/numbers.h" -#include "crypto/evp.h" -#include "internal/provider_ctx.h" -#include "internal/providercommonerr.h" -#include "internal/provider_algs.h" -#include "internal/provider_util.h" - -typedef struct { - void *provctx; - EVP_MAC_CTX *macctx; /* H(x) = HMAC_hash OR H(x) = KMAC */ - PROV_DIGEST digest; /* H(x) = hash(x) */ - unsigned char *secret; - size_t secret_len; - unsigned char *info; - size_t info_len; - unsigned char *salt; - size_t salt_len; - size_t out_len; /* optional KMAC parameter */ -} KDF_SSKDF; - -#define SSKDF_MAX_INLEN (1<<30) -#define SSKDF_KMAC128_DEFAULT_SALT_SIZE (168 - 4) -#define SSKDF_KMAC256_DEFAULT_SALT_SIZE (136 - 4) - -/* KMAC uses a Customisation string of 'KDF' */ -static const unsigned char kmac_custom_str[] = { 0x4B, 0x44, 0x46 }; - -static OSSL_OP_kdf_newctx_fn sskdf_new; -static OSSL_OP_kdf_freectx_fn sskdf_free; -static OSSL_OP_kdf_reset_fn sskdf_reset; -static OSSL_OP_kdf_derive_fn sskdf_derive; -static OSSL_OP_kdf_derive_fn x963kdf_derive; -static OSSL_OP_kdf_settable_ctx_params_fn sskdf_settable_ctx_params; -static OSSL_OP_kdf_set_ctx_params_fn sskdf_set_ctx_params; -static OSSL_OP_kdf_gettable_ctx_params_fn sskdf_gettable_ctx_params; -static OSSL_OP_kdf_get_ctx_params_fn sskdf_get_ctx_params; - -/* - * Refer to https://csrc.nist.gov/publications/detail/sp/800-56c/rev-1/final - * Section 4. One-Step Key Derivation using H(x) = hash(x) - * Note: X9.63 also uses this code with the only difference being that the - * counter is appended to the secret 'z'. - * i.e. - * result[i] = Hash(counter || z || info) for One Step OR - * result[i] = Hash(z || counter || info) for X9.63. - */ -static int SSKDF_hash_kdm(const EVP_MD *kdf_md, - const unsigned char *z, size_t z_len, - const unsigned char *info, size_t info_len, - unsigned int append_ctr, - unsigned char *derived_key, size_t derived_key_len) -{ - int ret = 0, hlen; - size_t counter, out_len, len = derived_key_len; - unsigned char c[4]; - unsigned char mac[EVP_MAX_MD_SIZE]; - unsigned char *out = derived_key; - EVP_MD_CTX *ctx = NULL, *ctx_init = NULL; - - if (z_len > SSKDF_MAX_INLEN || info_len > SSKDF_MAX_INLEN - || derived_key_len > SSKDF_MAX_INLEN - || derived_key_len == 0) - return 0; - - hlen = EVP_MD_size(kdf_md); - if (hlen <= 0) - return 0; - out_len = (size_t)hlen; - - ctx = EVP_MD_CTX_create(); - ctx_init = EVP_MD_CTX_create(); - if (ctx == NULL || ctx_init == NULL) - goto end; - - if (!EVP_DigestInit(ctx_init, kdf_md)) - goto end; - - for (counter = 1;; counter++) { - c[0] = (unsigned char)((counter >> 24) & 0xff); - c[1] = (unsigned char)((counter >> 16) & 0xff); - c[2] = (unsigned char)((counter >> 8) & 0xff); - c[3] = (unsigned char)(counter & 0xff); - - if (!(EVP_MD_CTX_copy_ex(ctx, ctx_init) - && (append_ctr || EVP_DigestUpdate(ctx, c, sizeof(c))) - && EVP_DigestUpdate(ctx, z, z_len) - && (!append_ctr || EVP_DigestUpdate(ctx, c, sizeof(c))) - && EVP_DigestUpdate(ctx, info, info_len))) - goto end; - if (len >= out_len) { - if (!EVP_DigestFinal_ex(ctx, out, NULL)) - goto end; - out += out_len; - len -= out_len; - if (len == 0) - break; - } else { - if (!EVP_DigestFinal_ex(ctx, mac, NULL)) - goto end; - memcpy(out, mac, len); - break; - } - } - ret = 1; -end: - EVP_MD_CTX_destroy(ctx); - EVP_MD_CTX_destroy(ctx_init); - OPENSSL_cleanse(mac, sizeof(mac)); - return ret; -} - -static int kmac_init(EVP_MAC_CTX *ctx, const unsigned char *custom, - size_t custom_len, size_t kmac_out_len, - size_t derived_key_len, unsigned char **out) -{ - OSSL_PARAM params[2]; - - /* Only KMAC has custom data - so return if not KMAC */ - if (custom == NULL) - return 1; - - params[0] = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_CUSTOM, - (void *)custom, custom_len); - params[1] = OSSL_PARAM_construct_end(); - - if (!EVP_MAC_CTX_set_params(ctx, params)) - return 0; - - /* By default only do one iteration if kmac_out_len is not specified */ - if (kmac_out_len == 0) - kmac_out_len = derived_key_len; - /* otherwise check the size is valid */ - else if (!(kmac_out_len == derived_key_len - || kmac_out_len == 20 - || kmac_out_len == 28 - || kmac_out_len == 32 - || kmac_out_len == 48 - || kmac_out_len == 64)) - return 0; - - params[0] = OSSL_PARAM_construct_size_t(OSSL_MAC_PARAM_SIZE, - &kmac_out_len); - - if (EVP_MAC_CTX_set_params(ctx, params) <= 0) - return 0; - - /* - * For kmac the output buffer can be larger than EVP_MAX_MD_SIZE: so - * alloc a buffer for this case. - */ - if (kmac_out_len > EVP_MAX_MD_SIZE) { - *out = OPENSSL_zalloc(kmac_out_len); - if (*out == NULL) - return 0; - } - return 1; -} - -/* - * Refer to https://csrc.nist.gov/publications/detail/sp/800-56c/rev-1/final - * Section 4. One-Step Key Derivation using MAC: i.e either - * H(x) = HMAC-hash(salt, x) OR - * H(x) = KMAC#(salt, x, outbits, CustomString='KDF') - */ -static int SSKDF_mac_kdm(EVP_MAC_CTX *ctx_init, - const unsigned char *kmac_custom, - size_t kmac_custom_len, size_t kmac_out_len, - const unsigned char *salt, size_t salt_len, - const unsigned char *z, size_t z_len, - const unsigned char *info, size_t info_len, - unsigned char *derived_key, size_t derived_key_len) -{ - int ret = 0; - size_t counter, out_len, len; - unsigned char c[4]; - unsigned char mac_buf[EVP_MAX_MD_SIZE]; - unsigned char *out = derived_key; - EVP_MAC_CTX *ctx = NULL; - unsigned char *mac = mac_buf, *kmac_buffer = NULL; - OSSL_PARAM params[2], *p = params; - - if (z_len > SSKDF_MAX_INLEN || info_len > SSKDF_MAX_INLEN - || derived_key_len > SSKDF_MAX_INLEN - || derived_key_len == 0) - return 0; - - *p++ = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY, - (void *)salt, salt_len); - *p = OSSL_PARAM_construct_end(); - - if (!EVP_MAC_CTX_set_params(ctx_init, params)) - goto end; - - if (!kmac_init(ctx_init, kmac_custom, kmac_custom_len, kmac_out_len, - derived_key_len, &kmac_buffer)) - goto end; - if (kmac_buffer != NULL) - mac = kmac_buffer; - - if (!EVP_MAC_init(ctx_init)) - goto end; - - out_len = EVP_MAC_size(ctx_init); /* output size */ - if (out_len <= 0) - goto end; - len = derived_key_len; - - for (counter = 1;; counter++) { - c[0] = (unsigned char)((counter >> 24) & 0xff); - c[1] = (unsigned char)((counter >> 16) & 0xff); - c[2] = (unsigned char)((counter >> 8) & 0xff); - c[3] = (unsigned char)(counter & 0xff); - - ctx = EVP_MAC_CTX_dup(ctx_init); - if (!(ctx != NULL - && EVP_MAC_update(ctx, c, sizeof(c)) - && EVP_MAC_update(ctx, z, z_len) - && EVP_MAC_update(ctx, info, info_len))) - goto end; - if (len >= out_len) { - if (!EVP_MAC_final(ctx, out, NULL, len)) - goto end; - out += out_len; - len -= out_len; - if (len == 0) - break; - } else { - if (!EVP_MAC_final(ctx, mac, NULL, len)) - goto end; - memcpy(out, mac, len); - break; - } - EVP_MAC_CTX_free(ctx); - ctx = NULL; - } - ret = 1; -end: - if (kmac_buffer != NULL) - OPENSSL_clear_free(kmac_buffer, kmac_out_len); - else - OPENSSL_cleanse(mac_buf, sizeof(mac_buf)); - - EVP_MAC_CTX_free(ctx); - return ret; -} - -static void *sskdf_new(void *provctx) -{ - KDF_SSKDF *ctx; - - if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) - ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); - ctx->provctx = provctx; - return ctx; -} - -static void sskdf_reset(void *vctx) -{ - KDF_SSKDF *ctx = (KDF_SSKDF *)vctx; - - EVP_MAC_CTX_free(ctx->macctx); - ossl_prov_digest_reset(&ctx->digest); - OPENSSL_clear_free(ctx->secret, ctx->secret_len); - OPENSSL_clear_free(ctx->info, ctx->info_len); - OPENSSL_clear_free(ctx->salt, ctx->salt_len); - memset(ctx, 0, sizeof(*ctx)); -} - -static void sskdf_free(void *vctx) -{ - KDF_SSKDF *ctx = (KDF_SSKDF *)vctx; - - sskdf_reset(ctx); - OPENSSL_free(ctx); -} - -static int sskdf_set_buffer(unsigned char **out, size_t *out_len, - const OSSL_PARAM *p) -{ - if (p->data == NULL || p->data_size == 0) - return 1; - OPENSSL_free(*out); - *out = NULL; - return OSSL_PARAM_get_octet_string(p, (void **)out, 0, out_len); -} - -static size_t sskdf_size(KDF_SSKDF *ctx) -{ - int len; - const EVP_MD *md = ossl_prov_digest_md(&ctx->digest); - - if (md == NULL) { - ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST); - return 0; - } - len = EVP_MD_size(md); - return (len <= 0) ? 0 : (size_t)len; -} - -static int sskdf_derive(void *vctx, unsigned char *key, size_t keylen) -{ - KDF_SSKDF *ctx = (KDF_SSKDF *)vctx; - const EVP_MD *md = ossl_prov_digest_md(&ctx->digest); - - if (ctx->secret == NULL) { - ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_SECRET); - return 0; - } - - if (ctx->macctx != NULL) { - /* H(x) = KMAC or H(x) = HMAC */ - int ret; - const unsigned char *custom = NULL; - size_t custom_len = 0; - int default_salt_len; - EVP_MAC *mac = EVP_MAC_CTX_mac(ctx->macctx); - - /* - * TODO(3.0) investigate the necessity to have all these controls. - * Why does KMAC require a salt length that's shorter than the MD - * block size? - */ - if (EVP_MAC_is_a(mac, OSSL_MAC_NAME_HMAC)) { - /* H(x) = HMAC(x, salt, hash) */ - if (md == NULL) { - ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST); - return 0; - } - default_salt_len = EVP_MD_size(md); - if (default_salt_len <= 0) - return 0; - } else if (EVP_MAC_is_a(mac, OSSL_MAC_NAME_KMAC128) - || EVP_MAC_is_a(mac, OSSL_MAC_NAME_KMAC256)) { - /* H(x) = KMACzzz(x, salt, custom) */ - custom = kmac_custom_str; - custom_len = sizeof(kmac_custom_str); - if (EVP_MAC_is_a(mac, OSSL_MAC_NAME_KMAC128)) - default_salt_len = SSKDF_KMAC128_DEFAULT_SALT_SIZE; - else - default_salt_len = SSKDF_KMAC256_DEFAULT_SALT_SIZE; - } else { - ERR_raise(ERR_LIB_PROV, PROV_R_UNSUPPORTED_MAC_TYPE); - return 0; - } - /* If no salt is set then use a default_salt of zeros */ - if (ctx->salt == NULL || ctx->salt_len <= 0) { - ctx->salt = OPENSSL_zalloc(default_salt_len); - if (ctx->salt == NULL) { - ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); - return 0; - } - ctx->salt_len = default_salt_len; - } - ret = SSKDF_mac_kdm(ctx->macctx, - custom, custom_len, ctx->out_len, - ctx->salt, ctx->salt_len, - ctx->secret, ctx->secret_len, - ctx->info, ctx->info_len, key, keylen); - return ret; - } else { - /* H(x) = hash */ - if (md == NULL) { - ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST); - return 0; - } - return SSKDF_hash_kdm(md, ctx->secret, ctx->secret_len, - ctx->info, ctx->info_len, 0, key, keylen); - } -} - -static int x963kdf_derive(void *vctx, unsigned char *key, size_t keylen) -{ - KDF_SSKDF *ctx = (KDF_SSKDF *)vctx; - const EVP_MD *md = ossl_prov_digest_md(&ctx->digest); - - if (ctx->secret == NULL) { - ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_SECRET); - return 0; - } - - if (ctx->macctx != NULL) { - ERR_raise(ERR_LIB_PROV, PROV_R_NOT_SUPPORTED); - return 0; - } - - /* H(x) = hash */ - if (md == NULL) { - ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST); - return 0; - } - - return SSKDF_hash_kdm(md, ctx->secret, ctx->secret_len, - ctx->info, ctx->info_len, 1, key, keylen); -} - -static int sskdf_set_ctx_params(void *vctx, const OSSL_PARAM params[]) -{ - const OSSL_PARAM *p; - KDF_SSKDF *ctx = vctx; - OPENSSL_CTX *libctx = PROV_LIBRARY_CONTEXT_OF(ctx->provctx); - size_t sz; - - if (!ossl_prov_digest_load_from_params(&ctx->digest, params, libctx)) - return 0; - - if (!ossl_prov_macctx_load_from_params(&ctx->macctx, params, - NULL, NULL, NULL, libctx)) - return 0; - - if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SECRET)) != NULL - || (p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_KEY)) != NULL) - if (!sskdf_set_buffer(&ctx->secret, &ctx->secret_len, p)) - return 0; - - if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_INFO)) != NULL) - if (!sskdf_set_buffer(&ctx->info, &ctx->info_len, p)) - return 0; - - if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SALT)) != NULL) - if (!sskdf_set_buffer(&ctx->salt, &ctx->salt_len, p)) - return 0; - - if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_MAC_SIZE)) - != NULL) { - if (!OSSL_PARAM_get_size_t(p, &sz) || sz == 0) - return 0; - ctx->out_len = sz; - } - return 1; -} - -static const OSSL_PARAM *sskdf_settable_ctx_params(void) -{ - static const OSSL_PARAM known_settable_ctx_params[] = { - OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SECRET, NULL, 0), - OSSL_PARAM_octet_string(OSSL_KDF_PARAM_KEY, NULL, 0), - OSSL_PARAM_octet_string(OSSL_KDF_PARAM_INFO, NULL, 0), - OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES, NULL, 0), - OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_DIGEST, NULL, 0), - OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_MAC, NULL, 0), - OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SALT, NULL, 0), - OSSL_PARAM_size_t(OSSL_KDF_PARAM_MAC_SIZE, NULL), - OSSL_PARAM_END - }; - return known_settable_ctx_params; -} - -static int sskdf_get_ctx_params(void *vctx, OSSL_PARAM params[]) -{ - KDF_SSKDF *ctx = (KDF_SSKDF *)vctx; - OSSL_PARAM *p; - - if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE)) != NULL) - return OSSL_PARAM_set_size_t(p, sskdf_size(ctx)); - return -2; -} - -static const OSSL_PARAM *sskdf_gettable_ctx_params(void) -{ - static const OSSL_PARAM known_gettable_ctx_params[] = { - OSSL_PARAM_size_t(OSSL_KDF_PARAM_SIZE, NULL), - OSSL_PARAM_END - }; - return known_gettable_ctx_params; -} - -const OSSL_DISPATCH kdf_sskdf_functions[] = { - { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))sskdf_new }, - { OSSL_FUNC_KDF_FREECTX, (void(*)(void))sskdf_free }, - { OSSL_FUNC_KDF_RESET, (void(*)(void))sskdf_reset }, - { OSSL_FUNC_KDF_DERIVE, (void(*)(void))sskdf_derive }, - { OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS, - (void(*)(void))sskdf_settable_ctx_params }, - { OSSL_FUNC_KDF_SET_CTX_PARAMS, (void(*)(void))sskdf_set_ctx_params }, - { OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS, - (void(*)(void))sskdf_gettable_ctx_params }, - { OSSL_FUNC_KDF_GET_CTX_PARAMS, (void(*)(void))sskdf_get_ctx_params }, - { 0, NULL } -}; - -const OSSL_DISPATCH kdf_x963_kdf_functions[] = { - { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))sskdf_new }, - { OSSL_FUNC_KDF_FREECTX, (void(*)(void))sskdf_free }, - { OSSL_FUNC_KDF_RESET, (void(*)(void))sskdf_reset }, - { OSSL_FUNC_KDF_DERIVE, (void(*)(void))x963kdf_derive }, - { OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS, - (void(*)(void))sskdf_settable_ctx_params }, - { OSSL_FUNC_KDF_SET_CTX_PARAMS, (void(*)(void))sskdf_set_ctx_params }, - { OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS, - (void(*)(void))sskdf_gettable_ctx_params }, - { OSSL_FUNC_KDF_GET_CTX_PARAMS, (void(*)(void))sskdf_get_ctx_params }, - { 0, NULL } -}; diff --git a/providers/common/kdfs/tls1_prf.c b/providers/common/kdfs/tls1_prf.c deleted file mode 100644 index af49b1b044..0000000000 --- a/providers/common/kdfs/tls1_prf.c +++ /dev/null @@ -1,396 +0,0 @@ -/* - * Copyright 2016-2019 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 - */ - -/* - * Refer to "The TLS Protocol Version 1.0" Section 5 - * (https://tools.ietf.org/html/rfc2246#section-5) and - * "The Transport Layer Security (TLS) Protocol Version 1.2" Section 5 - * (https://tools.ietf.org/html/rfc5246#section-5). - * - * For TLS v1.0 and TLS v1.1 the TLS PRF algorithm is given by: - * - * PRF(secret, label, seed) = P_MD5(S1, label + seed) XOR - * P_SHA-1(S2, label + seed) - * - * where P_MD5 and P_SHA-1 are defined by P_, below, and S1 and S2 are - * two halves of the secret (with the possibility of one shared byte, in the - * case where the length of the original secret is odd). S1 is taken from the - * first half of the secret, S2 from the second half. - * - * For TLS v1.2 the TLS PRF algorithm is given by: - * - * PRF(secret, label, seed) = P_(secret, label + seed) - * - * where hash is SHA-256 for all cipher suites defined in RFC 5246 as well as - * those published prior to TLS v1.2 while the TLS v1.2 protocol is in effect, - * unless defined otherwise by the cipher suite. - * - * P_ is an expansion function that uses a single hash function to expand - * a secret and seed into an arbitrary quantity of output: - * - * P_(secret, seed) = HMAC_(secret, A(1) + seed) + - * HMAC_(secret, A(2) + seed) + - * HMAC_(secret, A(3) + seed) + ... - * - * where + indicates concatenation. P_ can be iterated as many times as - * is necessary to produce the required quantity of data. - * - * A(i) is defined as: - * A(0) = seed - * A(i) = HMAC_(secret, A(i-1)) - */ -#include -#include -#include -#include -#include -#include -#include -#include "internal/cryptlib.h" -#include "internal/numbers.h" -#include "crypto/evp.h" -#include "internal/provider_ctx.h" -#include "internal/providercommonerr.h" -#include "internal/provider_algs.h" -#include "internal/provider_util.h" -#include "e_os.h" - -static OSSL_OP_kdf_newctx_fn kdf_tls1_prf_new; -static OSSL_OP_kdf_freectx_fn kdf_tls1_prf_free; -static OSSL_OP_kdf_reset_fn kdf_tls1_prf_reset; -static OSSL_OP_kdf_derive_fn kdf_tls1_prf_derive; -static OSSL_OP_kdf_settable_ctx_params_fn kdf_tls1_prf_settable_ctx_params; -static OSSL_OP_kdf_set_ctx_params_fn kdf_tls1_prf_set_ctx_params; - -static int tls1_prf_alg(EVP_MAC_CTX *mdctx, EVP_MAC_CTX *sha1ctx, - const unsigned char *sec, size_t slen, - const unsigned char *seed, size_t seed_len, - unsigned char *out, size_t olen); - -#define TLS1_PRF_MAXBUF 1024 - -/* TLS KDF kdf context structure */ -typedef struct { - void *provctx; - - /* MAC context for the main digest */ - EVP_MAC_CTX *P_hash; - /* MAC context for SHA1 for the MD5/SHA-1 combined PRF */ - EVP_MAC_CTX *P_sha1; - - /* Secret value to use for PRF */ - unsigned char *sec; - size_t seclen; - /* Buffer of concatenated seed data */ - unsigned char seed[TLS1_PRF_MAXBUF]; - size_t seedlen; -} TLS1_PRF; - -static void *kdf_tls1_prf_new(void *provctx) -{ - TLS1_PRF *ctx; - - if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) - ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); - ctx->provctx = provctx; - return ctx; -} - -static void kdf_tls1_prf_free(void *vctx) -{ - TLS1_PRF *ctx = (TLS1_PRF *)vctx; - - kdf_tls1_prf_reset(ctx); - OPENSSL_free(ctx); -} - -static void kdf_tls1_prf_reset(void *vctx) -{ - TLS1_PRF *ctx = (TLS1_PRF *)vctx; - - EVP_MAC_CTX_free(ctx->P_hash); - EVP_MAC_CTX_free(ctx->P_sha1); - OPENSSL_clear_free(ctx->sec, ctx->seclen); - OPENSSL_cleanse(ctx->seed, ctx->seedlen); - memset(ctx, 0, sizeof(*ctx)); -} - -static int kdf_tls1_prf_derive(void *vctx, unsigned char *key, - size_t keylen) -{ - TLS1_PRF *ctx = (TLS1_PRF *)vctx; - - if (ctx->P_hash == NULL) { - ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST); - return 0; - } - if (ctx->sec == NULL) { - ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_SECRET); - return 0; - } - if (ctx->seedlen == 0) { - ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_SEED); - return 0; - } - - return tls1_prf_alg(ctx->P_hash, ctx->P_sha1, - ctx->sec, ctx->seclen, - ctx->seed, ctx->seedlen, - key, keylen); -} - -static int kdf_tls1_prf_set_ctx_params(void *vctx, const OSSL_PARAM params[]) -{ - const OSSL_PARAM *p; - TLS1_PRF *ctx = vctx; - OPENSSL_CTX *libctx = PROV_LIBRARY_CONTEXT_OF(ctx->provctx); - - if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_DIGEST)) != NULL) { - if (strcasecmp(p->data, SN_md5_sha1) == 0) { - if (!ossl_prov_macctx_load_from_params(&ctx->P_hash, params, - OSSL_MAC_NAME_HMAC, - NULL, SN_md5, libctx) - || !ossl_prov_macctx_load_from_params(&ctx->P_sha1, params, - OSSL_MAC_NAME_HMAC, - NULL, SN_sha1, libctx)) - return 0; - } else { - EVP_MAC_CTX_free(ctx->P_sha1); - if (!ossl_prov_macctx_load_from_params(&ctx->P_hash, params, - OSSL_MAC_NAME_HMAC, - NULL, NULL, libctx)) - return 0; - } - } - - if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SECRET)) != NULL) { - OPENSSL_clear_free(ctx->sec, ctx->seclen); - ctx->sec = NULL; - if (!OSSL_PARAM_get_octet_string(p, (void **)&ctx->sec, 0, &ctx->seclen)) - return 0; - } - /* The seed fields concatenate, so process them all */ - if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SEED)) != NULL) { - OPENSSL_cleanse(ctx->seed, ctx->seedlen); - ctx->seedlen = 0; - - for (; p != NULL; p = OSSL_PARAM_locate_const(p + 1, - OSSL_KDF_PARAM_SEED)) { - const void *q = ctx->seed + ctx->seedlen; - size_t sz = 0; - - if (p->data_size != 0 - && p->data != NULL - && !OSSL_PARAM_get_octet_string(p, (void **)&q, - TLS1_PRF_MAXBUF - ctx->seedlen, - &sz)) - return 0; - ctx->seedlen += sz; - } - } - return 1; -} - -static const OSSL_PARAM *kdf_tls1_prf_settable_ctx_params(void) -{ - static const OSSL_PARAM known_settable_ctx_params[] = { - OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES, NULL, 0), - OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_DIGEST, NULL, 0), - OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SECRET, NULL, 0), - OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SEED, NULL, 0), - OSSL_PARAM_END - }; - return known_settable_ctx_params; -} - -static int kdf_tls1_prf_get_ctx_params(void *vctx, OSSL_PARAM params[]) -{ - OSSL_PARAM *p; - - if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE)) != NULL) - return OSSL_PARAM_set_size_t(p, SIZE_MAX); - return -2; -} - -static const OSSL_PARAM *kdf_tls1_prf_gettable_ctx_params(void) -{ - static const OSSL_PARAM known_gettable_ctx_params[] = { - OSSL_PARAM_size_t(OSSL_KDF_PARAM_SIZE, NULL), - OSSL_PARAM_END - }; - return known_gettable_ctx_params; -} - -const OSSL_DISPATCH kdf_tls1_prf_functions[] = { - { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))kdf_tls1_prf_new }, - { OSSL_FUNC_KDF_FREECTX, (void(*)(void))kdf_tls1_prf_free }, - { OSSL_FUNC_KDF_RESET, (void(*)(void))kdf_tls1_prf_reset }, - { OSSL_FUNC_KDF_DERIVE, (void(*)(void))kdf_tls1_prf_derive }, - { OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS, - (void(*)(void))kdf_tls1_prf_settable_ctx_params }, - { OSSL_FUNC_KDF_SET_CTX_PARAMS, - (void(*)(void))kdf_tls1_prf_set_ctx_params }, - { OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS, - (void(*)(void))kdf_tls1_prf_gettable_ctx_params }, - { OSSL_FUNC_KDF_GET_CTX_PARAMS, - (void(*)(void))kdf_tls1_prf_get_ctx_params }, - { 0, NULL } -}; - -/* - * Refer to "The TLS Protocol Version 1.0" Section 5 - * (https://tools.ietf.org/html/rfc2246#section-5) and - * "The Transport Layer Security (TLS) Protocol Version 1.2" Section 5 - * (https://tools.ietf.org/html/rfc5246#section-5). - * - * P_ is an expansion function that uses a single hash function to expand - * a secret and seed into an arbitrary quantity of output: - * - * P_(secret, seed) = HMAC_(secret, A(1) + seed) + - * HMAC_(secret, A(2) + seed) + - * HMAC_(secret, A(3) + seed) + ... - * - * where + indicates concatenation. P_ can be iterated as many times as - * is necessary to produce the required quantity of data. - * - * A(i) is defined as: - * A(0) = seed - * A(i) = HMAC_(secret, A(i-1)) - */ -static int tls1_prf_P_hash(EVP_MAC_CTX *ctx_init, - const unsigned char *sec, size_t sec_len, - const unsigned char *seed, size_t seed_len, - unsigned char *out, size_t olen) -{ - size_t chunk; - EVP_MAC_CTX *ctx = NULL, *ctx_Ai = NULL; - unsigned char Ai[EVP_MAX_MD_SIZE]; - size_t Ai_len; - int ret = 0; - OSSL_PARAM params[2], *p = params; - - *p++ = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY, - (void *)sec, sec_len); - *p = OSSL_PARAM_construct_end(); - if (!EVP_MAC_CTX_set_params(ctx_init, params)) - goto err; - if (!EVP_MAC_init(ctx_init)) - goto err; - chunk = EVP_MAC_size(ctx_init); - if (chunk == 0) - goto err; - /* A(0) = seed */ - ctx_Ai = EVP_MAC_CTX_dup(ctx_init); - if (ctx_Ai == NULL) - goto err; - if (seed != NULL && !EVP_MAC_update(ctx_Ai, seed, seed_len)) - goto err; - - for (;;) { - /* calc: A(i) = HMAC_(secret, A(i-1)) */ - if (!EVP_MAC_final(ctx_Ai, Ai, &Ai_len, sizeof(Ai))) - goto err; - EVP_MAC_CTX_free(ctx_Ai); - ctx_Ai = NULL; - - /* calc next chunk: HMAC_(secret, A(i) + seed) */ - ctx = EVP_MAC_CTX_dup(ctx_init); - if (ctx == NULL) - goto err; - if (!EVP_MAC_update(ctx, Ai, Ai_len)) - goto err; - /* save state for calculating next A(i) value */ - if (olen > chunk) { - ctx_Ai = EVP_MAC_CTX_dup(ctx); - if (ctx_Ai == NULL) - goto err; - } - if (seed != NULL && !EVP_MAC_update(ctx, seed, seed_len)) - goto err; - if (olen <= chunk) { - /* last chunk - use Ai as temp bounce buffer */ - if (!EVP_MAC_final(ctx, Ai, &Ai_len, sizeof(Ai))) - goto err; - memcpy(out, Ai, olen); - break; - } - if (!EVP_MAC_final(ctx, out, NULL, olen)) - goto err; - EVP_MAC_CTX_free(ctx); - ctx = NULL; - out += chunk; - olen -= chunk; - } - ret = 1; - err: - EVP_MAC_CTX_free(ctx); - EVP_MAC_CTX_free(ctx_Ai); - OPENSSL_cleanse(Ai, sizeof(Ai)); - return ret; -} - -/* - * Refer to "The TLS Protocol Version 1.0" Section 5 - * (https://tools.ietf.org/html/rfc2246#section-5) and - * "The Transport Layer Security (TLS) Protocol Version 1.2" Section 5 - * (https://tools.ietf.org/html/rfc5246#section-5). - * - * For TLS v1.0 and TLS v1.1: - * - * PRF(secret, label, seed) = P_MD5(S1, label + seed) XOR - * P_SHA-1(S2, label + seed) - * - * S1 is taken from the first half of the secret, S2 from the second half. - * - * L_S = length in bytes of secret; - * L_S1 = L_S2 = ceil(L_S / 2); - * - * For TLS v1.2: - * - * PRF(secret, label, seed) = P_(secret, label + seed) - */ -static int tls1_prf_alg(EVP_MAC_CTX *mdctx, EVP_MAC_CTX *sha1ctx, - const unsigned char *sec, size_t slen, - const unsigned char *seed, size_t seed_len, - unsigned char *out, size_t olen) -{ - if (sha1ctx != NULL) { - /* TLS v1.0 and TLS v1.1 */ - size_t i; - unsigned char *tmp; - /* calc: L_S1 = L_S2 = ceil(L_S / 2) */ - size_t L_S1 = (slen + 1) / 2; - size_t L_S2 = L_S1; - - if (!tls1_prf_P_hash(mdctx, sec, L_S1, - seed, seed_len, out, olen)) - return 0; - - if ((tmp = OPENSSL_malloc(olen)) == NULL) { - ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); - return 0; - } - - if (!tls1_prf_P_hash(sha1ctx, sec + slen - L_S2, L_S2, - seed, seed_len, tmp, olen)) { - OPENSSL_clear_free(tmp, olen); - return 0; - } - for (i = 0; i < olen; i++) - out[i] ^= tmp[i]; - OPENSSL_clear_free(tmp, olen); - return 1; - } - - /* TLS v1.2 */ - if (!tls1_prf_P_hash(mdctx, sec, slen, seed, seed_len, out, olen)) - return 0; - - return 1; -} diff --git a/providers/common/keymgmt/build.info b/providers/common/keymgmt/build.info deleted file mode 100644 index 533c489077..0000000000 --- a/providers/common/keymgmt/build.info +++ /dev/null @@ -1,8 +0,0 @@ -$GOAL=../../libimplementations.a - -IF[{- !$disabled{dh} -}] - SOURCE[$GOAL]=dh_kmgmt.c -ENDIF -IF[{- !$disabled{dsa} -}] - SOURCE[$GOAL]=dsa_kmgmt.c -ENDIF diff --git a/providers/common/keymgmt/dh_kmgmt.c b/providers/common/keymgmt/dh_kmgmt.c deleted file mode 100644 index c13f07546b..0000000000 --- a/providers/common/keymgmt/dh_kmgmt.c +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright 2019 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 - */ - -#include -#include -#include -#include -#include -#include "internal/provider_algs.h" - -static OSSL_OP_keymgmt_importkey_fn dh_importkey; - -static int params_to_key(DH *dh, const OSSL_PARAM params[]) -{ - const OSSL_PARAM *param_p, *param_g, *param_priv_key, *param_pub_key; - BIGNUM *p = NULL, *g = NULL, *priv_key = NULL, *pub_key = NULL; - - if (dh == NULL) - return 0; - - param_p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_P); - param_g = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_G); - param_priv_key = - OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_DH_PRIV_KEY); - param_pub_key = - OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_DH_PUB_KEY); - - /* - * DH documentation says that a public key must be present if a - * private key is present. - * We want to have at least a public key either way, so we end up - * requiring it unconditionally. - */ - if (param_pub_key == NULL) - return 0; - - if ((param_p != NULL && !OSSL_PARAM_get_BN(param_p, &p)) - || (param_g != NULL && !OSSL_PARAM_get_BN(param_g, &g)) - || (param_priv_key != NULL - && !OSSL_PARAM_get_BN(param_priv_key, &priv_key)) - || !OSSL_PARAM_get_BN(param_pub_key, &pub_key)) - goto err; - - if (!DH_set0_pqg(dh, p, NULL, g)) - goto err; - p = g = NULL; - - if (!DH_set0_key(dh, pub_key, priv_key)) - goto err; - priv_key = pub_key = NULL; - - return 1; - - err: - BN_free(p); - BN_free(g); - BN_free(priv_key); - BN_free(pub_key); - return 0; -} - -static void *dh_importkey(void *provctx, const OSSL_PARAM params[]) -{ - DH *dh; - - if ((dh = DH_new()) == NULL - || !params_to_key(dh, params)) { - DH_free(dh); - dh = NULL; - } - return dh; -} - -const OSSL_DISPATCH dh_keymgmt_functions[] = { - /* - * TODO(3.0) When implementing OSSL_FUNC_KEYMGMT_GENKEY, remember to also - * implement OSSL_FUNC_KEYMGMT_EXPORTKEY. - */ - { OSSL_FUNC_KEYMGMT_IMPORTKEY, (void (*)(void))dh_importkey }, - { OSSL_FUNC_KEYMGMT_FREEKEY, (void (*)(void))DH_free }, - { 0, NULL } -}; diff --git a/providers/common/keymgmt/dsa_kmgmt.c b/providers/common/keymgmt/dsa_kmgmt.c deleted file mode 100644 index a53c0b212c..0000000000 --- a/providers/common/keymgmt/dsa_kmgmt.c +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2019 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 - */ - -#include -#include -#include -#include -#include -#include "internal/provider_algs.h" - -static OSSL_OP_keymgmt_importkey_fn dsa_importkey; - -static int params_to_key(DSA *dsa, const OSSL_PARAM params[]) -{ - const OSSL_PARAM *param_p, *param_q, *param_g, *param_priv_key; - const OSSL_PARAM *param_pub_key; - BIGNUM *p = NULL, *q = NULL, *g = NULL, *priv_key = NULL, *pub_key = NULL; - - if (dsa == NULL) - return 0; - - param_p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_P); - param_q = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_Q); - param_g = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_G); - param_priv_key = - OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_DSA_PRIV_KEY); - param_pub_key = - OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_DSA_PUB_KEY); - - /* - * DSA documentation says that a public key must be present if a private key - * is. - */ - if (param_priv_key != NULL && param_pub_key == NULL) - return 0; - - if ((param_p != NULL && !OSSL_PARAM_get_BN(param_p, &p)) - || (param_q != NULL && !OSSL_PARAM_get_BN(param_q, &q)) - || (param_g != NULL && !OSSL_PARAM_get_BN(param_g, &g)) - || (param_priv_key != NULL - && !OSSL_PARAM_get_BN(param_priv_key, &priv_key)) - || (param_pub_key != NULL - && !OSSL_PARAM_get_BN(param_pub_key, &pub_key))) - goto err; - - if (!DSA_set0_pqg(dsa, p, q, g)) - goto err; - p = q = g = NULL; - - if (pub_key != NULL && !DSA_set0_key(dsa, pub_key, priv_key)) - goto err; - priv_key = pub_key = NULL; - - return 1; - - err: - BN_free(p); - BN_free(q); - BN_free(g); - BN_free(priv_key); - BN_free(pub_key); - return 0; -} - -static void *dsa_importkey(void *provctx, const OSSL_PARAM params[]) -{ - DSA *dsa; - - if ((dsa = DSA_new()) == NULL - || !params_to_key(dsa, params)) { - DSA_free(dsa); - dsa = NULL; - } - return dsa; -} - -const OSSL_DISPATCH dsa_keymgmt_functions[] = { - /* - * TODO(3.0) When implementing OSSL_FUNC_KEYMGMT_GENKEY, remember to also - * implement OSSL_FUNC_KEYMGMT_EXPORTKEY. - */ - { OSSL_FUNC_KEYMGMT_IMPORTKEY, (void (*)(void))dsa_importkey }, - { OSSL_FUNC_KEYMGMT_FREEKEY, (void (*)(void))DSA_free }, - { 0, NULL } -}; diff --git a/providers/common/macs/build.info b/providers/common/macs/build.info deleted file mode 100644 index 1eafe70604..0000000000 --- a/providers/common/macs/build.info +++ /dev/null @@ -1,9 +0,0 @@ -$GOAL=../../libimplementations.a - -$COMMON=gmac_prov.c hmac_prov.c kmac_prov.c - -IF[{- !$disabled{cmac} -}] - $COMMON=$COMMON cmac_prov.c -ENDIF - -SOURCE[$GOAL]=$COMMON diff --git a/providers/common/macs/cmac_prov.c b/providers/common/macs/cmac_prov.c deleted file mode 100644 index c01b2f87ad..0000000000 --- a/providers/common/macs/cmac_prov.c +++ /dev/null @@ -1,188 +0,0 @@ -/* - * 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 - */ - -#include -#include -#include -#include -#include -#include - -#include "internal/provider_algs.h" -#include "internal/provider_ctx.h" -#include "internal/provider_util.h" - -/* - * Forward declaration of everything implemented here. This is not strictly - * necessary for the compiler, but provides an assurance that the signatures - * of the functions in the dispatch table are correct. - */ -static OSSL_OP_mac_newctx_fn cmac_new; -static OSSL_OP_mac_dupctx_fn cmac_dup; -static OSSL_OP_mac_freectx_fn cmac_free; -static OSSL_OP_mac_gettable_ctx_params_fn cmac_gettable_ctx_params; -static OSSL_OP_mac_get_ctx_params_fn cmac_get_ctx_params; -static OSSL_OP_mac_settable_ctx_params_fn cmac_settable_ctx_params; -static OSSL_OP_mac_set_ctx_params_fn cmac_set_ctx_params; -static OSSL_OP_mac_init_fn cmac_init; -static OSSL_OP_mac_update_fn cmac_update; -static OSSL_OP_mac_final_fn cmac_final; - -/* local CMAC data */ - -struct cmac_data_st { - void *provctx; - CMAC_CTX *ctx; - PROV_CIPHER cipher; -}; - -static void *cmac_new(void *provctx) -{ - struct cmac_data_st *macctx; - - if ((macctx = OPENSSL_zalloc(sizeof(*macctx))) == NULL - || (macctx->ctx = CMAC_CTX_new()) == NULL) { - OPENSSL_free(macctx); - macctx = NULL; - } else { - macctx->provctx = provctx; - } - - return macctx; -} - -static void cmac_free(void *vmacctx) -{ - struct cmac_data_st *macctx = vmacctx; - - if (macctx != NULL) { - CMAC_CTX_free(macctx->ctx); - ossl_prov_cipher_reset(&macctx->cipher); - OPENSSL_free(macctx); - } -} - -static void *cmac_dup(void *vsrc) -{ - struct cmac_data_st *src = vsrc; - struct cmac_data_st *dst = cmac_new(src->provctx); - - if (!CMAC_CTX_copy(dst->ctx, src->ctx) - || !ossl_prov_cipher_copy(&dst->cipher, &src->cipher)) { - cmac_free(dst); - return NULL; - } - return dst; -} - -static size_t cmac_size(void *vmacctx) -{ - struct cmac_data_st *macctx = vmacctx; - - return EVP_CIPHER_CTX_block_size(CMAC_CTX_get0_cipher_ctx(macctx->ctx)); -} - -static int cmac_init(void *vmacctx) -{ - struct cmac_data_st *macctx = vmacctx; - int rv = CMAC_Init(macctx->ctx, NULL, 0, - ossl_prov_cipher_cipher(&macctx->cipher), - ossl_prov_cipher_engine(&macctx->cipher)); - - ossl_prov_cipher_reset(&macctx->cipher); - return rv; -} - -static int cmac_update(void *vmacctx, const unsigned char *data, - size_t datalen) -{ - struct cmac_data_st *macctx = vmacctx; - - return CMAC_Update(macctx->ctx, data, datalen); -} - -static int cmac_final(void *vmacctx, unsigned char *out, size_t *outl, - size_t outsize) -{ - struct cmac_data_st *macctx = vmacctx; - - return CMAC_Final(macctx->ctx, out, outl); -} - -static const OSSL_PARAM known_gettable_ctx_params[] = { - OSSL_PARAM_size_t(OSSL_MAC_PARAM_SIZE, NULL), - OSSL_PARAM_END -}; -static const OSSL_PARAM *cmac_gettable_ctx_params(void) -{ - return known_gettable_ctx_params; -} - -static int cmac_get_ctx_params(void *vmacctx, OSSL_PARAM params[]) -{ - OSSL_PARAM *p; - - if ((p = OSSL_PARAM_locate(params, OSSL_MAC_PARAM_SIZE)) != NULL) - return OSSL_PARAM_set_size_t(p, cmac_size(vmacctx)); - - return 1; -} - -static const OSSL_PARAM known_settable_ctx_params[] = { - OSSL_PARAM_utf8_string(OSSL_MAC_PARAM_CIPHER, NULL, 0), - OSSL_PARAM_utf8_string(OSSL_MAC_PARAM_PROPERTIES, NULL, 0), - OSSL_PARAM_octet_string(OSSL_MAC_PARAM_KEY, NULL, 0), - OSSL_PARAM_END -}; -static const OSSL_PARAM *cmac_settable_ctx_params(void) -{ - return known_settable_ctx_params; -} - -/* - * ALL parameters should be set before init(). - */ -static int cmac_set_ctx_params(void *vmacctx, const OSSL_PARAM params[]) -{ - struct cmac_data_st *macctx = vmacctx; - OPENSSL_CTX *ctx = PROV_LIBRARY_CONTEXT_OF(macctx->provctx); - const OSSL_PARAM *p; - - if (!ossl_prov_cipher_load_from_params(&macctx->cipher, params, ctx)) - return 0; - - if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_KEY)) != NULL) { - if (p->data_type != OSSL_PARAM_OCTET_STRING) - return 0; - - if (!CMAC_Init(macctx->ctx, p->data, p->data_size, - ossl_prov_cipher_cipher(&macctx->cipher), - ossl_prov_cipher_engine(&macctx->cipher))) - return 0; - - ossl_prov_cipher_reset(&macctx->cipher); - } - return 1; -} - -const OSSL_DISPATCH cmac_functions[] = { - { OSSL_FUNC_MAC_NEWCTX, (void (*)(void))cmac_new }, - { OSSL_FUNC_MAC_DUPCTX, (void (*)(void))cmac_dup }, - { OSSL_FUNC_MAC_FREECTX, (void (*)(void))cmac_free }, - { OSSL_FUNC_MAC_INIT, (void (*)(void))cmac_init }, - { OSSL_FUNC_MAC_UPDATE, (void (*)(void))cmac_update }, - { OSSL_FUNC_MAC_FINAL, (void (*)(void))cmac_final }, - { OSSL_FUNC_MAC_GETTABLE_CTX_PARAMS, - (void (*)(void))cmac_gettable_ctx_params }, - { OSSL_FUNC_MAC_GET_CTX_PARAMS, (void (*)(void))cmac_get_ctx_params }, - { OSSL_FUNC_MAC_SETTABLE_CTX_PARAMS, - (void (*)(void))cmac_settable_ctx_params }, - { OSSL_FUNC_MAC_SET_CTX_PARAMS, (void (*)(void))cmac_set_ctx_params }, - { 0, NULL } -}; diff --git a/providers/common/macs/gmac_prov.c b/providers/common/macs/gmac_prov.c deleted file mode 100644 index 3d81af8766..0000000000 --- a/providers/common/macs/gmac_prov.c +++ /dev/null @@ -1,226 +0,0 @@ -/* - * 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 - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "internal/providercommonerr.h" -#include "internal/provider_algs.h" -#include "internal/provider_ctx.h" -#include "internal/provider_util.h" - -/* - * Forward declaration of everything implemented here. This is not strictly - * necessary for the compiler, but provides an assurance that the signatures - * of the functions in the dispatch table are correct. - */ -static OSSL_OP_mac_newctx_fn gmac_new; -static OSSL_OP_mac_dupctx_fn gmac_dup; -static OSSL_OP_mac_freectx_fn gmac_free; -static OSSL_OP_mac_gettable_params_fn gmac_gettable_params; -static OSSL_OP_mac_get_params_fn gmac_get_params; -static OSSL_OP_mac_settable_ctx_params_fn gmac_settable_ctx_params; -static OSSL_OP_mac_set_ctx_params_fn gmac_set_ctx_params; -static OSSL_OP_mac_init_fn gmac_init; -static OSSL_OP_mac_update_fn gmac_update; -static OSSL_OP_mac_final_fn gmac_final; - -/* local GMAC pkey structure */ - -struct gmac_data_st { - void *provctx; - EVP_CIPHER_CTX *ctx; /* Cipher context */ - PROV_CIPHER cipher; -}; - -static size_t gmac_size(void); - -static void gmac_free(void *vmacctx) -{ - struct gmac_data_st *macctx = vmacctx; - - if (macctx != NULL) { - EVP_CIPHER_CTX_free(macctx->ctx); - ossl_prov_cipher_reset(&macctx->cipher); - OPENSSL_free(macctx); - } -} - -static void *gmac_new(void *provctx) -{ - struct gmac_data_st *macctx; - - if ((macctx = OPENSSL_zalloc(sizeof(*macctx))) == NULL - || (macctx->ctx = EVP_CIPHER_CTX_new()) == NULL) { - gmac_free(macctx); - return NULL; - } - macctx->provctx = provctx; - - return macctx; -} - -static void *gmac_dup(void *vsrc) -{ - struct gmac_data_st *src = vsrc; - struct gmac_data_st *dst = gmac_new(src->provctx); - - if (dst == NULL) - return NULL; - - if (!EVP_CIPHER_CTX_copy(dst->ctx, src->ctx) - || !ossl_prov_cipher_copy(&dst->cipher, &src->cipher)) { - gmac_free(dst); - return NULL; - } - return dst; -} - -static int gmac_init(void *vmacctx) -{ - return 1; -} - -static int gmac_update(void *vmacctx, const unsigned char *data, - size_t datalen) -{ - struct gmac_data_st *macctx = vmacctx; - EVP_CIPHER_CTX *ctx = macctx->ctx; - int outlen; - - while (datalen > INT_MAX) { - if (!EVP_EncryptUpdate(ctx, NULL, &outlen, data, INT_MAX)) - return 0; - data += INT_MAX; - datalen -= INT_MAX; - } - return EVP_EncryptUpdate(ctx, NULL, &outlen, data, datalen); -} - -static int gmac_final(void *vmacctx, unsigned char *out, size_t *outl, - size_t outsize) -{ - struct gmac_data_st *macctx = vmacctx; - int hlen = 0; - - if (!EVP_EncryptFinal_ex(macctx->ctx, out, &hlen)) - return 0; - - /* TODO(3.0) Use params */ - hlen = gmac_size(); - if (!EVP_CIPHER_CTX_ctrl(macctx->ctx, EVP_CTRL_AEAD_GET_TAG, - hlen, out)) - return 0; - - *outl = hlen; - return 1; -} - -static size_t gmac_size(void) -{ - return EVP_GCM_TLS_TAG_LEN; -} - -static const OSSL_PARAM known_gettable_params[] = { - OSSL_PARAM_size_t(OSSL_MAC_PARAM_SIZE, NULL), - OSSL_PARAM_END -}; -static const OSSL_PARAM *gmac_gettable_params(void) -{ - return known_gettable_params; -} - -static int gmac_get_params(OSSL_PARAM params[]) -{ - OSSL_PARAM *p; - - if ((p = OSSL_PARAM_locate(params, OSSL_MAC_PARAM_SIZE)) != NULL) - return OSSL_PARAM_set_size_t(p, gmac_size()); - - return 1; -} - -static const OSSL_PARAM known_settable_ctx_params[] = { - OSSL_PARAM_utf8_string(OSSL_MAC_PARAM_CIPHER, NULL, 0), - OSSL_PARAM_utf8_string(OSSL_MAC_PARAM_PROPERTIES, NULL, 0), - OSSL_PARAM_octet_string(OSSL_MAC_PARAM_KEY, NULL, 0), - OSSL_PARAM_octet_string(OSSL_MAC_PARAM_IV, NULL, 0), - OSSL_PARAM_END -}; -static const OSSL_PARAM *gmac_settable_ctx_params(void) -{ - return known_settable_ctx_params; -} - -/* - * ALL parameters should be set before init(). - */ -static int gmac_set_ctx_params(void *vmacctx, const OSSL_PARAM params[]) -{ - struct gmac_data_st *macctx = vmacctx; - EVP_CIPHER_CTX *ctx = macctx->ctx; - OPENSSL_CTX *provctx = PROV_LIBRARY_CONTEXT_OF(macctx->provctx); - const OSSL_PARAM *p; - - if (ctx == NULL - || !ossl_prov_cipher_load_from_params(&macctx->cipher, params, provctx)) - return 0; - - if (EVP_CIPHER_mode(ossl_prov_cipher_cipher(&macctx->cipher)) - != EVP_CIPH_GCM_MODE) { - ERR_raise(ERR_LIB_PROV, EVP_R_CIPHER_NOT_GCM_MODE); - return 0; - } - if (!EVP_EncryptInit_ex(ctx, ossl_prov_cipher_cipher(&macctx->cipher), - ossl_prov_cipher_engine(&macctx->cipher), NULL, - NULL)) - return 0; - - if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_KEY)) != NULL) { - if (p->data_type != OSSL_PARAM_OCTET_STRING) - return 0; - - if (p->data_size != (size_t)EVP_CIPHER_CTX_key_length(ctx)) { - ERR_raise(ERR_LIB_PROV, EVP_R_INVALID_KEY_LENGTH); - return 0; - } - if (!EVP_EncryptInit_ex(ctx, NULL, NULL, p->data, NULL)) - return 0; - } - if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_IV)) != NULL) { - if (p->data_type != OSSL_PARAM_OCTET_STRING) - return 0; - - if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, - p->data_size, NULL) - || !EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, p->data)) - return 0; - } - return 1; -} - -const OSSL_DISPATCH gmac_functions[] = { - { OSSL_FUNC_MAC_NEWCTX, (void (*)(void))gmac_new }, - { OSSL_FUNC_MAC_DUPCTX, (void (*)(void))gmac_dup }, - { OSSL_FUNC_MAC_FREECTX, (void (*)(void))gmac_free }, - { OSSL_FUNC_MAC_INIT, (void (*)(void))gmac_init }, - { OSSL_FUNC_MAC_UPDATE, (void (*)(void))gmac_update }, - { OSSL_FUNC_MAC_FINAL, (void (*)(void))gmac_final }, - { OSSL_FUNC_MAC_GETTABLE_PARAMS, (void (*)(void))gmac_gettable_params }, - { OSSL_FUNC_MAC_GET_PARAMS, (void (*)(void))gmac_get_params }, - { OSSL_FUNC_MAC_SETTABLE_CTX_PARAMS, - (void (*)(void))gmac_settable_ctx_params }, - { OSSL_FUNC_MAC_SET_CTX_PARAMS, (void (*)(void))gmac_set_ctx_params }, - { 0, NULL } -}; diff --git a/providers/common/macs/hmac_prov.c b/providers/common/macs/hmac_prov.c deleted file mode 100644 index e9d7647ce2..0000000000 --- a/providers/common/macs/hmac_prov.c +++ /dev/null @@ -1,212 +0,0 @@ -/* - * 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 - */ - -#include -#include -#include -#include -#include -#include - -#include "internal/provider_algs.h" -#include "internal/provider_ctx.h" -#include "internal/provider_util.h" - -/* - * Forward declaration of everything implemented here. This is not strictly - * necessary for the compiler, but provides an assurance that the signatures - * of the functions in the dispatch table are correct. - */ -static OSSL_OP_mac_newctx_fn hmac_new; -static OSSL_OP_mac_dupctx_fn hmac_dup; -static OSSL_OP_mac_freectx_fn hmac_free; -static OSSL_OP_mac_gettable_ctx_params_fn hmac_gettable_ctx_params; -static OSSL_OP_mac_get_ctx_params_fn hmac_get_ctx_params; -static OSSL_OP_mac_settable_ctx_params_fn hmac_settable_ctx_params; -static OSSL_OP_mac_set_ctx_params_fn hmac_set_ctx_params; -static OSSL_OP_mac_init_fn hmac_init; -static OSSL_OP_mac_update_fn hmac_update; -static OSSL_OP_mac_final_fn hmac_final; - -/* local HMAC context structure */ - -/* typedef EVP_MAC_IMPL */ -struct hmac_data_st { - void *provctx; - HMAC_CTX *ctx; /* HMAC context */ - PROV_DIGEST digest; -}; - -static size_t hmac_size(void *vmacctx); - -static void *hmac_new(void *provctx) -{ - struct hmac_data_st *macctx; - - if ((macctx = OPENSSL_zalloc(sizeof(*macctx))) == NULL - || (macctx->ctx = HMAC_CTX_new()) == NULL) { - OPENSSL_free(macctx); - return NULL; - } - /* TODO(3.0) Should we do something more with that context? */ - macctx->provctx = provctx; - - return macctx; -} - -static void hmac_free(void *vmacctx) -{ - struct hmac_data_st *macctx = vmacctx; - - if (macctx != NULL) { - HMAC_CTX_free(macctx->ctx); - ossl_prov_digest_reset(&macctx->digest); - OPENSSL_free(macctx); - } -} - -static void *hmac_dup(void *vsrc) -{ - struct hmac_data_st *src = vsrc; - struct hmac_data_st *dst = hmac_new(src->provctx); - - if (dst == NULL) - return NULL; - - if (!HMAC_CTX_copy(dst->ctx, src->ctx) - || !ossl_prov_digest_copy(&dst->digest, &src->digest)) { - hmac_free(dst); - return NULL; - } - return dst; -} - -static size_t hmac_size(void *vmacctx) -{ - struct hmac_data_st *macctx = vmacctx; - - return HMAC_size(macctx->ctx); -} - -static int hmac_init(void *vmacctx) -{ - struct hmac_data_st *macctx = vmacctx; - const EVP_MD *digest = ossl_prov_digest_md(&macctx->digest); - int rv = 1; - - /* HMAC_Init_ex doesn't tolerate all zero params, so we must be careful */ - if (digest != NULL) - rv = HMAC_Init_ex(macctx->ctx, NULL, 0, digest, - ossl_prov_digest_engine(&macctx->digest)); - ossl_prov_digest_reset(&macctx->digest); - return rv; -} - -static int hmac_update(void *vmacctx, const unsigned char *data, - size_t datalen) -{ - struct hmac_data_st *macctx = vmacctx; - - return HMAC_Update(macctx->ctx, data, datalen); -} - -static int hmac_final(void *vmacctx, unsigned char *out, size_t *outl, - size_t outsize) -{ - unsigned int hlen; - struct hmac_data_st *macctx = vmacctx; - - if (!HMAC_Final(macctx->ctx, out, &hlen)) - return 0; - if (outl != NULL) - *outl = hlen; - return 1; -} - -static const OSSL_PARAM known_gettable_ctx_params[] = { - OSSL_PARAM_size_t(OSSL_MAC_PARAM_SIZE, NULL), - OSSL_PARAM_END -}; -static const OSSL_PARAM *hmac_gettable_ctx_params(void) -{ - return known_gettable_ctx_params; -} - -static int hmac_get_ctx_params(void *vmacctx, OSSL_PARAM params[]) -{ - OSSL_PARAM *p; - - if ((p = OSSL_PARAM_locate(params, OSSL_MAC_PARAM_SIZE)) != NULL) - return OSSL_PARAM_set_size_t(p, hmac_size(vmacctx)); - - return 1; -} - -static const OSSL_PARAM known_settable_ctx_params[] = { - OSSL_PARAM_utf8_string(OSSL_MAC_PARAM_DIGEST, NULL, 0), - OSSL_PARAM_utf8_string(OSSL_MAC_PARAM_PROPERTIES, NULL, 0), - OSSL_PARAM_octet_string(OSSL_MAC_PARAM_KEY, NULL, 0), - OSSL_PARAM_int(OSSL_MAC_PARAM_FLAGS, NULL), - OSSL_PARAM_END -}; -static const OSSL_PARAM *hmac_settable_ctx_params(void) -{ - return known_settable_ctx_params; -} - -/* - * ALL parameters should be set before init(). - */ -static int hmac_set_ctx_params(void *vmacctx, const OSSL_PARAM params[]) -{ - struct hmac_data_st *macctx = vmacctx; - OPENSSL_CTX *ctx = PROV_LIBRARY_CONTEXT_OF(macctx->provctx); - const OSSL_PARAM *p; - - if (!ossl_prov_digest_load_from_params(&macctx->digest, params, ctx)) - return 0; - - /* TODO(3.0) formalize the meaning of "flags", perhaps as other params */ - if ((p = OSSL_PARAM_locate_const(params, - OSSL_MAC_PARAM_FLAGS)) != NULL) { - int flags = 0; - - if (!OSSL_PARAM_get_int(p, &flags)) - return 0; - HMAC_CTX_set_flags(macctx->ctx, flags); - } - if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_KEY)) != NULL) { - if (p->data_type != OSSL_PARAM_OCTET_STRING) - return 0; - - if (!HMAC_Init_ex(macctx->ctx, p->data, p->data_size, - ossl_prov_digest_md(&macctx->digest), - NULL /* ENGINE */)) - return 0; - - ossl_prov_digest_reset(&macctx->digest); - } - return 1; -} - -const OSSL_DISPATCH hmac_functions[] = { - { OSSL_FUNC_MAC_NEWCTX, (void (*)(void))hmac_new }, - { OSSL_FUNC_MAC_DUPCTX, (void (*)(void))hmac_dup }, - { OSSL_FUNC_MAC_FREECTX, (void (*)(void))hmac_free }, - { OSSL_FUNC_MAC_INIT, (void (*)(void))hmac_init }, - { OSSL_FUNC_MAC_UPDATE, (void (*)(void))hmac_update }, - { OSSL_FUNC_MAC_FINAL, (void (*)(void))hmac_final }, - { OSSL_FUNC_MAC_GETTABLE_CTX_PARAMS, - (void (*)(void))hmac_gettable_ctx_params }, - { OSSL_FUNC_MAC_GET_CTX_PARAMS, (void (*)(void))hmac_get_ctx_params }, - { OSSL_FUNC_MAC_SETTABLE_CTX_PARAMS, - (void (*)(void))hmac_settable_ctx_params }, - { OSSL_FUNC_MAC_SET_CTX_PARAMS, (void (*)(void))hmac_set_ctx_params }, - { 0, NULL } -}; diff --git a/providers/common/macs/kmac_prov.c b/providers/common/macs/kmac_prov.c deleted file mode 100644 index 99bcbf7da9..0000000000 --- a/providers/common/macs/kmac_prov.c +++ /dev/null @@ -1,543 +0,0 @@ -/* - * 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 - */ - -/* - * See SP800-185 "Appendix A - KMAC, .... in Terms of Keccak[c]" - * - * Inputs are: - * K = Key (len(K) < 2^2040 bits) - * X = Input - * L = Output length (0 <= L < 2^2040 bits) - * S = Customization String Default="" (len(S) < 2^2040 bits) - * - * KMAC128(K, X, L, S) - * { - * newX = bytepad(encode_string(K), 168) || X || right_encode(L). - * T = bytepad(encode_string("KMAC") || encode_string(S), 168). - * return KECCAK[256](T || newX || 00, L). - * } - * - * KMAC256(K, X, L, S) - * { - * newX = bytepad(encode_string(K), 136) || X || right_encode(L). - * T = bytepad(encode_string("KMAC") || encode_string(S), 136). - * return KECCAK[512](T || newX || 00, L). - * } - * - * KMAC128XOF(K, X, L, S) - * { - * newX = bytepad(encode_string(K), 168) || X || right_encode(0). - * T = bytepad(encode_string("KMAC") || encode_string(S), 168). - * return KECCAK[256](T || newX || 00, L). - * } - * - * KMAC256XOF(K, X, L, S) - * { - * newX = bytepad(encode_string(K), 136) || X || right_encode(0). - * T = bytepad(encode_string("KMAC") || encode_string(S), 136). - * return KECCAK[512](T || newX || 00, L). - * } - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "internal/providercommonerr.h" -#include "internal/provider_algs.h" -#include "internal/provider_ctx.h" -#include "internal/provider_util.h" - -/* - * Forward declaration of everything implemented here. This is not strictly - * necessary for the compiler, but provides an assurance that the signatures - * of the functions in the dispatch table are correct. - */ -static OSSL_OP_mac_newctx_fn kmac128_new; -static OSSL_OP_mac_newctx_fn kmac256_new; -static OSSL_OP_mac_dupctx_fn kmac_dup; -static OSSL_OP_mac_freectx_fn kmac_free; -static OSSL_OP_mac_gettable_ctx_params_fn kmac_gettable_ctx_params; -static OSSL_OP_mac_get_ctx_params_fn kmac_get_ctx_params; -static OSSL_OP_mac_settable_ctx_params_fn kmac_settable_ctx_params; -static OSSL_OP_mac_set_ctx_params_fn kmac_set_ctx_params; -static OSSL_OP_mac_size_fn kmac_size; -static OSSL_OP_mac_init_fn kmac_init; -static OSSL_OP_mac_update_fn kmac_update; -static OSSL_OP_mac_final_fn kmac_final; - -#define KMAC_MAX_BLOCKSIZE ((1600 - 128*2) / 8) /* 168 */ -#define KMAC_MIN_BLOCKSIZE ((1600 - 256*2) / 8) /* 136 */ - -/* Length encoding will be a 1 byte size + length in bits (2 bytes max) */ -#define KMAC_MAX_ENCODED_HEADER_LEN 3 - -/* - * Custom string max size is chosen such that: - * len(encoded_string(custom) + len(kmac_encoded_string) <= KMAC_MIN_BLOCKSIZE - * i.e: (KMAC_MAX_CUSTOM + KMAC_MAX_ENCODED_LEN) + 6 <= 136 - */ -#define KMAC_MAX_CUSTOM 127 - -/* Maximum size of encoded custom string */ -#define KMAC_MAX_CUSTOM_ENCODED (KMAC_MAX_CUSTOM + KMAC_MAX_ENCODED_HEADER_LEN) - -/* Maximum key size in bytes = 2040 / 8 */ -#define KMAC_MAX_KEY 255 - -/* - * Maximum Encoded Key size will be padded to a multiple of the blocksize - * i.e KMAC_MAX_KEY + KMAC_MAX_ENCODED_LEN = 258 - * Padded to a multiple of KMAC_MAX_BLOCKSIZE - */ -#define KMAC_MAX_KEY_ENCODED (KMAC_MAX_BLOCKSIZE * 2) - -/* Fixed value of encode_string("KMAC") */ -static const unsigned char kmac_string[] = { - 0x01, 0x20, 0x4B, 0x4D, 0x41, 0x43 -}; - - -#define KMAC_FLAG_XOF_MODE 1 - -struct kmac_data_st { - void *provctx; - EVP_MD_CTX *ctx; - PROV_DIGEST digest; - size_t out_len; - int key_len; - int custom_len; - /* If xof_mode = 1 then we use right_encode(0) */ - int xof_mode; - /* key and custom are stored in encoded form */ - unsigned char key[KMAC_MAX_KEY_ENCODED]; - unsigned char custom[KMAC_MAX_CUSTOM_ENCODED]; -}; - -static int encode_string(unsigned char *out, int *out_len, - const unsigned char *in, int in_len); -static int right_encode(unsigned char *out, int *out_len, size_t bits); -static int bytepad(unsigned char *out, int *out_len, - const unsigned char *in1, int in1_len, - const unsigned char *in2, int in2_len, - int w); -static int kmac_bytepad_encode_key(unsigned char *out, int *out_len, - const unsigned char *in, int in_len, - int w); - -static void kmac_free(void *vmacctx) -{ - struct kmac_data_st *kctx = vmacctx; - - if (kctx != NULL) { - EVP_MD_CTX_free(kctx->ctx); - ossl_prov_digest_reset(&kctx->digest); - OPENSSL_cleanse(kctx->key, kctx->key_len); - OPENSSL_cleanse(kctx->custom, kctx->custom_len); - OPENSSL_free(kctx); - } -} - -/* - * We have KMAC implemented as a hash, which we can use instead of - * reimplementing the EVP functionality with direct use of - * keccak_mac_init() and friends. - */ -static struct kmac_data_st *kmac_new(void *provctx) -{ - struct kmac_data_st *kctx; - - if ((kctx = OPENSSL_zalloc(sizeof(*kctx))) == NULL - || (kctx->ctx = EVP_MD_CTX_new()) == NULL) { - kmac_free(kctx); - return NULL; - } - kctx->provctx = provctx; - return kctx; -} - -static void *kmac_fetch_new(void *provctx, const OSSL_PARAM *params) -{ - struct kmac_data_st *kctx = kmac_new(provctx); - - if (kctx == NULL) - return 0; - if (!ossl_prov_digest_load_from_params(&kctx->digest, params, - PROV_LIBRARY_CONTEXT_OF(provctx))) { - kmac_free(kctx); - return 0; - } - - kctx->out_len = EVP_MD_size(ossl_prov_digest_md(&kctx->digest)); - return kctx; -} - -static void *kmac128_new(void *provctx) -{ - static const OSSL_PARAM kmac128_params[] = { - OSSL_PARAM_utf8_string("digest", OSSL_DIGEST_NAME_KECCAK_KMAC128, - sizeof(OSSL_DIGEST_NAME_KECCAK_KMAC128)), - OSSL_PARAM_END - }; - return kmac_fetch_new(provctx, kmac128_params); -} - -static void *kmac256_new(void *provctx) -{ - static const OSSL_PARAM kmac256_params[] = { - OSSL_PARAM_utf8_string("digest", OSSL_DIGEST_NAME_KECCAK_KMAC256, - sizeof(OSSL_DIGEST_NAME_KECCAK_KMAC256)), - OSSL_PARAM_END - }; - return kmac_fetch_new(provctx, kmac256_params); -} - -static void *kmac_dup(void *vsrc) -{ - struct kmac_data_st *src = vsrc; - struct kmac_data_st *dst = kmac_new(src->provctx); - - if (dst == NULL) - return NULL; - - if (!EVP_MD_CTX_copy(dst->ctx, src->ctx) - || !ossl_prov_digest_copy(&dst->digest, &src->digest)) { - kmac_free(dst); - return NULL; - } - - dst->out_len = src->out_len; - dst->key_len = src->key_len; - dst->custom_len = src->custom_len; - dst->xof_mode = src->xof_mode; - memcpy(dst->key, src->key, src->key_len); - memcpy(dst->custom, src->custom, dst->custom_len); - - return dst; -} - -/* - * The init() assumes that any ctrl methods are set beforehand for - * md, key and custom. Setting the fields afterwards will have no - * effect on the output mac. - */ -static int kmac_init(void *vmacctx) -{ - struct kmac_data_st *kctx = vmacctx; - EVP_MD_CTX *ctx = kctx->ctx; - unsigned char out[KMAC_MAX_BLOCKSIZE]; - int out_len, block_len; - - - /* Check key has been set */ - if (kctx->key_len == 0) { - EVPerr(EVP_F_KMAC_INIT, EVP_R_NO_KEY_SET); - return 0; - } - if (!EVP_DigestInit_ex(kctx->ctx, ossl_prov_digest_md(&kctx->digest), - NULL)) - return 0; - - block_len = EVP_MD_block_size(ossl_prov_digest_md(&kctx->digest)); - - /* Set default custom string if it is not already set */ - if (kctx->custom_len == 0) { - const OSSL_PARAM params[] = { - OSSL_PARAM_octet_string(OSSL_MAC_PARAM_CUSTOM, "", 0), - OSSL_PARAM_END - }; - (void)kmac_set_ctx_params(kctx, params); - } - - return bytepad(out, &out_len, kmac_string, sizeof(kmac_string), - kctx->custom, kctx->custom_len, block_len) - && EVP_DigestUpdate(ctx, out, out_len) - && EVP_DigestUpdate(ctx, kctx->key, kctx->key_len); -} - -static size_t kmac_size(void *vmacctx) -{ - struct kmac_data_st *kctx = vmacctx; - - return kctx->out_len; -} - -static int kmac_update(void *vmacctx, const unsigned char *data, - size_t datalen) -{ - struct kmac_data_st *kctx = vmacctx; - - return EVP_DigestUpdate(kctx->ctx, data, datalen); -} - -static int kmac_final(void *vmacctx, unsigned char *out, size_t *outl, - size_t outsize) -{ - struct kmac_data_st *kctx = vmacctx; - EVP_MD_CTX *ctx = kctx->ctx; - int lbits, len; - unsigned char encoded_outlen[KMAC_MAX_ENCODED_HEADER_LEN]; - int ok; - - /* KMAC XOF mode sets the encoded length to 0 */ - lbits = (kctx->xof_mode ? 0 : (kctx->out_len * 8)); - - ok = right_encode(encoded_outlen, &len, lbits) - && EVP_DigestUpdate(ctx, encoded_outlen, len) - && EVP_DigestFinalXOF(ctx, out, kctx->out_len); - if (ok && outl != NULL) - *outl = kctx->out_len; - return ok; -} - -static const OSSL_PARAM known_gettable_ctx_params[] = { - OSSL_PARAM_size_t(OSSL_MAC_PARAM_SIZE, NULL), - OSSL_PARAM_END -}; -static const OSSL_PARAM *kmac_gettable_ctx_params(void) -{ - return known_gettable_ctx_params; -} - -static int kmac_get_ctx_params(void *vmacctx, OSSL_PARAM params[]) -{ - OSSL_PARAM *p; - - if ((p = OSSL_PARAM_locate(params, OSSL_MAC_PARAM_SIZE)) != NULL) - return OSSL_PARAM_set_size_t(p, kmac_size(vmacctx)); - - return 1; -} - -static const OSSL_PARAM known_settable_ctx_params[] = { - OSSL_PARAM_int(OSSL_MAC_PARAM_XOF, NULL), - OSSL_PARAM_size_t(OSSL_MAC_PARAM_SIZE, NULL), - OSSL_PARAM_octet_string(OSSL_MAC_PARAM_KEY, NULL, 0), - OSSL_PARAM_octet_string(OSSL_MAC_PARAM_CUSTOM, NULL, 0), - OSSL_PARAM_END -}; -static const OSSL_PARAM *kmac_settable_ctx_params(void) -{ - return known_settable_ctx_params; -} - -/* - * The following params can be set any time before final(): - * - "outlen" or "size": The requested output length. - * - "xof": If set, this indicates that right_encoded(0) - * is part of the digested data, otherwise it - * uses right_encoded(requested output length). - * - * All other params should be set before init(). - */ -static int kmac_set_ctx_params(void *vmacctx, const OSSL_PARAM *params) -{ - struct kmac_data_st *kctx = vmacctx; - const OSSL_PARAM *p; - const EVP_MD *digest = ossl_prov_digest_md(&kctx->digest); - - if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_XOF)) != NULL - && !OSSL_PARAM_get_int(p, &kctx->xof_mode)) - return 0; - if (((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_SIZE)) != NULL) - && !OSSL_PARAM_get_size_t(p, &kctx->out_len)) - return 0; - if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_KEY)) != NULL) { - if (p->data_size < 4 || p->data_size > KMAC_MAX_KEY) { - ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH); - return 0; - } - if (!kmac_bytepad_encode_key(kctx->key, &kctx->key_len, - p->data, p->data_size, - EVP_MD_block_size(digest))) - return 0; - } - if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_CUSTOM)) - != NULL) { - if (p->data_size > KMAC_MAX_CUSTOM) { - ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_CUSTOM_LENGTH); - return 0; - } - if (!encode_string(kctx->custom, &kctx->custom_len, - p->data, p->data_size)) - return 0; - } - return 1; -} - -/* - * Encoding/Padding Methods. - */ - -/* Returns the number of bytes required to store 'bits' into a byte array */ -static unsigned int get_encode_size(size_t bits) -{ - unsigned int cnt = 0, sz = sizeof(size_t); - - while (bits && (cnt < sz)) { - ++cnt; - bits >>= 8; - } - /* If bits is zero 1 byte is required */ - if (cnt == 0) - cnt = 1; - return cnt; -} - -/* - * Convert an integer into bytes . The number of bytes is appended - * to the end of the buffer. Returns an array of bytes 'out' of size - * *out_len. - * - * e.g if bits = 32, out[2] = { 0x20, 0x01 } - * - */ -static int right_encode(unsigned char *out, int *out_len, size_t bits) -{ - unsigned int len = get_encode_size(bits); - int i; - - /* The length is constrained to a single byte: 2040/8 = 255 */ - if (len > 0xFF) - return 0; - - /* MSB's are at the start of the bytes array */ - for (i = len - 1; i >= 0; --i) { - out[i] = (unsigned char)(bits & 0xFF); - bits >>= 8; - } - /* Tack the length onto the end */ - out[len] = (unsigned char)len; - - /* The Returned length includes the tacked on byte */ - *out_len = len + 1; - return 1; -} - -/* - * Encodes a string with a left encoded length added. Note that the - * in_len is converted to bits (*8). - * - * e.g- in="KMAC" gives out[6] = { 0x01, 0x20, 0x4B, 0x4D, 0x41, 0x43 } - * len bits K M A C - */ -static int encode_string(unsigned char *out, int *out_len, - const unsigned char *in, int in_len) -{ - if (in == NULL) { - *out_len = 0; - } else { - int i, bits, len; - - bits = 8 * in_len; - len = get_encode_size(bits); - if (len > 0xFF) - return 0; - - out[0] = len; - for (i = len; i > 0; --i) { - out[i] = (bits & 0xFF); - bits >>= 8; - } - memcpy(out + len + 1, in, in_len); - *out_len = (1 + len + in_len); - } - return 1; -} - -/* - * Returns a zero padded encoding of the inputs in1 and an optional - * in2 (can be NULL). The padded output must be a multiple of the blocksize 'w'. - * The value of w is in bytes (< 256). - * - * The returned output is: - * zero_padded(multiple of w, (left_encode(w) || in1 [|| in2]) - */ -static int bytepad(unsigned char *out, int *out_len, - const unsigned char *in1, int in1_len, - const unsigned char *in2, int in2_len, int w) -{ - int len; - unsigned char *p = out; - int sz = w; - - /* Left encoded w */ - *p++ = 1; - *p++ = w; - /* || in1 */ - memcpy(p, in1, in1_len); - p += in1_len; - /* [ || in2 ] */ - if (in2 != NULL && in2_len > 0) { - memcpy(p, in2, in2_len); - p += in2_len; - } - /* Figure out the pad size (divisible by w) */ - len = p - out; - while (len > sz) { - sz += w; - } - /* zero pad the end of the buffer */ - memset(p, 0, sz - len); - *out_len = sz; - return 1; -} - -/* - * Returns out = bytepad(encode_string(in), w) - */ -static int kmac_bytepad_encode_key(unsigned char *out, int *out_len, - const unsigned char *in, int in_len, - int w) -{ - unsigned char tmp[KMAC_MAX_KEY + KMAC_MAX_ENCODED_HEADER_LEN]; - int tmp_len; - - if (!encode_string(tmp, &tmp_len, in, in_len)) - return 0; - - return bytepad(out, out_len, tmp, tmp_len, NULL, 0, w); -} - -const OSSL_DISPATCH kmac128_functions[] = { - { OSSL_FUNC_MAC_NEWCTX, (void (*)(void))kmac128_new }, - { OSSL_FUNC_MAC_DUPCTX, (void (*)(void))kmac_dup }, - { OSSL_FUNC_MAC_FREECTX, (void (*)(void))kmac_free }, - { OSSL_FUNC_MAC_INIT, (void (*)(void))kmac_init }, - { OSSL_FUNC_MAC_UPDATE, (void (*)(void))kmac_update }, - { OSSL_FUNC_MAC_FINAL, (void (*)(void))kmac_final }, - { OSSL_FUNC_MAC_GETTABLE_CTX_PARAMS, - (void (*)(void))kmac_gettable_ctx_params }, - { OSSL_FUNC_MAC_GET_CTX_PARAMS, (void (*)(void))kmac_get_ctx_params }, - { OSSL_FUNC_MAC_SETTABLE_CTX_PARAMS, - (void (*)(void))kmac_settable_ctx_params }, - { OSSL_FUNC_MAC_SET_CTX_PARAMS, (void (*)(void))kmac_set_ctx_params }, - { 0, NULL } -}; - -const OSSL_DISPATCH kmac256_functions[] = { - { OSSL_FUNC_MAC_NEWCTX, (void (*)(void))kmac256_new }, - { OSSL_FUNC_MAC_DUPCTX, (void (*)(void))kmac_dup }, - { OSSL_FUNC_MAC_FREECTX, (void (*)(void))kmac_free }, - { OSSL_FUNC_MAC_INIT, (void (*)(void))kmac_init }, - { OSSL_FUNC_MAC_UPDATE, (void (*)(void))kmac_update }, - { OSSL_FUNC_MAC_FINAL, (void (*)(void))kmac_final }, - { OSSL_FUNC_MAC_GETTABLE_CTX_PARAMS, - (void (*)(void))kmac_gettable_ctx_params }, - { OSSL_FUNC_MAC_GET_CTX_PARAMS, (void (*)(void))kmac_get_ctx_params }, - { OSSL_FUNC_MAC_SETTABLE_CTX_PARAMS, - (void (*)(void))kmac_settable_ctx_params }, - { OSSL_FUNC_MAC_SET_CTX_PARAMS, (void (*)(void))kmac_set_ctx_params }, - { 0, NULL } -}; diff --git a/providers/common/signature/build.info b/providers/common/signature/build.info deleted file mode 100644 index 496fb7d7d8..0000000000 --- a/providers/common/signature/build.info +++ /dev/null @@ -1,7 +0,0 @@ -$GOAL=../../libimplementations.a - -IF[{- !$disabled{dsa} -}] - SOURCE[$GOAL]=dsa.c -ENDIF - - diff --git a/providers/common/signature/dsa.c b/providers/common/signature/dsa.c deleted file mode 100644 index 1d6b565d38..0000000000 --- a/providers/common/signature/dsa.c +++ /dev/null @@ -1,407 +0,0 @@ -/* - * Copyright 2019 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 - */ - -#include -#include -#include -#include -#include -#include -#include "internal/provider_algs.h" -#include "internal/provider_ctx.h" - -static OSSL_OP_signature_newctx_fn dsa_newctx; -static OSSL_OP_signature_sign_init_fn dsa_signature_init; -static OSSL_OP_signature_verify_init_fn dsa_signature_init; -static OSSL_OP_signature_sign_fn dsa_sign; -static OSSL_OP_signature_verify_fn dsa_verify; -static OSSL_OP_signature_digest_sign_init_fn dsa_digest_signverify_init; -static OSSL_OP_signature_digest_sign_update_fn dsa_digest_signverify_update; -static OSSL_OP_signature_digest_sign_final_fn dsa_digest_sign_final; -static OSSL_OP_signature_digest_verify_init_fn dsa_digest_signverify_init; -static OSSL_OP_signature_digest_verify_update_fn dsa_digest_signverify_update; -static OSSL_OP_signature_digest_verify_final_fn dsa_digest_verify_final; -static OSSL_OP_signature_freectx_fn dsa_freectx; -static OSSL_OP_signature_dupctx_fn dsa_dupctx; -static OSSL_OP_signature_get_ctx_params_fn dsa_get_ctx_params; -static OSSL_OP_signature_gettable_ctx_params_fn dsa_gettable_ctx_params; -static OSSL_OP_signature_set_ctx_params_fn dsa_set_ctx_params; -static OSSL_OP_signature_settable_ctx_params_fn dsa_settable_ctx_params; -static OSSL_OP_signature_get_ctx_md_params_fn dsa_get_ctx_md_params; -static OSSL_OP_signature_gettable_ctx_md_params_fn dsa_gettable_ctx_md_params; -static OSSL_OP_signature_set_ctx_md_params_fn dsa_set_ctx_md_params; -static OSSL_OP_signature_settable_ctx_md_params_fn dsa_settable_ctx_md_params; - -/* - * What's passed as an actual key is defined by the KEYMGMT interface. - * We happen to know that our KEYMGMT simply passes DSA structures, so - * we use that here too. - */ - -typedef struct { - OPENSSL_CTX *libctx; - DSA *dsa; - size_t mdsize; - /* Should be big enough */ - char mdname[80]; - EVP_MD *md; - EVP_MD_CTX *mdctx; -} PROV_DSA_CTX; - -static void *dsa_newctx(void *provctx) -{ - PROV_DSA_CTX *pdsactx = OPENSSL_zalloc(sizeof(PROV_DSA_CTX)); - - if (pdsactx == NULL) - return NULL; - - pdsactx->libctx = PROV_LIBRARY_CONTEXT_OF(provctx); - return pdsactx; -} - -static int dsa_signature_init(void *vpdsactx, void *vdsa) -{ - PROV_DSA_CTX *pdsactx = (PROV_DSA_CTX *)vpdsactx; - - if (pdsactx == NULL || vdsa == NULL || !DSA_up_ref(vdsa)) - return 0; - DSA_free(pdsactx->dsa); - pdsactx->dsa = vdsa; - return 1; -} - -static int dsa_sign(void *vpdsactx, unsigned char *sig, size_t *siglen, - size_t sigsize, const unsigned char *tbs, size_t tbslen) -{ - PROV_DSA_CTX *pdsactx = (PROV_DSA_CTX *)vpdsactx; - int ret; - unsigned int sltmp; - size_t dsasize = DSA_size(pdsactx->dsa); - - if (sig == NULL) { - *siglen = dsasize; - return 1; - } - - if (sigsize < (size_t)dsasize) - return 0; - - if (pdsactx->mdsize != 0 && tbslen != pdsactx->mdsize) - return 0; - - ret = DSA_sign(0, tbs, tbslen, sig, &sltmp, pdsactx->dsa); - - if (ret <= 0) - return 0; - - *siglen = sltmp; - return 1; -} - -static int dsa_verify(void *vpdsactx, const unsigned char *sig, size_t siglen, - const unsigned char *tbs, size_t tbslen) -{ - PROV_DSA_CTX *pdsactx = (PROV_DSA_CTX *)vpdsactx; - - if (pdsactx->mdsize != 0 && tbslen != pdsactx->mdsize) - return 0; - - return DSA_verify(0, tbs, tbslen, sig, siglen, pdsactx->dsa); -} - -static int dsa_digest_signverify_init(void *vpdsactx, const char *mdname, - const char *props, void *vdsa) -{ - PROV_DSA_CTX *pdsactx = (PROV_DSA_CTX *)vpdsactx; - EVP_MD *md; - - if (!dsa_signature_init(vpdsactx, vdsa)) - return 0; - - md = EVP_MD_fetch(pdsactx->libctx, mdname, props); - if (md == NULL) - return 0; - pdsactx->md = md; - pdsactx->mdsize = EVP_MD_size(md); - pdsactx->mdctx = EVP_MD_CTX_new(); - if (pdsactx->mdctx == NULL) - return 0; - - if (!EVP_DigestInit_ex(pdsactx->mdctx, md, NULL)) - return 0; - - return 1; -} - -int dsa_digest_signverify_update(void *vpdsactx, const unsigned char *data, - size_t datalen) -{ - PROV_DSA_CTX *pdsactx = (PROV_DSA_CTX *)vpdsactx; - - if (pdsactx == NULL || pdsactx->mdctx == NULL) - return 0; - - return EVP_DigestUpdate(pdsactx->mdctx, data, datalen); -} - -int dsa_digest_sign_final(void *vpdsactx, unsigned char *sig, size_t *siglen, - size_t sigsize) -{ - PROV_DSA_CTX *pdsactx = (PROV_DSA_CTX *)vpdsactx; - unsigned char digest[EVP_MAX_MD_SIZE]; - unsigned int dlen = 0; - - if (pdsactx == NULL || pdsactx->mdctx == NULL) - return 0; - - /* - * If sig is NULL then we're just finding out the sig size. Other fields - * are ignored. Defer to dsa_sign. - */ - if (sig != NULL) { - /* - * TODO(3.0): There is the possibility that some externally provided - * digests exceed EVP_MAX_MD_SIZE. We should probably handle that somehow - - * but that problem is much larger than just in DSA. - */ - if (!EVP_DigestFinal_ex(pdsactx->mdctx, digest, &dlen)) - return 0; - } - - return dsa_sign(vpdsactx, sig, siglen, sigsize, digest, (size_t)dlen); -} - - -int dsa_digest_verify_final(void *vpdsactx, const unsigned char *sig, - size_t siglen) -{ - PROV_DSA_CTX *pdsactx = (PROV_DSA_CTX *)vpdsactx; - unsigned char digest[EVP_MAX_MD_SIZE]; - unsigned int dlen = 0; - - if (pdsactx == NULL || pdsactx->mdctx == NULL) - return 0; - - /* - * TODO(3.0): There is the possibility that some externally provided - * digests exceed EVP_MAX_MD_SIZE. We should probably handle that somehow - - * but that problem is much larger than just in DSA. - */ - if (!EVP_DigestFinal_ex(pdsactx->mdctx, digest, &dlen)) - return 0; - - return dsa_verify(vpdsactx, sig, siglen, digest, (size_t)dlen); -} - -static void dsa_freectx(void *vpdsactx) -{ - PROV_DSA_CTX *pdsactx = (PROV_DSA_CTX *)vpdsactx; - - DSA_free(pdsactx->dsa); - EVP_MD_CTX_free(pdsactx->mdctx); - EVP_MD_free(pdsactx->md); - - OPENSSL_free(pdsactx); -} - -static void *dsa_dupctx(void *vpdsactx) -{ - PROV_DSA_CTX *srcctx = (PROV_DSA_CTX *)vpdsactx; - PROV_DSA_CTX *dstctx; - - dstctx = OPENSSL_zalloc(sizeof(*srcctx)); - if (dstctx == NULL) - return NULL; - - *dstctx = *srcctx; - dstctx->dsa = NULL; - dstctx->md = NULL; - dstctx->mdctx = NULL; - - if (srcctx->dsa != NULL && !DSA_up_ref(srcctx->dsa)) - goto err; - dstctx->dsa = srcctx->dsa; - - if (srcctx->md != NULL && !EVP_MD_up_ref(srcctx->md)) - goto err; - dstctx->md = srcctx->md; - - if (srcctx->mdctx != NULL) { - dstctx->mdctx = EVP_MD_CTX_new(); - if (dstctx->mdctx == NULL - || !EVP_MD_CTX_copy_ex(dstctx->mdctx, srcctx->mdctx)) - goto err; - } - - return dstctx; - err: - dsa_freectx(dstctx); - return NULL; -} - -static int dsa_get_ctx_params(void *vpdsactx, OSSL_PARAM *params) -{ - PROV_DSA_CTX *pdsactx = (PROV_DSA_CTX *)vpdsactx; - OSSL_PARAM *p; - - if (pdsactx == NULL || params == NULL) - return 0; - - p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_DIGEST_SIZE); - if (p != NULL && !OSSL_PARAM_set_size_t(p, pdsactx->mdsize)) - return 0; - - p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_DIGEST); - if (p != NULL && !OSSL_PARAM_set_utf8_string(p, pdsactx->md == NULL - ? pdsactx->mdname - : EVP_MD_name(pdsactx->md))) - return 0; - - return 1; -} - -static const OSSL_PARAM known_gettable_ctx_params[] = { - OSSL_PARAM_size_t(OSSL_SIGNATURE_PARAM_DIGEST_SIZE, NULL), - OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST, NULL, 0), - OSSL_PARAM_END -}; - -static const OSSL_PARAM *dsa_gettable_ctx_params(void) -{ - return known_gettable_ctx_params; -} - -static int dsa_set_ctx_params(void *vpdsactx, const OSSL_PARAM params[]) -{ - PROV_DSA_CTX *pdsactx = (PROV_DSA_CTX *)vpdsactx; - const OSSL_PARAM *p; - char *mdname; - - if (pdsactx == NULL || params == NULL) - return 0; - - if (pdsactx->md != NULL) { - /* - * You cannot set the digest name/size when doing a DigestSign or - * DigestVerify. - */ - return 1; - } - - p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_DIGEST_SIZE); - if (p != NULL && !OSSL_PARAM_get_size_t(p, &pdsactx->mdsize)) - return 0; - - /* - * We never actually use the mdname, but we do support getting it later. - * This can be useful for applications that want to know the MD that they - * previously set. - */ - p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_DIGEST); - mdname = pdsactx->mdname; - if (p != NULL - && !OSSL_PARAM_get_utf8_string(p, &mdname, sizeof(pdsactx->mdname))) - return 0; - - return 1; -} - -static const OSSL_PARAM known_settable_ctx_params[] = { - OSSL_PARAM_size_t(OSSL_SIGNATURE_PARAM_DIGEST_SIZE, NULL), - OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST, NULL, 0), - OSSL_PARAM_END -}; - -static const OSSL_PARAM *dsa_settable_ctx_params(void) -{ - /* - * TODO(3.0): Should this function return a different set of settable ctx - * params if the ctx is being used for a DigestSign/DigestVerify? In that - * case it is not allowed to set the digest size/digest name because the - * digest is explicitly set as part of the init. - */ - return known_settable_ctx_params; -} - -static int dsa_get_ctx_md_params(void *vpdsactx, OSSL_PARAM *params) -{ - PROV_DSA_CTX *pdsactx = (PROV_DSA_CTX *)vpdsactx; - - if (pdsactx->mdctx == NULL) - return 0; - - return EVP_MD_CTX_get_params(pdsactx->mdctx, params); -} - -static const OSSL_PARAM *dsa_gettable_ctx_md_params(void *vpdsactx) -{ - PROV_DSA_CTX *pdsactx = (PROV_DSA_CTX *)vpdsactx; - - if (pdsactx->md == NULL) - return 0; - - return EVP_MD_gettable_ctx_params(pdsactx->md); -} - -static int dsa_set_ctx_md_params(void *vpdsactx, const OSSL_PARAM params[]) -{ - PROV_DSA_CTX *pdsactx = (PROV_DSA_CTX *)vpdsactx; - - if (pdsactx->mdctx == NULL) - return 0; - - return EVP_MD_CTX_set_params(pdsactx->mdctx, params); -} - -static const OSSL_PARAM *dsa_settable_ctx_md_params(void *vpdsactx) -{ - PROV_DSA_CTX *pdsactx = (PROV_DSA_CTX *)vpdsactx; - - if (pdsactx->md == NULL) - return 0; - - return EVP_MD_settable_ctx_params(pdsactx->md); -} - -const OSSL_DISPATCH dsa_signature_functions[] = { - { OSSL_FUNC_SIGNATURE_NEWCTX, (void (*)(void))dsa_newctx }, - { OSSL_FUNC_SIGNATURE_SIGN_INIT, (void (*)(void))dsa_signature_init }, - { OSSL_FUNC_SIGNATURE_SIGN, (void (*)(void))dsa_sign }, - { OSSL_FUNC_SIGNATURE_VERIFY_INIT, (void (*)(void))dsa_signature_init }, - { OSSL_FUNC_SIGNATURE_VERIFY, (void (*)(void))dsa_verify }, - { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT, - (void (*)(void))dsa_digest_signverify_init }, - { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_UPDATE, - (void (*)(void))dsa_digest_signverify_update }, - { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_FINAL, - (void (*)(void))dsa_digest_sign_final }, - { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT, - (void (*)(void))dsa_digest_signverify_init }, - { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_UPDATE, - (void (*)(void))dsa_digest_signverify_update }, - { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_FINAL, - (void (*)(void))dsa_digest_verify_final }, - { OSSL_FUNC_SIGNATURE_FREECTX, (void (*)(void))dsa_freectx }, - { OSSL_FUNC_SIGNATURE_DUPCTX, (void (*)(void))dsa_dupctx }, - { OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS, (void (*)(void))dsa_get_ctx_params }, - { OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS, - (void (*)(void))dsa_gettable_ctx_params }, - { OSSL_FUNC_SIGNATURE_SET_CTX_PARAMS, (void (*)(void))dsa_set_ctx_params }, - { OSSL_FUNC_SIGNATURE_SETTABLE_CTX_PARAMS, - (void (*)(void))dsa_settable_ctx_params }, - { OSSL_FUNC_SIGNATURE_GET_CTX_MD_PARAMS, - (void (*)(void))dsa_get_ctx_md_params }, - { OSSL_FUNC_SIGNATURE_GETTABLE_CTX_MD_PARAMS, - (void (*)(void))dsa_gettable_ctx_md_params }, - { OSSL_FUNC_SIGNATURE_SET_CTX_MD_PARAMS, - (void (*)(void))dsa_set_ctx_md_params }, - { OSSL_FUNC_SIGNATURE_SETTABLE_CTX_MD_PARAMS, - (void (*)(void))dsa_settable_ctx_md_params }, - { 0, NULL } -}; diff --git a/providers/implementations/build.info b/providers/implementations/build.info new file mode 100644 index 0000000000..1170ef96b3 --- /dev/null +++ b/providers/implementations/build.info @@ -0,0 +1 @@ +SUBDIRS=macs kdfs exchange keymgmt signature diff --git a/providers/implementations/exchange/build.info b/providers/implementations/exchange/build.info new file mode 100644 index 0000000000..fdedb86c03 --- /dev/null +++ b/providers/implementations/exchange/build.info @@ -0,0 +1,8 @@ +# We make separate GOAL variables for each algorithm, to make it easy to +# switch each to the Legacy provider when needed. + +$DH_GOAL=../../libimplementations.a + +IF[{- !$disabled{dh} -}] + SOURCE[$DH_GOAL]=dh_exch.c +ENDIF diff --git a/providers/implementations/exchange/dh_exch.c b/providers/implementations/exchange/dh_exch.c new file mode 100644 index 0000000000..cfbda43fb8 --- /dev/null +++ b/providers/implementations/exchange/dh_exch.c @@ -0,0 +1,166 @@ +/* + * Copyright 2019 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 + */ + +#include +#include +#include +#include +#include +#include "internal/provider_algs.h" + +static OSSL_OP_keyexch_newctx_fn dh_newctx; +static OSSL_OP_keyexch_init_fn dh_init; +static OSSL_OP_keyexch_set_peer_fn dh_set_peer; +static OSSL_OP_keyexch_derive_fn dh_derive; +static OSSL_OP_keyexch_freectx_fn dh_freectx; +static OSSL_OP_keyexch_dupctx_fn dh_dupctx; +static OSSL_OP_keyexch_set_ctx_params_fn dh_set_ctx_params; +static OSSL_OP_keyexch_settable_ctx_params_fn dh_settable_ctx_params; + +/* + * What's passed as an actual key is defined by the KEYMGMT interface. + * We happen to know that our KEYMGMT simply passes DH structures, so + * we use that here too. + */ + +typedef struct { + DH *dh; + DH *dhpeer; + unsigned int pad : 1; +} PROV_DH_CTX; + +static void *dh_newctx(void *provctx) +{ + return OPENSSL_zalloc(sizeof(PROV_DH_CTX)); +} + +static int dh_init(void *vpdhctx, void *vdh) +{ + PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx; + + if (pdhctx == NULL || vdh == NULL || !DH_up_ref(vdh)) + return 0; + DH_free(pdhctx->dh); + pdhctx->dh = vdh; + return 1; +} + +static int dh_set_peer(void *vpdhctx, void *vdh) +{ + PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx; + + if (pdhctx == NULL || vdh == NULL || !DH_up_ref(vdh)) + return 0; + DH_free(pdhctx->dhpeer); + pdhctx->dhpeer = vdh; + return 1; +} + +static int dh_derive(void *vpdhctx, unsigned char *secret, size_t *secretlen, + size_t outlen) +{ + PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx; + int ret; + size_t dhsize; + const BIGNUM *pub_key = NULL; + + /* TODO(3.0): Add errors to stack */ + if (pdhctx->dh == NULL || pdhctx->dhpeer == NULL) + return 0; + + dhsize = (size_t)DH_size(pdhctx->dh); + if (secret == NULL) { + *secretlen = dhsize; + return 1; + } + if (outlen < dhsize) + return 0; + + DH_get0_key(pdhctx->dhpeer, &pub_key, NULL); + ret = (pdhctx->pad) ? DH_compute_key_padded(secret, pub_key, pdhctx->dh) + : DH_compute_key(secret, pub_key, pdhctx->dh); + if (ret <= 0) + return 0; + + *secretlen = ret; + return 1; +} + +static void dh_freectx(void *vpdhctx) +{ + PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx; + + DH_free(pdhctx->dh); + DH_free(pdhctx->dhpeer); + + OPENSSL_free(pdhctx); +} + +static void *dh_dupctx(void *vpdhctx) +{ + PROV_DH_CTX *srcctx = (PROV_DH_CTX *)vpdhctx; + PROV_DH_CTX *dstctx; + + dstctx = OPENSSL_zalloc(sizeof(*srcctx)); + if (dstctx == NULL) + return NULL; + + *dstctx = *srcctx; + if (dstctx->dh != NULL && !DH_up_ref(dstctx->dh)) { + OPENSSL_free(dstctx); + return NULL; + } + + if (dstctx->dhpeer != NULL && !DH_up_ref(dstctx->dhpeer)) { + DH_free(dstctx->dh); + OPENSSL_free(dstctx); + return NULL; + } + + return dstctx; +} + +static int dh_set_ctx_params(void *vpdhctx, const OSSL_PARAM params[]) +{ + PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx; + const OSSL_PARAM *p; + unsigned int pad; + + if (pdhctx == NULL || params == NULL) + return 0; + + p = OSSL_PARAM_locate_const(params, OSSL_EXCHANGE_PARAM_PAD); + if (p == NULL || !OSSL_PARAM_get_uint(p, &pad)) + return 0; + pdhctx->pad = pad ? 1 : 0; + return 1; +} + +static const OSSL_PARAM known_settable_ctx_params[] = { + OSSL_PARAM_int(OSSL_EXCHANGE_PARAM_PAD, NULL), + OSSL_PARAM_END +}; + +static const OSSL_PARAM *dh_settable_ctx_params(void) +{ + return known_settable_ctx_params; +} + +const OSSL_DISPATCH dh_keyexch_functions[] = { + { OSSL_FUNC_KEYEXCH_NEWCTX, (void (*)(void))dh_newctx }, + { OSSL_FUNC_KEYEXCH_INIT, (void (*)(void))dh_init }, + { OSSL_FUNC_KEYEXCH_DERIVE, (void (*)(void))dh_derive }, + { OSSL_FUNC_KEYEXCH_SET_PEER, (void (*)(void))dh_set_peer }, + { OSSL_FUNC_KEYEXCH_FREECTX, (void (*)(void))dh_freectx }, + { OSSL_FUNC_KEYEXCH_DUPCTX, (void (*)(void))dh_dupctx }, + { OSSL_FUNC_KEYEXCH_SET_CTX_PARAMS, (void (*)(void))dh_set_ctx_params }, + { OSSL_FUNC_KEYEXCH_SETTABLE_CTX_PARAMS, + (void (*)(void))dh_settable_ctx_params }, + { 0, NULL } +}; diff --git a/providers/implementations/kdfs/build.info b/providers/implementations/kdfs/build.info new file mode 100644 index 0000000000..8800b12f7e --- /dev/null +++ b/providers/implementations/kdfs/build.info @@ -0,0 +1,22 @@ +# We make separate GOAL variables for each algorithm, to make it easy to +# switch each to the Legacy provider when needed. + +$TLS1_PRF_GOAL=../../libimplementations.a +$HKDF_GOAL=../../libimplementations.a +$KBKDF_GOAL=../../libimplementations.a +$PBKDF2_GOAL=../../libimplementations.a +$SSKDF_GOAL=../../libimplementations.a + +SOURCE[$TLS1_PRF_GOAL]=tls1_prf.c + +SOURCE[$HKDF_GOAL]=hkdf.c + +SOURCE[$KBKDF_GOAL]=kbkdf.c + +SOURCE[$PBKDF2_GOAL]=pbkdf2.c +# Extra code to satisfy the FIPS and non-FIPS separation. +# When the PBKDF2 moves to legacy, this can be removed. +SOURCE[../../libfips.a]=pbkdf2_fips.c +SOURCE[../../libnonfips.a]=pbkdf2_fips.c + +SOURCE[$SSKDF_GOAL]=sskdf.c diff --git a/providers/implementations/kdfs/hkdf.c b/providers/implementations/kdfs/hkdf.c new file mode 100644 index 0000000000..041811f0e1 --- /dev/null +++ b/providers/implementations/kdfs/hkdf.c @@ -0,0 +1,463 @@ +/* + * Copyright 2016-2019 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 + */ + +#include +#include +#include +#include +#include +#include +#include +#include "internal/cryptlib.h" +#include "internal/numbers.h" +#include "crypto/evp.h" +#include "internal/provider_ctx.h" +#include "internal/providercommonerr.h" +#include "internal/provider_algs.h" +#include "internal/provider_util.h" +#include "e_os.h" + +#define HKDF_MAXBUF 1024 + +static OSSL_OP_kdf_newctx_fn kdf_hkdf_new; +static OSSL_OP_kdf_freectx_fn kdf_hkdf_free; +static OSSL_OP_kdf_reset_fn kdf_hkdf_reset; +static OSSL_OP_kdf_derive_fn kdf_hkdf_derive; +static OSSL_OP_kdf_settable_ctx_params_fn kdf_hkdf_settable_ctx_params; +static OSSL_OP_kdf_set_ctx_params_fn kdf_hkdf_set_ctx_params; +static OSSL_OP_kdf_gettable_ctx_params_fn kdf_hkdf_gettable_ctx_params; +static OSSL_OP_kdf_get_ctx_params_fn kdf_hkdf_get_ctx_params; + +static int HKDF(const EVP_MD *evp_md, + const unsigned char *salt, size_t salt_len, + const unsigned char *key, size_t key_len, + const unsigned char *info, size_t info_len, + unsigned char *okm, size_t okm_len); +static int HKDF_Extract(const EVP_MD *evp_md, + const unsigned char *salt, size_t salt_len, + const unsigned char *ikm, size_t ikm_len, + unsigned char *prk, size_t prk_len); +static int HKDF_Expand(const EVP_MD *evp_md, + const unsigned char *prk, size_t prk_len, + const unsigned char *info, size_t info_len, + unsigned char *okm, size_t okm_len); + +typedef struct { + void *provctx; + int mode; + PROV_DIGEST digest; + unsigned char *salt; + size_t salt_len; + unsigned char *key; + size_t key_len; + unsigned char info[HKDF_MAXBUF]; + size_t info_len; +} KDF_HKDF; + +static void *kdf_hkdf_new(void *provctx) +{ + KDF_HKDF *ctx; + + if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + else + ctx->provctx = provctx; + return ctx; +} + +static void kdf_hkdf_free(void *vctx) +{ + KDF_HKDF *ctx = (KDF_HKDF *)vctx; + + kdf_hkdf_reset(ctx); + OPENSSL_free(ctx); +} + +static void kdf_hkdf_reset(void *vctx) +{ + KDF_HKDF *ctx = (KDF_HKDF *)vctx; + + ossl_prov_digest_reset(&ctx->digest); + OPENSSL_free(ctx->salt); + OPENSSL_clear_free(ctx->key, ctx->key_len); + OPENSSL_cleanse(ctx->info, ctx->info_len); + memset(ctx, 0, sizeof(*ctx)); +} + +static size_t kdf_hkdf_size(KDF_HKDF *ctx) +{ + int sz; + const EVP_MD *md = ossl_prov_digest_md(&ctx->digest); + + if (ctx->mode != EVP_KDF_HKDF_MODE_EXTRACT_ONLY) + return SIZE_MAX; + + if (md == NULL) { + ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST); + return 0; + } + sz = EVP_MD_size(md); + if (sz < 0) + return 0; + + return sz; +} + +static int kdf_hkdf_derive(void *vctx, unsigned char *key, size_t keylen) +{ + KDF_HKDF *ctx = (KDF_HKDF *)vctx; + const EVP_MD *md = ossl_prov_digest_md(&ctx->digest); + + if (md == NULL) { + ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST); + return 0; + } + if (ctx->key == NULL) { + ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_KEY); + return 0; + } + + switch (ctx->mode) { + case EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND: + return HKDF(md, ctx->salt, ctx->salt_len, ctx->key, + ctx->key_len, ctx->info, ctx->info_len, key, + keylen); + + case EVP_KDF_HKDF_MODE_EXTRACT_ONLY: + return HKDF_Extract(md, ctx->salt, ctx->salt_len, ctx->key, + ctx->key_len, key, keylen); + + case EVP_KDF_HKDF_MODE_EXPAND_ONLY: + return HKDF_Expand(md, ctx->key, ctx->key_len, ctx->info, + ctx->info_len, key, keylen); + + default: + return 0; + } +} + +static int kdf_hkdf_set_ctx_params(void *vctx, const OSSL_PARAM params[]) +{ + const OSSL_PARAM *p; + KDF_HKDF *ctx = vctx; + OPENSSL_CTX *provctx = PROV_LIBRARY_CONTEXT_OF(ctx->provctx); + int n; + + if (!ossl_prov_digest_load_from_params(&ctx->digest, params, provctx)) + return 0; + + if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_MODE)) != NULL) { + if (p->data_type == OSSL_PARAM_UTF8_STRING) { + if (strcasecmp(p->data, "EXTRACT_AND_EXPAND") == 0) { + ctx->mode = EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND; + } else if (strcasecmp(p->data, "EXTRACT_ONLY") == 0) { + ctx->mode = EVP_KDF_HKDF_MODE_EXTRACT_ONLY; + } else if (strcasecmp(p->data, "EXPAND_ONLY") == 0) { + ctx->mode = EVP_KDF_HKDF_MODE_EXPAND_ONLY; + } else { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_MODE); + return 0; + } + } else if (OSSL_PARAM_get_int(p, &n)) { + if (n != EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND + && n != EVP_KDF_HKDF_MODE_EXTRACT_ONLY + && n != EVP_KDF_HKDF_MODE_EXPAND_ONLY) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_MODE); + return 0; + } + ctx->mode = n; + } else { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_MODE); + return 0; + } + } + + if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_KEY)) != NULL) { + OPENSSL_clear_free(ctx->key, ctx->key_len); + ctx->key = NULL; + if (!OSSL_PARAM_get_octet_string(p, (void **)&ctx->key, 0, + &ctx->key_len)) + return 0; + } + + if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SALT)) != NULL) { + if (p->data_size != 0 && p->data != NULL) { + OPENSSL_free(ctx->salt); + ctx->salt = NULL; + if (!OSSL_PARAM_get_octet_string(p, (void **)&ctx->salt, 0, + &ctx->salt_len)) + return 0; + } + } + /* The info fields concatenate, so process them all */ + if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_INFO)) != NULL) { + ctx->info_len = 0; + for (; p != NULL; p = OSSL_PARAM_locate_const(p + 1, + OSSL_KDF_PARAM_INFO)) { + const void *q = ctx->info + ctx->info_len; + size_t sz = 0; + + if (p->data_size != 0 + && p->data != NULL + && !OSSL_PARAM_get_octet_string(p, (void **)&q, + HKDF_MAXBUF - ctx->info_len, + &sz)) + return 0; + ctx->info_len += sz; + } + } + return 1; +} + +static const OSSL_PARAM *kdf_hkdf_settable_ctx_params(void) +{ + static const OSSL_PARAM known_settable_ctx_params[] = { + OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_MODE, NULL, 0), + OSSL_PARAM_int(OSSL_KDF_PARAM_MODE, NULL), + OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES, NULL, 0), + OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_DIGEST, NULL, 0), + OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SALT, NULL, 0), + OSSL_PARAM_octet_string(OSSL_KDF_PARAM_KEY, NULL, 0), + OSSL_PARAM_octet_string(OSSL_KDF_PARAM_INFO, NULL, 0), + OSSL_PARAM_END + }; + return known_settable_ctx_params; +} + +static int kdf_hkdf_get_ctx_params(void *vctx, OSSL_PARAM params[]) +{ + KDF_HKDF *ctx = (KDF_HKDF *)vctx; + OSSL_PARAM *p; + + if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE)) != NULL) + return OSSL_PARAM_set_size_t(p, kdf_hkdf_size(ctx)); + return -2; +} + +static const OSSL_PARAM *kdf_hkdf_gettable_ctx_params(void) +{ + static const OSSL_PARAM known_gettable_ctx_params[] = { + OSSL_PARAM_size_t(OSSL_KDF_PARAM_SIZE, NULL), + OSSL_PARAM_END + }; + return known_gettable_ctx_params; +} + +const OSSL_DISPATCH kdf_hkdf_functions[] = { + { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))kdf_hkdf_new }, + { OSSL_FUNC_KDF_FREECTX, (void(*)(void))kdf_hkdf_free }, + { OSSL_FUNC_KDF_RESET, (void(*)(void))kdf_hkdf_reset }, + { OSSL_FUNC_KDF_DERIVE, (void(*)(void))kdf_hkdf_derive }, + { OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS, + (void(*)(void))kdf_hkdf_settable_ctx_params }, + { OSSL_FUNC_KDF_SET_CTX_PARAMS, (void(*)(void))kdf_hkdf_set_ctx_params }, + { OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS, + (void(*)(void))kdf_hkdf_gettable_ctx_params }, + { OSSL_FUNC_KDF_GET_CTX_PARAMS, (void(*)(void))kdf_hkdf_get_ctx_params }, + { 0, NULL } +}; + +/* + * Refer to "HMAC-based Extract-and-Expand Key Derivation Function (HKDF)" + * Section 2 (https://tools.ietf.org/html/rfc5869#section-2) and + * "Cryptographic Extraction and Key Derivation: The HKDF Scheme" + * Section 4.2 (https://eprint.iacr.org/2010/264.pdf). + * + * From the paper: + * The scheme HKDF is specified as: + * HKDF(XTS, SKM, CTXinfo, L) = K(1) | K(2) | ... | K(t) + * + * where: + * SKM is source key material + * XTS is extractor salt (which may be null or constant) + * CTXinfo is context information (may be null) + * L is the number of key bits to be produced by KDF + * k is the output length in bits of the hash function used with HMAC + * t = ceil(L/k) + * the value K(t) is truncated to its first d = L mod k bits. + * + * From RFC 5869: + * 2.2. Step 1: Extract + * HKDF-Extract(salt, IKM) -> PRK + * 2.3. Step 2: Expand + * HKDF-Expand(PRK, info, L) -> OKM + */ +static int HKDF(const EVP_MD *evp_md, + const unsigned char *salt, size_t salt_len, + const unsigned char *ikm, size_t ikm_len, + const unsigned char *info, size_t info_len, + unsigned char *okm, size_t okm_len) +{ + unsigned char prk[EVP_MAX_MD_SIZE]; + int ret, sz; + size_t prk_len; + + sz = EVP_MD_size(evp_md); + if (sz < 0) + return 0; + prk_len = (size_t)sz; + + /* Step 1: HKDF-Extract(salt, IKM) -> PRK */ + if (!HKDF_Extract(evp_md, salt, salt_len, ikm, ikm_len, prk, prk_len)) + return 0; + + /* Step 2: HKDF-Expand(PRK, info, L) -> OKM */ + ret = HKDF_Expand(evp_md, prk, prk_len, info, info_len, okm, okm_len); + OPENSSL_cleanse(prk, sizeof(prk)); + + return ret; +} + +/* + * Refer to "HMAC-based Extract-and-Expand Key Derivation Function (HKDF)" + * Section 2.2 (https://tools.ietf.org/html/rfc5869#section-2.2). + * + * 2.2. Step 1: Extract + * + * HKDF-Extract(salt, IKM) -> PRK + * + * Options: + * Hash a hash function; HashLen denotes the length of the + * hash function output in octets + * + * Inputs: + * salt optional salt value (a non-secret random value); + * if not provided, it is set to a string of HashLen zeros. + * IKM input keying material + * + * Output: + * PRK a pseudorandom key (of HashLen octets) + * + * The output PRK is calculated as follows: + * + * PRK = HMAC-Hash(salt, IKM) + */ +static int HKDF_Extract(const EVP_MD *evp_md, + const unsigned char *salt, size_t salt_len, + const unsigned char *ikm, size_t ikm_len, + unsigned char *prk, size_t prk_len) +{ + int sz = EVP_MD_size(evp_md); + + if (sz < 0) + return 0; + if (prk_len != (size_t)sz) { + ERR_raise(ERR_LIB_PROV, PROV_R_WRONG_OUTPUT_BUFFER_SIZE); + return 0; + } + /* calc: PRK = HMAC-Hash(salt, IKM) */ + return HMAC(evp_md, salt, salt_len, ikm, ikm_len, prk, NULL) != NULL; +} + +/* + * Refer to "HMAC-based Extract-and-Expand Key Derivation Function (HKDF)" + * Section 2.3 (https://tools.ietf.org/html/rfc5869#section-2.3). + * + * 2.3. Step 2: Expand + * + * HKDF-Expand(PRK, info, L) -> OKM + * + * Options: + * Hash a hash function; HashLen denotes the length of the + * hash function output in octets + * + * Inputs: + * PRK a pseudorandom key of at least HashLen octets + * (usually, the output from the extract step) + * info optional context and application specific information + * (can be a zero-length string) + * L length of output keying material in octets + * (<= 255*HashLen) + * + * Output: + * OKM output keying material (of L octets) + * + * The output OKM is calculated as follows: + * + * N = ceil(L/HashLen) + * T = T(1) | T(2) | T(3) | ... | T(N) + * OKM = first L octets of T + * + * where: + * T(0) = empty string (zero length) + * T(1) = HMAC-Hash(PRK, T(0) | info | 0x01) + * T(2) = HMAC-Hash(PRK, T(1) | info | 0x02) + * T(3) = HMAC-Hash(PRK, T(2) | info | 0x03) + * ... + * + * (where the constant concatenated to the end of each T(n) is a + * single octet.) + */ +static int HKDF_Expand(const EVP_MD *evp_md, + const unsigned char *prk, size_t prk_len, + const unsigned char *info, size_t info_len, + unsigned char *okm, size_t okm_len) +{ + HMAC_CTX *hmac; + int ret = 0, sz; + unsigned int i; + unsigned char prev[EVP_MAX_MD_SIZE]; + size_t done_len = 0, dig_len, n; + + sz = EVP_MD_size(evp_md); + if (sz <= 0) + return 0; + dig_len = (size_t)sz; + + /* calc: N = ceil(L/HashLen) */ + n = okm_len / dig_len; + if (okm_len % dig_len) + n++; + + if (n > 255 || okm == NULL) + return 0; + + if ((hmac = HMAC_CTX_new()) == NULL) + return 0; + + if (!HMAC_Init_ex(hmac, prk, prk_len, evp_md, NULL)) + goto err; + + for (i = 1; i <= n; i++) { + size_t copy_len; + const unsigned char ctr = i; + + /* calc: T(i) = HMAC-Hash(PRK, T(i - 1) | info | i) */ + if (i > 1) { + if (!HMAC_Init_ex(hmac, NULL, 0, NULL, NULL)) + goto err; + + if (!HMAC_Update(hmac, prev, dig_len)) + goto err; + } + + if (!HMAC_Update(hmac, info, info_len)) + goto err; + + if (!HMAC_Update(hmac, &ctr, 1)) + goto err; + + if (!HMAC_Final(hmac, prev, NULL)) + goto err; + + copy_len = (done_len + dig_len > okm_len) ? + okm_len - done_len : + dig_len; + + memcpy(okm + done_len, prev, copy_len); + + done_len += copy_len; + } + ret = 1; + + err: + OPENSSL_cleanse(prev, sizeof(prev)); + HMAC_CTX_free(hmac); + return ret; +} diff --git a/providers/implementations/kdfs/kbkdf.c b/providers/implementations/kdfs/kbkdf.c new file mode 100644 index 0000000000..ffffef0b17 --- /dev/null +++ b/providers/implementations/kdfs/kbkdf.c @@ -0,0 +1,303 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2019 Red Hat, Inc. + * + * 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 + */ + +/* + * This implements https://csrc.nist.gov/publications/detail/sp/800-108/final + * section 5.1 ("counter mode") in HMAC only. That document does not name the + * KDFs it defines; the name is derived from + * https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/Key-Derivation + * + * Note that sections 5.2 ("feedback mode") and 5.3 ("double-pipeline mode") + * are not implemented, though it would be possible to do so in the future. + * CMAC mode is also not implemented; some plumbing would be required. + * + * These versions all assume the counter is used. It would be relatively + * straightforward to expose a configuration handle should the need arise. + * + * Variable names attempt to match those of SP800-108. + */ + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "internal/cryptlib.h" +#include "crypto/evp.h" +#include "internal/numbers.h" +#include "internal/provider_algs.h" +#include "internal/provider_ctx.h" +#include "internal/provider_util.h" +#include "internal/providercommonerr.h" + +#include "e_os.h" + +#define MIN(a, b) ((a) < (b)) ? (a) : (b) + +/* Our context structure. */ +typedef struct { + void *provctx; + EVP_MAC_CTX *ctx_init; + + /* Names are lowercased versions of those found in SP800-108. */ + unsigned char *ki; + size_t ki_len; + unsigned char *label; + size_t label_len; + unsigned char *context; + size_t context_len; +} KBKDF; + +/* Definitions needed for typechecking. */ +static OSSL_OP_kdf_newctx_fn kbkdf_new; +static OSSL_OP_kdf_freectx_fn kbkdf_free; +static OSSL_OP_kdf_reset_fn kbkdf_reset; +static OSSL_OP_kdf_derive_fn kbkdf_derive; +static OSSL_OP_kdf_settable_ctx_params_fn kbkdf_settable_ctx_params; +static OSSL_OP_kdf_set_ctx_params_fn kbkdf_set_ctx_params; + +/* Not all platforms have htobe32(). */ +static uint32_t be32(uint32_t host) +{ + uint32_t big = 0; + const union { + long one; + char little; + } is_endian = { 1 }; + + if (!is_endian.little) + return host; + + big |= (host & 0xff000000) >> 24; + big |= (host & 0x00ff0000) >> 8; + big |= (host & 0x0000ff00) << 8; + big |= (host & 0x000000ff) << 24; + return big; +} + +static void *kbkdf_new(void *provctx) +{ + KBKDF *ctx; + + ctx = OPENSSL_zalloc(sizeof(*ctx)); + if (ctx == NULL) { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + return NULL; + } + + ctx->provctx = provctx; + return ctx; +} + +static void kbkdf_free(void *vctx) +{ + KBKDF *ctx = (KBKDF *)vctx; + + kbkdf_reset(ctx); + OPENSSL_free(ctx); +} + +static void kbkdf_reset(void *vctx) +{ + KBKDF *ctx = (KBKDF *)vctx; + + EVP_MAC_CTX_free(ctx->ctx_init); + OPENSSL_clear_free(ctx->context, ctx->context_len); + OPENSSL_clear_free(ctx->label, ctx->label_len); + OPENSSL_clear_free(ctx->ki, ctx->ki_len); + memset(ctx, 0, sizeof(*ctx)); +} + +/* SP800-108 section 5.1. */ +static int kbkdf_derive_counter(EVP_MAC_CTX *ctx_init, + unsigned char *label, size_t label_len, + unsigned char *context, size_t context_len, + unsigned char *k_i, size_t h, uint32_t l, + unsigned char *ko, size_t ko_len) +{ + int ret = 0; + EVP_MAC_CTX *ctx = NULL; + size_t written = 0, to_write; + const unsigned char zero = 0; + uint32_t counter, i; + + for (counter = 1; written < ko_len; counter++) { + i = be32(counter); + + ctx = EVP_MAC_CTX_dup(ctx_init); + if (ctx == NULL) + goto done; + + if (!EVP_MAC_update(ctx, (unsigned char *)&i, 4) + || !EVP_MAC_update(ctx, label, label_len) + || !EVP_MAC_update(ctx, &zero, 1) + || !EVP_MAC_update(ctx, context, context_len) + || !EVP_MAC_update(ctx, (unsigned char *)&l, 4) + || !EVP_MAC_final(ctx, k_i, NULL, h)) + goto done; + + to_write = ko_len - written; + memcpy(ko + written, k_i, MIN(to_write, h)); + written += h; + + EVP_MAC_CTX_free(ctx); + ctx = NULL; + } + + ret = 1; +done: + EVP_MAC_CTX_free(ctx); + return ret; +} + +static int kbkdf_derive(void *vctx, unsigned char *key, size_t keylen) +{ + KBKDF *ctx = (KBKDF *)vctx; + int ret = 0; + unsigned char *k_i = NULL; + uint32_t l = be32(keylen * 8); + size_t h = 0; + + /* Label and Context are permitted to be empty. Check everything else. */ + if (ctx->ctx_init == NULL) { + if (ctx->ki_len == 0 || ctx->ki == NULL) { + ERR_raise(ERR_LIB_PROV, PROV_R_NO_KEY_SET); + return 0; + } + /* Could either be missing MAC or missing message digest - + * arbitrarily, I pick this one. */ + ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MAC); + return 0; + } + + h = EVP_MAC_size(ctx->ctx_init); + if (h == 0) + goto done; + + k_i = OPENSSL_zalloc(h); + if (k_i == NULL) + goto done; + + ret = kbkdf_derive_counter( + ctx->ctx_init, ctx->label, ctx->label_len, ctx->context, + ctx->context_len, k_i, h, l, key, keylen); +done: + if (ret != 1) + OPENSSL_cleanse(key, keylen); + OPENSSL_clear_free(k_i, h); + return ret; +} + +static int kbkdf_set_buffer(unsigned char **out, size_t *out_len, + const OSSL_PARAM *p) +{ + if (p->data == NULL || p->data_size == 0) + return 1; + + OPENSSL_clear_free(*out, *out_len); + *out = NULL; + return OSSL_PARAM_get_octet_string(p, (void **)out, 0, out_len); +} + +static int kbkdf_set_ctx_params(void *vctx, const OSSL_PARAM params[]) +{ + KBKDF *ctx = (KBKDF *)vctx; + OPENSSL_CTX *libctx = PROV_LIBRARY_CONTEXT_OF(ctx->provctx); + const OSSL_PARAM *p; + OSSL_PARAM mparams[2]; + + if (!ossl_prov_macctx_load_from_params(&ctx->ctx_init, params, NULL, + NULL, NULL, libctx)) + return 0; + else if (ctx->ctx_init != NULL + && !EVP_MAC_is_a(EVP_MAC_CTX_mac(ctx->ctx_init), + OSSL_MAC_NAME_HMAC)) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_MAC); + return 0; + } + + p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_KEY); + if (p != NULL && !kbkdf_set_buffer(&ctx->ki, &ctx->ki_len, p)) + return 0; + + p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SALT); + if (p != NULL && !kbkdf_set_buffer(&ctx->label, &ctx->label_len, p)) + return 0; + + p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_INFO); + if (p != NULL && !kbkdf_set_buffer(&ctx->context, &ctx->context_len, p)) + return 0; + + /* Set up digest context, if we can. */ + if (ctx->ctx_init != NULL && ctx->ki_len != 0) { + mparams[0] = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY, + ctx->ki, ctx->ki_len); + mparams[1] = OSSL_PARAM_construct_end(); + + if (!EVP_MAC_CTX_set_params(ctx->ctx_init, mparams) + || !EVP_MAC_init(ctx->ctx_init)) + return 0; + } + + return 1; +} + +static const OSSL_PARAM *kbkdf_settable_ctx_params(void) +{ + static const OSSL_PARAM known_settable_ctx_params[] = { + OSSL_PARAM_octet_string(OSSL_KDF_PARAM_INFO, NULL, 0), + OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SALT, NULL, 0), + OSSL_PARAM_octet_string(OSSL_KDF_PARAM_KEY, NULL, 0), + OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_DIGEST, NULL, 0), + OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_MAC, NULL, 0), + + OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES, NULL, 0), + OSSL_PARAM_END, + }; + return known_settable_ctx_params; +} + +static int kbkdf_get_ctx_params(void *vctx, OSSL_PARAM params[]) +{ + OSSL_PARAM *p; + + p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE); + if (p == NULL) + return -2; + + /* KBKDF can produce results as large as you like. */ + return OSSL_PARAM_set_size_t(p, SIZE_MAX); +} + +static const OSSL_PARAM *kbkdf_gettable_ctx_params(void) +{ + static const OSSL_PARAM known_gettable_ctx_params[] = + { OSSL_PARAM_size_t(OSSL_KDF_PARAM_SIZE, NULL), OSSL_PARAM_END }; + return known_gettable_ctx_params; +} + +const OSSL_DISPATCH kdf_kbkdf_functions[] = { + { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))kbkdf_new }, + { OSSL_FUNC_KDF_FREECTX, (void(*)(void))kbkdf_free }, + { OSSL_FUNC_KDF_RESET, (void(*)(void))kbkdf_reset }, + { OSSL_FUNC_KDF_DERIVE, (void(*)(void))kbkdf_derive }, + { OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS, + (void(*)(void))kbkdf_settable_ctx_params }, + { OSSL_FUNC_KDF_SET_CTX_PARAMS, (void(*)(void))kbkdf_set_ctx_params }, + { OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS, + (void(*)(void))kbkdf_gettable_ctx_params }, + { OSSL_FUNC_KDF_GET_CTX_PARAMS, (void(*)(void))kbkdf_get_ctx_params }, + { 0, NULL }, +}; diff --git a/providers/implementations/kdfs/pbkdf2.c b/providers/implementations/kdfs/pbkdf2.c new file mode 100644 index 0000000000..68aa0aa7c4 --- /dev/null +++ b/providers/implementations/kdfs/pbkdf2.c @@ -0,0 +1,336 @@ +/* + * Copyright 2018-2019 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 + */ + +#include +#include +#include +#include +#include +#include +#include +#include "internal/cryptlib.h" +#include "internal/numbers.h" +#include "crypto/evp.h" +#include "internal/provider_ctx.h" +#include "internal/providercommonerr.h" +#include "internal/provider_algs.h" +#include "internal/provider_util.h" +#include "pbkdf2.h" + +/* Constants specified in SP800-132 */ +#define KDF_PBKDF2_MIN_KEY_LEN_BITS 112 +#define KDF_PBKDF2_MAX_KEY_LEN_DIGEST_RATIO 0xFFFFFFFF +#define KDF_PBKDF2_MIN_ITERATIONS 1000 +#define KDF_PBKDF2_MIN_SALT_LEN (128 / 8) + +static OSSL_OP_kdf_newctx_fn kdf_pbkdf2_new; +static OSSL_OP_kdf_freectx_fn kdf_pbkdf2_free; +static OSSL_OP_kdf_reset_fn kdf_pbkdf2_reset; +static OSSL_OP_kdf_derive_fn kdf_pbkdf2_derive; +static OSSL_OP_kdf_settable_ctx_params_fn kdf_pbkdf2_settable_ctx_params; +static OSSL_OP_kdf_set_ctx_params_fn kdf_pbkdf2_set_ctx_params; + +static int pbkdf2_derive(const char *pass, size_t passlen, + const unsigned char *salt, int saltlen, uint64_t iter, + const EVP_MD *digest, unsigned char *key, + size_t keylen, int extra_checks); + +typedef struct { + void *provctx; + unsigned char *pass; + size_t pass_len; + unsigned char *salt; + size_t salt_len; + uint64_t iter; + PROV_DIGEST digest; + int lower_bound_checks; +} KDF_PBKDF2; + +static void kdf_pbkdf2_init(KDF_PBKDF2 *ctx); + +static void *kdf_pbkdf2_new(void *provctx) +{ + KDF_PBKDF2 *ctx; + + ctx = OPENSSL_zalloc(sizeof(*ctx)); + if (ctx == NULL) { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + return NULL; + } + ctx->provctx = provctx; + kdf_pbkdf2_init(ctx); + return ctx; +} + +static void kdf_pbkdf2_cleanup(KDF_PBKDF2 *ctx) +{ + ossl_prov_digest_reset(&ctx->digest); + OPENSSL_free(ctx->salt); + OPENSSL_clear_free(ctx->pass, ctx->pass_len); + memset(ctx, 0, sizeof(*ctx)); +} + +static void kdf_pbkdf2_free(void *vctx) +{ + KDF_PBKDF2 *ctx = (KDF_PBKDF2 *)vctx; + + kdf_pbkdf2_cleanup(ctx); + OPENSSL_free(ctx); +} + +static void kdf_pbkdf2_reset(void *vctx) +{ + KDF_PBKDF2 *ctx = (KDF_PBKDF2 *)vctx; + + kdf_pbkdf2_cleanup(ctx); + kdf_pbkdf2_init(ctx); +} + +static void kdf_pbkdf2_init(KDF_PBKDF2 *ctx) +{ + OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END }; + OPENSSL_CTX *provctx = PROV_LIBRARY_CONTEXT_OF(ctx->provctx); + + params[0] = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST, + SN_sha1, 0); + if (!ossl_prov_digest_load_from_params(&ctx->digest, params, provctx)) + /* This is an error, but there is no way to indicate such directly */ + ossl_prov_digest_reset(&ctx->digest); + ctx->iter = PKCS5_DEFAULT_ITER; + ctx->lower_bound_checks = kdf_pbkdf2_default_checks; +} + +static int pbkdf2_set_membuf(unsigned char **buffer, size_t *buflen, + const OSSL_PARAM *p) +{ + OPENSSL_clear_free(*buffer, *buflen); + if (p->data_size == 0) { + if ((*buffer = OPENSSL_malloc(1)) == NULL) { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + return 0; + } + } else if (p->data != NULL) { + *buffer = NULL; + if (!OSSL_PARAM_get_octet_string(p, (void **)buffer, 0, buflen)) + return 0; + } + return 1; +} + +static int kdf_pbkdf2_derive(void *vctx, unsigned char *key, + size_t keylen) +{ + KDF_PBKDF2 *ctx = (KDF_PBKDF2 *)vctx; + const EVP_MD *md = ossl_prov_digest_md(&ctx->digest); + + if (ctx->pass == NULL) { + ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_PASS); + return 0; + } + + if (ctx->salt == NULL) { + ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_SALT); + return 0; + } + + return pbkdf2_derive((char *)ctx->pass, ctx->pass_len, + ctx->salt, ctx->salt_len, ctx->iter, + md, key, keylen, ctx->lower_bound_checks); +} + +static int kdf_pbkdf2_set_ctx_params(void *vctx, const OSSL_PARAM params[]) +{ + const OSSL_PARAM *p; + KDF_PBKDF2 *ctx = vctx; + OPENSSL_CTX *provctx = PROV_LIBRARY_CONTEXT_OF(ctx->provctx); + int pkcs5; + uint64_t iter, min_iter; + + if (!ossl_prov_digest_load_from_params(&ctx->digest, params, provctx)) + return 0; + + if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PKCS5)) != NULL) { + if (!OSSL_PARAM_get_int(p, &pkcs5)) + return 0; + ctx->lower_bound_checks = pkcs5 == 0; + } + + if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PASSWORD)) != NULL) + if (!pbkdf2_set_membuf(&ctx->pass, &ctx->pass_len, p)) + return 0; + + if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SALT)) != NULL) { + if (ctx->lower_bound_checks != 0 + && p->data_size < KDF_PBKDF2_MIN_SALT_LEN) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_SALT_LENGTH); + return 0; + } + if (!pbkdf2_set_membuf(&ctx->salt, &ctx->salt_len,p)) + return 0; + } + + if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_ITER)) != NULL) { + if (!OSSL_PARAM_get_uint64(p, &iter)) + return 0; + min_iter = ctx->lower_bound_checks != 0 ? KDF_PBKDF2_MIN_ITERATIONS : 1; + if (iter < min_iter) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_ITERATION_COUNT); + return 0; + } + ctx->iter = iter; + } + return 1; +} + +static const OSSL_PARAM *kdf_pbkdf2_settable_ctx_params(void) +{ + static const OSSL_PARAM known_settable_ctx_params[] = { + OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES, NULL, 0), + OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_DIGEST, NULL, 0), + OSSL_PARAM_octet_string(OSSL_KDF_PARAM_PASSWORD, NULL, 0), + OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SALT, NULL, 0), + OSSL_PARAM_uint64(OSSL_KDF_PARAM_ITER, NULL), + OSSL_PARAM_int(OSSL_KDF_PARAM_PKCS5, NULL), + OSSL_PARAM_END + }; + return known_settable_ctx_params; +} + +static int kdf_pbkdf2_get_ctx_params(void *vctx, OSSL_PARAM params[]) +{ + OSSL_PARAM *p; + + if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE)) != NULL) + return OSSL_PARAM_set_size_t(p, SIZE_MAX); + return -2; +} + +static const OSSL_PARAM *kdf_pbkdf2_gettable_ctx_params(void) +{ + static const OSSL_PARAM known_gettable_ctx_params[] = { + OSSL_PARAM_size_t(OSSL_KDF_PARAM_SIZE, NULL), + OSSL_PARAM_END + }; + return known_gettable_ctx_params; +} + +const OSSL_DISPATCH kdf_pbkdf2_functions[] = { + { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))kdf_pbkdf2_new }, + { OSSL_FUNC_KDF_FREECTX, (void(*)(void))kdf_pbkdf2_free }, + { OSSL_FUNC_KDF_RESET, (void(*)(void))kdf_pbkdf2_reset }, + { OSSL_FUNC_KDF_DERIVE, (void(*)(void))kdf_pbkdf2_derive }, + { OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS, + (void(*)(void))kdf_pbkdf2_settable_ctx_params }, + { OSSL_FUNC_KDF_SET_CTX_PARAMS, (void(*)(void))kdf_pbkdf2_set_ctx_params }, + { OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS, + (void(*)(void))kdf_pbkdf2_gettable_ctx_params }, + { OSSL_FUNC_KDF_GET_CTX_PARAMS, (void(*)(void))kdf_pbkdf2_get_ctx_params }, + { 0, NULL } +}; + +/* + * This is an implementation of PKCS#5 v2.0 password based encryption key + * derivation function PBKDF2. SHA1 version verified against test vectors + * posted by Peter Gutmann to the PKCS-TNG mailing list. + * + * The constraints specified by SP800-132 have been added i.e. + * - Check the range of the key length. + * - Minimum iteration count of 1000. + * - Randomly-generated portion of the salt shall be at least 128 bits. + */ +static int pbkdf2_derive(const char *pass, size_t passlen, + const unsigned char *salt, int saltlen, uint64_t iter, + const EVP_MD *digest, unsigned char *key, + size_t keylen, int lower_bound_checks) +{ + int ret = 0; + unsigned char digtmp[EVP_MAX_MD_SIZE], *p, itmp[4]; + int cplen, k, tkeylen, mdlen; + uint64_t j; + unsigned long i = 1; + HMAC_CTX *hctx_tpl = NULL, *hctx = NULL; + + mdlen = EVP_MD_size(digest); + if (mdlen <= 0) + return 0; + + /* + * This check should always be done because keylen / mdlen >= (2^32 - 1) + * results in an overflow of the loop counter 'i'. + */ + if ((keylen / mdlen) >= KDF_PBKDF2_MAX_KEY_LEN_DIGEST_RATIO) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LEN); + return 0; + } + + if (lower_bound_checks) { + if ((keylen * 8) < KDF_PBKDF2_MIN_KEY_LEN_BITS) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LEN); + return 0; + } + if (saltlen < KDF_PBKDF2_MIN_SALT_LEN) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_SALT_LENGTH); + return 0; + } + if (iter < KDF_PBKDF2_MIN_ITERATIONS) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_ITERATION_COUNT); + return 0; + } + } + + hctx_tpl = HMAC_CTX_new(); + if (hctx_tpl == NULL) + return 0; + p = key; + tkeylen = keylen; + if (!HMAC_Init_ex(hctx_tpl, pass, passlen, digest, NULL)) + goto err; + hctx = HMAC_CTX_new(); + if (hctx == NULL) + goto err; + while (tkeylen) { + if (tkeylen > mdlen) + cplen = mdlen; + else + cplen = tkeylen; + /* + * We are unlikely to ever use more than 256 blocks (5120 bits!) but + * just in case... + */ + itmp[0] = (unsigned char)((i >> 24) & 0xff); + itmp[1] = (unsigned char)((i >> 16) & 0xff); + itmp[2] = (unsigned char)((i >> 8) & 0xff); + itmp[3] = (unsigned char)(i & 0xff); + if (!HMAC_CTX_copy(hctx, hctx_tpl)) + goto err; + if (!HMAC_Update(hctx, salt, saltlen) + || !HMAC_Update(hctx, itmp, 4) + || !HMAC_Final(hctx, digtmp, NULL)) + goto err; + memcpy(p, digtmp, cplen); + for (j = 1; j < iter; j++) { + if (!HMAC_CTX_copy(hctx, hctx_tpl)) + goto err; + if (!HMAC_Update(hctx, digtmp, mdlen) + || !HMAC_Final(hctx, digtmp, NULL)) + goto err; + for (k = 0; k < cplen; k++) + p[k] ^= digtmp[k]; + } + tkeylen -= cplen; + i++; + p += cplen; + } + ret = 1; + +err: + HMAC_CTX_free(hctx); + HMAC_CTX_free(hctx_tpl); + return ret; +} diff --git a/providers/implementations/kdfs/pbkdf2.h b/providers/implementations/kdfs/pbkdf2.h new file mode 100644 index 0000000000..c8c2e5b8a7 --- /dev/null +++ b/providers/implementations/kdfs/pbkdf2.h @@ -0,0 +1,14 @@ +/* + * Copyright 2019 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 + */ + +/* + * Available in pbkdfe_fips.c, and compiled with different values depending + * on we're in the FIPS module or not. + */ +extern const int kdf_pbkdf2_default_checks; diff --git a/providers/implementations/kdfs/pbkdf2_fips.c b/providers/implementations/kdfs/pbkdf2_fips.c new file mode 100644 index 0000000000..d33782b24c --- /dev/null +++ b/providers/implementations/kdfs/pbkdf2_fips.c @@ -0,0 +1,20 @@ +/* + * Copyright 2019 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 + */ + +#include "pbkdf2.h" + +/* + * For backwards compatibility reasons, + * Extra checks are done by default in fips mode only. + */ +#ifdef FIPS_MODE +const int kdf_pbkdf2_default_checks = 1; +#else +const int kdf_pbkdf2_default_checks = 0; +#endif /* FIPS_MODE */ diff --git a/providers/implementations/kdfs/sskdf.c b/providers/implementations/kdfs/sskdf.c new file mode 100644 index 0000000000..1e538a9c0a --- /dev/null +++ b/providers/implementations/kdfs/sskdf.c @@ -0,0 +1,538 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2019, Oracle and/or its affiliates. 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 + */ + +/* + * Refer to https://csrc.nist.gov/publications/detail/sp/800-56c/rev-1/final + * Section 4.1. + * + * The Single Step KDF algorithm is given by: + * + * Result(0) = empty bit string (i.e., the null string). + * For i = 1 to reps, do the following: + * Increment counter by 1. + * Result(i) = Result(i - 1) || H(counter || Z || FixedInfo). + * DKM = LeftmostBits(Result(reps), L)) + * + * NOTES: + * Z is a shared secret required to produce the derived key material. + * counter is a 4 byte buffer. + * FixedInfo is a bit string containing context specific data. + * DKM is the output derived key material. + * L is the required size of the DKM. + * reps = [L / H_outputBits] + * H(x) is the auxiliary function that can be either a hash, HMAC or KMAC. + * H_outputBits is the length of the output of the auxiliary function H(x). + * + * Currently there is not a comprehensive list of test vectors for this + * algorithm, especially for H(x) = HMAC and H(x) = KMAC. + * Test vectors for H(x) = Hash are indirectly used by CAVS KAS tests. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include "internal/cryptlib.h" +#include "internal/numbers.h" +#include "crypto/evp.h" +#include "internal/provider_ctx.h" +#include "internal/providercommonerr.h" +#include "internal/provider_algs.h" +#include "internal/provider_util.h" + +typedef struct { + void *provctx; + EVP_MAC_CTX *macctx; /* H(x) = HMAC_hash OR H(x) = KMAC */ + PROV_DIGEST digest; /* H(x) = hash(x) */ + unsigned char *secret; + size_t secret_len; + unsigned char *info; + size_t info_len; + unsigned char *salt; + size_t salt_len; + size_t out_len; /* optional KMAC parameter */ +} KDF_SSKDF; + +#define SSKDF_MAX_INLEN (1<<30) +#define SSKDF_KMAC128_DEFAULT_SALT_SIZE (168 - 4) +#define SSKDF_KMAC256_DEFAULT_SALT_SIZE (136 - 4) + +/* KMAC uses a Customisation string of 'KDF' */ +static const unsigned char kmac_custom_str[] = { 0x4B, 0x44, 0x46 }; + +static OSSL_OP_kdf_newctx_fn sskdf_new; +static OSSL_OP_kdf_freectx_fn sskdf_free; +static OSSL_OP_kdf_reset_fn sskdf_reset; +static OSSL_OP_kdf_derive_fn sskdf_derive; +static OSSL_OP_kdf_derive_fn x963kdf_derive; +static OSSL_OP_kdf_settable_ctx_params_fn sskdf_settable_ctx_params; +static OSSL_OP_kdf_set_ctx_params_fn sskdf_set_ctx_params; +static OSSL_OP_kdf_gettable_ctx_params_fn sskdf_gettable_ctx_params; +static OSSL_OP_kdf_get_ctx_params_fn sskdf_get_ctx_params; + +/* + * Refer to https://csrc.nist.gov/publications/detail/sp/800-56c/rev-1/final + * Section 4. One-Step Key Derivation using H(x) = hash(x) + * Note: X9.63 also uses this code with the only difference being that the + * counter is appended to the secret 'z'. + * i.e. + * result[i] = Hash(counter || z || info) for One Step OR + * result[i] = Hash(z || counter || info) for X9.63. + */ +static int SSKDF_hash_kdm(const EVP_MD *kdf_md, + const unsigned char *z, size_t z_len, + const unsigned char *info, size_t info_len, + unsigned int append_ctr, + unsigned char *derived_key, size_t derived_key_len) +{ + int ret = 0, hlen; + size_t counter, out_len, len = derived_key_len; + unsigned char c[4]; + unsigned char mac[EVP_MAX_MD_SIZE]; + unsigned char *out = derived_key; + EVP_MD_CTX *ctx = NULL, *ctx_init = NULL; + + if (z_len > SSKDF_MAX_INLEN || info_len > SSKDF_MAX_INLEN + || derived_key_len > SSKDF_MAX_INLEN + || derived_key_len == 0) + return 0; + + hlen = EVP_MD_size(kdf_md); + if (hlen <= 0) + return 0; + out_len = (size_t)hlen; + + ctx = EVP_MD_CTX_create(); + ctx_init = EVP_MD_CTX_create(); + if (ctx == NULL || ctx_init == NULL) + goto end; + + if (!EVP_DigestInit(ctx_init, kdf_md)) + goto end; + + for (counter = 1;; counter++) { + c[0] = (unsigned char)((counter >> 24) & 0xff); + c[1] = (unsigned char)((counter >> 16) & 0xff); + c[2] = (unsigned char)((counter >> 8) & 0xff); + c[3] = (unsigned char)(counter & 0xff); + + if (!(EVP_MD_CTX_copy_ex(ctx, ctx_init) + && (append_ctr || EVP_DigestUpdate(ctx, c, sizeof(c))) + && EVP_DigestUpdate(ctx, z, z_len) + && (!append_ctr || EVP_DigestUpdate(ctx, c, sizeof(c))) + && EVP_DigestUpdate(ctx, info, info_len))) + goto end; + if (len >= out_len) { + if (!EVP_DigestFinal_ex(ctx, out, NULL)) + goto end; + out += out_len; + len -= out_len; + if (len == 0) + break; + } else { + if (!EVP_DigestFinal_ex(ctx, mac, NULL)) + goto end; + memcpy(out, mac, len); + break; + } + } + ret = 1; +end: + EVP_MD_CTX_destroy(ctx); + EVP_MD_CTX_destroy(ctx_init); + OPENSSL_cleanse(mac, sizeof(mac)); + return ret; +} + +static int kmac_init(EVP_MAC_CTX *ctx, const unsigned char *custom, + size_t custom_len, size_t kmac_out_len, + size_t derived_key_len, unsigned char **out) +{ + OSSL_PARAM params[2]; + + /* Only KMAC has custom data - so return if not KMAC */ + if (custom == NULL) + return 1; + + params[0] = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_CUSTOM, + (void *)custom, custom_len); + params[1] = OSSL_PARAM_construct_end(); + + if (!EVP_MAC_CTX_set_params(ctx, params)) + return 0; + + /* By default only do one iteration if kmac_out_len is not specified */ + if (kmac_out_len == 0) + kmac_out_len = derived_key_len; + /* otherwise check the size is valid */ + else if (!(kmac_out_len == derived_key_len + || kmac_out_len == 20 + || kmac_out_len == 28 + || kmac_out_len == 32 + || kmac_out_len == 48 + || kmac_out_len == 64)) + return 0; + + params[0] = OSSL_PARAM_construct_size_t(OSSL_MAC_PARAM_SIZE, + &kmac_out_len); + + if (EVP_MAC_CTX_set_params(ctx, params) <= 0) + return 0; + + /* + * For kmac the output buffer can be larger than EVP_MAX_MD_SIZE: so + * alloc a buffer for this case. + */ + if (kmac_out_len > EVP_MAX_MD_SIZE) { + *out = OPENSSL_zalloc(kmac_out_len); + if (*out == NULL) + return 0; + } + return 1; +} + +/* + * Refer to https://csrc.nist.gov/publications/detail/sp/800-56c/rev-1/final + * Section 4. One-Step Key Derivation using MAC: i.e either + * H(x) = HMAC-hash(salt, x) OR + * H(x) = KMAC#(salt, x, outbits, CustomString='KDF') + */ +static int SSKDF_mac_kdm(EVP_MAC_CTX *ctx_init, + const unsigned char *kmac_custom, + size_t kmac_custom_len, size_t kmac_out_len, + const unsigned char *salt, size_t salt_len, + const unsigned char *z, size_t z_len, + const unsigned char *info, size_t info_len, + unsigned char *derived_key, size_t derived_key_len) +{ + int ret = 0; + size_t counter, out_len, len; + unsigned char c[4]; + unsigned char mac_buf[EVP_MAX_MD_SIZE]; + unsigned char *out = derived_key; + EVP_MAC_CTX *ctx = NULL; + unsigned char *mac = mac_buf, *kmac_buffer = NULL; + OSSL_PARAM params[2], *p = params; + + if (z_len > SSKDF_MAX_INLEN || info_len > SSKDF_MAX_INLEN + || derived_key_len > SSKDF_MAX_INLEN + || derived_key_len == 0) + return 0; + + *p++ = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY, + (void *)salt, salt_len); + *p = OSSL_PARAM_construct_end(); + + if (!EVP_MAC_CTX_set_params(ctx_init, params)) + goto end; + + if (!kmac_init(ctx_init, kmac_custom, kmac_custom_len, kmac_out_len, + derived_key_len, &kmac_buffer)) + goto end; + if (kmac_buffer != NULL) + mac = kmac_buffer; + + if (!EVP_MAC_init(ctx_init)) + goto end; + + out_len = EVP_MAC_size(ctx_init); /* output size */ + if (out_len <= 0) + goto end; + len = derived_key_len; + + for (counter = 1;; counter++) { + c[0] = (unsigned char)((counter >> 24) & 0xff); + c[1] = (unsigned char)((counter >> 16) & 0xff); + c[2] = (unsigned char)((counter >> 8) & 0xff); + c[3] = (unsigned char)(counter & 0xff); + + ctx = EVP_MAC_CTX_dup(ctx_init); + if (!(ctx != NULL + && EVP_MAC_update(ctx, c, sizeof(c)) + && EVP_MAC_update(ctx, z, z_len) + && EVP_MAC_update(ctx, info, info_len))) + goto end; + if (len >= out_len) { + if (!EVP_MAC_final(ctx, out, NULL, len)) + goto end; + out += out_len; + len -= out_len; + if (len == 0) + break; + } else { + if (!EVP_MAC_final(ctx, mac, NULL, len)) + goto end; + memcpy(out, mac, len); + break; + } + EVP_MAC_CTX_free(ctx); + ctx = NULL; + } + ret = 1; +end: + if (kmac_buffer != NULL) + OPENSSL_clear_free(kmac_buffer, kmac_out_len); + else + OPENSSL_cleanse(mac_buf, sizeof(mac_buf)); + + EVP_MAC_CTX_free(ctx); + return ret; +} + +static void *sskdf_new(void *provctx) +{ + KDF_SSKDF *ctx; + + if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + ctx->provctx = provctx; + return ctx; +} + +static void sskdf_reset(void *vctx) +{ + KDF_SSKDF *ctx = (KDF_SSKDF *)vctx; + + EVP_MAC_CTX_free(ctx->macctx); + ossl_prov_digest_reset(&ctx->digest); + OPENSSL_clear_free(ctx->secret, ctx->secret_len); + OPENSSL_clear_free(ctx->info, ctx->info_len); + OPENSSL_clear_free(ctx->salt, ctx->salt_len); + memset(ctx, 0, sizeof(*ctx)); +} + +static void sskdf_free(void *vctx) +{ + KDF_SSKDF *ctx = (KDF_SSKDF *)vctx; + + sskdf_reset(ctx); + OPENSSL_free(ctx); +} + +static int sskdf_set_buffer(unsigned char **out, size_t *out_len, + const OSSL_PARAM *p) +{ + if (p->data == NULL || p->data_size == 0) + return 1; + OPENSSL_free(*out); + *out = NULL; + return OSSL_PARAM_get_octet_string(p, (void **)out, 0, out_len); +} + +static size_t sskdf_size(KDF_SSKDF *ctx) +{ + int len; + const EVP_MD *md = ossl_prov_digest_md(&ctx->digest); + + if (md == NULL) { + ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST); + return 0; + } + len = EVP_MD_size(md); + return (len <= 0) ? 0 : (size_t)len; +} + +static int sskdf_derive(void *vctx, unsigned char *key, size_t keylen) +{ + KDF_SSKDF *ctx = (KDF_SSKDF *)vctx; + const EVP_MD *md = ossl_prov_digest_md(&ctx->digest); + + if (ctx->secret == NULL) { + ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_SECRET); + return 0; + } + + if (ctx->macctx != NULL) { + /* H(x) = KMAC or H(x) = HMAC */ + int ret; + const unsigned char *custom = NULL; + size_t custom_len = 0; + int default_salt_len; + EVP_MAC *mac = EVP_MAC_CTX_mac(ctx->macctx); + + /* + * TODO(3.0) investigate the necessity to have all these controls. + * Why does KMAC require a salt length that's shorter than the MD + * block size? + */ + if (EVP_MAC_is_a(mac, OSSL_MAC_NAME_HMAC)) { + /* H(x) = HMAC(x, salt, hash) */ + if (md == NULL) { + ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST); + return 0; + } + default_salt_len = EVP_MD_size(md); + if (default_salt_len <= 0) + return 0; + } else if (EVP_MAC_is_a(mac, OSSL_MAC_NAME_KMAC128) + || EVP_MAC_is_a(mac, OSSL_MAC_NAME_KMAC256)) { + /* H(x) = KMACzzz(x, salt, custom) */ + custom = kmac_custom_str; + custom_len = sizeof(kmac_custom_str); + if (EVP_MAC_is_a(mac, OSSL_MAC_NAME_KMAC128)) + default_salt_len = SSKDF_KMAC128_DEFAULT_SALT_SIZE; + else + default_salt_len = SSKDF_KMAC256_DEFAULT_SALT_SIZE; + } else { + ERR_raise(ERR_LIB_PROV, PROV_R_UNSUPPORTED_MAC_TYPE); + return 0; + } + /* If no salt is set then use a default_salt of zeros */ + if (ctx->salt == NULL || ctx->salt_len <= 0) { + ctx->salt = OPENSSL_zalloc(default_salt_len); + if (ctx->salt == NULL) { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + return 0; + } + ctx->salt_len = default_salt_len; + } + ret = SSKDF_mac_kdm(ctx->macctx, + custom, custom_len, ctx->out_len, + ctx->salt, ctx->salt_len, + ctx->secret, ctx->secret_len, + ctx->info, ctx->info_len, key, keylen); + return ret; + } else { + /* H(x) = hash */ + if (md == NULL) { + ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST); + return 0; + } + return SSKDF_hash_kdm(md, ctx->secret, ctx->secret_len, + ctx->info, ctx->info_len, 0, key, keylen); + } +} + +static int x963kdf_derive(void *vctx, unsigned char *key, size_t keylen) +{ + KDF_SSKDF *ctx = (KDF_SSKDF *)vctx; + const EVP_MD *md = ossl_prov_digest_md(&ctx->digest); + + if (ctx->secret == NULL) { + ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_SECRET); + return 0; + } + + if (ctx->macctx != NULL) { + ERR_raise(ERR_LIB_PROV, PROV_R_NOT_SUPPORTED); + return 0; + } + + /* H(x) = hash */ + if (md == NULL) { + ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST); + return 0; + } + + return SSKDF_hash_kdm(md, ctx->secret, ctx->secret_len, + ctx->info, ctx->info_len, 1, key, keylen); +} + +static int sskdf_set_ctx_params(void *vctx, const OSSL_PARAM params[]) +{ + const OSSL_PARAM *p; + KDF_SSKDF *ctx = vctx; + OPENSSL_CTX *libctx = PROV_LIBRARY_CONTEXT_OF(ctx->provctx); + size_t sz; + + if (!ossl_prov_digest_load_from_params(&ctx->digest, params, libctx)) + return 0; + + if (!ossl_prov_macctx_load_from_params(&ctx->macctx, params, + NULL, NULL, NULL, libctx)) + return 0; + + if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SECRET)) != NULL + || (p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_KEY)) != NULL) + if (!sskdf_set_buffer(&ctx->secret, &ctx->secret_len, p)) + return 0; + + if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_INFO)) != NULL) + if (!sskdf_set_buffer(&ctx->info, &ctx->info_len, p)) + return 0; + + if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SALT)) != NULL) + if (!sskdf_set_buffer(&ctx->salt, &ctx->salt_len, p)) + return 0; + + if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_MAC_SIZE)) + != NULL) { + if (!OSSL_PARAM_get_size_t(p, &sz) || sz == 0) + return 0; + ctx->out_len = sz; + } + return 1; +} + +static const OSSL_PARAM *sskdf_settable_ctx_params(void) +{ + static const OSSL_PARAM known_settable_ctx_params[] = { + OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SECRET, NULL, 0), + OSSL_PARAM_octet_string(OSSL_KDF_PARAM_KEY, NULL, 0), + OSSL_PARAM_octet_string(OSSL_KDF_PARAM_INFO, NULL, 0), + OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES, NULL, 0), + OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_DIGEST, NULL, 0), + OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_MAC, NULL, 0), + OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SALT, NULL, 0), + OSSL_PARAM_size_t(OSSL_KDF_PARAM_MAC_SIZE, NULL), + OSSL_PARAM_END + }; + return known_settable_ctx_params; +} + +static int sskdf_get_ctx_params(void *vctx, OSSL_PARAM params[]) +{ + KDF_SSKDF *ctx = (KDF_SSKDF *)vctx; + OSSL_PARAM *p; + + if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE)) != NULL) + return OSSL_PARAM_set_size_t(p, sskdf_size(ctx)); + return -2; +} + +static const OSSL_PARAM *sskdf_gettable_ctx_params(void) +{ + static const OSSL_PARAM known_gettable_ctx_params[] = { + OSSL_PARAM_size_t(OSSL_KDF_PARAM_SIZE, NULL), + OSSL_PARAM_END + }; + return known_gettable_ctx_params; +} + +const OSSL_DISPATCH kdf_sskdf_functions[] = { + { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))sskdf_new }, + { OSSL_FUNC_KDF_FREECTX, (void(*)(void))sskdf_free }, + { OSSL_FUNC_KDF_RESET, (void(*)(void))sskdf_reset }, + { OSSL_FUNC_KDF_DERIVE, (void(*)(void))sskdf_derive }, + { OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS, + (void(*)(void))sskdf_settable_ctx_params }, + { OSSL_FUNC_KDF_SET_CTX_PARAMS, (void(*)(void))sskdf_set_ctx_params }, + { OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS, + (void(*)(void))sskdf_gettable_ctx_params }, + { OSSL_FUNC_KDF_GET_CTX_PARAMS, (void(*)(void))sskdf_get_ctx_params }, + { 0, NULL } +}; + +const OSSL_DISPATCH kdf_x963_kdf_functions[] = { + { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))sskdf_new }, + { OSSL_FUNC_KDF_FREECTX, (void(*)(void))sskdf_free }, + { OSSL_FUNC_KDF_RESET, (void(*)(void))sskdf_reset }, + { OSSL_FUNC_KDF_DERIVE, (void(*)(void))x963kdf_derive }, + { OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS, + (void(*)(void))sskdf_settable_ctx_params }, + { OSSL_FUNC_KDF_SET_CTX_PARAMS, (void(*)(void))sskdf_set_ctx_params }, + { OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS, + (void(*)(void))sskdf_gettable_ctx_params }, + { OSSL_FUNC_KDF_GET_CTX_PARAMS, (void(*)(void))sskdf_get_ctx_params }, + { 0, NULL } +}; diff --git a/providers/implementations/kdfs/tls1_prf.c b/providers/implementations/kdfs/tls1_prf.c new file mode 100644 index 0000000000..af49b1b044 --- /dev/null +++ b/providers/implementations/kdfs/tls1_prf.c @@ -0,0 +1,396 @@ +/* + * Copyright 2016-2019 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 + */ + +/* + * Refer to "The TLS Protocol Version 1.0" Section 5 + * (https://tools.ietf.org/html/rfc2246#section-5) and + * "The Transport Layer Security (TLS) Protocol Version 1.2" Section 5 + * (https://tools.ietf.org/html/rfc5246#section-5). + * + * For TLS v1.0 and TLS v1.1 the TLS PRF algorithm is given by: + * + * PRF(secret, label, seed) = P_MD5(S1, label + seed) XOR + * P_SHA-1(S2, label + seed) + * + * where P_MD5 and P_SHA-1 are defined by P_, below, and S1 and S2 are + * two halves of the secret (with the possibility of one shared byte, in the + * case where the length of the original secret is odd). S1 is taken from the + * first half of the secret, S2 from the second half. + * + * For TLS v1.2 the TLS PRF algorithm is given by: + * + * PRF(secret, label, seed) = P_(secret, label + seed) + * + * where hash is SHA-256 for all cipher suites defined in RFC 5246 as well as + * those published prior to TLS v1.2 while the TLS v1.2 protocol is in effect, + * unless defined otherwise by the cipher suite. + * + * P_ is an expansion function that uses a single hash function to expand + * a secret and seed into an arbitrary quantity of output: + * + * P_(secret, seed) = HMAC_(secret, A(1) + seed) + + * HMAC_(secret, A(2) + seed) + + * HMAC_(secret, A(3) + seed) + ... + * + * where + indicates concatenation. P_ can be iterated as many times as + * is necessary to produce the required quantity of data. + * + * A(i) is defined as: + * A(0) = seed + * A(i) = HMAC_(secret, A(i-1)) + */ +#include +#include +#include +#include +#include +#include +#include +#include "internal/cryptlib.h" +#include "internal/numbers.h" +#include "crypto/evp.h" +#include "internal/provider_ctx.h" +#include "internal/providercommonerr.h" +#include "internal/provider_algs.h" +#include "internal/provider_util.h" +#include "e_os.h" + +static OSSL_OP_kdf_newctx_fn kdf_tls1_prf_new; +static OSSL_OP_kdf_freectx_fn kdf_tls1_prf_free; +static OSSL_OP_kdf_reset_fn kdf_tls1_prf_reset; +static OSSL_OP_kdf_derive_fn kdf_tls1_prf_derive; +static OSSL_OP_kdf_settable_ctx_params_fn kdf_tls1_prf_settable_ctx_params; +static OSSL_OP_kdf_set_ctx_params_fn kdf_tls1_prf_set_ctx_params; + +static int tls1_prf_alg(EVP_MAC_CTX *mdctx, EVP_MAC_CTX *sha1ctx, + const unsigned char *sec, size_t slen, + const unsigned char *seed, size_t seed_len, + unsigned char *out, size_t olen); + +#define TLS1_PRF_MAXBUF 1024 + +/* TLS KDF kdf context structure */ +typedef struct { + void *provctx; + + /* MAC context for the main digest */ + EVP_MAC_CTX *P_hash; + /* MAC context for SHA1 for the MD5/SHA-1 combined PRF */ + EVP_MAC_CTX *P_sha1; + + /* Secret value to use for PRF */ + unsigned char *sec; + size_t seclen; + /* Buffer of concatenated seed data */ + unsigned char seed[TLS1_PRF_MAXBUF]; + size_t seedlen; +} TLS1_PRF; + +static void *kdf_tls1_prf_new(void *provctx) +{ + TLS1_PRF *ctx; + + if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + ctx->provctx = provctx; + return ctx; +} + +static void kdf_tls1_prf_free(void *vctx) +{ + TLS1_PRF *ctx = (TLS1_PRF *)vctx; + + kdf_tls1_prf_reset(ctx); + OPENSSL_free(ctx); +} + +static void kdf_tls1_prf_reset(void *vctx) +{ + TLS1_PRF *ctx = (TLS1_PRF *)vctx; + + EVP_MAC_CTX_free(ctx->P_hash); + EVP_MAC_CTX_free(ctx->P_sha1); + OPENSSL_clear_free(ctx->sec, ctx->seclen); + OPENSSL_cleanse(ctx->seed, ctx->seedlen); + memset(ctx, 0, sizeof(*ctx)); +} + +static int kdf_tls1_prf_derive(void *vctx, unsigned char *key, + size_t keylen) +{ + TLS1_PRF *ctx = (TLS1_PRF *)vctx; + + if (ctx->P_hash == NULL) { + ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST); + return 0; + } + if (ctx->sec == NULL) { + ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_SECRET); + return 0; + } + if (ctx->seedlen == 0) { + ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_SEED); + return 0; + } + + return tls1_prf_alg(ctx->P_hash, ctx->P_sha1, + ctx->sec, ctx->seclen, + ctx->seed, ctx->seedlen, + key, keylen); +} + +static int kdf_tls1_prf_set_ctx_params(void *vctx, const OSSL_PARAM params[]) +{ + const OSSL_PARAM *p; + TLS1_PRF *ctx = vctx; + OPENSSL_CTX *libctx = PROV_LIBRARY_CONTEXT_OF(ctx->provctx); + + if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_DIGEST)) != NULL) { + if (strcasecmp(p->data, SN_md5_sha1) == 0) { + if (!ossl_prov_macctx_load_from_params(&ctx->P_hash, params, + OSSL_MAC_NAME_HMAC, + NULL, SN_md5, libctx) + || !ossl_prov_macctx_load_from_params(&ctx->P_sha1, params, + OSSL_MAC_NAME_HMAC, + NULL, SN_sha1, libctx)) + return 0; + } else { + EVP_MAC_CTX_free(ctx->P_sha1); + if (!ossl_prov_macctx_load_from_params(&ctx->P_hash, params, + OSSL_MAC_NAME_HMAC, + NULL, NULL, libctx)) + return 0; + } + } + + if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SECRET)) != NULL) { + OPENSSL_clear_free(ctx->sec, ctx->seclen); + ctx->sec = NULL; + if (!OSSL_PARAM_get_octet_string(p, (void **)&ctx->sec, 0, &ctx->seclen)) + return 0; + } + /* The seed fields concatenate, so process them all */ + if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SEED)) != NULL) { + OPENSSL_cleanse(ctx->seed, ctx->seedlen); + ctx->seedlen = 0; + + for (; p != NULL; p = OSSL_PARAM_locate_const(p + 1, + OSSL_KDF_PARAM_SEED)) { + const void *q = ctx->seed + ctx->seedlen; + size_t sz = 0; + + if (p->data_size != 0 + && p->data != NULL + && !OSSL_PARAM_get_octet_string(p, (void **)&q, + TLS1_PRF_MAXBUF - ctx->seedlen, + &sz)) + return 0; + ctx->seedlen += sz; + } + } + return 1; +} + +static const OSSL_PARAM *kdf_tls1_prf_settable_ctx_params(void) +{ + static const OSSL_PARAM known_settable_ctx_params[] = { + OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES, NULL, 0), + OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_DIGEST, NULL, 0), + OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SECRET, NULL, 0), + OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SEED, NULL, 0), + OSSL_PARAM_END + }; + return known_settable_ctx_params; +} + +static int kdf_tls1_prf_get_ctx_params(void *vctx, OSSL_PARAM params[]) +{ + OSSL_PARAM *p; + + if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE)) != NULL) + return OSSL_PARAM_set_size_t(p, SIZE_MAX); + return -2; +} + +static const OSSL_PARAM *kdf_tls1_prf_gettable_ctx_params(void) +{ + static const OSSL_PARAM known_gettable_ctx_params[] = { + OSSL_PARAM_size_t(OSSL_KDF_PARAM_SIZE, NULL), + OSSL_PARAM_END + }; + return known_gettable_ctx_params; +} + +const OSSL_DISPATCH kdf_tls1_prf_functions[] = { + { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))kdf_tls1_prf_new }, + { OSSL_FUNC_KDF_FREECTX, (void(*)(void))kdf_tls1_prf_free }, + { OSSL_FUNC_KDF_RESET, (void(*)(void))kdf_tls1_prf_reset }, + { OSSL_FUNC_KDF_DERIVE, (void(*)(void))kdf_tls1_prf_derive }, + { OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS, + (void(*)(void))kdf_tls1_prf_settable_ctx_params }, + { OSSL_FUNC_KDF_SET_CTX_PARAMS, + (void(*)(void))kdf_tls1_prf_set_ctx_params }, + { OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS, + (void(*)(void))kdf_tls1_prf_gettable_ctx_params }, + { OSSL_FUNC_KDF_GET_CTX_PARAMS, + (void(*)(void))kdf_tls1_prf_get_ctx_params }, + { 0, NULL } +}; + +/* + * Refer to "The TLS Protocol Version 1.0" Section 5 + * (https://tools.ietf.org/html/rfc2246#section-5) and + * "The Transport Layer Security (TLS) Protocol Version 1.2" Section 5 + * (https://tools.ietf.org/html/rfc5246#section-5). + * + * P_ is an expansion function that uses a single hash function to expand + * a secret and seed into an arbitrary quantity of output: + * + * P_(secret, seed) = HMAC_(secret, A(1) + seed) + + * HMAC_(secret, A(2) + seed) + + * HMAC_(secret, A(3) + seed) + ... + * + * where + indicates concatenation. P_ can be iterated as many times as + * is necessary to produce the required quantity of data. + * + * A(i) is defined as: + * A(0) = seed + * A(i) = HMAC_(secret, A(i-1)) + */ +static int tls1_prf_P_hash(EVP_MAC_CTX *ctx_init, + const unsigned char *sec, size_t sec_len, + const unsigned char *seed, size_t seed_len, + unsigned char *out, size_t olen) +{ + size_t chunk; + EVP_MAC_CTX *ctx = NULL, *ctx_Ai = NULL; + unsigned char Ai[EVP_MAX_MD_SIZE]; + size_t Ai_len; + int ret = 0; + OSSL_PARAM params[2], *p = params; + + *p++ = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY, + (void *)sec, sec_len); + *p = OSSL_PARAM_construct_end(); + if (!EVP_MAC_CTX_set_params(ctx_init, params)) + goto err; + if (!EVP_MAC_init(ctx_init)) + goto err; + chunk = EVP_MAC_size(ctx_init); + if (chunk == 0) + goto err; + /* A(0) = seed */ + ctx_Ai = EVP_MAC_CTX_dup(ctx_init); + if (ctx_Ai == NULL) + goto err; + if (seed != NULL && !EVP_MAC_update(ctx_Ai, seed, seed_len)) + goto err; + + for (;;) { + /* calc: A(i) = HMAC_(secret, A(i-1)) */ + if (!EVP_MAC_final(ctx_Ai, Ai, &Ai_len, sizeof(Ai))) + goto err; + EVP_MAC_CTX_free(ctx_Ai); + ctx_Ai = NULL; + + /* calc next chunk: HMAC_(secret, A(i) + seed) */ + ctx = EVP_MAC_CTX_dup(ctx_init); + if (ctx == NULL) + goto err; + if (!EVP_MAC_update(ctx, Ai, Ai_len)) + goto err; + /* save state for calculating next A(i) value */ + if (olen > chunk) { + ctx_Ai = EVP_MAC_CTX_dup(ctx); + if (ctx_Ai == NULL) + goto err; + } + if (seed != NULL && !EVP_MAC_update(ctx, seed, seed_len)) + goto err; + if (olen <= chunk) { + /* last chunk - use Ai as temp bounce buffer */ + if (!EVP_MAC_final(ctx, Ai, &Ai_len, sizeof(Ai))) + goto err; + memcpy(out, Ai, olen); + break; + } + if (!EVP_MAC_final(ctx, out, NULL, olen)) + goto err; + EVP_MAC_CTX_free(ctx); + ctx = NULL; + out += chunk; + olen -= chunk; + } + ret = 1; + err: + EVP_MAC_CTX_free(ctx); + EVP_MAC_CTX_free(ctx_Ai); + OPENSSL_cleanse(Ai, sizeof(Ai)); + return ret; +} + +/* + * Refer to "The TLS Protocol Version 1.0" Section 5 + * (https://tools.ietf.org/html/rfc2246#section-5) and + * "The Transport Layer Security (TLS) Protocol Version 1.2" Section 5 + * (https://tools.ietf.org/html/rfc5246#section-5). + * + * For TLS v1.0 and TLS v1.1: + * + * PRF(secret, label, seed) = P_MD5(S1, label + seed) XOR + * P_SHA-1(S2, label + seed) + * + * S1 is taken from the first half of the secret, S2 from the second half. + * + * L_S = length in bytes of secret; + * L_S1 = L_S2 = ceil(L_S / 2); + * + * For TLS v1.2: + * + * PRF(secret, label, seed) = P_(secret, label + seed) + */ +static int tls1_prf_alg(EVP_MAC_CTX *mdctx, EVP_MAC_CTX *sha1ctx, + const unsigned char *sec, size_t slen, + const unsigned char *seed, size_t seed_len, + unsigned char *out, size_t olen) +{ + if (sha1ctx != NULL) { + /* TLS v1.0 and TLS v1.1 */ + size_t i; + unsigned char *tmp; + /* calc: L_S1 = L_S2 = ceil(L_S / 2) */ + size_t L_S1 = (slen + 1) / 2; + size_t L_S2 = L_S1; + + if (!tls1_prf_P_hash(mdctx, sec, L_S1, + seed, seed_len, out, olen)) + return 0; + + if ((tmp = OPENSSL_malloc(olen)) == NULL) { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + return 0; + } + + if (!tls1_prf_P_hash(sha1ctx, sec + slen - L_S2, L_S2, + seed, seed_len, tmp, olen)) { + OPENSSL_clear_free(tmp, olen); + return 0; + } + for (i = 0; i < olen; i++) + out[i] ^= tmp[i]; + OPENSSL_clear_free(tmp, olen); + return 1; + } + + /* TLS v1.2 */ + if (!tls1_prf_P_hash(mdctx, sec, slen, seed, seed_len, out, olen)) + return 0; + + return 1; +} diff --git a/providers/implementations/keymgmt/build.info b/providers/implementations/keymgmt/build.info new file mode 100644 index 0000000000..dc6039b02d --- /dev/null +++ b/providers/implementations/keymgmt/build.info @@ -0,0 +1,12 @@ +# We make separate GOAL variables for each algorithm, to make it easy to +# switch each to the Legacy provider when needed. + +$DH_GOAL=../../libimplementations.a +$DSA_GOAL=../../libimplementations.a + +IF[{- !$disabled{dh} -}] + SOURCE[$DH_GOAL]=dh_kmgmt.c +ENDIF +IF[{- !$disabled{dsa} -}] + SOURCE[$DSA_GOAL]=dsa_kmgmt.c +ENDIF diff --git a/providers/implementations/keymgmt/dh_kmgmt.c b/providers/implementations/keymgmt/dh_kmgmt.c new file mode 100644 index 0000000000..c13f07546b --- /dev/null +++ b/providers/implementations/keymgmt/dh_kmgmt.c @@ -0,0 +1,88 @@ +/* + * Copyright 2019 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 + */ + +#include +#include +#include +#include +#include +#include "internal/provider_algs.h" + +static OSSL_OP_keymgmt_importkey_fn dh_importkey; + +static int params_to_key(DH *dh, const OSSL_PARAM params[]) +{ + const OSSL_PARAM *param_p, *param_g, *param_priv_key, *param_pub_key; + BIGNUM *p = NULL, *g = NULL, *priv_key = NULL, *pub_key = NULL; + + if (dh == NULL) + return 0; + + param_p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_P); + param_g = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_G); + param_priv_key = + OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_DH_PRIV_KEY); + param_pub_key = + OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_DH_PUB_KEY); + + /* + * DH documentation says that a public key must be present if a + * private key is present. + * We want to have at least a public key either way, so we end up + * requiring it unconditionally. + */ + if (param_pub_key == NULL) + return 0; + + if ((param_p != NULL && !OSSL_PARAM_get_BN(param_p, &p)) + || (param_g != NULL && !OSSL_PARAM_get_BN(param_g, &g)) + || (param_priv_key != NULL + && !OSSL_PARAM_get_BN(param_priv_key, &priv_key)) + || !OSSL_PARAM_get_BN(param_pub_key, &pub_key)) + goto err; + + if (!DH_set0_pqg(dh, p, NULL, g)) + goto err; + p = g = NULL; + + if (!DH_set0_key(dh, pub_key, priv_key)) + goto err; + priv_key = pub_key = NULL; + + return 1; + + err: + BN_free(p); + BN_free(g); + BN_free(priv_key); + BN_free(pub_key); + return 0; +} + +static void *dh_importkey(void *provctx, const OSSL_PARAM params[]) +{ + DH *dh; + + if ((dh = DH_new()) == NULL + || !params_to_key(dh, params)) { + DH_free(dh); + dh = NULL; + } + return dh; +} + +const OSSL_DISPATCH dh_keymgmt_functions[] = { + /* + * TODO(3.0) When implementing OSSL_FUNC_KEYMGMT_GENKEY, remember to also + * implement OSSL_FUNC_KEYMGMT_EXPORTKEY. + */ + { OSSL_FUNC_KEYMGMT_IMPORTKEY, (void (*)(void))dh_importkey }, + { OSSL_FUNC_KEYMGMT_FREEKEY, (void (*)(void))DH_free }, + { 0, NULL } +}; diff --git a/providers/implementations/keymgmt/dsa_kmgmt.c b/providers/implementations/keymgmt/dsa_kmgmt.c new file mode 100644 index 0000000000..a53c0b212c --- /dev/null +++ b/providers/implementations/keymgmt/dsa_kmgmt.c @@ -0,0 +1,91 @@ +/* + * Copyright 2019 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 + */ + +#include +#include +#include +#include +#include +#include "internal/provider_algs.h" + +static OSSL_OP_keymgmt_importkey_fn dsa_importkey; + +static int params_to_key(DSA *dsa, const OSSL_PARAM params[]) +{ + const OSSL_PARAM *param_p, *param_q, *param_g, *param_priv_key; + const OSSL_PARAM *param_pub_key; + BIGNUM *p = NULL, *q = NULL, *g = NULL, *priv_key = NULL, *pub_key = NULL; + + if (dsa == NULL) + return 0; + + param_p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_P); + param_q = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_Q); + param_g = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_G); + param_priv_key = + OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_DSA_PRIV_KEY); + param_pub_key = + OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_DSA_PUB_KEY); + + /* + * DSA documentation says that a public key must be present if a private key + * is. + */ + if (param_priv_key != NULL && param_pub_key == NULL) + return 0; + + if ((param_p != NULL && !OSSL_PARAM_get_BN(param_p, &p)) + || (param_q != NULL && !OSSL_PARAM_get_BN(param_q, &q)) + || (param_g != NULL && !OSSL_PARAM_get_BN(param_g, &g)) + || (param_priv_key != NULL + && !OSSL_PARAM_get_BN(param_priv_key, &priv_key)) + || (param_pub_key != NULL + && !OSSL_PARAM_get_BN(param_pub_key, &pub_key))) + goto err; + + if (!DSA_set0_pqg(dsa, p, q, g)) + goto err; + p = q = g = NULL; + + if (pub_key != NULL && !DSA_set0_key(dsa, pub_key, priv_key)) + goto err; + priv_key = pub_key = NULL; + + return 1; + + err: + BN_free(p); + BN_free(q); + BN_free(g); + BN_free(priv_key); + BN_free(pub_key); + return 0; +} + +static void *dsa_importkey(void *provctx, const OSSL_PARAM params[]) +{ + DSA *dsa; + + if ((dsa = DSA_new()) == NULL + || !params_to_key(dsa, params)) { + DSA_free(dsa); + dsa = NULL; + } + return dsa; +} + +const OSSL_DISPATCH dsa_keymgmt_functions[] = { + /* + * TODO(3.0) When implementing OSSL_FUNC_KEYMGMT_GENKEY, remember to also + * implement OSSL_FUNC_KEYMGMT_EXPORTKEY. + */ + { OSSL_FUNC_KEYMGMT_IMPORTKEY, (void (*)(void))dsa_importkey }, + { OSSL_FUNC_KEYMGMT_FREEKEY, (void (*)(void))DSA_free }, + { 0, NULL } +}; diff --git a/providers/implementations/macs/build.info b/providers/implementations/macs/build.info new file mode 100644 index 0000000000..d4538098e0 --- /dev/null +++ b/providers/implementations/macs/build.info @@ -0,0 +1,15 @@ +# We make separate GOAL variables for each algorithm, to make it easy to +# switch each to the Legacy provider when needed. + +$GMAC_GOAL=../../libimplementations.a +$HMAC_GOAL=../../libimplementations.a +$KMAC_GOAL=../../libimplementations.a +$CMAC_GOAL=../../libimplementations.a + +SOURCE[$GMAC_GOAL]=gmac_prov.c +SOURCE[$HMAC_GOAL]=hmac_prov.c +SOURCE[$KMAC_GOAL]=kmac_prov.c + +IF[{- !$disabled{cmac} -}] + SOURCE[$CMAC_GOAL]=cmac_prov.c +ENDIF diff --git a/providers/implementations/macs/cmac_prov.c b/providers/implementations/macs/cmac_prov.c new file mode 100644 index 0000000000..c01b2f87ad --- /dev/null +++ b/providers/implementations/macs/cmac_prov.c @@ -0,0 +1,188 @@ +/* + * 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 + */ + +#include +#include +#include +#include +#include +#include + +#include "internal/provider_algs.h" +#include "internal/provider_ctx.h" +#include "internal/provider_util.h" + +/* + * Forward declaration of everything implemented here. This is not strictly + * necessary for the compiler, but provides an assurance that the signatures + * of the functions in the dispatch table are correct. + */ +static OSSL_OP_mac_newctx_fn cmac_new; +static OSSL_OP_mac_dupctx_fn cmac_dup; +static OSSL_OP_mac_freectx_fn cmac_free; +static OSSL_OP_mac_gettable_ctx_params_fn cmac_gettable_ctx_params; +static OSSL_OP_mac_get_ctx_params_fn cmac_get_ctx_params; +static OSSL_OP_mac_settable_ctx_params_fn cmac_settable_ctx_params; +static OSSL_OP_mac_set_ctx_params_fn cmac_set_ctx_params; +static OSSL_OP_mac_init_fn cmac_init; +static OSSL_OP_mac_update_fn cmac_update; +static OSSL_OP_mac_final_fn cmac_final; + +/* local CMAC data */ + +struct cmac_data_st { + void *provctx; + CMAC_CTX *ctx; + PROV_CIPHER cipher; +}; + +static void *cmac_new(void *provctx) +{ + struct cmac_data_st *macctx; + + if ((macctx = OPENSSL_zalloc(sizeof(*macctx))) == NULL + || (macctx->ctx = CMAC_CTX_new()) == NULL) { + OPENSSL_free(macctx); + macctx = NULL; + } else { + macctx->provctx = provctx; + } + + return macctx; +} + +static void cmac_free(void *vmacctx) +{ + struct cmac_data_st *macctx = vmacctx; + + if (macctx != NULL) { + CMAC_CTX_free(macctx->ctx); + ossl_prov_cipher_reset(&macctx->cipher); + OPENSSL_free(macctx); + } +} + +static void *cmac_dup(void *vsrc) +{ + struct cmac_data_st *src = vsrc; + struct cmac_data_st *dst = cmac_new(src->provctx); + + if (!CMAC_CTX_copy(dst->ctx, src->ctx) + || !ossl_prov_cipher_copy(&dst->cipher, &src->cipher)) { + cmac_free(dst); + return NULL; + } + return dst; +} + +static size_t cmac_size(void *vmacctx) +{ + struct cmac_data_st *macctx = vmacctx; + + return EVP_CIPHER_CTX_block_size(CMAC_CTX_get0_cipher_ctx(macctx->ctx)); +} + +static int cmac_init(void *vmacctx) +{ + struct cmac_data_st *macctx = vmacctx; + int rv = CMAC_Init(macctx->ctx, NULL, 0, + ossl_prov_cipher_cipher(&macctx->cipher), + ossl_prov_cipher_engine(&macctx->cipher)); + + ossl_prov_cipher_reset(&macctx->cipher); + return rv; +} + +static int cmac_update(void *vmacctx, const unsigned char *data, + size_t datalen) +{ + struct cmac_data_st *macctx = vmacctx; + + return CMAC_Update(macctx->ctx, data, datalen); +} + +static int cmac_final(void *vmacctx, unsigned char *out, size_t *outl, + size_t outsize) +{ + struct cmac_data_st *macctx = vmacctx; + + return CMAC_Final(macctx->ctx, out, outl); +} + +static const OSSL_PARAM known_gettable_ctx_params[] = { + OSSL_PARAM_size_t(OSSL_MAC_PARAM_SIZE, NULL), + OSSL_PARAM_END +}; +static const OSSL_PARAM *cmac_gettable_ctx_params(void) +{ + return known_gettable_ctx_params; +} + +static int cmac_get_ctx_params(void *vmacctx, OSSL_PARAM params[]) +{ + OSSL_PARAM *p; + + if ((p = OSSL_PARAM_locate(params, OSSL_MAC_PARAM_SIZE)) != NULL) + return OSSL_PARAM_set_size_t(p, cmac_size(vmacctx)); + + return 1; +} + +static const OSSL_PARAM known_settable_ctx_params[] = { + OSSL_PARAM_utf8_string(OSSL_MAC_PARAM_CIPHER, NULL, 0), + OSSL_PARAM_utf8_string(OSSL_MAC_PARAM_PROPERTIES, NULL, 0), + OSSL_PARAM_octet_string(OSSL_MAC_PARAM_KEY, NULL, 0), + OSSL_PARAM_END +}; +static const OSSL_PARAM *cmac_settable_ctx_params(void) +{ + return known_settable_ctx_params; +} + +/* + * ALL parameters should be set before init(). + */ +static int cmac_set_ctx_params(void *vmacctx, const OSSL_PARAM params[]) +{ + struct cmac_data_st *macctx = vmacctx; + OPENSSL_CTX *ctx = PROV_LIBRARY_CONTEXT_OF(macctx->provctx); + const OSSL_PARAM *p; + + if (!ossl_prov_cipher_load_from_params(&macctx->cipher, params, ctx)) + return 0; + + if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_KEY)) != NULL) { + if (p->data_type != OSSL_PARAM_OCTET_STRING) + return 0; + + if (!CMAC_Init(macctx->ctx, p->data, p->data_size, + ossl_prov_cipher_cipher(&macctx->cipher), + ossl_prov_cipher_engine(&macctx->cipher))) + return 0; + + ossl_prov_cipher_reset(&macctx->cipher); + } + return 1; +} + +const OSSL_DISPATCH cmac_functions[] = { + { OSSL_FUNC_MAC_NEWCTX, (void (*)(void))cmac_new }, + { OSSL_FUNC_MAC_DUPCTX, (void (*)(void))cmac_dup }, + { OSSL_FUNC_MAC_FREECTX, (void (*)(void))cmac_free }, + { OSSL_FUNC_MAC_INIT, (void (*)(void))cmac_init }, + { OSSL_FUNC_MAC_UPDATE, (void (*)(void))cmac_update }, + { OSSL_FUNC_MAC_FINAL, (void (*)(void))cmac_final }, + { OSSL_FUNC_MAC_GETTABLE_CTX_PARAMS, + (void (*)(void))cmac_gettable_ctx_params }, + { OSSL_FUNC_MAC_GET_CTX_PARAMS, (void (*)(void))cmac_get_ctx_params }, + { OSSL_FUNC_MAC_SETTABLE_CTX_PARAMS, + (void (*)(void))cmac_settable_ctx_params }, + { OSSL_FUNC_MAC_SET_CTX_PARAMS, (void (*)(void))cmac_set_ctx_params }, + { 0, NULL } +}; diff --git a/providers/implementations/macs/gmac_prov.c b/providers/implementations/macs/gmac_prov.c new file mode 100644 index 0000000000..3d81af8766 --- /dev/null +++ b/providers/implementations/macs/gmac_prov.c @@ -0,0 +1,226 @@ +/* + * 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 + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "internal/providercommonerr.h" +#include "internal/provider_algs.h" +#include "internal/provider_ctx.h" +#include "internal/provider_util.h" + +/* + * Forward declaration of everything implemented here. This is not strictly + * necessary for the compiler, but provides an assurance that the signatures + * of the functions in the dispatch table are correct. + */ +static OSSL_OP_mac_newctx_fn gmac_new; +static OSSL_OP_mac_dupctx_fn gmac_dup; +static OSSL_OP_mac_freectx_fn gmac_free; +static OSSL_OP_mac_gettable_params_fn gmac_gettable_params; +static OSSL_OP_mac_get_params_fn gmac_get_params; +static OSSL_OP_mac_settable_ctx_params_fn gmac_settable_ctx_params; +static OSSL_OP_mac_set_ctx_params_fn gmac_set_ctx_params; +static OSSL_OP_mac_init_fn gmac_init; +static OSSL_OP_mac_update_fn gmac_update; +static OSSL_OP_mac_final_fn gmac_final; + +/* local GMAC pkey structure */ + +struct gmac_data_st { + void *provctx; + EVP_CIPHER_CTX *ctx; /* Cipher context */ + PROV_CIPHER cipher; +}; + +static size_t gmac_size(void); + +static void gmac_free(void *vmacctx) +{ + struct gmac_data_st *macctx = vmacctx; + + if (macctx != NULL) { + EVP_CIPHER_CTX_free(macctx->ctx); + ossl_prov_cipher_reset(&macctx->cipher); + OPENSSL_free(macctx); + } +} + +static void *gmac_new(void *provctx) +{ + struct gmac_data_st *macctx; + + if ((macctx = OPENSSL_zalloc(sizeof(*macctx))) == NULL + || (macctx->ctx = EVP_CIPHER_CTX_new()) == NULL) { + gmac_free(macctx); + return NULL; + } + macctx->provctx = provctx; + + return macctx; +} + +static void *gmac_dup(void *vsrc) +{ + struct gmac_data_st *src = vsrc; + struct gmac_data_st *dst = gmac_new(src->provctx); + + if (dst == NULL) + return NULL; + + if (!EVP_CIPHER_CTX_copy(dst->ctx, src->ctx) + || !ossl_prov_cipher_copy(&dst->cipher, &src->cipher)) { + gmac_free(dst); + return NULL; + } + return dst; +} + +static int gmac_init(void *vmacctx) +{ + return 1; +} + +static int gmac_update(void *vmacctx, const unsigned char *data, + size_t datalen) +{ + struct gmac_data_st *macctx = vmacctx; + EVP_CIPHER_CTX *ctx = macctx->ctx; + int outlen; + + while (datalen > INT_MAX) { + if (!EVP_EncryptUpdate(ctx, NULL, &outlen, data, INT_MAX)) + return 0; + data += INT_MAX; + datalen -= INT_MAX; + } + return EVP_EncryptUpdate(ctx, NULL, &outlen, data, datalen); +} + +static int gmac_final(void *vmacctx, unsigned char *out, size_t *outl, + size_t outsize) +{ + struct gmac_data_st *macctx = vmacctx; + int hlen = 0; + + if (!EVP_EncryptFinal_ex(macctx->ctx, out, &hlen)) + return 0; + + /* TODO(3.0) Use params */ + hlen = gmac_size(); + if (!EVP_CIPHER_CTX_ctrl(macctx->ctx, EVP_CTRL_AEAD_GET_TAG, + hlen, out)) + return 0; + + *outl = hlen; + return 1; +} + +static size_t gmac_size(void) +{ + return EVP_GCM_TLS_TAG_LEN; +} + +static const OSSL_PARAM known_gettable_params[] = { + OSSL_PARAM_size_t(OSSL_MAC_PARAM_SIZE, NULL), + OSSL_PARAM_END +}; +static const OSSL_PARAM *gmac_gettable_params(void) +{ + return known_gettable_params; +} + +static int gmac_get_params(OSSL_PARAM params[]) +{ + OSSL_PARAM *p; + + if ((p = OSSL_PARAM_locate(params, OSSL_MAC_PARAM_SIZE)) != NULL) + return OSSL_PARAM_set_size_t(p, gmac_size()); + + return 1; +} + +static const OSSL_PARAM known_settable_ctx_params[] = { + OSSL_PARAM_utf8_string(OSSL_MAC_PARAM_CIPHER, NULL, 0), + OSSL_PARAM_utf8_string(OSSL_MAC_PARAM_PROPERTIES, NULL, 0), + OSSL_PARAM_octet_string(OSSL_MAC_PARAM_KEY, NULL, 0), + OSSL_PARAM_octet_string(OSSL_MAC_PARAM_IV, NULL, 0), + OSSL_PARAM_END +}; +static const OSSL_PARAM *gmac_settable_ctx_params(void) +{ + return known_settable_ctx_params; +} + +/* + * ALL parameters should be set before init(). + */ +static int gmac_set_ctx_params(void *vmacctx, const OSSL_PARAM params[]) +{ + struct gmac_data_st *macctx = vmacctx; + EVP_CIPHER_CTX *ctx = macctx->ctx; + OPENSSL_CTX *provctx = PROV_LIBRARY_CONTEXT_OF(macctx->provctx); + const OSSL_PARAM *p; + + if (ctx == NULL + || !ossl_prov_cipher_load_from_params(&macctx->cipher, params, provctx)) + return 0; + + if (EVP_CIPHER_mode(ossl_prov_cipher_cipher(&macctx->cipher)) + != EVP_CIPH_GCM_MODE) { + ERR_raise(ERR_LIB_PROV, EVP_R_CIPHER_NOT_GCM_MODE); + return 0; + } + if (!EVP_EncryptInit_ex(ctx, ossl_prov_cipher_cipher(&macctx->cipher), + ossl_prov_cipher_engine(&macctx->cipher), NULL, + NULL)) + return 0; + + if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_KEY)) != NULL) { + if (p->data_type != OSSL_PARAM_OCTET_STRING) + return 0; + + if (p->data_size != (size_t)EVP_CIPHER_CTX_key_length(ctx)) { + ERR_raise(ERR_LIB_PROV, EVP_R_INVALID_KEY_LENGTH); + return 0; + } + if (!EVP_EncryptInit_ex(ctx, NULL, NULL, p->data, NULL)) + return 0; + } + if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_IV)) != NULL) { + if (p->data_type != OSSL_PARAM_OCTET_STRING) + return 0; + + if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, + p->data_size, NULL) + || !EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, p->data)) + return 0; + } + return 1; +} + +const OSSL_DISPATCH gmac_functions[] = { + { OSSL_FUNC_MAC_NEWCTX, (void (*)(void))gmac_new }, + { OSSL_FUNC_MAC_DUPCTX, (void (*)(void))gmac_dup }, + { OSSL_FUNC_MAC_FREECTX, (void (*)(void))gmac_free }, + { OSSL_FUNC_MAC_INIT, (void (*)(void))gmac_init }, + { OSSL_FUNC_MAC_UPDATE, (void (*)(void))gmac_update }, + { OSSL_FUNC_MAC_FINAL, (void (*)(void))gmac_final }, + { OSSL_FUNC_MAC_GETTABLE_PARAMS, (void (*)(void))gmac_gettable_params }, + { OSSL_FUNC_MAC_GET_PARAMS, (void (*)(void))gmac_get_params }, + { OSSL_FUNC_MAC_SETTABLE_CTX_PARAMS, + (void (*)(void))gmac_settable_ctx_params }, + { OSSL_FUNC_MAC_SET_CTX_PARAMS, (void (*)(void))gmac_set_ctx_params }, + { 0, NULL } +}; diff --git a/providers/implementations/macs/hmac_prov.c b/providers/implementations/macs/hmac_prov.c new file mode 100644 index 0000000000..e9d7647ce2 --- /dev/null +++ b/providers/implementations/macs/hmac_prov.c @@ -0,0 +1,212 @@ +/* + * 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 + */ + +#include +#include +#include +#include +#include +#include + +#include "internal/provider_algs.h" +#include "internal/provider_ctx.h" +#include "internal/provider_util.h" + +/* + * Forward declaration of everything implemented here. This is not strictly + * necessary for the compiler, but provides an assurance that the signatures + * of the functions in the dispatch table are correct. + */ +static OSSL_OP_mac_newctx_fn hmac_new; +static OSSL_OP_mac_dupctx_fn hmac_dup; +static OSSL_OP_mac_freectx_fn hmac_free; +static OSSL_OP_mac_gettable_ctx_params_fn hmac_gettable_ctx_params; +static OSSL_OP_mac_get_ctx_params_fn hmac_get_ctx_params; +static OSSL_OP_mac_settable_ctx_params_fn hmac_settable_ctx_params; +static OSSL_OP_mac_set_ctx_params_fn hmac_set_ctx_params; +static OSSL_OP_mac_init_fn hmac_init; +static OSSL_OP_mac_update_fn hmac_update; +static OSSL_OP_mac_final_fn hmac_final; + +/* local HMAC context structure */ + +/* typedef EVP_MAC_IMPL */ +struct hmac_data_st { + void *provctx; + HMAC_CTX *ctx; /* HMAC context */ + PROV_DIGEST digest; +}; + +static size_t hmac_size(void *vmacctx); + +static void *hmac_new(void *provctx) +{ + struct hmac_data_st *macctx; + + if ((macctx = OPENSSL_zalloc(sizeof(*macctx))) == NULL + || (macctx->ctx = HMAC_CTX_new()) == NULL) { + OPENSSL_free(macctx); + return NULL; + } + /* TODO(3.0) Should we do something more with that context? */ + macctx->provctx = provctx; + + return macctx; +} + +static void hmac_free(void *vmacctx) +{ + struct hmac_data_st *macctx = vmacctx; + + if (macctx != NULL) { + HMAC_CTX_free(macctx->ctx); + ossl_prov_digest_reset(&macctx->digest); + OPENSSL_free(macctx); + } +} + +static void *hmac_dup(void *vsrc) +{ + struct hmac_data_st *src = vsrc; + struct hmac_data_st *dst = hmac_new(src->provctx); + + if (dst == NULL) + return NULL; + + if (!HMAC_CTX_copy(dst->ctx, src->ctx) + || !ossl_prov_digest_copy(&dst->digest, &src->digest)) { + hmac_free(dst); + return NULL; + } + return dst; +} + +static size_t hmac_size(void *vmacctx) +{ + struct hmac_data_st *macctx = vmacctx; + + return HMAC_size(macctx->ctx); +} + +static int hmac_init(void *vmacctx) +{ + struct hmac_data_st *macctx = vmacctx; + const EVP_MD *digest = ossl_prov_digest_md(&macctx->digest); + int rv = 1; + + /* HMAC_Init_ex doesn't tolerate all zero params, so we must be careful */ + if (digest != NULL) + rv = HMAC_Init_ex(macctx->ctx, NULL, 0, digest, + ossl_prov_digest_engine(&macctx->digest)); + ossl_prov_digest_reset(&macctx->digest); + return rv; +} + +static int hmac_update(void *vmacctx, const unsigned char *data, + size_t datalen) +{ + struct hmac_data_st *macctx = vmacctx; + + return HMAC_Update(macctx->ctx, data, datalen); +} + +static int hmac_final(void *vmacctx, unsigned char *out, size_t *outl, + size_t outsize) +{ + unsigned int hlen; + struct hmac_data_st *macctx = vmacctx; + + if (!HMAC_Final(macctx->ctx, out, &hlen)) + return 0; + if (outl != NULL) + *outl = hlen; + return 1; +} + +static const OSSL_PARAM known_gettable_ctx_params[] = { + OSSL_PARAM_size_t(OSSL_MAC_PARAM_SIZE, NULL), + OSSL_PARAM_END +}; +static const OSSL_PARAM *hmac_gettable_ctx_params(void) +{ + return known_gettable_ctx_params; +} + +static int hmac_get_ctx_params(void *vmacctx, OSSL_PARAM params[]) +{ + OSSL_PARAM *p; + + if ((p = OSSL_PARAM_locate(params, OSSL_MAC_PARAM_SIZE)) != NULL) + return OSSL_PARAM_set_size_t(p, hmac_size(vmacctx)); + + return 1; +} + +static const OSSL_PARAM known_settable_ctx_params[] = { + OSSL_PARAM_utf8_string(OSSL_MAC_PARAM_DIGEST, NULL, 0), + OSSL_PARAM_utf8_string(OSSL_MAC_PARAM_PROPERTIES, NULL, 0), + OSSL_PARAM_octet_string(OSSL_MAC_PARAM_KEY, NULL, 0), + OSSL_PARAM_int(OSSL_MAC_PARAM_FLAGS, NULL), + OSSL_PARAM_END +}; +static const OSSL_PARAM *hmac_settable_ctx_params(void) +{ + return known_settable_ctx_params; +} + +/* + * ALL parameters should be set before init(). + */ +static int hmac_set_ctx_params(void *vmacctx, const OSSL_PARAM params[]) +{ + struct hmac_data_st *macctx = vmacctx; + OPENSSL_CTX *ctx = PROV_LIBRARY_CONTEXT_OF(macctx->provctx); + const OSSL_PARAM *p; + + if (!ossl_prov_digest_load_from_params(&macctx->digest, params, ctx)) + return 0; + + /* TODO(3.0) formalize the meaning of "flags", perhaps as other params */ + if ((p = OSSL_PARAM_locate_const(params, + OSSL_MAC_PARAM_FLAGS)) != NULL) { + int flags = 0; + + if (!OSSL_PARAM_get_int(p, &flags)) + return 0; + HMAC_CTX_set_flags(macctx->ctx, flags); + } + if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_KEY)) != NULL) { + if (p->data_type != OSSL_PARAM_OCTET_STRING) + return 0; + + if (!HMAC_Init_ex(macctx->ctx, p->data, p->data_size, + ossl_prov_digest_md(&macctx->digest), + NULL /* ENGINE */)) + return 0; + + ossl_prov_digest_reset(&macctx->digest); + } + return 1; +} + +const OSSL_DISPATCH hmac_functions[] = { + { OSSL_FUNC_MAC_NEWCTX, (void (*)(void))hmac_new }, + { OSSL_FUNC_MAC_DUPCTX, (void (*)(void))hmac_dup }, + { OSSL_FUNC_MAC_FREECTX, (void (*)(void))hmac_free }, + { OSSL_FUNC_MAC_INIT, (void (*)(void))hmac_init }, + { OSSL_FUNC_MAC_UPDATE, (void (*)(void))hmac_update }, + { OSSL_FUNC_MAC_FINAL, (void (*)(void))hmac_final }, + { OSSL_FUNC_MAC_GETTABLE_CTX_PARAMS, + (void (*)(void))hmac_gettable_ctx_params }, + { OSSL_FUNC_MAC_GET_CTX_PARAMS, (void (*)(void))hmac_get_ctx_params }, + { OSSL_FUNC_MAC_SETTABLE_CTX_PARAMS, + (void (*)(void))hmac_settable_ctx_params }, + { OSSL_FUNC_MAC_SET_CTX_PARAMS, (void (*)(void))hmac_set_ctx_params }, + { 0, NULL } +}; diff --git a/providers/implementations/macs/kmac_prov.c b/providers/implementations/macs/kmac_prov.c new file mode 100644 index 0000000000..99bcbf7da9 --- /dev/null +++ b/providers/implementations/macs/kmac_prov.c @@ -0,0 +1,543 @@ +/* + * 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 + */ + +/* + * See SP800-185 "Appendix A - KMAC, .... in Terms of Keccak[c]" + * + * Inputs are: + * K = Key (len(K) < 2^2040 bits) + * X = Input + * L = Output length (0 <= L < 2^2040 bits) + * S = Customization String Default="" (len(S) < 2^2040 bits) + * + * KMAC128(K, X, L, S) + * { + * newX = bytepad(encode_string(K), 168) || X || right_encode(L). + * T = bytepad(encode_string("KMAC") || encode_string(S), 168). + * return KECCAK[256](T || newX || 00, L). + * } + * + * KMAC256(K, X, L, S) + * { + * newX = bytepad(encode_string(K), 136) || X || right_encode(L). + * T = bytepad(encode_string("KMAC") || encode_string(S), 136). + * return KECCAK[512](T || newX || 00, L). + * } + * + * KMAC128XOF(K, X, L, S) + * { + * newX = bytepad(encode_string(K), 168) || X || right_encode(0). + * T = bytepad(encode_string("KMAC") || encode_string(S), 168). + * return KECCAK[256](T || newX || 00, L). + * } + * + * KMAC256XOF(K, X, L, S) + * { + * newX = bytepad(encode_string(K), 136) || X || right_encode(0). + * T = bytepad(encode_string("KMAC") || encode_string(S), 136). + * return KECCAK[512](T || newX || 00, L). + * } + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "internal/providercommonerr.h" +#include "internal/provider_algs.h" +#include "internal/provider_ctx.h" +#include "internal/provider_util.h" + +/* + * Forward declaration of everything implemented here. This is not strictly + * necessary for the compiler, but provides an assurance that the signatures + * of the functions in the dispatch table are correct. + */ +static OSSL_OP_mac_newctx_fn kmac128_new; +static OSSL_OP_mac_newctx_fn kmac256_new; +static OSSL_OP_mac_dupctx_fn kmac_dup; +static OSSL_OP_mac_freectx_fn kmac_free; +static OSSL_OP_mac_gettable_ctx_params_fn kmac_gettable_ctx_params; +static OSSL_OP_mac_get_ctx_params_fn kmac_get_ctx_params; +static OSSL_OP_mac_settable_ctx_params_fn kmac_settable_ctx_params; +static OSSL_OP_mac_set_ctx_params_fn kmac_set_ctx_params; +static OSSL_OP_mac_size_fn kmac_size; +static OSSL_OP_mac_init_fn kmac_init; +static OSSL_OP_mac_update_fn kmac_update; +static OSSL_OP_mac_final_fn kmac_final; + +#define KMAC_MAX_BLOCKSIZE ((1600 - 128*2) / 8) /* 168 */ +#define KMAC_MIN_BLOCKSIZE ((1600 - 256*2) / 8) /* 136 */ + +/* Length encoding will be a 1 byte size + length in bits (2 bytes max) */ +#define KMAC_MAX_ENCODED_HEADER_LEN 3 + +/* + * Custom string max size is chosen such that: + * len(encoded_string(custom) + len(kmac_encoded_string) <= KMAC_MIN_BLOCKSIZE + * i.e: (KMAC_MAX_CUSTOM + KMAC_MAX_ENCODED_LEN) + 6 <= 136 + */ +#define KMAC_MAX_CUSTOM 127 + +/* Maximum size of encoded custom string */ +#define KMAC_MAX_CUSTOM_ENCODED (KMAC_MAX_CUSTOM + KMAC_MAX_ENCODED_HEADER_LEN) + +/* Maximum key size in bytes = 2040 / 8 */ +#define KMAC_MAX_KEY 255 + +/* + * Maximum Encoded Key size will be padded to a multiple of the blocksize + * i.e KMAC_MAX_KEY + KMAC_MAX_ENCODED_LEN = 258 + * Padded to a multiple of KMAC_MAX_BLOCKSIZE + */ +#define KMAC_MAX_KEY_ENCODED (KMAC_MAX_BLOCKSIZE * 2) + +/* Fixed value of encode_string("KMAC") */ +static const unsigned char kmac_string[] = { + 0x01, 0x20, 0x4B, 0x4D, 0x41, 0x43 +}; + + +#define KMAC_FLAG_XOF_MODE 1 + +struct kmac_data_st { + void *provctx; + EVP_MD_CTX *ctx; + PROV_DIGEST digest; + size_t out_len; + int key_len; + int custom_len; + /* If xof_mode = 1 then we use right_encode(0) */ + int xof_mode; + /* key and custom are stored in encoded form */ + unsigned char key[KMAC_MAX_KEY_ENCODED]; + unsigned char custom[KMAC_MAX_CUSTOM_ENCODED]; +}; + +static int encode_string(unsigned char *out, int *out_len, + const unsigned char *in, int in_len); +static int right_encode(unsigned char *out, int *out_len, size_t bits); +static int bytepad(unsigned char *out, int *out_len, + const unsigned char *in1, int in1_len, + const unsigned char *in2, int in2_len, + int w); +static int kmac_bytepad_encode_key(unsigned char *out, int *out_len, + const unsigned char *in, int in_len, + int w); + +static void kmac_free(void *vmacctx) +{ + struct kmac_data_st *kctx = vmacctx; + + if (kctx != NULL) { + EVP_MD_CTX_free(kctx->ctx); + ossl_prov_digest_reset(&kctx->digest); + OPENSSL_cleanse(kctx->key, kctx->key_len); + OPENSSL_cleanse(kctx->custom, kctx->custom_len); + OPENSSL_free(kctx); + } +} + +/* + * We have KMAC implemented as a hash, which we can use instead of + * reimplementing the EVP functionality with direct use of + * keccak_mac_init() and friends. + */ +static struct kmac_data_st *kmac_new(void *provctx) +{ + struct kmac_data_st *kctx; + + if ((kctx = OPENSSL_zalloc(sizeof(*kctx))) == NULL + || (kctx->ctx = EVP_MD_CTX_new()) == NULL) { + kmac_free(kctx); + return NULL; + } + kctx->provctx = provctx; + return kctx; +} + +static void *kmac_fetch_new(void *provctx, const OSSL_PARAM *params) +{ + struct kmac_data_st *kctx = kmac_new(provctx); + + if (kctx == NULL) + return 0; + if (!ossl_prov_digest_load_from_params(&kctx->digest, params, + PROV_LIBRARY_CONTEXT_OF(provctx))) { + kmac_free(kctx); + return 0; + } + + kctx->out_len = EVP_MD_size(ossl_prov_digest_md(&kctx->digest)); + return kctx; +} + +static void *kmac128_new(void *provctx) +{ + static const OSSL_PARAM kmac128_params[] = { + OSSL_PARAM_utf8_string("digest", OSSL_DIGEST_NAME_KECCAK_KMAC128, + sizeof(OSSL_DIGEST_NAME_KECCAK_KMAC128)), + OSSL_PARAM_END + }; + return kmac_fetch_new(provctx, kmac128_params); +} + +static void *kmac256_new(void *provctx) +{ + static const OSSL_PARAM kmac256_params[] = { + OSSL_PARAM_utf8_string("digest", OSSL_DIGEST_NAME_KECCAK_KMAC256, + sizeof(OSSL_DIGEST_NAME_KECCAK_KMAC256)), + OSSL_PARAM_END + }; + return kmac_fetch_new(provctx, kmac256_params); +} + +static void *kmac_dup(void *vsrc) +{ + struct kmac_data_st *src = vsrc; + struct kmac_data_st *dst = kmac_new(src->provctx); + + if (dst == NULL) + return NULL; + + if (!EVP_MD_CTX_copy(dst->ctx, src->ctx) + || !ossl_prov_digest_copy(&dst->digest, &src->digest)) { + kmac_free(dst); + return NULL; + } + + dst->out_len = src->out_len; + dst->key_len = src->key_len; + dst->custom_len = src->custom_len; + dst->xof_mode = src->xof_mode; + memcpy(dst->key, src->key, src->key_len); + memcpy(dst->custom, src->custom, dst->custom_len); + + return dst; +} + +/* + * The init() assumes that any ctrl methods are set beforehand for + * md, key and custom. Setting the fields afterwards will have no + * effect on the output mac. + */ +static int kmac_init(void *vmacctx) +{ + struct kmac_data_st *kctx = vmacctx; + EVP_MD_CTX *ctx = kctx->ctx; + unsigned char out[KMAC_MAX_BLOCKSIZE]; + int out_len, block_len; + + + /* Check key has been set */ + if (kctx->key_len == 0) { + EVPerr(EVP_F_KMAC_INIT, EVP_R_NO_KEY_SET); + return 0; + } + if (!EVP_DigestInit_ex(kctx->ctx, ossl_prov_digest_md(&kctx->digest), + NULL)) + return 0; + + block_len = EVP_MD_block_size(ossl_prov_digest_md(&kctx->digest)); + + /* Set default custom string if it is not already set */ + if (kctx->custom_len == 0) { + const OSSL_PARAM params[] = { + OSSL_PARAM_octet_string(OSSL_MAC_PARAM_CUSTOM, "", 0), + OSSL_PARAM_END + }; + (void)kmac_set_ctx_params(kctx, params); + } + + return bytepad(out, &out_len, kmac_string, sizeof(kmac_string), + kctx->custom, kctx->custom_len, block_len) + && EVP_DigestUpdate(ctx, out, out_len) + && EVP_DigestUpdate(ctx, kctx->key, kctx->key_len); +} + +static size_t kmac_size(void *vmacctx) +{ + struct kmac_data_st *kctx = vmacctx; + + return kctx->out_len; +} + +static int kmac_update(void *vmacctx, const unsigned char *data, + size_t datalen) +{ + struct kmac_data_st *kctx = vmacctx; + + return EVP_DigestUpdate(kctx->ctx, data, datalen); +} + +static int kmac_final(void *vmacctx, unsigned char *out, size_t *outl, + size_t outsize) +{ + struct kmac_data_st *kctx = vmacctx; + EVP_MD_CTX *ctx = kctx->ctx; + int lbits, len; + unsigned char encoded_outlen[KMAC_MAX_ENCODED_HEADER_LEN]; + int ok; + + /* KMAC XOF mode sets the encoded length to 0 */ + lbits = (kctx->xof_mode ? 0 : (kctx->out_len * 8)); + + ok = right_encode(encoded_outlen, &len, lbits) + && EVP_DigestUpdate(ctx, encoded_outlen, len) + && EVP_DigestFinalXOF(ctx, out, kctx->out_len); + if (ok && outl != NULL) + *outl = kctx->out_len; + return ok; +} + +static const OSSL_PARAM known_gettable_ctx_params[] = { + OSSL_PARAM_size_t(OSSL_MAC_PARAM_SIZE, NULL), + OSSL_PARAM_END +}; +static const OSSL_PARAM *kmac_gettable_ctx_params(void) +{ + return known_gettable_ctx_params; +} + +static int kmac_get_ctx_params(void *vmacctx, OSSL_PARAM params[]) +{ + OSSL_PARAM *p; + + if ((p = OSSL_PARAM_locate(params, OSSL_MAC_PARAM_SIZE)) != NULL) + return OSSL_PARAM_set_size_t(p, kmac_size(vmacctx)); + + return 1; +} + +static const OSSL_PARAM known_settable_ctx_params[] = { + OSSL_PARAM_int(OSSL_MAC_PARAM_XOF, NULL), + OSSL_PARAM_size_t(OSSL_MAC_PARAM_SIZE, NULL), + OSSL_PARAM_octet_string(OSSL_MAC_PARAM_KEY, NULL, 0), + OSSL_PARAM_octet_string(OSSL_MAC_PARAM_CUSTOM, NULL, 0), + OSSL_PARAM_END +}; +static const OSSL_PARAM *kmac_settable_ctx_params(void) +{ + return known_settable_ctx_params; +} + +/* + * The following params can be set any time before final(): + * - "outlen" or "size": The requested output length. + * - "xof": If set, this indicates that right_encoded(0) + * is part of the digested data, otherwise it + * uses right_encoded(requested output length). + * + * All other params should be set before init(). + */ +static int kmac_set_ctx_params(void *vmacctx, const OSSL_PARAM *params) +{ + struct kmac_data_st *kctx = vmacctx; + const OSSL_PARAM *p; + const EVP_MD *digest = ossl_prov_digest_md(&kctx->digest); + + if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_XOF)) != NULL + && !OSSL_PARAM_get_int(p, &kctx->xof_mode)) + return 0; + if (((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_SIZE)) != NULL) + && !OSSL_PARAM_get_size_t(p, &kctx->out_len)) + return 0; + if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_KEY)) != NULL) { + if (p->data_size < 4 || p->data_size > KMAC_MAX_KEY) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH); + return 0; + } + if (!kmac_bytepad_encode_key(kctx->key, &kctx->key_len, + p->data, p->data_size, + EVP_MD_block_size(digest))) + return 0; + } + if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_CUSTOM)) + != NULL) { + if (p->data_size > KMAC_MAX_CUSTOM) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_CUSTOM_LENGTH); + return 0; + } + if (!encode_string(kctx->custom, &kctx->custom_len, + p->data, p->data_size)) + return 0; + } + return 1; +} + +/* + * Encoding/Padding Methods. + */ + +/* Returns the number of bytes required to store 'bits' into a byte array */ +static unsigned int get_encode_size(size_t bits) +{ + unsigned int cnt = 0, sz = sizeof(size_t); + + while (bits && (cnt < sz)) { + ++cnt; + bits >>= 8; + } + /* If bits is zero 1 byte is required */ + if (cnt == 0) + cnt = 1; + return cnt; +} + +/* + * Convert an integer into bytes . The number of bytes is appended + * to the end of the buffer. Returns an array of bytes 'out' of size + * *out_len. + * + * e.g if bits = 32, out[2] = { 0x20, 0x01 } + * + */ +static int right_encode(unsigned char *out, int *out_len, size_t bits) +{ + unsigned int len = get_encode_size(bits); + int i; + + /* The length is constrained to a single byte: 2040/8 = 255 */ + if (len > 0xFF) + return 0; + + /* MSB's are at the start of the bytes array */ + for (i = len - 1; i >= 0; --i) { + out[i] = (unsigned char)(bits & 0xFF); + bits >>= 8; + } + /* Tack the length onto the end */ + out[len] = (unsigned char)len; + + /* The Returned length includes the tacked on byte */ + *out_len = len + 1; + return 1; +} + +/* + * Encodes a string with a left encoded length added. Note that the + * in_len is converted to bits (*8). + * + * e.g- in="KMAC" gives out[6] = { 0x01, 0x20, 0x4B, 0x4D, 0x41, 0x43 } + * len bits K M A C + */ +static int encode_string(unsigned char *out, int *out_len, + const unsigned char *in, int in_len) +{ + if (in == NULL) { + *out_len = 0; + } else { + int i, bits, len; + + bits = 8 * in_len; + len = get_encode_size(bits); + if (len > 0xFF) + return 0; + + out[0] = len; + for (i = len; i > 0; --i) { + out[i] = (bits & 0xFF); + bits >>= 8; + } + memcpy(out + len + 1, in, in_len); + *out_len = (1 + len + in_len); + } + return 1; +} + +/* + * Returns a zero padded encoding of the inputs in1 and an optional + * in2 (can be NULL). The padded output must be a multiple of the blocksize 'w'. + * The value of w is in bytes (< 256). + * + * The returned output is: + * zero_padded(multiple of w, (left_encode(w) || in1 [|| in2]) + */ +static int bytepad(unsigned char *out, int *out_len, + const unsigned char *in1, int in1_len, + const unsigned char *in2, int in2_len, int w) +{ + int len; + unsigned char *p = out; + int sz = w; + + /* Left encoded w */ + *p++ = 1; + *p++ = w; + /* || in1 */ + memcpy(p, in1, in1_len); + p += in1_len; + /* [ || in2 ] */ + if (in2 != NULL && in2_len > 0) { + memcpy(p, in2, in2_len); + p += in2_len; + } + /* Figure out the pad size (divisible by w) */ + len = p - out; + while (len > sz) { + sz += w; + } + /* zero pad the end of the buffer */ + memset(p, 0, sz - len); + *out_len = sz; + return 1; +} + +/* + * Returns out = bytepad(encode_string(in), w) + */ +static int kmac_bytepad_encode_key(unsigned char *out, int *out_len, + const unsigned char *in, int in_len, + int w) +{ + unsigned char tmp[KMAC_MAX_KEY + KMAC_MAX_ENCODED_HEADER_LEN]; + int tmp_len; + + if (!encode_string(tmp, &tmp_len, in, in_len)) + return 0; + + return bytepad(out, out_len, tmp, tmp_len, NULL, 0, w); +} + +const OSSL_DISPATCH kmac128_functions[] = { + { OSSL_FUNC_MAC_NEWCTX, (void (*)(void))kmac128_new }, + { OSSL_FUNC_MAC_DUPCTX, (void (*)(void))kmac_dup }, + { OSSL_FUNC_MAC_FREECTX, (void (*)(void))kmac_free }, + { OSSL_FUNC_MAC_INIT, (void (*)(void))kmac_init }, + { OSSL_FUNC_MAC_UPDATE, (void (*)(void))kmac_update }, + { OSSL_FUNC_MAC_FINAL, (void (*)(void))kmac_final }, + { OSSL_FUNC_MAC_GETTABLE_CTX_PARAMS, + (void (*)(void))kmac_gettable_ctx_params }, + { OSSL_FUNC_MAC_GET_CTX_PARAMS, (void (*)(void))kmac_get_ctx_params }, + { OSSL_FUNC_MAC_SETTABLE_CTX_PARAMS, + (void (*)(void))kmac_settable_ctx_params }, + { OSSL_FUNC_MAC_SET_CTX_PARAMS, (void (*)(void))kmac_set_ctx_params }, + { 0, NULL } +}; + +const OSSL_DISPATCH kmac256_functions[] = { + { OSSL_FUNC_MAC_NEWCTX, (void (*)(void))kmac256_new }, + { OSSL_FUNC_MAC_DUPCTX, (void (*)(void))kmac_dup }, + { OSSL_FUNC_MAC_FREECTX, (void (*)(void))kmac_free }, + { OSSL_FUNC_MAC_INIT, (void (*)(void))kmac_init }, + { OSSL_FUNC_MAC_UPDATE, (void (*)(void))kmac_update }, + { OSSL_FUNC_MAC_FINAL, (void (*)(void))kmac_final }, + { OSSL_FUNC_MAC_GETTABLE_CTX_PARAMS, + (void (*)(void))kmac_gettable_ctx_params }, + { OSSL_FUNC_MAC_GET_CTX_PARAMS, (void (*)(void))kmac_get_ctx_params }, + { OSSL_FUNC_MAC_SETTABLE_CTX_PARAMS, + (void (*)(void))kmac_settable_ctx_params }, + { OSSL_FUNC_MAC_SET_CTX_PARAMS, (void (*)(void))kmac_set_ctx_params }, + { 0, NULL } +}; diff --git a/providers/implementations/signature/build.info b/providers/implementations/signature/build.info new file mode 100644 index 0000000000..a9687fc929 --- /dev/null +++ b/providers/implementations/signature/build.info @@ -0,0 +1,10 @@ +# We make separate GOAL variables for each algorithm, to make it easy to +# switch each to the Legacy provider when needed. + +$DSA_GOAL=../../libimplementations.a + +IF[{- !$disabled{dsa} -}] + SOURCE[$DSA_GOAL]=dsa.c +ENDIF + + diff --git a/providers/implementations/signature/dsa.c b/providers/implementations/signature/dsa.c new file mode 100644 index 0000000000..1d6b565d38 --- /dev/null +++ b/providers/implementations/signature/dsa.c @@ -0,0 +1,407 @@ +/* + * Copyright 2019 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 + */ + +#include +#include +#include +#include +#include +#include +#include "internal/provider_algs.h" +#include "internal/provider_ctx.h" + +static OSSL_OP_signature_newctx_fn dsa_newctx; +static OSSL_OP_signature_sign_init_fn dsa_signature_init; +static OSSL_OP_signature_verify_init_fn dsa_signature_init; +static OSSL_OP_signature_sign_fn dsa_sign; +static OSSL_OP_signature_verify_fn dsa_verify; +static OSSL_OP_signature_digest_sign_init_fn dsa_digest_signverify_init; +static OSSL_OP_signature_digest_sign_update_fn dsa_digest_signverify_update; +static OSSL_OP_signature_digest_sign_final_fn dsa_digest_sign_final; +static OSSL_OP_signature_digest_verify_init_fn dsa_digest_signverify_init; +static OSSL_OP_signature_digest_verify_update_fn dsa_digest_signverify_update; +static OSSL_OP_signature_digest_verify_final_fn dsa_digest_verify_final; +static OSSL_OP_signature_freectx_fn dsa_freectx; +static OSSL_OP_signature_dupctx_fn dsa_dupctx; +static OSSL_OP_signature_get_ctx_params_fn dsa_get_ctx_params; +static OSSL_OP_signature_gettable_ctx_params_fn dsa_gettable_ctx_params; +static OSSL_OP_signature_set_ctx_params_fn dsa_set_ctx_params; +static OSSL_OP_signature_settable_ctx_params_fn dsa_settable_ctx_params; +static OSSL_OP_signature_get_ctx_md_params_fn dsa_get_ctx_md_params; +static OSSL_OP_signature_gettable_ctx_md_params_fn dsa_gettable_ctx_md_params; +static OSSL_OP_signature_set_ctx_md_params_fn dsa_set_ctx_md_params; +static OSSL_OP_signature_settable_ctx_md_params_fn dsa_settable_ctx_md_params; + +/* + * What's passed as an actual key is defined by the KEYMGMT interface. + * We happen to know that our KEYMGMT simply passes DSA structures, so + * we use that here too. + */ + +typedef struct { + OPENSSL_CTX *libctx; + DSA *dsa; + size_t mdsize; + /* Should be big enough */ + char mdname[80]; + EVP_MD *md; + EVP_MD_CTX *mdctx; +} PROV_DSA_CTX; + +static void *dsa_newctx(void *provctx) +{ + PROV_DSA_CTX *pdsactx = OPENSSL_zalloc(sizeof(PROV_DSA_CTX)); + + if (pdsactx == NULL) + return NULL; + + pdsactx->libctx = PROV_LIBRARY_CONTEXT_OF(provctx); + return pdsactx; +} + +static int dsa_signature_init(void *vpdsactx, void *vdsa) +{ + PROV_DSA_CTX *pdsactx = (PROV_DSA_CTX *)vpdsactx; + + if (pdsactx == NULL || vdsa == NULL || !DSA_up_ref(vdsa)) + return 0; + DSA_free(pdsactx->dsa); + pdsactx->dsa = vdsa; + return 1; +} + +static int dsa_sign(void *vpdsactx, unsigned char *sig, size_t *siglen, + size_t sigsize, const unsigned char *tbs, size_t tbslen) +{ + PROV_DSA_CTX *pdsactx = (PROV_DSA_CTX *)vpdsactx; + int ret; + unsigned int sltmp; + size_t dsasize = DSA_size(pdsactx->dsa); + + if (sig == NULL) { + *siglen = dsasize; + return 1; + } + + if (sigsize < (size_t)dsasize) + return 0; + + if (pdsactx->mdsize != 0 && tbslen != pdsactx->mdsize) + return 0; + + ret = DSA_sign(0, tbs, tbslen, sig, &sltmp, pdsactx->dsa); + + if (ret <= 0) + return 0; + + *siglen = sltmp; + return 1; +} + +static int dsa_verify(void *vpdsactx, const unsigned char *sig, size_t siglen, + const unsigned char *tbs, size_t tbslen) +{ + PROV_DSA_CTX *pdsactx = (PROV_DSA_CTX *)vpdsactx; + + if (pdsactx->mdsize != 0 && tbslen != pdsactx->mdsize) + return 0; + + return DSA_verify(0, tbs, tbslen, sig, siglen, pdsactx->dsa); +} + +static int dsa_digest_signverify_init(void *vpdsactx, const char *mdname, + const char *props, void *vdsa) +{ + PROV_DSA_CTX *pdsactx = (PROV_DSA_CTX *)vpdsactx; + EVP_MD *md; + + if (!dsa_signature_init(vpdsactx, vdsa)) + return 0; + + md = EVP_MD_fetch(pdsactx->libctx, mdname, props); + if (md == NULL) + return 0; + pdsactx->md = md; + pdsactx->mdsize = EVP_MD_size(md); + pdsactx->mdctx = EVP_MD_CTX_new(); + if (pdsactx->mdctx == NULL) + return 0; + + if (!EVP_DigestInit_ex(pdsactx->mdctx, md, NULL)) + return 0; + + return 1; +} + +int dsa_digest_signverify_update(void *vpdsactx, const unsigned char *data, + size_t datalen) +{ + PROV_DSA_CTX *pdsactx = (PROV_DSA_CTX *)vpdsactx; + + if (pdsactx == NULL || pdsactx->mdctx == NULL) + return 0; + + return EVP_DigestUpdate(pdsactx->mdctx, data, datalen); +} + +int dsa_digest_sign_final(void *vpdsactx, unsigned char *sig, size_t *siglen, + size_t sigsize) +{ + PROV_DSA_CTX *pdsactx = (PROV_DSA_CTX *)vpdsactx; + unsigned char digest[EVP_MAX_MD_SIZE]; + unsigned int dlen = 0; + + if (pdsactx == NULL || pdsactx->mdctx == NULL) + return 0; + + /* + * If sig is NULL then we're just finding out the sig size. Other fields + * are ignored. Defer to dsa_sign. + */ + if (sig != NULL) { + /* + * TODO(3.0): There is the possibility that some externally provided + * digests exceed EVP_MAX_MD_SIZE. We should probably handle that somehow - + * but that problem is much larger than just in DSA. + */ + if (!EVP_DigestFinal_ex(pdsactx->mdctx, digest, &dlen)) + return 0; + } + + return dsa_sign(vpdsactx, sig, siglen, sigsize, digest, (size_t)dlen); +} + + +int dsa_digest_verify_final(void *vpdsactx, const unsigned char *sig, + size_t siglen) +{ + PROV_DSA_CTX *pdsactx = (PROV_DSA_CTX *)vpdsactx; + unsigned char digest[EVP_MAX_MD_SIZE]; + unsigned int dlen = 0; + + if (pdsactx == NULL || pdsactx->mdctx == NULL) + return 0; + + /* + * TODO(3.0): There is the possibility that some externally provided + * digests exceed EVP_MAX_MD_SIZE. We should probably handle that somehow - + * but that problem is much larger than just in DSA. + */ + if (!EVP_DigestFinal_ex(pdsactx->mdctx, digest, &dlen)) + return 0; + + return dsa_verify(vpdsactx, sig, siglen, digest, (size_t)dlen); +} + +static void dsa_freectx(void *vpdsactx) +{ + PROV_DSA_CTX *pdsactx = (PROV_DSA_CTX *)vpdsactx; + + DSA_free(pdsactx->dsa); + EVP_MD_CTX_free(pdsactx->mdctx); + EVP_MD_free(pdsactx->md); + + OPENSSL_free(pdsactx); +} + +static void *dsa_dupctx(void *vpdsactx) +{ + PROV_DSA_CTX *srcctx = (PROV_DSA_CTX *)vpdsactx; + PROV_DSA_CTX *dstctx; + + dstctx = OPENSSL_zalloc(sizeof(*srcctx)); + if (dstctx == NULL) + return NULL; + + *dstctx = *srcctx; + dstctx->dsa = NULL; + dstctx->md = NULL; + dstctx->mdctx = NULL; + + if (srcctx->dsa != NULL && !DSA_up_ref(srcctx->dsa)) + goto err; + dstctx->dsa = srcctx->dsa; + + if (srcctx->md != NULL && !EVP_MD_up_ref(srcctx->md)) + goto err; + dstctx->md = srcctx->md; + + if (srcctx->mdctx != NULL) { + dstctx->mdctx = EVP_MD_CTX_new(); + if (dstctx->mdctx == NULL + || !EVP_MD_CTX_copy_ex(dstctx->mdctx, srcctx->mdctx)) + goto err; + } + + return dstctx; + err: + dsa_freectx(dstctx); + return NULL; +} + +static int dsa_get_ctx_params(void *vpdsactx, OSSL_PARAM *params) +{ + PROV_DSA_CTX *pdsactx = (PROV_DSA_CTX *)vpdsactx; + OSSL_PARAM *p; + + if (pdsactx == NULL || params == NULL) + return 0; + + p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_DIGEST_SIZE); + if (p != NULL && !OSSL_PARAM_set_size_t(p, pdsactx->mdsize)) + return 0; + + p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_DIGEST); + if (p != NULL && !OSSL_PARAM_set_utf8_string(p, pdsactx->md == NULL + ? pdsactx->mdname + : EVP_MD_name(pdsactx->md))) + return 0; + + return 1; +} + +static const OSSL_PARAM known_gettable_ctx_params[] = { + OSSL_PARAM_size_t(OSSL_SIGNATURE_PARAM_DIGEST_SIZE, NULL), + OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST, NULL, 0), + OSSL_PARAM_END +}; + +static const OSSL_PARAM *dsa_gettable_ctx_params(void) +{ + return known_gettable_ctx_params; +} + +static int dsa_set_ctx_params(void *vpdsactx, const OSSL_PARAM params[]) +{ + PROV_DSA_CTX *pdsactx = (PROV_DSA_CTX *)vpdsactx; + const OSSL_PARAM *p; + char *mdname; + + if (pdsactx == NULL || params == NULL) + return 0; + + if (pdsactx->md != NULL) { + /* + * You cannot set the digest name/size when doing a DigestSign or + * DigestVerify. + */ + return 1; + } + + p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_DIGEST_SIZE); + if (p != NULL && !OSSL_PARAM_get_size_t(p, &pdsactx->mdsize)) + return 0; + + /* + * We never actually use the mdname, but we do support getting it later. + * This can be useful for applications that want to know the MD that they + * previously set. + */ + p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_DIGEST); + mdname = pdsactx->mdname; + if (p != NULL + && !OSSL_PARAM_get_utf8_string(p, &mdname, sizeof(pdsactx->mdname))) + return 0; + + return 1; +} + +static const OSSL_PARAM known_settable_ctx_params[] = { + OSSL_PARAM_size_t(OSSL_SIGNATURE_PARAM_DIGEST_SIZE, NULL), + OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST, NULL, 0), + OSSL_PARAM_END +}; + +static const OSSL_PARAM *dsa_settable_ctx_params(void) +{ + /* + * TODO(3.0): Should this function return a different set of settable ctx + * params if the ctx is being used for a DigestSign/DigestVerify? In that + * case it is not allowed to set the digest size/digest name because the + * digest is explicitly set as part of the init. + */ + return known_settable_ctx_params; +} + +static int dsa_get_ctx_md_params(void *vpdsactx, OSSL_PARAM *params) +{ + PROV_DSA_CTX *pdsactx = (PROV_DSA_CTX *)vpdsactx; + + if (pdsactx->mdctx == NULL) + return 0; + + return EVP_MD_CTX_get_params(pdsactx->mdctx, params); +} + +static const OSSL_PARAM *dsa_gettable_ctx_md_params(void *vpdsactx) +{ + PROV_DSA_CTX *pdsactx = (PROV_DSA_CTX *)vpdsactx; + + if (pdsactx->md == NULL) + return 0; + + return EVP_MD_gettable_ctx_params(pdsactx->md); +} + +static int dsa_set_ctx_md_params(void *vpdsactx, const OSSL_PARAM params[]) +{ + PROV_DSA_CTX *pdsactx = (PROV_DSA_CTX *)vpdsactx; + + if (pdsactx->mdctx == NULL) + return 0; + + return EVP_MD_CTX_set_params(pdsactx->mdctx, params); +} + +static const OSSL_PARAM *dsa_settable_ctx_md_params(void *vpdsactx) +{ + PROV_DSA_CTX *pdsactx = (PROV_DSA_CTX *)vpdsactx; + + if (pdsactx->md == NULL) + return 0; + + return EVP_MD_settable_ctx_params(pdsactx->md); +} + +const OSSL_DISPATCH dsa_signature_functions[] = { + { OSSL_FUNC_SIGNATURE_NEWCTX, (void (*)(void))dsa_newctx }, + { OSSL_FUNC_SIGNATURE_SIGN_INIT, (void (*)(void))dsa_signature_init }, + { OSSL_FUNC_SIGNATURE_SIGN, (void (*)(void))dsa_sign }, + { OSSL_FUNC_SIGNATURE_VERIFY_INIT, (void (*)(void))dsa_signature_init }, + { OSSL_FUNC_SIGNATURE_VERIFY, (void (*)(void))dsa_verify }, + { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT, + (void (*)(void))dsa_digest_signverify_init }, + { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_UPDATE, + (void (*)(void))dsa_digest_signverify_update }, + { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_FINAL, + (void (*)(void))dsa_digest_sign_final }, + { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT, + (void (*)(void))dsa_digest_signverify_init }, + { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_UPDATE, + (void (*)(void))dsa_digest_signverify_update }, + { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_FINAL, + (void (*)(void))dsa_digest_verify_final }, + { OSSL_FUNC_SIGNATURE_FREECTX, (void (*)(void))dsa_freectx }, + { OSSL_FUNC_SIGNATURE_DUPCTX, (void (*)(void))dsa_dupctx }, + { OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS, (void (*)(void))dsa_get_ctx_params }, + { OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS, + (void (*)(void))dsa_gettable_ctx_params }, + { OSSL_FUNC_SIGNATURE_SET_CTX_PARAMS, (void (*)(void))dsa_set_ctx_params }, + { OSSL_FUNC_SIGNATURE_SETTABLE_CTX_PARAMS, + (void (*)(void))dsa_settable_ctx_params }, + { OSSL_FUNC_SIGNATURE_GET_CTX_MD_PARAMS, + (void (*)(void))dsa_get_ctx_md_params }, + { OSSL_FUNC_SIGNATURE_GETTABLE_CTX_MD_PARAMS, + (void (*)(void))dsa_gettable_ctx_md_params }, + { OSSL_FUNC_SIGNATURE_SET_CTX_MD_PARAMS, + (void (*)(void))dsa_set_ctx_md_params }, + { OSSL_FUNC_SIGNATURE_SETTABLE_CTX_MD_PARAMS, + (void (*)(void))dsa_settable_ctx_md_params }, + { 0, NULL } +};