From: Richard Levitte Date: Tue, 3 Dec 2019 18:41:05 +0000 (+0100) Subject: Move providers/common/{ciphers,digests}/* to providers/implementations X-Git-Tag: openssl-3.0.0-alpha1~838 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=68a51d59a29796803af3b6e7f0142feca2622c9e;p=oweals%2Fopenssl.git Move providers/common/{ciphers,digests}/* to providers/implementations The idea to have all these things in providers/common was viable as long as the implementations was spread around their main providers. This is, however, no longer the case, so we move the common blocks closer to the source that use them. Reviewed-by: Paul Dale (Merged from https://github.com/openssl/openssl/pull/10564) --- diff --git a/providers/build.info b/providers/build.info index c31c4271de..39e767fb0e 100644 --- a/providers/build.info +++ b/providers/build.info @@ -40,14 +40,14 @@ $LIBNONFIPS=libnonfips.a $LIBFIPS=libfips.a # Enough of our implementations include prov/ciphercommon.h (present in -# providers/common/include), which includes crypto/ciphermode_platform.h +# providers/implementations/include), which includes crypto/ciphermode_platform.h # (present in include), which in turn may include very internal header # files in crypto/, so let's have a common include list for them all. -$COMMON_INCLUDES=../crypto ../include common/include +$COMMON_INCLUDES=../crypto ../include implementations/include common/include INCLUDE[$LIBCOMMON]=$COMMON_INCLUDES -INCLUDE[$LIBIMPLEMENTATIONS]=.. $COMMON_INCLUDES implementations/include -INCLUDE[$LIBLEGACY]=$COMMON_INCLUDES implementations/include +INCLUDE[$LIBIMPLEMENTATIONS]=.. $COMMON_INCLUDES +INCLUDE[$LIBLEGACY]=$COMMON_INCLUDES INCLUDE[$LIBNONFIPS]=$COMMON_INCLUDES INCLUDE[$LIBFIPS]=.. $COMMON_INCLUDES DEFINE[$LIBFIPS]=FIPS_MODE @@ -84,7 +84,7 @@ $DEFAULTGOAL=../libcrypto SOURCE[$DEFAULTGOAL]=$LIBIMPLEMENTATIONS $LIBNONFIPS SOURCE[$DEFAULTGOAL]=defltprov.c # Some legacy implementations depend on provider header files -INCLUDE[../libcrypto]=implementations/include +INCLUDE[$DEFAULTGOAL]=implementations/include LIBS=$DEFAULTGOAL diff --git a/providers/common/build.info b/providers/common/build.info index 3f20fb3c09..ccc99e515b 100644 --- a/providers/common/build.info +++ b/providers/common/build.info @@ -1,5 +1,3 @@ -SUBDIRS=digests ciphers - SOURCE[../libcommon.a]=provider_err.c bio_prov.c $FIPSCOMMON=provider_util.c SOURCE[../libnonfips.a]=$FIPSCOMMON nid_to_name.c diff --git a/providers/common/ciphers/block.c b/providers/common/ciphers/block.c deleted file mode 100644 index 95acfaf323..0000000000 --- a/providers/common/ciphers/block.c +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. - * - * Licensed under the Apache License 2.0 (the "License"). You may not use - * this file except in compliance with the License. You can obtain a copy - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ - -#include -#include "cipher_local.h" -#include "prov/providercommonerr.h" - -/* - * Fills a single block of buffered data from the input, and returns the amount - * of data remaining in the input that is a multiple of the blocksize. The buffer - * is only filled if it already has some data in it, isn't full already or we - * don't have at least one block in the input. - * - * buf: a buffer of blocksize bytes - * buflen: contains the amount of data already in buf on entry. Updated with the - * amount of data in buf at the end. On entry *buflen must always be - * less than the blocksize - * blocksize: size of a block. Must be greater than 0 and a power of 2 - * in: pointer to a pointer containing the input data - * inlen: amount of input data available - * - * On return buf is filled with as much data as possible up to a full block, - * *buflen is updated containing the amount of data in buf. *in is updated to - * the new location where input data should be read from, *inlen is updated with - * the remaining amount of data in *in. Returns the largest value <= *inlen - * which is a multiple of the blocksize. - */ -size_t fillblock(unsigned char *buf, size_t *buflen, size_t blocksize, - const unsigned char **in, size_t *inlen) -{ - size_t blockmask = ~(blocksize - 1); - - assert(*buflen <= blocksize); - assert(blocksize > 0 && (blocksize & (blocksize - 1)) == 0); - - if (*buflen != blocksize && (*buflen != 0 || *inlen < blocksize)) { - size_t bufremain = blocksize - *buflen; - - if (*inlen < bufremain) - bufremain = *inlen; - memcpy(buf + *buflen, *in, bufremain); - *in += bufremain; - *inlen -= bufremain; - *buflen += bufremain; - } - - return *inlen & blockmask; -} - -/* - * Fills the buffer with trailing data from an encryption/decryption that didn't - * fit into a full block. - */ -int trailingdata(unsigned char *buf, size_t *buflen, size_t blocksize, - const unsigned char **in, size_t *inlen) -{ - if (*inlen == 0) - return 1; - - if (*buflen + *inlen > blocksize) { - ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); - return 0; - } - - memcpy(buf + *buflen, *in, *inlen); - *buflen += *inlen; - *inlen = 0; - - return 1; -} - -/* Pad the final block for encryption */ -void padblock(unsigned char *buf, size_t *buflen, size_t blocksize) -{ - size_t i; - unsigned char pad = (unsigned char)(blocksize - *buflen); - - for (i = *buflen; i < blocksize; i++) - buf[i] = pad; -} - -int unpadblock(unsigned char *buf, size_t *buflen, size_t blocksize) -{ - size_t pad, i; - size_t len = *buflen; - - if(len != blocksize) { - ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); - return 0; - } - - /* - * The following assumes that the ciphertext has been authenticated. - * Otherwise it provides a padding oracle. - */ - pad = buf[blocksize - 1]; - if (pad == 0 || pad > blocksize) { - ERR_raise(ERR_LIB_PROV, PROV_R_BAD_DECRYPT); - return 0; - } - for (i = 0; i < pad; i++) { - if (buf[--len] != pad) { - ERR_raise(ERR_LIB_PROV, PROV_R_BAD_DECRYPT); - return 0; - } - } - *buflen = len; - return 1; -} diff --git a/providers/common/ciphers/build.info b/providers/common/ciphers/build.info deleted file mode 100644 index b76b8ba10a..0000000000 --- a/providers/common/ciphers/build.info +++ /dev/null @@ -1,5 +0,0 @@ -# This source is common building blocks for all ciphers in all our providers. -SOURCE[../../libcommon.a]=\ - cipher_common.c cipher_common_hw.c block.c \ - cipher_gcm.c cipher_gcm_hw.c \ - cipher_ccm.c cipher_ccm_hw.c diff --git a/providers/common/ciphers/cipher_ccm.c b/providers/common/ciphers/cipher_ccm.c deleted file mode 100644 index 021a004276..0000000000 --- a/providers/common/ciphers/cipher_ccm.c +++ /dev/null @@ -1,421 +0,0 @@ -/* - * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. - * - * Licensed under the Apache License 2.0 (the "License"). You may not use - * this file except in compliance with the License. You can obtain a copy - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ - -/* Dispatch functions for ccm mode */ - -#include "prov/ciphercommon.h" -#include "prov/cipher_ccm.h" -#include "prov/providercommonerr.h" - -static int ccm_cipher_internal(PROV_CCM_CTX *ctx, unsigned char *out, - size_t *padlen, const unsigned char *in, - size_t len); - -static int ccm_tls_init(PROV_CCM_CTX *ctx, unsigned char *aad, size_t alen) -{ - size_t len; - - if (alen != EVP_AEAD_TLS1_AAD_LEN) - return 0; - - /* Save the aad for later use. */ - memcpy(ctx->buf, aad, alen); - ctx->tls_aad_len = alen; - - len = ctx->buf[alen - 2] << 8 | ctx->buf[alen - 1]; - if (len < EVP_CCM_TLS_EXPLICIT_IV_LEN) - return 0; - - /* Correct length for explicit iv. */ - len -= EVP_CCM_TLS_EXPLICIT_IV_LEN; - - if (!ctx->enc) { - if (len < ctx->m) - return 0; - /* Correct length for tag. */ - len -= ctx->m; - } - ctx->buf[alen - 2] = (unsigned char)(len >> 8); - ctx->buf[alen - 1] = (unsigned char)(len & 0xff); - - /* Extra padding: tag appended to record. */ - return ctx->m; -} - -static int ccm_tls_iv_set_fixed(PROV_CCM_CTX *ctx, unsigned char *fixed, - size_t flen) -{ - if (flen != EVP_CCM_TLS_FIXED_IV_LEN) - return 0; - - /* Copy to first part of the iv. */ - memcpy(ctx->iv, fixed, flen); - return 1; -} - -static size_t ccm_get_ivlen(PROV_CCM_CTX *ctx) -{ - return 15 - ctx->l; -} - -int ccm_set_ctx_params(void *vctx, const OSSL_PARAM params[]) -{ - PROV_CCM_CTX *ctx = (PROV_CCM_CTX *)vctx; - const OSSL_PARAM *p; - size_t sz; - - p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TAG); - if (p != NULL) { - if (p->data_type != OSSL_PARAM_OCTET_STRING) { - ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); - return 0; - } - if ((p->data_size & 1) || (p->data_size < 4) || p->data_size > 16) { - ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_TAGLEN); - return 0; - } - - if (p->data != NULL) { - if (ctx->enc) { - ERR_raise(ERR_LIB_PROV, PROV_R_TAG_NOT_NEEDED); - return 0; - } - memcpy(ctx->buf, p->data, p->data_size); - ctx->tag_set = 1; - } - ctx->m = p->data_size; - } - - p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_IVLEN); - if (p != NULL) { - size_t ivlen; - - if (!OSSL_PARAM_get_size_t(p, &sz)) { - ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); - return 0; - } - ivlen = 15 - sz; - if (ivlen < 2 || ivlen > 8) { - ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IVLEN); - return 0; - } - ctx->l = ivlen; - } - - p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TLS1_AAD); - if (p != NULL) { - if (p->data_type != OSSL_PARAM_OCTET_STRING) { - ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); - return 0; - } - sz = ccm_tls_init(ctx, p->data, p->data_size); - if (sz == 0) { - ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DATA); - return 0; - } - ctx->tls_aad_pad_sz = sz; - } - - p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TLS1_IV_FIXED); - if (p != NULL) { - if (p->data_type != OSSL_PARAM_OCTET_STRING) { - ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); - return 0; - } - if (ccm_tls_iv_set_fixed(ctx, p->data, p->data_size) == 0) { - ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IVLEN); - return 0; - } - } - - return 1; -} - -int ccm_get_ctx_params(void *vctx, OSSL_PARAM params[]) -{ - PROV_CCM_CTX *ctx = (PROV_CCM_CTX *)vctx; - OSSL_PARAM *p; - - p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IVLEN); - if (p != NULL && !OSSL_PARAM_set_size_t(p, ccm_get_ivlen(ctx))) { - ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); - return 0; - } - - p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TAGLEN); - if (p != NULL) { - size_t m = ctx->m; - - if (!OSSL_PARAM_set_size_t(p, m)) { - ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); - return 0; - } - } - - p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IV); - if (p != NULL) { - if (ccm_get_ivlen(ctx) != p->data_size) { - ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IVLEN); - return 0; - } - if (!OSSL_PARAM_set_octet_string(p, ctx->iv, p->data_size)) { - ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); - return 0; - } - } - - p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_KEYLEN); - if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->keylen)) { - ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); - return 0; - } - - p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TLS1_AAD_PAD); - if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->tls_aad_pad_sz)) { - ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); - return 0; - } - - p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TAG); - if (p != NULL) { - if (!ctx->enc || !ctx->tag_set) { - ERR_raise(ERR_LIB_PROV, PROV_R_TAG_NOTSET); - return 0; - } - if (p->data_type != OSSL_PARAM_OCTET_STRING) { - ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); - return 0; - } - if (!ctx->hw->gettag(ctx, p->data, p->data_size)) - return 0; - ctx->tag_set = 0; - ctx->iv_set = 0; - ctx->len_set = 0; - } - return 1; -} - -static int ccm_init(void *vctx, const unsigned char *key, size_t keylen, - const unsigned char *iv, size_t ivlen, int enc) -{ - PROV_CCM_CTX *ctx = (PROV_CCM_CTX *)vctx; - - ctx->enc = enc; - - if (iv != NULL) { - if (ivlen != ccm_get_ivlen(ctx)) { - ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IVLEN); - return 0; - } - memcpy(ctx->iv, iv, ivlen); - ctx->iv_set = 1; - } - if (key != NULL) { - if (keylen != ctx->keylen) { - ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEYLEN); - return 0; - } - return ctx->hw->setkey(ctx, key, keylen); - } - return 1; -} - -int ccm_einit(void *vctx, const unsigned char *key, size_t keylen, - const unsigned char *iv, size_t ivlen) -{ - return ccm_init(vctx, key, keylen, iv, ivlen, 1); -} - -int ccm_dinit(void *vctx, const unsigned char *key, size_t keylen, - const unsigned char *iv, size_t ivlen) -{ - return ccm_init(vctx, key, keylen, iv, ivlen, 0); -} - -int ccm_stream_update(void *vctx, unsigned char *out, size_t *outl, - size_t outsize, const unsigned char *in, - size_t inl) -{ - PROV_CCM_CTX *ctx = (PROV_CCM_CTX *)vctx; - - if (outsize < inl) { - ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); - return 0; - } - - if (!ccm_cipher_internal(ctx, out, outl, in, inl)) { - ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED); - return 0; - } - return 1; -} - -int ccm_stream_final(void *vctx, unsigned char *out, size_t *outl, - size_t outsize) -{ - PROV_CCM_CTX *ctx = (PROV_CCM_CTX *)vctx; - int i; - - i = ccm_cipher_internal(ctx, out, outl, NULL, 0); - if (i <= 0) - return 0; - - *outl = 0; - return 1; -} - -int ccm_cipher(void *vctx, - unsigned char *out, size_t *outl, size_t outsize, - const unsigned char *in, size_t inl) -{ - PROV_CCM_CTX *ctx = (PROV_CCM_CTX *)vctx; - - if (outsize < inl) { - ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); - return 0; - } - - if (ccm_cipher_internal(ctx, out, outl, in, inl) <= 0) - return 0; - - *outl = inl; - return 1; -} - -/* Copy the buffered iv */ -static int ccm_set_iv(PROV_CCM_CTX *ctx, size_t mlen) -{ - const PROV_CCM_HW *hw = ctx->hw; - - if (!hw->setiv(ctx, ctx->iv, ccm_get_ivlen(ctx), mlen)) - return 0; - ctx->len_set = 1; - return 1; -} - -static int ccm_tls_cipher(PROV_CCM_CTX *ctx, - unsigned char *out, size_t *padlen, - const unsigned char *in, size_t len) -{ - int rv = 0; - size_t olen = 0; - - /* Encrypt/decrypt must be performed in place */ - if (out != in || len < (EVP_CCM_TLS_EXPLICIT_IV_LEN + (size_t)ctx->m)) - goto err; - - /* If encrypting set explicit IV from sequence number (start of AAD) */ - if (ctx->enc) - memcpy(out, ctx->buf, EVP_CCM_TLS_EXPLICIT_IV_LEN); - /* Get rest of IV from explicit IV */ - memcpy(ctx->iv + EVP_CCM_TLS_FIXED_IV_LEN, in, EVP_CCM_TLS_EXPLICIT_IV_LEN); - /* Correct length value */ - len -= EVP_CCM_TLS_EXPLICIT_IV_LEN + ctx->m; - if (!ccm_set_iv(ctx, len)) - goto err; - - /* Use saved AAD */ - if (!ctx->hw->setaad(ctx, ctx->buf, ctx->tls_aad_len)) - goto err; - - /* Fix buffer to point to payload */ - in += EVP_CCM_TLS_EXPLICIT_IV_LEN; - out += EVP_CCM_TLS_EXPLICIT_IV_LEN; - if (ctx->enc) { - if (!ctx->hw->auth_encrypt(ctx, in, out, len, out + len, ctx->m)) - goto err; - olen = len + EVP_CCM_TLS_EXPLICIT_IV_LEN + ctx->m; - } else { - if (!ctx->hw->auth_decrypt(ctx, in, out, len, - (unsigned char *)in + len, ctx->m)) - goto err; - olen = len; - } - rv = 1; -err: - *padlen = olen; - return rv; -} - -static int ccm_cipher_internal(PROV_CCM_CTX *ctx, unsigned char *out, - size_t *padlen, const unsigned char *in, - size_t len) -{ - int rv = 0; - size_t olen = 0; - const PROV_CCM_HW *hw = ctx->hw; - - /* If no key set, return error */ - if (!ctx->key_set) - return 0; - - if (ctx->tls_aad_len != UNINITIALISED_SIZET) - return ccm_tls_cipher(ctx, out, padlen, in, len); - - /* EVP_*Final() doesn't return any data */ - if (in == NULL && out != NULL) - goto finish; - - if (!ctx->iv_set) - goto err; - - if (out == NULL) { - if (in == NULL) { - if (!ccm_set_iv(ctx, len)) - goto err; - } else { - /* If we have AAD, we need a message length */ - if (!ctx->len_set && len) - goto err; - if (!hw->setaad(ctx, in, len)) - goto err; - } - } else { - /* If not set length yet do it */ - if (!ctx->len_set && !ccm_set_iv(ctx, len)) - goto err; - - if (ctx->enc) { - if (!hw->auth_encrypt(ctx, in, out, len, NULL, 0)) - goto err; - ctx->tag_set = 1; - } else { - /* The tag must be set before actually decrypting data */ - if (!ctx->tag_set) - goto err; - - if (!hw->auth_decrypt(ctx, in, out, len, ctx->buf, ctx->m)) - goto err; - /* Finished - reset flags so calling this method again will fail */ - ctx->iv_set = 0; - ctx->tag_set = 0; - ctx->len_set = 0; - } - } - olen = len; -finish: - rv = 1; -err: - *padlen = olen; - return rv; -} - -void ccm_initctx(PROV_CCM_CTX *ctx, size_t keybits, const PROV_CCM_HW *hw) -{ - ctx->keylen = keybits / 8; - ctx->key_set = 0; - ctx->iv_set = 0; - ctx->tag_set = 0; - ctx->len_set = 0; - ctx->l = 8; - ctx->m = 12; - ctx->tls_aad_len = UNINITIALISED_SIZET; - ctx->hw = hw; -} - diff --git a/providers/common/ciphers/cipher_ccm_hw.c b/providers/common/ciphers/cipher_ccm_hw.c deleted file mode 100644 index 5503a41687..0000000000 --- a/providers/common/ciphers/cipher_ccm_hw.c +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. - * - * Licensed under the Apache License 2.0 (the "License"). You may not use - * this file except in compliance with the License. You can obtain a copy - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ - -#include "prov/ciphercommon.h" -#include "prov/cipher_ccm.h" - -int ccm_generic_setiv(PROV_CCM_CTX *ctx, const unsigned char *nonce, - size_t nlen, size_t mlen) -{ - return CRYPTO_ccm128_setiv(&ctx->ccm_ctx, nonce, nlen, mlen) == 0; -} - -int ccm_generic_setaad(PROV_CCM_CTX *ctx, const unsigned char *aad, size_t alen) -{ - CRYPTO_ccm128_aad(&ctx->ccm_ctx, aad, alen); - return 1; -} - -int ccm_generic_gettag(PROV_CCM_CTX *ctx, unsigned char *tag, size_t tlen) -{ - return CRYPTO_ccm128_tag(&ctx->ccm_ctx, tag, tlen) > 0; -} - -int ccm_generic_auth_encrypt(PROV_CCM_CTX *ctx, const unsigned char *in, - unsigned char *out, size_t len, - unsigned char *tag, size_t taglen) -{ - int rv; - - if (ctx->str != NULL) - rv = CRYPTO_ccm128_encrypt_ccm64(&ctx->ccm_ctx, in, - out, len, ctx->str) == 0; - else - rv = CRYPTO_ccm128_encrypt(&ctx->ccm_ctx, in, out, len) == 0; - - if (rv == 1 && tag != NULL) - rv = (CRYPTO_ccm128_tag(&ctx->ccm_ctx, tag, taglen) > 0); - return rv; -} - -int ccm_generic_auth_decrypt(PROV_CCM_CTX *ctx, const unsigned char *in, - unsigned char *out, size_t len, - unsigned char *expected_tag, size_t taglen) -{ - int rv = 0; - - if (ctx->str != NULL) - rv = CRYPTO_ccm128_decrypt_ccm64(&ctx->ccm_ctx, in, out, len, - ctx->str) == 0; - else - rv = CRYPTO_ccm128_decrypt(&ctx->ccm_ctx, in, out, len) == 0; - if (rv) { - unsigned char tag[16]; - - if (!CRYPTO_ccm128_tag(&ctx->ccm_ctx, tag, taglen) - || CRYPTO_memcmp(tag, expected_tag, taglen) != 0) - rv = 0; - } - if (rv == 0) - OPENSSL_cleanse(out, len); - return rv; -} - diff --git a/providers/common/ciphers/cipher_common.c b/providers/common/ciphers/cipher_common.c deleted file mode 100644 index 83c370793b..0000000000 --- a/providers/common/ciphers/cipher_common.c +++ /dev/null @@ -1,431 +0,0 @@ -/* - * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. - * - * Licensed under the Apache License 2.0 (the "License"). You may not use - * this file except in compliance with the License. You can obtain a copy - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ - -/* - * Generic dispatch table functions for ciphers. - */ - -#include "cipher_local.h" -#include "prov/provider_ctx.h" -#include "prov/providercommonerr.h" - -/*- - * Generic cipher functions for OSSL_PARAM gettables and settables - */ -static const OSSL_PARAM cipher_known_gettable_params[] = { - OSSL_PARAM_uint(OSSL_CIPHER_PARAM_MODE, NULL), - OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL), - OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_IVLEN, NULL), - OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_BLOCK_SIZE, NULL), - OSSL_PARAM_ulong(OSSL_CIPHER_PARAM_FLAGS, NULL), - OSSL_PARAM_END -}; -const OSSL_PARAM *cipher_generic_gettable_params(void) -{ - return cipher_known_gettable_params; -} - -int cipher_generic_get_params(OSSL_PARAM params[], unsigned int md, - unsigned long flags, - size_t kbits, size_t blkbits, size_t ivbits) -{ - OSSL_PARAM *p; - - p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_MODE); - if (p != NULL && !OSSL_PARAM_set_uint(p, md)) { - ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); - return 0; - } - p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_FLAGS); - if (p != NULL && !OSSL_PARAM_set_ulong(p, flags)) { - ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); - return 0; - } - p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_KEYLEN); - if (p != NULL && !OSSL_PARAM_set_size_t(p, kbits / 8)) { - ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); - return 0; - } - p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_BLOCK_SIZE); - if (p != NULL && !OSSL_PARAM_set_size_t(p, blkbits / 8)) { - ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); - return 0; - } - p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IVLEN); - if (p != NULL && !OSSL_PARAM_set_size_t(p, ivbits / 8)) { - ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); - return 0; - } - return 1; -} - -CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_START(cipher_generic) -CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_END(cipher_generic) - -CIPHER_DEFAULT_SETTABLE_CTX_PARAMS_START(cipher_generic) -CIPHER_DEFAULT_SETTABLE_CTX_PARAMS_END(cipher_generic) - -/* - * Variable key length cipher functions for OSSL_PARAM settables - */ - -int cipher_var_keylen_set_ctx_params(void *vctx, const OSSL_PARAM params[]) -{ - PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx; - const OSSL_PARAM *p; - - if (!cipher_generic_set_ctx_params(vctx, params)) - return 0; - p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_KEYLEN); - if (p != NULL) { - size_t keylen; - - if (!OSSL_PARAM_get_size_t(p, &keylen)) { - ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); - return 0; - } - ctx->keylen = keylen; - } - return 1; -} - -CIPHER_DEFAULT_SETTABLE_CTX_PARAMS_START(cipher_var_keylen) -OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL), -CIPHER_DEFAULT_SETTABLE_CTX_PARAMS_END(cipher_var_keylen) - -/*- - * AEAD cipher functions for OSSL_PARAM gettables and settables - */ -static const OSSL_PARAM cipher_aead_known_gettable_ctx_params[] = { - OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL), - OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_IVLEN, NULL), - OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_AEAD_TAGLEN, NULL), - OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_IV, NULL, 0), - OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, NULL, 0), - OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_AEAD_TLS1_AAD_PAD, NULL), - OSSL_PARAM_END -}; -const OSSL_PARAM *cipher_aead_gettable_ctx_params(void) -{ - return cipher_aead_known_gettable_ctx_params; -} - -static const OSSL_PARAM cipher_aead_known_settable_ctx_params[] = { - OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_AEAD_IVLEN, NULL), - OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, NULL, 0), - OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TLS1_AAD, NULL, 0), - OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TLS1_IV_FIXED, NULL, 0), - OSSL_PARAM_END -}; -const OSSL_PARAM *cipher_aead_settable_ctx_params(void) -{ - return cipher_aead_known_settable_ctx_params; -} - -static int cipher_generic_init_internal(PROV_CIPHER_CTX *ctx, - const unsigned char *key, size_t keylen, - const unsigned char *iv, size_t ivlen, - int enc) -{ - ctx->enc = enc ? 1 : 0; - - if (iv != NULL && ctx->mode != EVP_CIPH_ECB_MODE) { - if (!cipher_generic_initiv(ctx, iv, ivlen)) - return 0; - } - if (key != NULL) { - if ((ctx->flags & EVP_CIPH_VARIABLE_LENGTH) == 0) { - if (keylen != ctx->keylen) { - ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEYLEN); - return 0; - } - } else { - ctx->keylen = keylen; - } - return ctx->hw->init(ctx, key, ctx->keylen); - } - return 1; -} - -int cipher_generic_einit(void *vctx, const unsigned char *key, size_t keylen, - const unsigned char *iv, size_t ivlen) -{ - return cipher_generic_init_internal((PROV_CIPHER_CTX *)vctx, key, keylen, - iv, ivlen, 1); -} - -int cipher_generic_dinit(void *vctx, const unsigned char *key, size_t keylen, - const unsigned char *iv, size_t ivlen) -{ - return cipher_generic_init_internal((PROV_CIPHER_CTX *)vctx, key, keylen, - iv, ivlen, 0); -} - -int cipher_generic_block_update(void *vctx, unsigned char *out, size_t *outl, - size_t outsize, const unsigned char *in, - size_t inl) -{ - size_t outlint = 0; - PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx; - size_t blksz = ctx->blocksize; - size_t nextblocks = fillblock(ctx->buf, &ctx->bufsz, blksz, &in, &inl); - - /* - * If we're decrypting and we end an update on a block boundary we hold - * the last block back in case this is the last update call and the last - * block is padded. - */ - if (ctx->bufsz == blksz && (ctx->enc || inl > 0 || !ctx->pad)) { - if (outsize < blksz) { - ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); - return 0; - } - if (!ctx->hw->cipher(ctx, out, ctx->buf, blksz)) { - ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED); - return 0; - } - ctx->bufsz = 0; - outlint = blksz; - out += blksz; - } - if (nextblocks > 0) { - if (!ctx->enc && ctx->pad && nextblocks == inl) { - if (!ossl_assert(inl >= blksz)) { - ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); - return 0; - } - nextblocks -= blksz; - } - outlint += nextblocks; - if (outsize < outlint) { - ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); - return 0; - } - } - if (nextblocks > 0) { - if (!ctx->hw->cipher(ctx, out, in, nextblocks)) { - ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED); - return 0; - } - in += nextblocks; - inl -= nextblocks; - } - if (!trailingdata(ctx->buf, &ctx->bufsz, blksz, &in, &inl)) { - /* ERR_raise already called */ - return 0; - } - - *outl = outlint; - return inl == 0; -} - -int cipher_generic_block_final(void *vctx, unsigned char *out, size_t *outl, - size_t outsize) -{ - PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx; - size_t blksz = ctx->blocksize; - - if (ctx->enc) { - if (ctx->pad) { - padblock(ctx->buf, &ctx->bufsz, blksz); - } else if (ctx->bufsz == 0) { - *outl = 0; - return 1; - } else if (ctx->bufsz != blksz) { - ERR_raise(ERR_LIB_PROV, PROV_R_WRONG_FINAL_BLOCK_LENGTH); - return 0; - } - - if (outsize < blksz) { - ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); - return 0; - } - if (!ctx->hw->cipher(ctx, out, ctx->buf, blksz)) { - ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED); - return 0; - } - ctx->bufsz = 0; - *outl = blksz; - return 1; - } - - /* Decrypting */ - if (ctx->bufsz != blksz) { - if (ctx->bufsz == 0 && !ctx->pad) { - *outl = 0; - return 1; - } - ERR_raise(ERR_LIB_PROV, PROV_R_WRONG_FINAL_BLOCK_LENGTH); - return 0; - } - - if (!ctx->hw->cipher(ctx, ctx->buf, ctx->buf, blksz)) { - ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED); - return 0; - } - - if (ctx->pad && !unpadblock(ctx->buf, &ctx->bufsz, blksz)) { - /* ERR_raise already called */ - return 0; - } - - if (outsize < ctx->bufsz) { - ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); - return 0; - } - memcpy(out, ctx->buf, ctx->bufsz); - *outl = ctx->bufsz; - ctx->bufsz = 0; - return 1; -} - -int cipher_generic_stream_update(void *vctx, unsigned char *out, size_t *outl, - size_t outsize, const unsigned char *in, - size_t inl) -{ - PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx; - - if (inl == 0) { - *outl = 0; - return 1; - } - - if (outsize < inl) { - ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); - return 0; - } - - if (!ctx->hw->cipher(ctx, out, in, inl)) { - ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED); - return 0; - } - - *outl = inl; - return 1; -} -int cipher_generic_stream_final(void *vctx, unsigned char *out, size_t *outl, - size_t outsize) -{ - *outl = 0; - return 1; -} - -int cipher_generic_cipher(void *vctx, - unsigned char *out, size_t *outl, size_t outsize, - const unsigned char *in, size_t inl) -{ - PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx; - - if (outsize < inl) { - ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); - return 0; - } - - if (!ctx->hw->cipher(ctx, out, in, inl)) { - ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED); - return 0; - } - - *outl = inl; - return 1; -} - -int cipher_generic_get_ctx_params(void *vctx, OSSL_PARAM params[]) -{ - PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx; - OSSL_PARAM *p; - - p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IVLEN); - if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->ivlen)) { - ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); - return 0; - } - p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_PADDING); - if (p != NULL && !OSSL_PARAM_set_uint(p, ctx->pad)) { - ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); - return 0; - } - p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IV); - if (p != NULL - && !OSSL_PARAM_set_octet_ptr(p, &ctx->oiv, ctx->ivlen) - && !OSSL_PARAM_set_octet_string(p, &ctx->oiv, ctx->ivlen)) { - ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); - return 0; - } - p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_NUM); - if (p != NULL && !OSSL_PARAM_set_uint(p, ctx->num)) { - ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); - return 0; - } - p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_KEYLEN); - if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->keylen)) { - ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); - return 0; - } - return 1; -} - -int cipher_generic_set_ctx_params(void *vctx, const OSSL_PARAM params[]) -{ - PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx; - const OSSL_PARAM *p; - - p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_PADDING); - if (p != NULL) { - unsigned int pad; - - if (!OSSL_PARAM_get_uint(p, &pad)) { - ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); - return 0; - } - ctx->pad = pad ? 1 : 0; - } - p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_NUM); - if (p != NULL) { - unsigned int num; - - if (!OSSL_PARAM_get_uint(p, &num)) { - ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); - return 0; - } - ctx->num = num; - } - return 1; -} - -int cipher_generic_initiv(PROV_CIPHER_CTX *ctx, const unsigned char *iv, - size_t ivlen) -{ - if (ivlen != ctx->ivlen - || ivlen > sizeof(ctx->iv)) { - ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IVLEN); - return 0; - } - ctx->iv_set = 1; - memcpy(ctx->iv, iv, ivlen); - memcpy(ctx->oiv, iv, ivlen); - return 1; -} - -void cipher_generic_initkey(void *vctx, size_t kbits, size_t blkbits, - size_t ivbits, unsigned int mode, uint64_t flags, - const PROV_CIPHER_HW *hw, void *provctx) -{ - PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx; - - ctx->flags = flags; - ctx->pad = 1; - ctx->keylen = ((kbits) / 8); - ctx->ivlen = ((ivbits) / 8); - ctx->hw = hw; - ctx->mode = mode; - ctx->blocksize = blkbits / 8; - if (provctx != NULL) - ctx->libctx = PROV_LIBRARY_CONTEXT_OF(provctx); /* used for rand */ -} diff --git a/providers/common/ciphers/cipher_common_hw.c b/providers/common/ciphers/cipher_common_hw.c deleted file mode 100644 index f1c466edc8..0000000000 --- a/providers/common/ciphers/cipher_common_hw.c +++ /dev/null @@ -1,189 +0,0 @@ -/* - * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. - * - * Licensed under the Apache License 2.0 (the "License"). You may not use - * this file except in compliance with the License. You can obtain a copy - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ - -#include "prov/ciphercommon.h" - -/*- - * The generic cipher functions for cipher modes cbc, ecb, ofb, cfb and ctr. - * Used if there is no special hardware implementations. - */ -int cipher_hw_generic_cbc(PROV_CIPHER_CTX *dat, unsigned char *out, - const unsigned char *in, size_t len) -{ - if (dat->stream.cbc) - (*dat->stream.cbc) (in, out, len, dat->ks, dat->iv, dat->enc); - else if (dat->enc) - CRYPTO_cbc128_encrypt(in, out, len, dat->ks, dat->iv, dat->block); - else - CRYPTO_cbc128_decrypt(in, out, len, dat->ks, dat->iv, dat->block); - - return 1; -} - -int cipher_hw_generic_ecb(PROV_CIPHER_CTX *dat, unsigned char *out, - const unsigned char *in, size_t len) -{ - size_t i, bl = dat->blocksize; - - if (len < bl) - return 1; - - for (i = 0, len -= bl; i <= len; i += bl) - (*dat->block) (in + i, out + i, dat->ks); - - return 1; -} - -int cipher_hw_generic_ofb128(PROV_CIPHER_CTX *dat, unsigned char *out, - const unsigned char *in, size_t len) -{ - int num = dat->num; - - CRYPTO_ofb128_encrypt(in, out, len, dat->ks, dat->iv, &num, dat->block); - dat->num = num; - - return 1; -} - -int cipher_hw_generic_cfb128(PROV_CIPHER_CTX *dat, unsigned char *out, - const unsigned char *in, size_t len) -{ - int num = dat->num; - - CRYPTO_cfb128_encrypt(in, out, len, dat->ks, dat->iv, &num, dat->enc, - dat->block); - dat->num = num; - - return 1; -} - -int cipher_hw_generic_cfb8(PROV_CIPHER_CTX *dat, unsigned char *out, - const unsigned char *in, size_t len) -{ - int num = dat->num; - - CRYPTO_cfb128_8_encrypt(in, out, len, dat->ks, dat->iv, &num, dat->enc, - dat->block); - dat->num = num; - - return 1; -} - -int cipher_hw_generic_cfb1(PROV_CIPHER_CTX *dat, unsigned char *out, - const unsigned char *in, size_t len) -{ - int num = dat->num; - - if ((dat->flags & EVP_CIPH_FLAG_LENGTH_BITS) != 0) { - CRYPTO_cfb128_1_encrypt(in, out, len, dat->ks, dat->iv, &num, - dat->enc, dat->block); - dat->num = num; - return 1; - } - - while (len >= MAXBITCHUNK) { - CRYPTO_cfb128_1_encrypt(in, out, MAXBITCHUNK * 8, dat->ks, - dat->iv, &num, dat->enc, dat->block); - len -= MAXBITCHUNK; - out += MAXBITCHUNK; - in += MAXBITCHUNK; - } - if (len) - CRYPTO_cfb128_1_encrypt(in, out, len * 8, dat->ks, dat->iv, &num, - dat->enc, dat->block); - - dat->num = num; - - return 1; -} - -int cipher_hw_generic_ctr(PROV_CIPHER_CTX *dat, unsigned char *out, - const unsigned char *in, size_t len) -{ - unsigned int num = dat->num; - - if (dat->stream.ctr) - CRYPTO_ctr128_encrypt_ctr32(in, out, len, dat->ks, dat->iv, dat->buf, - &num, dat->stream.ctr); - else - CRYPTO_ctr128_encrypt(in, out, len, dat->ks, dat->iv, dat->buf, - &num, dat->block); - dat->num = num; - - return 1; -} - -/*- - * The chunked cipher functions for cipher modes cbc, ecb, ofb, cfb and ctr. - * Used if there is no special hardware implementations. - */ - -int cipher_hw_chunked_cbc(PROV_CIPHER_CTX *ctx, unsigned char *out, - const unsigned char *in, size_t inl) -{ - while (inl >= MAXCHUNK) { - cipher_hw_generic_cbc(ctx, out, in, MAXCHUNK); - inl -= MAXCHUNK; - in += MAXCHUNK; - out += MAXCHUNK; - } - if (inl > 0) - cipher_hw_generic_cbc(ctx, out, in, inl); - return 1; -} - -int cipher_hw_chunked_cfb8(PROV_CIPHER_CTX *ctx, unsigned char *out, - const unsigned char *in, size_t inl) -{ - size_t chunk = MAXCHUNK; - - if (inl < chunk) - chunk = inl; - while (inl > 0 && inl >= chunk) { - cipher_hw_generic_cfb8(ctx, out, in, inl); - inl -= chunk; - in += chunk; - out += chunk; - if (inl < chunk) - chunk = inl; - } - return 1; -} - -int cipher_hw_chunked_cfb128(PROV_CIPHER_CTX *ctx, unsigned char *out, - const unsigned char *in, size_t inl) -{ - size_t chunk = MAXCHUNK; - - if (inl < chunk) - chunk = inl; - while (inl > 0 && inl >= chunk) { - cipher_hw_generic_cfb128(ctx, out, in, inl); - inl -= chunk; - in += chunk; - out += chunk; - if (inl < chunk) - chunk = inl; - } - return 1; -} - -int cipher_hw_chunked_ofb128(PROV_CIPHER_CTX *ctx, unsigned char *out, - const unsigned char *in, size_t inl) -{ - while (inl >= MAXCHUNK) { - cipher_hw_generic_ofb128(ctx, out, in, MAXCHUNK); - inl -= MAXCHUNK; - in += MAXCHUNK; - out += MAXCHUNK; - } - if (inl > 0) - cipher_hw_generic_ofb128(ctx, out, in, inl); - return 1; -} diff --git a/providers/common/ciphers/cipher_gcm.c b/providers/common/ciphers/cipher_gcm.c deleted file mode 100644 index 619d4f61b0..0000000000 --- a/providers/common/ciphers/cipher_gcm.c +++ /dev/null @@ -1,495 +0,0 @@ -/* - * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. - * - * Licensed under the Apache License 2.0 (the "License"). You may not use - * this file except in compliance with the License. You can obtain a copy - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ - -/* Dispatch functions for gcm mode */ - -#include "prov/ciphercommon.h" -#include "prov/cipher_gcm.h" -#include "prov/providercommonerr.h" -#include "crypto/rand.h" -#include "prov/provider_ctx.h" - -static int gcm_tls_init(PROV_GCM_CTX *dat, unsigned char *aad, size_t aad_len); -static int gcm_tls_iv_set_fixed(PROV_GCM_CTX *ctx, unsigned char *iv, - size_t len); -static int gcm_tls_cipher(PROV_GCM_CTX *ctx, unsigned char *out, size_t *padlen, - const unsigned char *in, size_t len); -static int gcm_cipher_internal(PROV_GCM_CTX *ctx, unsigned char *out, - size_t *padlen, const unsigned char *in, - size_t len); - -void gcm_initctx(void *provctx, PROV_GCM_CTX *ctx, size_t keybits, - const PROV_GCM_HW *hw, size_t ivlen_min) -{ - ctx->pad = 1; - ctx->mode = EVP_CIPH_GCM_MODE; - ctx->taglen = UNINITIALISED_SIZET; - ctx->tls_aad_len = UNINITIALISED_SIZET; - ctx->ivlen_min = ivlen_min; - ctx->ivlen = (EVP_GCM_TLS_FIXED_IV_LEN + EVP_GCM_TLS_EXPLICIT_IV_LEN); - ctx->keylen = keybits / 8; - ctx->hw = hw; - ctx->libctx = PROV_LIBRARY_CONTEXT_OF(provctx); -} - -static int gcm_init(void *vctx, const unsigned char *key, size_t keylen, - const unsigned char *iv, size_t ivlen, int enc) -{ - PROV_GCM_CTX *ctx = (PROV_GCM_CTX *)vctx; - - ctx->enc = enc; - - if (iv != NULL) { - if (ivlen < ctx->ivlen_min || ivlen > sizeof(ctx->iv)) { - ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH); - return 0; - } - ctx->ivlen = ivlen; - memcpy(ctx->iv, iv, ivlen); - ctx->iv_state = IV_STATE_BUFFERED; - } - - if (key != NULL) { - if (keylen != ctx->keylen) { - ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH); - return 0; - } - return ctx->hw->setkey(ctx, key, ctx->keylen); - } - return 1; -} - -int gcm_einit(void *vctx, const unsigned char *key, size_t keylen, - const unsigned char *iv, size_t ivlen) -{ - return gcm_init(vctx, key, keylen, iv, ivlen, 1); -} - -int gcm_dinit(void *vctx, const unsigned char *key, size_t keylen, - const unsigned char *iv, size_t ivlen) -{ - return gcm_init(vctx, key, keylen, iv, ivlen, 0); -} - -int gcm_get_ctx_params(void *vctx, OSSL_PARAM params[]) -{ - PROV_GCM_CTX *ctx = (PROV_GCM_CTX *)vctx; - OSSL_PARAM *p; - size_t sz; - - p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IVLEN); - if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->ivlen)) { - ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); - return 0; - } - p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_KEYLEN); - if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->keylen)) { - ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); - return 0; - } - p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TAGLEN); - if (p != NULL) { - size_t taglen = (ctx->taglen != UNINITIALISED_SIZET) ? ctx->taglen : - GCM_TAG_MAX_SIZE; - - if (!OSSL_PARAM_set_size_t(p, taglen)) { - ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); - return 0; - } - } - - p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IV); - if (p != NULL) { - if (ctx->iv_gen != 1 && ctx->iv_gen_rand != 1) - return 0; - if (ctx->ivlen != p->data_size) { - ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH); - return 0; - } - if (!OSSL_PARAM_set_octet_string(p, ctx->iv, ctx->ivlen)) { - ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); - return 0; - } - } - - p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TLS1_AAD_PAD); - if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->tls_aad_pad_sz)) { - ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); - return 0; - } - p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TAG); - if (p != NULL) { - sz = p->data_size; - if (sz == 0 - || sz > EVP_GCM_TLS_TAG_LEN - || !ctx->enc - || ctx->taglen == UNINITIALISED_SIZET) { - ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_TAG); - return 0; - } - if (!OSSL_PARAM_set_octet_string(p, ctx->buf, sz)) { - ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); - return 0; - } - } - - return 1; -} - -int gcm_set_ctx_params(void *vctx, const OSSL_PARAM params[]) -{ - PROV_GCM_CTX *ctx = (PROV_GCM_CTX *)vctx; - const OSSL_PARAM *p; - size_t sz; - void *vp; - - p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TAG); - if (p != NULL) { - vp = ctx->buf; - if (!OSSL_PARAM_get_octet_string(p, &vp, EVP_GCM_TLS_TAG_LEN, &sz)) { - ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); - return 0; - } - if (sz == 0 || ctx->enc) { - ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_TAG); - return 0; - } - ctx->taglen = sz; - } - - p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_IVLEN); - if (p != NULL) { - if (!OSSL_PARAM_get_size_t(p, &sz)) { - ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); - return 0; - } - if (sz == 0 || sz > sizeof(ctx->iv)) { - ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH); - return 0; - } - ctx->ivlen = sz; - } - - p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TLS1_AAD); - if (p != NULL) { - if (p->data_type != OSSL_PARAM_OCTET_STRING) { - ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); - return 0; - } - sz = gcm_tls_init(ctx, p->data, p->data_size); - if (sz == 0) { - ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_AAD); - return 0; - } - ctx->tls_aad_pad_sz = sz; - } - - p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TLS1_IV_FIXED); - if (p != NULL) { - if (p->data_type != OSSL_PARAM_OCTET_STRING) { - ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); - return 0; - } - if (gcm_tls_iv_set_fixed(ctx, p->data, p->data_size) == 0) { - ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); - return 0; - } - } - - return 1; -} - -int gcm_stream_update(void *vctx, unsigned char *out, size_t *outl, - size_t outsize, const unsigned char *in, size_t inl) -{ - PROV_GCM_CTX *ctx = (PROV_GCM_CTX *)vctx; - - if (inl == 0) { - *outl = 0; - return 1; - } - - if (outsize < inl) { - ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); - return -1; - } - - if (gcm_cipher_internal(ctx, out, outl, in, inl) <= 0) { - ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED); - return -1; - } - return 1; -} - -int gcm_stream_final(void *vctx, unsigned char *out, size_t *outl, - size_t outsize) -{ - PROV_GCM_CTX *ctx = (PROV_GCM_CTX *)vctx; - int i; - - i = gcm_cipher_internal(ctx, out, outl, NULL, 0); - if (i <= 0) - return 0; - - *outl = 0; - return 1; -} - -int gcm_cipher(void *vctx, - unsigned char *out, size_t *outl, size_t outsize, - const unsigned char *in, size_t inl) -{ - PROV_GCM_CTX *ctx = (PROV_GCM_CTX *)vctx; - - if (outsize < inl) { - ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); - return 0; - } - - if (gcm_cipher_internal(ctx, out, outl, in, inl) <= 0) - return 0; - - *outl = inl; - return 1; -} - -/* - * See SP800-38D (GCM) Section 8 "Uniqueness requirement on IVS and keys" - * - * See also 8.2.2 RBG-based construction. - * Random construction consists of a free field (which can be NULL) and a - * random field which will use a DRBG that can return at least 96 bits of - * entropy strength. (The DRBG must be seeded by the FIPS module). - */ -static int gcm_iv_generate(PROV_GCM_CTX *ctx, int offset) -{ - int sz = ctx->ivlen - offset; - - /* Must be at least 96 bits */ - if (sz <= 0 || ctx->ivlen < GCM_IV_DEFAULT_SIZE) - return 0; - - /* Use DRBG to generate random iv */ - if (rand_bytes_ex(ctx->libctx, ctx->iv + offset, sz) <= 0) - return 0; - ctx->iv_state = IV_STATE_BUFFERED; - ctx->iv_gen_rand = 1; - return 1; -} - -static int gcm_cipher_internal(PROV_GCM_CTX *ctx, unsigned char *out, - size_t *padlen, const unsigned char *in, - size_t len) -{ - size_t olen = 0; - int rv = 0; - const PROV_GCM_HW *hw = ctx->hw; - - if (ctx->tls_aad_len != UNINITIALISED_SIZET) - return gcm_tls_cipher(ctx, out, padlen, in, len); - - if (!ctx->key_set || ctx->iv_state == IV_STATE_FINISHED) - goto err; - - /* - * FIPS requires generation of AES-GCM IV's inside the FIPS module. - * The IV can still be set externally (the security policy will state that - * this is not FIPS compliant). There are some applications - * where setting the IV externally is the only option available. - */ - if (ctx->iv_state == IV_STATE_UNINITIALISED) { - if (!ctx->enc || !gcm_iv_generate(ctx, 0)) - goto err; - } - - if (ctx->iv_state == IV_STATE_BUFFERED) { - if (!hw->setiv(ctx, ctx->iv, ctx->ivlen)) - goto err; - ctx->iv_state = IV_STATE_COPIED; - } - - if (in != NULL) { - /* The input is AAD if out is NULL */ - if (out == NULL) { - if (!hw->aadupdate(ctx, in, len)) - goto err; - } else { - /* The input is ciphertext OR plaintext */ - if (!hw->cipherupdate(ctx, in, len, out)) - goto err; - } - } else { - /* The tag must be set before actually decrypting data */ - if (!ctx->enc && ctx->taglen == UNINITIALISED_SIZET) - goto err; - if (!hw->cipherfinal(ctx, ctx->buf)) - goto err; - ctx->iv_state = IV_STATE_FINISHED; /* Don't reuse the IV */ - goto finish; - } - olen = len; -finish: - rv = 1; -err: - *padlen = olen; - return rv; -} - -static int gcm_tls_init(PROV_GCM_CTX *dat, unsigned char *aad, size_t aad_len) -{ - unsigned char *buf; - size_t len; - - if (aad_len != EVP_AEAD_TLS1_AAD_LEN) - return 0; - - /* Save the aad for later use. */ - buf = dat->buf; - memcpy(buf, aad, aad_len); - dat->tls_aad_len = aad_len; - dat->tls_enc_records = 0; - - len = buf[aad_len - 2] << 8 | buf[aad_len - 1]; - /* Correct length for explicit iv. */ - if (len < EVP_GCM_TLS_EXPLICIT_IV_LEN) - return 0; - len -= EVP_GCM_TLS_EXPLICIT_IV_LEN; - - /* If decrypting correct for tag too. */ - if (!dat->enc) { - if (len < EVP_GCM_TLS_TAG_LEN) - return 0; - len -= EVP_GCM_TLS_TAG_LEN; - } - buf[aad_len - 2] = (unsigned char)(len >> 8); - buf[aad_len - 1] = (unsigned char)(len & 0xff); - /* Extra padding: tag appended to record. */ - return EVP_GCM_TLS_TAG_LEN; -} - -static int gcm_tls_iv_set_fixed(PROV_GCM_CTX *ctx, unsigned char *iv, - size_t len) -{ - /* Special case: -1 length restores whole IV */ - if (len == (size_t)-1) { - memcpy(ctx->iv, iv, ctx->ivlen); - ctx->iv_gen = 1; - ctx->iv_state = IV_STATE_BUFFERED; - return 1; - } - /* Fixed field must be at least 4 bytes and invocation field at least 8 */ - if ((len < EVP_GCM_TLS_FIXED_IV_LEN) - || (ctx->ivlen - (int)len) < EVP_GCM_TLS_EXPLICIT_IV_LEN) - return 0; - if (len > 0) - memcpy(ctx->iv, iv, len); - if (ctx->enc - && rand_bytes_ex(ctx->libctx, ctx->iv + len, ctx->ivlen - len) <= 0) - return 0; - ctx->iv_gen = 1; - ctx->iv_state = IV_STATE_BUFFERED; - return 1; -} - -/* increment counter (64-bit int) by 1 */ -static void ctr64_inc(unsigned char *counter) -{ - int n = 8; - unsigned char c; - - do { - --n; - c = counter[n]; - ++c; - counter[n] = c; - if (c > 0) - return; - } while (n > 0); -} - -/* - * Handle TLS GCM packet format. This consists of the last portion of the IV - * followed by the payload and finally the tag. On encrypt generate IV, - * encrypt payload and write the tag. On verify retrieve IV, decrypt payload - * and verify tag. - */ -static int gcm_tls_cipher(PROV_GCM_CTX *ctx, unsigned char *out, size_t *padlen, - const unsigned char *in, size_t len) -{ - int rv = 0; - size_t arg = EVP_GCM_TLS_EXPLICIT_IV_LEN; - size_t plen = 0; - unsigned char *tag = NULL; - - if (!ctx->key_set) - goto err; - - /* Encrypt/decrypt must be performed in place */ - if (out != in || len < (EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN)) - goto err; - - /* - * Check for too many keys as per FIPS 140-2 IG A.5 "Key/IV Pair Uniqueness - * Requirements from SP 800-38D". The requirements is for one party to the - * communication to fail after 2^64 - 1 keys. We do this on the encrypting - * side only. - */ - if (ctx->enc && ++ctx->tls_enc_records == 0) { - ERR_raise(ERR_LIB_PROV, EVP_R_TOO_MANY_RECORDS); - goto err; - } - - if (ctx->iv_gen == 0) - goto err; - /* - * Set IV from start of buffer or generate IV and write to start of - * buffer. - */ - if (ctx->enc) { - if (!ctx->hw->setiv(ctx, ctx->iv, ctx->ivlen)) - goto err; - if (arg > ctx->ivlen) - arg = ctx->ivlen; - memcpy(out, ctx->iv + ctx->ivlen - arg, arg); - /* - * Invocation field will be at least 8 bytes in size and so no need - * to check wrap around or increment more than last 8 bytes. - */ - ctr64_inc(ctx->iv + ctx->ivlen - 8); - } else { - memcpy(ctx->iv + ctx->ivlen - arg, out, arg); - if (!ctx->hw->setiv(ctx, ctx->iv, ctx->ivlen)) - goto err; - } - ctx->iv_state = IV_STATE_COPIED; - - /* Fix buffer and length to point to payload */ - in += EVP_GCM_TLS_EXPLICIT_IV_LEN; - out += EVP_GCM_TLS_EXPLICIT_IV_LEN; - len -= EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN; - - tag = ctx->enc ? out + len : (unsigned char *)in + len; - if (!ctx->hw->oneshot(ctx, ctx->buf, ctx->tls_aad_len, in, len, out, tag, - EVP_GCM_TLS_TAG_LEN)) { - if (!ctx->enc) - OPENSSL_cleanse(out, len); - goto err; - } - if (ctx->enc) - plen = len + EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN; - else - plen = len; - - rv = 1; -err: - ctx->iv_state = IV_STATE_FINISHED; - ctx->tls_aad_len = UNINITIALISED_SIZET; - *padlen = plen; - return rv; -} diff --git a/providers/common/ciphers/cipher_gcm_hw.c b/providers/common/ciphers/cipher_gcm_hw.c deleted file mode 100644 index 09e3c27400..0000000000 --- a/providers/common/ciphers/cipher_gcm_hw.c +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright 2001-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 "prov/ciphercommon.h" -#include "prov/cipher_gcm.h" - - -int gcm_setiv(PROV_GCM_CTX *ctx, const unsigned char *iv, size_t ivlen) -{ - CRYPTO_gcm128_setiv(&ctx->gcm, iv, ivlen); - return 1; -} - -int gcm_aad_update(PROV_GCM_CTX *ctx, const unsigned char *aad, size_t aad_len) -{ - return CRYPTO_gcm128_aad(&ctx->gcm, aad, aad_len) == 0; -} - -int gcm_cipher_update(PROV_GCM_CTX *ctx, const unsigned char *in, - size_t len, unsigned char *out) -{ - if (ctx->enc) { - if (ctx->ctr != NULL) { -#if defined(AES_GCM_ASM) - size_t bulk = 0; - - if (len >= 32 && AES_GCM_ASM(ctx)) { - size_t res = (16 - ctx->gcm.mres) % 16; - - if (CRYPTO_gcm128_encrypt(&ctx->gcm, in, out, res)) - return 0; - bulk = aesni_gcm_encrypt(in + res, out + res, len - res, - ctx->gcm.key, - ctx->gcm.Yi.c, ctx->gcm.Xi.u); - ctx->gcm.len.u[1] += bulk; - bulk += res; - } - if (CRYPTO_gcm128_encrypt_ctr32(&ctx->gcm, in + bulk, out + bulk, - len - bulk, ctx->ctr)) - return 0; -#else - if (CRYPTO_gcm128_encrypt_ctr32(&ctx->gcm, in, out, len, ctx->ctr)) - return 0; -#endif /* AES_GCM_ASM */ - } else { - if (CRYPTO_gcm128_encrypt(&ctx->gcm, in, out, len)) - return 0; - } - } else { - if (ctx->ctr != NULL) { -#if defined(AES_GCM_ASM) - size_t bulk = 0; - - if (len >= 16 && AES_GCM_ASM(ctx)) { - size_t res = (16 - ctx->gcm.mres) % 16; - - if (CRYPTO_gcm128_decrypt(&ctx->gcm, in, out, res)) - return -1; - - bulk = aesni_gcm_decrypt(in + res, out + res, len - res, - ctx->gcm.key, - ctx->gcm.Yi.c, ctx->gcm.Xi.u); - ctx->gcm.len.u[1] += bulk; - bulk += res; - } - if (CRYPTO_gcm128_decrypt_ctr32(&ctx->gcm, in + bulk, out + bulk, - len - bulk, ctx->ctr)) - return 0; -#else - if (CRYPTO_gcm128_decrypt_ctr32(&ctx->gcm, in, out, len, ctx->ctr)) - return 0; -#endif /* AES_GCM_ASM */ - } else { - if (CRYPTO_gcm128_decrypt(&ctx->gcm, in, out, len)) - return 0; - } - } - return 1; -} - -int gcm_cipher_final(PROV_GCM_CTX *ctx, unsigned char *tag) -{ - if (ctx->enc) { - CRYPTO_gcm128_tag(&ctx->gcm, tag, GCM_TAG_MAX_SIZE); - ctx->taglen = GCM_TAG_MAX_SIZE; - } else { - if (CRYPTO_gcm128_finish(&ctx->gcm, tag, ctx->taglen) != 0) - return 0; - } - return 1; -} - -int gcm_one_shot(PROV_GCM_CTX *ctx, unsigned char *aad, size_t aad_len, - const unsigned char *in, size_t in_len, - unsigned char *out, unsigned char *tag, size_t tag_len) -{ - int ret = 0; - - /* Use saved AAD */ - if (!ctx->hw->aadupdate(ctx, aad, aad_len)) - goto err; - if (!ctx->hw->cipherupdate(ctx, in, in_len, out)) - goto err; - ctx->taglen = GCM_TAG_MAX_SIZE; - if (!ctx->hw->cipherfinal(ctx, tag)) - goto err; - ret = 1; - -err: - return ret; -} diff --git a/providers/common/ciphers/cipher_local.h b/providers/common/ciphers/cipher_local.h deleted file mode 100644 index 1c4716f357..0000000000 --- a/providers/common/ciphers/cipher_local.h +++ /dev/null @@ -1,13 +0,0 @@ -/* - * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. - * - * Licensed under the Apache License 2.0 (the "License"). You may not use - * this file except in compliance with the License. You can obtain a copy - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ - -#include "prov/ciphercommon.h" - -void padblock(unsigned char *buf, size_t *buflen, size_t blocksize); -int unpadblock(unsigned char *buf, size_t *buflen, size_t blocksize); diff --git a/providers/common/digests/build.info b/providers/common/digests/build.info deleted file mode 100644 index 730046d670..0000000000 --- a/providers/common/digests/build.info +++ /dev/null @@ -1,2 +0,0 @@ -# This source is common for all digests in all our providers. -SOURCE[../../libcommon.a]=digest_common.c diff --git a/providers/common/digests/digest_common.c b/providers/common/digests/digest_common.c deleted file mode 100644 index 9d30b2be2c..0000000000 --- a/providers/common/digests/digest_common.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. - * - * Licensed under the Apache License 2.0 (the "License"). You may not use - * this file except in compliance with the License. You can obtain a copy - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ - -#include "openssl/err.h" -#include "prov/digestcommon.h" -#include "prov/providercommonerr.h" - -int digest_default_get_params(OSSL_PARAM params[], size_t blksz, size_t paramsz, - unsigned long flags) -{ - OSSL_PARAM *p = NULL; - - p = OSSL_PARAM_locate(params, OSSL_DIGEST_PARAM_BLOCK_SIZE); - if (p != NULL && !OSSL_PARAM_set_size_t(p, blksz)) { - ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); - return 0; - } - p = OSSL_PARAM_locate(params, OSSL_DIGEST_PARAM_SIZE); - if (p != NULL && !OSSL_PARAM_set_size_t(p, paramsz)) { - ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); - return 0; - } - p = OSSL_PARAM_locate(params, OSSL_DIGEST_PARAM_FLAGS); - if (p != NULL && !OSSL_PARAM_set_ulong(p, flags)) { - ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); - return 0; - } - return 1; -} - -static const OSSL_PARAM digest_default_known_gettable_params[] = { - OSSL_PARAM_size_t(OSSL_DIGEST_PARAM_BLOCK_SIZE, NULL), - OSSL_PARAM_size_t(OSSL_DIGEST_PARAM_SIZE, NULL), - OSSL_PARAM_ulong(OSSL_DIGEST_PARAM_FLAGS, NULL), - OSSL_PARAM_END -}; -const OSSL_PARAM *digest_default_gettable_params(void) -{ - return digest_default_known_gettable_params; -} diff --git a/providers/common/include/prov/cipher_aead.h b/providers/common/include/prov/cipher_aead.h deleted file mode 100644 index db938d7fbe..0000000000 --- a/providers/common/include/prov/cipher_aead.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. - * - * Licensed under the Apache License 2.0 (the "License"). You may not use - * this file except in compliance with the License. You can obtain a copy - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ - -#define UNINITIALISED_SIZET ((size_t)-1) - -/* TODO(3.0) Figure out what flags are really needed */ -#define AEAD_FLAGS (EVP_CIPH_FLAG_AEAD_CIPHER \ - | EVP_CIPH_CUSTOM_IV \ - | EVP_CIPH_ALWAYS_CALL_INIT \ - | EVP_CIPH_CTRL_INIT \ - | EVP_CIPH_CUSTOM_COPY) - -#define IMPLEMENT_aead_cipher(alg, lc, UCMODE, flags, kbits, blkbits, ivbits) \ -static OSSL_OP_cipher_get_params_fn alg##_##kbits##_##lc##_get_params; \ -static int alg##_##kbits##_##lc##_get_params(OSSL_PARAM params[]) \ -{ \ - return cipher_generic_get_params(params, EVP_CIPH_##UCMODE##_MODE, \ - flags, kbits, blkbits, ivbits); \ -} \ -static OSSL_OP_cipher_newctx_fn alg##kbits##lc##_newctx; \ -static void * alg##kbits##lc##_newctx(void *provctx) \ -{ \ - return alg##_##lc##_newctx(provctx, kbits); \ -} \ -const OSSL_DISPATCH alg##kbits##lc##_functions[] = { \ - { OSSL_FUNC_CIPHER_NEWCTX, (void (*)(void))alg##kbits##lc##_newctx }, \ - { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))alg##_##lc##_freectx }, \ - { OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void)) lc##_einit }, \ - { OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void)) lc##_dinit }, \ - { OSSL_FUNC_CIPHER_UPDATE, (void (*)(void)) lc##_stream_update }, \ - { OSSL_FUNC_CIPHER_FINAL, (void (*)(void)) lc##_stream_final }, \ - { OSSL_FUNC_CIPHER_CIPHER, (void (*)(void)) lc##_cipher }, \ - { OSSL_FUNC_CIPHER_GET_PARAMS, \ - (void (*)(void)) alg##_##kbits##_##lc##_get_params }, \ - { OSSL_FUNC_CIPHER_GET_CTX_PARAMS, \ - (void (*)(void)) lc##_get_ctx_params }, \ - { OSSL_FUNC_CIPHER_SET_CTX_PARAMS, \ - (void (*)(void)) lc##_set_ctx_params }, \ - { OSSL_FUNC_CIPHER_GETTABLE_PARAMS, \ - (void (*)(void))cipher_generic_gettable_params }, \ - { OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS, \ - (void (*)(void))cipher_aead_gettable_ctx_params }, \ - { OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS, \ - (void (*)(void))cipher_aead_settable_ctx_params }, \ - { 0, NULL } \ -} diff --git a/providers/common/include/prov/cipher_ccm.h b/providers/common/include/prov/cipher_ccm.h deleted file mode 100644 index 2214b5fc64..0000000000 --- a/providers/common/include/prov/cipher_ccm.h +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. - * - * Licensed under the Apache License 2.0 (the "License"). You may not use - * this file except in compliance with the License. You can obtain a copy - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ - -#include "cipher_aead.h" - -typedef struct prov_ccm_hw_st PROV_CCM_HW; - -#if defined(OPENSSL_CPUID_OBJ) && defined(__s390__) -/*- - * KMAC-AES parameter block - begin - * (see z/Architecture Principles of Operation >= SA22-7832-08) - */ -typedef struct S390X_kmac_params_st { - union { - unsigned long long g[2]; - unsigned char b[16]; - } icv; - unsigned char k[32]; -} S390X_KMAC_PARAMS; -/* KMAC-AES parameter block - end */ -#endif - -/* Base structure that is shared by AES & ARIA for CCM MODE */ -typedef struct prov_ccm_st { - unsigned int enc : 1; - unsigned int key_set : 1; /* Set if key initialised */ - unsigned int iv_set : 1; /* Set if an iv is set */ - unsigned int tag_set : 1; /* Set if tag is valid */ - unsigned int len_set : 1; /* Set if message length set */ - size_t l, m; /* L and M parameters from RFC3610 */ - size_t keylen; - size_t tls_aad_len; /* TLS AAD length */ - size_t tls_aad_pad_sz; - unsigned char iv[AES_BLOCK_SIZE]; - unsigned char buf[AES_BLOCK_SIZE]; - CCM128_CONTEXT ccm_ctx; - ccm128_f str; - const PROV_CCM_HW *hw; /* hardware specific methods */ -} PROV_CCM_CTX; - -typedef struct prov_aes_ccm_ctx_st { - PROV_CCM_CTX base; /* Must be first */ - union { - OSSL_UNION_ALIGN; - /*- - * Padding is chosen so that s390x.kmac.k overlaps with ks.ks and - * fc with ks.ks.rounds. Remember that on s390x, an AES_KEY's - * rounds field is used to store the function code and that the key - * schedule is not stored (if aes hardware support is detected). - */ - struct { - unsigned char pad[16]; - AES_KEY ks; - } ks; -#if defined(OPENSSL_CPUID_OBJ) && defined(__s390__) - struct { - S390X_KMAC_PARAMS kmac; - unsigned long long blocks; - union { - unsigned long long g[2]; - unsigned char b[AES_BLOCK_SIZE]; - } nonce; - union { - unsigned long long g[2]; - unsigned char b[AES_BLOCK_SIZE]; - } buf; - unsigned char dummy_pad[168]; - unsigned int fc; /* fc has same offset as ks.ks.rounds */ - } s390x; -#endif /* defined(OPENSSL_CPUID_OBJ) && defined(__s390__) */ - } ccm; -} PROV_AES_CCM_CTX; - -PROV_CIPHER_FUNC(int, CCM_cipher, (PROV_CCM_CTX *ctx, unsigned char *out, \ - size_t *padlen, const unsigned char *in, \ - size_t len)); -PROV_CIPHER_FUNC(int, CCM_setkey, (PROV_CCM_CTX *ctx, \ - const unsigned char *key, size_t keylen)); -PROV_CIPHER_FUNC(int, CCM_setiv, (PROV_CCM_CTX *dat, \ - const unsigned char *iv, size_t ivlen, \ - size_t mlen)); -PROV_CIPHER_FUNC(int, CCM_setaad, (PROV_CCM_CTX *ctx, \ - const unsigned char *aad, size_t aadlen)); -PROV_CIPHER_FUNC(int, CCM_auth_encrypt, (PROV_CCM_CTX *ctx, \ - const unsigned char *in, \ - unsigned char *out, size_t len, \ - unsigned char *tag, size_t taglen)); -PROV_CIPHER_FUNC(int, CCM_auth_decrypt, (PROV_CCM_CTX *ctx, \ - const unsigned char *in, \ - unsigned char *out, size_t len, \ - unsigned char *tag, size_t taglen)); -PROV_CIPHER_FUNC(int, CCM_gettag, (PROV_CCM_CTX *ctx, \ - unsigned char *tag, size_t taglen)); - -/* - * CCM Mode internal method table used to handle hardware specific differences, - * (and different algorithms). - */ -struct prov_ccm_hw_st { - OSSL_CCM_setkey_fn setkey; - OSSL_CCM_setiv_fn setiv; - OSSL_CCM_setaad_fn setaad; - OSSL_CCM_auth_encrypt_fn auth_encrypt; - OSSL_CCM_auth_decrypt_fn auth_decrypt; - OSSL_CCM_gettag_fn gettag; -}; - -const PROV_CCM_HW *PROV_AES_HW_ccm(size_t keylen); - -OSSL_OP_cipher_encrypt_init_fn ccm_einit; -OSSL_OP_cipher_decrypt_init_fn ccm_dinit; -OSSL_OP_cipher_get_ctx_params_fn ccm_get_ctx_params; -OSSL_OP_cipher_set_ctx_params_fn ccm_set_ctx_params; -OSSL_OP_cipher_update_fn ccm_stream_update; -OSSL_OP_cipher_final_fn ccm_stream_final; -OSSL_OP_cipher_cipher_fn ccm_cipher; -void ccm_initctx(PROV_CCM_CTX *ctx, size_t keybits, const PROV_CCM_HW *hw); - -int ccm_generic_setiv(PROV_CCM_CTX *ctx, const unsigned char *nonce, - size_t nlen, size_t mlen); -int ccm_generic_setaad(PROV_CCM_CTX *ctx, const unsigned char *aad, size_t alen); -int ccm_generic_gettag(PROV_CCM_CTX *ctx, unsigned char *tag, size_t tlen); -int ccm_generic_auth_encrypt(PROV_CCM_CTX *ctx, const unsigned char *in, - unsigned char *out, size_t len, - unsigned char *tag, size_t taglen); -int ccm_generic_auth_decrypt(PROV_CCM_CTX *ctx, const unsigned char *in, - unsigned char *out, size_t len, - unsigned char *expected_tag, size_t taglen); diff --git a/providers/common/include/prov/cipher_gcm.h b/providers/common/include/prov/cipher_gcm.h deleted file mode 100644 index 711b40cdd4..0000000000 --- a/providers/common/include/prov/cipher_gcm.h +++ /dev/null @@ -1,160 +0,0 @@ - -/* - * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. - * - * Licensed under the Apache License 2.0 (the "License"). You may not use - * this file except in compliance with the License. You can obtain a copy - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ - -#include -#include "cipher_aead.h" - -typedef struct prov_gcm_hw_st PROV_GCM_HW; - -#define GCM_IV_DEFAULT_SIZE 12 /* IV's for AES_GCM should normally be 12 bytes */ -#define GCM_IV_MAX_SIZE 64 -#define GCM_TAG_MAX_SIZE 16 - -#if defined(OPENSSL_CPUID_OBJ) && defined(__s390__) -/*- - * KMA-GCM-AES parameter block - begin - * (see z/Architecture Principles of Operation >= SA22-7832-11) - */ -typedef struct S390X_kma_params_st { - unsigned char reserved[12]; - union { - unsigned int w; - unsigned char b[4]; - } cv; /* 32 bit counter value */ - union { - unsigned long long g[2]; - unsigned char b[16]; - } t; /* tag */ - unsigned char h[16]; /* hash subkey */ - unsigned long long taadl; /* total AAD length */ - unsigned long long tpcl; /* total plaintxt/ciphertxt len */ - union { - unsigned long long g[2]; - unsigned int w[4]; - } j0; /* initial counter value */ - unsigned char k[32]; /* key */ -} S390X_KMA_PARAMS; - -#endif - -typedef struct prov_gcm_ctx_st { - unsigned int mode; /* The mode that we are using */ - size_t keylen; - size_t ivlen; - size_t ivlen_min; - size_t taglen; - size_t tls_aad_pad_sz; - size_t tls_aad_len; /* TLS AAD length */ - uint64_t tls_enc_records; /* Number of TLS records encrypted */ - - /* - * num contains the number of bytes of |iv| which are valid for modes that - * manage partial blocks themselves. - */ - size_t num; - size_t bufsz; /* Number of bytes in buf */ - uint64_t flags; - - unsigned int iv_state; /* set to one of IV_STATE_XXX */ - unsigned int enc:1; /* Set to 1 if we are encrypting or 0 otherwise */ - unsigned int pad:1; /* Whether padding should be used or not */ - unsigned int key_set:1; /* Set if key initialised */ - unsigned int iv_gen_rand:1; /* No IV was specified, so generate a rand IV */ - unsigned int iv_gen:1; /* It is OK to generate IVs */ - - unsigned char iv[GCM_IV_MAX_SIZE]; /* Buffer to use for IV's */ - unsigned char buf[AES_BLOCK_SIZE]; /* Buffer of partial blocks processed via update calls */ - - OPENSSL_CTX *libctx; /* needed for rand calls */ - const PROV_GCM_HW *hw; /* hardware specific methods */ - GCM128_CONTEXT gcm; - ctr128_f ctr; - const void *ks; -} PROV_GCM_CTX; - -typedef struct prov_aes_gcm_ctx_st { - PROV_GCM_CTX base; /* must be first entry in struct */ - union { - OSSL_UNION_ALIGN; - AES_KEY ks; - } ks; /* AES key schedule to use */ - - /* Platform specific data */ - union { - int dummy; -#if defined(OPENSSL_CPUID_OBJ) && defined(__s390__) - struct { - union { - OSSL_UNION_ALIGN; - S390X_KMA_PARAMS kma; - } param; - unsigned int fc; - unsigned char ares[16]; - unsigned char mres[16]; - unsigned char kres[16]; - int areslen; - int mreslen; - int kreslen; - int res; - } s390x; -#endif /* defined(OPENSSL_CPUID_OBJ) && defined(__s390__) */ - } plat; -} PROV_AES_GCM_CTX; - -PROV_CIPHER_FUNC(int, GCM_setkey, (PROV_GCM_CTX *ctx, const unsigned char *key, - size_t keylen)); -PROV_CIPHER_FUNC(int, GCM_setiv, (PROV_GCM_CTX *dat, const unsigned char *iv, - size_t ivlen)); -PROV_CIPHER_FUNC(int, GCM_aadupdate, (PROV_GCM_CTX *ctx, - const unsigned char *aad, size_t aadlen)); -PROV_CIPHER_FUNC(int, GCM_cipherupdate, (PROV_GCM_CTX *ctx, - const unsigned char *in, size_t len, - unsigned char *out)); -PROV_CIPHER_FUNC(int, GCM_cipherfinal, (PROV_GCM_CTX *ctx, unsigned char *tag)); -PROV_CIPHER_FUNC(int, GCM_oneshot, (PROV_GCM_CTX *ctx, unsigned char *aad, - size_t aad_len, const unsigned char *in, - size_t in_len, unsigned char *out, - unsigned char *tag, size_t taglen)); -struct prov_gcm_hw_st { - OSSL_GCM_setkey_fn setkey; - OSSL_GCM_setiv_fn setiv; - OSSL_GCM_aadupdate_fn aadupdate; - OSSL_GCM_cipherupdate_fn cipherupdate; - OSSL_GCM_cipherfinal_fn cipherfinal; - OSSL_GCM_oneshot_fn oneshot; -}; -const PROV_GCM_HW *PROV_AES_HW_gcm(size_t keybits); - -OSSL_OP_cipher_encrypt_init_fn gcm_einit; -OSSL_OP_cipher_decrypt_init_fn gcm_dinit; -OSSL_OP_cipher_get_ctx_params_fn gcm_get_ctx_params; -OSSL_OP_cipher_set_ctx_params_fn gcm_set_ctx_params; -OSSL_OP_cipher_cipher_fn gcm_cipher; -OSSL_OP_cipher_update_fn gcm_stream_update; -OSSL_OP_cipher_final_fn gcm_stream_final; -void gcm_initctx(void *provctx, PROV_GCM_CTX *ctx, size_t keybits, - const PROV_GCM_HW *hw, size_t ivlen_min); - -int gcm_setiv(PROV_GCM_CTX *ctx, const unsigned char *iv, size_t ivlen); -int gcm_aad_update(PROV_GCM_CTX *ctx, const unsigned char *aad, - size_t aad_len); -int gcm_cipher_final(PROV_GCM_CTX *ctx, unsigned char *tag); -int gcm_one_shot(PROV_GCM_CTX *ctx, unsigned char *aad, size_t aad_len, - const unsigned char *in, size_t in_len, - unsigned char *out, unsigned char *tag, size_t tag_len); -int gcm_cipher_update(PROV_GCM_CTX *ctx, const unsigned char *in, - size_t len, unsigned char *out); - -#define GCM_HW_SET_KEY_CTR_FN(ks, fn_set_enc_key, fn_block, fn_ctr) \ - ctx->ks = ks; \ - fn_set_enc_key(key, keylen * 8, ks); \ - CRYPTO_gcm128_init(&ctx->gcm, ks, (block128_f)fn_block); \ - ctx->ctr = (ctr128_f)fn_ctr; \ - ctx->key_set = 1; diff --git a/providers/common/include/prov/ciphercommon.h b/providers/common/include/prov/ciphercommon.h deleted file mode 100644 index 1072b577fe..0000000000 --- a/providers/common/include/prov/ciphercommon.h +++ /dev/null @@ -1,324 +0,0 @@ -/* - * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. - * - * Licensed under the Apache License 2.0 (the "License"). You may not use - * this file except in compliance with the License. You can obtain a copy - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ - -#include -#include -#include -#include -#include "internal/cryptlib.h" -#include "crypto/modes.h" -#include "crypto/ciphermode_platform.h" - -#define MAXCHUNK ((size_t)1 << (sizeof(long) * 8 - 2)) -#define MAXBITCHUNK ((size_t)1 << (sizeof(size_t) * 8 - 4)) - -#define GENERIC_BLOCK_SIZE 16 -#define IV_STATE_UNINITIALISED 0 /* initial state is not initialized */ -#define IV_STATE_BUFFERED 1 /* iv has been copied to the iv buffer */ -#define IV_STATE_COPIED 2 /* iv has been copied from the iv buffer */ -#define IV_STATE_FINISHED 3 /* the iv has been used - so don't reuse it */ - -#define PROV_CIPHER_FUNC(type, name, args) typedef type (* OSSL_##name##_fn)args - -typedef struct prov_cipher_hw_st PROV_CIPHER_HW; -typedef struct prov_cipher_ctx_st PROV_CIPHER_CTX; - -typedef int (PROV_CIPHER_HW_FN)(PROV_CIPHER_CTX *dat, unsigned char *out, - const unsigned char *in, size_t len); - -struct prov_cipher_ctx_st { - block128_f block; - union { - cbc128_f cbc; - ctr128_f ctr; - } stream; - - unsigned int mode; - size_t keylen; /* key size (in bytes) */ - size_t ivlen; - size_t blocksize; - size_t bufsz; /* Number of bytes in buf */ - unsigned int pad : 1; /* Whether padding should be used or not */ - unsigned int enc : 1; /* Set to 1 for encrypt, or 0 otherwise */ - unsigned int iv_set : 1; /* Set when the iv is copied to the iv/oiv buffers */ - - /* - * num contains the number of bytes of |iv| which are valid for modes that - * manage partial blocks themselves. - */ - unsigned int num; - uint64_t flags; - - /* The original value of the iv */ - unsigned char oiv[GENERIC_BLOCK_SIZE]; - /* Buffer of partial blocks processed via update calls */ - unsigned char buf[GENERIC_BLOCK_SIZE]; - unsigned char iv[GENERIC_BLOCK_SIZE]; - const PROV_CIPHER_HW *hw; /* hardware specific functions */ - const void *ks; /* Pointer to algorithm specific key data */ - OPENSSL_CTX *libctx; -}; - -struct prov_cipher_hw_st { - int (*init)(PROV_CIPHER_CTX *dat, const uint8_t *key, size_t keylen); - PROV_CIPHER_HW_FN *cipher; - void (*copyctx)(PROV_CIPHER_CTX *dst, const PROV_CIPHER_CTX *src); -}; - -OSSL_OP_cipher_encrypt_init_fn cipher_generic_einit; -OSSL_OP_cipher_decrypt_init_fn cipher_generic_dinit; -OSSL_OP_cipher_update_fn cipher_generic_block_update; -OSSL_OP_cipher_final_fn cipher_generic_block_final; -OSSL_OP_cipher_update_fn cipher_generic_stream_update; -OSSL_OP_cipher_final_fn cipher_generic_stream_final; -OSSL_OP_cipher_cipher_fn cipher_generic_cipher; -OSSL_OP_cipher_get_ctx_params_fn cipher_generic_get_ctx_params; -OSSL_OP_cipher_set_ctx_params_fn cipher_generic_set_ctx_params; -OSSL_OP_cipher_gettable_params_fn cipher_generic_gettable_params; -OSSL_OP_cipher_gettable_ctx_params_fn cipher_generic_gettable_ctx_params; -OSSL_OP_cipher_settable_ctx_params_fn cipher_generic_settable_ctx_params; -OSSL_OP_cipher_set_ctx_params_fn cipher_var_keylen_set_ctx_params; -OSSL_OP_cipher_settable_ctx_params_fn cipher_var_keylen_settable_ctx_params; -OSSL_OP_cipher_gettable_ctx_params_fn cipher_aead_gettable_ctx_params; -OSSL_OP_cipher_settable_ctx_params_fn cipher_aead_settable_ctx_params; -int cipher_generic_get_params(OSSL_PARAM params[], unsigned int md, - unsigned long flags, - size_t kbits, size_t blkbits, size_t ivbits); -void cipher_generic_initkey(void *vctx, size_t kbits, size_t blkbits, - size_t ivbits, unsigned int mode, uint64_t flags, - const PROV_CIPHER_HW *hw, void *provctx); - -#define IMPLEMENT_generic_cipher_func(alg, UCALG, lcmode, UCMODE, flags, kbits,\ - blkbits, ivbits, typ) \ -const OSSL_DISPATCH alg##kbits##lcmode##_functions[] = { \ - { OSSL_FUNC_CIPHER_NEWCTX, \ - (void (*)(void)) alg##_##kbits##_##lcmode##_newctx }, \ - { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void)) alg##_freectx }, \ - { OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void)) alg##_dupctx }, \ - { OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))cipher_generic_einit }, \ - { OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))cipher_generic_dinit }, \ - { OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))cipher_generic_##typ##_update },\ - { OSSL_FUNC_CIPHER_FINAL, (void (*)(void))cipher_generic_##typ##_final }, \ - { OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))cipher_generic_cipher }, \ - { OSSL_FUNC_CIPHER_GET_PARAMS, \ - (void (*)(void)) alg##_##kbits##_##lcmode##_get_params }, \ - { OSSL_FUNC_CIPHER_GET_CTX_PARAMS, \ - (void (*)(void))cipher_generic_get_ctx_params }, \ - { OSSL_FUNC_CIPHER_SET_CTX_PARAMS, \ - (void (*)(void))cipher_generic_set_ctx_params }, \ - { OSSL_FUNC_CIPHER_GETTABLE_PARAMS, \ - (void (*)(void))cipher_generic_gettable_params }, \ - { OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS, \ - (void (*)(void))cipher_generic_gettable_ctx_params }, \ - { OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS, \ - (void (*)(void))cipher_generic_settable_ctx_params }, \ - { 0, NULL } \ -}; - -#define IMPLEMENT_var_keylen_cipher_func(alg, UCALG, lcmode, UCMODE, flags, \ - kbits, blkbits, ivbits, typ) \ -const OSSL_DISPATCH alg##kbits##lcmode##_functions[] = { \ - { OSSL_FUNC_CIPHER_NEWCTX, \ - (void (*)(void)) alg##_##kbits##_##lcmode##_newctx }, \ - { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void)) alg##_freectx }, \ - { OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void)) alg##_dupctx }, \ - { OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))cipher_generic_einit }, \ - { OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))cipher_generic_dinit }, \ - { OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))cipher_generic_##typ##_update },\ - { OSSL_FUNC_CIPHER_FINAL, (void (*)(void))cipher_generic_##typ##_final }, \ - { OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))cipher_generic_cipher }, \ - { OSSL_FUNC_CIPHER_GET_PARAMS, \ - (void (*)(void)) alg##_##kbits##_##lcmode##_get_params }, \ - { OSSL_FUNC_CIPHER_GET_CTX_PARAMS, \ - (void (*)(void))cipher_generic_get_ctx_params }, \ - { OSSL_FUNC_CIPHER_SET_CTX_PARAMS, \ - (void (*)(void))cipher_var_keylen_set_ctx_params }, \ - { OSSL_FUNC_CIPHER_GETTABLE_PARAMS, \ - (void (*)(void))cipher_generic_gettable_params }, \ - { OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS, \ - (void (*)(void))cipher_generic_gettable_ctx_params }, \ - { OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS, \ - (void (*)(void))cipher_var_keylen_settable_ctx_params }, \ - { 0, NULL } \ -}; - - -#define IMPLEMENT_generic_cipher_genfn(alg, UCALG, lcmode, UCMODE, flags, \ - kbits, blkbits, ivbits, typ) \ -static OSSL_OP_cipher_get_params_fn alg##_##kbits##_##lcmode##_get_params; \ -static int alg##_##kbits##_##lcmode##_get_params(OSSL_PARAM params[]) \ -{ \ - return cipher_generic_get_params(params, EVP_CIPH_##UCMODE##_MODE, flags, \ - kbits, blkbits, ivbits); \ -} \ -static OSSL_OP_cipher_newctx_fn alg##_##kbits##_##lcmode##_newctx; \ -static void * alg##_##kbits##_##lcmode##_newctx(void *provctx) \ -{ \ - PROV_##UCALG##_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx)); \ - if (ctx != NULL) { \ - cipher_generic_initkey(ctx, kbits, blkbits, ivbits, \ - EVP_CIPH_##UCMODE##_MODE, flags, \ - PROV_CIPHER_HW_##alg##_##lcmode(kbits), NULL); \ - } \ - return ctx; \ -} \ - -#define IMPLEMENT_generic_cipher(alg, UCALG, lcmode, UCMODE, flags, kbits, \ - blkbits, ivbits, typ) \ -IMPLEMENT_generic_cipher_genfn(alg, UCALG, lcmode, UCMODE, flags, kbits, \ - blkbits, ivbits, typ) \ -IMPLEMENT_generic_cipher_func(alg, UCALG, lcmode, UCMODE, flags, kbits, \ - blkbits, ivbits, typ) - -#define IMPLEMENT_var_keylen_cipher(alg, UCALG, lcmode, UCMODE, flags, kbits, \ - blkbits, ivbits, typ) \ -IMPLEMENT_generic_cipher_genfn(alg, UCALG, lcmode, UCMODE, flags, kbits, \ - blkbits, ivbits, typ) \ -IMPLEMENT_var_keylen_cipher_func(alg, UCALG, lcmode, UCMODE, flags, kbits, \ - blkbits, ivbits, typ) - -PROV_CIPHER_HW_FN cipher_hw_generic_cbc; -PROV_CIPHER_HW_FN cipher_hw_generic_ecb; -PROV_CIPHER_HW_FN cipher_hw_generic_ofb128; -PROV_CIPHER_HW_FN cipher_hw_generic_cfb128; -PROV_CIPHER_HW_FN cipher_hw_generic_cfb8; -PROV_CIPHER_HW_FN cipher_hw_generic_cfb1; -PROV_CIPHER_HW_FN cipher_hw_generic_ctr; -PROV_CIPHER_HW_FN cipher_hw_chunked_cbc; -PROV_CIPHER_HW_FN cipher_hw_chunked_cfb8; -PROV_CIPHER_HW_FN cipher_hw_chunked_cfb128; -PROV_CIPHER_HW_FN cipher_hw_chunked_ofb128; -#define cipher_hw_chunked_ecb cipher_hw_generic_ecb -#define cipher_hw_chunked_ctr cipher_hw_generic_ctr -#define cipher_hw_chunked_cfb1 cipher_hw_generic_cfb1 - -#define IMPLEMENT_CIPHER_HW_OFB(MODE, NAME, CTX_NAME, KEY_NAME, FUNC_PREFIX) \ -static int cipher_hw_##NAME##_##MODE##_cipher(PROV_CIPHER_CTX *ctx, \ - unsigned char *out, \ - const unsigned char *in, size_t len) \ -{ \ - int num = ctx->num; \ - KEY_NAME *key = &(((CTX_NAME *)ctx)->ks.ks); \ - \ - while (len >= MAXCHUNK) { \ - FUNC_PREFIX##_encrypt(in, out, MAXCHUNK, key, ctx->iv, &num); \ - len -= MAXCHUNK; \ - in += MAXCHUNK; \ - out += MAXCHUNK; \ - } \ - if (len > 0) { \ - FUNC_PREFIX##_encrypt(in, out, (long)len, key, ctx->iv, &num); \ - } \ - ctx->num = num; \ - return 1; \ -} - -#define IMPLEMENT_CIPHER_HW_ECB(MODE, NAME, CTX_NAME, KEY_NAME, FUNC_PREFIX) \ -static int cipher_hw_##NAME##_##MODE##_cipher(PROV_CIPHER_CTX *ctx, \ - unsigned char *out, \ - const unsigned char *in, size_t len) \ -{ \ - size_t i, bl = ctx->blocksize; \ - KEY_NAME *key = &(((CTX_NAME *)ctx)->ks.ks); \ - \ - if (len < bl) \ - return 1; \ - for (i = 0, len -= bl; i <= len; i += bl) \ - FUNC_PREFIX##_encrypt(in + i, out + i, key, ctx->enc); \ - return 1; \ -} - -#define IMPLEMENT_CIPHER_HW_CBC(MODE, NAME, CTX_NAME, KEY_NAME, FUNC_PREFIX) \ -static int cipher_hw_##NAME##_##MODE##_cipher(PROV_CIPHER_CTX *ctx, \ - unsigned char *out, \ - const unsigned char *in, size_t len) \ -{ \ - KEY_NAME *key = &(((CTX_NAME *)ctx)->ks.ks); \ - \ - while (len >= MAXCHUNK) { \ - FUNC_PREFIX##_encrypt(in, out, MAXCHUNK, key, ctx->iv, ctx->enc); \ - len -= MAXCHUNK; \ - in += MAXCHUNK; \ - out += MAXCHUNK; \ - } \ - if (len > 0) \ - FUNC_PREFIX##_encrypt(in, out, (long)len, key, ctx->iv, ctx->enc); \ - return 1; \ -} - -#define IMPLEMENT_CIPHER_HW_CFB(MODE, NAME, CTX_NAME, KEY_NAME, FUNC_PREFIX) \ -static int cipher_hw_##NAME##_##MODE##_cipher(PROV_CIPHER_CTX *ctx, \ - unsigned char *out, \ - const unsigned char *in, size_t len) \ -{ \ - size_t chunk = MAXCHUNK; \ - KEY_NAME *key = &(((CTX_NAME *)ctx)->ks.ks); \ - int num = ctx->num; \ - \ - if (len < chunk) \ - chunk = len; \ - while (len > 0 && len >= chunk) { \ - FUNC_PREFIX##_encrypt(in, out, (long)chunk, key, ctx->iv, &num, \ - ctx->enc); \ - len -= chunk; \ - in += chunk; \ - out += chunk; \ - if (len < chunk) \ - chunk = len; \ - } \ - ctx->num = num; \ - return 1; \ -} - -#define IMPLEMENT_CIPHER_HW_COPYCTX(name, CTX_TYPE) \ -static void name(PROV_CIPHER_CTX *dst, const PROV_CIPHER_CTX *src) \ -{ \ - CTX_TYPE *sctx = (CTX_TYPE *)src; \ - CTX_TYPE *dctx = (CTX_TYPE *)dst; \ - \ - *dctx = *sctx; \ - dst->ks = &dctx->ks.ks; \ -} - -#define CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_START(name) \ -static const OSSL_PARAM name##_known_gettable_ctx_params[] = { \ - OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL), \ - OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_IVLEN, NULL), \ - OSSL_PARAM_uint(OSSL_CIPHER_PARAM_PADDING, NULL), \ - OSSL_PARAM_uint(OSSL_CIPHER_PARAM_NUM, NULL), \ - OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_IV, NULL, 0), - -#define CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_END(name) \ - OSSL_PARAM_END \ -}; \ -const OSSL_PARAM * name##_gettable_ctx_params(void) \ -{ \ - return name##_known_gettable_ctx_params; \ -} - -#define CIPHER_DEFAULT_SETTABLE_CTX_PARAMS_START(name) \ -static const OSSL_PARAM name##_known_settable_ctx_params[] = { \ - OSSL_PARAM_uint(OSSL_CIPHER_PARAM_PADDING, NULL), \ - OSSL_PARAM_uint(OSSL_CIPHER_PARAM_NUM, NULL), -#define CIPHER_DEFAULT_SETTABLE_CTX_PARAMS_END(name) \ - OSSL_PARAM_END \ -}; \ -const OSSL_PARAM * name##_settable_ctx_params(void) \ -{ \ - return name##_known_settable_ctx_params; \ -} - -int cipher_generic_initiv(PROV_CIPHER_CTX *ctx, const unsigned char *iv, - size_t ivlen); - -size_t fillblock(unsigned char *buf, size_t *buflen, size_t blocksize, - const unsigned char **in, size_t *inlen); -int trailingdata(unsigned char *buf, size_t *buflen, size_t blocksize, - const unsigned char **in, size_t *inlen); - diff --git a/providers/common/include/prov/digestcommon.h b/providers/common/include/prov/digestcommon.h deleted file mode 100644 index e5b76ff49f..0000000000 --- a/providers/common/include/prov/digestcommon.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. - * - * Licensed under the Apache License 2.0 (the "License"). You may not use - * this file except in compliance with the License. You can obtain a copy - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ - -#ifndef OSSL_PROVIDERS_DIGESTCOMMON_H -# define OSSL_PROVIDERS_DIGESTCOMMON_H - -# include -# include -# include - -# ifdef __cplusplus -extern "C" { -# endif - -#define PROV_FUNC_DIGEST_GET_PARAM(name, blksize, dgstsize, flags) \ -static OSSL_OP_digest_get_params_fn name##_get_params; \ -static int name##_get_params(OSSL_PARAM params[]) \ -{ \ - return digest_default_get_params(params, blksize, dgstsize, flags); \ -} - -#define PROV_DISPATCH_FUNC_DIGEST_GET_PARAMS(name) \ -{ OSSL_FUNC_DIGEST_GET_PARAMS, (void (*)(void))name##_get_params }, \ -{ OSSL_FUNC_DIGEST_GETTABLE_PARAMS, \ - (void (*)(void))digest_default_gettable_params } - -# define PROV_DISPATCH_FUNC_DIGEST_CONSTRUCT_START( \ - name, CTX, blksize, dgstsize, flags, init, upd, fin) \ -static OSSL_OP_digest_newctx_fn name##_newctx; \ -static OSSL_OP_digest_freectx_fn name##_freectx; \ -static OSSL_OP_digest_dupctx_fn name##_dupctx; \ -static void *name##_newctx(void *prov_ctx) \ -{ \ - CTX *ctx = OPENSSL_zalloc(sizeof(*ctx)); \ - return ctx; \ -} \ -static void name##_freectx(void *vctx) \ -{ \ - CTX *ctx = (CTX *)vctx; \ - OPENSSL_clear_free(ctx, sizeof(*ctx)); \ -} \ -static void *name##_dupctx(void *ctx) \ -{ \ - CTX *in = (CTX *)ctx; \ - CTX *ret = OPENSSL_malloc(sizeof(*ret)); \ - if (ret != NULL) \ - *ret = *in; \ - return ret; \ -} \ -static OSSL_OP_digest_final_fn name##_internal_final; \ -static int name##_internal_final(void *ctx, unsigned char *out, size_t *outl, \ - size_t outsz) \ -{ \ - if (outsz >= dgstsize && fin(out, ctx)) { \ - *outl = dgstsize; \ - return 1; \ - } \ - return 0; \ -} \ -PROV_FUNC_DIGEST_GET_PARAM(name, blksize, dgstsize, flags) \ -const OSSL_DISPATCH name##_functions[] = { \ - { OSSL_FUNC_DIGEST_NEWCTX, (void (*)(void))name##_newctx }, \ - { OSSL_FUNC_DIGEST_INIT, (void (*)(void))init }, \ - { OSSL_FUNC_DIGEST_UPDATE, (void (*)(void))upd }, \ - { OSSL_FUNC_DIGEST_FINAL, (void (*)(void))name##_internal_final }, \ - { OSSL_FUNC_DIGEST_FREECTX, (void (*)(void))name##_freectx }, \ - { OSSL_FUNC_DIGEST_DUPCTX, (void (*)(void))name##_dupctx }, \ - PROV_DISPATCH_FUNC_DIGEST_GET_PARAMS(name) - -# define PROV_DISPATCH_FUNC_DIGEST_CONSTRUCT_END \ - { 0, NULL } \ -}; - -# define IMPLEMENT_digest_functions( \ - name, CTX, blksize, dgstsize, flags, init, upd, fin) \ -PROV_DISPATCH_FUNC_DIGEST_CONSTRUCT_START(name, CTX, blksize, dgstsize, flags, \ - init, upd, fin), \ -PROV_DISPATCH_FUNC_DIGEST_CONSTRUCT_END - -# define IMPLEMENT_digest_functions_with_settable_ctx( \ - name, CTX, blksize, dgstsize, flags, init, upd, fin, \ - settable_ctx_params, set_ctx_params) \ -PROV_DISPATCH_FUNC_DIGEST_CONSTRUCT_START(name, CTX, blksize, dgstsize, flags, \ - init, upd, fin), \ -{ OSSL_FUNC_DIGEST_SETTABLE_CTX_PARAMS, (void (*)(void))settable_ctx_params }, \ -{ OSSL_FUNC_DIGEST_SET_CTX_PARAMS, (void (*)(void))set_ctx_params }, \ -PROV_DISPATCH_FUNC_DIGEST_CONSTRUCT_END - - -const OSSL_PARAM *digest_default_gettable_params(void); -int digest_default_get_params(OSSL_PARAM params[], size_t blksz, size_t paramsz, - unsigned long flags); - -# ifdef __cplusplus -} -# endif - -#endif /* OSSL_PROVIDERS_DIGESTCOMMON_H */ diff --git a/providers/implementations/ciphers/build.info b/providers/implementations/ciphers/build.info index 0a76962669..abc193bb1d 100644 --- a/providers/implementations/ciphers/build.info +++ b/providers/implementations/ciphers/build.info @@ -5,6 +5,8 @@ # The latter may become legacy sooner, so it's comfortable to have two # variables already now, to switch the non-FIPSable TDES to legacy if needed. +$COMMON_GOAL=../../libcommon.a + $AES_GOAL=../../libimplementations.a $TDES_1_GOAL=../../libimplementations.a $TDES_2_GOAL=../../libimplementations.a @@ -23,6 +25,12 @@ $CHACHA_GOAL=../../libimplementations.a $CHACHAPOLY_GOAL=../../libimplementations.a $SIV_GOAL=../../libimplementations.a +# This source is common building blocks for all ciphers in all our providers. +SOURCE[$COMMON_GOAL]=\ + ciphercommon.c ciphercommon_hw.c ciphercommon_block.c \ + ciphercommon_gcm.c ciphercommon_gcm_hw.c \ + ciphercommon_ccm.c ciphercommon_ccm_hw.c + IF[{- !$disabled{des} -}] SOURCE[$TDES_1_GOAL]=cipher_tdes.c cipher_tdes_hw.c ENDIF diff --git a/providers/implementations/ciphers/cipher_aes_ccm.c b/providers/implementations/ciphers/cipher_aes_ccm.c index c1fb51b565..b6655143d9 100644 --- a/providers/implementations/ciphers/cipher_aes_ccm.c +++ b/providers/implementations/ciphers/cipher_aes_ccm.c @@ -10,7 +10,7 @@ /* Dispatch functions for AES CCM mode */ #include "prov/ciphercommon.h" -#include "prov/cipher_ccm.h" +#include "prov/ciphercommon_ccm.h" #include "prov/implementations.h" static void *aes_ccm_newctx(void *provctx, size_t keybits) diff --git a/providers/implementations/ciphers/cipher_aes_ccm_hw.c b/providers/implementations/ciphers/cipher_aes_ccm_hw.c index ae200ebada..0b1e50163b 100644 --- a/providers/implementations/ciphers/cipher_aes_ccm_hw.c +++ b/providers/implementations/ciphers/cipher_aes_ccm_hw.c @@ -10,7 +10,7 @@ /* AES CCM mode */ #include "prov/ciphercommon.h" -#include "prov/cipher_ccm.h" +#include "prov/ciphercommon_ccm.h" #define AES_HW_CCM_SET_KEY_FN(fn_set_enc_key, fn_blk, fn_ccm_enc, fn_ccm_dec) \ fn_set_enc_key(key, keylen * 8, &actx->ccm.ks.ks); \ diff --git a/providers/implementations/ciphers/cipher_aes_ccm_hw_aesni.inc b/providers/implementations/ciphers/cipher_aes_ccm_hw_aesni.inc index 3a5e4a740d..7e83565809 100644 --- a/providers/implementations/ciphers/cipher_aes_ccm_hw_aesni.inc +++ b/providers/implementations/ciphers/cipher_aes_ccm_hw_aesni.inc @@ -9,7 +9,7 @@ /*- * AES-NI support for AES CCM. - * This file is included by cipher_ccm_hw.c + * This file is included by cipher_aes_ccm_hw.c */ static int ccm_aesni_initkey(PROV_CCM_CTX *ctx, const unsigned char *key, diff --git a/providers/implementations/ciphers/cipher_aes_ccm_hw_s390x.inc b/providers/implementations/ciphers/cipher_aes_ccm_hw_s390x.inc index a5025e5960..cec7c96902 100644 --- a/providers/implementations/ciphers/cipher_aes_ccm_hw_s390x.inc +++ b/providers/implementations/ciphers/cipher_aes_ccm_hw_s390x.inc @@ -9,7 +9,7 @@ /*- * S390X support for AES CCM. - * This file is included by cipher_ccm_hw.c + * This file is included by cipher_aes_ccm_hw.c */ #define S390X_CCM_AAD_FLAG 0x40 diff --git a/providers/implementations/ciphers/cipher_aes_ccm_hw_t4.inc b/providers/implementations/ciphers/cipher_aes_ccm_hw_t4.inc index 21bf6861e0..c4b6d15ed9 100644 --- a/providers/implementations/ciphers/cipher_aes_ccm_hw_t4.inc +++ b/providers/implementations/ciphers/cipher_aes_ccm_hw_t4.inc @@ -9,7 +9,7 @@ /*- * Fujitsu SPARC64 X support for AES CCM. - * This file is included by cipher_ccm_hw.c + * This file is included by cipher_aes_ccm_hw.c */ static int ccm_t4_aes_initkey(PROV_CCM_CTX *ctx, const unsigned char *key, diff --git a/providers/implementations/ciphers/cipher_aes_gcm.c b/providers/implementations/ciphers/cipher_aes_gcm.c index 4ebc8140ee..18277c705e 100644 --- a/providers/implementations/ciphers/cipher_aes_gcm.c +++ b/providers/implementations/ciphers/cipher_aes_gcm.c @@ -10,7 +10,7 @@ /* Dispatch functions for AES GCM mode */ #include "prov/ciphercommon.h" -#include "prov/cipher_gcm.h" +#include "prov/ciphercommon_gcm.h" #include "prov/implementations.h" static void *aes_gcm_newctx(void *provctx, size_t keybits) diff --git a/providers/implementations/ciphers/cipher_aes_gcm_hw.c b/providers/implementations/ciphers/cipher_aes_gcm_hw.c index f5dc0c4eed..6a2f8a5fd4 100644 --- a/providers/implementations/ciphers/cipher_aes_gcm_hw.c +++ b/providers/implementations/ciphers/cipher_aes_gcm_hw.c @@ -10,7 +10,7 @@ /* Dispatch functions for AES GCM mode */ #include "prov/ciphercommon.h" -#include "prov/cipher_gcm.h" +#include "prov/ciphercommon_gcm.h" static int generic_aes_gcm_initkey(PROV_GCM_CTX *ctx, const unsigned char *key, size_t keylen) diff --git a/providers/implementations/ciphers/cipher_aes_gcm_hw_aesni.inc b/providers/implementations/ciphers/cipher_aes_gcm_hw_aesni.inc index eb2a3f343a..2fc86982c0 100644 --- a/providers/implementations/ciphers/cipher_aes_gcm_hw_aesni.inc +++ b/providers/implementations/ciphers/cipher_aes_gcm_hw_aesni.inc @@ -9,7 +9,7 @@ /*- * AES-NI support for AES GCM. - * This file is included by cipher_gcm_hw.c + * This file is included by cipher_aes_gcm_hw.c */ static int aesni_gcm_initkey(PROV_GCM_CTX *ctx, const unsigned char *key, diff --git a/providers/implementations/ciphers/cipher_aes_gcm_hw_s390x.inc b/providers/implementations/ciphers/cipher_aes_gcm_hw_s390x.inc index 44c3bf332d..e13771a449 100644 --- a/providers/implementations/ciphers/cipher_aes_gcm_hw_s390x.inc +++ b/providers/implementations/ciphers/cipher_aes_gcm_hw_s390x.inc @@ -9,7 +9,7 @@ /*- * IBM S390X support for AES GCM. - * This file is included by cipher_gcm_hw.c + * This file is included by cipher_aes_gcm_hw.c */ /* iv + padding length for iv lengths != 12 */ diff --git a/providers/implementations/ciphers/cipher_aes_gcm_hw_t4.inc b/providers/implementations/ciphers/cipher_aes_gcm_hw_t4.inc index 19e9ccb760..cc7d4ba528 100644 --- a/providers/implementations/ciphers/cipher_aes_gcm_hw_t4.inc +++ b/providers/implementations/ciphers/cipher_aes_gcm_hw_t4.inc @@ -9,7 +9,7 @@ /*- * Fujitsu SPARC64 X support for AES GCM. - * This file is included by cipher_gcm_hw.c + * This file is included by cipher_aes_gcm_hw.c */ static int t4_aes_gcm_initkey(PROV_GCM_CTX *ctx, const unsigned char *key, diff --git a/providers/implementations/ciphers/cipher_aes_ocb.c b/providers/implementations/ciphers/cipher_aes_ocb.c index 6b07caaa52..03ec70b949 100644 --- a/providers/implementations/ciphers/cipher_aes_ocb.c +++ b/providers/implementations/ciphers/cipher_aes_ocb.c @@ -9,7 +9,7 @@ #include "cipher_aes_ocb.h" #include "prov/providercommonerr.h" -#include "prov/cipher_aead.h" +#include "prov/ciphercommon_aead.h" #include "prov/implementations.h" #define AES_OCB_FLAGS AEAD_FLAGS diff --git a/providers/implementations/ciphers/cipher_aes_siv.c b/providers/implementations/ciphers/cipher_aes_siv.c index 864ebc725e..ada6b27435 100644 --- a/providers/implementations/ciphers/cipher_aes_siv.c +++ b/providers/implementations/ciphers/cipher_aes_siv.c @@ -12,7 +12,7 @@ #include "cipher_aes_siv.h" #include "prov/implementations.h" #include "prov/providercommonerr.h" -#include "prov/cipher_aead.h" +#include "prov/ciphercommon_aead.h" #define siv_stream_update siv_cipher #define SIV_FLAGS AEAD_FLAGS diff --git a/providers/implementations/ciphers/cipher_aria_ccm.h b/providers/implementations/ciphers/cipher_aria_ccm.h index 301ce14306..a85cf899ef 100644 --- a/providers/implementations/ciphers/cipher_aria_ccm.h +++ b/providers/implementations/ciphers/cipher_aria_ccm.h @@ -9,7 +9,7 @@ #include "crypto/aria.h" #include "prov/ciphercommon.h" -#include "prov/cipher_ccm.h" +#include "prov/ciphercommon_ccm.h" typedef struct prov_aria_ccm_ctx_st { PROV_CCM_CTX base; /* Must be first */ diff --git a/providers/implementations/ciphers/cipher_aria_gcm.h b/providers/implementations/ciphers/cipher_aria_gcm.h index 13fbe175d9..2d08a59029 100644 --- a/providers/implementations/ciphers/cipher_aria_gcm.h +++ b/providers/implementations/ciphers/cipher_aria_gcm.h @@ -9,7 +9,7 @@ #include "crypto/aria.h" #include "prov/ciphercommon.h" -#include "prov/cipher_gcm.h" +#include "prov/ciphercommon_gcm.h" typedef struct prov_aria_gcm_ctx_st { PROV_GCM_CTX base; /* must be first entry in struct */ diff --git a/providers/implementations/ciphers/ciphercommon.c b/providers/implementations/ciphers/ciphercommon.c new file mode 100644 index 0000000000..a6b890704e --- /dev/null +++ b/providers/implementations/ciphers/ciphercommon.c @@ -0,0 +1,431 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * Generic dispatch table functions for ciphers. + */ + +#include "ciphercommon_local.h" +#include "prov/provider_ctx.h" +#include "prov/providercommonerr.h" + +/*- + * Generic cipher functions for OSSL_PARAM gettables and settables + */ +static const OSSL_PARAM cipher_known_gettable_params[] = { + OSSL_PARAM_uint(OSSL_CIPHER_PARAM_MODE, NULL), + OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL), + OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_IVLEN, NULL), + OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_BLOCK_SIZE, NULL), + OSSL_PARAM_ulong(OSSL_CIPHER_PARAM_FLAGS, NULL), + OSSL_PARAM_END +}; +const OSSL_PARAM *cipher_generic_gettable_params(void) +{ + return cipher_known_gettable_params; +} + +int cipher_generic_get_params(OSSL_PARAM params[], unsigned int md, + unsigned long flags, + size_t kbits, size_t blkbits, size_t ivbits) +{ + OSSL_PARAM *p; + + p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_MODE); + if (p != NULL && !OSSL_PARAM_set_uint(p, md)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + return 0; + } + p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_FLAGS); + if (p != NULL && !OSSL_PARAM_set_ulong(p, flags)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + return 0; + } + p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_KEYLEN); + if (p != NULL && !OSSL_PARAM_set_size_t(p, kbits / 8)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + return 0; + } + p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_BLOCK_SIZE); + if (p != NULL && !OSSL_PARAM_set_size_t(p, blkbits / 8)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + return 0; + } + p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IVLEN); + if (p != NULL && !OSSL_PARAM_set_size_t(p, ivbits / 8)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + return 0; + } + return 1; +} + +CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_START(cipher_generic) +CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_END(cipher_generic) + +CIPHER_DEFAULT_SETTABLE_CTX_PARAMS_START(cipher_generic) +CIPHER_DEFAULT_SETTABLE_CTX_PARAMS_END(cipher_generic) + +/* + * Variable key length cipher functions for OSSL_PARAM settables + */ + +int cipher_var_keylen_set_ctx_params(void *vctx, const OSSL_PARAM params[]) +{ + PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx; + const OSSL_PARAM *p; + + if (!cipher_generic_set_ctx_params(vctx, params)) + return 0; + p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_KEYLEN); + if (p != NULL) { + size_t keylen; + + if (!OSSL_PARAM_get_size_t(p, &keylen)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); + return 0; + } + ctx->keylen = keylen; + } + return 1; +} + +CIPHER_DEFAULT_SETTABLE_CTX_PARAMS_START(cipher_var_keylen) +OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL), +CIPHER_DEFAULT_SETTABLE_CTX_PARAMS_END(cipher_var_keylen) + +/*- + * AEAD cipher functions for OSSL_PARAM gettables and settables + */ +static const OSSL_PARAM cipher_aead_known_gettable_ctx_params[] = { + OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL), + OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_IVLEN, NULL), + OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_AEAD_TAGLEN, NULL), + OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_IV, NULL, 0), + OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, NULL, 0), + OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_AEAD_TLS1_AAD_PAD, NULL), + OSSL_PARAM_END +}; +const OSSL_PARAM *cipher_aead_gettable_ctx_params(void) +{ + return cipher_aead_known_gettable_ctx_params; +} + +static const OSSL_PARAM cipher_aead_known_settable_ctx_params[] = { + OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_AEAD_IVLEN, NULL), + OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, NULL, 0), + OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TLS1_AAD, NULL, 0), + OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TLS1_IV_FIXED, NULL, 0), + OSSL_PARAM_END +}; +const OSSL_PARAM *cipher_aead_settable_ctx_params(void) +{ + return cipher_aead_known_settable_ctx_params; +} + +static int cipher_generic_init_internal(PROV_CIPHER_CTX *ctx, + const unsigned char *key, size_t keylen, + const unsigned char *iv, size_t ivlen, + int enc) +{ + ctx->enc = enc ? 1 : 0; + + if (iv != NULL && ctx->mode != EVP_CIPH_ECB_MODE) { + if (!cipher_generic_initiv(ctx, iv, ivlen)) + return 0; + } + if (key != NULL) { + if ((ctx->flags & EVP_CIPH_VARIABLE_LENGTH) == 0) { + if (keylen != ctx->keylen) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEYLEN); + return 0; + } + } else { + ctx->keylen = keylen; + } + return ctx->hw->init(ctx, key, ctx->keylen); + } + return 1; +} + +int cipher_generic_einit(void *vctx, const unsigned char *key, size_t keylen, + const unsigned char *iv, size_t ivlen) +{ + return cipher_generic_init_internal((PROV_CIPHER_CTX *)vctx, key, keylen, + iv, ivlen, 1); +} + +int cipher_generic_dinit(void *vctx, const unsigned char *key, size_t keylen, + const unsigned char *iv, size_t ivlen) +{ + return cipher_generic_init_internal((PROV_CIPHER_CTX *)vctx, key, keylen, + iv, ivlen, 0); +} + +int cipher_generic_block_update(void *vctx, unsigned char *out, size_t *outl, + size_t outsize, const unsigned char *in, + size_t inl) +{ + size_t outlint = 0; + PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx; + size_t blksz = ctx->blocksize; + size_t nextblocks = fillblock(ctx->buf, &ctx->bufsz, blksz, &in, &inl); + + /* + * If we're decrypting and we end an update on a block boundary we hold + * the last block back in case this is the last update call and the last + * block is padded. + */ + if (ctx->bufsz == blksz && (ctx->enc || inl > 0 || !ctx->pad)) { + if (outsize < blksz) { + ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); + return 0; + } + if (!ctx->hw->cipher(ctx, out, ctx->buf, blksz)) { + ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED); + return 0; + } + ctx->bufsz = 0; + outlint = blksz; + out += blksz; + } + if (nextblocks > 0) { + if (!ctx->enc && ctx->pad && nextblocks == inl) { + if (!ossl_assert(inl >= blksz)) { + ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); + return 0; + } + nextblocks -= blksz; + } + outlint += nextblocks; + if (outsize < outlint) { + ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); + return 0; + } + } + if (nextblocks > 0) { + if (!ctx->hw->cipher(ctx, out, in, nextblocks)) { + ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED); + return 0; + } + in += nextblocks; + inl -= nextblocks; + } + if (!trailingdata(ctx->buf, &ctx->bufsz, blksz, &in, &inl)) { + /* ERR_raise already called */ + return 0; + } + + *outl = outlint; + return inl == 0; +} + +int cipher_generic_block_final(void *vctx, unsigned char *out, size_t *outl, + size_t outsize) +{ + PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx; + size_t blksz = ctx->blocksize; + + if (ctx->enc) { + if (ctx->pad) { + padblock(ctx->buf, &ctx->bufsz, blksz); + } else if (ctx->bufsz == 0) { + *outl = 0; + return 1; + } else if (ctx->bufsz != blksz) { + ERR_raise(ERR_LIB_PROV, PROV_R_WRONG_FINAL_BLOCK_LENGTH); + return 0; + } + + if (outsize < blksz) { + ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); + return 0; + } + if (!ctx->hw->cipher(ctx, out, ctx->buf, blksz)) { + ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED); + return 0; + } + ctx->bufsz = 0; + *outl = blksz; + return 1; + } + + /* Decrypting */ + if (ctx->bufsz != blksz) { + if (ctx->bufsz == 0 && !ctx->pad) { + *outl = 0; + return 1; + } + ERR_raise(ERR_LIB_PROV, PROV_R_WRONG_FINAL_BLOCK_LENGTH); + return 0; + } + + if (!ctx->hw->cipher(ctx, ctx->buf, ctx->buf, blksz)) { + ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED); + return 0; + } + + if (ctx->pad && !unpadblock(ctx->buf, &ctx->bufsz, blksz)) { + /* ERR_raise already called */ + return 0; + } + + if (outsize < ctx->bufsz) { + ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); + return 0; + } + memcpy(out, ctx->buf, ctx->bufsz); + *outl = ctx->bufsz; + ctx->bufsz = 0; + return 1; +} + +int cipher_generic_stream_update(void *vctx, unsigned char *out, size_t *outl, + size_t outsize, const unsigned char *in, + size_t inl) +{ + PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx; + + if (inl == 0) { + *outl = 0; + return 1; + } + + if (outsize < inl) { + ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); + return 0; + } + + if (!ctx->hw->cipher(ctx, out, in, inl)) { + ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED); + return 0; + } + + *outl = inl; + return 1; +} +int cipher_generic_stream_final(void *vctx, unsigned char *out, size_t *outl, + size_t outsize) +{ + *outl = 0; + return 1; +} + +int cipher_generic_cipher(void *vctx, + unsigned char *out, size_t *outl, size_t outsize, + const unsigned char *in, size_t inl) +{ + PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx; + + if (outsize < inl) { + ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); + return 0; + } + + if (!ctx->hw->cipher(ctx, out, in, inl)) { + ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED); + return 0; + } + + *outl = inl; + return 1; +} + +int cipher_generic_get_ctx_params(void *vctx, OSSL_PARAM params[]) +{ + PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx; + OSSL_PARAM *p; + + p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IVLEN); + if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->ivlen)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + return 0; + } + p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_PADDING); + if (p != NULL && !OSSL_PARAM_set_uint(p, ctx->pad)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + return 0; + } + p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IV); + if (p != NULL + && !OSSL_PARAM_set_octet_ptr(p, &ctx->oiv, ctx->ivlen) + && !OSSL_PARAM_set_octet_string(p, &ctx->oiv, ctx->ivlen)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + return 0; + } + p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_NUM); + if (p != NULL && !OSSL_PARAM_set_uint(p, ctx->num)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + return 0; + } + p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_KEYLEN); + if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->keylen)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + return 0; + } + return 1; +} + +int cipher_generic_set_ctx_params(void *vctx, const OSSL_PARAM params[]) +{ + PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx; + const OSSL_PARAM *p; + + p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_PADDING); + if (p != NULL) { + unsigned int pad; + + if (!OSSL_PARAM_get_uint(p, &pad)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); + return 0; + } + ctx->pad = pad ? 1 : 0; + } + p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_NUM); + if (p != NULL) { + unsigned int num; + + if (!OSSL_PARAM_get_uint(p, &num)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); + return 0; + } + ctx->num = num; + } + return 1; +} + +int cipher_generic_initiv(PROV_CIPHER_CTX *ctx, const unsigned char *iv, + size_t ivlen) +{ + if (ivlen != ctx->ivlen + || ivlen > sizeof(ctx->iv)) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IVLEN); + return 0; + } + ctx->iv_set = 1; + memcpy(ctx->iv, iv, ivlen); + memcpy(ctx->oiv, iv, ivlen); + return 1; +} + +void cipher_generic_initkey(void *vctx, size_t kbits, size_t blkbits, + size_t ivbits, unsigned int mode, uint64_t flags, + const PROV_CIPHER_HW *hw, void *provctx) +{ + PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx; + + ctx->flags = flags; + ctx->pad = 1; + ctx->keylen = ((kbits) / 8); + ctx->ivlen = ((ivbits) / 8); + ctx->hw = hw; + ctx->mode = mode; + ctx->blocksize = blkbits / 8; + if (provctx != NULL) + ctx->libctx = PROV_LIBRARY_CONTEXT_OF(provctx); /* used for rand */ +} diff --git a/providers/implementations/ciphers/ciphercommon_block.c b/providers/implementations/ciphers/ciphercommon_block.c new file mode 100644 index 0000000000..eff94842ed --- /dev/null +++ b/providers/implementations/ciphers/ciphercommon_block.c @@ -0,0 +1,115 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "ciphercommon_local.h" +#include "prov/providercommonerr.h" + +/* + * Fills a single block of buffered data from the input, and returns the amount + * of data remaining in the input that is a multiple of the blocksize. The buffer + * is only filled if it already has some data in it, isn't full already or we + * don't have at least one block in the input. + * + * buf: a buffer of blocksize bytes + * buflen: contains the amount of data already in buf on entry. Updated with the + * amount of data in buf at the end. On entry *buflen must always be + * less than the blocksize + * blocksize: size of a block. Must be greater than 0 and a power of 2 + * in: pointer to a pointer containing the input data + * inlen: amount of input data available + * + * On return buf is filled with as much data as possible up to a full block, + * *buflen is updated containing the amount of data in buf. *in is updated to + * the new location where input data should be read from, *inlen is updated with + * the remaining amount of data in *in. Returns the largest value <= *inlen + * which is a multiple of the blocksize. + */ +size_t fillblock(unsigned char *buf, size_t *buflen, size_t blocksize, + const unsigned char **in, size_t *inlen) +{ + size_t blockmask = ~(blocksize - 1); + + assert(*buflen <= blocksize); + assert(blocksize > 0 && (blocksize & (blocksize - 1)) == 0); + + if (*buflen != blocksize && (*buflen != 0 || *inlen < blocksize)) { + size_t bufremain = blocksize - *buflen; + + if (*inlen < bufremain) + bufremain = *inlen; + memcpy(buf + *buflen, *in, bufremain); + *in += bufremain; + *inlen -= bufremain; + *buflen += bufremain; + } + + return *inlen & blockmask; +} + +/* + * Fills the buffer with trailing data from an encryption/decryption that didn't + * fit into a full block. + */ +int trailingdata(unsigned char *buf, size_t *buflen, size_t blocksize, + const unsigned char **in, size_t *inlen) +{ + if (*inlen == 0) + return 1; + + if (*buflen + *inlen > blocksize) { + ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); + return 0; + } + + memcpy(buf + *buflen, *in, *inlen); + *buflen += *inlen; + *inlen = 0; + + return 1; +} + +/* Pad the final block for encryption */ +void padblock(unsigned char *buf, size_t *buflen, size_t blocksize) +{ + size_t i; + unsigned char pad = (unsigned char)(blocksize - *buflen); + + for (i = *buflen; i < blocksize; i++) + buf[i] = pad; +} + +int unpadblock(unsigned char *buf, size_t *buflen, size_t blocksize) +{ + size_t pad, i; + size_t len = *buflen; + + if(len != blocksize) { + ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); + return 0; + } + + /* + * The following assumes that the ciphertext has been authenticated. + * Otherwise it provides a padding oracle. + */ + pad = buf[blocksize - 1]; + if (pad == 0 || pad > blocksize) { + ERR_raise(ERR_LIB_PROV, PROV_R_BAD_DECRYPT); + return 0; + } + for (i = 0; i < pad; i++) { + if (buf[--len] != pad) { + ERR_raise(ERR_LIB_PROV, PROV_R_BAD_DECRYPT); + return 0; + } + } + *buflen = len; + return 1; +} diff --git a/providers/implementations/ciphers/ciphercommon_ccm.c b/providers/implementations/ciphers/ciphercommon_ccm.c new file mode 100644 index 0000000000..edb8e81bf9 --- /dev/null +++ b/providers/implementations/ciphers/ciphercommon_ccm.c @@ -0,0 +1,421 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* Dispatch functions for ccm mode */ + +#include "prov/ciphercommon.h" +#include "prov/ciphercommon_ccm.h" +#include "prov/providercommonerr.h" + +static int ccm_cipher_internal(PROV_CCM_CTX *ctx, unsigned char *out, + size_t *padlen, const unsigned char *in, + size_t len); + +static int ccm_tls_init(PROV_CCM_CTX *ctx, unsigned char *aad, size_t alen) +{ + size_t len; + + if (alen != EVP_AEAD_TLS1_AAD_LEN) + return 0; + + /* Save the aad for later use. */ + memcpy(ctx->buf, aad, alen); + ctx->tls_aad_len = alen; + + len = ctx->buf[alen - 2] << 8 | ctx->buf[alen - 1]; + if (len < EVP_CCM_TLS_EXPLICIT_IV_LEN) + return 0; + + /* Correct length for explicit iv. */ + len -= EVP_CCM_TLS_EXPLICIT_IV_LEN; + + if (!ctx->enc) { + if (len < ctx->m) + return 0; + /* Correct length for tag. */ + len -= ctx->m; + } + ctx->buf[alen - 2] = (unsigned char)(len >> 8); + ctx->buf[alen - 1] = (unsigned char)(len & 0xff); + + /* Extra padding: tag appended to record. */ + return ctx->m; +} + +static int ccm_tls_iv_set_fixed(PROV_CCM_CTX *ctx, unsigned char *fixed, + size_t flen) +{ + if (flen != EVP_CCM_TLS_FIXED_IV_LEN) + return 0; + + /* Copy to first part of the iv. */ + memcpy(ctx->iv, fixed, flen); + return 1; +} + +static size_t ccm_get_ivlen(PROV_CCM_CTX *ctx) +{ + return 15 - ctx->l; +} + +int ccm_set_ctx_params(void *vctx, const OSSL_PARAM params[]) +{ + PROV_CCM_CTX *ctx = (PROV_CCM_CTX *)vctx; + const OSSL_PARAM *p; + size_t sz; + + p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TAG); + if (p != NULL) { + if (p->data_type != OSSL_PARAM_OCTET_STRING) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); + return 0; + } + if ((p->data_size & 1) || (p->data_size < 4) || p->data_size > 16) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_TAGLEN); + return 0; + } + + if (p->data != NULL) { + if (ctx->enc) { + ERR_raise(ERR_LIB_PROV, PROV_R_TAG_NOT_NEEDED); + return 0; + } + memcpy(ctx->buf, p->data, p->data_size); + ctx->tag_set = 1; + } + ctx->m = p->data_size; + } + + p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_IVLEN); + if (p != NULL) { + size_t ivlen; + + if (!OSSL_PARAM_get_size_t(p, &sz)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); + return 0; + } + ivlen = 15 - sz; + if (ivlen < 2 || ivlen > 8) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IVLEN); + return 0; + } + ctx->l = ivlen; + } + + p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TLS1_AAD); + if (p != NULL) { + if (p->data_type != OSSL_PARAM_OCTET_STRING) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); + return 0; + } + sz = ccm_tls_init(ctx, p->data, p->data_size); + if (sz == 0) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DATA); + return 0; + } + ctx->tls_aad_pad_sz = sz; + } + + p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TLS1_IV_FIXED); + if (p != NULL) { + if (p->data_type != OSSL_PARAM_OCTET_STRING) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); + return 0; + } + if (ccm_tls_iv_set_fixed(ctx, p->data, p->data_size) == 0) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IVLEN); + return 0; + } + } + + return 1; +} + +int ccm_get_ctx_params(void *vctx, OSSL_PARAM params[]) +{ + PROV_CCM_CTX *ctx = (PROV_CCM_CTX *)vctx; + OSSL_PARAM *p; + + p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IVLEN); + if (p != NULL && !OSSL_PARAM_set_size_t(p, ccm_get_ivlen(ctx))) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + return 0; + } + + p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TAGLEN); + if (p != NULL) { + size_t m = ctx->m; + + if (!OSSL_PARAM_set_size_t(p, m)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + return 0; + } + } + + p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IV); + if (p != NULL) { + if (ccm_get_ivlen(ctx) != p->data_size) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IVLEN); + return 0; + } + if (!OSSL_PARAM_set_octet_string(p, ctx->iv, p->data_size)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + return 0; + } + } + + p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_KEYLEN); + if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->keylen)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + return 0; + } + + p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TLS1_AAD_PAD); + if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->tls_aad_pad_sz)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + return 0; + } + + p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TAG); + if (p != NULL) { + if (!ctx->enc || !ctx->tag_set) { + ERR_raise(ERR_LIB_PROV, PROV_R_TAG_NOTSET); + return 0; + } + if (p->data_type != OSSL_PARAM_OCTET_STRING) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + return 0; + } + if (!ctx->hw->gettag(ctx, p->data, p->data_size)) + return 0; + ctx->tag_set = 0; + ctx->iv_set = 0; + ctx->len_set = 0; + } + return 1; +} + +static int ccm_init(void *vctx, const unsigned char *key, size_t keylen, + const unsigned char *iv, size_t ivlen, int enc) +{ + PROV_CCM_CTX *ctx = (PROV_CCM_CTX *)vctx; + + ctx->enc = enc; + + if (iv != NULL) { + if (ivlen != ccm_get_ivlen(ctx)) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IVLEN); + return 0; + } + memcpy(ctx->iv, iv, ivlen); + ctx->iv_set = 1; + } + if (key != NULL) { + if (keylen != ctx->keylen) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEYLEN); + return 0; + } + return ctx->hw->setkey(ctx, key, keylen); + } + return 1; +} + +int ccm_einit(void *vctx, const unsigned char *key, size_t keylen, + const unsigned char *iv, size_t ivlen) +{ + return ccm_init(vctx, key, keylen, iv, ivlen, 1); +} + +int ccm_dinit(void *vctx, const unsigned char *key, size_t keylen, + const unsigned char *iv, size_t ivlen) +{ + return ccm_init(vctx, key, keylen, iv, ivlen, 0); +} + +int ccm_stream_update(void *vctx, unsigned char *out, size_t *outl, + size_t outsize, const unsigned char *in, + size_t inl) +{ + PROV_CCM_CTX *ctx = (PROV_CCM_CTX *)vctx; + + if (outsize < inl) { + ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); + return 0; + } + + if (!ccm_cipher_internal(ctx, out, outl, in, inl)) { + ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED); + return 0; + } + return 1; +} + +int ccm_stream_final(void *vctx, unsigned char *out, size_t *outl, + size_t outsize) +{ + PROV_CCM_CTX *ctx = (PROV_CCM_CTX *)vctx; + int i; + + i = ccm_cipher_internal(ctx, out, outl, NULL, 0); + if (i <= 0) + return 0; + + *outl = 0; + return 1; +} + +int ccm_cipher(void *vctx, + unsigned char *out, size_t *outl, size_t outsize, + const unsigned char *in, size_t inl) +{ + PROV_CCM_CTX *ctx = (PROV_CCM_CTX *)vctx; + + if (outsize < inl) { + ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); + return 0; + } + + if (ccm_cipher_internal(ctx, out, outl, in, inl) <= 0) + return 0; + + *outl = inl; + return 1; +} + +/* Copy the buffered iv */ +static int ccm_set_iv(PROV_CCM_CTX *ctx, size_t mlen) +{ + const PROV_CCM_HW *hw = ctx->hw; + + if (!hw->setiv(ctx, ctx->iv, ccm_get_ivlen(ctx), mlen)) + return 0; + ctx->len_set = 1; + return 1; +} + +static int ccm_tls_cipher(PROV_CCM_CTX *ctx, + unsigned char *out, size_t *padlen, + const unsigned char *in, size_t len) +{ + int rv = 0; + size_t olen = 0; + + /* Encrypt/decrypt must be performed in place */ + if (out != in || len < (EVP_CCM_TLS_EXPLICIT_IV_LEN + (size_t)ctx->m)) + goto err; + + /* If encrypting set explicit IV from sequence number (start of AAD) */ + if (ctx->enc) + memcpy(out, ctx->buf, EVP_CCM_TLS_EXPLICIT_IV_LEN); + /* Get rest of IV from explicit IV */ + memcpy(ctx->iv + EVP_CCM_TLS_FIXED_IV_LEN, in, EVP_CCM_TLS_EXPLICIT_IV_LEN); + /* Correct length value */ + len -= EVP_CCM_TLS_EXPLICIT_IV_LEN + ctx->m; + if (!ccm_set_iv(ctx, len)) + goto err; + + /* Use saved AAD */ + if (!ctx->hw->setaad(ctx, ctx->buf, ctx->tls_aad_len)) + goto err; + + /* Fix buffer to point to payload */ + in += EVP_CCM_TLS_EXPLICIT_IV_LEN; + out += EVP_CCM_TLS_EXPLICIT_IV_LEN; + if (ctx->enc) { + if (!ctx->hw->auth_encrypt(ctx, in, out, len, out + len, ctx->m)) + goto err; + olen = len + EVP_CCM_TLS_EXPLICIT_IV_LEN + ctx->m; + } else { + if (!ctx->hw->auth_decrypt(ctx, in, out, len, + (unsigned char *)in + len, ctx->m)) + goto err; + olen = len; + } + rv = 1; +err: + *padlen = olen; + return rv; +} + +static int ccm_cipher_internal(PROV_CCM_CTX *ctx, unsigned char *out, + size_t *padlen, const unsigned char *in, + size_t len) +{ + int rv = 0; + size_t olen = 0; + const PROV_CCM_HW *hw = ctx->hw; + + /* If no key set, return error */ + if (!ctx->key_set) + return 0; + + if (ctx->tls_aad_len != UNINITIALISED_SIZET) + return ccm_tls_cipher(ctx, out, padlen, in, len); + + /* EVP_*Final() doesn't return any data */ + if (in == NULL && out != NULL) + goto finish; + + if (!ctx->iv_set) + goto err; + + if (out == NULL) { + if (in == NULL) { + if (!ccm_set_iv(ctx, len)) + goto err; + } else { + /* If we have AAD, we need a message length */ + if (!ctx->len_set && len) + goto err; + if (!hw->setaad(ctx, in, len)) + goto err; + } + } else { + /* If not set length yet do it */ + if (!ctx->len_set && !ccm_set_iv(ctx, len)) + goto err; + + if (ctx->enc) { + if (!hw->auth_encrypt(ctx, in, out, len, NULL, 0)) + goto err; + ctx->tag_set = 1; + } else { + /* The tag must be set before actually decrypting data */ + if (!ctx->tag_set) + goto err; + + if (!hw->auth_decrypt(ctx, in, out, len, ctx->buf, ctx->m)) + goto err; + /* Finished - reset flags so calling this method again will fail */ + ctx->iv_set = 0; + ctx->tag_set = 0; + ctx->len_set = 0; + } + } + olen = len; +finish: + rv = 1; +err: + *padlen = olen; + return rv; +} + +void ccm_initctx(PROV_CCM_CTX *ctx, size_t keybits, const PROV_CCM_HW *hw) +{ + ctx->keylen = keybits / 8; + ctx->key_set = 0; + ctx->iv_set = 0; + ctx->tag_set = 0; + ctx->len_set = 0; + ctx->l = 8; + ctx->m = 12; + ctx->tls_aad_len = UNINITIALISED_SIZET; + ctx->hw = hw; +} + diff --git a/providers/implementations/ciphers/ciphercommon_ccm_hw.c b/providers/implementations/ciphers/ciphercommon_ccm_hw.c new file mode 100644 index 0000000000..96cc744f87 --- /dev/null +++ b/providers/implementations/ciphers/ciphercommon_ccm_hw.c @@ -0,0 +1,69 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "prov/ciphercommon.h" +#include "prov/ciphercommon_ccm.h" + +int ccm_generic_setiv(PROV_CCM_CTX *ctx, const unsigned char *nonce, + size_t nlen, size_t mlen) +{ + return CRYPTO_ccm128_setiv(&ctx->ccm_ctx, nonce, nlen, mlen) == 0; +} + +int ccm_generic_setaad(PROV_CCM_CTX *ctx, const unsigned char *aad, size_t alen) +{ + CRYPTO_ccm128_aad(&ctx->ccm_ctx, aad, alen); + return 1; +} + +int ccm_generic_gettag(PROV_CCM_CTX *ctx, unsigned char *tag, size_t tlen) +{ + return CRYPTO_ccm128_tag(&ctx->ccm_ctx, tag, tlen) > 0; +} + +int ccm_generic_auth_encrypt(PROV_CCM_CTX *ctx, const unsigned char *in, + unsigned char *out, size_t len, + unsigned char *tag, size_t taglen) +{ + int rv; + + if (ctx->str != NULL) + rv = CRYPTO_ccm128_encrypt_ccm64(&ctx->ccm_ctx, in, + out, len, ctx->str) == 0; + else + rv = CRYPTO_ccm128_encrypt(&ctx->ccm_ctx, in, out, len) == 0; + + if (rv == 1 && tag != NULL) + rv = (CRYPTO_ccm128_tag(&ctx->ccm_ctx, tag, taglen) > 0); + return rv; +} + +int ccm_generic_auth_decrypt(PROV_CCM_CTX *ctx, const unsigned char *in, + unsigned char *out, size_t len, + unsigned char *expected_tag, size_t taglen) +{ + int rv = 0; + + if (ctx->str != NULL) + rv = CRYPTO_ccm128_decrypt_ccm64(&ctx->ccm_ctx, in, out, len, + ctx->str) == 0; + else + rv = CRYPTO_ccm128_decrypt(&ctx->ccm_ctx, in, out, len) == 0; + if (rv) { + unsigned char tag[16]; + + if (!CRYPTO_ccm128_tag(&ctx->ccm_ctx, tag, taglen) + || CRYPTO_memcmp(tag, expected_tag, taglen) != 0) + rv = 0; + } + if (rv == 0) + OPENSSL_cleanse(out, len); + return rv; +} + diff --git a/providers/implementations/ciphers/ciphercommon_gcm.c b/providers/implementations/ciphers/ciphercommon_gcm.c new file mode 100644 index 0000000000..803f810a30 --- /dev/null +++ b/providers/implementations/ciphers/ciphercommon_gcm.c @@ -0,0 +1,495 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* Dispatch functions for gcm mode */ + +#include "prov/ciphercommon.h" +#include "prov/ciphercommon_gcm.h" +#include "prov/providercommonerr.h" +#include "crypto/rand.h" +#include "prov/provider_ctx.h" + +static int gcm_tls_init(PROV_GCM_CTX *dat, unsigned char *aad, size_t aad_len); +static int gcm_tls_iv_set_fixed(PROV_GCM_CTX *ctx, unsigned char *iv, + size_t len); +static int gcm_tls_cipher(PROV_GCM_CTX *ctx, unsigned char *out, size_t *padlen, + const unsigned char *in, size_t len); +static int gcm_cipher_internal(PROV_GCM_CTX *ctx, unsigned char *out, + size_t *padlen, const unsigned char *in, + size_t len); + +void gcm_initctx(void *provctx, PROV_GCM_CTX *ctx, size_t keybits, + const PROV_GCM_HW *hw, size_t ivlen_min) +{ + ctx->pad = 1; + ctx->mode = EVP_CIPH_GCM_MODE; + ctx->taglen = UNINITIALISED_SIZET; + ctx->tls_aad_len = UNINITIALISED_SIZET; + ctx->ivlen_min = ivlen_min; + ctx->ivlen = (EVP_GCM_TLS_FIXED_IV_LEN + EVP_GCM_TLS_EXPLICIT_IV_LEN); + ctx->keylen = keybits / 8; + ctx->hw = hw; + ctx->libctx = PROV_LIBRARY_CONTEXT_OF(provctx); +} + +static int gcm_init(void *vctx, const unsigned char *key, size_t keylen, + const unsigned char *iv, size_t ivlen, int enc) +{ + PROV_GCM_CTX *ctx = (PROV_GCM_CTX *)vctx; + + ctx->enc = enc; + + if (iv != NULL) { + if (ivlen < ctx->ivlen_min || ivlen > sizeof(ctx->iv)) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH); + return 0; + } + ctx->ivlen = ivlen; + memcpy(ctx->iv, iv, ivlen); + ctx->iv_state = IV_STATE_BUFFERED; + } + + if (key != NULL) { + if (keylen != ctx->keylen) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH); + return 0; + } + return ctx->hw->setkey(ctx, key, ctx->keylen); + } + return 1; +} + +int gcm_einit(void *vctx, const unsigned char *key, size_t keylen, + const unsigned char *iv, size_t ivlen) +{ + return gcm_init(vctx, key, keylen, iv, ivlen, 1); +} + +int gcm_dinit(void *vctx, const unsigned char *key, size_t keylen, + const unsigned char *iv, size_t ivlen) +{ + return gcm_init(vctx, key, keylen, iv, ivlen, 0); +} + +int gcm_get_ctx_params(void *vctx, OSSL_PARAM params[]) +{ + PROV_GCM_CTX *ctx = (PROV_GCM_CTX *)vctx; + OSSL_PARAM *p; + size_t sz; + + p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IVLEN); + if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->ivlen)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + return 0; + } + p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_KEYLEN); + if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->keylen)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + return 0; + } + p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TAGLEN); + if (p != NULL) { + size_t taglen = (ctx->taglen != UNINITIALISED_SIZET) ? ctx->taglen : + GCM_TAG_MAX_SIZE; + + if (!OSSL_PARAM_set_size_t(p, taglen)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + return 0; + } + } + + p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IV); + if (p != NULL) { + if (ctx->iv_gen != 1 && ctx->iv_gen_rand != 1) + return 0; + if (ctx->ivlen != p->data_size) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH); + return 0; + } + if (!OSSL_PARAM_set_octet_string(p, ctx->iv, ctx->ivlen)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + return 0; + } + } + + p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TLS1_AAD_PAD); + if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->tls_aad_pad_sz)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + return 0; + } + p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TAG); + if (p != NULL) { + sz = p->data_size; + if (sz == 0 + || sz > EVP_GCM_TLS_TAG_LEN + || !ctx->enc + || ctx->taglen == UNINITIALISED_SIZET) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_TAG); + return 0; + } + if (!OSSL_PARAM_set_octet_string(p, ctx->buf, sz)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + return 0; + } + } + + return 1; +} + +int gcm_set_ctx_params(void *vctx, const OSSL_PARAM params[]) +{ + PROV_GCM_CTX *ctx = (PROV_GCM_CTX *)vctx; + const OSSL_PARAM *p; + size_t sz; + void *vp; + + p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TAG); + if (p != NULL) { + vp = ctx->buf; + if (!OSSL_PARAM_get_octet_string(p, &vp, EVP_GCM_TLS_TAG_LEN, &sz)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); + return 0; + } + if (sz == 0 || ctx->enc) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_TAG); + return 0; + } + ctx->taglen = sz; + } + + p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_IVLEN); + if (p != NULL) { + if (!OSSL_PARAM_get_size_t(p, &sz)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); + return 0; + } + if (sz == 0 || sz > sizeof(ctx->iv)) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH); + return 0; + } + ctx->ivlen = sz; + } + + p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TLS1_AAD); + if (p != NULL) { + if (p->data_type != OSSL_PARAM_OCTET_STRING) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); + return 0; + } + sz = gcm_tls_init(ctx, p->data, p->data_size); + if (sz == 0) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_AAD); + return 0; + } + ctx->tls_aad_pad_sz = sz; + } + + p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TLS1_IV_FIXED); + if (p != NULL) { + if (p->data_type != OSSL_PARAM_OCTET_STRING) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); + return 0; + } + if (gcm_tls_iv_set_fixed(ctx, p->data, p->data_size) == 0) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); + return 0; + } + } + + return 1; +} + +int gcm_stream_update(void *vctx, unsigned char *out, size_t *outl, + size_t outsize, const unsigned char *in, size_t inl) +{ + PROV_GCM_CTX *ctx = (PROV_GCM_CTX *)vctx; + + if (inl == 0) { + *outl = 0; + return 1; + } + + if (outsize < inl) { + ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); + return -1; + } + + if (gcm_cipher_internal(ctx, out, outl, in, inl) <= 0) { + ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED); + return -1; + } + return 1; +} + +int gcm_stream_final(void *vctx, unsigned char *out, size_t *outl, + size_t outsize) +{ + PROV_GCM_CTX *ctx = (PROV_GCM_CTX *)vctx; + int i; + + i = gcm_cipher_internal(ctx, out, outl, NULL, 0); + if (i <= 0) + return 0; + + *outl = 0; + return 1; +} + +int gcm_cipher(void *vctx, + unsigned char *out, size_t *outl, size_t outsize, + const unsigned char *in, size_t inl) +{ + PROV_GCM_CTX *ctx = (PROV_GCM_CTX *)vctx; + + if (outsize < inl) { + ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); + return 0; + } + + if (gcm_cipher_internal(ctx, out, outl, in, inl) <= 0) + return 0; + + *outl = inl; + return 1; +} + +/* + * See SP800-38D (GCM) Section 8 "Uniqueness requirement on IVS and keys" + * + * See also 8.2.2 RBG-based construction. + * Random construction consists of a free field (which can be NULL) and a + * random field which will use a DRBG that can return at least 96 bits of + * entropy strength. (The DRBG must be seeded by the FIPS module). + */ +static int gcm_iv_generate(PROV_GCM_CTX *ctx, int offset) +{ + int sz = ctx->ivlen - offset; + + /* Must be at least 96 bits */ + if (sz <= 0 || ctx->ivlen < GCM_IV_DEFAULT_SIZE) + return 0; + + /* Use DRBG to generate random iv */ + if (rand_bytes_ex(ctx->libctx, ctx->iv + offset, sz) <= 0) + return 0; + ctx->iv_state = IV_STATE_BUFFERED; + ctx->iv_gen_rand = 1; + return 1; +} + +static int gcm_cipher_internal(PROV_GCM_CTX *ctx, unsigned char *out, + size_t *padlen, const unsigned char *in, + size_t len) +{ + size_t olen = 0; + int rv = 0; + const PROV_GCM_HW *hw = ctx->hw; + + if (ctx->tls_aad_len != UNINITIALISED_SIZET) + return gcm_tls_cipher(ctx, out, padlen, in, len); + + if (!ctx->key_set || ctx->iv_state == IV_STATE_FINISHED) + goto err; + + /* + * FIPS requires generation of AES-GCM IV's inside the FIPS module. + * The IV can still be set externally (the security policy will state that + * this is not FIPS compliant). There are some applications + * where setting the IV externally is the only option available. + */ + if (ctx->iv_state == IV_STATE_UNINITIALISED) { + if (!ctx->enc || !gcm_iv_generate(ctx, 0)) + goto err; + } + + if (ctx->iv_state == IV_STATE_BUFFERED) { + if (!hw->setiv(ctx, ctx->iv, ctx->ivlen)) + goto err; + ctx->iv_state = IV_STATE_COPIED; + } + + if (in != NULL) { + /* The input is AAD if out is NULL */ + if (out == NULL) { + if (!hw->aadupdate(ctx, in, len)) + goto err; + } else { + /* The input is ciphertext OR plaintext */ + if (!hw->cipherupdate(ctx, in, len, out)) + goto err; + } + } else { + /* The tag must be set before actually decrypting data */ + if (!ctx->enc && ctx->taglen == UNINITIALISED_SIZET) + goto err; + if (!hw->cipherfinal(ctx, ctx->buf)) + goto err; + ctx->iv_state = IV_STATE_FINISHED; /* Don't reuse the IV */ + goto finish; + } + olen = len; +finish: + rv = 1; +err: + *padlen = olen; + return rv; +} + +static int gcm_tls_init(PROV_GCM_CTX *dat, unsigned char *aad, size_t aad_len) +{ + unsigned char *buf; + size_t len; + + if (aad_len != EVP_AEAD_TLS1_AAD_LEN) + return 0; + + /* Save the aad for later use. */ + buf = dat->buf; + memcpy(buf, aad, aad_len); + dat->tls_aad_len = aad_len; + dat->tls_enc_records = 0; + + len = buf[aad_len - 2] << 8 | buf[aad_len - 1]; + /* Correct length for explicit iv. */ + if (len < EVP_GCM_TLS_EXPLICIT_IV_LEN) + return 0; + len -= EVP_GCM_TLS_EXPLICIT_IV_LEN; + + /* If decrypting correct for tag too. */ + if (!dat->enc) { + if (len < EVP_GCM_TLS_TAG_LEN) + return 0; + len -= EVP_GCM_TLS_TAG_LEN; + } + buf[aad_len - 2] = (unsigned char)(len >> 8); + buf[aad_len - 1] = (unsigned char)(len & 0xff); + /* Extra padding: tag appended to record. */ + return EVP_GCM_TLS_TAG_LEN; +} + +static int gcm_tls_iv_set_fixed(PROV_GCM_CTX *ctx, unsigned char *iv, + size_t len) +{ + /* Special case: -1 length restores whole IV */ + if (len == (size_t)-1) { + memcpy(ctx->iv, iv, ctx->ivlen); + ctx->iv_gen = 1; + ctx->iv_state = IV_STATE_BUFFERED; + return 1; + } + /* Fixed field must be at least 4 bytes and invocation field at least 8 */ + if ((len < EVP_GCM_TLS_FIXED_IV_LEN) + || (ctx->ivlen - (int)len) < EVP_GCM_TLS_EXPLICIT_IV_LEN) + return 0; + if (len > 0) + memcpy(ctx->iv, iv, len); + if (ctx->enc + && rand_bytes_ex(ctx->libctx, ctx->iv + len, ctx->ivlen - len) <= 0) + return 0; + ctx->iv_gen = 1; + ctx->iv_state = IV_STATE_BUFFERED; + return 1; +} + +/* increment counter (64-bit int) by 1 */ +static void ctr64_inc(unsigned char *counter) +{ + int n = 8; + unsigned char c; + + do { + --n; + c = counter[n]; + ++c; + counter[n] = c; + if (c > 0) + return; + } while (n > 0); +} + +/* + * Handle TLS GCM packet format. This consists of the last portion of the IV + * followed by the payload and finally the tag. On encrypt generate IV, + * encrypt payload and write the tag. On verify retrieve IV, decrypt payload + * and verify tag. + */ +static int gcm_tls_cipher(PROV_GCM_CTX *ctx, unsigned char *out, size_t *padlen, + const unsigned char *in, size_t len) +{ + int rv = 0; + size_t arg = EVP_GCM_TLS_EXPLICIT_IV_LEN; + size_t plen = 0; + unsigned char *tag = NULL; + + if (!ctx->key_set) + goto err; + + /* Encrypt/decrypt must be performed in place */ + if (out != in || len < (EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN)) + goto err; + + /* + * Check for too many keys as per FIPS 140-2 IG A.5 "Key/IV Pair Uniqueness + * Requirements from SP 800-38D". The requirements is for one party to the + * communication to fail after 2^64 - 1 keys. We do this on the encrypting + * side only. + */ + if (ctx->enc && ++ctx->tls_enc_records == 0) { + ERR_raise(ERR_LIB_PROV, EVP_R_TOO_MANY_RECORDS); + goto err; + } + + if (ctx->iv_gen == 0) + goto err; + /* + * Set IV from start of buffer or generate IV and write to start of + * buffer. + */ + if (ctx->enc) { + if (!ctx->hw->setiv(ctx, ctx->iv, ctx->ivlen)) + goto err; + if (arg > ctx->ivlen) + arg = ctx->ivlen; + memcpy(out, ctx->iv + ctx->ivlen - arg, arg); + /* + * Invocation field will be at least 8 bytes in size and so no need + * to check wrap around or increment more than last 8 bytes. + */ + ctr64_inc(ctx->iv + ctx->ivlen - 8); + } else { + memcpy(ctx->iv + ctx->ivlen - arg, out, arg); + if (!ctx->hw->setiv(ctx, ctx->iv, ctx->ivlen)) + goto err; + } + ctx->iv_state = IV_STATE_COPIED; + + /* Fix buffer and length to point to payload */ + in += EVP_GCM_TLS_EXPLICIT_IV_LEN; + out += EVP_GCM_TLS_EXPLICIT_IV_LEN; + len -= EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN; + + tag = ctx->enc ? out + len : (unsigned char *)in + len; + if (!ctx->hw->oneshot(ctx, ctx->buf, ctx->tls_aad_len, in, len, out, tag, + EVP_GCM_TLS_TAG_LEN)) { + if (!ctx->enc) + OPENSSL_cleanse(out, len); + goto err; + } + if (ctx->enc) + plen = len + EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN; + else + plen = len; + + rv = 1; +err: + ctx->iv_state = IV_STATE_FINISHED; + ctx->tls_aad_len = UNINITIALISED_SIZET; + *padlen = plen; + return rv; +} diff --git a/providers/implementations/ciphers/ciphercommon_gcm_hw.c b/providers/implementations/ciphers/ciphercommon_gcm_hw.c new file mode 100644 index 0000000000..60c7ac5d8f --- /dev/null +++ b/providers/implementations/ciphers/ciphercommon_gcm_hw.c @@ -0,0 +1,117 @@ +/* + * Copyright 2001-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 "prov/ciphercommon.h" +#include "prov/ciphercommon_gcm.h" + + +int gcm_setiv(PROV_GCM_CTX *ctx, const unsigned char *iv, size_t ivlen) +{ + CRYPTO_gcm128_setiv(&ctx->gcm, iv, ivlen); + return 1; +} + +int gcm_aad_update(PROV_GCM_CTX *ctx, const unsigned char *aad, size_t aad_len) +{ + return CRYPTO_gcm128_aad(&ctx->gcm, aad, aad_len) == 0; +} + +int gcm_cipher_update(PROV_GCM_CTX *ctx, const unsigned char *in, + size_t len, unsigned char *out) +{ + if (ctx->enc) { + if (ctx->ctr != NULL) { +#if defined(AES_GCM_ASM) + size_t bulk = 0; + + if (len >= 32 && AES_GCM_ASM(ctx)) { + size_t res = (16 - ctx->gcm.mres) % 16; + + if (CRYPTO_gcm128_encrypt(&ctx->gcm, in, out, res)) + return 0; + bulk = aesni_gcm_encrypt(in + res, out + res, len - res, + ctx->gcm.key, + ctx->gcm.Yi.c, ctx->gcm.Xi.u); + ctx->gcm.len.u[1] += bulk; + bulk += res; + } + if (CRYPTO_gcm128_encrypt_ctr32(&ctx->gcm, in + bulk, out + bulk, + len - bulk, ctx->ctr)) + return 0; +#else + if (CRYPTO_gcm128_encrypt_ctr32(&ctx->gcm, in, out, len, ctx->ctr)) + return 0; +#endif /* AES_GCM_ASM */ + } else { + if (CRYPTO_gcm128_encrypt(&ctx->gcm, in, out, len)) + return 0; + } + } else { + if (ctx->ctr != NULL) { +#if defined(AES_GCM_ASM) + size_t bulk = 0; + + if (len >= 16 && AES_GCM_ASM(ctx)) { + size_t res = (16 - ctx->gcm.mres) % 16; + + if (CRYPTO_gcm128_decrypt(&ctx->gcm, in, out, res)) + return -1; + + bulk = aesni_gcm_decrypt(in + res, out + res, len - res, + ctx->gcm.key, + ctx->gcm.Yi.c, ctx->gcm.Xi.u); + ctx->gcm.len.u[1] += bulk; + bulk += res; + } + if (CRYPTO_gcm128_decrypt_ctr32(&ctx->gcm, in + bulk, out + bulk, + len - bulk, ctx->ctr)) + return 0; +#else + if (CRYPTO_gcm128_decrypt_ctr32(&ctx->gcm, in, out, len, ctx->ctr)) + return 0; +#endif /* AES_GCM_ASM */ + } else { + if (CRYPTO_gcm128_decrypt(&ctx->gcm, in, out, len)) + return 0; + } + } + return 1; +} + +int gcm_cipher_final(PROV_GCM_CTX *ctx, unsigned char *tag) +{ + if (ctx->enc) { + CRYPTO_gcm128_tag(&ctx->gcm, tag, GCM_TAG_MAX_SIZE); + ctx->taglen = GCM_TAG_MAX_SIZE; + } else { + if (CRYPTO_gcm128_finish(&ctx->gcm, tag, ctx->taglen) != 0) + return 0; + } + return 1; +} + +int gcm_one_shot(PROV_GCM_CTX *ctx, unsigned char *aad, size_t aad_len, + const unsigned char *in, size_t in_len, + unsigned char *out, unsigned char *tag, size_t tag_len) +{ + int ret = 0; + + /* Use saved AAD */ + if (!ctx->hw->aadupdate(ctx, aad, aad_len)) + goto err; + if (!ctx->hw->cipherupdate(ctx, in, in_len, out)) + goto err; + ctx->taglen = GCM_TAG_MAX_SIZE; + if (!ctx->hw->cipherfinal(ctx, tag)) + goto err; + ret = 1; + +err: + return ret; +} diff --git a/providers/implementations/ciphers/ciphercommon_hw.c b/providers/implementations/ciphers/ciphercommon_hw.c new file mode 100644 index 0000000000..f1c466edc8 --- /dev/null +++ b/providers/implementations/ciphers/ciphercommon_hw.c @@ -0,0 +1,189 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "prov/ciphercommon.h" + +/*- + * The generic cipher functions for cipher modes cbc, ecb, ofb, cfb and ctr. + * Used if there is no special hardware implementations. + */ +int cipher_hw_generic_cbc(PROV_CIPHER_CTX *dat, unsigned char *out, + const unsigned char *in, size_t len) +{ + if (dat->stream.cbc) + (*dat->stream.cbc) (in, out, len, dat->ks, dat->iv, dat->enc); + else if (dat->enc) + CRYPTO_cbc128_encrypt(in, out, len, dat->ks, dat->iv, dat->block); + else + CRYPTO_cbc128_decrypt(in, out, len, dat->ks, dat->iv, dat->block); + + return 1; +} + +int cipher_hw_generic_ecb(PROV_CIPHER_CTX *dat, unsigned char *out, + const unsigned char *in, size_t len) +{ + size_t i, bl = dat->blocksize; + + if (len < bl) + return 1; + + for (i = 0, len -= bl; i <= len; i += bl) + (*dat->block) (in + i, out + i, dat->ks); + + return 1; +} + +int cipher_hw_generic_ofb128(PROV_CIPHER_CTX *dat, unsigned char *out, + const unsigned char *in, size_t len) +{ + int num = dat->num; + + CRYPTO_ofb128_encrypt(in, out, len, dat->ks, dat->iv, &num, dat->block); + dat->num = num; + + return 1; +} + +int cipher_hw_generic_cfb128(PROV_CIPHER_CTX *dat, unsigned char *out, + const unsigned char *in, size_t len) +{ + int num = dat->num; + + CRYPTO_cfb128_encrypt(in, out, len, dat->ks, dat->iv, &num, dat->enc, + dat->block); + dat->num = num; + + return 1; +} + +int cipher_hw_generic_cfb8(PROV_CIPHER_CTX *dat, unsigned char *out, + const unsigned char *in, size_t len) +{ + int num = dat->num; + + CRYPTO_cfb128_8_encrypt(in, out, len, dat->ks, dat->iv, &num, dat->enc, + dat->block); + dat->num = num; + + return 1; +} + +int cipher_hw_generic_cfb1(PROV_CIPHER_CTX *dat, unsigned char *out, + const unsigned char *in, size_t len) +{ + int num = dat->num; + + if ((dat->flags & EVP_CIPH_FLAG_LENGTH_BITS) != 0) { + CRYPTO_cfb128_1_encrypt(in, out, len, dat->ks, dat->iv, &num, + dat->enc, dat->block); + dat->num = num; + return 1; + } + + while (len >= MAXBITCHUNK) { + CRYPTO_cfb128_1_encrypt(in, out, MAXBITCHUNK * 8, dat->ks, + dat->iv, &num, dat->enc, dat->block); + len -= MAXBITCHUNK; + out += MAXBITCHUNK; + in += MAXBITCHUNK; + } + if (len) + CRYPTO_cfb128_1_encrypt(in, out, len * 8, dat->ks, dat->iv, &num, + dat->enc, dat->block); + + dat->num = num; + + return 1; +} + +int cipher_hw_generic_ctr(PROV_CIPHER_CTX *dat, unsigned char *out, + const unsigned char *in, size_t len) +{ + unsigned int num = dat->num; + + if (dat->stream.ctr) + CRYPTO_ctr128_encrypt_ctr32(in, out, len, dat->ks, dat->iv, dat->buf, + &num, dat->stream.ctr); + else + CRYPTO_ctr128_encrypt(in, out, len, dat->ks, dat->iv, dat->buf, + &num, dat->block); + dat->num = num; + + return 1; +} + +/*- + * The chunked cipher functions for cipher modes cbc, ecb, ofb, cfb and ctr. + * Used if there is no special hardware implementations. + */ + +int cipher_hw_chunked_cbc(PROV_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl) +{ + while (inl >= MAXCHUNK) { + cipher_hw_generic_cbc(ctx, out, in, MAXCHUNK); + inl -= MAXCHUNK; + in += MAXCHUNK; + out += MAXCHUNK; + } + if (inl > 0) + cipher_hw_generic_cbc(ctx, out, in, inl); + return 1; +} + +int cipher_hw_chunked_cfb8(PROV_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl) +{ + size_t chunk = MAXCHUNK; + + if (inl < chunk) + chunk = inl; + while (inl > 0 && inl >= chunk) { + cipher_hw_generic_cfb8(ctx, out, in, inl); + inl -= chunk; + in += chunk; + out += chunk; + if (inl < chunk) + chunk = inl; + } + return 1; +} + +int cipher_hw_chunked_cfb128(PROV_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl) +{ + size_t chunk = MAXCHUNK; + + if (inl < chunk) + chunk = inl; + while (inl > 0 && inl >= chunk) { + cipher_hw_generic_cfb128(ctx, out, in, inl); + inl -= chunk; + in += chunk; + out += chunk; + if (inl < chunk) + chunk = inl; + } + return 1; +} + +int cipher_hw_chunked_ofb128(PROV_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl) +{ + while (inl >= MAXCHUNK) { + cipher_hw_generic_ofb128(ctx, out, in, MAXCHUNK); + inl -= MAXCHUNK; + in += MAXCHUNK; + out += MAXCHUNK; + } + if (inl > 0) + cipher_hw_generic_ofb128(ctx, out, in, inl); + return 1; +} diff --git a/providers/implementations/ciphers/ciphercommon_local.h b/providers/implementations/ciphers/ciphercommon_local.h new file mode 100644 index 0000000000..1c4716f357 --- /dev/null +++ b/providers/implementations/ciphers/ciphercommon_local.h @@ -0,0 +1,13 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "prov/ciphercommon.h" + +void padblock(unsigned char *buf, size_t *buflen, size_t blocksize); +int unpadblock(unsigned char *buf, size_t *buflen, size_t blocksize); diff --git a/providers/implementations/digests/build.info b/providers/implementations/digests/build.info index 2026de95d7..a90636cbb9 100644 --- a/providers/implementations/digests/build.info +++ b/providers/implementations/digests/build.info @@ -1,6 +1,8 @@ # We make separate GOAL variables for each algorithm, to make it easy to # switch each to the Legacy provider when needed. +$COMMON_GOAL=../../libcommon.a + $SHA1_GOAL=../../libimplementations.a $SHA2_GOAL=../../libimplementations.a $SHA3_GOAL=../../libimplementations.a @@ -14,11 +16,12 @@ $MDC2_GOAL=../../liblegacy.a $WHIRLPOOL_GOAL=../../liblegacy.a $RIPEMD_GOAL=../../liblegacy.a +# This source is common for all digests in all our providers. +SOURCE[$COMMON_GOAL]=digestcommon.c + SOURCE[$SHA2_GOAL]=sha2_prov.c SOURCE[$SHA3_GOAL]=sha3_prov.c -$GOAL=../../libimplementations.a - IF[{- !$disabled{blake2} -}] SOURCE[$BLAKE2_GOAL]=blake2_prov.c blake2b_prov.c blake2s_prov.c ENDIF diff --git a/providers/implementations/digests/digestcommon.c b/providers/implementations/digests/digestcommon.c new file mode 100644 index 0000000000..9d30b2be2c --- /dev/null +++ b/providers/implementations/digests/digestcommon.c @@ -0,0 +1,46 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "openssl/err.h" +#include "prov/digestcommon.h" +#include "prov/providercommonerr.h" + +int digest_default_get_params(OSSL_PARAM params[], size_t blksz, size_t paramsz, + unsigned long flags) +{ + OSSL_PARAM *p = NULL; + + p = OSSL_PARAM_locate(params, OSSL_DIGEST_PARAM_BLOCK_SIZE); + if (p != NULL && !OSSL_PARAM_set_size_t(p, blksz)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + return 0; + } + p = OSSL_PARAM_locate(params, OSSL_DIGEST_PARAM_SIZE); + if (p != NULL && !OSSL_PARAM_set_size_t(p, paramsz)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + return 0; + } + p = OSSL_PARAM_locate(params, OSSL_DIGEST_PARAM_FLAGS); + if (p != NULL && !OSSL_PARAM_set_ulong(p, flags)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + return 0; + } + return 1; +} + +static const OSSL_PARAM digest_default_known_gettable_params[] = { + OSSL_PARAM_size_t(OSSL_DIGEST_PARAM_BLOCK_SIZE, NULL), + OSSL_PARAM_size_t(OSSL_DIGEST_PARAM_SIZE, NULL), + OSSL_PARAM_ulong(OSSL_DIGEST_PARAM_FLAGS, NULL), + OSSL_PARAM_END +}; +const OSSL_PARAM *digest_default_gettable_params(void) +{ + return digest_default_known_gettable_params; +} diff --git a/providers/implementations/include/prov/ciphercommon.h b/providers/implementations/include/prov/ciphercommon.h new file mode 100644 index 0000000000..1072b577fe --- /dev/null +++ b/providers/implementations/include/prov/ciphercommon.h @@ -0,0 +1,324 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include +#include +#include +#include "internal/cryptlib.h" +#include "crypto/modes.h" +#include "crypto/ciphermode_platform.h" + +#define MAXCHUNK ((size_t)1 << (sizeof(long) * 8 - 2)) +#define MAXBITCHUNK ((size_t)1 << (sizeof(size_t) * 8 - 4)) + +#define GENERIC_BLOCK_SIZE 16 +#define IV_STATE_UNINITIALISED 0 /* initial state is not initialized */ +#define IV_STATE_BUFFERED 1 /* iv has been copied to the iv buffer */ +#define IV_STATE_COPIED 2 /* iv has been copied from the iv buffer */ +#define IV_STATE_FINISHED 3 /* the iv has been used - so don't reuse it */ + +#define PROV_CIPHER_FUNC(type, name, args) typedef type (* OSSL_##name##_fn)args + +typedef struct prov_cipher_hw_st PROV_CIPHER_HW; +typedef struct prov_cipher_ctx_st PROV_CIPHER_CTX; + +typedef int (PROV_CIPHER_HW_FN)(PROV_CIPHER_CTX *dat, unsigned char *out, + const unsigned char *in, size_t len); + +struct prov_cipher_ctx_st { + block128_f block; + union { + cbc128_f cbc; + ctr128_f ctr; + } stream; + + unsigned int mode; + size_t keylen; /* key size (in bytes) */ + size_t ivlen; + size_t blocksize; + size_t bufsz; /* Number of bytes in buf */ + unsigned int pad : 1; /* Whether padding should be used or not */ + unsigned int enc : 1; /* Set to 1 for encrypt, or 0 otherwise */ + unsigned int iv_set : 1; /* Set when the iv is copied to the iv/oiv buffers */ + + /* + * num contains the number of bytes of |iv| which are valid for modes that + * manage partial blocks themselves. + */ + unsigned int num; + uint64_t flags; + + /* The original value of the iv */ + unsigned char oiv[GENERIC_BLOCK_SIZE]; + /* Buffer of partial blocks processed via update calls */ + unsigned char buf[GENERIC_BLOCK_SIZE]; + unsigned char iv[GENERIC_BLOCK_SIZE]; + const PROV_CIPHER_HW *hw; /* hardware specific functions */ + const void *ks; /* Pointer to algorithm specific key data */ + OPENSSL_CTX *libctx; +}; + +struct prov_cipher_hw_st { + int (*init)(PROV_CIPHER_CTX *dat, const uint8_t *key, size_t keylen); + PROV_CIPHER_HW_FN *cipher; + void (*copyctx)(PROV_CIPHER_CTX *dst, const PROV_CIPHER_CTX *src); +}; + +OSSL_OP_cipher_encrypt_init_fn cipher_generic_einit; +OSSL_OP_cipher_decrypt_init_fn cipher_generic_dinit; +OSSL_OP_cipher_update_fn cipher_generic_block_update; +OSSL_OP_cipher_final_fn cipher_generic_block_final; +OSSL_OP_cipher_update_fn cipher_generic_stream_update; +OSSL_OP_cipher_final_fn cipher_generic_stream_final; +OSSL_OP_cipher_cipher_fn cipher_generic_cipher; +OSSL_OP_cipher_get_ctx_params_fn cipher_generic_get_ctx_params; +OSSL_OP_cipher_set_ctx_params_fn cipher_generic_set_ctx_params; +OSSL_OP_cipher_gettable_params_fn cipher_generic_gettable_params; +OSSL_OP_cipher_gettable_ctx_params_fn cipher_generic_gettable_ctx_params; +OSSL_OP_cipher_settable_ctx_params_fn cipher_generic_settable_ctx_params; +OSSL_OP_cipher_set_ctx_params_fn cipher_var_keylen_set_ctx_params; +OSSL_OP_cipher_settable_ctx_params_fn cipher_var_keylen_settable_ctx_params; +OSSL_OP_cipher_gettable_ctx_params_fn cipher_aead_gettable_ctx_params; +OSSL_OP_cipher_settable_ctx_params_fn cipher_aead_settable_ctx_params; +int cipher_generic_get_params(OSSL_PARAM params[], unsigned int md, + unsigned long flags, + size_t kbits, size_t blkbits, size_t ivbits); +void cipher_generic_initkey(void *vctx, size_t kbits, size_t blkbits, + size_t ivbits, unsigned int mode, uint64_t flags, + const PROV_CIPHER_HW *hw, void *provctx); + +#define IMPLEMENT_generic_cipher_func(alg, UCALG, lcmode, UCMODE, flags, kbits,\ + blkbits, ivbits, typ) \ +const OSSL_DISPATCH alg##kbits##lcmode##_functions[] = { \ + { OSSL_FUNC_CIPHER_NEWCTX, \ + (void (*)(void)) alg##_##kbits##_##lcmode##_newctx }, \ + { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void)) alg##_freectx }, \ + { OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void)) alg##_dupctx }, \ + { OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))cipher_generic_einit }, \ + { OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))cipher_generic_dinit }, \ + { OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))cipher_generic_##typ##_update },\ + { OSSL_FUNC_CIPHER_FINAL, (void (*)(void))cipher_generic_##typ##_final }, \ + { OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))cipher_generic_cipher }, \ + { OSSL_FUNC_CIPHER_GET_PARAMS, \ + (void (*)(void)) alg##_##kbits##_##lcmode##_get_params }, \ + { OSSL_FUNC_CIPHER_GET_CTX_PARAMS, \ + (void (*)(void))cipher_generic_get_ctx_params }, \ + { OSSL_FUNC_CIPHER_SET_CTX_PARAMS, \ + (void (*)(void))cipher_generic_set_ctx_params }, \ + { OSSL_FUNC_CIPHER_GETTABLE_PARAMS, \ + (void (*)(void))cipher_generic_gettable_params }, \ + { OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS, \ + (void (*)(void))cipher_generic_gettable_ctx_params }, \ + { OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS, \ + (void (*)(void))cipher_generic_settable_ctx_params }, \ + { 0, NULL } \ +}; + +#define IMPLEMENT_var_keylen_cipher_func(alg, UCALG, lcmode, UCMODE, flags, \ + kbits, blkbits, ivbits, typ) \ +const OSSL_DISPATCH alg##kbits##lcmode##_functions[] = { \ + { OSSL_FUNC_CIPHER_NEWCTX, \ + (void (*)(void)) alg##_##kbits##_##lcmode##_newctx }, \ + { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void)) alg##_freectx }, \ + { OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void)) alg##_dupctx }, \ + { OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))cipher_generic_einit }, \ + { OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))cipher_generic_dinit }, \ + { OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))cipher_generic_##typ##_update },\ + { OSSL_FUNC_CIPHER_FINAL, (void (*)(void))cipher_generic_##typ##_final }, \ + { OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))cipher_generic_cipher }, \ + { OSSL_FUNC_CIPHER_GET_PARAMS, \ + (void (*)(void)) alg##_##kbits##_##lcmode##_get_params }, \ + { OSSL_FUNC_CIPHER_GET_CTX_PARAMS, \ + (void (*)(void))cipher_generic_get_ctx_params }, \ + { OSSL_FUNC_CIPHER_SET_CTX_PARAMS, \ + (void (*)(void))cipher_var_keylen_set_ctx_params }, \ + { OSSL_FUNC_CIPHER_GETTABLE_PARAMS, \ + (void (*)(void))cipher_generic_gettable_params }, \ + { OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS, \ + (void (*)(void))cipher_generic_gettable_ctx_params }, \ + { OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS, \ + (void (*)(void))cipher_var_keylen_settable_ctx_params }, \ + { 0, NULL } \ +}; + + +#define IMPLEMENT_generic_cipher_genfn(alg, UCALG, lcmode, UCMODE, flags, \ + kbits, blkbits, ivbits, typ) \ +static OSSL_OP_cipher_get_params_fn alg##_##kbits##_##lcmode##_get_params; \ +static int alg##_##kbits##_##lcmode##_get_params(OSSL_PARAM params[]) \ +{ \ + return cipher_generic_get_params(params, EVP_CIPH_##UCMODE##_MODE, flags, \ + kbits, blkbits, ivbits); \ +} \ +static OSSL_OP_cipher_newctx_fn alg##_##kbits##_##lcmode##_newctx; \ +static void * alg##_##kbits##_##lcmode##_newctx(void *provctx) \ +{ \ + PROV_##UCALG##_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx)); \ + if (ctx != NULL) { \ + cipher_generic_initkey(ctx, kbits, blkbits, ivbits, \ + EVP_CIPH_##UCMODE##_MODE, flags, \ + PROV_CIPHER_HW_##alg##_##lcmode(kbits), NULL); \ + } \ + return ctx; \ +} \ + +#define IMPLEMENT_generic_cipher(alg, UCALG, lcmode, UCMODE, flags, kbits, \ + blkbits, ivbits, typ) \ +IMPLEMENT_generic_cipher_genfn(alg, UCALG, lcmode, UCMODE, flags, kbits, \ + blkbits, ivbits, typ) \ +IMPLEMENT_generic_cipher_func(alg, UCALG, lcmode, UCMODE, flags, kbits, \ + blkbits, ivbits, typ) + +#define IMPLEMENT_var_keylen_cipher(alg, UCALG, lcmode, UCMODE, flags, kbits, \ + blkbits, ivbits, typ) \ +IMPLEMENT_generic_cipher_genfn(alg, UCALG, lcmode, UCMODE, flags, kbits, \ + blkbits, ivbits, typ) \ +IMPLEMENT_var_keylen_cipher_func(alg, UCALG, lcmode, UCMODE, flags, kbits, \ + blkbits, ivbits, typ) + +PROV_CIPHER_HW_FN cipher_hw_generic_cbc; +PROV_CIPHER_HW_FN cipher_hw_generic_ecb; +PROV_CIPHER_HW_FN cipher_hw_generic_ofb128; +PROV_CIPHER_HW_FN cipher_hw_generic_cfb128; +PROV_CIPHER_HW_FN cipher_hw_generic_cfb8; +PROV_CIPHER_HW_FN cipher_hw_generic_cfb1; +PROV_CIPHER_HW_FN cipher_hw_generic_ctr; +PROV_CIPHER_HW_FN cipher_hw_chunked_cbc; +PROV_CIPHER_HW_FN cipher_hw_chunked_cfb8; +PROV_CIPHER_HW_FN cipher_hw_chunked_cfb128; +PROV_CIPHER_HW_FN cipher_hw_chunked_ofb128; +#define cipher_hw_chunked_ecb cipher_hw_generic_ecb +#define cipher_hw_chunked_ctr cipher_hw_generic_ctr +#define cipher_hw_chunked_cfb1 cipher_hw_generic_cfb1 + +#define IMPLEMENT_CIPHER_HW_OFB(MODE, NAME, CTX_NAME, KEY_NAME, FUNC_PREFIX) \ +static int cipher_hw_##NAME##_##MODE##_cipher(PROV_CIPHER_CTX *ctx, \ + unsigned char *out, \ + const unsigned char *in, size_t len) \ +{ \ + int num = ctx->num; \ + KEY_NAME *key = &(((CTX_NAME *)ctx)->ks.ks); \ + \ + while (len >= MAXCHUNK) { \ + FUNC_PREFIX##_encrypt(in, out, MAXCHUNK, key, ctx->iv, &num); \ + len -= MAXCHUNK; \ + in += MAXCHUNK; \ + out += MAXCHUNK; \ + } \ + if (len > 0) { \ + FUNC_PREFIX##_encrypt(in, out, (long)len, key, ctx->iv, &num); \ + } \ + ctx->num = num; \ + return 1; \ +} + +#define IMPLEMENT_CIPHER_HW_ECB(MODE, NAME, CTX_NAME, KEY_NAME, FUNC_PREFIX) \ +static int cipher_hw_##NAME##_##MODE##_cipher(PROV_CIPHER_CTX *ctx, \ + unsigned char *out, \ + const unsigned char *in, size_t len) \ +{ \ + size_t i, bl = ctx->blocksize; \ + KEY_NAME *key = &(((CTX_NAME *)ctx)->ks.ks); \ + \ + if (len < bl) \ + return 1; \ + for (i = 0, len -= bl; i <= len; i += bl) \ + FUNC_PREFIX##_encrypt(in + i, out + i, key, ctx->enc); \ + return 1; \ +} + +#define IMPLEMENT_CIPHER_HW_CBC(MODE, NAME, CTX_NAME, KEY_NAME, FUNC_PREFIX) \ +static int cipher_hw_##NAME##_##MODE##_cipher(PROV_CIPHER_CTX *ctx, \ + unsigned char *out, \ + const unsigned char *in, size_t len) \ +{ \ + KEY_NAME *key = &(((CTX_NAME *)ctx)->ks.ks); \ + \ + while (len >= MAXCHUNK) { \ + FUNC_PREFIX##_encrypt(in, out, MAXCHUNK, key, ctx->iv, ctx->enc); \ + len -= MAXCHUNK; \ + in += MAXCHUNK; \ + out += MAXCHUNK; \ + } \ + if (len > 0) \ + FUNC_PREFIX##_encrypt(in, out, (long)len, key, ctx->iv, ctx->enc); \ + return 1; \ +} + +#define IMPLEMENT_CIPHER_HW_CFB(MODE, NAME, CTX_NAME, KEY_NAME, FUNC_PREFIX) \ +static int cipher_hw_##NAME##_##MODE##_cipher(PROV_CIPHER_CTX *ctx, \ + unsigned char *out, \ + const unsigned char *in, size_t len) \ +{ \ + size_t chunk = MAXCHUNK; \ + KEY_NAME *key = &(((CTX_NAME *)ctx)->ks.ks); \ + int num = ctx->num; \ + \ + if (len < chunk) \ + chunk = len; \ + while (len > 0 && len >= chunk) { \ + FUNC_PREFIX##_encrypt(in, out, (long)chunk, key, ctx->iv, &num, \ + ctx->enc); \ + len -= chunk; \ + in += chunk; \ + out += chunk; \ + if (len < chunk) \ + chunk = len; \ + } \ + ctx->num = num; \ + return 1; \ +} + +#define IMPLEMENT_CIPHER_HW_COPYCTX(name, CTX_TYPE) \ +static void name(PROV_CIPHER_CTX *dst, const PROV_CIPHER_CTX *src) \ +{ \ + CTX_TYPE *sctx = (CTX_TYPE *)src; \ + CTX_TYPE *dctx = (CTX_TYPE *)dst; \ + \ + *dctx = *sctx; \ + dst->ks = &dctx->ks.ks; \ +} + +#define CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_START(name) \ +static const OSSL_PARAM name##_known_gettable_ctx_params[] = { \ + OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL), \ + OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_IVLEN, NULL), \ + OSSL_PARAM_uint(OSSL_CIPHER_PARAM_PADDING, NULL), \ + OSSL_PARAM_uint(OSSL_CIPHER_PARAM_NUM, NULL), \ + OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_IV, NULL, 0), + +#define CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_END(name) \ + OSSL_PARAM_END \ +}; \ +const OSSL_PARAM * name##_gettable_ctx_params(void) \ +{ \ + return name##_known_gettable_ctx_params; \ +} + +#define CIPHER_DEFAULT_SETTABLE_CTX_PARAMS_START(name) \ +static const OSSL_PARAM name##_known_settable_ctx_params[] = { \ + OSSL_PARAM_uint(OSSL_CIPHER_PARAM_PADDING, NULL), \ + OSSL_PARAM_uint(OSSL_CIPHER_PARAM_NUM, NULL), +#define CIPHER_DEFAULT_SETTABLE_CTX_PARAMS_END(name) \ + OSSL_PARAM_END \ +}; \ +const OSSL_PARAM * name##_settable_ctx_params(void) \ +{ \ + return name##_known_settable_ctx_params; \ +} + +int cipher_generic_initiv(PROV_CIPHER_CTX *ctx, const unsigned char *iv, + size_t ivlen); + +size_t fillblock(unsigned char *buf, size_t *buflen, size_t blocksize, + const unsigned char **in, size_t *inlen); +int trailingdata(unsigned char *buf, size_t *buflen, size_t blocksize, + const unsigned char **in, size_t *inlen); + diff --git a/providers/implementations/include/prov/ciphercommon_aead.h b/providers/implementations/include/prov/ciphercommon_aead.h new file mode 100644 index 0000000000..db938d7fbe --- /dev/null +++ b/providers/implementations/include/prov/ciphercommon_aead.h @@ -0,0 +1,52 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#define UNINITIALISED_SIZET ((size_t)-1) + +/* TODO(3.0) Figure out what flags are really needed */ +#define AEAD_FLAGS (EVP_CIPH_FLAG_AEAD_CIPHER \ + | EVP_CIPH_CUSTOM_IV \ + | EVP_CIPH_ALWAYS_CALL_INIT \ + | EVP_CIPH_CTRL_INIT \ + | EVP_CIPH_CUSTOM_COPY) + +#define IMPLEMENT_aead_cipher(alg, lc, UCMODE, flags, kbits, blkbits, ivbits) \ +static OSSL_OP_cipher_get_params_fn alg##_##kbits##_##lc##_get_params; \ +static int alg##_##kbits##_##lc##_get_params(OSSL_PARAM params[]) \ +{ \ + return cipher_generic_get_params(params, EVP_CIPH_##UCMODE##_MODE, \ + flags, kbits, blkbits, ivbits); \ +} \ +static OSSL_OP_cipher_newctx_fn alg##kbits##lc##_newctx; \ +static void * alg##kbits##lc##_newctx(void *provctx) \ +{ \ + return alg##_##lc##_newctx(provctx, kbits); \ +} \ +const OSSL_DISPATCH alg##kbits##lc##_functions[] = { \ + { OSSL_FUNC_CIPHER_NEWCTX, (void (*)(void))alg##kbits##lc##_newctx }, \ + { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))alg##_##lc##_freectx }, \ + { OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void)) lc##_einit }, \ + { OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void)) lc##_dinit }, \ + { OSSL_FUNC_CIPHER_UPDATE, (void (*)(void)) lc##_stream_update }, \ + { OSSL_FUNC_CIPHER_FINAL, (void (*)(void)) lc##_stream_final }, \ + { OSSL_FUNC_CIPHER_CIPHER, (void (*)(void)) lc##_cipher }, \ + { OSSL_FUNC_CIPHER_GET_PARAMS, \ + (void (*)(void)) alg##_##kbits##_##lc##_get_params }, \ + { OSSL_FUNC_CIPHER_GET_CTX_PARAMS, \ + (void (*)(void)) lc##_get_ctx_params }, \ + { OSSL_FUNC_CIPHER_SET_CTX_PARAMS, \ + (void (*)(void)) lc##_set_ctx_params }, \ + { OSSL_FUNC_CIPHER_GETTABLE_PARAMS, \ + (void (*)(void))cipher_generic_gettable_params }, \ + { OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS, \ + (void (*)(void))cipher_aead_gettable_ctx_params }, \ + { OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS, \ + (void (*)(void))cipher_aead_settable_ctx_params }, \ + { 0, NULL } \ +} diff --git a/providers/implementations/include/prov/ciphercommon_ccm.h b/providers/implementations/include/prov/ciphercommon_ccm.h new file mode 100644 index 0000000000..0c2af15d54 --- /dev/null +++ b/providers/implementations/include/prov/ciphercommon_ccm.h @@ -0,0 +1,134 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "ciphercommon_aead.h" + +typedef struct prov_ccm_hw_st PROV_CCM_HW; + +#if defined(OPENSSL_CPUID_OBJ) && defined(__s390__) +/*- + * KMAC-AES parameter block - begin + * (see z/Architecture Principles of Operation >= SA22-7832-08) + */ +typedef struct S390X_kmac_params_st { + union { + unsigned long long g[2]; + unsigned char b[16]; + } icv; + unsigned char k[32]; +} S390X_KMAC_PARAMS; +/* KMAC-AES parameter block - end */ +#endif + +/* Base structure that is shared by AES & ARIA for CCM MODE */ +typedef struct prov_ccm_st { + unsigned int enc : 1; + unsigned int key_set : 1; /* Set if key initialised */ + unsigned int iv_set : 1; /* Set if an iv is set */ + unsigned int tag_set : 1; /* Set if tag is valid */ + unsigned int len_set : 1; /* Set if message length set */ + size_t l, m; /* L and M parameters from RFC3610 */ + size_t keylen; + size_t tls_aad_len; /* TLS AAD length */ + size_t tls_aad_pad_sz; + unsigned char iv[AES_BLOCK_SIZE]; + unsigned char buf[AES_BLOCK_SIZE]; + CCM128_CONTEXT ccm_ctx; + ccm128_f str; + const PROV_CCM_HW *hw; /* hardware specific methods */ +} PROV_CCM_CTX; + +typedef struct prov_aes_ccm_ctx_st { + PROV_CCM_CTX base; /* Must be first */ + union { + OSSL_UNION_ALIGN; + /*- + * Padding is chosen so that s390x.kmac.k overlaps with ks.ks and + * fc with ks.ks.rounds. Remember that on s390x, an AES_KEY's + * rounds field is used to store the function code and that the key + * schedule is not stored (if aes hardware support is detected). + */ + struct { + unsigned char pad[16]; + AES_KEY ks; + } ks; +#if defined(OPENSSL_CPUID_OBJ) && defined(__s390__) + struct { + S390X_KMAC_PARAMS kmac; + unsigned long long blocks; + union { + unsigned long long g[2]; + unsigned char b[AES_BLOCK_SIZE]; + } nonce; + union { + unsigned long long g[2]; + unsigned char b[AES_BLOCK_SIZE]; + } buf; + unsigned char dummy_pad[168]; + unsigned int fc; /* fc has same offset as ks.ks.rounds */ + } s390x; +#endif /* defined(OPENSSL_CPUID_OBJ) && defined(__s390__) */ + } ccm; +} PROV_AES_CCM_CTX; + +PROV_CIPHER_FUNC(int, CCM_cipher, (PROV_CCM_CTX *ctx, unsigned char *out, \ + size_t *padlen, const unsigned char *in, \ + size_t len)); +PROV_CIPHER_FUNC(int, CCM_setkey, (PROV_CCM_CTX *ctx, \ + const unsigned char *key, size_t keylen)); +PROV_CIPHER_FUNC(int, CCM_setiv, (PROV_CCM_CTX *dat, \ + const unsigned char *iv, size_t ivlen, \ + size_t mlen)); +PROV_CIPHER_FUNC(int, CCM_setaad, (PROV_CCM_CTX *ctx, \ + const unsigned char *aad, size_t aadlen)); +PROV_CIPHER_FUNC(int, CCM_auth_encrypt, (PROV_CCM_CTX *ctx, \ + const unsigned char *in, \ + unsigned char *out, size_t len, \ + unsigned char *tag, size_t taglen)); +PROV_CIPHER_FUNC(int, CCM_auth_decrypt, (PROV_CCM_CTX *ctx, \ + const unsigned char *in, \ + unsigned char *out, size_t len, \ + unsigned char *tag, size_t taglen)); +PROV_CIPHER_FUNC(int, CCM_gettag, (PROV_CCM_CTX *ctx, \ + unsigned char *tag, size_t taglen)); + +/* + * CCM Mode internal method table used to handle hardware specific differences, + * (and different algorithms). + */ +struct prov_ccm_hw_st { + OSSL_CCM_setkey_fn setkey; + OSSL_CCM_setiv_fn setiv; + OSSL_CCM_setaad_fn setaad; + OSSL_CCM_auth_encrypt_fn auth_encrypt; + OSSL_CCM_auth_decrypt_fn auth_decrypt; + OSSL_CCM_gettag_fn gettag; +}; + +const PROV_CCM_HW *PROV_AES_HW_ccm(size_t keylen); + +OSSL_OP_cipher_encrypt_init_fn ccm_einit; +OSSL_OP_cipher_decrypt_init_fn ccm_dinit; +OSSL_OP_cipher_get_ctx_params_fn ccm_get_ctx_params; +OSSL_OP_cipher_set_ctx_params_fn ccm_set_ctx_params; +OSSL_OP_cipher_update_fn ccm_stream_update; +OSSL_OP_cipher_final_fn ccm_stream_final; +OSSL_OP_cipher_cipher_fn ccm_cipher; +void ccm_initctx(PROV_CCM_CTX *ctx, size_t keybits, const PROV_CCM_HW *hw); + +int ccm_generic_setiv(PROV_CCM_CTX *ctx, const unsigned char *nonce, + size_t nlen, size_t mlen); +int ccm_generic_setaad(PROV_CCM_CTX *ctx, const unsigned char *aad, size_t alen); +int ccm_generic_gettag(PROV_CCM_CTX *ctx, unsigned char *tag, size_t tlen); +int ccm_generic_auth_encrypt(PROV_CCM_CTX *ctx, const unsigned char *in, + unsigned char *out, size_t len, + unsigned char *tag, size_t taglen); +int ccm_generic_auth_decrypt(PROV_CCM_CTX *ctx, const unsigned char *in, + unsigned char *out, size_t len, + unsigned char *expected_tag, size_t taglen); diff --git a/providers/implementations/include/prov/ciphercommon_gcm.h b/providers/implementations/include/prov/ciphercommon_gcm.h new file mode 100644 index 0000000000..1932e14c4c --- /dev/null +++ b/providers/implementations/include/prov/ciphercommon_gcm.h @@ -0,0 +1,160 @@ + +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "ciphercommon_aead.h" + +typedef struct prov_gcm_hw_st PROV_GCM_HW; + +#define GCM_IV_DEFAULT_SIZE 12 /* IV's for AES_GCM should normally be 12 bytes */ +#define GCM_IV_MAX_SIZE 64 +#define GCM_TAG_MAX_SIZE 16 + +#if defined(OPENSSL_CPUID_OBJ) && defined(__s390__) +/*- + * KMA-GCM-AES parameter block - begin + * (see z/Architecture Principles of Operation >= SA22-7832-11) + */ +typedef struct S390X_kma_params_st { + unsigned char reserved[12]; + union { + unsigned int w; + unsigned char b[4]; + } cv; /* 32 bit counter value */ + union { + unsigned long long g[2]; + unsigned char b[16]; + } t; /* tag */ + unsigned char h[16]; /* hash subkey */ + unsigned long long taadl; /* total AAD length */ + unsigned long long tpcl; /* total plaintxt/ciphertxt len */ + union { + unsigned long long g[2]; + unsigned int w[4]; + } j0; /* initial counter value */ + unsigned char k[32]; /* key */ +} S390X_KMA_PARAMS; + +#endif + +typedef struct prov_gcm_ctx_st { + unsigned int mode; /* The mode that we are using */ + size_t keylen; + size_t ivlen; + size_t ivlen_min; + size_t taglen; + size_t tls_aad_pad_sz; + size_t tls_aad_len; /* TLS AAD length */ + uint64_t tls_enc_records; /* Number of TLS records encrypted */ + + /* + * num contains the number of bytes of |iv| which are valid for modes that + * manage partial blocks themselves. + */ + size_t num; + size_t bufsz; /* Number of bytes in buf */ + uint64_t flags; + + unsigned int iv_state; /* set to one of IV_STATE_XXX */ + unsigned int enc:1; /* Set to 1 if we are encrypting or 0 otherwise */ + unsigned int pad:1; /* Whether padding should be used or not */ + unsigned int key_set:1; /* Set if key initialised */ + unsigned int iv_gen_rand:1; /* No IV was specified, so generate a rand IV */ + unsigned int iv_gen:1; /* It is OK to generate IVs */ + + unsigned char iv[GCM_IV_MAX_SIZE]; /* Buffer to use for IV's */ + unsigned char buf[AES_BLOCK_SIZE]; /* Buffer of partial blocks processed via update calls */ + + OPENSSL_CTX *libctx; /* needed for rand calls */ + const PROV_GCM_HW *hw; /* hardware specific methods */ + GCM128_CONTEXT gcm; + ctr128_f ctr; + const void *ks; +} PROV_GCM_CTX; + +typedef struct prov_aes_gcm_ctx_st { + PROV_GCM_CTX base; /* must be first entry in struct */ + union { + OSSL_UNION_ALIGN; + AES_KEY ks; + } ks; /* AES key schedule to use */ + + /* Platform specific data */ + union { + int dummy; +#if defined(OPENSSL_CPUID_OBJ) && defined(__s390__) + struct { + union { + OSSL_UNION_ALIGN; + S390X_KMA_PARAMS kma; + } param; + unsigned int fc; + unsigned char ares[16]; + unsigned char mres[16]; + unsigned char kres[16]; + int areslen; + int mreslen; + int kreslen; + int res; + } s390x; +#endif /* defined(OPENSSL_CPUID_OBJ) && defined(__s390__) */ + } plat; +} PROV_AES_GCM_CTX; + +PROV_CIPHER_FUNC(int, GCM_setkey, (PROV_GCM_CTX *ctx, const unsigned char *key, + size_t keylen)); +PROV_CIPHER_FUNC(int, GCM_setiv, (PROV_GCM_CTX *dat, const unsigned char *iv, + size_t ivlen)); +PROV_CIPHER_FUNC(int, GCM_aadupdate, (PROV_GCM_CTX *ctx, + const unsigned char *aad, size_t aadlen)); +PROV_CIPHER_FUNC(int, GCM_cipherupdate, (PROV_GCM_CTX *ctx, + const unsigned char *in, size_t len, + unsigned char *out)); +PROV_CIPHER_FUNC(int, GCM_cipherfinal, (PROV_GCM_CTX *ctx, unsigned char *tag)); +PROV_CIPHER_FUNC(int, GCM_oneshot, (PROV_GCM_CTX *ctx, unsigned char *aad, + size_t aad_len, const unsigned char *in, + size_t in_len, unsigned char *out, + unsigned char *tag, size_t taglen)); +struct prov_gcm_hw_st { + OSSL_GCM_setkey_fn setkey; + OSSL_GCM_setiv_fn setiv; + OSSL_GCM_aadupdate_fn aadupdate; + OSSL_GCM_cipherupdate_fn cipherupdate; + OSSL_GCM_cipherfinal_fn cipherfinal; + OSSL_GCM_oneshot_fn oneshot; +}; +const PROV_GCM_HW *PROV_AES_HW_gcm(size_t keybits); + +OSSL_OP_cipher_encrypt_init_fn gcm_einit; +OSSL_OP_cipher_decrypt_init_fn gcm_dinit; +OSSL_OP_cipher_get_ctx_params_fn gcm_get_ctx_params; +OSSL_OP_cipher_set_ctx_params_fn gcm_set_ctx_params; +OSSL_OP_cipher_cipher_fn gcm_cipher; +OSSL_OP_cipher_update_fn gcm_stream_update; +OSSL_OP_cipher_final_fn gcm_stream_final; +void gcm_initctx(void *provctx, PROV_GCM_CTX *ctx, size_t keybits, + const PROV_GCM_HW *hw, size_t ivlen_min); + +int gcm_setiv(PROV_GCM_CTX *ctx, const unsigned char *iv, size_t ivlen); +int gcm_aad_update(PROV_GCM_CTX *ctx, const unsigned char *aad, + size_t aad_len); +int gcm_cipher_final(PROV_GCM_CTX *ctx, unsigned char *tag); +int gcm_one_shot(PROV_GCM_CTX *ctx, unsigned char *aad, size_t aad_len, + const unsigned char *in, size_t in_len, + unsigned char *out, unsigned char *tag, size_t tag_len); +int gcm_cipher_update(PROV_GCM_CTX *ctx, const unsigned char *in, + size_t len, unsigned char *out); + +#define GCM_HW_SET_KEY_CTR_FN(ks, fn_set_enc_key, fn_block, fn_ctr) \ + ctx->ks = ks; \ + fn_set_enc_key(key, keylen * 8, ks); \ + CRYPTO_gcm128_init(&ctx->gcm, ks, (block128_f)fn_block); \ + ctx->ctr = (ctr128_f)fn_ctr; \ + ctx->key_set = 1; diff --git a/providers/implementations/include/prov/digestcommon.h b/providers/implementations/include/prov/digestcommon.h new file mode 100644 index 0000000000..e5b76ff49f --- /dev/null +++ b/providers/implementations/include/prov/digestcommon.h @@ -0,0 +1,104 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef OSSL_PROVIDERS_DIGESTCOMMON_H +# define OSSL_PROVIDERS_DIGESTCOMMON_H + +# include +# include +# include + +# ifdef __cplusplus +extern "C" { +# endif + +#define PROV_FUNC_DIGEST_GET_PARAM(name, blksize, dgstsize, flags) \ +static OSSL_OP_digest_get_params_fn name##_get_params; \ +static int name##_get_params(OSSL_PARAM params[]) \ +{ \ + return digest_default_get_params(params, blksize, dgstsize, flags); \ +} + +#define PROV_DISPATCH_FUNC_DIGEST_GET_PARAMS(name) \ +{ OSSL_FUNC_DIGEST_GET_PARAMS, (void (*)(void))name##_get_params }, \ +{ OSSL_FUNC_DIGEST_GETTABLE_PARAMS, \ + (void (*)(void))digest_default_gettable_params } + +# define PROV_DISPATCH_FUNC_DIGEST_CONSTRUCT_START( \ + name, CTX, blksize, dgstsize, flags, init, upd, fin) \ +static OSSL_OP_digest_newctx_fn name##_newctx; \ +static OSSL_OP_digest_freectx_fn name##_freectx; \ +static OSSL_OP_digest_dupctx_fn name##_dupctx; \ +static void *name##_newctx(void *prov_ctx) \ +{ \ + CTX *ctx = OPENSSL_zalloc(sizeof(*ctx)); \ + return ctx; \ +} \ +static void name##_freectx(void *vctx) \ +{ \ + CTX *ctx = (CTX *)vctx; \ + OPENSSL_clear_free(ctx, sizeof(*ctx)); \ +} \ +static void *name##_dupctx(void *ctx) \ +{ \ + CTX *in = (CTX *)ctx; \ + CTX *ret = OPENSSL_malloc(sizeof(*ret)); \ + if (ret != NULL) \ + *ret = *in; \ + return ret; \ +} \ +static OSSL_OP_digest_final_fn name##_internal_final; \ +static int name##_internal_final(void *ctx, unsigned char *out, size_t *outl, \ + size_t outsz) \ +{ \ + if (outsz >= dgstsize && fin(out, ctx)) { \ + *outl = dgstsize; \ + return 1; \ + } \ + return 0; \ +} \ +PROV_FUNC_DIGEST_GET_PARAM(name, blksize, dgstsize, flags) \ +const OSSL_DISPATCH name##_functions[] = { \ + { OSSL_FUNC_DIGEST_NEWCTX, (void (*)(void))name##_newctx }, \ + { OSSL_FUNC_DIGEST_INIT, (void (*)(void))init }, \ + { OSSL_FUNC_DIGEST_UPDATE, (void (*)(void))upd }, \ + { OSSL_FUNC_DIGEST_FINAL, (void (*)(void))name##_internal_final }, \ + { OSSL_FUNC_DIGEST_FREECTX, (void (*)(void))name##_freectx }, \ + { OSSL_FUNC_DIGEST_DUPCTX, (void (*)(void))name##_dupctx }, \ + PROV_DISPATCH_FUNC_DIGEST_GET_PARAMS(name) + +# define PROV_DISPATCH_FUNC_DIGEST_CONSTRUCT_END \ + { 0, NULL } \ +}; + +# define IMPLEMENT_digest_functions( \ + name, CTX, blksize, dgstsize, flags, init, upd, fin) \ +PROV_DISPATCH_FUNC_DIGEST_CONSTRUCT_START(name, CTX, blksize, dgstsize, flags, \ + init, upd, fin), \ +PROV_DISPATCH_FUNC_DIGEST_CONSTRUCT_END + +# define IMPLEMENT_digest_functions_with_settable_ctx( \ + name, CTX, blksize, dgstsize, flags, init, upd, fin, \ + settable_ctx_params, set_ctx_params) \ +PROV_DISPATCH_FUNC_DIGEST_CONSTRUCT_START(name, CTX, blksize, dgstsize, flags, \ + init, upd, fin), \ +{ OSSL_FUNC_DIGEST_SETTABLE_CTX_PARAMS, (void (*)(void))settable_ctx_params }, \ +{ OSSL_FUNC_DIGEST_SET_CTX_PARAMS, (void (*)(void))set_ctx_params }, \ +PROV_DISPATCH_FUNC_DIGEST_CONSTRUCT_END + + +const OSSL_PARAM *digest_default_gettable_params(void); +int digest_default_get_params(OSSL_PARAM params[], size_t blksz, size_t paramsz, + unsigned long flags); + +# ifdef __cplusplus +} +# endif + +#endif /* OSSL_PROVIDERS_DIGESTCOMMON_H */