$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
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
-SUBDIRS=digests ciphers
-
SOURCE[../libcommon.a]=provider_err.c bio_prov.c
$FIPSCOMMON=provider_util.c
SOURCE[../libnonfips.a]=$FIPSCOMMON nid_to_name.c
+++ /dev/null
-/*
- * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the Apache License 2.0 (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include <assert.h>
-#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;
-}
+++ /dev/null
-# 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
+++ /dev/null
-/*
- * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the Apache License 2.0 (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-/* 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;
-}
-
+++ /dev/null
-/*
- * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the Apache License 2.0 (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include "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;
-}
-
+++ /dev/null
-/*
- * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the Apache License 2.0 (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-/*
- * 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 */
-}
+++ /dev/null
-/*
- * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the Apache License 2.0 (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include "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;
-}
+++ /dev/null
-/*
- * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the Apache License 2.0 (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-/* 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;
-}
+++ /dev/null
-/*
- * 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;
-}
+++ /dev/null
-/*
- * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the Apache License 2.0 (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include "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);
+++ /dev/null
-# This source is common for all digests in all our providers.
-SOURCE[../../libcommon.a]=digest_common.c
+++ /dev/null
-/*
- * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the Apache License 2.0 (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include "openssl/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;
-}
+++ /dev/null
-/*
- * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the Apache License 2.0 (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#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 } \
-}
+++ /dev/null
-/*
- * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the Apache License 2.0 (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include "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);
+++ /dev/null
-
-/*
- * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the Apache License 2.0 (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include <openssl/aes.h>
-#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;
+++ /dev/null
-/*
- * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the Apache License 2.0 (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include <openssl/params.h>
-#include <openssl/core_numbers.h>
-#include <openssl/core_names.h>
-#include <openssl/evp.h>
-#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);
-
+++ /dev/null
-/*
- * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the Apache License 2.0 (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#ifndef OSSL_PROVIDERS_DIGESTCOMMON_H
-# define OSSL_PROVIDERS_DIGESTCOMMON_H
-
-# include <openssl/core_numbers.h>
-# include <openssl/core_names.h>
-# include <openssl/params.h>
-
-# 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 */
# 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
$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
/* 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)
/* 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); \
/*-
* 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,
/*-
* 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
/*-
* 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,
/* 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)
/* 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)
/*-
* 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,
/*-
* 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 */
/*-
* 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,
#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
#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
#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 */
#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 */
--- /dev/null
+/*
+ * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * 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 */
+}
--- /dev/null
+/*
+ * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <assert.h>
+#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;
+}
--- /dev/null
+/*
+ * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/* 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;
+}
+
--- /dev/null
+/*
+ * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "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;
+}
+
--- /dev/null
+/*
+ * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/* 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;
+}
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "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;
+}
--- /dev/null
+/*
+ * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "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);
# 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
$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
--- /dev/null
+/*
+ * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "openssl/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;
+}
--- /dev/null
+/*
+ * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/params.h>
+#include <openssl/core_numbers.h>
+#include <openssl/core_names.h>
+#include <openssl/evp.h>
+#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);
+
--- /dev/null
+/*
+ * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#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 } \
+}
--- /dev/null
+/*
+ * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "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);
--- /dev/null
+
+/*
+ * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/aes.h>
+#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;
--- /dev/null
+/*
+ * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_PROVIDERS_DIGESTCOMMON_H
+# define OSSL_PROVIDERS_DIGESTCOMMON_H
+
+# include <openssl/core_numbers.h>
+# include <openssl/core_names.h>
+# include <openssl/params.h>
+
+# 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 */