# FIPS_MODE undefined. The default and legacy
# providers use this.
-SUBDIRS=common default
+SUBDIRS=common default implementations
INCLUDE[../libcrypto]=common/include
-SUBDIRS=digests ciphers macs kdfs exchange keymgmt signature
+SUBDIRS=digests ciphers
SOURCE[../libcommon.a]=provider_err.c provlib.c
$FIPSCOMMON=provider_util.c
+++ /dev/null
-$GOAL=../../libimplementations.a
-
-IF[{- !$disabled{dh} -}]
- SOURCE[$GOAL]=dh_exch.c
-ENDIF
+++ /dev/null
-/*
- * 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 <openssl/crypto.h>
-#include <openssl/core_numbers.h>
-#include <openssl/core_names.h>
-#include <openssl/dh.h>
-#include <openssl/params.h>
-#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 }
-};
+++ /dev/null
-$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
+++ /dev/null
-/*
- * 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 <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <openssl/hmac.h>
-#include <openssl/evp.h>
-#include <openssl/kdf.h>
-#include <openssl/core_names.h>
-#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;
-}
+++ /dev/null
-/*
- * 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 <stdarg.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <openssl/core_names.h>
-#include <openssl/evp.h>
-#include <openssl/hmac.h>
-#include <openssl/kdf.h>
-#include <openssl/params.h>
-
-#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 },
-};
+++ /dev/null
-/*
- * 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 <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <openssl/hmac.h>
-#include <openssl/evp.h>
-#include <openssl/kdf.h>
-#include <openssl/core_names.h>
-#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;
-}
+++ /dev/null
-/*
- * 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;
+++ /dev/null
-/*
- * 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 */
+++ /dev/null
-/*
- * 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 <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <openssl/hmac.h>
-#include <openssl/evp.h>
-#include <openssl/kdf.h>
-#include <openssl/core_names.h>
-#include <openssl/params.h>
-#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 }
-};
+++ /dev/null
-/*
- * 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_<hash>, 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_<hash>(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_<hash> is an expansion function that uses a single hash function to expand
- * a secret and seed into an arbitrary quantity of output:
- *
- * P_<hash>(secret, seed) = HMAC_<hash>(secret, A(1) + seed) +
- * HMAC_<hash>(secret, A(2) + seed) +
- * HMAC_<hash>(secret, A(3) + seed) + ...
- *
- * where + indicates concatenation. P_<hash> 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_<hash>(secret, A(i-1))
- */
-#include <stdio.h>
-#include <stdarg.h>
-#include <string.h>
-#include <openssl/evp.h>
-#include <openssl/kdf.h>
-#include <openssl/core_names.h>
-#include <openssl/params.h>
-#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_<hash> is an expansion function that uses a single hash function to expand
- * a secret and seed into an arbitrary quantity of output:
- *
- * P_<hash>(secret, seed) = HMAC_<hash>(secret, A(1) + seed) +
- * HMAC_<hash>(secret, A(2) + seed) +
- * HMAC_<hash>(secret, A(3) + seed) + ...
- *
- * where + indicates concatenation. P_<hash> 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_<hash>(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_<hash>(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_<hash>(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_<hash>(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;
-}
+++ /dev/null
-$GOAL=../../libimplementations.a
-
-IF[{- !$disabled{dh} -}]
- SOURCE[$GOAL]=dh_kmgmt.c
-ENDIF
-IF[{- !$disabled{dsa} -}]
- SOURCE[$GOAL]=dsa_kmgmt.c
-ENDIF
+++ /dev/null
-/*
- * 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 <openssl/core_numbers.h>
-#include <openssl/core_names.h>
-#include <openssl/bn.h>
-#include <openssl/dh.h>
-#include <openssl/params.h>
-#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 }
-};
+++ /dev/null
-/*
- * 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 <openssl/core_numbers.h>
-#include <openssl/core_names.h>
-#include <openssl/bn.h>
-#include <openssl/dsa.h>
-#include <openssl/params.h>
-#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 }
-};
+++ /dev/null
-$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
+++ /dev/null
-/*
- * 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 <openssl/core_numbers.h>
-#include <openssl/core_names.h>
-#include <openssl/params.h>
-#include <openssl/engine.h>
-#include <openssl/evp.h>
-#include <openssl/cmac.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 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 }
-};
+++ /dev/null
-/*
- * 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 <stdlib.h>
-#include <openssl/core_numbers.h>
-#include <openssl/core_names.h>
-#include <openssl/params.h>
-#include <openssl/engine.h>
-#include <openssl/evp.h>
-#include <openssl/err.h>
-
-#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 }
-};
+++ /dev/null
-/*
- * 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 <openssl/core_numbers.h>
-#include <openssl/core_names.h>
-#include <openssl/params.h>
-#include <openssl/engine.h>
-#include <openssl/evp.h>
-#include <openssl/hmac.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 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 }
-};
+++ /dev/null
-/*
- * 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 <stdlib.h>
-#include <string.h>
-#include <openssl/core_numbers.h>
-#include <openssl/core_names.h>
-#include <openssl/params.h>
-#include <openssl/evp.h>
-#include <openssl/err.h>
-
-#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 }
-};
+++ /dev/null
-$GOAL=../../libimplementations.a
-
-IF[{- !$disabled{dsa} -}]
- SOURCE[$GOAL]=dsa.c
-ENDIF
-
-
+++ /dev/null
-/*
- * 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 <openssl/crypto.h>
-#include <openssl/core_numbers.h>
-#include <openssl/core_names.h>
-#include <openssl/dsa.h>
-#include <openssl/params.h>
-#include <openssl/evp.h>
-#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 }
-};
--- /dev/null
+SUBDIRS=macs kdfs exchange keymgmt signature
--- /dev/null
+# 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
--- /dev/null
+/*
+ * 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 <openssl/crypto.h>
+#include <openssl/core_numbers.h>
+#include <openssl/core_names.h>
+#include <openssl/dh.h>
+#include <openssl/params.h>
+#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 }
+};
--- /dev/null
+# 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
--- /dev/null
+/*
+ * 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 <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <openssl/hmac.h>
+#include <openssl/evp.h>
+#include <openssl/kdf.h>
+#include <openssl/core_names.h>
+#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;
+}
--- /dev/null
+/*
+ * 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 <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <openssl/core_names.h>
+#include <openssl/evp.h>
+#include <openssl/hmac.h>
+#include <openssl/kdf.h>
+#include <openssl/params.h>
+
+#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 },
+};
--- /dev/null
+/*
+ * 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 <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <openssl/hmac.h>
+#include <openssl/evp.h>
+#include <openssl/kdf.h>
+#include <openssl/core_names.h>
+#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;
+}
--- /dev/null
+/*
+ * 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;
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/*
+ * 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 <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <openssl/hmac.h>
+#include <openssl/evp.h>
+#include <openssl/kdf.h>
+#include <openssl/core_names.h>
+#include <openssl/params.h>
+#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 }
+};
--- /dev/null
+/*
+ * 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_<hash>, 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_<hash>(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_<hash> is an expansion function that uses a single hash function to expand
+ * a secret and seed into an arbitrary quantity of output:
+ *
+ * P_<hash>(secret, seed) = HMAC_<hash>(secret, A(1) + seed) +
+ * HMAC_<hash>(secret, A(2) + seed) +
+ * HMAC_<hash>(secret, A(3) + seed) + ...
+ *
+ * where + indicates concatenation. P_<hash> 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_<hash>(secret, A(i-1))
+ */
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <openssl/evp.h>
+#include <openssl/kdf.h>
+#include <openssl/core_names.h>
+#include <openssl/params.h>
+#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_<hash> is an expansion function that uses a single hash function to expand
+ * a secret and seed into an arbitrary quantity of output:
+ *
+ * P_<hash>(secret, seed) = HMAC_<hash>(secret, A(1) + seed) +
+ * HMAC_<hash>(secret, A(2) + seed) +
+ * HMAC_<hash>(secret, A(3) + seed) + ...
+ *
+ * where + indicates concatenation. P_<hash> 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_<hash>(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_<hash>(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_<hash>(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_<hash>(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;
+}
--- /dev/null
+# 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
--- /dev/null
+/*
+ * 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 <openssl/core_numbers.h>
+#include <openssl/core_names.h>
+#include <openssl/bn.h>
+#include <openssl/dh.h>
+#include <openssl/params.h>
+#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 }
+};
--- /dev/null
+/*
+ * 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 <openssl/core_numbers.h>
+#include <openssl/core_names.h>
+#include <openssl/bn.h>
+#include <openssl/dsa.h>
+#include <openssl/params.h>
+#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 }
+};
--- /dev/null
+# 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
--- /dev/null
+/*
+ * 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 <openssl/core_numbers.h>
+#include <openssl/core_names.h>
+#include <openssl/params.h>
+#include <openssl/engine.h>
+#include <openssl/evp.h>
+#include <openssl/cmac.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 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 }
+};
--- /dev/null
+/*
+ * 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 <stdlib.h>
+#include <openssl/core_numbers.h>
+#include <openssl/core_names.h>
+#include <openssl/params.h>
+#include <openssl/engine.h>
+#include <openssl/evp.h>
+#include <openssl/err.h>
+
+#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 }
+};
--- /dev/null
+/*
+ * 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 <openssl/core_numbers.h>
+#include <openssl/core_names.h>
+#include <openssl/params.h>
+#include <openssl/engine.h>
+#include <openssl/evp.h>
+#include <openssl/hmac.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 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 }
+};
--- /dev/null
+/*
+ * 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 <stdlib.h>
+#include <string.h>
+#include <openssl/core_numbers.h>
+#include <openssl/core_names.h>
+#include <openssl/params.h>
+#include <openssl/evp.h>
+#include <openssl/err.h>
+
+#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 }
+};
--- /dev/null
+# 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
+
+
--- /dev/null
+/*
+ * 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 <openssl/crypto.h>
+#include <openssl/core_numbers.h>
+#include <openssl/core_names.h>
+#include <openssl/dsa.h>
+#include <openssl/params.h>
+#include <openssl/evp.h>
+#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 }
+};