From: Richard Levitte Date: Fri, 4 Oct 2019 09:28:20 +0000 (+0200) Subject: Providers: move default kdfs,macs X-Git-Tag: openssl-3.0.0-alpha1~1171 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=e42cf7180b4fb32e985f15484e04c7fb8afc11ab;p=oweals%2Fopenssl.git Providers: move default kdfs,macs From providers/default/ to providers/implementations/ Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/10088) --- diff --git a/providers/default/build.info b/providers/default/build.info index 31ae507965..67b4d3a977 100644 --- a/providers/default/build.info +++ b/providers/default/build.info @@ -1,4 +1,4 @@ -SUBDIRS=digests kdfs macs ciphers +SUBDIRS=digests ciphers $GOAL=../../libcrypto SOURCE[$GOAL]=defltprov.c INCLUDE[$GOAL]=include diff --git a/providers/default/kdfs/build.info b/providers/default/kdfs/build.info deleted file mode 100644 index 90b127d731..0000000000 --- a/providers/default/kdfs/build.info +++ /dev/null @@ -1,2 +0,0 @@ -$GOAL=../../libimplementations.a -SOURCE[$GOAL]=scrypt.c sshkdf.c x942kdf.c diff --git a/providers/default/kdfs/scrypt.c b/providers/default/kdfs/scrypt.c deleted file mode 100644 index 505963eec5..0000000000 --- a/providers/default/kdfs/scrypt.c +++ /dev/null @@ -1,463 +0,0 @@ -/* - * Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved. - * - * Licensed under the Apache License 2.0 (the "License"). You may not use - * this file except in compliance with the License. You can obtain a copy - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ - -#include -#include -#include -#include -#include -#include -#include -#include "crypto/evp.h" -#include "internal/numbers.h" -#include "internal/provider_algs.h" -#include "internal/provider_ctx.h" -#include "internal/providercommonerr.h" -#include "internal/provider_algs.h" - -#ifndef OPENSSL_NO_SCRYPT - -static OSSL_OP_kdf_newctx_fn kdf_scrypt_new; -static OSSL_OP_kdf_freectx_fn kdf_scrypt_free; -static OSSL_OP_kdf_reset_fn kdf_scrypt_reset; -static OSSL_OP_kdf_derive_fn kdf_scrypt_derive; -static OSSL_OP_kdf_settable_ctx_params_fn kdf_scrypt_settable_ctx_params; -static OSSL_OP_kdf_set_ctx_params_fn kdf_scrypt_set_ctx_params; - -static int scrypt_alg(const char *pass, size_t passlen, - const unsigned char *salt, size_t saltlen, - uint64_t N, uint64_t r, uint64_t p, uint64_t maxmem, - unsigned char *key, size_t keylen, EVP_MD *sha256); - -typedef struct { - void *provctx; - unsigned char *pass; - size_t pass_len; - unsigned char *salt; - size_t salt_len; - uint64_t N; - uint64_t r, p; - uint64_t maxmem_bytes; - EVP_MD *sha256; -} KDF_SCRYPT; - -static void kdf_scrypt_init(KDF_SCRYPT *ctx); - -static void *kdf_scrypt_new(void *provctx) -{ - KDF_SCRYPT *ctx; - - ctx = OPENSSL_zalloc(sizeof(*ctx)); - if (ctx == NULL) { - ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); - return NULL; - } - ctx->provctx = provctx; - ctx->sha256 = EVP_MD_fetch(PROV_LIBRARY_CONTEXT_OF(provctx), - "sha256", NULL); - if (ctx->sha256 == NULL) { - OPENSSL_free(ctx); - ERR_raise(ERR_LIB_PROV, PROV_R_UNABLE_TO_LOAD_SHA256); - return NULL; - } - kdf_scrypt_init(ctx); - return ctx; -} - -static void kdf_scrypt_free(void *vctx) -{ - KDF_SCRYPT *ctx = (KDF_SCRYPT *)vctx; - - EVP_MD_meth_free(ctx->sha256); - kdf_scrypt_reset(ctx); - OPENSSL_free(ctx); -} - -static void kdf_scrypt_reset(void *vctx) -{ - KDF_SCRYPT *ctx = (KDF_SCRYPT *)vctx; - - OPENSSL_free(ctx->salt); - OPENSSL_clear_free(ctx->pass, ctx->pass_len); - kdf_scrypt_init(ctx); -} - -static void kdf_scrypt_init(KDF_SCRYPT *ctx) -{ - /* Default values are the most conservative recommendation given in the - * original paper of C. Percival. Derivation uses roughly 1 GiB of memory - * for this parameter choice (approx. 128 * r * N * p bytes). - */ - ctx->N = 1 << 20; - ctx->r = 8; - ctx->p = 1; - ctx->maxmem_bytes = 1025 * 1024 * 1024; -} - -static int scrypt_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_scrypt_derive(void *vctx, unsigned char *key, - size_t keylen) -{ - KDF_SCRYPT *ctx = (KDF_SCRYPT *)vctx; - - 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 scrypt_alg((char *)ctx->pass, ctx->pass_len, ctx->salt, - ctx->salt_len, ctx->N, ctx->r, ctx->p, - ctx->maxmem_bytes, key, keylen, ctx->sha256); -} - -static int is_power_of_two(uint64_t value) -{ - return (value != 0) && ((value & (value - 1)) == 0); -} - -static int kdf_scrypt_set_ctx_params(void *vctx, const OSSL_PARAM params[]) -{ - const OSSL_PARAM *p; - KDF_SCRYPT *ctx = vctx; - uint64_t u64_value; - - if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PASSWORD)) != NULL) - if (!scrypt_set_membuf(&ctx->pass, &ctx->pass_len, p)) - return 0; - - if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SALT)) != NULL) - if (!scrypt_set_membuf(&ctx->salt, &ctx->salt_len, p)) - return 0; - - if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SCRYPT_N)) - != NULL) { - if (!OSSL_PARAM_get_uint64(p, &u64_value) - || u64_value <= 1 - || !is_power_of_two(u64_value)) - return 0; - ctx->N = u64_value; - } - - if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SCRYPT_R)) - != NULL) { - if (!OSSL_PARAM_get_uint64(p, &u64_value) || u64_value < 1) - return 0; - ctx->r = u64_value; - } - - if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SCRYPT_P)) - != NULL) { - if (!OSSL_PARAM_get_uint64(p, &u64_value) || u64_value < 1) - return 0; - ctx->p = u64_value; - } - - if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SCRYPT_MAXMEM)) - != NULL) { - if (!OSSL_PARAM_get_uint64(p, &u64_value) || u64_value < 1) - return 0; - ctx->maxmem_bytes = u64_value; - } - return 1; -} - -static const OSSL_PARAM *kdf_scrypt_settable_ctx_params(void) -{ - static const OSSL_PARAM known_settable_ctx_params[] = { - 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_SCRYPT_N, NULL), - OSSL_PARAM_uint32(OSSL_KDF_PARAM_SCRYPT_R, NULL), - OSSL_PARAM_uint32(OSSL_KDF_PARAM_SCRYPT_P, NULL), - OSSL_PARAM_uint64(OSSL_KDF_PARAM_SCRYPT_MAXMEM, NULL), - OSSL_PARAM_END - }; - return known_settable_ctx_params; -} - -static int kdf_scrypt_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_scrypt_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_scrypt_functions[] = { - { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))kdf_scrypt_new }, - { OSSL_FUNC_KDF_FREECTX, (void(*)(void))kdf_scrypt_free }, - { OSSL_FUNC_KDF_RESET, (void(*)(void))kdf_scrypt_reset }, - { OSSL_FUNC_KDF_DERIVE, (void(*)(void))kdf_scrypt_derive }, - { OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS, - (void(*)(void))kdf_scrypt_settable_ctx_params }, - { OSSL_FUNC_KDF_SET_CTX_PARAMS, (void(*)(void))kdf_scrypt_set_ctx_params }, - { OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS, - (void(*)(void))kdf_scrypt_gettable_ctx_params }, - { OSSL_FUNC_KDF_GET_CTX_PARAMS, (void(*)(void))kdf_scrypt_get_ctx_params }, - { 0, NULL } -}; - -#define R(a,b) (((a) << (b)) | ((a) >> (32 - (b)))) -static void salsa208_word_specification(uint32_t inout[16]) -{ - int i; - uint32_t x[16]; - - memcpy(x, inout, sizeof(x)); - for (i = 8; i > 0; i -= 2) { - x[4] ^= R(x[0] + x[12], 7); - x[8] ^= R(x[4] + x[0], 9); - x[12] ^= R(x[8] + x[4], 13); - x[0] ^= R(x[12] + x[8], 18); - x[9] ^= R(x[5] + x[1], 7); - x[13] ^= R(x[9] + x[5], 9); - x[1] ^= R(x[13] + x[9], 13); - x[5] ^= R(x[1] + x[13], 18); - x[14] ^= R(x[10] + x[6], 7); - x[2] ^= R(x[14] + x[10], 9); - x[6] ^= R(x[2] + x[14], 13); - x[10] ^= R(x[6] + x[2], 18); - x[3] ^= R(x[15] + x[11], 7); - x[7] ^= R(x[3] + x[15], 9); - x[11] ^= R(x[7] + x[3], 13); - x[15] ^= R(x[11] + x[7], 18); - x[1] ^= R(x[0] + x[3], 7); - x[2] ^= R(x[1] + x[0], 9); - x[3] ^= R(x[2] + x[1], 13); - x[0] ^= R(x[3] + x[2], 18); - x[6] ^= R(x[5] + x[4], 7); - x[7] ^= R(x[6] + x[5], 9); - x[4] ^= R(x[7] + x[6], 13); - x[5] ^= R(x[4] + x[7], 18); - x[11] ^= R(x[10] + x[9], 7); - x[8] ^= R(x[11] + x[10], 9); - x[9] ^= R(x[8] + x[11], 13); - x[10] ^= R(x[9] + x[8], 18); - x[12] ^= R(x[15] + x[14], 7); - x[13] ^= R(x[12] + x[15], 9); - x[14] ^= R(x[13] + x[12], 13); - x[15] ^= R(x[14] + x[13], 18); - } - for (i = 0; i < 16; ++i) - inout[i] += x[i]; - OPENSSL_cleanse(x, sizeof(x)); -} - -static void scryptBlockMix(uint32_t *B_, uint32_t *B, uint64_t r) -{ - uint64_t i, j; - uint32_t X[16], *pB; - - memcpy(X, B + (r * 2 - 1) * 16, sizeof(X)); - pB = B; - for (i = 0; i < r * 2; i++) { - for (j = 0; j < 16; j++) - X[j] ^= *pB++; - salsa208_word_specification(X); - memcpy(B_ + (i / 2 + (i & 1) * r) * 16, X, sizeof(X)); - } - OPENSSL_cleanse(X, sizeof(X)); -} - -static void scryptROMix(unsigned char *B, uint64_t r, uint64_t N, - uint32_t *X, uint32_t *T, uint32_t *V) -{ - unsigned char *pB; - uint32_t *pV; - uint64_t i, k; - - /* Convert from little endian input */ - for (pV = V, i = 0, pB = B; i < 32 * r; i++, pV++) { - *pV = *pB++; - *pV |= *pB++ << 8; - *pV |= *pB++ << 16; - *pV |= (uint32_t)*pB++ << 24; - } - - for (i = 1; i < N; i++, pV += 32 * r) - scryptBlockMix(pV, pV - 32 * r, r); - - scryptBlockMix(X, V + (N - 1) * 32 * r, r); - - for (i = 0; i < N; i++) { - uint32_t j; - j = X[16 * (2 * r - 1)] % N; - pV = V + 32 * r * j; - for (k = 0; k < 32 * r; k++) - T[k] = X[k] ^ *pV++; - scryptBlockMix(X, T, r); - } - /* Convert output to little endian */ - for (i = 0, pB = B; i < 32 * r; i++) { - uint32_t xtmp = X[i]; - *pB++ = xtmp & 0xff; - *pB++ = (xtmp >> 8) & 0xff; - *pB++ = (xtmp >> 16) & 0xff; - *pB++ = (xtmp >> 24) & 0xff; - } -} - -#ifndef SIZE_MAX -# define SIZE_MAX ((size_t)-1) -#endif - -/* - * Maximum power of two that will fit in uint64_t: this should work on - * most (all?) platforms. - */ - -#define LOG2_UINT64_MAX (sizeof(uint64_t) * 8 - 1) - -/* - * Maximum value of p * r: - * p <= ((2^32-1) * hLen) / MFLen => - * p <= ((2^32-1) * 32) / (128 * r) => - * p * r <= (2^30-1) - */ - -#define SCRYPT_PR_MAX ((1 << 30) - 1) - -static int scrypt_alg(const char *pass, size_t passlen, - const unsigned char *salt, size_t saltlen, - uint64_t N, uint64_t r, uint64_t p, uint64_t maxmem, - unsigned char *key, size_t keylen, EVP_MD *sha256) -{ - int rv = 0; - unsigned char *B; - uint32_t *X, *V, *T; - uint64_t i, Blen, Vlen; - - /* Sanity check parameters */ - /* initial check, r,p must be non zero, N >= 2 and a power of 2 */ - if (r == 0 || p == 0 || N < 2 || (N & (N - 1))) - return 0; - /* Check p * r < SCRYPT_PR_MAX avoiding overflow */ - if (p > SCRYPT_PR_MAX / r) { - EVPerr(EVP_F_SCRYPT_ALG, EVP_R_MEMORY_LIMIT_EXCEEDED); - return 0; - } - - /* - * Need to check N: if 2^(128 * r / 8) overflows limit this is - * automatically satisfied since N <= UINT64_MAX. - */ - - if (16 * r <= LOG2_UINT64_MAX) { - if (N >= (((uint64_t)1) << (16 * r))) { - EVPerr(EVP_F_SCRYPT_ALG, EVP_R_MEMORY_LIMIT_EXCEEDED); - return 0; - } - } - - /* Memory checks: check total allocated buffer size fits in uint64_t */ - - /* - * B size in section 5 step 1.S - * Note: we know p * 128 * r < UINT64_MAX because we already checked - * p * r < SCRYPT_PR_MAX - */ - Blen = p * 128 * r; - /* - * Yet we pass it as integer to PKCS5_PBKDF2_HMAC... [This would - * have to be revised when/if PKCS5_PBKDF2_HMAC accepts size_t.] - */ - if (Blen > INT_MAX) { - EVPerr(EVP_F_SCRYPT_ALG, EVP_R_MEMORY_LIMIT_EXCEEDED); - return 0; - } - - /* - * Check 32 * r * (N + 2) * sizeof(uint32_t) fits in uint64_t - * This is combined size V, X and T (section 4) - */ - i = UINT64_MAX / (32 * sizeof(uint32_t)); - if (N + 2 > i / r) { - EVPerr(EVP_F_SCRYPT_ALG, EVP_R_MEMORY_LIMIT_EXCEEDED); - return 0; - } - Vlen = 32 * r * (N + 2) * sizeof(uint32_t); - - /* check total allocated size fits in uint64_t */ - if (Blen > UINT64_MAX - Vlen) { - EVPerr(EVP_F_SCRYPT_ALG, EVP_R_MEMORY_LIMIT_EXCEEDED); - return 0; - } - - /* Check that the maximum memory doesn't exceed a size_t limits */ - if (maxmem > SIZE_MAX) - maxmem = SIZE_MAX; - - if (Blen + Vlen > maxmem) { - EVPerr(EVP_F_SCRYPT_ALG, EVP_R_MEMORY_LIMIT_EXCEEDED); - return 0; - } - - /* If no key return to indicate parameters are OK */ - if (key == NULL) - return 1; - - B = OPENSSL_malloc((size_t)(Blen + Vlen)); - if (B == NULL) { - EVPerr(EVP_F_SCRYPT_ALG, ERR_R_MALLOC_FAILURE); - return 0; - } - X = (uint32_t *)(B + Blen); - T = X + 32 * r; - V = T + 32 * r; - if (PKCS5_PBKDF2_HMAC(pass, passlen, salt, saltlen, 1, sha256, - (int)Blen, B) == 0) - goto err; - - for (i = 0; i < p; i++) - scryptROMix(B + 128 * r * i, r, N, X, T, V); - - if (PKCS5_PBKDF2_HMAC(pass, passlen, B, (int)Blen, 1, sha256, - keylen, key) == 0) - goto err; - rv = 1; - err: - if (rv == 0) - EVPerr(EVP_F_SCRYPT_ALG, EVP_R_PBKDF2_ERROR); - - OPENSSL_clear_free(B, (size_t)(Blen + Vlen)); - return rv; -} - -#endif diff --git a/providers/default/kdfs/sshkdf.c b/providers/default/kdfs/sshkdf.c deleted file mode 100644 index 7e6445dbdd..0000000000 --- a/providers/default/kdfs/sshkdf.c +++ /dev/null @@ -1,280 +0,0 @@ -/* - * Copyright 2018-2019 The OpenSSL Project Authors. All Rights Reserved. - * - * Licensed under the OpenSSL license (the "License"). You may not use - * this file except in compliance with the License. You can obtain a copy - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ - -#include -#include -#include -#include -#include -#include -#include "internal/cryptlib.h" -#include "internal/numbers.h" -#include "crypto/evp.h" -#include "internal/provider_ctx.h" -#include "internal/providercommonerr.h" -#include "internal/provider_algs.h" -# include "internal/provider_util.h" - -/* See RFC 4253, Section 7.2 */ -static OSSL_OP_kdf_newctx_fn kdf_sshkdf_new; -static OSSL_OP_kdf_freectx_fn kdf_sshkdf_free; -static OSSL_OP_kdf_reset_fn kdf_sshkdf_reset; -static OSSL_OP_kdf_derive_fn kdf_sshkdf_derive; -static OSSL_OP_kdf_settable_ctx_params_fn kdf_sshkdf_settable_ctx_params; -static OSSL_OP_kdf_set_ctx_params_fn kdf_sshkdf_set_ctx_params; -static OSSL_OP_kdf_gettable_ctx_params_fn kdf_sshkdf_gettable_ctx_params; -static OSSL_OP_kdf_get_ctx_params_fn kdf_sshkdf_get_ctx_params; - -static int SSHKDF(const EVP_MD *evp_md, - const unsigned char *key, size_t key_len, - const unsigned char *xcghash, size_t xcghash_len, - const unsigned char *session_id, size_t session_id_len, - char type, unsigned char *okey, size_t okey_len); - -typedef struct { - void *provctx; - PROV_DIGEST digest; - unsigned char *key; /* K */ - size_t key_len; - unsigned char *xcghash; /* H */ - size_t xcghash_len; - char type; /* X */ - unsigned char *session_id; - size_t session_id_len; -} KDF_SSHKDF; - -static void *kdf_sshkdf_new(void *provctx) -{ - KDF_SSHKDF *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_sshkdf_free(void *vctx) -{ - KDF_SSHKDF *ctx = (KDF_SSHKDF *)vctx; - - kdf_sshkdf_reset(ctx); - OPENSSL_free(ctx); -} - -static void kdf_sshkdf_reset(void *vctx) -{ - KDF_SSHKDF *ctx = (KDF_SSHKDF *)vctx; - - ossl_prov_digest_reset(&ctx->digest); - OPENSSL_clear_free(ctx->key, ctx->key_len); - OPENSSL_clear_free(ctx->xcghash, ctx->xcghash_len); - OPENSSL_clear_free(ctx->session_id, ctx->session_id_len); - memset(ctx, 0, sizeof(*ctx)); -} - -static int sshkdf_set_membuf(unsigned char **dst, size_t *dst_len, - const OSSL_PARAM *p) -{ - OPENSSL_clear_free(*dst, *dst_len); - *dst = NULL; - return OSSL_PARAM_get_octet_string(p, (void **)dst, 0, dst_len); -} - -static int kdf_sshkdf_derive(void *vctx, unsigned char *key, - size_t keylen) -{ - KDF_SSHKDF *ctx = (KDF_SSHKDF *)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; - } - if (ctx->xcghash == NULL) { - ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_XCGHASH); - return 0; - } - if (ctx->session_id == NULL) { - ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_SESSION_ID); - return 0; - } - if (ctx->type == 0) { - ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_TYPE); - return 0; - } - return SSHKDF(md, ctx->key, ctx->key_len, - ctx->xcghash, ctx->xcghash_len, - ctx->session_id, ctx->session_id_len, - ctx->type, key, keylen); -} - -static int kdf_sshkdf_set_ctx_params(void *vctx, const OSSL_PARAM params[]) -{ - const OSSL_PARAM *p; - KDF_SSHKDF *ctx = vctx; - OPENSSL_CTX *provctx = PROV_LIBRARY_CONTEXT_OF(ctx->provctx); - int t; - - if (!ossl_prov_digest_load_from_params(&ctx->digest, params, provctx)) - return 0; - - if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_KEY)) != NULL) - if (!sshkdf_set_membuf(&ctx->key, &ctx->key_len, p)) - return 0; - - if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SSHKDF_XCGHASH)) - != NULL) - if (!sshkdf_set_membuf(&ctx->xcghash, &ctx->xcghash_len, p)) - return 0; - - if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SSHKDF_SESSION_ID)) - != NULL) - if (!sshkdf_set_membuf(&ctx->session_id, &ctx->session_id_len, p)) - return 0; - - if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SSHKDF_TYPE)) - != NULL) { - if (p->data == NULL || p->data_size == 0) - return 0; - t = *(unsigned char *)p->data; - if (t < 65 || t > 70) { - ERR_raise(ERR_LIB_PROV, PROV_R_VALUE_ERROR); - return 0; - } - ctx->type = (char)t; - } - return 1; -} - -static const OSSL_PARAM *kdf_sshkdf_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_KEY, NULL, 0), - OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SSHKDF_XCGHASH, NULL, 0), - OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SSHKDF_SESSION_ID, NULL, 0), - OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_SSHKDF_TYPE, NULL, 0), - OSSL_PARAM_END - }; - return known_settable_ctx_params; -} - -static int kdf_sshkdf_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_sshkdf_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_sshkdf_functions[] = { - { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))kdf_sshkdf_new }, - { OSSL_FUNC_KDF_FREECTX, (void(*)(void))kdf_sshkdf_free }, - { OSSL_FUNC_KDF_RESET, (void(*)(void))kdf_sshkdf_reset }, - { OSSL_FUNC_KDF_DERIVE, (void(*)(void))kdf_sshkdf_derive }, - { OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS, - (void(*)(void))kdf_sshkdf_settable_ctx_params }, - { OSSL_FUNC_KDF_SET_CTX_PARAMS, (void(*)(void))kdf_sshkdf_set_ctx_params }, - { OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS, - (void(*)(void))kdf_sshkdf_gettable_ctx_params }, - { OSSL_FUNC_KDF_GET_CTX_PARAMS, (void(*)(void))kdf_sshkdf_get_ctx_params }, - { 0, NULL } -}; - -static int SSHKDF(const EVP_MD *evp_md, - const unsigned char *key, size_t key_len, - const unsigned char *xcghash, size_t xcghash_len, - const unsigned char *session_id, size_t session_id_len, - char type, unsigned char *okey, size_t okey_len) -{ - EVP_MD_CTX *md = NULL; - unsigned char digest[EVP_MAX_MD_SIZE]; - unsigned int dsize = 0; - size_t cursize = 0; - int ret = 0; - - md = EVP_MD_CTX_new(); - if (md == NULL) - return 0; - - if (!EVP_DigestInit_ex(md, evp_md, NULL)) - goto out; - - if (!EVP_DigestUpdate(md, key, key_len)) - goto out; - - if (!EVP_DigestUpdate(md, xcghash, xcghash_len)) - goto out; - - if (!EVP_DigestUpdate(md, &type, 1)) - goto out; - - if (!EVP_DigestUpdate(md, session_id, session_id_len)) - goto out; - - if (!EVP_DigestFinal_ex(md, digest, &dsize)) - goto out; - - if (okey_len < dsize) { - memcpy(okey, digest, okey_len); - ret = 1; - goto out; - } - - memcpy(okey, digest, dsize); - - for (cursize = dsize; cursize < okey_len; cursize += dsize) { - - if (!EVP_DigestInit_ex(md, evp_md, NULL)) - goto out; - - if (!EVP_DigestUpdate(md, key, key_len)) - goto out; - - if (!EVP_DigestUpdate(md, xcghash, xcghash_len)) - goto out; - - if (!EVP_DigestUpdate(md, okey, cursize)) - goto out; - - if (!EVP_DigestFinal_ex(md, digest, &dsize)) - goto out; - - if (okey_len < cursize + dsize) { - memcpy(okey + cursize, digest, okey_len - cursize); - ret = 1; - goto out; - } - - memcpy(okey + cursize, digest, dsize); - } - - ret = 1; - -out: - EVP_MD_CTX_free(md); - OPENSSL_cleanse(digest, EVP_MAX_MD_SIZE); - return ret; -} - diff --git a/providers/default/kdfs/x942kdf.c b/providers/default/kdfs/x942kdf.c deleted file mode 100644 index 65c586fb99..0000000000 --- a/providers/default/kdfs/x942kdf.c +++ /dev/null @@ -1,424 +0,0 @@ -/* - * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. - * - * Licensed under the Apache License 2.0 (the "License"). You may not use - * this file except in compliance with the License. You can obtain a copy - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ - -#include "e_os.h" - -#ifndef OPENSSL_NO_CMS - -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include "internal/cryptlib.h" -# include "internal/numbers.h" -# include "crypto/evp.h" -# include "internal/provider_ctx.h" -# include "internal/providercommonerr.h" -# include "internal/provider_algs.h" -# include "internal/provider_util.h" - -# define X942KDF_MAX_INLEN (1 << 30) - -static OSSL_OP_kdf_newctx_fn x942kdf_new; -static OSSL_OP_kdf_freectx_fn x942kdf_free; -static OSSL_OP_kdf_reset_fn x942kdf_reset; -static OSSL_OP_kdf_derive_fn x942kdf_derive; -static OSSL_OP_kdf_settable_ctx_params_fn x942kdf_settable_ctx_params; -static OSSL_OP_kdf_set_ctx_params_fn x942kdf_set_ctx_params; -static OSSL_OP_kdf_gettable_ctx_params_fn x942kdf_gettable_ctx_params; -static OSSL_OP_kdf_get_ctx_params_fn x942kdf_get_ctx_params; - -typedef struct { - void *provctx; - PROV_DIGEST digest; - unsigned char *secret; - size_t secret_len; - int cek_nid; - unsigned char *ukm; - size_t ukm_len; - size_t dkm_len; -} KDF_X942; - -/* A table of allowed wrapping algorithms and the associated output lengths */ -static const struct { - int nid; - size_t keklen; /* size in bytes */ -} kek_algs[] = { - { NID_id_smime_alg_CMS3DESwrap, 24 }, - { NID_id_smime_alg_CMSRC2wrap, 16 }, - { NID_id_aes128_wrap, 16 }, - { NID_id_aes192_wrap, 24 }, - { NID_id_aes256_wrap, 32 }, - { NID_id_camellia128_wrap, 16 }, - { NID_id_camellia192_wrap, 24 }, - { NID_id_camellia256_wrap, 32 } -}; - -/* Skip past an ASN1 structure: for OBJECT skip content octets too */ -static int skip_asn1(unsigned char **pp, long *plen, int exptag) -{ - int i, tag, xclass; - long tmplen; - const unsigned char *q = *pp; - - i = ASN1_get_object(&q, &tmplen, &tag, &xclass, *plen); - if ((i & 0x80) != 0 || tag != exptag || xclass != V_ASN1_UNIVERSAL) - return 0; - if (tag == V_ASN1_OBJECT) - q += tmplen; - *pp = (unsigned char *)q; - *plen -= q - *pp; - return 1; -} - -/* - * Encode the other info structure. - * - * RFC2631 Section 2.1.2 Contains the following definition for otherinfo - * - * OtherInfo ::= SEQUENCE { - * keyInfo KeySpecificInfo, - * partyAInfo [0] OCTET STRING OPTIONAL, - * suppPubInfo [2] OCTET STRING - * } - * - * KeySpecificInfo ::= SEQUENCE { - * algorithm OBJECT IDENTIFIER, - * counter OCTET STRING SIZE (4..4) - * } - * - * |nid| is the algorithm object identifier. - * |keylen| is the length (in bytes) of the generated KEK. It is stored into - * suppPubInfo (in bits). - * |ukm| is the optional user keying material that is stored into partyAInfo. It - * can be NULL. - * |ukmlen| is the user keying material length (in bytes). - * |der| is the returned encoded data. It must be freed by the caller. - * |der_len| is the returned size of the encoded data. - * |out_ctr| returns a pointer to the counter data which is embedded inside the - * encoded data. This allows the counter bytes to be updated without re-encoding. - * - * Returns: 1 if successfully encoded, or 0 otherwise. - * Assumptions: |der|, |der_len| & |out_ctr| are not NULL. - */ -static int x942_encode_otherinfo(int nid, size_t keylen, - const unsigned char *ukm, size_t ukmlen, - unsigned char **der, size_t *der_len, - unsigned char **out_ctr) -{ - unsigned char *p, *encoded = NULL; - int ret = 0, encoded_len; - long tlen; - /* "magic" value to check offset is sane */ - static unsigned char ctr[4] = { 0x00, 0x00, 0x00, 0x01 }; - X509_ALGOR *ksi = NULL; - ASN1_OBJECT *alg_oid = NULL; - ASN1_OCTET_STRING *ctr_oct = NULL, *ukm_oct = NULL; - - /* set the KeySpecificInfo - which contains an algorithm oid and counter */ - ksi = X509_ALGOR_new(); - alg_oid = OBJ_dup(OBJ_nid2obj(nid)); - ctr_oct = ASN1_OCTET_STRING_new(); - if (ksi == NULL - || alg_oid == NULL - || ctr_oct == NULL - || !ASN1_OCTET_STRING_set(ctr_oct, ctr, sizeof(ctr)) - || !X509_ALGOR_set0(ksi, alg_oid, V_ASN1_OCTET_STRING, ctr_oct)) - goto err; - /* NULL these as they now belong to ksi */ - alg_oid = NULL; - ctr_oct = NULL; - - /* Set the optional partyAInfo */ - if (ukm != NULL) { - ukm_oct = ASN1_OCTET_STRING_new(); - if (ukm_oct == NULL) - goto err; - ASN1_OCTET_STRING_set(ukm_oct, (unsigned char *)ukm, ukmlen); - } - /* Generate the OtherInfo DER data */ - encoded_len = CMS_SharedInfo_encode(&encoded, ksi, ukm_oct, keylen); - if (encoded_len <= 0) - goto err; - - /* Parse the encoded data to find the offset of the counter data */ - p = encoded; - tlen = (long)encoded_len; - if (skip_asn1(&p, &tlen, V_ASN1_SEQUENCE) - && skip_asn1(&p, &tlen, V_ASN1_SEQUENCE) - && skip_asn1(&p, &tlen, V_ASN1_OBJECT) - && skip_asn1(&p, &tlen, V_ASN1_OCTET_STRING) - && CRYPTO_memcmp(p, ctr, 4) == 0) { - *out_ctr = p; - *der = encoded; - *der_len = (size_t)encoded_len; - ret = 1; - } -err: - if (ret != 1) - OPENSSL_free(encoded); - ASN1_OCTET_STRING_free(ctr_oct); - ASN1_OCTET_STRING_free(ukm_oct); - ASN1_OBJECT_free(alg_oid); - X509_ALGOR_free(ksi); - return ret; -} - -static int x942kdf_hash_kdm(const EVP_MD *kdf_md, - const unsigned char *z, size_t z_len, - const unsigned char *other, size_t other_len, - unsigned char *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 mac[EVP_MAX_MD_SIZE]; - unsigned char *out = derived_key; - EVP_MD_CTX *ctx = NULL, *ctx_init = NULL; - - if (z_len > X942KDF_MAX_INLEN || other_len > X942KDF_MAX_INLEN - || derived_key_len > X942KDF_MAX_INLEN - || derived_key_len == 0) { - ERR_raise(ERR_LIB_PROV, PROV_R_BAD_LENGTH); - 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++) { - /* updating the ctr modifies 4 bytes in the 'other' buffer */ - ctr[0] = (unsigned char)((counter >> 24) & 0xff); - ctr[1] = (unsigned char)((counter >> 16) & 0xff); - ctr[2] = (unsigned char)((counter >> 8) & 0xff); - ctr[3] = (unsigned char)(counter & 0xff); - - if (!EVP_MD_CTX_copy_ex(ctx, ctx_init) - || !EVP_DigestUpdate(ctx, z, z_len) - || !EVP_DigestUpdate(ctx, other, other_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_free(ctx); - EVP_MD_CTX_free(ctx_init); - OPENSSL_cleanse(mac, sizeof(mac)); - return ret; -} - -static void *x942kdf_new(void *provctx) -{ - KDF_X942 *ctx; - - if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) - ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); - ctx->provctx = provctx; - return ctx; -} - -static void x942kdf_reset(void *vctx) -{ - KDF_X942 *ctx = (KDF_X942 *)vctx; - - ossl_prov_digest_reset(&ctx->digest); - OPENSSL_clear_free(ctx->secret, ctx->secret_len); - OPENSSL_clear_free(ctx->ukm, ctx->ukm_len); - memset(ctx, 0, sizeof(*ctx)); -} - -static void x942kdf_free(void *vctx) -{ - KDF_X942 *ctx = (KDF_X942 *)vctx; - - x942kdf_reset(ctx); - OPENSSL_free(ctx); -} - -static int x942kdf_set_buffer(unsigned char **out, size_t *out_len, - const OSSL_PARAM *p) -{ - if (p->data_size == 0 || p->data == NULL) - return 1; - - OPENSSL_free(*out); - *out = NULL; - return OSSL_PARAM_get_octet_string(p, (void **)out, 0, out_len); -} - -static size_t x942kdf_size(KDF_X942 *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 x942kdf_derive(void *vctx, unsigned char *key, size_t keylen) -{ - KDF_X942 *ctx = (KDF_X942 *)vctx; - const EVP_MD *md = ossl_prov_digest_md(&ctx->digest); - int ret = 0; - unsigned char *ctr; - unsigned char *der = NULL; - size_t der_len = 0; - - if (ctx->secret == NULL) { - ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_SECRET); - return 0; - } - if (md == NULL) { - ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST); - return 0; - } - if (ctx->cek_nid == NID_undef) { - ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_CEK_ALG); - return 0; - } - if (ctx->ukm != NULL && ctx->ukm_len >= X942KDF_MAX_INLEN) { - /* - * Note the ukm length MUST be 512 bits. - * For backwards compatibility the old check is being done. - */ - ERR_raise(ERR_LIB_PROV, PROV_R_INAVLID_UKM_LENGTH); - return 0; - } - if (keylen != ctx->dkm_len) { - ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_CEK_ALG); - return 0; - } - /* generate the otherinfo der */ - if (!x942_encode_otherinfo(ctx->cek_nid, ctx->dkm_len, - ctx->ukm, ctx->ukm_len, - &der, &der_len, &ctr)) { - ERR_raise(ERR_LIB_PROV, PROV_R_BAD_ENCODING); - return 0; - } - ret = x942kdf_hash_kdm(md, ctx->secret, ctx->secret_len, - der, der_len, ctr, key, keylen); - OPENSSL_free(der); - return ret; -} - -static int x942kdf_set_ctx_params(void *vctx, const OSSL_PARAM params[]) -{ - const OSSL_PARAM *p; - KDF_X942 *ctx = vctx; - OPENSSL_CTX *provctx = PROV_LIBRARY_CONTEXT_OF(ctx->provctx); - size_t i; - - if (!ossl_prov_digest_load_from_params(&ctx->digest, params, provctx)) - 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 (!x942kdf_set_buffer(&ctx->secret, &ctx->secret_len, p)) - return 0; - - if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_UKM)) != NULL) - if (!x942kdf_set_buffer(&ctx->ukm, &ctx->ukm_len, p)) - return 0; - - if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_CEK_ALG)) != NULL) { - if (p->data_type != OSSL_PARAM_UTF8_STRING) - return 0; - ctx->cek_nid = OBJ_sn2nid(p->data); - for (i = 0; i < OSSL_NELEM(kek_algs); i++) - if (kek_algs[i].nid == ctx->cek_nid) - goto cek_found; - ERR_raise(ERR_LIB_PROV, PROV_R_UNSUPPORTED_CEK_ALG); - return 0; -cek_found: - ctx->dkm_len = kek_algs[i].keklen; - } - return 1; -} - -static const OSSL_PARAM *x942kdf_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_KEY, NULL, 0), - OSSL_PARAM_octet_string(OSSL_KDF_PARAM_UKM, NULL, 0), - OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_CEK_ALG, NULL, 0), - OSSL_PARAM_END - }; - return known_settable_ctx_params; -} - -static int x942kdf_get_ctx_params(void *vctx, OSSL_PARAM params[]) -{ - KDF_X942 *ctx = (KDF_X942 *)vctx; - OSSL_PARAM *p; - - if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE)) != NULL) - return OSSL_PARAM_set_size_t(p, x942kdf_size(ctx)); - return -2; -} - -static const OSSL_PARAM *x942kdf_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_x942_kdf_functions[] = { - { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))x942kdf_new }, - { OSSL_FUNC_KDF_FREECTX, (void(*)(void))x942kdf_free }, - { OSSL_FUNC_KDF_RESET, (void(*)(void))x942kdf_reset }, - { OSSL_FUNC_KDF_DERIVE, (void(*)(void))x942kdf_derive }, - { OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS, - (void(*)(void))x942kdf_settable_ctx_params }, - { OSSL_FUNC_KDF_SET_CTX_PARAMS, (void(*)(void))x942kdf_set_ctx_params }, - { OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS, - (void(*)(void))x942kdf_gettable_ctx_params }, - { OSSL_FUNC_KDF_GET_CTX_PARAMS, (void(*)(void))x942kdf_get_ctx_params }, - { 0, NULL } -}; - -#endif /* OPENSSL_NO_CMS */ diff --git a/providers/default/macs/blake2_mac_impl.c b/providers/default/macs/blake2_mac_impl.c deleted file mode 100644 index a190b91b98..0000000000 --- a/providers/default/macs/blake2_mac_impl.c +++ /dev/null @@ -1,220 +0,0 @@ -/* - * Copyright 2018 The OpenSSL Project Authors. All Rights Reserved. - * - * Licensed under the Apache License 2.0 (the "License"). You may not use - * this file except in compliance with the License. You can obtain a copy - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ - -#include -#include -#include - -#include "internal/blake2.h" -#include "internal/cryptlib.h" -#include "internal/providercommonerr.h" -#include "internal/provider_algs.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 blake2_mac_new; -static OSSL_OP_mac_dupctx_fn blake2_mac_dup; -static OSSL_OP_mac_freectx_fn blake2_mac_free; -static OSSL_OP_mac_gettable_ctx_params_fn blake2_gettable_ctx_params; -static OSSL_OP_mac_get_ctx_params_fn blake2_get_ctx_params; -static OSSL_OP_mac_settable_ctx_params_fn blake2_mac_settable_ctx_params; -static OSSL_OP_mac_set_ctx_params_fn blake2_mac_set_ctx_params; -static OSSL_OP_mac_init_fn blake2_mac_init; -static OSSL_OP_mac_update_fn blake2_mac_update; -static OSSL_OP_mac_final_fn blake2_mac_final; - -struct blake2_mac_data_st { - BLAKE2_CTX ctx; - BLAKE2_PARAM params; - unsigned char key[BLAKE2_KEYBYTES]; -}; - -static size_t blake2_mac_size(void *vmacctx); - -static void *blake2_mac_new(void *unused_provctx) -{ - struct blake2_mac_data_st *macctx = OPENSSL_zalloc(sizeof(*macctx)); - - if (macctx != NULL) { - BLAKE2_PARAM_INIT(&macctx->params); - /* ctx initialization is deferred to BLAKE2b_Init() */ - } - return macctx; -} - -static void *blake2_mac_dup(void *vsrc) -{ - struct blake2_mac_data_st *dst; - struct blake2_mac_data_st *src = vsrc; - - dst = OPENSSL_zalloc(sizeof(*dst)); - if (dst == NULL) - return NULL; - - *dst = *src; - return dst; -} - -static void blake2_mac_free(void *vmacctx) -{ - struct blake2_mac_data_st *macctx = vmacctx; - - if (macctx != NULL) { - OPENSSL_cleanse(macctx->key, sizeof(macctx->key)); - OPENSSL_free(macctx); - } -} - -static int blake2_mac_init(void *vmacctx) -{ - struct blake2_mac_data_st *macctx = vmacctx; - - /* Check key has been set */ - if (macctx->params.key_length == 0) { - ERR_raise(ERR_LIB_PROV, PROV_R_NO_KEY_SET); - return 0; - } - - return BLAKE2_INIT_KEY(&macctx->ctx, &macctx->params, macctx->key); -} - -static int blake2_mac_update(void *vmacctx, - const unsigned char *data, size_t datalen) -{ - struct blake2_mac_data_st *macctx = vmacctx; - - return BLAKE2_UPDATE(&macctx->ctx, data, datalen); -} - -static int blake2_mac_final(void *vmacctx, - unsigned char *out, size_t *outl, - size_t outsize) -{ - struct blake2_mac_data_st *macctx = vmacctx; - - return BLAKE2_FINAL(out, &macctx->ctx); -} - -static const OSSL_PARAM known_gettable_ctx_params[] = { - OSSL_PARAM_size_t(OSSL_MAC_PARAM_SIZE, NULL), - OSSL_PARAM_END -}; -static const OSSL_PARAM *blake2_gettable_ctx_params(void) -{ - return known_gettable_ctx_params; -} - -static int blake2_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, blake2_mac_size(vmacctx)); - - return 1; -} - -static const OSSL_PARAM known_settable_ctx_params[] = { - 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_octet_string(OSSL_MAC_PARAM_SALT, NULL, 0), - OSSL_PARAM_END -}; -static const OSSL_PARAM *blake2_mac_settable_ctx_params() -{ - return known_settable_ctx_params; -} - -/* - * ALL parameters should be set before init(). - */ -static int blake2_mac_set_ctx_params(void *vmacctx, const OSSL_PARAM params[]) -{ - struct blake2_mac_data_st *macctx = vmacctx; - const OSSL_PARAM *p; - - if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_SIZE)) != NULL) { - size_t size; - - if (!OSSL_PARAM_get_size_t(p, &size) - || size < 1 - || size > BLAKE2_OUTBYTES) { - ERR_raise(ERR_LIB_PROV, PROV_R_NOT_XOF_OR_INVALID_LENGTH); - return 0; - } - BLAKE2_PARAM_SET_DIGEST_LENGTH(&macctx->params, (uint8_t)size); - } - - if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_KEY)) != NULL) { - size_t len; - void *key_p = macctx->key; - - if (!OSSL_PARAM_get_octet_string(p, &key_p, BLAKE2_KEYBYTES, &len)) { - ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH); - return 0; - } - /* Pad with zeroes at the end */ - memset(macctx->key + len, 0, BLAKE2_KEYBYTES - len); - - BLAKE2_PARAM_SET_KEY_LENGTH(&macctx->params, (uint8_t)len); - } - - if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_CUSTOM)) - != NULL) { - /* - * The OSSL_PARAM API doesn't provide direct pointer use, so we - * must handle the OSSL_PARAM structure ourselves here - */ - if (p->data_size > BLAKE2_PERSONALBYTES) { - ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_CUSTOM_LENGTH); - return 0; - } - BLAKE2_PARAM_SET_PERSONAL(&macctx->params, p->data, p->data_size); - } - - if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_SALT)) != NULL) { - /* - * The OSSL_PARAM API doesn't provide direct pointer use, so we - * must handle the OSSL_PARAM structure ourselves here as well - */ - if (p->data_size > BLAKE2_SALTBYTES) { - ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_SALT_LENGTH); - return 0; - } - BLAKE2_PARAM_SET_SALT(&macctx->params, p->data, p->data_size); - } - return 1; -} - -static size_t blake2_mac_size(void *vmacctx) -{ - struct blake2_mac_data_st *macctx = vmacctx; - - return macctx->params.digest_length; -} - -const OSSL_DISPATCH BLAKE2_FUNCTIONS[] = { - { OSSL_FUNC_MAC_NEWCTX, (void (*)(void))blake2_mac_new }, - { OSSL_FUNC_MAC_DUPCTX, (void (*)(void))blake2_mac_dup }, - { OSSL_FUNC_MAC_FREECTX, (void (*)(void))blake2_mac_free }, - { OSSL_FUNC_MAC_INIT, (void (*)(void))blake2_mac_init }, - { OSSL_FUNC_MAC_UPDATE, (void (*)(void))blake2_mac_update }, - { OSSL_FUNC_MAC_FINAL, (void (*)(void))blake2_mac_final }, - { OSSL_FUNC_MAC_GETTABLE_CTX_PARAMS, - (void (*)(void))blake2_gettable_ctx_params }, - { OSSL_FUNC_MAC_GET_CTX_PARAMS, (void (*)(void))blake2_get_ctx_params }, - { OSSL_FUNC_MAC_SETTABLE_CTX_PARAMS, - (void (*)(void))blake2_mac_settable_ctx_params }, - { OSSL_FUNC_MAC_SET_CTX_PARAMS, (void (*)(void))blake2_mac_set_ctx_params }, - { 0, NULL } -}; diff --git a/providers/default/macs/blake2b_mac.c b/providers/default/macs/blake2b_mac.c deleted file mode 100644 index aa1a8dee1f..0000000000 --- a/providers/default/macs/blake2b_mac.c +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2018 The OpenSSL Project Authors. All Rights Reserved. - * - * Licensed under the Apache License 2.0 (the "License"). You may not use - * this file except in compliance with the License. You can obtain a copy - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ - -/* Constants */ -#define BLAKE2_CTX BLAKE2B_CTX -#define BLAKE2_PARAM BLAKE2B_PARAM -#define BLAKE2_KEYBYTES BLAKE2B_KEYBYTES -#define BLAKE2_OUTBYTES BLAKE2B_OUTBYTES -#define BLAKE2_PERSONALBYTES BLAKE2B_PERSONALBYTES -#define BLAKE2_SALTBYTES BLAKE2B_SALTBYTES - -/* Function names */ -#define BLAKE2_PARAM_INIT blake2b_param_init -#define BLAKE2_INIT_KEY blake2b_init_key -#define BLAKE2_UPDATE blake2b_update -#define BLAKE2_FINAL blake2b_final -#define BLAKE2_PARAM_SET_DIGEST_LENGTH blake2b_param_set_digest_length -#define BLAKE2_PARAM_SET_KEY_LENGTH blake2b_param_set_key_length -#define BLAKE2_PARAM_SET_PERSONAL blake2b_param_set_personal -#define BLAKE2_PARAM_SET_SALT blake2b_param_set_salt - -/* OSSL_DISPATCH symbol */ -#define BLAKE2_FUNCTIONS blake2bmac_functions - -#include "blake2_mac_impl.c" - diff --git a/providers/default/macs/blake2s_mac.c b/providers/default/macs/blake2s_mac.c deleted file mode 100644 index ccd7035523..0000000000 --- a/providers/default/macs/blake2s_mac.c +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2018 The OpenSSL Project Authors. All Rights Reserved. - * - * Licensed under the Apache License 2.0 (the "License"). You may not use - * this file except in compliance with the License. You can obtain a copy - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ - -/* Constants */ -#define BLAKE2_CTX BLAKE2S_CTX -#define BLAKE2_PARAM BLAKE2S_PARAM -#define BLAKE2_KEYBYTES BLAKE2S_KEYBYTES -#define BLAKE2_OUTBYTES BLAKE2S_OUTBYTES -#define BLAKE2_PERSONALBYTES BLAKE2S_PERSONALBYTES -#define BLAKE2_SALTBYTES BLAKE2S_SALTBYTES - -/* Function names */ -#define BLAKE2_PARAM_INIT blake2s_param_init -#define BLAKE2_INIT_KEY blake2s_init_key -#define BLAKE2_UPDATE blake2s_update -#define BLAKE2_FINAL blake2s_final -#define BLAKE2_PARAM_SET_DIGEST_LENGTH blake2s_param_set_digest_length -#define BLAKE2_PARAM_SET_KEY_LENGTH blake2s_param_set_key_length -#define BLAKE2_PARAM_SET_PERSONAL blake2s_param_set_personal -#define BLAKE2_PARAM_SET_SALT blake2s_param_set_salt - -/* OSSL_DISPATCH symbol */ -#define BLAKE2_FUNCTIONS blake2smac_functions - -#include "blake2_mac_impl.c" diff --git a/providers/default/macs/build.info b/providers/default/macs/build.info deleted file mode 100644 index 821a3d467b..0000000000 --- a/providers/default/macs/build.info +++ /dev/null @@ -1,13 +0,0 @@ -$GOAL=../../libimplementations.a - -IF[{- !$disabled{blake2} -}] - SOURCE[$GOAL]=blake2b_mac.c blake2s_mac.c -ENDIF - -IF[{- !$disabled{siphash} -}] - SOURCE[$GOAL]=siphash_prov.c -ENDIF - -IF[{- !$disabled{poly1305} -}] - SOURCE[$GOAL]=poly1305_prov.c -ENDIF diff --git a/providers/default/macs/poly1305_prov.c b/providers/default/macs/poly1305_prov.c deleted file mode 100644 index 88005716e6..0000000000 --- a/providers/default/macs/poly1305_prov.c +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Copyright 2018 The OpenSSL Project Authors. All Rights Reserved. - * - * Licensed under the Apache License 2.0 (the "License"). You may not use - * this file except in compliance with the License. You can obtain a copy - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ - -#include -#include -#include -#include -#include - -#include "crypto/poly1305.h" -/* - * TODO(3.0) when poly1305 has moved entirely to our providers, this - * header should be moved to the provider include directory. For the - * moment, crypto/poly1305/poly1305_ameth.c has us stuck. - */ -#include "../../../crypto/poly1305/poly1305_local.h" - -#include "internal/providercommonerr.h" -#include "internal/provider_algs.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 poly1305_new; -static OSSL_OP_mac_dupctx_fn poly1305_dup; -static OSSL_OP_mac_freectx_fn poly1305_free; -static OSSL_OP_mac_gettable_params_fn poly1305_gettable_params; -static OSSL_OP_mac_get_params_fn poly1305_get_params; -static OSSL_OP_mac_settable_ctx_params_fn poly1305_settable_ctx_params; -static OSSL_OP_mac_set_ctx_params_fn poly1305_set_ctx_params; -static OSSL_OP_mac_init_fn poly1305_init; -static OSSL_OP_mac_update_fn poly1305_update; -static OSSL_OP_mac_final_fn poly1305_final; - -struct poly1305_data_st { - void *provctx; - POLY1305 poly1305; /* Poly1305 data */ -}; - -static size_t poly1305_size(void); - -static void *poly1305_new(void *provctx) -{ - struct poly1305_data_st *ctx = OPENSSL_zalloc(sizeof(*ctx)); - - ctx->provctx = provctx; - return ctx; -} - -static void poly1305_free(void *vmacctx) -{ - OPENSSL_free(vmacctx); -} - -static void *poly1305_dup(void *vsrc) -{ - struct poly1305_data_st *src = vsrc; - struct poly1305_data_st *dst = poly1305_new(src->provctx); - - if (dst == NULL) - return NULL; - - dst->poly1305 = src->poly1305; - return dst; -} - -static size_t poly1305_size(void) -{ - return POLY1305_DIGEST_SIZE; -} - -static int poly1305_init(void *vmacctx) -{ - /* initialize the context in MAC_ctrl function */ - return 1; -} - -static int poly1305_update(void *vmacctx, const unsigned char *data, - size_t datalen) -{ - struct poly1305_data_st *ctx = vmacctx; - - /* poly1305 has nothing to return in its update function */ - Poly1305_Update(&ctx->poly1305, data, datalen); - return 1; -} - -static int poly1305_final(void *vmacctx, unsigned char *out, size_t *outl, - size_t outsize) -{ - struct poly1305_data_st *ctx = vmacctx; - - Poly1305_Final(&ctx->poly1305, out); - return 1; -} - -static const OSSL_PARAM known_gettable_params[] = { - OSSL_PARAM_size_t(OSSL_MAC_PARAM_SIZE, NULL), - OSSL_PARAM_END -}; -static const OSSL_PARAM *poly1305_gettable_params(void) -{ - return known_gettable_params; -} - -static int poly1305_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, poly1305_size()); - - return 1; -} - -static const OSSL_PARAM known_settable_ctx_params[] = { - OSSL_PARAM_octet_string(OSSL_MAC_PARAM_KEY, NULL, 0), - OSSL_PARAM_END -}; -static const OSSL_PARAM *poly1305_settable_ctx_params(void) -{ - return known_settable_ctx_params; -} - -static int poly1305_set_ctx_params(void *vmacctx, const OSSL_PARAM *params) -{ - struct poly1305_data_st *ctx = vmacctx; - const OSSL_PARAM *p = NULL; - - if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_KEY)) != NULL) { - if (p->data_type != OSSL_PARAM_OCTET_STRING - || p->data_size != POLY1305_KEY_SIZE) { - ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH); - return 0; - } - Poly1305_Init(&ctx->poly1305, p->data); - } - return 1; -} - -const OSSL_DISPATCH poly1305_functions[] = { - { OSSL_FUNC_MAC_NEWCTX, (void (*)(void))poly1305_new }, - { OSSL_FUNC_MAC_DUPCTX, (void (*)(void))poly1305_dup }, - { OSSL_FUNC_MAC_FREECTX, (void (*)(void))poly1305_free }, - { OSSL_FUNC_MAC_INIT, (void (*)(void))poly1305_init }, - { OSSL_FUNC_MAC_UPDATE, (void (*)(void))poly1305_update }, - { OSSL_FUNC_MAC_FINAL, (void (*)(void))poly1305_final }, - { OSSL_FUNC_MAC_GETTABLE_PARAMS, (void (*)(void))poly1305_gettable_params }, - { OSSL_FUNC_MAC_GET_PARAMS, (void (*)(void))poly1305_get_params }, - { OSSL_FUNC_MAC_SETTABLE_CTX_PARAMS, - (void (*)(void))poly1305_settable_ctx_params }, - { OSSL_FUNC_MAC_SET_CTX_PARAMS, (void (*)(void))poly1305_set_ctx_params }, - { 0, NULL } -}; diff --git a/providers/default/macs/siphash_prov.c b/providers/default/macs/siphash_prov.c deleted file mode 100644 index a9511925f0..0000000000 --- a/providers/default/macs/siphash_prov.c +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Copyright 2018 The OpenSSL Project Authors. All Rights Reserved. - * - * Licensed under the Apache License 2.0 (the "License"). You may not use - * this file except in compliance with the License. You can obtain a copy - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ - -#include -#include -#include -#include -#include -#include - -#include "crypto/siphash.h" -/* - * TODO(3.0) when siphash has moved entirely to our providers, this - * header should be moved to the provider include directory. For the - * moment, crypto/siphash/siphash_ameth.c has us stuck. - */ -#include "../../../crypto/siphash/siphash_local.h" - -#include "internal/providercommonerr.h" -#include "internal/provider_algs.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 siphash_new; -static OSSL_OP_mac_dupctx_fn siphash_dup; -static OSSL_OP_mac_freectx_fn siphash_free; -static OSSL_OP_mac_gettable_ctx_params_fn siphash_gettable_ctx_params; -static OSSL_OP_mac_get_ctx_params_fn siphash_get_ctx_params; -static OSSL_OP_mac_settable_ctx_params_fn siphash_settable_params; -static OSSL_OP_mac_set_ctx_params_fn siphash_set_params; -static OSSL_OP_mac_size_fn siphash_size; -static OSSL_OP_mac_init_fn siphash_init; -static OSSL_OP_mac_update_fn siphash_update; -static OSSL_OP_mac_final_fn siphash_final; - -struct siphash_data_st { - void *provctx; - SIPHASH siphash; /* Siphash data */ -}; - -static void *siphash_new(void *provctx) -{ - struct siphash_data_st *ctx = OPENSSL_zalloc(sizeof(*ctx)); - - ctx->provctx = provctx; - return ctx; -} - -static void siphash_free(void *vmacctx) -{ - OPENSSL_free(vmacctx); -} - -static void *siphash_dup(void *vsrc) -{ - struct siphash_data_st *ssrc = vsrc; - struct siphash_data_st *sdst = siphash_new(ssrc->provctx); - - if (sdst == NULL) - return NULL; - - sdst->siphash = ssrc->siphash; - return sdst; -} - -static size_t siphash_size(void *vmacctx) -{ - struct siphash_data_st *ctx = vmacctx; - - return SipHash_hash_size(&ctx->siphash); -} - -static int siphash_init(void *vmacctx) -{ - /* Not much to do here, actual initialization happens through controls */ - return 1; -} - -static int siphash_update(void *vmacctx, const unsigned char *data, - size_t datalen) -{ - struct siphash_data_st *ctx = vmacctx; - - SipHash_Update(&ctx->siphash, data, datalen); - return 1; -} - -static int siphash_final(void *vmacctx, unsigned char *out, size_t *outl, - size_t outsize) -{ - struct siphash_data_st *ctx = vmacctx; - size_t hlen = siphash_size(ctx); - - if (outsize < hlen) - return 0; - - *outl = hlen; - return SipHash_Final(&ctx->siphash, out, hlen); -} - -static const OSSL_PARAM known_gettable_ctx_params[] = { - OSSL_PARAM_size_t(OSSL_MAC_PARAM_SIZE, NULL), - OSSL_PARAM_END -}; -static const OSSL_PARAM *siphash_gettable_ctx_params(void) -{ - return known_gettable_ctx_params; -} - -static int siphash_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, siphash_size(vmacctx)); - - return 1; -} - -static const OSSL_PARAM known_settable_ctx_params[] = { - OSSL_PARAM_size_t(OSSL_MAC_PARAM_SIZE, NULL), - OSSL_PARAM_octet_string(OSSL_MAC_PARAM_KEY, NULL, 0), - OSSL_PARAM_END -}; -static const OSSL_PARAM *siphash_settable_params(void) -{ - return known_settable_ctx_params; -} - -static int siphash_set_params(void *vmacctx, const OSSL_PARAM *params) -{ - struct siphash_data_st *ctx = vmacctx; - const OSSL_PARAM *p = NULL; - - if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_SIZE)) != NULL) { - size_t size; - - if (!OSSL_PARAM_get_size_t(p, &size) - || !SipHash_set_hash_size(&ctx->siphash, size)) - return 0; - } - if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_KEY)) != NULL) - if (p->data_type != OSSL_PARAM_OCTET_STRING - || p->data_size != SIPHASH_KEY_SIZE - || !SipHash_Init(&ctx->siphash, p->data, 0, 0)) - return 0; - return 1; -} - -const OSSL_DISPATCH siphash_functions[] = { - { OSSL_FUNC_MAC_NEWCTX, (void (*)(void))siphash_new }, - { OSSL_FUNC_MAC_DUPCTX, (void (*)(void))siphash_dup }, - { OSSL_FUNC_MAC_FREECTX, (void (*)(void))siphash_free }, - { OSSL_FUNC_MAC_INIT, (void (*)(void))siphash_init }, - { OSSL_FUNC_MAC_UPDATE, (void (*)(void))siphash_update }, - { OSSL_FUNC_MAC_FINAL, (void (*)(void))siphash_final }, - { OSSL_FUNC_MAC_GETTABLE_CTX_PARAMS, - (void (*)(void))siphash_gettable_ctx_params }, - { OSSL_FUNC_MAC_GET_CTX_PARAMS, (void (*)(void))siphash_get_ctx_params }, - { OSSL_FUNC_MAC_SETTABLE_CTX_PARAMS, - (void (*)(void))siphash_settable_params }, - { OSSL_FUNC_MAC_SET_CTX_PARAMS, (void (*)(void))siphash_set_params }, - { 0, NULL } -}; diff --git a/providers/implementations/kdfs/build.info b/providers/implementations/kdfs/build.info index 8800b12f7e..dee8f532fa 100644 --- a/providers/implementations/kdfs/build.info +++ b/providers/implementations/kdfs/build.info @@ -6,6 +6,9 @@ $HKDF_GOAL=../../libimplementations.a $KBKDF_GOAL=../../libimplementations.a $PBKDF2_GOAL=../../libimplementations.a $SSKDF_GOAL=../../libimplementations.a +$SCRYPT_GOAL=../../libimplementations.a +$SSHKDF_GOAL=../../libimplementations.a +$X942KDF_GOAL=../../libimplementations.a SOURCE[$TLS1_PRF_GOAL]=tls1_prf.c @@ -20,3 +23,7 @@ SOURCE[../../libfips.a]=pbkdf2_fips.c SOURCE[../../libnonfips.a]=pbkdf2_fips.c SOURCE[$SSKDF_GOAL]=sskdf.c + +SOURCE[$SCRYPT_GOAL]=scrypt.c +SOURCE[$SSHKDF_GOAL]=sshkdf.c +SOURCE[$X942KDF_GOAL]=x942kdf.c diff --git a/providers/implementations/kdfs/scrypt.c b/providers/implementations/kdfs/scrypt.c new file mode 100644 index 0000000000..505963eec5 --- /dev/null +++ b/providers/implementations/kdfs/scrypt.c @@ -0,0 +1,463 @@ +/* + * Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include +#include +#include +#include +#include "crypto/evp.h" +#include "internal/numbers.h" +#include "internal/provider_algs.h" +#include "internal/provider_ctx.h" +#include "internal/providercommonerr.h" +#include "internal/provider_algs.h" + +#ifndef OPENSSL_NO_SCRYPT + +static OSSL_OP_kdf_newctx_fn kdf_scrypt_new; +static OSSL_OP_kdf_freectx_fn kdf_scrypt_free; +static OSSL_OP_kdf_reset_fn kdf_scrypt_reset; +static OSSL_OP_kdf_derive_fn kdf_scrypt_derive; +static OSSL_OP_kdf_settable_ctx_params_fn kdf_scrypt_settable_ctx_params; +static OSSL_OP_kdf_set_ctx_params_fn kdf_scrypt_set_ctx_params; + +static int scrypt_alg(const char *pass, size_t passlen, + const unsigned char *salt, size_t saltlen, + uint64_t N, uint64_t r, uint64_t p, uint64_t maxmem, + unsigned char *key, size_t keylen, EVP_MD *sha256); + +typedef struct { + void *provctx; + unsigned char *pass; + size_t pass_len; + unsigned char *salt; + size_t salt_len; + uint64_t N; + uint64_t r, p; + uint64_t maxmem_bytes; + EVP_MD *sha256; +} KDF_SCRYPT; + +static void kdf_scrypt_init(KDF_SCRYPT *ctx); + +static void *kdf_scrypt_new(void *provctx) +{ + KDF_SCRYPT *ctx; + + ctx = OPENSSL_zalloc(sizeof(*ctx)); + if (ctx == NULL) { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + return NULL; + } + ctx->provctx = provctx; + ctx->sha256 = EVP_MD_fetch(PROV_LIBRARY_CONTEXT_OF(provctx), + "sha256", NULL); + if (ctx->sha256 == NULL) { + OPENSSL_free(ctx); + ERR_raise(ERR_LIB_PROV, PROV_R_UNABLE_TO_LOAD_SHA256); + return NULL; + } + kdf_scrypt_init(ctx); + return ctx; +} + +static void kdf_scrypt_free(void *vctx) +{ + KDF_SCRYPT *ctx = (KDF_SCRYPT *)vctx; + + EVP_MD_meth_free(ctx->sha256); + kdf_scrypt_reset(ctx); + OPENSSL_free(ctx); +} + +static void kdf_scrypt_reset(void *vctx) +{ + KDF_SCRYPT *ctx = (KDF_SCRYPT *)vctx; + + OPENSSL_free(ctx->salt); + OPENSSL_clear_free(ctx->pass, ctx->pass_len); + kdf_scrypt_init(ctx); +} + +static void kdf_scrypt_init(KDF_SCRYPT *ctx) +{ + /* Default values are the most conservative recommendation given in the + * original paper of C. Percival. Derivation uses roughly 1 GiB of memory + * for this parameter choice (approx. 128 * r * N * p bytes). + */ + ctx->N = 1 << 20; + ctx->r = 8; + ctx->p = 1; + ctx->maxmem_bytes = 1025 * 1024 * 1024; +} + +static int scrypt_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_scrypt_derive(void *vctx, unsigned char *key, + size_t keylen) +{ + KDF_SCRYPT *ctx = (KDF_SCRYPT *)vctx; + + 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 scrypt_alg((char *)ctx->pass, ctx->pass_len, ctx->salt, + ctx->salt_len, ctx->N, ctx->r, ctx->p, + ctx->maxmem_bytes, key, keylen, ctx->sha256); +} + +static int is_power_of_two(uint64_t value) +{ + return (value != 0) && ((value & (value - 1)) == 0); +} + +static int kdf_scrypt_set_ctx_params(void *vctx, const OSSL_PARAM params[]) +{ + const OSSL_PARAM *p; + KDF_SCRYPT *ctx = vctx; + uint64_t u64_value; + + if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PASSWORD)) != NULL) + if (!scrypt_set_membuf(&ctx->pass, &ctx->pass_len, p)) + return 0; + + if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SALT)) != NULL) + if (!scrypt_set_membuf(&ctx->salt, &ctx->salt_len, p)) + return 0; + + if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SCRYPT_N)) + != NULL) { + if (!OSSL_PARAM_get_uint64(p, &u64_value) + || u64_value <= 1 + || !is_power_of_two(u64_value)) + return 0; + ctx->N = u64_value; + } + + if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SCRYPT_R)) + != NULL) { + if (!OSSL_PARAM_get_uint64(p, &u64_value) || u64_value < 1) + return 0; + ctx->r = u64_value; + } + + if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SCRYPT_P)) + != NULL) { + if (!OSSL_PARAM_get_uint64(p, &u64_value) || u64_value < 1) + return 0; + ctx->p = u64_value; + } + + if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SCRYPT_MAXMEM)) + != NULL) { + if (!OSSL_PARAM_get_uint64(p, &u64_value) || u64_value < 1) + return 0; + ctx->maxmem_bytes = u64_value; + } + return 1; +} + +static const OSSL_PARAM *kdf_scrypt_settable_ctx_params(void) +{ + static const OSSL_PARAM known_settable_ctx_params[] = { + 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_SCRYPT_N, NULL), + OSSL_PARAM_uint32(OSSL_KDF_PARAM_SCRYPT_R, NULL), + OSSL_PARAM_uint32(OSSL_KDF_PARAM_SCRYPT_P, NULL), + OSSL_PARAM_uint64(OSSL_KDF_PARAM_SCRYPT_MAXMEM, NULL), + OSSL_PARAM_END + }; + return known_settable_ctx_params; +} + +static int kdf_scrypt_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_scrypt_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_scrypt_functions[] = { + { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))kdf_scrypt_new }, + { OSSL_FUNC_KDF_FREECTX, (void(*)(void))kdf_scrypt_free }, + { OSSL_FUNC_KDF_RESET, (void(*)(void))kdf_scrypt_reset }, + { OSSL_FUNC_KDF_DERIVE, (void(*)(void))kdf_scrypt_derive }, + { OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS, + (void(*)(void))kdf_scrypt_settable_ctx_params }, + { OSSL_FUNC_KDF_SET_CTX_PARAMS, (void(*)(void))kdf_scrypt_set_ctx_params }, + { OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS, + (void(*)(void))kdf_scrypt_gettable_ctx_params }, + { OSSL_FUNC_KDF_GET_CTX_PARAMS, (void(*)(void))kdf_scrypt_get_ctx_params }, + { 0, NULL } +}; + +#define R(a,b) (((a) << (b)) | ((a) >> (32 - (b)))) +static void salsa208_word_specification(uint32_t inout[16]) +{ + int i; + uint32_t x[16]; + + memcpy(x, inout, sizeof(x)); + for (i = 8; i > 0; i -= 2) { + x[4] ^= R(x[0] + x[12], 7); + x[8] ^= R(x[4] + x[0], 9); + x[12] ^= R(x[8] + x[4], 13); + x[0] ^= R(x[12] + x[8], 18); + x[9] ^= R(x[5] + x[1], 7); + x[13] ^= R(x[9] + x[5], 9); + x[1] ^= R(x[13] + x[9], 13); + x[5] ^= R(x[1] + x[13], 18); + x[14] ^= R(x[10] + x[6], 7); + x[2] ^= R(x[14] + x[10], 9); + x[6] ^= R(x[2] + x[14], 13); + x[10] ^= R(x[6] + x[2], 18); + x[3] ^= R(x[15] + x[11], 7); + x[7] ^= R(x[3] + x[15], 9); + x[11] ^= R(x[7] + x[3], 13); + x[15] ^= R(x[11] + x[7], 18); + x[1] ^= R(x[0] + x[3], 7); + x[2] ^= R(x[1] + x[0], 9); + x[3] ^= R(x[2] + x[1], 13); + x[0] ^= R(x[3] + x[2], 18); + x[6] ^= R(x[5] + x[4], 7); + x[7] ^= R(x[6] + x[5], 9); + x[4] ^= R(x[7] + x[6], 13); + x[5] ^= R(x[4] + x[7], 18); + x[11] ^= R(x[10] + x[9], 7); + x[8] ^= R(x[11] + x[10], 9); + x[9] ^= R(x[8] + x[11], 13); + x[10] ^= R(x[9] + x[8], 18); + x[12] ^= R(x[15] + x[14], 7); + x[13] ^= R(x[12] + x[15], 9); + x[14] ^= R(x[13] + x[12], 13); + x[15] ^= R(x[14] + x[13], 18); + } + for (i = 0; i < 16; ++i) + inout[i] += x[i]; + OPENSSL_cleanse(x, sizeof(x)); +} + +static void scryptBlockMix(uint32_t *B_, uint32_t *B, uint64_t r) +{ + uint64_t i, j; + uint32_t X[16], *pB; + + memcpy(X, B + (r * 2 - 1) * 16, sizeof(X)); + pB = B; + for (i = 0; i < r * 2; i++) { + for (j = 0; j < 16; j++) + X[j] ^= *pB++; + salsa208_word_specification(X); + memcpy(B_ + (i / 2 + (i & 1) * r) * 16, X, sizeof(X)); + } + OPENSSL_cleanse(X, sizeof(X)); +} + +static void scryptROMix(unsigned char *B, uint64_t r, uint64_t N, + uint32_t *X, uint32_t *T, uint32_t *V) +{ + unsigned char *pB; + uint32_t *pV; + uint64_t i, k; + + /* Convert from little endian input */ + for (pV = V, i = 0, pB = B; i < 32 * r; i++, pV++) { + *pV = *pB++; + *pV |= *pB++ << 8; + *pV |= *pB++ << 16; + *pV |= (uint32_t)*pB++ << 24; + } + + for (i = 1; i < N; i++, pV += 32 * r) + scryptBlockMix(pV, pV - 32 * r, r); + + scryptBlockMix(X, V + (N - 1) * 32 * r, r); + + for (i = 0; i < N; i++) { + uint32_t j; + j = X[16 * (2 * r - 1)] % N; + pV = V + 32 * r * j; + for (k = 0; k < 32 * r; k++) + T[k] = X[k] ^ *pV++; + scryptBlockMix(X, T, r); + } + /* Convert output to little endian */ + for (i = 0, pB = B; i < 32 * r; i++) { + uint32_t xtmp = X[i]; + *pB++ = xtmp & 0xff; + *pB++ = (xtmp >> 8) & 0xff; + *pB++ = (xtmp >> 16) & 0xff; + *pB++ = (xtmp >> 24) & 0xff; + } +} + +#ifndef SIZE_MAX +# define SIZE_MAX ((size_t)-1) +#endif + +/* + * Maximum power of two that will fit in uint64_t: this should work on + * most (all?) platforms. + */ + +#define LOG2_UINT64_MAX (sizeof(uint64_t) * 8 - 1) + +/* + * Maximum value of p * r: + * p <= ((2^32-1) * hLen) / MFLen => + * p <= ((2^32-1) * 32) / (128 * r) => + * p * r <= (2^30-1) + */ + +#define SCRYPT_PR_MAX ((1 << 30) - 1) + +static int scrypt_alg(const char *pass, size_t passlen, + const unsigned char *salt, size_t saltlen, + uint64_t N, uint64_t r, uint64_t p, uint64_t maxmem, + unsigned char *key, size_t keylen, EVP_MD *sha256) +{ + int rv = 0; + unsigned char *B; + uint32_t *X, *V, *T; + uint64_t i, Blen, Vlen; + + /* Sanity check parameters */ + /* initial check, r,p must be non zero, N >= 2 and a power of 2 */ + if (r == 0 || p == 0 || N < 2 || (N & (N - 1))) + return 0; + /* Check p * r < SCRYPT_PR_MAX avoiding overflow */ + if (p > SCRYPT_PR_MAX / r) { + EVPerr(EVP_F_SCRYPT_ALG, EVP_R_MEMORY_LIMIT_EXCEEDED); + return 0; + } + + /* + * Need to check N: if 2^(128 * r / 8) overflows limit this is + * automatically satisfied since N <= UINT64_MAX. + */ + + if (16 * r <= LOG2_UINT64_MAX) { + if (N >= (((uint64_t)1) << (16 * r))) { + EVPerr(EVP_F_SCRYPT_ALG, EVP_R_MEMORY_LIMIT_EXCEEDED); + return 0; + } + } + + /* Memory checks: check total allocated buffer size fits in uint64_t */ + + /* + * B size in section 5 step 1.S + * Note: we know p * 128 * r < UINT64_MAX because we already checked + * p * r < SCRYPT_PR_MAX + */ + Blen = p * 128 * r; + /* + * Yet we pass it as integer to PKCS5_PBKDF2_HMAC... [This would + * have to be revised when/if PKCS5_PBKDF2_HMAC accepts size_t.] + */ + if (Blen > INT_MAX) { + EVPerr(EVP_F_SCRYPT_ALG, EVP_R_MEMORY_LIMIT_EXCEEDED); + return 0; + } + + /* + * Check 32 * r * (N + 2) * sizeof(uint32_t) fits in uint64_t + * This is combined size V, X and T (section 4) + */ + i = UINT64_MAX / (32 * sizeof(uint32_t)); + if (N + 2 > i / r) { + EVPerr(EVP_F_SCRYPT_ALG, EVP_R_MEMORY_LIMIT_EXCEEDED); + return 0; + } + Vlen = 32 * r * (N + 2) * sizeof(uint32_t); + + /* check total allocated size fits in uint64_t */ + if (Blen > UINT64_MAX - Vlen) { + EVPerr(EVP_F_SCRYPT_ALG, EVP_R_MEMORY_LIMIT_EXCEEDED); + return 0; + } + + /* Check that the maximum memory doesn't exceed a size_t limits */ + if (maxmem > SIZE_MAX) + maxmem = SIZE_MAX; + + if (Blen + Vlen > maxmem) { + EVPerr(EVP_F_SCRYPT_ALG, EVP_R_MEMORY_LIMIT_EXCEEDED); + return 0; + } + + /* If no key return to indicate parameters are OK */ + if (key == NULL) + return 1; + + B = OPENSSL_malloc((size_t)(Blen + Vlen)); + if (B == NULL) { + EVPerr(EVP_F_SCRYPT_ALG, ERR_R_MALLOC_FAILURE); + return 0; + } + X = (uint32_t *)(B + Blen); + T = X + 32 * r; + V = T + 32 * r; + if (PKCS5_PBKDF2_HMAC(pass, passlen, salt, saltlen, 1, sha256, + (int)Blen, B) == 0) + goto err; + + for (i = 0; i < p; i++) + scryptROMix(B + 128 * r * i, r, N, X, T, V); + + if (PKCS5_PBKDF2_HMAC(pass, passlen, B, (int)Blen, 1, sha256, + keylen, key) == 0) + goto err; + rv = 1; + err: + if (rv == 0) + EVPerr(EVP_F_SCRYPT_ALG, EVP_R_PBKDF2_ERROR); + + OPENSSL_clear_free(B, (size_t)(Blen + Vlen)); + return rv; +} + +#endif diff --git a/providers/implementations/kdfs/sshkdf.c b/providers/implementations/kdfs/sshkdf.c new file mode 100644 index 0000000000..7e6445dbdd --- /dev/null +++ b/providers/implementations/kdfs/sshkdf.c @@ -0,0 +1,280 @@ +/* + * Copyright 2018-2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include +#include +#include +#include "internal/cryptlib.h" +#include "internal/numbers.h" +#include "crypto/evp.h" +#include "internal/provider_ctx.h" +#include "internal/providercommonerr.h" +#include "internal/provider_algs.h" +# include "internal/provider_util.h" + +/* See RFC 4253, Section 7.2 */ +static OSSL_OP_kdf_newctx_fn kdf_sshkdf_new; +static OSSL_OP_kdf_freectx_fn kdf_sshkdf_free; +static OSSL_OP_kdf_reset_fn kdf_sshkdf_reset; +static OSSL_OP_kdf_derive_fn kdf_sshkdf_derive; +static OSSL_OP_kdf_settable_ctx_params_fn kdf_sshkdf_settable_ctx_params; +static OSSL_OP_kdf_set_ctx_params_fn kdf_sshkdf_set_ctx_params; +static OSSL_OP_kdf_gettable_ctx_params_fn kdf_sshkdf_gettable_ctx_params; +static OSSL_OP_kdf_get_ctx_params_fn kdf_sshkdf_get_ctx_params; + +static int SSHKDF(const EVP_MD *evp_md, + const unsigned char *key, size_t key_len, + const unsigned char *xcghash, size_t xcghash_len, + const unsigned char *session_id, size_t session_id_len, + char type, unsigned char *okey, size_t okey_len); + +typedef struct { + void *provctx; + PROV_DIGEST digest; + unsigned char *key; /* K */ + size_t key_len; + unsigned char *xcghash; /* H */ + size_t xcghash_len; + char type; /* X */ + unsigned char *session_id; + size_t session_id_len; +} KDF_SSHKDF; + +static void *kdf_sshkdf_new(void *provctx) +{ + KDF_SSHKDF *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_sshkdf_free(void *vctx) +{ + KDF_SSHKDF *ctx = (KDF_SSHKDF *)vctx; + + kdf_sshkdf_reset(ctx); + OPENSSL_free(ctx); +} + +static void kdf_sshkdf_reset(void *vctx) +{ + KDF_SSHKDF *ctx = (KDF_SSHKDF *)vctx; + + ossl_prov_digest_reset(&ctx->digest); + OPENSSL_clear_free(ctx->key, ctx->key_len); + OPENSSL_clear_free(ctx->xcghash, ctx->xcghash_len); + OPENSSL_clear_free(ctx->session_id, ctx->session_id_len); + memset(ctx, 0, sizeof(*ctx)); +} + +static int sshkdf_set_membuf(unsigned char **dst, size_t *dst_len, + const OSSL_PARAM *p) +{ + OPENSSL_clear_free(*dst, *dst_len); + *dst = NULL; + return OSSL_PARAM_get_octet_string(p, (void **)dst, 0, dst_len); +} + +static int kdf_sshkdf_derive(void *vctx, unsigned char *key, + size_t keylen) +{ + KDF_SSHKDF *ctx = (KDF_SSHKDF *)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; + } + if (ctx->xcghash == NULL) { + ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_XCGHASH); + return 0; + } + if (ctx->session_id == NULL) { + ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_SESSION_ID); + return 0; + } + if (ctx->type == 0) { + ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_TYPE); + return 0; + } + return SSHKDF(md, ctx->key, ctx->key_len, + ctx->xcghash, ctx->xcghash_len, + ctx->session_id, ctx->session_id_len, + ctx->type, key, keylen); +} + +static int kdf_sshkdf_set_ctx_params(void *vctx, const OSSL_PARAM params[]) +{ + const OSSL_PARAM *p; + KDF_SSHKDF *ctx = vctx; + OPENSSL_CTX *provctx = PROV_LIBRARY_CONTEXT_OF(ctx->provctx); + int t; + + if (!ossl_prov_digest_load_from_params(&ctx->digest, params, provctx)) + return 0; + + if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_KEY)) != NULL) + if (!sshkdf_set_membuf(&ctx->key, &ctx->key_len, p)) + return 0; + + if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SSHKDF_XCGHASH)) + != NULL) + if (!sshkdf_set_membuf(&ctx->xcghash, &ctx->xcghash_len, p)) + return 0; + + if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SSHKDF_SESSION_ID)) + != NULL) + if (!sshkdf_set_membuf(&ctx->session_id, &ctx->session_id_len, p)) + return 0; + + if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SSHKDF_TYPE)) + != NULL) { + if (p->data == NULL || p->data_size == 0) + return 0; + t = *(unsigned char *)p->data; + if (t < 65 || t > 70) { + ERR_raise(ERR_LIB_PROV, PROV_R_VALUE_ERROR); + return 0; + } + ctx->type = (char)t; + } + return 1; +} + +static const OSSL_PARAM *kdf_sshkdf_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_KEY, NULL, 0), + OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SSHKDF_XCGHASH, NULL, 0), + OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SSHKDF_SESSION_ID, NULL, 0), + OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_SSHKDF_TYPE, NULL, 0), + OSSL_PARAM_END + }; + return known_settable_ctx_params; +} + +static int kdf_sshkdf_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_sshkdf_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_sshkdf_functions[] = { + { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))kdf_sshkdf_new }, + { OSSL_FUNC_KDF_FREECTX, (void(*)(void))kdf_sshkdf_free }, + { OSSL_FUNC_KDF_RESET, (void(*)(void))kdf_sshkdf_reset }, + { OSSL_FUNC_KDF_DERIVE, (void(*)(void))kdf_sshkdf_derive }, + { OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS, + (void(*)(void))kdf_sshkdf_settable_ctx_params }, + { OSSL_FUNC_KDF_SET_CTX_PARAMS, (void(*)(void))kdf_sshkdf_set_ctx_params }, + { OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS, + (void(*)(void))kdf_sshkdf_gettable_ctx_params }, + { OSSL_FUNC_KDF_GET_CTX_PARAMS, (void(*)(void))kdf_sshkdf_get_ctx_params }, + { 0, NULL } +}; + +static int SSHKDF(const EVP_MD *evp_md, + const unsigned char *key, size_t key_len, + const unsigned char *xcghash, size_t xcghash_len, + const unsigned char *session_id, size_t session_id_len, + char type, unsigned char *okey, size_t okey_len) +{ + EVP_MD_CTX *md = NULL; + unsigned char digest[EVP_MAX_MD_SIZE]; + unsigned int dsize = 0; + size_t cursize = 0; + int ret = 0; + + md = EVP_MD_CTX_new(); + if (md == NULL) + return 0; + + if (!EVP_DigestInit_ex(md, evp_md, NULL)) + goto out; + + if (!EVP_DigestUpdate(md, key, key_len)) + goto out; + + if (!EVP_DigestUpdate(md, xcghash, xcghash_len)) + goto out; + + if (!EVP_DigestUpdate(md, &type, 1)) + goto out; + + if (!EVP_DigestUpdate(md, session_id, session_id_len)) + goto out; + + if (!EVP_DigestFinal_ex(md, digest, &dsize)) + goto out; + + if (okey_len < dsize) { + memcpy(okey, digest, okey_len); + ret = 1; + goto out; + } + + memcpy(okey, digest, dsize); + + for (cursize = dsize; cursize < okey_len; cursize += dsize) { + + if (!EVP_DigestInit_ex(md, evp_md, NULL)) + goto out; + + if (!EVP_DigestUpdate(md, key, key_len)) + goto out; + + if (!EVP_DigestUpdate(md, xcghash, xcghash_len)) + goto out; + + if (!EVP_DigestUpdate(md, okey, cursize)) + goto out; + + if (!EVP_DigestFinal_ex(md, digest, &dsize)) + goto out; + + if (okey_len < cursize + dsize) { + memcpy(okey + cursize, digest, okey_len - cursize); + ret = 1; + goto out; + } + + memcpy(okey + cursize, digest, dsize); + } + + ret = 1; + +out: + EVP_MD_CTX_free(md); + OPENSSL_cleanse(digest, EVP_MAX_MD_SIZE); + return ret; +} + diff --git a/providers/implementations/kdfs/x942kdf.c b/providers/implementations/kdfs/x942kdf.c new file mode 100644 index 0000000000..65c586fb99 --- /dev/null +++ b/providers/implementations/kdfs/x942kdf.c @@ -0,0 +1,424 @@ +/* + * 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 + */ + +#include "e_os.h" + +#ifndef OPENSSL_NO_CMS + +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include "internal/cryptlib.h" +# include "internal/numbers.h" +# include "crypto/evp.h" +# include "internal/provider_ctx.h" +# include "internal/providercommonerr.h" +# include "internal/provider_algs.h" +# include "internal/provider_util.h" + +# define X942KDF_MAX_INLEN (1 << 30) + +static OSSL_OP_kdf_newctx_fn x942kdf_new; +static OSSL_OP_kdf_freectx_fn x942kdf_free; +static OSSL_OP_kdf_reset_fn x942kdf_reset; +static OSSL_OP_kdf_derive_fn x942kdf_derive; +static OSSL_OP_kdf_settable_ctx_params_fn x942kdf_settable_ctx_params; +static OSSL_OP_kdf_set_ctx_params_fn x942kdf_set_ctx_params; +static OSSL_OP_kdf_gettable_ctx_params_fn x942kdf_gettable_ctx_params; +static OSSL_OP_kdf_get_ctx_params_fn x942kdf_get_ctx_params; + +typedef struct { + void *provctx; + PROV_DIGEST digest; + unsigned char *secret; + size_t secret_len; + int cek_nid; + unsigned char *ukm; + size_t ukm_len; + size_t dkm_len; +} KDF_X942; + +/* A table of allowed wrapping algorithms and the associated output lengths */ +static const struct { + int nid; + size_t keklen; /* size in bytes */ +} kek_algs[] = { + { NID_id_smime_alg_CMS3DESwrap, 24 }, + { NID_id_smime_alg_CMSRC2wrap, 16 }, + { NID_id_aes128_wrap, 16 }, + { NID_id_aes192_wrap, 24 }, + { NID_id_aes256_wrap, 32 }, + { NID_id_camellia128_wrap, 16 }, + { NID_id_camellia192_wrap, 24 }, + { NID_id_camellia256_wrap, 32 } +}; + +/* Skip past an ASN1 structure: for OBJECT skip content octets too */ +static int skip_asn1(unsigned char **pp, long *plen, int exptag) +{ + int i, tag, xclass; + long tmplen; + const unsigned char *q = *pp; + + i = ASN1_get_object(&q, &tmplen, &tag, &xclass, *plen); + if ((i & 0x80) != 0 || tag != exptag || xclass != V_ASN1_UNIVERSAL) + return 0; + if (tag == V_ASN1_OBJECT) + q += tmplen; + *pp = (unsigned char *)q; + *plen -= q - *pp; + return 1; +} + +/* + * Encode the other info structure. + * + * RFC2631 Section 2.1.2 Contains the following definition for otherinfo + * + * OtherInfo ::= SEQUENCE { + * keyInfo KeySpecificInfo, + * partyAInfo [0] OCTET STRING OPTIONAL, + * suppPubInfo [2] OCTET STRING + * } + * + * KeySpecificInfo ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * counter OCTET STRING SIZE (4..4) + * } + * + * |nid| is the algorithm object identifier. + * |keylen| is the length (in bytes) of the generated KEK. It is stored into + * suppPubInfo (in bits). + * |ukm| is the optional user keying material that is stored into partyAInfo. It + * can be NULL. + * |ukmlen| is the user keying material length (in bytes). + * |der| is the returned encoded data. It must be freed by the caller. + * |der_len| is the returned size of the encoded data. + * |out_ctr| returns a pointer to the counter data which is embedded inside the + * encoded data. This allows the counter bytes to be updated without re-encoding. + * + * Returns: 1 if successfully encoded, or 0 otherwise. + * Assumptions: |der|, |der_len| & |out_ctr| are not NULL. + */ +static int x942_encode_otherinfo(int nid, size_t keylen, + const unsigned char *ukm, size_t ukmlen, + unsigned char **der, size_t *der_len, + unsigned char **out_ctr) +{ + unsigned char *p, *encoded = NULL; + int ret = 0, encoded_len; + long tlen; + /* "magic" value to check offset is sane */ + static unsigned char ctr[4] = { 0x00, 0x00, 0x00, 0x01 }; + X509_ALGOR *ksi = NULL; + ASN1_OBJECT *alg_oid = NULL; + ASN1_OCTET_STRING *ctr_oct = NULL, *ukm_oct = NULL; + + /* set the KeySpecificInfo - which contains an algorithm oid and counter */ + ksi = X509_ALGOR_new(); + alg_oid = OBJ_dup(OBJ_nid2obj(nid)); + ctr_oct = ASN1_OCTET_STRING_new(); + if (ksi == NULL + || alg_oid == NULL + || ctr_oct == NULL + || !ASN1_OCTET_STRING_set(ctr_oct, ctr, sizeof(ctr)) + || !X509_ALGOR_set0(ksi, alg_oid, V_ASN1_OCTET_STRING, ctr_oct)) + goto err; + /* NULL these as they now belong to ksi */ + alg_oid = NULL; + ctr_oct = NULL; + + /* Set the optional partyAInfo */ + if (ukm != NULL) { + ukm_oct = ASN1_OCTET_STRING_new(); + if (ukm_oct == NULL) + goto err; + ASN1_OCTET_STRING_set(ukm_oct, (unsigned char *)ukm, ukmlen); + } + /* Generate the OtherInfo DER data */ + encoded_len = CMS_SharedInfo_encode(&encoded, ksi, ukm_oct, keylen); + if (encoded_len <= 0) + goto err; + + /* Parse the encoded data to find the offset of the counter data */ + p = encoded; + tlen = (long)encoded_len; + if (skip_asn1(&p, &tlen, V_ASN1_SEQUENCE) + && skip_asn1(&p, &tlen, V_ASN1_SEQUENCE) + && skip_asn1(&p, &tlen, V_ASN1_OBJECT) + && skip_asn1(&p, &tlen, V_ASN1_OCTET_STRING) + && CRYPTO_memcmp(p, ctr, 4) == 0) { + *out_ctr = p; + *der = encoded; + *der_len = (size_t)encoded_len; + ret = 1; + } +err: + if (ret != 1) + OPENSSL_free(encoded); + ASN1_OCTET_STRING_free(ctr_oct); + ASN1_OCTET_STRING_free(ukm_oct); + ASN1_OBJECT_free(alg_oid); + X509_ALGOR_free(ksi); + return ret; +} + +static int x942kdf_hash_kdm(const EVP_MD *kdf_md, + const unsigned char *z, size_t z_len, + const unsigned char *other, size_t other_len, + unsigned char *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 mac[EVP_MAX_MD_SIZE]; + unsigned char *out = derived_key; + EVP_MD_CTX *ctx = NULL, *ctx_init = NULL; + + if (z_len > X942KDF_MAX_INLEN || other_len > X942KDF_MAX_INLEN + || derived_key_len > X942KDF_MAX_INLEN + || derived_key_len == 0) { + ERR_raise(ERR_LIB_PROV, PROV_R_BAD_LENGTH); + 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++) { + /* updating the ctr modifies 4 bytes in the 'other' buffer */ + ctr[0] = (unsigned char)((counter >> 24) & 0xff); + ctr[1] = (unsigned char)((counter >> 16) & 0xff); + ctr[2] = (unsigned char)((counter >> 8) & 0xff); + ctr[3] = (unsigned char)(counter & 0xff); + + if (!EVP_MD_CTX_copy_ex(ctx, ctx_init) + || !EVP_DigestUpdate(ctx, z, z_len) + || !EVP_DigestUpdate(ctx, other, other_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_free(ctx); + EVP_MD_CTX_free(ctx_init); + OPENSSL_cleanse(mac, sizeof(mac)); + return ret; +} + +static void *x942kdf_new(void *provctx) +{ + KDF_X942 *ctx; + + if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + ctx->provctx = provctx; + return ctx; +} + +static void x942kdf_reset(void *vctx) +{ + KDF_X942 *ctx = (KDF_X942 *)vctx; + + ossl_prov_digest_reset(&ctx->digest); + OPENSSL_clear_free(ctx->secret, ctx->secret_len); + OPENSSL_clear_free(ctx->ukm, ctx->ukm_len); + memset(ctx, 0, sizeof(*ctx)); +} + +static void x942kdf_free(void *vctx) +{ + KDF_X942 *ctx = (KDF_X942 *)vctx; + + x942kdf_reset(ctx); + OPENSSL_free(ctx); +} + +static int x942kdf_set_buffer(unsigned char **out, size_t *out_len, + const OSSL_PARAM *p) +{ + if (p->data_size == 0 || p->data == NULL) + return 1; + + OPENSSL_free(*out); + *out = NULL; + return OSSL_PARAM_get_octet_string(p, (void **)out, 0, out_len); +} + +static size_t x942kdf_size(KDF_X942 *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 x942kdf_derive(void *vctx, unsigned char *key, size_t keylen) +{ + KDF_X942 *ctx = (KDF_X942 *)vctx; + const EVP_MD *md = ossl_prov_digest_md(&ctx->digest); + int ret = 0; + unsigned char *ctr; + unsigned char *der = NULL; + size_t der_len = 0; + + if (ctx->secret == NULL) { + ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_SECRET); + return 0; + } + if (md == NULL) { + ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST); + return 0; + } + if (ctx->cek_nid == NID_undef) { + ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_CEK_ALG); + return 0; + } + if (ctx->ukm != NULL && ctx->ukm_len >= X942KDF_MAX_INLEN) { + /* + * Note the ukm length MUST be 512 bits. + * For backwards compatibility the old check is being done. + */ + ERR_raise(ERR_LIB_PROV, PROV_R_INAVLID_UKM_LENGTH); + return 0; + } + if (keylen != ctx->dkm_len) { + ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_CEK_ALG); + return 0; + } + /* generate the otherinfo der */ + if (!x942_encode_otherinfo(ctx->cek_nid, ctx->dkm_len, + ctx->ukm, ctx->ukm_len, + &der, &der_len, &ctr)) { + ERR_raise(ERR_LIB_PROV, PROV_R_BAD_ENCODING); + return 0; + } + ret = x942kdf_hash_kdm(md, ctx->secret, ctx->secret_len, + der, der_len, ctr, key, keylen); + OPENSSL_free(der); + return ret; +} + +static int x942kdf_set_ctx_params(void *vctx, const OSSL_PARAM params[]) +{ + const OSSL_PARAM *p; + KDF_X942 *ctx = vctx; + OPENSSL_CTX *provctx = PROV_LIBRARY_CONTEXT_OF(ctx->provctx); + size_t i; + + if (!ossl_prov_digest_load_from_params(&ctx->digest, params, provctx)) + 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 (!x942kdf_set_buffer(&ctx->secret, &ctx->secret_len, p)) + return 0; + + if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_UKM)) != NULL) + if (!x942kdf_set_buffer(&ctx->ukm, &ctx->ukm_len, p)) + return 0; + + if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_CEK_ALG)) != NULL) { + if (p->data_type != OSSL_PARAM_UTF8_STRING) + return 0; + ctx->cek_nid = OBJ_sn2nid(p->data); + for (i = 0; i < OSSL_NELEM(kek_algs); i++) + if (kek_algs[i].nid == ctx->cek_nid) + goto cek_found; + ERR_raise(ERR_LIB_PROV, PROV_R_UNSUPPORTED_CEK_ALG); + return 0; +cek_found: + ctx->dkm_len = kek_algs[i].keklen; + } + return 1; +} + +static const OSSL_PARAM *x942kdf_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_KEY, NULL, 0), + OSSL_PARAM_octet_string(OSSL_KDF_PARAM_UKM, NULL, 0), + OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_CEK_ALG, NULL, 0), + OSSL_PARAM_END + }; + return known_settable_ctx_params; +} + +static int x942kdf_get_ctx_params(void *vctx, OSSL_PARAM params[]) +{ + KDF_X942 *ctx = (KDF_X942 *)vctx; + OSSL_PARAM *p; + + if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE)) != NULL) + return OSSL_PARAM_set_size_t(p, x942kdf_size(ctx)); + return -2; +} + +static const OSSL_PARAM *x942kdf_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_x942_kdf_functions[] = { + { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))x942kdf_new }, + { OSSL_FUNC_KDF_FREECTX, (void(*)(void))x942kdf_free }, + { OSSL_FUNC_KDF_RESET, (void(*)(void))x942kdf_reset }, + { OSSL_FUNC_KDF_DERIVE, (void(*)(void))x942kdf_derive }, + { OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS, + (void(*)(void))x942kdf_settable_ctx_params }, + { OSSL_FUNC_KDF_SET_CTX_PARAMS, (void(*)(void))x942kdf_set_ctx_params }, + { OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS, + (void(*)(void))x942kdf_gettable_ctx_params }, + { OSSL_FUNC_KDF_GET_CTX_PARAMS, (void(*)(void))x942kdf_get_ctx_params }, + { 0, NULL } +}; + +#endif /* OPENSSL_NO_CMS */ diff --git a/providers/implementations/macs/blake2_mac_impl.c b/providers/implementations/macs/blake2_mac_impl.c new file mode 100644 index 0000000000..a190b91b98 --- /dev/null +++ b/providers/implementations/macs/blake2_mac_impl.c @@ -0,0 +1,220 @@ +/* + * Copyright 2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include + +#include "internal/blake2.h" +#include "internal/cryptlib.h" +#include "internal/providercommonerr.h" +#include "internal/provider_algs.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 blake2_mac_new; +static OSSL_OP_mac_dupctx_fn blake2_mac_dup; +static OSSL_OP_mac_freectx_fn blake2_mac_free; +static OSSL_OP_mac_gettable_ctx_params_fn blake2_gettable_ctx_params; +static OSSL_OP_mac_get_ctx_params_fn blake2_get_ctx_params; +static OSSL_OP_mac_settable_ctx_params_fn blake2_mac_settable_ctx_params; +static OSSL_OP_mac_set_ctx_params_fn blake2_mac_set_ctx_params; +static OSSL_OP_mac_init_fn blake2_mac_init; +static OSSL_OP_mac_update_fn blake2_mac_update; +static OSSL_OP_mac_final_fn blake2_mac_final; + +struct blake2_mac_data_st { + BLAKE2_CTX ctx; + BLAKE2_PARAM params; + unsigned char key[BLAKE2_KEYBYTES]; +}; + +static size_t blake2_mac_size(void *vmacctx); + +static void *blake2_mac_new(void *unused_provctx) +{ + struct blake2_mac_data_st *macctx = OPENSSL_zalloc(sizeof(*macctx)); + + if (macctx != NULL) { + BLAKE2_PARAM_INIT(&macctx->params); + /* ctx initialization is deferred to BLAKE2b_Init() */ + } + return macctx; +} + +static void *blake2_mac_dup(void *vsrc) +{ + struct blake2_mac_data_st *dst; + struct blake2_mac_data_st *src = vsrc; + + dst = OPENSSL_zalloc(sizeof(*dst)); + if (dst == NULL) + return NULL; + + *dst = *src; + return dst; +} + +static void blake2_mac_free(void *vmacctx) +{ + struct blake2_mac_data_st *macctx = vmacctx; + + if (macctx != NULL) { + OPENSSL_cleanse(macctx->key, sizeof(macctx->key)); + OPENSSL_free(macctx); + } +} + +static int blake2_mac_init(void *vmacctx) +{ + struct blake2_mac_data_st *macctx = vmacctx; + + /* Check key has been set */ + if (macctx->params.key_length == 0) { + ERR_raise(ERR_LIB_PROV, PROV_R_NO_KEY_SET); + return 0; + } + + return BLAKE2_INIT_KEY(&macctx->ctx, &macctx->params, macctx->key); +} + +static int blake2_mac_update(void *vmacctx, + const unsigned char *data, size_t datalen) +{ + struct blake2_mac_data_st *macctx = vmacctx; + + return BLAKE2_UPDATE(&macctx->ctx, data, datalen); +} + +static int blake2_mac_final(void *vmacctx, + unsigned char *out, size_t *outl, + size_t outsize) +{ + struct blake2_mac_data_st *macctx = vmacctx; + + return BLAKE2_FINAL(out, &macctx->ctx); +} + +static const OSSL_PARAM known_gettable_ctx_params[] = { + OSSL_PARAM_size_t(OSSL_MAC_PARAM_SIZE, NULL), + OSSL_PARAM_END +}; +static const OSSL_PARAM *blake2_gettable_ctx_params(void) +{ + return known_gettable_ctx_params; +} + +static int blake2_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, blake2_mac_size(vmacctx)); + + return 1; +} + +static const OSSL_PARAM known_settable_ctx_params[] = { + 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_octet_string(OSSL_MAC_PARAM_SALT, NULL, 0), + OSSL_PARAM_END +}; +static const OSSL_PARAM *blake2_mac_settable_ctx_params() +{ + return known_settable_ctx_params; +} + +/* + * ALL parameters should be set before init(). + */ +static int blake2_mac_set_ctx_params(void *vmacctx, const OSSL_PARAM params[]) +{ + struct blake2_mac_data_st *macctx = vmacctx; + const OSSL_PARAM *p; + + if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_SIZE)) != NULL) { + size_t size; + + if (!OSSL_PARAM_get_size_t(p, &size) + || size < 1 + || size > BLAKE2_OUTBYTES) { + ERR_raise(ERR_LIB_PROV, PROV_R_NOT_XOF_OR_INVALID_LENGTH); + return 0; + } + BLAKE2_PARAM_SET_DIGEST_LENGTH(&macctx->params, (uint8_t)size); + } + + if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_KEY)) != NULL) { + size_t len; + void *key_p = macctx->key; + + if (!OSSL_PARAM_get_octet_string(p, &key_p, BLAKE2_KEYBYTES, &len)) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH); + return 0; + } + /* Pad with zeroes at the end */ + memset(macctx->key + len, 0, BLAKE2_KEYBYTES - len); + + BLAKE2_PARAM_SET_KEY_LENGTH(&macctx->params, (uint8_t)len); + } + + if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_CUSTOM)) + != NULL) { + /* + * The OSSL_PARAM API doesn't provide direct pointer use, so we + * must handle the OSSL_PARAM structure ourselves here + */ + if (p->data_size > BLAKE2_PERSONALBYTES) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_CUSTOM_LENGTH); + return 0; + } + BLAKE2_PARAM_SET_PERSONAL(&macctx->params, p->data, p->data_size); + } + + if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_SALT)) != NULL) { + /* + * The OSSL_PARAM API doesn't provide direct pointer use, so we + * must handle the OSSL_PARAM structure ourselves here as well + */ + if (p->data_size > BLAKE2_SALTBYTES) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_SALT_LENGTH); + return 0; + } + BLAKE2_PARAM_SET_SALT(&macctx->params, p->data, p->data_size); + } + return 1; +} + +static size_t blake2_mac_size(void *vmacctx) +{ + struct blake2_mac_data_st *macctx = vmacctx; + + return macctx->params.digest_length; +} + +const OSSL_DISPATCH BLAKE2_FUNCTIONS[] = { + { OSSL_FUNC_MAC_NEWCTX, (void (*)(void))blake2_mac_new }, + { OSSL_FUNC_MAC_DUPCTX, (void (*)(void))blake2_mac_dup }, + { OSSL_FUNC_MAC_FREECTX, (void (*)(void))blake2_mac_free }, + { OSSL_FUNC_MAC_INIT, (void (*)(void))blake2_mac_init }, + { OSSL_FUNC_MAC_UPDATE, (void (*)(void))blake2_mac_update }, + { OSSL_FUNC_MAC_FINAL, (void (*)(void))blake2_mac_final }, + { OSSL_FUNC_MAC_GETTABLE_CTX_PARAMS, + (void (*)(void))blake2_gettable_ctx_params }, + { OSSL_FUNC_MAC_GET_CTX_PARAMS, (void (*)(void))blake2_get_ctx_params }, + { OSSL_FUNC_MAC_SETTABLE_CTX_PARAMS, + (void (*)(void))blake2_mac_settable_ctx_params }, + { OSSL_FUNC_MAC_SET_CTX_PARAMS, (void (*)(void))blake2_mac_set_ctx_params }, + { 0, NULL } +}; diff --git a/providers/implementations/macs/blake2b_mac.c b/providers/implementations/macs/blake2b_mac.c new file mode 100644 index 0000000000..aa1a8dee1f --- /dev/null +++ b/providers/implementations/macs/blake2b_mac.c @@ -0,0 +1,32 @@ +/* + * 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 + */ + +/* Constants */ +#define BLAKE2_CTX BLAKE2B_CTX +#define BLAKE2_PARAM BLAKE2B_PARAM +#define BLAKE2_KEYBYTES BLAKE2B_KEYBYTES +#define BLAKE2_OUTBYTES BLAKE2B_OUTBYTES +#define BLAKE2_PERSONALBYTES BLAKE2B_PERSONALBYTES +#define BLAKE2_SALTBYTES BLAKE2B_SALTBYTES + +/* Function names */ +#define BLAKE2_PARAM_INIT blake2b_param_init +#define BLAKE2_INIT_KEY blake2b_init_key +#define BLAKE2_UPDATE blake2b_update +#define BLAKE2_FINAL blake2b_final +#define BLAKE2_PARAM_SET_DIGEST_LENGTH blake2b_param_set_digest_length +#define BLAKE2_PARAM_SET_KEY_LENGTH blake2b_param_set_key_length +#define BLAKE2_PARAM_SET_PERSONAL blake2b_param_set_personal +#define BLAKE2_PARAM_SET_SALT blake2b_param_set_salt + +/* OSSL_DISPATCH symbol */ +#define BLAKE2_FUNCTIONS blake2bmac_functions + +#include "blake2_mac_impl.c" + diff --git a/providers/implementations/macs/blake2s_mac.c b/providers/implementations/macs/blake2s_mac.c new file mode 100644 index 0000000000..ccd7035523 --- /dev/null +++ b/providers/implementations/macs/blake2s_mac.c @@ -0,0 +1,31 @@ +/* + * 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 + */ + +/* Constants */ +#define BLAKE2_CTX BLAKE2S_CTX +#define BLAKE2_PARAM BLAKE2S_PARAM +#define BLAKE2_KEYBYTES BLAKE2S_KEYBYTES +#define BLAKE2_OUTBYTES BLAKE2S_OUTBYTES +#define BLAKE2_PERSONALBYTES BLAKE2S_PERSONALBYTES +#define BLAKE2_SALTBYTES BLAKE2S_SALTBYTES + +/* Function names */ +#define BLAKE2_PARAM_INIT blake2s_param_init +#define BLAKE2_INIT_KEY blake2s_init_key +#define BLAKE2_UPDATE blake2s_update +#define BLAKE2_FINAL blake2s_final +#define BLAKE2_PARAM_SET_DIGEST_LENGTH blake2s_param_set_digest_length +#define BLAKE2_PARAM_SET_KEY_LENGTH blake2s_param_set_key_length +#define BLAKE2_PARAM_SET_PERSONAL blake2s_param_set_personal +#define BLAKE2_PARAM_SET_SALT blake2s_param_set_salt + +/* OSSL_DISPATCH symbol */ +#define BLAKE2_FUNCTIONS blake2smac_functions + +#include "blake2_mac_impl.c" diff --git a/providers/implementations/macs/build.info b/providers/implementations/macs/build.info index d4538098e0..07c40d354b 100644 --- a/providers/implementations/macs/build.info +++ b/providers/implementations/macs/build.info @@ -5,6 +5,9 @@ $GMAC_GOAL=../../libimplementations.a $HMAC_GOAL=../../libimplementations.a $KMAC_GOAL=../../libimplementations.a $CMAC_GOAL=../../libimplementations.a +$BLAKE2_GOAL=../../libimplementations.a +$SIPHASH_GOAL=../../libimplementations.a +$POLY1305_GOAL=../../libimplementations.a SOURCE[$GMAC_GOAL]=gmac_prov.c SOURCE[$HMAC_GOAL]=hmac_prov.c @@ -13,3 +16,17 @@ SOURCE[$KMAC_GOAL]=kmac_prov.c IF[{- !$disabled{cmac} -}] SOURCE[$CMAC_GOAL]=cmac_prov.c ENDIF + +$GOAL=../../libimplementations.a + +IF[{- !$disabled{blake2} -}] + SOURCE[$BLAKE2_GOAL]=blake2b_mac.c blake2s_mac.c +ENDIF + +IF[{- !$disabled{siphash} -}] + SOURCE[$SIPHASH_GOAL]=siphash_prov.c +ENDIF + +IF[{- !$disabled{poly1305} -}] + SOURCE[$POLY1305_GOAL]=poly1305_prov.c +ENDIF diff --git a/providers/implementations/macs/poly1305_prov.c b/providers/implementations/macs/poly1305_prov.c new file mode 100644 index 0000000000..88005716e6 --- /dev/null +++ b/providers/implementations/macs/poly1305_prov.c @@ -0,0 +1,162 @@ +/* + * Copyright 2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include +#include + +#include "crypto/poly1305.h" +/* + * TODO(3.0) when poly1305 has moved entirely to our providers, this + * header should be moved to the provider include directory. For the + * moment, crypto/poly1305/poly1305_ameth.c has us stuck. + */ +#include "../../../crypto/poly1305/poly1305_local.h" + +#include "internal/providercommonerr.h" +#include "internal/provider_algs.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 poly1305_new; +static OSSL_OP_mac_dupctx_fn poly1305_dup; +static OSSL_OP_mac_freectx_fn poly1305_free; +static OSSL_OP_mac_gettable_params_fn poly1305_gettable_params; +static OSSL_OP_mac_get_params_fn poly1305_get_params; +static OSSL_OP_mac_settable_ctx_params_fn poly1305_settable_ctx_params; +static OSSL_OP_mac_set_ctx_params_fn poly1305_set_ctx_params; +static OSSL_OP_mac_init_fn poly1305_init; +static OSSL_OP_mac_update_fn poly1305_update; +static OSSL_OP_mac_final_fn poly1305_final; + +struct poly1305_data_st { + void *provctx; + POLY1305 poly1305; /* Poly1305 data */ +}; + +static size_t poly1305_size(void); + +static void *poly1305_new(void *provctx) +{ + struct poly1305_data_st *ctx = OPENSSL_zalloc(sizeof(*ctx)); + + ctx->provctx = provctx; + return ctx; +} + +static void poly1305_free(void *vmacctx) +{ + OPENSSL_free(vmacctx); +} + +static void *poly1305_dup(void *vsrc) +{ + struct poly1305_data_st *src = vsrc; + struct poly1305_data_st *dst = poly1305_new(src->provctx); + + if (dst == NULL) + return NULL; + + dst->poly1305 = src->poly1305; + return dst; +} + +static size_t poly1305_size(void) +{ + return POLY1305_DIGEST_SIZE; +} + +static int poly1305_init(void *vmacctx) +{ + /* initialize the context in MAC_ctrl function */ + return 1; +} + +static int poly1305_update(void *vmacctx, const unsigned char *data, + size_t datalen) +{ + struct poly1305_data_st *ctx = vmacctx; + + /* poly1305 has nothing to return in its update function */ + Poly1305_Update(&ctx->poly1305, data, datalen); + return 1; +} + +static int poly1305_final(void *vmacctx, unsigned char *out, size_t *outl, + size_t outsize) +{ + struct poly1305_data_st *ctx = vmacctx; + + Poly1305_Final(&ctx->poly1305, out); + return 1; +} + +static const OSSL_PARAM known_gettable_params[] = { + OSSL_PARAM_size_t(OSSL_MAC_PARAM_SIZE, NULL), + OSSL_PARAM_END +}; +static const OSSL_PARAM *poly1305_gettable_params(void) +{ + return known_gettable_params; +} + +static int poly1305_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, poly1305_size()); + + return 1; +} + +static const OSSL_PARAM known_settable_ctx_params[] = { + OSSL_PARAM_octet_string(OSSL_MAC_PARAM_KEY, NULL, 0), + OSSL_PARAM_END +}; +static const OSSL_PARAM *poly1305_settable_ctx_params(void) +{ + return known_settable_ctx_params; +} + +static int poly1305_set_ctx_params(void *vmacctx, const OSSL_PARAM *params) +{ + struct poly1305_data_st *ctx = vmacctx; + const OSSL_PARAM *p = NULL; + + if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_KEY)) != NULL) { + if (p->data_type != OSSL_PARAM_OCTET_STRING + || p->data_size != POLY1305_KEY_SIZE) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH); + return 0; + } + Poly1305_Init(&ctx->poly1305, p->data); + } + return 1; +} + +const OSSL_DISPATCH poly1305_functions[] = { + { OSSL_FUNC_MAC_NEWCTX, (void (*)(void))poly1305_new }, + { OSSL_FUNC_MAC_DUPCTX, (void (*)(void))poly1305_dup }, + { OSSL_FUNC_MAC_FREECTX, (void (*)(void))poly1305_free }, + { OSSL_FUNC_MAC_INIT, (void (*)(void))poly1305_init }, + { OSSL_FUNC_MAC_UPDATE, (void (*)(void))poly1305_update }, + { OSSL_FUNC_MAC_FINAL, (void (*)(void))poly1305_final }, + { OSSL_FUNC_MAC_GETTABLE_PARAMS, (void (*)(void))poly1305_gettable_params }, + { OSSL_FUNC_MAC_GET_PARAMS, (void (*)(void))poly1305_get_params }, + { OSSL_FUNC_MAC_SETTABLE_CTX_PARAMS, + (void (*)(void))poly1305_settable_ctx_params }, + { OSSL_FUNC_MAC_SET_CTX_PARAMS, (void (*)(void))poly1305_set_ctx_params }, + { 0, NULL } +}; diff --git a/providers/implementations/macs/siphash_prov.c b/providers/implementations/macs/siphash_prov.c new file mode 100644 index 0000000000..a9511925f0 --- /dev/null +++ b/providers/implementations/macs/siphash_prov.c @@ -0,0 +1,173 @@ +/* + * Copyright 2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include +#include +#include + +#include "crypto/siphash.h" +/* + * TODO(3.0) when siphash has moved entirely to our providers, this + * header should be moved to the provider include directory. For the + * moment, crypto/siphash/siphash_ameth.c has us stuck. + */ +#include "../../../crypto/siphash/siphash_local.h" + +#include "internal/providercommonerr.h" +#include "internal/provider_algs.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 siphash_new; +static OSSL_OP_mac_dupctx_fn siphash_dup; +static OSSL_OP_mac_freectx_fn siphash_free; +static OSSL_OP_mac_gettable_ctx_params_fn siphash_gettable_ctx_params; +static OSSL_OP_mac_get_ctx_params_fn siphash_get_ctx_params; +static OSSL_OP_mac_settable_ctx_params_fn siphash_settable_params; +static OSSL_OP_mac_set_ctx_params_fn siphash_set_params; +static OSSL_OP_mac_size_fn siphash_size; +static OSSL_OP_mac_init_fn siphash_init; +static OSSL_OP_mac_update_fn siphash_update; +static OSSL_OP_mac_final_fn siphash_final; + +struct siphash_data_st { + void *provctx; + SIPHASH siphash; /* Siphash data */ +}; + +static void *siphash_new(void *provctx) +{ + struct siphash_data_st *ctx = OPENSSL_zalloc(sizeof(*ctx)); + + ctx->provctx = provctx; + return ctx; +} + +static void siphash_free(void *vmacctx) +{ + OPENSSL_free(vmacctx); +} + +static void *siphash_dup(void *vsrc) +{ + struct siphash_data_st *ssrc = vsrc; + struct siphash_data_st *sdst = siphash_new(ssrc->provctx); + + if (sdst == NULL) + return NULL; + + sdst->siphash = ssrc->siphash; + return sdst; +} + +static size_t siphash_size(void *vmacctx) +{ + struct siphash_data_st *ctx = vmacctx; + + return SipHash_hash_size(&ctx->siphash); +} + +static int siphash_init(void *vmacctx) +{ + /* Not much to do here, actual initialization happens through controls */ + return 1; +} + +static int siphash_update(void *vmacctx, const unsigned char *data, + size_t datalen) +{ + struct siphash_data_st *ctx = vmacctx; + + SipHash_Update(&ctx->siphash, data, datalen); + return 1; +} + +static int siphash_final(void *vmacctx, unsigned char *out, size_t *outl, + size_t outsize) +{ + struct siphash_data_st *ctx = vmacctx; + size_t hlen = siphash_size(ctx); + + if (outsize < hlen) + return 0; + + *outl = hlen; + return SipHash_Final(&ctx->siphash, out, hlen); +} + +static const OSSL_PARAM known_gettable_ctx_params[] = { + OSSL_PARAM_size_t(OSSL_MAC_PARAM_SIZE, NULL), + OSSL_PARAM_END +}; +static const OSSL_PARAM *siphash_gettable_ctx_params(void) +{ + return known_gettable_ctx_params; +} + +static int siphash_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, siphash_size(vmacctx)); + + return 1; +} + +static const OSSL_PARAM known_settable_ctx_params[] = { + OSSL_PARAM_size_t(OSSL_MAC_PARAM_SIZE, NULL), + OSSL_PARAM_octet_string(OSSL_MAC_PARAM_KEY, NULL, 0), + OSSL_PARAM_END +}; +static const OSSL_PARAM *siphash_settable_params(void) +{ + return known_settable_ctx_params; +} + +static int siphash_set_params(void *vmacctx, const OSSL_PARAM *params) +{ + struct siphash_data_st *ctx = vmacctx; + const OSSL_PARAM *p = NULL; + + if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_SIZE)) != NULL) { + size_t size; + + if (!OSSL_PARAM_get_size_t(p, &size) + || !SipHash_set_hash_size(&ctx->siphash, size)) + return 0; + } + if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_KEY)) != NULL) + if (p->data_type != OSSL_PARAM_OCTET_STRING + || p->data_size != SIPHASH_KEY_SIZE + || !SipHash_Init(&ctx->siphash, p->data, 0, 0)) + return 0; + return 1; +} + +const OSSL_DISPATCH siphash_functions[] = { + { OSSL_FUNC_MAC_NEWCTX, (void (*)(void))siphash_new }, + { OSSL_FUNC_MAC_DUPCTX, (void (*)(void))siphash_dup }, + { OSSL_FUNC_MAC_FREECTX, (void (*)(void))siphash_free }, + { OSSL_FUNC_MAC_INIT, (void (*)(void))siphash_init }, + { OSSL_FUNC_MAC_UPDATE, (void (*)(void))siphash_update }, + { OSSL_FUNC_MAC_FINAL, (void (*)(void))siphash_final }, + { OSSL_FUNC_MAC_GETTABLE_CTX_PARAMS, + (void (*)(void))siphash_gettable_ctx_params }, + { OSSL_FUNC_MAC_GET_CTX_PARAMS, (void (*)(void))siphash_get_ctx_params }, + { OSSL_FUNC_MAC_SETTABLE_CTX_PARAMS, + (void (*)(void))siphash_settable_params }, + { OSSL_FUNC_MAC_SET_CTX_PARAMS, (void (*)(void))siphash_set_params }, + { 0, NULL } +};