Move providers/common/{ciphers,digests}/* to providers/implementations
authorRichard Levitte <levitte@openssl.org>
Tue, 3 Dec 2019 18:41:05 +0000 (19:41 +0100)
committerRichard Levitte <levitte@openssl.org>
Wed, 11 Dec 2019 11:55:48 +0000 (12:55 +0100)
The idea to have all these things in providers/common was viable as
long as the implementations was spread around their main providers.
This is, however, no longer the case, so we move the common blocks
closer to the source that use them.

Reviewed-by: Paul Dale <paul.dale@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/10564)

48 files changed:
providers/build.info
providers/common/build.info
providers/common/ciphers/block.c [deleted file]
providers/common/ciphers/build.info [deleted file]
providers/common/ciphers/cipher_ccm.c [deleted file]
providers/common/ciphers/cipher_ccm_hw.c [deleted file]
providers/common/ciphers/cipher_common.c [deleted file]
providers/common/ciphers/cipher_common_hw.c [deleted file]
providers/common/ciphers/cipher_gcm.c [deleted file]
providers/common/ciphers/cipher_gcm_hw.c [deleted file]
providers/common/ciphers/cipher_local.h [deleted file]
providers/common/digests/build.info [deleted file]
providers/common/digests/digest_common.c [deleted file]
providers/common/include/prov/cipher_aead.h [deleted file]
providers/common/include/prov/cipher_ccm.h [deleted file]
providers/common/include/prov/cipher_gcm.h [deleted file]
providers/common/include/prov/ciphercommon.h [deleted file]
providers/common/include/prov/digestcommon.h [deleted file]
providers/implementations/ciphers/build.info
providers/implementations/ciphers/cipher_aes_ccm.c
providers/implementations/ciphers/cipher_aes_ccm_hw.c
providers/implementations/ciphers/cipher_aes_ccm_hw_aesni.inc
providers/implementations/ciphers/cipher_aes_ccm_hw_s390x.inc
providers/implementations/ciphers/cipher_aes_ccm_hw_t4.inc
providers/implementations/ciphers/cipher_aes_gcm.c
providers/implementations/ciphers/cipher_aes_gcm_hw.c
providers/implementations/ciphers/cipher_aes_gcm_hw_aesni.inc
providers/implementations/ciphers/cipher_aes_gcm_hw_s390x.inc
providers/implementations/ciphers/cipher_aes_gcm_hw_t4.inc
providers/implementations/ciphers/cipher_aes_ocb.c
providers/implementations/ciphers/cipher_aes_siv.c
providers/implementations/ciphers/cipher_aria_ccm.h
providers/implementations/ciphers/cipher_aria_gcm.h
providers/implementations/ciphers/ciphercommon.c [new file with mode: 0644]
providers/implementations/ciphers/ciphercommon_block.c [new file with mode: 0644]
providers/implementations/ciphers/ciphercommon_ccm.c [new file with mode: 0644]
providers/implementations/ciphers/ciphercommon_ccm_hw.c [new file with mode: 0644]
providers/implementations/ciphers/ciphercommon_gcm.c [new file with mode: 0644]
providers/implementations/ciphers/ciphercommon_gcm_hw.c [new file with mode: 0644]
providers/implementations/ciphers/ciphercommon_hw.c [new file with mode: 0644]
providers/implementations/ciphers/ciphercommon_local.h [new file with mode: 0644]
providers/implementations/digests/build.info
providers/implementations/digests/digestcommon.c [new file with mode: 0644]
providers/implementations/include/prov/ciphercommon.h [new file with mode: 0644]
providers/implementations/include/prov/ciphercommon_aead.h [new file with mode: 0644]
providers/implementations/include/prov/ciphercommon_ccm.h [new file with mode: 0644]
providers/implementations/include/prov/ciphercommon_gcm.h [new file with mode: 0644]
providers/implementations/include/prov/digestcommon.h [new file with mode: 0644]

index c31c4271defd7c1d1d5adb424f06ed71226fcf58..39e767fb0e784eed0a2b481136526529d6fdb6e8 100644 (file)
@@ -40,14 +40,14 @@ $LIBNONFIPS=libnonfips.a
 $LIBFIPS=libfips.a
 
 # Enough of our implementations include prov/ciphercommon.h (present in
-# providers/common/include), which includes crypto/ciphermode_platform.h
+# providers/implementations/include), which includes crypto/ciphermode_platform.h
 # (present in include), which in turn may include very internal header
 # files in crypto/, so let's have a common include list for them all.
-$COMMON_INCLUDES=../crypto ../include common/include
+$COMMON_INCLUDES=../crypto ../include implementations/include common/include
 
 INCLUDE[$LIBCOMMON]=$COMMON_INCLUDES
-INCLUDE[$LIBIMPLEMENTATIONS]=.. $COMMON_INCLUDES implementations/include
-INCLUDE[$LIBLEGACY]=$COMMON_INCLUDES implementations/include
+INCLUDE[$LIBIMPLEMENTATIONS]=.. $COMMON_INCLUDES
+INCLUDE[$LIBLEGACY]=$COMMON_INCLUDES
 INCLUDE[$LIBNONFIPS]=$COMMON_INCLUDES
 INCLUDE[$LIBFIPS]=.. $COMMON_INCLUDES
 DEFINE[$LIBFIPS]=FIPS_MODE
@@ -84,7 +84,7 @@ $DEFAULTGOAL=../libcrypto
 SOURCE[$DEFAULTGOAL]=$LIBIMPLEMENTATIONS $LIBNONFIPS
 SOURCE[$DEFAULTGOAL]=defltprov.c
 # Some legacy implementations depend on provider header files
-INCLUDE[../libcrypto]=implementations/include
+INCLUDE[$DEFAULTGOAL]=implementations/include
 
 LIBS=$DEFAULTGOAL
 
index 3f20fb3c09b3748289ed3786788c4c3392402a8d..ccc99e515b305a471c22b19fcf1d76f85d3ab424 100644 (file)
@@ -1,5 +1,3 @@
-SUBDIRS=digests ciphers
-
 SOURCE[../libcommon.a]=provider_err.c bio_prov.c
 $FIPSCOMMON=provider_util.c
 SOURCE[../libnonfips.a]=$FIPSCOMMON nid_to_name.c
diff --git a/providers/common/ciphers/block.c b/providers/common/ciphers/block.c
deleted file mode 100644 (file)
index 95acfaf..0000000
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the Apache License 2.0 (the "License").  You may not use
- * this file except in compliance with the License.  You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include <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;
-}
diff --git a/providers/common/ciphers/build.info b/providers/common/ciphers/build.info
deleted file mode 100644 (file)
index b76b8ba..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-# This source is common building blocks for all ciphers in all our providers.
-SOURCE[../../libcommon.a]=\
-        cipher_common.c cipher_common_hw.c block.c \
-        cipher_gcm.c cipher_gcm_hw.c \
-        cipher_ccm.c cipher_ccm_hw.c
diff --git a/providers/common/ciphers/cipher_ccm.c b/providers/common/ciphers/cipher_ccm.c
deleted file mode 100644 (file)
index 021a004..0000000
+++ /dev/null
@@ -1,421 +0,0 @@
-/*
- * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the Apache License 2.0 (the "License").  You may not use
- * this file except in compliance with the License.  You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-/* Dispatch functions for ccm mode */
-
-#include "prov/ciphercommon.h"
-#include "prov/cipher_ccm.h"
-#include "prov/providercommonerr.h"
-
-static int ccm_cipher_internal(PROV_CCM_CTX *ctx, unsigned char *out,
-                               size_t *padlen, const unsigned char *in,
-                               size_t len);
-
-static int ccm_tls_init(PROV_CCM_CTX *ctx, unsigned char *aad, size_t alen)
-{
-    size_t len;
-
-    if (alen != EVP_AEAD_TLS1_AAD_LEN)
-        return 0;
-
-    /* Save the aad for later use. */
-    memcpy(ctx->buf, aad, alen);
-    ctx->tls_aad_len = alen;
-
-    len = ctx->buf[alen - 2] << 8 | ctx->buf[alen - 1];
-    if (len < EVP_CCM_TLS_EXPLICIT_IV_LEN)
-        return 0;
-
-    /* Correct length for explicit iv. */
-    len -= EVP_CCM_TLS_EXPLICIT_IV_LEN;
-
-    if (!ctx->enc) {
-        if (len < ctx->m)
-            return 0;
-        /* Correct length for tag. */
-        len -= ctx->m;
-    }
-    ctx->buf[alen - 2] = (unsigned char)(len >> 8);
-    ctx->buf[alen - 1] = (unsigned char)(len & 0xff);
-
-    /* Extra padding: tag appended to record. */
-    return ctx->m;
-}
-
-static int ccm_tls_iv_set_fixed(PROV_CCM_CTX *ctx, unsigned char *fixed,
-                                size_t flen)
-{
-    if (flen != EVP_CCM_TLS_FIXED_IV_LEN)
-        return 0;
-
-    /* Copy to first part of the iv. */
-    memcpy(ctx->iv, fixed, flen);
-    return 1;
-}
-
-static size_t ccm_get_ivlen(PROV_CCM_CTX *ctx)
-{
-    return 15 - ctx->l;
-}
-
-int ccm_set_ctx_params(void *vctx, const OSSL_PARAM params[])
-{
-    PROV_CCM_CTX *ctx = (PROV_CCM_CTX *)vctx;
-    const OSSL_PARAM *p;
-    size_t sz;
-
-    p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TAG);
-    if (p != NULL) {
-        if (p->data_type != OSSL_PARAM_OCTET_STRING) {
-            ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
-            return 0;
-        }
-        if ((p->data_size & 1) || (p->data_size < 4) || p->data_size > 16) {
-            ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_TAGLEN);
-            return 0;
-        }
-
-        if (p->data != NULL) {
-            if (ctx->enc) {
-                ERR_raise(ERR_LIB_PROV, PROV_R_TAG_NOT_NEEDED);
-                return 0;
-            }
-            memcpy(ctx->buf, p->data, p->data_size);
-            ctx->tag_set = 1;
-        }
-        ctx->m = p->data_size;
-    }
-
-    p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_IVLEN);
-    if (p != NULL) {
-        size_t ivlen;
-
-        if (!OSSL_PARAM_get_size_t(p, &sz)) {
-            ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
-            return 0;
-        }
-        ivlen = 15 - sz;
-        if (ivlen < 2 || ivlen > 8) {
-            ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IVLEN);
-            return 0;
-        }
-        ctx->l = ivlen;
-    }
-
-    p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TLS1_AAD);
-    if (p != NULL) {
-        if (p->data_type != OSSL_PARAM_OCTET_STRING) {
-            ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
-            return 0;
-        }
-        sz = ccm_tls_init(ctx, p->data, p->data_size);
-        if (sz == 0) {
-            ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DATA);
-            return 0;
-        }
-        ctx->tls_aad_pad_sz = sz;
-    }
-
-    p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TLS1_IV_FIXED);
-    if (p != NULL) {
-        if (p->data_type != OSSL_PARAM_OCTET_STRING) {
-            ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
-            return 0;
-        }
-        if (ccm_tls_iv_set_fixed(ctx, p->data, p->data_size) == 0) {
-            ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IVLEN);
-            return 0;
-        }
-    }
-
-    return 1;
-}
-
-int ccm_get_ctx_params(void *vctx, OSSL_PARAM params[])
-{
-    PROV_CCM_CTX *ctx = (PROV_CCM_CTX *)vctx;
-    OSSL_PARAM *p;
-
-    p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IVLEN);
-    if (p != NULL && !OSSL_PARAM_set_size_t(p, ccm_get_ivlen(ctx))) {
-        ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
-        return 0;
-    }
-
-    p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TAGLEN);
-    if (p != NULL) {
-        size_t m = ctx->m;
-
-        if (!OSSL_PARAM_set_size_t(p, m)) {
-            ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
-            return 0;
-        }
-    }
-
-    p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IV);
-    if (p != NULL) {
-        if (ccm_get_ivlen(ctx) != p->data_size) {
-            ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IVLEN);
-            return 0;
-        }
-        if (!OSSL_PARAM_set_octet_string(p, ctx->iv, p->data_size)) {
-            ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
-            return 0;
-        }
-    }
-
-    p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_KEYLEN);
-    if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->keylen)) {
-        ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
-        return 0;
-    }
-
-    p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TLS1_AAD_PAD);
-    if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->tls_aad_pad_sz)) {
-        ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
-        return 0;
-    }
-
-    p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TAG);
-    if (p != NULL) {
-        if (!ctx->enc || !ctx->tag_set) {
-            ERR_raise(ERR_LIB_PROV, PROV_R_TAG_NOTSET);
-            return 0;
-        }
-        if (p->data_type != OSSL_PARAM_OCTET_STRING) {
-            ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
-            return 0;
-        }
-        if (!ctx->hw->gettag(ctx, p->data, p->data_size))
-            return 0;
-        ctx->tag_set = 0;
-        ctx->iv_set = 0;
-        ctx->len_set = 0;
-    }
-    return 1;
-}
-
-static int ccm_init(void *vctx, const unsigned char *key, size_t keylen,
-                    const unsigned char *iv, size_t ivlen, int enc)
-{
-    PROV_CCM_CTX *ctx = (PROV_CCM_CTX *)vctx;
-
-    ctx->enc = enc;
-
-    if (iv != NULL) {
-        if (ivlen != ccm_get_ivlen(ctx)) {
-            ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IVLEN);
-            return 0;
-        }
-        memcpy(ctx->iv, iv, ivlen);
-        ctx->iv_set = 1;
-    }
-    if (key != NULL) {
-        if (keylen != ctx->keylen) {
-            ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEYLEN);
-            return 0;
-        }
-        return ctx->hw->setkey(ctx, key, keylen);
-    }
-    return 1;
-}
-
-int ccm_einit(void *vctx, const unsigned char *key, size_t keylen,
-                     const unsigned char *iv, size_t ivlen)
-{
-    return ccm_init(vctx, key, keylen, iv, ivlen, 1);
-}
-
-int ccm_dinit(void *vctx, const unsigned char *key, size_t keylen,
-                     const unsigned char *iv, size_t ivlen)
-{
-    return ccm_init(vctx, key, keylen, iv, ivlen, 0);
-}
-
-int ccm_stream_update(void *vctx, unsigned char *out, size_t *outl,
-                             size_t outsize, const unsigned char *in,
-                             size_t inl)
-{
-    PROV_CCM_CTX *ctx = (PROV_CCM_CTX *)vctx;
-
-    if (outsize < inl) {
-        ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
-        return 0;
-    }
-
-    if (!ccm_cipher_internal(ctx, out, outl, in, inl)) {
-        ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);
-        return 0;
-    }
-    return 1;
-}
-
-int ccm_stream_final(void *vctx, unsigned char *out, size_t *outl,
-                            size_t outsize)
-{
-    PROV_CCM_CTX *ctx = (PROV_CCM_CTX *)vctx;
-    int i;
-
-    i = ccm_cipher_internal(ctx, out, outl, NULL, 0);
-    if (i <= 0)
-        return 0;
-
-    *outl = 0;
-    return 1;
-}
-
-int ccm_cipher(void *vctx,
-                      unsigned char *out, size_t *outl, size_t outsize,
-                      const unsigned char *in, size_t inl)
-{
-    PROV_CCM_CTX *ctx = (PROV_CCM_CTX *)vctx;
-
-    if (outsize < inl) {
-        ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
-        return 0;
-    }
-
-    if (ccm_cipher_internal(ctx, out, outl, in, inl) <= 0)
-        return 0;
-
-    *outl = inl;
-    return 1;
-}
-
-/* Copy the buffered iv */
-static int ccm_set_iv(PROV_CCM_CTX *ctx, size_t mlen)
-{
-    const PROV_CCM_HW *hw = ctx->hw;
-
-    if (!hw->setiv(ctx, ctx->iv, ccm_get_ivlen(ctx), mlen))
-        return 0;
-    ctx->len_set = 1;
-    return 1;
-}
-
-static int ccm_tls_cipher(PROV_CCM_CTX *ctx,
-                          unsigned char *out, size_t *padlen,
-                          const unsigned char *in, size_t len)
-{
-    int rv = 0;
-    size_t olen = 0;
-
-    /* Encrypt/decrypt must be performed in place */
-    if (out != in || len < (EVP_CCM_TLS_EXPLICIT_IV_LEN + (size_t)ctx->m))
-        goto err;
-
-    /* If encrypting set explicit IV from sequence number (start of AAD) */
-    if (ctx->enc)
-        memcpy(out, ctx->buf, EVP_CCM_TLS_EXPLICIT_IV_LEN);
-    /* Get rest of IV from explicit IV */
-    memcpy(ctx->iv + EVP_CCM_TLS_FIXED_IV_LEN, in, EVP_CCM_TLS_EXPLICIT_IV_LEN);
-    /* Correct length value */
-    len -= EVP_CCM_TLS_EXPLICIT_IV_LEN + ctx->m;
-    if (!ccm_set_iv(ctx, len))
-        goto err;
-
-    /* Use saved AAD */
-    if (!ctx->hw->setaad(ctx, ctx->buf, ctx->tls_aad_len))
-        goto err;
-
-    /* Fix buffer to point to payload */
-    in += EVP_CCM_TLS_EXPLICIT_IV_LEN;
-    out += EVP_CCM_TLS_EXPLICIT_IV_LEN;
-    if (ctx->enc) {
-        if (!ctx->hw->auth_encrypt(ctx, in, out, len,  out + len, ctx->m))
-            goto err;
-        olen = len + EVP_CCM_TLS_EXPLICIT_IV_LEN + ctx->m;
-    } else {
-        if (!ctx->hw->auth_decrypt(ctx, in, out, len,
-                                   (unsigned char *)in + len, ctx->m))
-            goto err;
-        olen = len;
-    }
-    rv = 1;
-err:
-    *padlen = olen;
-    return rv;
-}
-
-static int ccm_cipher_internal(PROV_CCM_CTX *ctx, unsigned char *out,
-                               size_t *padlen, const unsigned char *in,
-                               size_t len)
-{
-    int rv = 0;
-    size_t olen = 0;
-    const PROV_CCM_HW *hw = ctx->hw;
-
-    /* If no key set, return error */
-    if (!ctx->key_set)
-        return 0;
-
-    if (ctx->tls_aad_len != UNINITIALISED_SIZET)
-        return ccm_tls_cipher(ctx, out, padlen, in, len);
-
-    /* EVP_*Final() doesn't return any data */
-    if (in == NULL && out != NULL)
-        goto finish;
-
-    if (!ctx->iv_set)
-        goto err;
-
-    if (out == NULL) {
-        if (in == NULL) {
-            if (!ccm_set_iv(ctx, len))
-                goto err;
-        } else {
-            /* If we have AAD, we need a message length */
-            if (!ctx->len_set && len)
-                goto err;
-            if (!hw->setaad(ctx, in, len))
-                goto err;
-        }
-    } else {
-        /* If not set length yet do it */
-        if (!ctx->len_set && !ccm_set_iv(ctx, len))
-            goto err;
-
-        if (ctx->enc) {
-            if (!hw->auth_encrypt(ctx, in, out, len, NULL, 0))
-                goto err;
-            ctx->tag_set = 1;
-        } else {
-            /* The tag must be set before actually decrypting data */
-            if (!ctx->tag_set)
-                goto err;
-
-            if (!hw->auth_decrypt(ctx, in, out, len, ctx->buf, ctx->m))
-                goto err;
-            /* Finished - reset flags so calling this method again will fail */
-            ctx->iv_set = 0;
-            ctx->tag_set = 0;
-            ctx->len_set = 0;
-        }
-    }
-    olen = len;
-finish:
-    rv = 1;
-err:
-    *padlen = olen;
-    return rv;
-}
-
-void ccm_initctx(PROV_CCM_CTX *ctx, size_t keybits, const PROV_CCM_HW *hw)
-{
-    ctx->keylen = keybits / 8;
-    ctx->key_set = 0;
-    ctx->iv_set = 0;
-    ctx->tag_set = 0;
-    ctx->len_set = 0;
-    ctx->l = 8;
-    ctx->m = 12;
-    ctx->tls_aad_len = UNINITIALISED_SIZET;
-    ctx->hw = hw;
-}
-
diff --git a/providers/common/ciphers/cipher_ccm_hw.c b/providers/common/ciphers/cipher_ccm_hw.c
deleted file mode 100644 (file)
index 5503a41..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the Apache License 2.0 (the "License").  You may not use
- * this file except in compliance with the License.  You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include "prov/ciphercommon.h"
-#include "prov/cipher_ccm.h"
-
-int ccm_generic_setiv(PROV_CCM_CTX *ctx, const unsigned char *nonce,
-                      size_t nlen, size_t mlen)
-{
-    return CRYPTO_ccm128_setiv(&ctx->ccm_ctx, nonce, nlen, mlen) == 0;
-}
-
-int ccm_generic_setaad(PROV_CCM_CTX *ctx, const unsigned char *aad, size_t alen)
-{
-    CRYPTO_ccm128_aad(&ctx->ccm_ctx, aad, alen);
-    return 1;
-}
-
-int ccm_generic_gettag(PROV_CCM_CTX *ctx, unsigned char *tag, size_t tlen)
-{
-    return CRYPTO_ccm128_tag(&ctx->ccm_ctx, tag, tlen) > 0;
-}
-
-int ccm_generic_auth_encrypt(PROV_CCM_CTX *ctx, const unsigned char *in,
-                             unsigned char *out, size_t len,
-                             unsigned char *tag, size_t taglen)
-{
-    int rv;
-
-    if (ctx->str != NULL)
-        rv = CRYPTO_ccm128_encrypt_ccm64(&ctx->ccm_ctx, in,
-                                         out, len, ctx->str) == 0;
-    else
-        rv = CRYPTO_ccm128_encrypt(&ctx->ccm_ctx, in, out, len) == 0;
-
-    if (rv == 1 && tag != NULL)
-        rv = (CRYPTO_ccm128_tag(&ctx->ccm_ctx, tag, taglen) > 0);
-    return rv;
-}
-
-int ccm_generic_auth_decrypt(PROV_CCM_CTX *ctx, const unsigned char *in,
-                             unsigned char *out, size_t len,
-                             unsigned char *expected_tag, size_t taglen)
-{
-    int rv = 0;
-
-    if (ctx->str != NULL)
-        rv = CRYPTO_ccm128_decrypt_ccm64(&ctx->ccm_ctx, in, out, len,
-                                         ctx->str) == 0;
-    else
-        rv = CRYPTO_ccm128_decrypt(&ctx->ccm_ctx, in, out, len) == 0;
-    if (rv) {
-        unsigned char tag[16];
-
-        if (!CRYPTO_ccm128_tag(&ctx->ccm_ctx, tag, taglen)
-            || CRYPTO_memcmp(tag, expected_tag, taglen) != 0)
-            rv = 0;
-    }
-    if (rv == 0)
-        OPENSSL_cleanse(out, len);
-    return rv;
-}
-
diff --git a/providers/common/ciphers/cipher_common.c b/providers/common/ciphers/cipher_common.c
deleted file mode 100644 (file)
index 83c3707..0000000
+++ /dev/null
@@ -1,431 +0,0 @@
-/*
- * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the Apache License 2.0 (the "License").  You may not use
- * this file except in compliance with the License.  You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-/*
- * Generic dispatch table functions for ciphers.
- */
-
-#include "cipher_local.h"
-#include "prov/provider_ctx.h"
-#include "prov/providercommonerr.h"
-
-/*-
- * Generic cipher functions for OSSL_PARAM gettables and settables
- */
-static const OSSL_PARAM cipher_known_gettable_params[] = {
-    OSSL_PARAM_uint(OSSL_CIPHER_PARAM_MODE, NULL),
-    OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL),
-    OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_IVLEN, NULL),
-    OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_BLOCK_SIZE, NULL),
-    OSSL_PARAM_ulong(OSSL_CIPHER_PARAM_FLAGS, NULL),
-    OSSL_PARAM_END
-};
-const OSSL_PARAM *cipher_generic_gettable_params(void)
-{
-    return cipher_known_gettable_params;
-}
-
-int cipher_generic_get_params(OSSL_PARAM params[], unsigned int md,
-                              unsigned long flags,
-                              size_t kbits, size_t blkbits, size_t ivbits)
-{
-    OSSL_PARAM *p;
-
-    p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_MODE);
-    if (p != NULL && !OSSL_PARAM_set_uint(p, md)) {
-        ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
-        return 0;
-    }
-    p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_FLAGS);
-    if (p != NULL && !OSSL_PARAM_set_ulong(p, flags)) {
-        ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
-        return 0;
-    }
-    p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_KEYLEN);
-    if (p != NULL && !OSSL_PARAM_set_size_t(p, kbits / 8)) {
-        ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
-        return 0;
-    }
-    p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_BLOCK_SIZE);
-    if (p != NULL && !OSSL_PARAM_set_size_t(p, blkbits / 8)) {
-        ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
-        return 0;
-    }
-    p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IVLEN);
-    if (p != NULL && !OSSL_PARAM_set_size_t(p, ivbits / 8)) {
-        ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
-        return 0;
-    }
-    return 1;
-}
-
-CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_START(cipher_generic)
-CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_END(cipher_generic)
-
-CIPHER_DEFAULT_SETTABLE_CTX_PARAMS_START(cipher_generic)
-CIPHER_DEFAULT_SETTABLE_CTX_PARAMS_END(cipher_generic)
-
-/*
- * Variable key length cipher functions for OSSL_PARAM settables
- */
-
-int cipher_var_keylen_set_ctx_params(void *vctx, const OSSL_PARAM params[])
-{
-    PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
-    const OSSL_PARAM *p;
-
-    if (!cipher_generic_set_ctx_params(vctx, params))
-        return 0;
-    p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_KEYLEN);
-    if (p != NULL) {
-        size_t keylen;
-
-        if (!OSSL_PARAM_get_size_t(p, &keylen)) {
-            ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
-            return 0;
-        }
-        ctx->keylen = keylen;
-    }
-    return 1;
-}
-
-CIPHER_DEFAULT_SETTABLE_CTX_PARAMS_START(cipher_var_keylen)
-OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL),
-CIPHER_DEFAULT_SETTABLE_CTX_PARAMS_END(cipher_var_keylen)
-
-/*-
- * AEAD cipher functions for OSSL_PARAM gettables and settables
- */
-static const OSSL_PARAM cipher_aead_known_gettable_ctx_params[] = {
-    OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL),
-    OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_IVLEN, NULL),
-    OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_AEAD_TAGLEN, NULL),
-    OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_IV, NULL, 0),
-    OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, NULL, 0),
-    OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_AEAD_TLS1_AAD_PAD, NULL),
-    OSSL_PARAM_END
-};
-const OSSL_PARAM *cipher_aead_gettable_ctx_params(void)
-{
-    return cipher_aead_known_gettable_ctx_params;
-}
-
-static const OSSL_PARAM cipher_aead_known_settable_ctx_params[] = {
-    OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_AEAD_IVLEN, NULL),
-    OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, NULL, 0),
-    OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TLS1_AAD, NULL, 0),
-    OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TLS1_IV_FIXED, NULL, 0),
-    OSSL_PARAM_END
-};
-const OSSL_PARAM *cipher_aead_settable_ctx_params(void)
-{
-    return cipher_aead_known_settable_ctx_params;
-}
-
-static int cipher_generic_init_internal(PROV_CIPHER_CTX *ctx,
-                                        const unsigned char *key, size_t keylen,
-                                        const unsigned char *iv, size_t ivlen,
-                                        int enc)
-{
-    ctx->enc = enc ? 1 : 0;
-
-    if (iv != NULL && ctx->mode != EVP_CIPH_ECB_MODE) {
-        if (!cipher_generic_initiv(ctx, iv, ivlen))
-            return 0;
-    }
-    if (key != NULL) {
-        if ((ctx->flags & EVP_CIPH_VARIABLE_LENGTH) == 0) {
-            if (keylen != ctx->keylen) {
-                ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEYLEN);
-                return 0;
-            }
-        } else {
-            ctx->keylen = keylen;
-        }
-        return ctx->hw->init(ctx, key, ctx->keylen);
-    }
-    return 1;
-}
-
-int cipher_generic_einit(void *vctx, const unsigned char *key, size_t keylen,
-                         const unsigned char *iv, size_t ivlen)
-{
-    return cipher_generic_init_internal((PROV_CIPHER_CTX *)vctx, key, keylen,
-                                        iv, ivlen, 1);
-}
-
-int cipher_generic_dinit(void *vctx, const unsigned char *key, size_t keylen,
-                         const unsigned char *iv, size_t ivlen)
-{
-    return cipher_generic_init_internal((PROV_CIPHER_CTX *)vctx, key, keylen,
-                                        iv, ivlen, 0);
-}
-
-int cipher_generic_block_update(void *vctx, unsigned char *out, size_t *outl,
-                                size_t outsize, const unsigned char *in,
-                                size_t inl)
-{
-    size_t outlint = 0;
-    PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
-    size_t blksz = ctx->blocksize;
-    size_t nextblocks = fillblock(ctx->buf, &ctx->bufsz, blksz, &in, &inl);
-
-    /*
-     * If we're decrypting and we end an update on a block boundary we hold
-     * the last block back in case this is the last update call and the last
-     * block is padded.
-     */
-    if (ctx->bufsz == blksz && (ctx->enc || inl > 0 || !ctx->pad)) {
-        if (outsize < blksz) {
-            ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
-            return 0;
-        }
-        if (!ctx->hw->cipher(ctx, out, ctx->buf, blksz)) {
-            ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);
-            return 0;
-        }
-        ctx->bufsz = 0;
-        outlint = blksz;
-        out += blksz;
-    }
-    if (nextblocks > 0) {
-        if (!ctx->enc && ctx->pad && nextblocks == inl) {
-            if (!ossl_assert(inl >= blksz)) {
-                ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
-                return 0;
-            }
-            nextblocks -= blksz;
-        }
-        outlint += nextblocks;
-        if (outsize < outlint) {
-            ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
-            return 0;
-        }
-    }
-    if (nextblocks > 0) {
-        if (!ctx->hw->cipher(ctx, out, in, nextblocks)) {
-            ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);
-            return 0;
-        }
-        in += nextblocks;
-        inl -= nextblocks;
-    }
-    if (!trailingdata(ctx->buf, &ctx->bufsz, blksz, &in, &inl)) {
-        /* ERR_raise already called */
-        return 0;
-    }
-
-    *outl = outlint;
-    return inl == 0;
-}
-
-int cipher_generic_block_final(void *vctx, unsigned char *out, size_t *outl,
-                               size_t outsize)
-{
-    PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
-    size_t blksz = ctx->blocksize;
-
-    if (ctx->enc) {
-        if (ctx->pad) {
-            padblock(ctx->buf, &ctx->bufsz, blksz);
-        } else if (ctx->bufsz == 0) {
-            *outl = 0;
-            return 1;
-        } else if (ctx->bufsz != blksz) {
-            ERR_raise(ERR_LIB_PROV, PROV_R_WRONG_FINAL_BLOCK_LENGTH);
-            return 0;
-        }
-
-        if (outsize < blksz) {
-            ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
-            return 0;
-        }
-        if (!ctx->hw->cipher(ctx, out, ctx->buf, blksz)) {
-            ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);
-            return 0;
-        }
-        ctx->bufsz = 0;
-        *outl = blksz;
-        return 1;
-    }
-
-    /* Decrypting */
-    if (ctx->bufsz != blksz) {
-        if (ctx->bufsz == 0 && !ctx->pad) {
-            *outl = 0;
-            return 1;
-        }
-        ERR_raise(ERR_LIB_PROV, PROV_R_WRONG_FINAL_BLOCK_LENGTH);
-        return 0;
-    }
-
-    if (!ctx->hw->cipher(ctx, ctx->buf, ctx->buf, blksz)) {
-        ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);
-        return 0;
-    }
-
-    if (ctx->pad && !unpadblock(ctx->buf, &ctx->bufsz, blksz)) {
-        /* ERR_raise already called */
-        return 0;
-    }
-
-    if (outsize < ctx->bufsz) {
-        ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
-        return 0;
-    }
-    memcpy(out, ctx->buf, ctx->bufsz);
-    *outl = ctx->bufsz;
-    ctx->bufsz = 0;
-    return 1;
-}
-
-int cipher_generic_stream_update(void *vctx, unsigned char *out, size_t *outl,
-                                 size_t outsize, const unsigned char *in,
-                                 size_t inl)
-{
-    PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
-
-    if (inl == 0) {
-        *outl = 0;
-        return 1;
-    }
-
-    if (outsize < inl) {
-        ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
-        return 0;
-    }
-
-    if (!ctx->hw->cipher(ctx, out, in, inl)) {
-        ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);
-        return 0;
-    }
-
-    *outl = inl;
-    return 1;
-}
-int cipher_generic_stream_final(void *vctx, unsigned char *out, size_t *outl,
-                                size_t outsize)
-{
-    *outl = 0;
-    return 1;
-}
-
-int cipher_generic_cipher(void *vctx,
-                          unsigned char *out, size_t *outl, size_t outsize,
-                          const unsigned char *in, size_t inl)
-{
-    PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
-
-    if (outsize < inl) {
-        ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
-        return 0;
-    }
-
-    if (!ctx->hw->cipher(ctx, out, in, inl)) {
-        ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);
-        return 0;
-    }
-
-    *outl = inl;
-    return 1;
-}
-
-int cipher_generic_get_ctx_params(void *vctx, OSSL_PARAM params[])
-{
-    PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
-    OSSL_PARAM *p;
-
-    p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IVLEN);
-    if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->ivlen)) {
-        ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
-        return 0;
-    }
-    p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_PADDING);
-    if (p != NULL && !OSSL_PARAM_set_uint(p, ctx->pad)) {
-        ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
-        return 0;
-    }
-    p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IV);
-    if (p != NULL
-        && !OSSL_PARAM_set_octet_ptr(p, &ctx->oiv, ctx->ivlen)
-        && !OSSL_PARAM_set_octet_string(p, &ctx->oiv, ctx->ivlen)) {
-        ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
-        return 0;
-    }
-    p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_NUM);
-    if (p != NULL && !OSSL_PARAM_set_uint(p, ctx->num)) {
-        ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
-        return 0;
-    }
-    p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_KEYLEN);
-    if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->keylen)) {
-        ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
-        return 0;
-    }
-    return 1;
-}
-
-int cipher_generic_set_ctx_params(void *vctx, const OSSL_PARAM params[])
-{
-    PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
-    const OSSL_PARAM *p;
-
-    p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_PADDING);
-    if (p != NULL) {
-        unsigned int pad;
-
-        if (!OSSL_PARAM_get_uint(p, &pad)) {
-            ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
-            return 0;
-        }
-        ctx->pad = pad ? 1 : 0;
-    }
-    p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_NUM);
-    if (p != NULL) {
-        unsigned int num;
-
-        if (!OSSL_PARAM_get_uint(p, &num)) {
-            ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
-            return 0;
-        }
-        ctx->num = num;
-    }
-    return 1;
-}
-
-int cipher_generic_initiv(PROV_CIPHER_CTX *ctx, const unsigned char *iv,
-                          size_t ivlen)
-{
-    if (ivlen != ctx->ivlen
-        || ivlen > sizeof(ctx->iv)) {
-        ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IVLEN);
-        return 0;
-    }
-    ctx->iv_set = 1;
-    memcpy(ctx->iv, iv, ivlen);
-    memcpy(ctx->oiv, iv, ivlen);
-    return 1;
-}
-
-void cipher_generic_initkey(void *vctx, size_t kbits, size_t blkbits,
-                            size_t ivbits, unsigned int mode, uint64_t flags,
-                            const PROV_CIPHER_HW *hw, void *provctx)
-{
-    PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
-
-    ctx->flags = flags;
-    ctx->pad = 1;
-    ctx->keylen = ((kbits) / 8);
-    ctx->ivlen = ((ivbits) / 8);
-    ctx->hw = hw;
-    ctx->mode = mode;
-    ctx->blocksize = blkbits / 8;
-    if (provctx != NULL)
-        ctx->libctx = PROV_LIBRARY_CONTEXT_OF(provctx); /* used for rand */
-}
diff --git a/providers/common/ciphers/cipher_common_hw.c b/providers/common/ciphers/cipher_common_hw.c
deleted file mode 100644 (file)
index f1c466e..0000000
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the Apache License 2.0 (the "License").  You may not use
- * this file except in compliance with the License.  You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include "prov/ciphercommon.h"
-
-/*-
- * The generic cipher functions for cipher modes cbc, ecb, ofb, cfb and ctr.
- * Used if there is no special hardware implementations.
- */
-int cipher_hw_generic_cbc(PROV_CIPHER_CTX *dat, unsigned char *out,
-                          const unsigned char *in, size_t len)
-{
-    if (dat->stream.cbc)
-        (*dat->stream.cbc) (in, out, len, dat->ks, dat->iv, dat->enc);
-    else if (dat->enc)
-        CRYPTO_cbc128_encrypt(in, out, len, dat->ks, dat->iv, dat->block);
-    else
-        CRYPTO_cbc128_decrypt(in, out, len, dat->ks, dat->iv, dat->block);
-
-    return 1;
-}
-
-int cipher_hw_generic_ecb(PROV_CIPHER_CTX *dat, unsigned char *out,
-                          const unsigned char *in, size_t len)
-{
-    size_t i, bl = dat->blocksize;
-
-    if (len < bl)
-        return 1;
-
-    for (i = 0, len -= bl; i <= len; i += bl)
-        (*dat->block) (in + i, out + i, dat->ks);
-
-    return 1;
-}
-
-int cipher_hw_generic_ofb128(PROV_CIPHER_CTX *dat, unsigned char *out,
-                             const unsigned char *in, size_t len)
-{
-    int num = dat->num;
-
-    CRYPTO_ofb128_encrypt(in, out, len, dat->ks, dat->iv, &num, dat->block);
-    dat->num = num;
-
-    return 1;
-}
-
-int cipher_hw_generic_cfb128(PROV_CIPHER_CTX *dat, unsigned char *out,
-                             const unsigned char *in, size_t len)
-{
-    int num = dat->num;
-
-    CRYPTO_cfb128_encrypt(in, out, len, dat->ks, dat->iv, &num, dat->enc,
-                          dat->block);
-    dat->num = num;
-
-    return 1;
-}
-
-int cipher_hw_generic_cfb8(PROV_CIPHER_CTX *dat, unsigned char *out,
-                           const unsigned char *in, size_t len)
-{
-    int num = dat->num;
-
-    CRYPTO_cfb128_8_encrypt(in, out, len, dat->ks, dat->iv, &num, dat->enc,
-                            dat->block);
-    dat->num = num;
-
-    return 1;
-}
-
-int cipher_hw_generic_cfb1(PROV_CIPHER_CTX *dat, unsigned char *out,
-                           const unsigned char *in, size_t len)
-{
-    int num = dat->num;
-
-    if ((dat->flags & EVP_CIPH_FLAG_LENGTH_BITS) != 0) {
-        CRYPTO_cfb128_1_encrypt(in, out, len, dat->ks, dat->iv, &num,
-                                dat->enc, dat->block);
-        dat->num = num;
-        return 1;
-    }
-
-    while (len >= MAXBITCHUNK) {
-        CRYPTO_cfb128_1_encrypt(in, out, MAXBITCHUNK * 8, dat->ks,
-                                dat->iv, &num, dat->enc, dat->block);
-        len -= MAXBITCHUNK;
-        out += MAXBITCHUNK;
-        in  += MAXBITCHUNK;
-    }
-    if (len)
-        CRYPTO_cfb128_1_encrypt(in, out, len * 8, dat->ks, dat->iv, &num,
-                                dat->enc, dat->block);
-
-    dat->num = num;
-
-    return 1;
-}
-
-int cipher_hw_generic_ctr(PROV_CIPHER_CTX *dat, unsigned char *out,
-                          const unsigned char *in, size_t len)
-{
-    unsigned int num = dat->num;
-
-    if (dat->stream.ctr)
-        CRYPTO_ctr128_encrypt_ctr32(in, out, len, dat->ks, dat->iv, dat->buf,
-                                    &num, dat->stream.ctr);
-    else
-        CRYPTO_ctr128_encrypt(in, out, len, dat->ks, dat->iv, dat->buf,
-                              &num, dat->block);
-    dat->num = num;
-
-    return 1;
-}
-
-/*-
- * The chunked cipher functions for cipher modes cbc, ecb, ofb, cfb and ctr.
- * Used if there is no special hardware implementations.
- */
-
-int cipher_hw_chunked_cbc(PROV_CIPHER_CTX *ctx, unsigned char *out,
-                          const unsigned char *in, size_t inl)
-{
-    while (inl >= MAXCHUNK) {
-        cipher_hw_generic_cbc(ctx, out, in, MAXCHUNK);
-        inl -= MAXCHUNK;
-        in  += MAXCHUNK;
-        out += MAXCHUNK;
-    }
-    if (inl > 0)
-        cipher_hw_generic_cbc(ctx, out, in, inl);
-    return 1;
-}
-
-int cipher_hw_chunked_cfb8(PROV_CIPHER_CTX *ctx, unsigned char *out,
-                           const unsigned char *in, size_t inl)
-{
-    size_t chunk = MAXCHUNK;
-
-    if (inl < chunk)
-        chunk = inl;
-    while (inl > 0 && inl >= chunk) {
-        cipher_hw_generic_cfb8(ctx, out, in, inl);
-        inl -= chunk;
-        in += chunk;
-        out += chunk;
-        if (inl < chunk)
-            chunk = inl;
-    }
-    return 1;
-}
-
-int cipher_hw_chunked_cfb128(PROV_CIPHER_CTX *ctx, unsigned char *out,
-                             const unsigned char *in, size_t inl)
-{
-    size_t chunk = MAXCHUNK;
-
-    if (inl < chunk)
-        chunk = inl;
-    while (inl > 0 && inl >= chunk) {
-        cipher_hw_generic_cfb128(ctx, out, in, inl);
-        inl -= chunk;
-        in += chunk;
-        out += chunk;
-        if (inl < chunk)
-            chunk = inl;
-    }
-    return 1;
-}
-
-int cipher_hw_chunked_ofb128(PROV_CIPHER_CTX *ctx, unsigned char *out,
-                             const unsigned char *in, size_t inl)
-{
-    while (inl >= MAXCHUNK) {
-        cipher_hw_generic_ofb128(ctx, out, in, MAXCHUNK);
-        inl -= MAXCHUNK;
-        in  += MAXCHUNK;
-        out += MAXCHUNK;
-    }
-    if (inl > 0)
-        cipher_hw_generic_ofb128(ctx, out, in, inl);
-    return 1;
-}
diff --git a/providers/common/ciphers/cipher_gcm.c b/providers/common/ciphers/cipher_gcm.c
deleted file mode 100644 (file)
index 619d4f6..0000000
+++ /dev/null
@@ -1,495 +0,0 @@
-/*
- * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the Apache License 2.0 (the "License").  You may not use
- * this file except in compliance with the License.  You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-/* Dispatch functions for gcm mode */
-
-#include "prov/ciphercommon.h"
-#include "prov/cipher_gcm.h"
-#include "prov/providercommonerr.h"
-#include "crypto/rand.h"
-#include "prov/provider_ctx.h"
-
-static int gcm_tls_init(PROV_GCM_CTX *dat, unsigned char *aad, size_t aad_len);
-static int gcm_tls_iv_set_fixed(PROV_GCM_CTX *ctx, unsigned char *iv,
-                                size_t len);
-static int gcm_tls_cipher(PROV_GCM_CTX *ctx, unsigned char *out, size_t *padlen,
-                          const unsigned char *in, size_t len);
-static int gcm_cipher_internal(PROV_GCM_CTX *ctx, unsigned char *out,
-                               size_t *padlen, const unsigned char *in,
-                               size_t len);
-
-void gcm_initctx(void *provctx, PROV_GCM_CTX *ctx, size_t keybits,
-                 const PROV_GCM_HW *hw, size_t ivlen_min)
-{
-    ctx->pad = 1;
-    ctx->mode = EVP_CIPH_GCM_MODE;
-    ctx->taglen = UNINITIALISED_SIZET;
-    ctx->tls_aad_len = UNINITIALISED_SIZET;
-    ctx->ivlen_min = ivlen_min;
-    ctx->ivlen = (EVP_GCM_TLS_FIXED_IV_LEN + EVP_GCM_TLS_EXPLICIT_IV_LEN);
-    ctx->keylen = keybits / 8;
-    ctx->hw = hw;
-    ctx->libctx = PROV_LIBRARY_CONTEXT_OF(provctx);
-}
-
-static int gcm_init(void *vctx, const unsigned char *key, size_t keylen,
-                    const unsigned char *iv, size_t ivlen, int enc)
-{
-    PROV_GCM_CTX *ctx = (PROV_GCM_CTX *)vctx;
-
-    ctx->enc = enc;
-
-    if (iv != NULL) {
-        if (ivlen < ctx->ivlen_min || ivlen > sizeof(ctx->iv)) {
-            ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH);
-            return 0;
-        }
-        ctx->ivlen = ivlen;
-        memcpy(ctx->iv, iv, ivlen);
-        ctx->iv_state = IV_STATE_BUFFERED;
-    }
-
-    if (key != NULL) {
-        if (keylen != ctx->keylen) {
-            ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
-            return 0;
-        }
-        return ctx->hw->setkey(ctx, key, ctx->keylen);
-    }
-    return 1;
-}
-
-int gcm_einit(void *vctx, const unsigned char *key, size_t keylen,
-              const unsigned char *iv, size_t ivlen)
-{
-    return gcm_init(vctx, key, keylen, iv, ivlen, 1);
-}
-
-int gcm_dinit(void *vctx, const unsigned char *key, size_t keylen,
-              const unsigned char *iv, size_t ivlen)
-{
-    return gcm_init(vctx, key, keylen, iv, ivlen, 0);
-}
-
-int gcm_get_ctx_params(void *vctx, OSSL_PARAM params[])
-{
-    PROV_GCM_CTX *ctx = (PROV_GCM_CTX *)vctx;
-    OSSL_PARAM *p;
-    size_t sz;
-
-    p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IVLEN);
-    if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->ivlen)) {
-        ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
-        return 0;
-    }
-    p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_KEYLEN);
-    if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->keylen)) {
-        ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
-        return 0;
-    }
-    p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TAGLEN);
-    if (p != NULL) {
-        size_t taglen = (ctx->taglen != UNINITIALISED_SIZET) ? ctx->taglen :
-                         GCM_TAG_MAX_SIZE;
-
-        if (!OSSL_PARAM_set_size_t(p, taglen)) {
-            ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
-            return 0;
-        }
-    }
-
-    p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IV);
-    if (p != NULL) {
-        if (ctx->iv_gen != 1 && ctx->iv_gen_rand != 1)
-            return 0;
-        if (ctx->ivlen != p->data_size) {
-            ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH);
-            return 0;
-        }
-        if (!OSSL_PARAM_set_octet_string(p, ctx->iv, ctx->ivlen)) {
-            ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
-            return 0;
-        }
-    }
-
-    p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TLS1_AAD_PAD);
-    if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->tls_aad_pad_sz)) {
-        ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
-        return 0;
-    }
-    p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TAG);
-    if (p != NULL) {
-        sz = p->data_size;
-        if (sz == 0
-            || sz > EVP_GCM_TLS_TAG_LEN
-            || !ctx->enc
-            || ctx->taglen == UNINITIALISED_SIZET) {
-            ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_TAG);
-            return 0;
-        }
-        if (!OSSL_PARAM_set_octet_string(p, ctx->buf, sz)) {
-            ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
-            return 0;
-        }
-    }
-
-    return 1;
-}
-
-int gcm_set_ctx_params(void *vctx, const OSSL_PARAM params[])
-{
-    PROV_GCM_CTX *ctx = (PROV_GCM_CTX *)vctx;
-    const OSSL_PARAM *p;
-    size_t sz;
-    void *vp;
-
-    p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TAG);
-    if (p != NULL) {
-        vp = ctx->buf;
-        if (!OSSL_PARAM_get_octet_string(p, &vp, EVP_GCM_TLS_TAG_LEN, &sz)) {
-            ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
-            return 0;
-        }
-        if (sz == 0 || ctx->enc) {
-            ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_TAG);
-            return 0;
-        }
-        ctx->taglen = sz;
-    }
-
-    p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_IVLEN);
-    if (p != NULL) {
-        if (!OSSL_PARAM_get_size_t(p, &sz)) {
-            ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
-            return 0;
-        }
-        if (sz == 0 || sz > sizeof(ctx->iv)) {
-            ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH);
-            return 0;
-        }
-        ctx->ivlen = sz;
-    }
-
-    p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TLS1_AAD);
-    if (p != NULL) {
-        if (p->data_type != OSSL_PARAM_OCTET_STRING) {
-            ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
-            return 0;
-        }
-        sz = gcm_tls_init(ctx, p->data, p->data_size);
-        if (sz == 0) {
-            ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_AAD);
-            return 0;
-        }
-        ctx->tls_aad_pad_sz = sz;
-    }
-
-    p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TLS1_IV_FIXED);
-    if (p != NULL) {
-        if (p->data_type != OSSL_PARAM_OCTET_STRING) {
-            ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
-            return 0;
-        }
-        if (gcm_tls_iv_set_fixed(ctx, p->data, p->data_size) == 0) {
-            ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
-            return 0;
-        }
-    }
-
-    return 1;
-}
-
-int gcm_stream_update(void *vctx, unsigned char *out, size_t *outl,
-                      size_t outsize, const unsigned char *in, size_t inl)
-{
-    PROV_GCM_CTX *ctx = (PROV_GCM_CTX *)vctx;
-
-    if (inl == 0) {
-        *outl = 0;
-        return 1;
-    }
-
-    if (outsize < inl) {
-        ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
-        return -1;
-    }
-
-    if (gcm_cipher_internal(ctx, out, outl, in, inl) <= 0) {
-        ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);
-        return -1;
-    }
-    return 1;
-}
-
-int gcm_stream_final(void *vctx, unsigned char *out, size_t *outl,
-                     size_t outsize)
-{
-    PROV_GCM_CTX *ctx = (PROV_GCM_CTX *)vctx;
-    int i;
-
-    i = gcm_cipher_internal(ctx, out, outl, NULL, 0);
-    if (i <= 0)
-        return 0;
-
-    *outl = 0;
-    return 1;
-}
-
-int gcm_cipher(void *vctx,
-               unsigned char *out, size_t *outl, size_t outsize,
-               const unsigned char *in, size_t inl)
-{
-    PROV_GCM_CTX *ctx = (PROV_GCM_CTX *)vctx;
-
-    if (outsize < inl) {
-        ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
-        return 0;
-    }
-
-    if (gcm_cipher_internal(ctx, out, outl, in, inl) <= 0)
-        return 0;
-
-    *outl = inl;
-    return 1;
-}
-
-/*
- * See SP800-38D (GCM) Section 8 "Uniqueness requirement on IVS and keys"
- *
- * See also 8.2.2 RBG-based construction.
- * Random construction consists of a free field (which can be NULL) and a
- * random field which will use a DRBG that can return at least 96 bits of
- * entropy strength. (The DRBG must be seeded by the FIPS module).
- */
-static int gcm_iv_generate(PROV_GCM_CTX *ctx, int offset)
-{
-    int sz = ctx->ivlen - offset;
-
-    /* Must be at least 96 bits */
-    if (sz <= 0 || ctx->ivlen < GCM_IV_DEFAULT_SIZE)
-        return 0;
-
-    /* Use DRBG to generate random iv */
-    if (rand_bytes_ex(ctx->libctx, ctx->iv + offset, sz) <= 0)
-        return 0;
-    ctx->iv_state = IV_STATE_BUFFERED;
-    ctx->iv_gen_rand = 1;
-    return 1;
-}
-
-static int gcm_cipher_internal(PROV_GCM_CTX *ctx, unsigned char *out,
-                               size_t *padlen, const unsigned char *in,
-                               size_t len)
-{
-    size_t olen = 0;
-    int rv = 0;
-    const PROV_GCM_HW *hw = ctx->hw;
-
-    if (ctx->tls_aad_len != UNINITIALISED_SIZET)
-        return gcm_tls_cipher(ctx, out, padlen, in, len);
-
-    if (!ctx->key_set || ctx->iv_state == IV_STATE_FINISHED)
-        goto err;
-
-    /*
-     * FIPS requires generation of AES-GCM IV's inside the FIPS module.
-     * The IV can still be set externally (the security policy will state that
-     * this is not FIPS compliant). There are some applications
-     * where setting the IV externally is the only option available.
-     */
-    if (ctx->iv_state == IV_STATE_UNINITIALISED) {
-        if (!ctx->enc || !gcm_iv_generate(ctx, 0))
-            goto err;
-    }
-
-    if (ctx->iv_state == IV_STATE_BUFFERED) {
-        if (!hw->setiv(ctx, ctx->iv, ctx->ivlen))
-            goto err;
-        ctx->iv_state = IV_STATE_COPIED;
-    }
-
-    if (in != NULL) {
-        /*  The input is AAD if out is NULL */
-        if (out == NULL) {
-            if (!hw->aadupdate(ctx, in, len))
-                goto err;
-        } else {
-            /* The input is ciphertext OR plaintext */
-            if (!hw->cipherupdate(ctx, in, len, out))
-                goto err;
-        }
-    } else {
-        /* The tag must be set before actually decrypting data */
-        if (!ctx->enc && ctx->taglen == UNINITIALISED_SIZET)
-            goto err;
-        if (!hw->cipherfinal(ctx, ctx->buf))
-            goto err;
-        ctx->iv_state = IV_STATE_FINISHED; /* Don't reuse the IV */
-        goto finish;
-    }
-    olen = len;
-finish:
-    rv = 1;
-err:
-    *padlen = olen;
-    return rv;
-}
-
-static int gcm_tls_init(PROV_GCM_CTX *dat, unsigned char *aad, size_t aad_len)
-{
-    unsigned char *buf;
-    size_t len;
-
-    if (aad_len != EVP_AEAD_TLS1_AAD_LEN)
-       return 0;
-
-    /* Save the aad for later use. */
-    buf = dat->buf;
-    memcpy(buf, aad, aad_len);
-    dat->tls_aad_len = aad_len;
-    dat->tls_enc_records = 0;
-
-    len = buf[aad_len - 2] << 8 | buf[aad_len - 1];
-    /* Correct length for explicit iv. */
-    if (len < EVP_GCM_TLS_EXPLICIT_IV_LEN)
-        return 0;
-    len -= EVP_GCM_TLS_EXPLICIT_IV_LEN;
-
-    /* If decrypting correct for tag too. */
-    if (!dat->enc) {
-        if (len < EVP_GCM_TLS_TAG_LEN)
-            return 0;
-        len -= EVP_GCM_TLS_TAG_LEN;
-    }
-    buf[aad_len - 2] = (unsigned char)(len >> 8);
-    buf[aad_len - 1] = (unsigned char)(len & 0xff);
-    /* Extra padding: tag appended to record. */
-    return EVP_GCM_TLS_TAG_LEN;
-}
-
-static int gcm_tls_iv_set_fixed(PROV_GCM_CTX *ctx, unsigned char *iv,
-                                size_t len)
-{
-    /* Special case: -1 length restores whole IV */
-    if (len == (size_t)-1) {
-        memcpy(ctx->iv, iv, ctx->ivlen);
-        ctx->iv_gen = 1;
-        ctx->iv_state = IV_STATE_BUFFERED;
-        return 1;
-    }
-    /* Fixed field must be at least 4 bytes and invocation field at least 8 */
-    if ((len < EVP_GCM_TLS_FIXED_IV_LEN)
-        || (ctx->ivlen - (int)len) < EVP_GCM_TLS_EXPLICIT_IV_LEN)
-            return 0;
-    if (len > 0)
-        memcpy(ctx->iv, iv, len);
-    if (ctx->enc
-        && rand_bytes_ex(ctx->libctx, ctx->iv + len, ctx->ivlen - len) <= 0)
-            return 0;
-    ctx->iv_gen = 1;
-    ctx->iv_state = IV_STATE_BUFFERED;
-    return 1;
-}
-
-/* increment counter (64-bit int) by 1 */
-static void ctr64_inc(unsigned char *counter)
-{
-    int n = 8;
-    unsigned char c;
-
-    do {
-        --n;
-        c = counter[n];
-        ++c;
-        counter[n] = c;
-        if (c > 0)
-            return;
-    } while (n > 0);
-}
-
-/*
- * Handle TLS GCM packet format. This consists of the last portion of the IV
- * followed by the payload and finally the tag. On encrypt generate IV,
- * encrypt payload and write the tag. On verify retrieve IV, decrypt payload
- * and verify tag.
- */
-static int gcm_tls_cipher(PROV_GCM_CTX *ctx, unsigned char *out, size_t *padlen,
-                          const unsigned char *in, size_t len)
-{
-    int rv = 0;
-    size_t arg = EVP_GCM_TLS_EXPLICIT_IV_LEN;
-    size_t plen = 0;
-    unsigned char *tag = NULL;
-
-    if (!ctx->key_set)
-        goto err;
-
-    /* Encrypt/decrypt must be performed in place */
-    if (out != in || len < (EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN))
-        goto err;
-
-    /*
-     * Check for too many keys as per FIPS 140-2 IG A.5 "Key/IV Pair Uniqueness
-     * Requirements from SP 800-38D".  The requirements is for one party to the
-     * communication to fail after 2^64 - 1 keys.  We do this on the encrypting
-     * side only.
-     */
-    if (ctx->enc && ++ctx->tls_enc_records == 0) {
-        ERR_raise(ERR_LIB_PROV, EVP_R_TOO_MANY_RECORDS);
-        goto err;
-    }
-
-    if (ctx->iv_gen == 0)
-        goto err;
-    /*
-     * Set IV from start of buffer or generate IV and write to start of
-     * buffer.
-     */
-    if (ctx->enc) {
-        if (!ctx->hw->setiv(ctx, ctx->iv, ctx->ivlen))
-            goto err;
-        if (arg > ctx->ivlen)
-            arg = ctx->ivlen;
-        memcpy(out, ctx->iv + ctx->ivlen - arg, arg);
-        /*
-         * Invocation field will be at least 8 bytes in size and so no need
-         * to check wrap around or increment more than last 8 bytes.
-         */
-        ctr64_inc(ctx->iv + ctx->ivlen - 8);
-    } else {
-        memcpy(ctx->iv + ctx->ivlen - arg, out, arg);
-        if (!ctx->hw->setiv(ctx, ctx->iv, ctx->ivlen))
-            goto err;
-    }
-    ctx->iv_state = IV_STATE_COPIED;
-
-    /* Fix buffer and length to point to payload */
-    in += EVP_GCM_TLS_EXPLICIT_IV_LEN;
-    out += EVP_GCM_TLS_EXPLICIT_IV_LEN;
-    len -= EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN;
-
-    tag = ctx->enc ? out + len : (unsigned char *)in + len;
-    if (!ctx->hw->oneshot(ctx, ctx->buf, ctx->tls_aad_len, in, len, out, tag,
-                          EVP_GCM_TLS_TAG_LEN)) {
-        if (!ctx->enc)
-            OPENSSL_cleanse(out, len);
-        goto err;
-    }
-    if (ctx->enc)
-        plen =  len + EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN;
-    else
-        plen = len;
-
-    rv = 1;
-err:
-    ctx->iv_state = IV_STATE_FINISHED;
-    ctx->tls_aad_len = UNINITIALISED_SIZET;
-    *padlen = plen;
-    return rv;
-}
diff --git a/providers/common/ciphers/cipher_gcm_hw.c b/providers/common/ciphers/cipher_gcm_hw.c
deleted file mode 100644 (file)
index 09e3c27..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright 2001-2019 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the Apache License 2.0 (the "License").  You may not use
- * this file except in compliance with the License.  You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include "prov/ciphercommon.h"
-#include "prov/cipher_gcm.h"
-
-
-int gcm_setiv(PROV_GCM_CTX *ctx, const unsigned char *iv, size_t ivlen)
-{
-    CRYPTO_gcm128_setiv(&ctx->gcm, iv, ivlen);
-    return 1;
-}
-
-int gcm_aad_update(PROV_GCM_CTX *ctx, const unsigned char *aad, size_t aad_len)
-{
-    return CRYPTO_gcm128_aad(&ctx->gcm, aad, aad_len) == 0;
-}
-
-int gcm_cipher_update(PROV_GCM_CTX *ctx, const unsigned char *in,
-                      size_t len, unsigned char *out)
-{
-    if (ctx->enc) {
-        if (ctx->ctr != NULL) {
-#if defined(AES_GCM_ASM)
-            size_t bulk = 0;
-
-            if (len >= 32 && AES_GCM_ASM(ctx)) {
-                size_t res = (16 - ctx->gcm.mres) % 16;
-
-                if (CRYPTO_gcm128_encrypt(&ctx->gcm, in, out, res))
-                    return 0;
-                bulk = aesni_gcm_encrypt(in + res, out + res, len - res,
-                                         ctx->gcm.key,
-                                         ctx->gcm.Yi.c, ctx->gcm.Xi.u);
-                ctx->gcm.len.u[1] += bulk;
-                bulk += res;
-            }
-            if (CRYPTO_gcm128_encrypt_ctr32(&ctx->gcm, in + bulk, out + bulk,
-                                            len - bulk, ctx->ctr))
-                return 0;
-#else
-            if (CRYPTO_gcm128_encrypt_ctr32(&ctx->gcm, in, out, len, ctx->ctr))
-                return 0;
-#endif /* AES_GCM_ASM */
-        } else {
-            if (CRYPTO_gcm128_encrypt(&ctx->gcm, in, out, len))
-                return 0;
-        }
-    } else {
-        if (ctx->ctr != NULL) {
-#if defined(AES_GCM_ASM)
-            size_t bulk = 0;
-
-            if (len >= 16 && AES_GCM_ASM(ctx)) {
-                size_t res = (16 - ctx->gcm.mres) % 16;
-
-                if (CRYPTO_gcm128_decrypt(&ctx->gcm, in, out, res))
-                    return -1;
-
-                bulk = aesni_gcm_decrypt(in + res, out + res, len - res,
-                                         ctx->gcm.key,
-                                         ctx->gcm.Yi.c, ctx->gcm.Xi.u);
-                ctx->gcm.len.u[1] += bulk;
-                bulk += res;
-            }
-            if (CRYPTO_gcm128_decrypt_ctr32(&ctx->gcm, in + bulk, out + bulk,
-                                            len - bulk, ctx->ctr))
-                return 0;
-#else
-            if (CRYPTO_gcm128_decrypt_ctr32(&ctx->gcm, in, out, len, ctx->ctr))
-                return 0;
-#endif /* AES_GCM_ASM */
-        } else {
-            if (CRYPTO_gcm128_decrypt(&ctx->gcm, in, out, len))
-                return 0;
-        }
-    }
-    return 1;
-}
-
-int gcm_cipher_final(PROV_GCM_CTX *ctx, unsigned char *tag)
-{
-    if (ctx->enc) {
-        CRYPTO_gcm128_tag(&ctx->gcm, tag, GCM_TAG_MAX_SIZE);
-        ctx->taglen = GCM_TAG_MAX_SIZE;
-    } else {
-        if (CRYPTO_gcm128_finish(&ctx->gcm, tag, ctx->taglen) != 0)
-            return 0;
-    }
-    return 1;
-}
-
-int gcm_one_shot(PROV_GCM_CTX *ctx, unsigned char *aad, size_t aad_len,
-                 const unsigned char *in, size_t in_len,
-                 unsigned char *out, unsigned char *tag, size_t tag_len)
-{
-    int ret = 0;
-
-    /* Use saved AAD */
-    if (!ctx->hw->aadupdate(ctx, aad, aad_len))
-        goto err;
-    if (!ctx->hw->cipherupdate(ctx, in, in_len, out))
-        goto err;
-    ctx->taglen = GCM_TAG_MAX_SIZE;
-    if (!ctx->hw->cipherfinal(ctx, tag))
-        goto err;
-    ret = 1;
-
-err:
-    return ret;
-}
diff --git a/providers/common/ciphers/cipher_local.h b/providers/common/ciphers/cipher_local.h
deleted file mode 100644 (file)
index 1c4716f..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the Apache License 2.0 (the "License").  You may not use
- * this file except in compliance with the License.  You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include "prov/ciphercommon.h"
-
-void padblock(unsigned char *buf, size_t *buflen, size_t blocksize);
-int unpadblock(unsigned char *buf, size_t *buflen, size_t blocksize);
diff --git a/providers/common/digests/build.info b/providers/common/digests/build.info
deleted file mode 100644 (file)
index 730046d..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-# This source is common for all digests in all our providers.
-SOURCE[../../libcommon.a]=digest_common.c
diff --git a/providers/common/digests/digest_common.c b/providers/common/digests/digest_common.c
deleted file mode 100644 (file)
index 9d30b2b..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the Apache License 2.0 (the "License").  You may not use
- * this file except in compliance with the License.  You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include "openssl/err.h"
-#include "prov/digestcommon.h"
-#include "prov/providercommonerr.h"
-
-int digest_default_get_params(OSSL_PARAM params[], size_t blksz, size_t paramsz,
-                              unsigned long flags)
-{
-    OSSL_PARAM *p = NULL;
-
-    p = OSSL_PARAM_locate(params, OSSL_DIGEST_PARAM_BLOCK_SIZE);
-    if (p != NULL && !OSSL_PARAM_set_size_t(p, blksz)) {
-        ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
-        return 0;
-    }
-    p = OSSL_PARAM_locate(params, OSSL_DIGEST_PARAM_SIZE);
-    if (p != NULL && !OSSL_PARAM_set_size_t(p, paramsz)) {
-        ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
-        return 0;
-    }
-    p = OSSL_PARAM_locate(params, OSSL_DIGEST_PARAM_FLAGS);
-    if (p != NULL && !OSSL_PARAM_set_ulong(p, flags)) {
-        ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
-        return 0;
-    }
-    return 1;
-}
-
-static const OSSL_PARAM digest_default_known_gettable_params[] = {
-    OSSL_PARAM_size_t(OSSL_DIGEST_PARAM_BLOCK_SIZE, NULL),
-    OSSL_PARAM_size_t(OSSL_DIGEST_PARAM_SIZE, NULL),
-    OSSL_PARAM_ulong(OSSL_DIGEST_PARAM_FLAGS, NULL),
-    OSSL_PARAM_END
-};
-const OSSL_PARAM *digest_default_gettable_params(void)
-{
-    return digest_default_known_gettable_params;
-}
diff --git a/providers/common/include/prov/cipher_aead.h b/providers/common/include/prov/cipher_aead.h
deleted file mode 100644 (file)
index db938d7..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the Apache License 2.0 (the "License").  You may not use
- * this file except in compliance with the License.  You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#define UNINITIALISED_SIZET ((size_t)-1)
-
-/* TODO(3.0) Figure out what flags are really needed */
-#define AEAD_FLAGS (EVP_CIPH_FLAG_AEAD_CIPHER           \
-                    | EVP_CIPH_CUSTOM_IV                \
-                    | EVP_CIPH_ALWAYS_CALL_INIT         \
-                    | EVP_CIPH_CTRL_INIT                \
-                    | EVP_CIPH_CUSTOM_COPY)
-
-#define IMPLEMENT_aead_cipher(alg, lc, UCMODE, flags, kbits, blkbits, ivbits)  \
-static OSSL_OP_cipher_get_params_fn alg##_##kbits##_##lc##_get_params;         \
-static int alg##_##kbits##_##lc##_get_params(OSSL_PARAM params[])              \
-{                                                                              \
-    return cipher_generic_get_params(params, EVP_CIPH_##UCMODE##_MODE,         \
-                                     flags, kbits, blkbits, ivbits);           \
-}                                                                              \
-static OSSL_OP_cipher_newctx_fn alg##kbits##lc##_newctx;                       \
-static void * alg##kbits##lc##_newctx(void *provctx)                           \
-{                                                                              \
-    return alg##_##lc##_newctx(provctx, kbits);                                \
-}                                                                              \
-const OSSL_DISPATCH alg##kbits##lc##_functions[] = {                           \
-    { OSSL_FUNC_CIPHER_NEWCTX, (void (*)(void))alg##kbits##lc##_newctx },      \
-    { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))alg##_##lc##_freectx },        \
-    { OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void)) lc##_einit },            \
-    { OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void)) lc##_dinit },            \
-    { OSSL_FUNC_CIPHER_UPDATE, (void (*)(void)) lc##_stream_update },          \
-    { OSSL_FUNC_CIPHER_FINAL, (void (*)(void)) lc##_stream_final },            \
-    { OSSL_FUNC_CIPHER_CIPHER, (void (*)(void)) lc##_cipher },                 \
-    { OSSL_FUNC_CIPHER_GET_PARAMS,                                             \
-      (void (*)(void)) alg##_##kbits##_##lc##_get_params },                    \
-    { OSSL_FUNC_CIPHER_GET_CTX_PARAMS,                                         \
-      (void (*)(void)) lc##_get_ctx_params },                                  \
-    { OSSL_FUNC_CIPHER_SET_CTX_PARAMS,                                         \
-      (void (*)(void)) lc##_set_ctx_params },                                  \
-    { OSSL_FUNC_CIPHER_GETTABLE_PARAMS,                                        \
-      (void (*)(void))cipher_generic_gettable_params },                        \
-    { OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS,                                    \
-      (void (*)(void))cipher_aead_gettable_ctx_params },                       \
-    { OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS,                                    \
-      (void (*)(void))cipher_aead_settable_ctx_params },                       \
-    { 0, NULL }                                                                \
-}
diff --git a/providers/common/include/prov/cipher_ccm.h b/providers/common/include/prov/cipher_ccm.h
deleted file mode 100644 (file)
index 2214b5f..0000000
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the Apache License 2.0 (the "License").  You may not use
- * this file except in compliance with the License.  You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include "cipher_aead.h"
-
-typedef struct prov_ccm_hw_st PROV_CCM_HW;
-
-#if defined(OPENSSL_CPUID_OBJ) && defined(__s390__)
-/*-
- * KMAC-AES parameter block - begin
- * (see z/Architecture Principles of Operation >= SA22-7832-08)
- */
-typedef struct S390X_kmac_params_st {
-    union {
-        unsigned long long g[2];
-        unsigned char b[16];
-    } icv;
-    unsigned char k[32];
-} S390X_KMAC_PARAMS;
-/* KMAC-AES parameter block - end */
-#endif
-
-/* Base structure that is shared by AES & ARIA for CCM MODE */
-typedef struct prov_ccm_st {
-    unsigned int enc : 1;
-    unsigned int key_set : 1;  /* Set if key initialised */
-    unsigned int iv_set : 1;   /* Set if an iv is set */
-    unsigned int tag_set : 1;  /* Set if tag is valid */
-    unsigned int len_set : 1;  /* Set if message length set */
-    size_t l, m;               /* L and M parameters from RFC3610 */
-    size_t keylen;
-    size_t tls_aad_len;        /* TLS AAD length */
-    size_t tls_aad_pad_sz;
-    unsigned char iv[AES_BLOCK_SIZE];
-    unsigned char buf[AES_BLOCK_SIZE];
-    CCM128_CONTEXT ccm_ctx;
-    ccm128_f str;
-    const PROV_CCM_HW *hw;     /* hardware specific methods  */
-} PROV_CCM_CTX;
-
-typedef struct prov_aes_ccm_ctx_st {
-    PROV_CCM_CTX base;         /* Must be first */
-    union {
-        OSSL_UNION_ALIGN;
-        /*-
-         * Padding is chosen so that s390x.kmac.k overlaps with ks.ks and
-         * fc with ks.ks.rounds. Remember that on s390x, an AES_KEY's
-         * rounds field is used to store the function code and that the key
-         * schedule is not stored (if aes hardware support is detected).
-         */
-        struct {
-            unsigned char pad[16];
-            AES_KEY ks;
-        } ks;
-#if defined(OPENSSL_CPUID_OBJ) && defined(__s390__)
-        struct {
-            S390X_KMAC_PARAMS kmac;
-            unsigned long long blocks;
-            union {
-                unsigned long long g[2];
-                unsigned char b[AES_BLOCK_SIZE];
-            } nonce;
-            union {
-                unsigned long long g[2];
-                unsigned char b[AES_BLOCK_SIZE];
-            } buf;
-            unsigned char dummy_pad[168];
-            unsigned int fc;   /* fc has same offset as ks.ks.rounds */
-        } s390x;
-#endif /* defined(OPENSSL_CPUID_OBJ) && defined(__s390__) */
-    } ccm;
-} PROV_AES_CCM_CTX;
-
-PROV_CIPHER_FUNC(int, CCM_cipher, (PROV_CCM_CTX *ctx, unsigned char *out,      \
-                                   size_t *padlen, const unsigned char *in,    \
-                                   size_t len));
-PROV_CIPHER_FUNC(int, CCM_setkey, (PROV_CCM_CTX *ctx,                          \
-                                   const unsigned char *key, size_t keylen));
-PROV_CIPHER_FUNC(int, CCM_setiv, (PROV_CCM_CTX *dat,                           \
-                                  const unsigned char *iv, size_t ivlen,       \
-                                  size_t mlen));
-PROV_CIPHER_FUNC(int, CCM_setaad, (PROV_CCM_CTX *ctx,                          \
-                                   const unsigned char *aad, size_t aadlen));
-PROV_CIPHER_FUNC(int, CCM_auth_encrypt, (PROV_CCM_CTX *ctx,                    \
-                                         const unsigned char *in,              \
-                                         unsigned char *out, size_t len,       \
-                                         unsigned char *tag, size_t taglen));
-PROV_CIPHER_FUNC(int, CCM_auth_decrypt, (PROV_CCM_CTX *ctx,                    \
-                                         const unsigned char *in,              \
-                                         unsigned char *out, size_t len,       \
-                                         unsigned char *tag, size_t taglen));
-PROV_CIPHER_FUNC(int, CCM_gettag, (PROV_CCM_CTX *ctx,                          \
-                                   unsigned char *tag,  size_t taglen));
-
-/*
- * CCM Mode internal method table used to handle hardware specific differences,
- * (and different algorithms).
- */
-struct prov_ccm_hw_st {
-    OSSL_CCM_setkey_fn setkey;
-    OSSL_CCM_setiv_fn setiv;
-    OSSL_CCM_setaad_fn setaad;
-    OSSL_CCM_auth_encrypt_fn auth_encrypt;
-    OSSL_CCM_auth_decrypt_fn auth_decrypt;
-    OSSL_CCM_gettag_fn gettag;
-};
-
-const PROV_CCM_HW *PROV_AES_HW_ccm(size_t keylen);
-
-OSSL_OP_cipher_encrypt_init_fn ccm_einit;
-OSSL_OP_cipher_decrypt_init_fn ccm_dinit;
-OSSL_OP_cipher_get_ctx_params_fn ccm_get_ctx_params;
-OSSL_OP_cipher_set_ctx_params_fn ccm_set_ctx_params;
-OSSL_OP_cipher_update_fn ccm_stream_update;
-OSSL_OP_cipher_final_fn ccm_stream_final;
-OSSL_OP_cipher_cipher_fn ccm_cipher;
-void ccm_initctx(PROV_CCM_CTX *ctx, size_t keybits, const PROV_CCM_HW *hw);
-
-int ccm_generic_setiv(PROV_CCM_CTX *ctx, const unsigned char *nonce,
-                      size_t nlen, size_t mlen);
-int ccm_generic_setaad(PROV_CCM_CTX *ctx, const unsigned char *aad, size_t alen);
-int ccm_generic_gettag(PROV_CCM_CTX *ctx, unsigned char *tag, size_t tlen);
-int ccm_generic_auth_encrypt(PROV_CCM_CTX *ctx, const unsigned char *in,
-                             unsigned char *out, size_t len,
-                             unsigned char *tag, size_t taglen);
-int ccm_generic_auth_decrypt(PROV_CCM_CTX *ctx, const unsigned char *in,
-                             unsigned char *out, size_t len,
-                             unsigned char *expected_tag, size_t taglen);
diff --git a/providers/common/include/prov/cipher_gcm.h b/providers/common/include/prov/cipher_gcm.h
deleted file mode 100644 (file)
index 711b40c..0000000
+++ /dev/null
@@ -1,160 +0,0 @@
-
-/*
- * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the Apache License 2.0 (the "License").  You may not use
- * this file except in compliance with the License.  You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include <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;
diff --git a/providers/common/include/prov/ciphercommon.h b/providers/common/include/prov/ciphercommon.h
deleted file mode 100644 (file)
index 1072b57..0000000
+++ /dev/null
@@ -1,324 +0,0 @@
-/*
- * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the Apache License 2.0 (the "License").  You may not use
- * this file except in compliance with the License.  You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include <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);
-
diff --git a/providers/common/include/prov/digestcommon.h b/providers/common/include/prov/digestcommon.h
deleted file mode 100644 (file)
index e5b76ff..0000000
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the Apache License 2.0 (the "License").  You may not use
- * this file except in compliance with the License.  You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#ifndef OSSL_PROVIDERS_DIGESTCOMMON_H
-# define OSSL_PROVIDERS_DIGESTCOMMON_H
-
-# include <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 */
index 0a76962669e91a7e1591681d72ffc75c427f91db..abc193bb1de56743aa731a93751ffc491af9669d 100644 (file)
@@ -5,6 +5,8 @@
 # The latter may become legacy sooner, so it's comfortable to have two
 # variables already now, to switch the non-FIPSable TDES to legacy if needed.
 
+$COMMON_GOAL=../../libcommon.a
+
 $AES_GOAL=../../libimplementations.a
 $TDES_1_GOAL=../../libimplementations.a
 $TDES_2_GOAL=../../libimplementations.a
@@ -23,6 +25,12 @@ $CHACHA_GOAL=../../libimplementations.a
 $CHACHAPOLY_GOAL=../../libimplementations.a
 $SIV_GOAL=../../libimplementations.a
 
+# This source is common building blocks for all ciphers in all our providers.
+SOURCE[$COMMON_GOAL]=\
+        ciphercommon.c ciphercommon_hw.c ciphercommon_block.c \
+        ciphercommon_gcm.c ciphercommon_gcm_hw.c \
+        ciphercommon_ccm.c ciphercommon_ccm_hw.c
+
 IF[{- !$disabled{des} -}]
   SOURCE[$TDES_1_GOAL]=cipher_tdes.c cipher_tdes_hw.c
 ENDIF
index c1fb51b56575bf54a7a860f19848f990048ebe7e..b6655143d958279aca28688b8078383b5e2b5ce3 100644 (file)
@@ -10,7 +10,7 @@
 /* Dispatch functions for AES CCM mode */
 
 #include "prov/ciphercommon.h"
-#include "prov/cipher_ccm.h"
+#include "prov/ciphercommon_ccm.h"
 #include "prov/implementations.h"
 
 static void *aes_ccm_newctx(void *provctx, size_t keybits)
index ae200ebada6bb6bcc60734d280e5dcb679726d32..0b1e50163b29a292a3a030921ba451787fc7857c 100644 (file)
@@ -10,7 +10,7 @@
 /* AES CCM mode */
 
 #include "prov/ciphercommon.h"
-#include "prov/cipher_ccm.h"
+#include "prov/ciphercommon_ccm.h"
 
 #define AES_HW_CCM_SET_KEY_FN(fn_set_enc_key, fn_blk, fn_ccm_enc, fn_ccm_dec)  \
     fn_set_enc_key(key, keylen * 8, &actx->ccm.ks.ks);                         \
index 3a5e4a740ddbc46fecfa4a96b7cee073dd1c84a8..7e835658095e9d6d0434eb591cffa219123b9c93 100644 (file)
@@ -9,7 +9,7 @@
 
 /*-
  * AES-NI support for AES CCM.
- * This file is included by cipher_ccm_hw.c
+ * This file is included by cipher_aes_ccm_hw.c
  */
 
 static int ccm_aesni_initkey(PROV_CCM_CTX *ctx, const unsigned char *key,
index a5025e5960feffd6b3e0f2ee1bf117dea10af030..cec7c9690277919f92f43d9ac38c08f9032ab253 100644 (file)
@@ -9,7 +9,7 @@
 
 /*-
  * S390X support for AES CCM.
- * This file is included by cipher_ccm_hw.c
+ * This file is included by cipher_aes_ccm_hw.c
  */
 
 #define S390X_CCM_AAD_FLAG 0x40
index 21bf6861e0bd4ca4af788d891ecffd2c39ced19e..c4b6d15ed9e663e35a1503c1bdf516fa185f2a6d 100644 (file)
@@ -9,7 +9,7 @@
 
 /*-
  * Fujitsu SPARC64 X support for AES CCM.
- * This file is included by cipher_ccm_hw.c
+ * This file is included by cipher_aes_ccm_hw.c
  */
 
 static int ccm_t4_aes_initkey(PROV_CCM_CTX *ctx, const unsigned char *key,
index 4ebc8140ee45e025d5744ba3c0e523e19b61eb7a..18277c705e33627c4afaefd80d800de9000cc916 100644 (file)
@@ -10,7 +10,7 @@
 /* Dispatch functions for AES GCM mode */
 
 #include "prov/ciphercommon.h"
-#include "prov/cipher_gcm.h"
+#include "prov/ciphercommon_gcm.h"
 #include "prov/implementations.h"
 
 static void *aes_gcm_newctx(void *provctx, size_t keybits)
index f5dc0c4eed37ecec1617d9d3b85d1bf1d04ce692..6a2f8a5fd47b5db0f2bff734546f8bae0c907c2b 100644 (file)
@@ -10,7 +10,7 @@
 /* Dispatch functions for AES GCM mode */
 
 #include "prov/ciphercommon.h"
-#include "prov/cipher_gcm.h"
+#include "prov/ciphercommon_gcm.h"
 
 static int generic_aes_gcm_initkey(PROV_GCM_CTX *ctx, const unsigned char *key,
                                    size_t keylen)
index eb2a3f343a83f7657fcd0f4ef4d8b1e3a751ec46..2fc86982c036ed3dc7b2dfa0152fdad7f479051f 100644 (file)
@@ -9,7 +9,7 @@
 
 /*-
  * AES-NI support for AES GCM.
- * This file is included by cipher_gcm_hw.c
+ * This file is included by cipher_aes_gcm_hw.c
  */
 
 static int aesni_gcm_initkey(PROV_GCM_CTX *ctx, const unsigned char *key,
index 44c3bf332d9dab8c1d57d287ebf0892181f9524e..e13771a44959a5f6629a0fef9a208e76767c0e13 100644 (file)
@@ -9,7 +9,7 @@
 
 /*-
  * IBM S390X support for AES GCM.
- * This file is included by cipher_gcm_hw.c
+ * This file is included by cipher_aes_gcm_hw.c
  */
 
 /* iv + padding length for iv lengths != 12 */
index 19e9ccb760749912e6faa036e9b536ad84e2b888..cc7d4ba528ef51bbdff8fcc6ac6d054440dfdda7 100644 (file)
@@ -9,7 +9,7 @@
 
 /*-
  * Fujitsu SPARC64 X support for AES GCM.
- * This file is included by cipher_gcm_hw.c
+ * This file is included by cipher_aes_gcm_hw.c
  */
 
 static int t4_aes_gcm_initkey(PROV_GCM_CTX *ctx, const unsigned char *key,
index 6b07caaa52e875677d43aff2b198c391b1e51ca3..03ec70b9498b6a873bad027fd78c87f144947860 100644 (file)
@@ -9,7 +9,7 @@
 
 #include "cipher_aes_ocb.h"
 #include "prov/providercommonerr.h"
-#include "prov/cipher_aead.h"
+#include "prov/ciphercommon_aead.h"
 #include "prov/implementations.h"
 
 #define AES_OCB_FLAGS AEAD_FLAGS
index 864ebc725edfb934644d29512728c373da114193..ada6b27435c530e5e1b5c1e3c023a3e5c1880911 100644 (file)
@@ -12,7 +12,7 @@
 #include "cipher_aes_siv.h"
 #include "prov/implementations.h"
 #include "prov/providercommonerr.h"
-#include "prov/cipher_aead.h"
+#include "prov/ciphercommon_aead.h"
 
 #define siv_stream_update siv_cipher
 #define SIV_FLAGS AEAD_FLAGS
index 301ce14306b31684a05f31e298429fbea0dcf4fd..a85cf899efd1af227a7d940ee3813ac91918d091 100644 (file)
@@ -9,7 +9,7 @@
 
 #include "crypto/aria.h"
 #include "prov/ciphercommon.h"
-#include "prov/cipher_ccm.h"
+#include "prov/ciphercommon_ccm.h"
 
 typedef struct prov_aria_ccm_ctx_st {
     PROV_CCM_CTX base; /* Must be first */
index 13fbe175d93ae43b22ddecc16b817a8da2b51c9e..2d08a5902903d89eee747038e92d6f136b54b973 100644 (file)
@@ -9,7 +9,7 @@
 
 #include "crypto/aria.h"
 #include "prov/ciphercommon.h"
-#include "prov/cipher_gcm.h"
+#include "prov/ciphercommon_gcm.h"
 
 typedef struct prov_aria_gcm_ctx_st {
     PROV_GCM_CTX base;              /* must be first entry in struct */
diff --git a/providers/implementations/ciphers/ciphercommon.c b/providers/implementations/ciphers/ciphercommon.c
new file mode 100644 (file)
index 0000000..a6b8907
--- /dev/null
@@ -0,0 +1,431 @@
+/*
+ * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * Generic dispatch table functions for ciphers.
+ */
+
+#include "ciphercommon_local.h"
+#include "prov/provider_ctx.h"
+#include "prov/providercommonerr.h"
+
+/*-
+ * Generic cipher functions for OSSL_PARAM gettables and settables
+ */
+static const OSSL_PARAM cipher_known_gettable_params[] = {
+    OSSL_PARAM_uint(OSSL_CIPHER_PARAM_MODE, NULL),
+    OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL),
+    OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_IVLEN, NULL),
+    OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_BLOCK_SIZE, NULL),
+    OSSL_PARAM_ulong(OSSL_CIPHER_PARAM_FLAGS, NULL),
+    OSSL_PARAM_END
+};
+const OSSL_PARAM *cipher_generic_gettable_params(void)
+{
+    return cipher_known_gettable_params;
+}
+
+int cipher_generic_get_params(OSSL_PARAM params[], unsigned int md,
+                              unsigned long flags,
+                              size_t kbits, size_t blkbits, size_t ivbits)
+{
+    OSSL_PARAM *p;
+
+    p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_MODE);
+    if (p != NULL && !OSSL_PARAM_set_uint(p, md)) {
+        ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+        return 0;
+    }
+    p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_FLAGS);
+    if (p != NULL && !OSSL_PARAM_set_ulong(p, flags)) {
+        ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+        return 0;
+    }
+    p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_KEYLEN);
+    if (p != NULL && !OSSL_PARAM_set_size_t(p, kbits / 8)) {
+        ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+        return 0;
+    }
+    p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_BLOCK_SIZE);
+    if (p != NULL && !OSSL_PARAM_set_size_t(p, blkbits / 8)) {
+        ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+        return 0;
+    }
+    p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IVLEN);
+    if (p != NULL && !OSSL_PARAM_set_size_t(p, ivbits / 8)) {
+        ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+        return 0;
+    }
+    return 1;
+}
+
+CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_START(cipher_generic)
+CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_END(cipher_generic)
+
+CIPHER_DEFAULT_SETTABLE_CTX_PARAMS_START(cipher_generic)
+CIPHER_DEFAULT_SETTABLE_CTX_PARAMS_END(cipher_generic)
+
+/*
+ * Variable key length cipher functions for OSSL_PARAM settables
+ */
+
+int cipher_var_keylen_set_ctx_params(void *vctx, const OSSL_PARAM params[])
+{
+    PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
+    const OSSL_PARAM *p;
+
+    if (!cipher_generic_set_ctx_params(vctx, params))
+        return 0;
+    p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_KEYLEN);
+    if (p != NULL) {
+        size_t keylen;
+
+        if (!OSSL_PARAM_get_size_t(p, &keylen)) {
+            ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
+            return 0;
+        }
+        ctx->keylen = keylen;
+    }
+    return 1;
+}
+
+CIPHER_DEFAULT_SETTABLE_CTX_PARAMS_START(cipher_var_keylen)
+OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL),
+CIPHER_DEFAULT_SETTABLE_CTX_PARAMS_END(cipher_var_keylen)
+
+/*-
+ * AEAD cipher functions for OSSL_PARAM gettables and settables
+ */
+static const OSSL_PARAM cipher_aead_known_gettable_ctx_params[] = {
+    OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL),
+    OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_IVLEN, NULL),
+    OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_AEAD_TAGLEN, NULL),
+    OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_IV, NULL, 0),
+    OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, NULL, 0),
+    OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_AEAD_TLS1_AAD_PAD, NULL),
+    OSSL_PARAM_END
+};
+const OSSL_PARAM *cipher_aead_gettable_ctx_params(void)
+{
+    return cipher_aead_known_gettable_ctx_params;
+}
+
+static const OSSL_PARAM cipher_aead_known_settable_ctx_params[] = {
+    OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_AEAD_IVLEN, NULL),
+    OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, NULL, 0),
+    OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TLS1_AAD, NULL, 0),
+    OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TLS1_IV_FIXED, NULL, 0),
+    OSSL_PARAM_END
+};
+const OSSL_PARAM *cipher_aead_settable_ctx_params(void)
+{
+    return cipher_aead_known_settable_ctx_params;
+}
+
+static int cipher_generic_init_internal(PROV_CIPHER_CTX *ctx,
+                                        const unsigned char *key, size_t keylen,
+                                        const unsigned char *iv, size_t ivlen,
+                                        int enc)
+{
+    ctx->enc = enc ? 1 : 0;
+
+    if (iv != NULL && ctx->mode != EVP_CIPH_ECB_MODE) {
+        if (!cipher_generic_initiv(ctx, iv, ivlen))
+            return 0;
+    }
+    if (key != NULL) {
+        if ((ctx->flags & EVP_CIPH_VARIABLE_LENGTH) == 0) {
+            if (keylen != ctx->keylen) {
+                ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEYLEN);
+                return 0;
+            }
+        } else {
+            ctx->keylen = keylen;
+        }
+        return ctx->hw->init(ctx, key, ctx->keylen);
+    }
+    return 1;
+}
+
+int cipher_generic_einit(void *vctx, const unsigned char *key, size_t keylen,
+                         const unsigned char *iv, size_t ivlen)
+{
+    return cipher_generic_init_internal((PROV_CIPHER_CTX *)vctx, key, keylen,
+                                        iv, ivlen, 1);
+}
+
+int cipher_generic_dinit(void *vctx, const unsigned char *key, size_t keylen,
+                         const unsigned char *iv, size_t ivlen)
+{
+    return cipher_generic_init_internal((PROV_CIPHER_CTX *)vctx, key, keylen,
+                                        iv, ivlen, 0);
+}
+
+int cipher_generic_block_update(void *vctx, unsigned char *out, size_t *outl,
+                                size_t outsize, const unsigned char *in,
+                                size_t inl)
+{
+    size_t outlint = 0;
+    PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
+    size_t blksz = ctx->blocksize;
+    size_t nextblocks = fillblock(ctx->buf, &ctx->bufsz, blksz, &in, &inl);
+
+    /*
+     * If we're decrypting and we end an update on a block boundary we hold
+     * the last block back in case this is the last update call and the last
+     * block is padded.
+     */
+    if (ctx->bufsz == blksz && (ctx->enc || inl > 0 || !ctx->pad)) {
+        if (outsize < blksz) {
+            ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
+            return 0;
+        }
+        if (!ctx->hw->cipher(ctx, out, ctx->buf, blksz)) {
+            ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);
+            return 0;
+        }
+        ctx->bufsz = 0;
+        outlint = blksz;
+        out += blksz;
+    }
+    if (nextblocks > 0) {
+        if (!ctx->enc && ctx->pad && nextblocks == inl) {
+            if (!ossl_assert(inl >= blksz)) {
+                ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
+                return 0;
+            }
+            nextblocks -= blksz;
+        }
+        outlint += nextblocks;
+        if (outsize < outlint) {
+            ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
+            return 0;
+        }
+    }
+    if (nextblocks > 0) {
+        if (!ctx->hw->cipher(ctx, out, in, nextblocks)) {
+            ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);
+            return 0;
+        }
+        in += nextblocks;
+        inl -= nextblocks;
+    }
+    if (!trailingdata(ctx->buf, &ctx->bufsz, blksz, &in, &inl)) {
+        /* ERR_raise already called */
+        return 0;
+    }
+
+    *outl = outlint;
+    return inl == 0;
+}
+
+int cipher_generic_block_final(void *vctx, unsigned char *out, size_t *outl,
+                               size_t outsize)
+{
+    PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
+    size_t blksz = ctx->blocksize;
+
+    if (ctx->enc) {
+        if (ctx->pad) {
+            padblock(ctx->buf, &ctx->bufsz, blksz);
+        } else if (ctx->bufsz == 0) {
+            *outl = 0;
+            return 1;
+        } else if (ctx->bufsz != blksz) {
+            ERR_raise(ERR_LIB_PROV, PROV_R_WRONG_FINAL_BLOCK_LENGTH);
+            return 0;
+        }
+
+        if (outsize < blksz) {
+            ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
+            return 0;
+        }
+        if (!ctx->hw->cipher(ctx, out, ctx->buf, blksz)) {
+            ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);
+            return 0;
+        }
+        ctx->bufsz = 0;
+        *outl = blksz;
+        return 1;
+    }
+
+    /* Decrypting */
+    if (ctx->bufsz != blksz) {
+        if (ctx->bufsz == 0 && !ctx->pad) {
+            *outl = 0;
+            return 1;
+        }
+        ERR_raise(ERR_LIB_PROV, PROV_R_WRONG_FINAL_BLOCK_LENGTH);
+        return 0;
+    }
+
+    if (!ctx->hw->cipher(ctx, ctx->buf, ctx->buf, blksz)) {
+        ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);
+        return 0;
+    }
+
+    if (ctx->pad && !unpadblock(ctx->buf, &ctx->bufsz, blksz)) {
+        /* ERR_raise already called */
+        return 0;
+    }
+
+    if (outsize < ctx->bufsz) {
+        ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
+        return 0;
+    }
+    memcpy(out, ctx->buf, ctx->bufsz);
+    *outl = ctx->bufsz;
+    ctx->bufsz = 0;
+    return 1;
+}
+
+int cipher_generic_stream_update(void *vctx, unsigned char *out, size_t *outl,
+                                 size_t outsize, const unsigned char *in,
+                                 size_t inl)
+{
+    PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
+
+    if (inl == 0) {
+        *outl = 0;
+        return 1;
+    }
+
+    if (outsize < inl) {
+        ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
+        return 0;
+    }
+
+    if (!ctx->hw->cipher(ctx, out, in, inl)) {
+        ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);
+        return 0;
+    }
+
+    *outl = inl;
+    return 1;
+}
+int cipher_generic_stream_final(void *vctx, unsigned char *out, size_t *outl,
+                                size_t outsize)
+{
+    *outl = 0;
+    return 1;
+}
+
+int cipher_generic_cipher(void *vctx,
+                          unsigned char *out, size_t *outl, size_t outsize,
+                          const unsigned char *in, size_t inl)
+{
+    PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
+
+    if (outsize < inl) {
+        ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
+        return 0;
+    }
+
+    if (!ctx->hw->cipher(ctx, out, in, inl)) {
+        ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);
+        return 0;
+    }
+
+    *outl = inl;
+    return 1;
+}
+
+int cipher_generic_get_ctx_params(void *vctx, OSSL_PARAM params[])
+{
+    PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
+    OSSL_PARAM *p;
+
+    p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IVLEN);
+    if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->ivlen)) {
+        ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+        return 0;
+    }
+    p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_PADDING);
+    if (p != NULL && !OSSL_PARAM_set_uint(p, ctx->pad)) {
+        ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+        return 0;
+    }
+    p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IV);
+    if (p != NULL
+        && !OSSL_PARAM_set_octet_ptr(p, &ctx->oiv, ctx->ivlen)
+        && !OSSL_PARAM_set_octet_string(p, &ctx->oiv, ctx->ivlen)) {
+        ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+        return 0;
+    }
+    p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_NUM);
+    if (p != NULL && !OSSL_PARAM_set_uint(p, ctx->num)) {
+        ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+        return 0;
+    }
+    p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_KEYLEN);
+    if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->keylen)) {
+        ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+        return 0;
+    }
+    return 1;
+}
+
+int cipher_generic_set_ctx_params(void *vctx, const OSSL_PARAM params[])
+{
+    PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
+    const OSSL_PARAM *p;
+
+    p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_PADDING);
+    if (p != NULL) {
+        unsigned int pad;
+
+        if (!OSSL_PARAM_get_uint(p, &pad)) {
+            ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
+            return 0;
+        }
+        ctx->pad = pad ? 1 : 0;
+    }
+    p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_NUM);
+    if (p != NULL) {
+        unsigned int num;
+
+        if (!OSSL_PARAM_get_uint(p, &num)) {
+            ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
+            return 0;
+        }
+        ctx->num = num;
+    }
+    return 1;
+}
+
+int cipher_generic_initiv(PROV_CIPHER_CTX *ctx, const unsigned char *iv,
+                          size_t ivlen)
+{
+    if (ivlen != ctx->ivlen
+        || ivlen > sizeof(ctx->iv)) {
+        ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IVLEN);
+        return 0;
+    }
+    ctx->iv_set = 1;
+    memcpy(ctx->iv, iv, ivlen);
+    memcpy(ctx->oiv, iv, ivlen);
+    return 1;
+}
+
+void cipher_generic_initkey(void *vctx, size_t kbits, size_t blkbits,
+                            size_t ivbits, unsigned int mode, uint64_t flags,
+                            const PROV_CIPHER_HW *hw, void *provctx)
+{
+    PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx;
+
+    ctx->flags = flags;
+    ctx->pad = 1;
+    ctx->keylen = ((kbits) / 8);
+    ctx->ivlen = ((ivbits) / 8);
+    ctx->hw = hw;
+    ctx->mode = mode;
+    ctx->blocksize = blkbits / 8;
+    if (provctx != NULL)
+        ctx->libctx = PROV_LIBRARY_CONTEXT_OF(provctx); /* used for rand */
+}
diff --git a/providers/implementations/ciphers/ciphercommon_block.c b/providers/implementations/ciphers/ciphercommon_block.c
new file mode 100644 (file)
index 0000000..eff9484
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <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;
+}
diff --git a/providers/implementations/ciphers/ciphercommon_ccm.c b/providers/implementations/ciphers/ciphercommon_ccm.c
new file mode 100644 (file)
index 0000000..edb8e81
--- /dev/null
@@ -0,0 +1,421 @@
+/*
+ * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/* Dispatch functions for ccm mode */
+
+#include "prov/ciphercommon.h"
+#include "prov/ciphercommon_ccm.h"
+#include "prov/providercommonerr.h"
+
+static int ccm_cipher_internal(PROV_CCM_CTX *ctx, unsigned char *out,
+                               size_t *padlen, const unsigned char *in,
+                               size_t len);
+
+static int ccm_tls_init(PROV_CCM_CTX *ctx, unsigned char *aad, size_t alen)
+{
+    size_t len;
+
+    if (alen != EVP_AEAD_TLS1_AAD_LEN)
+        return 0;
+
+    /* Save the aad for later use. */
+    memcpy(ctx->buf, aad, alen);
+    ctx->tls_aad_len = alen;
+
+    len = ctx->buf[alen - 2] << 8 | ctx->buf[alen - 1];
+    if (len < EVP_CCM_TLS_EXPLICIT_IV_LEN)
+        return 0;
+
+    /* Correct length for explicit iv. */
+    len -= EVP_CCM_TLS_EXPLICIT_IV_LEN;
+
+    if (!ctx->enc) {
+        if (len < ctx->m)
+            return 0;
+        /* Correct length for tag. */
+        len -= ctx->m;
+    }
+    ctx->buf[alen - 2] = (unsigned char)(len >> 8);
+    ctx->buf[alen - 1] = (unsigned char)(len & 0xff);
+
+    /* Extra padding: tag appended to record. */
+    return ctx->m;
+}
+
+static int ccm_tls_iv_set_fixed(PROV_CCM_CTX *ctx, unsigned char *fixed,
+                                size_t flen)
+{
+    if (flen != EVP_CCM_TLS_FIXED_IV_LEN)
+        return 0;
+
+    /* Copy to first part of the iv. */
+    memcpy(ctx->iv, fixed, flen);
+    return 1;
+}
+
+static size_t ccm_get_ivlen(PROV_CCM_CTX *ctx)
+{
+    return 15 - ctx->l;
+}
+
+int ccm_set_ctx_params(void *vctx, const OSSL_PARAM params[])
+{
+    PROV_CCM_CTX *ctx = (PROV_CCM_CTX *)vctx;
+    const OSSL_PARAM *p;
+    size_t sz;
+
+    p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TAG);
+    if (p != NULL) {
+        if (p->data_type != OSSL_PARAM_OCTET_STRING) {
+            ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
+            return 0;
+        }
+        if ((p->data_size & 1) || (p->data_size < 4) || p->data_size > 16) {
+            ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_TAGLEN);
+            return 0;
+        }
+
+        if (p->data != NULL) {
+            if (ctx->enc) {
+                ERR_raise(ERR_LIB_PROV, PROV_R_TAG_NOT_NEEDED);
+                return 0;
+            }
+            memcpy(ctx->buf, p->data, p->data_size);
+            ctx->tag_set = 1;
+        }
+        ctx->m = p->data_size;
+    }
+
+    p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_IVLEN);
+    if (p != NULL) {
+        size_t ivlen;
+
+        if (!OSSL_PARAM_get_size_t(p, &sz)) {
+            ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
+            return 0;
+        }
+        ivlen = 15 - sz;
+        if (ivlen < 2 || ivlen > 8) {
+            ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IVLEN);
+            return 0;
+        }
+        ctx->l = ivlen;
+    }
+
+    p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TLS1_AAD);
+    if (p != NULL) {
+        if (p->data_type != OSSL_PARAM_OCTET_STRING) {
+            ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
+            return 0;
+        }
+        sz = ccm_tls_init(ctx, p->data, p->data_size);
+        if (sz == 0) {
+            ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DATA);
+            return 0;
+        }
+        ctx->tls_aad_pad_sz = sz;
+    }
+
+    p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TLS1_IV_FIXED);
+    if (p != NULL) {
+        if (p->data_type != OSSL_PARAM_OCTET_STRING) {
+            ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
+            return 0;
+        }
+        if (ccm_tls_iv_set_fixed(ctx, p->data, p->data_size) == 0) {
+            ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IVLEN);
+            return 0;
+        }
+    }
+
+    return 1;
+}
+
+int ccm_get_ctx_params(void *vctx, OSSL_PARAM params[])
+{
+    PROV_CCM_CTX *ctx = (PROV_CCM_CTX *)vctx;
+    OSSL_PARAM *p;
+
+    p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IVLEN);
+    if (p != NULL && !OSSL_PARAM_set_size_t(p, ccm_get_ivlen(ctx))) {
+        ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+        return 0;
+    }
+
+    p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TAGLEN);
+    if (p != NULL) {
+        size_t m = ctx->m;
+
+        if (!OSSL_PARAM_set_size_t(p, m)) {
+            ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+            return 0;
+        }
+    }
+
+    p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IV);
+    if (p != NULL) {
+        if (ccm_get_ivlen(ctx) != p->data_size) {
+            ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IVLEN);
+            return 0;
+        }
+        if (!OSSL_PARAM_set_octet_string(p, ctx->iv, p->data_size)) {
+            ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+            return 0;
+        }
+    }
+
+    p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_KEYLEN);
+    if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->keylen)) {
+        ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+        return 0;
+    }
+
+    p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TLS1_AAD_PAD);
+    if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->tls_aad_pad_sz)) {
+        ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+        return 0;
+    }
+
+    p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TAG);
+    if (p != NULL) {
+        if (!ctx->enc || !ctx->tag_set) {
+            ERR_raise(ERR_LIB_PROV, PROV_R_TAG_NOTSET);
+            return 0;
+        }
+        if (p->data_type != OSSL_PARAM_OCTET_STRING) {
+            ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+            return 0;
+        }
+        if (!ctx->hw->gettag(ctx, p->data, p->data_size))
+            return 0;
+        ctx->tag_set = 0;
+        ctx->iv_set = 0;
+        ctx->len_set = 0;
+    }
+    return 1;
+}
+
+static int ccm_init(void *vctx, const unsigned char *key, size_t keylen,
+                    const unsigned char *iv, size_t ivlen, int enc)
+{
+    PROV_CCM_CTX *ctx = (PROV_CCM_CTX *)vctx;
+
+    ctx->enc = enc;
+
+    if (iv != NULL) {
+        if (ivlen != ccm_get_ivlen(ctx)) {
+            ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IVLEN);
+            return 0;
+        }
+        memcpy(ctx->iv, iv, ivlen);
+        ctx->iv_set = 1;
+    }
+    if (key != NULL) {
+        if (keylen != ctx->keylen) {
+            ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEYLEN);
+            return 0;
+        }
+        return ctx->hw->setkey(ctx, key, keylen);
+    }
+    return 1;
+}
+
+int ccm_einit(void *vctx, const unsigned char *key, size_t keylen,
+                     const unsigned char *iv, size_t ivlen)
+{
+    return ccm_init(vctx, key, keylen, iv, ivlen, 1);
+}
+
+int ccm_dinit(void *vctx, const unsigned char *key, size_t keylen,
+                     const unsigned char *iv, size_t ivlen)
+{
+    return ccm_init(vctx, key, keylen, iv, ivlen, 0);
+}
+
+int ccm_stream_update(void *vctx, unsigned char *out, size_t *outl,
+                             size_t outsize, const unsigned char *in,
+                             size_t inl)
+{
+    PROV_CCM_CTX *ctx = (PROV_CCM_CTX *)vctx;
+
+    if (outsize < inl) {
+        ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
+        return 0;
+    }
+
+    if (!ccm_cipher_internal(ctx, out, outl, in, inl)) {
+        ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);
+        return 0;
+    }
+    return 1;
+}
+
+int ccm_stream_final(void *vctx, unsigned char *out, size_t *outl,
+                            size_t outsize)
+{
+    PROV_CCM_CTX *ctx = (PROV_CCM_CTX *)vctx;
+    int i;
+
+    i = ccm_cipher_internal(ctx, out, outl, NULL, 0);
+    if (i <= 0)
+        return 0;
+
+    *outl = 0;
+    return 1;
+}
+
+int ccm_cipher(void *vctx,
+                      unsigned char *out, size_t *outl, size_t outsize,
+                      const unsigned char *in, size_t inl)
+{
+    PROV_CCM_CTX *ctx = (PROV_CCM_CTX *)vctx;
+
+    if (outsize < inl) {
+        ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
+        return 0;
+    }
+
+    if (ccm_cipher_internal(ctx, out, outl, in, inl) <= 0)
+        return 0;
+
+    *outl = inl;
+    return 1;
+}
+
+/* Copy the buffered iv */
+static int ccm_set_iv(PROV_CCM_CTX *ctx, size_t mlen)
+{
+    const PROV_CCM_HW *hw = ctx->hw;
+
+    if (!hw->setiv(ctx, ctx->iv, ccm_get_ivlen(ctx), mlen))
+        return 0;
+    ctx->len_set = 1;
+    return 1;
+}
+
+static int ccm_tls_cipher(PROV_CCM_CTX *ctx,
+                          unsigned char *out, size_t *padlen,
+                          const unsigned char *in, size_t len)
+{
+    int rv = 0;
+    size_t olen = 0;
+
+    /* Encrypt/decrypt must be performed in place */
+    if (out != in || len < (EVP_CCM_TLS_EXPLICIT_IV_LEN + (size_t)ctx->m))
+        goto err;
+
+    /* If encrypting set explicit IV from sequence number (start of AAD) */
+    if (ctx->enc)
+        memcpy(out, ctx->buf, EVP_CCM_TLS_EXPLICIT_IV_LEN);
+    /* Get rest of IV from explicit IV */
+    memcpy(ctx->iv + EVP_CCM_TLS_FIXED_IV_LEN, in, EVP_CCM_TLS_EXPLICIT_IV_LEN);
+    /* Correct length value */
+    len -= EVP_CCM_TLS_EXPLICIT_IV_LEN + ctx->m;
+    if (!ccm_set_iv(ctx, len))
+        goto err;
+
+    /* Use saved AAD */
+    if (!ctx->hw->setaad(ctx, ctx->buf, ctx->tls_aad_len))
+        goto err;
+
+    /* Fix buffer to point to payload */
+    in += EVP_CCM_TLS_EXPLICIT_IV_LEN;
+    out += EVP_CCM_TLS_EXPLICIT_IV_LEN;
+    if (ctx->enc) {
+        if (!ctx->hw->auth_encrypt(ctx, in, out, len,  out + len, ctx->m))
+            goto err;
+        olen = len + EVP_CCM_TLS_EXPLICIT_IV_LEN + ctx->m;
+    } else {
+        if (!ctx->hw->auth_decrypt(ctx, in, out, len,
+                                   (unsigned char *)in + len, ctx->m))
+            goto err;
+        olen = len;
+    }
+    rv = 1;
+err:
+    *padlen = olen;
+    return rv;
+}
+
+static int ccm_cipher_internal(PROV_CCM_CTX *ctx, unsigned char *out,
+                               size_t *padlen, const unsigned char *in,
+                               size_t len)
+{
+    int rv = 0;
+    size_t olen = 0;
+    const PROV_CCM_HW *hw = ctx->hw;
+
+    /* If no key set, return error */
+    if (!ctx->key_set)
+        return 0;
+
+    if (ctx->tls_aad_len != UNINITIALISED_SIZET)
+        return ccm_tls_cipher(ctx, out, padlen, in, len);
+
+    /* EVP_*Final() doesn't return any data */
+    if (in == NULL && out != NULL)
+        goto finish;
+
+    if (!ctx->iv_set)
+        goto err;
+
+    if (out == NULL) {
+        if (in == NULL) {
+            if (!ccm_set_iv(ctx, len))
+                goto err;
+        } else {
+            /* If we have AAD, we need a message length */
+            if (!ctx->len_set && len)
+                goto err;
+            if (!hw->setaad(ctx, in, len))
+                goto err;
+        }
+    } else {
+        /* If not set length yet do it */
+        if (!ctx->len_set && !ccm_set_iv(ctx, len))
+            goto err;
+
+        if (ctx->enc) {
+            if (!hw->auth_encrypt(ctx, in, out, len, NULL, 0))
+                goto err;
+            ctx->tag_set = 1;
+        } else {
+            /* The tag must be set before actually decrypting data */
+            if (!ctx->tag_set)
+                goto err;
+
+            if (!hw->auth_decrypt(ctx, in, out, len, ctx->buf, ctx->m))
+                goto err;
+            /* Finished - reset flags so calling this method again will fail */
+            ctx->iv_set = 0;
+            ctx->tag_set = 0;
+            ctx->len_set = 0;
+        }
+    }
+    olen = len;
+finish:
+    rv = 1;
+err:
+    *padlen = olen;
+    return rv;
+}
+
+void ccm_initctx(PROV_CCM_CTX *ctx, size_t keybits, const PROV_CCM_HW *hw)
+{
+    ctx->keylen = keybits / 8;
+    ctx->key_set = 0;
+    ctx->iv_set = 0;
+    ctx->tag_set = 0;
+    ctx->len_set = 0;
+    ctx->l = 8;
+    ctx->m = 12;
+    ctx->tls_aad_len = UNINITIALISED_SIZET;
+    ctx->hw = hw;
+}
+
diff --git a/providers/implementations/ciphers/ciphercommon_ccm_hw.c b/providers/implementations/ciphers/ciphercommon_ccm_hw.c
new file mode 100644 (file)
index 0000000..96cc744
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "prov/ciphercommon.h"
+#include "prov/ciphercommon_ccm.h"
+
+int ccm_generic_setiv(PROV_CCM_CTX *ctx, const unsigned char *nonce,
+                      size_t nlen, size_t mlen)
+{
+    return CRYPTO_ccm128_setiv(&ctx->ccm_ctx, nonce, nlen, mlen) == 0;
+}
+
+int ccm_generic_setaad(PROV_CCM_CTX *ctx, const unsigned char *aad, size_t alen)
+{
+    CRYPTO_ccm128_aad(&ctx->ccm_ctx, aad, alen);
+    return 1;
+}
+
+int ccm_generic_gettag(PROV_CCM_CTX *ctx, unsigned char *tag, size_t tlen)
+{
+    return CRYPTO_ccm128_tag(&ctx->ccm_ctx, tag, tlen) > 0;
+}
+
+int ccm_generic_auth_encrypt(PROV_CCM_CTX *ctx, const unsigned char *in,
+                             unsigned char *out, size_t len,
+                             unsigned char *tag, size_t taglen)
+{
+    int rv;
+
+    if (ctx->str != NULL)
+        rv = CRYPTO_ccm128_encrypt_ccm64(&ctx->ccm_ctx, in,
+                                         out, len, ctx->str) == 0;
+    else
+        rv = CRYPTO_ccm128_encrypt(&ctx->ccm_ctx, in, out, len) == 0;
+
+    if (rv == 1 && tag != NULL)
+        rv = (CRYPTO_ccm128_tag(&ctx->ccm_ctx, tag, taglen) > 0);
+    return rv;
+}
+
+int ccm_generic_auth_decrypt(PROV_CCM_CTX *ctx, const unsigned char *in,
+                             unsigned char *out, size_t len,
+                             unsigned char *expected_tag, size_t taglen)
+{
+    int rv = 0;
+
+    if (ctx->str != NULL)
+        rv = CRYPTO_ccm128_decrypt_ccm64(&ctx->ccm_ctx, in, out, len,
+                                         ctx->str) == 0;
+    else
+        rv = CRYPTO_ccm128_decrypt(&ctx->ccm_ctx, in, out, len) == 0;
+    if (rv) {
+        unsigned char tag[16];
+
+        if (!CRYPTO_ccm128_tag(&ctx->ccm_ctx, tag, taglen)
+            || CRYPTO_memcmp(tag, expected_tag, taglen) != 0)
+            rv = 0;
+    }
+    if (rv == 0)
+        OPENSSL_cleanse(out, len);
+    return rv;
+}
+
diff --git a/providers/implementations/ciphers/ciphercommon_gcm.c b/providers/implementations/ciphers/ciphercommon_gcm.c
new file mode 100644 (file)
index 0000000..803f810
--- /dev/null
@@ -0,0 +1,495 @@
+/*
+ * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/* Dispatch functions for gcm mode */
+
+#include "prov/ciphercommon.h"
+#include "prov/ciphercommon_gcm.h"
+#include "prov/providercommonerr.h"
+#include "crypto/rand.h"
+#include "prov/provider_ctx.h"
+
+static int gcm_tls_init(PROV_GCM_CTX *dat, unsigned char *aad, size_t aad_len);
+static int gcm_tls_iv_set_fixed(PROV_GCM_CTX *ctx, unsigned char *iv,
+                                size_t len);
+static int gcm_tls_cipher(PROV_GCM_CTX *ctx, unsigned char *out, size_t *padlen,
+                          const unsigned char *in, size_t len);
+static int gcm_cipher_internal(PROV_GCM_CTX *ctx, unsigned char *out,
+                               size_t *padlen, const unsigned char *in,
+                               size_t len);
+
+void gcm_initctx(void *provctx, PROV_GCM_CTX *ctx, size_t keybits,
+                 const PROV_GCM_HW *hw, size_t ivlen_min)
+{
+    ctx->pad = 1;
+    ctx->mode = EVP_CIPH_GCM_MODE;
+    ctx->taglen = UNINITIALISED_SIZET;
+    ctx->tls_aad_len = UNINITIALISED_SIZET;
+    ctx->ivlen_min = ivlen_min;
+    ctx->ivlen = (EVP_GCM_TLS_FIXED_IV_LEN + EVP_GCM_TLS_EXPLICIT_IV_LEN);
+    ctx->keylen = keybits / 8;
+    ctx->hw = hw;
+    ctx->libctx = PROV_LIBRARY_CONTEXT_OF(provctx);
+}
+
+static int gcm_init(void *vctx, const unsigned char *key, size_t keylen,
+                    const unsigned char *iv, size_t ivlen, int enc)
+{
+    PROV_GCM_CTX *ctx = (PROV_GCM_CTX *)vctx;
+
+    ctx->enc = enc;
+
+    if (iv != NULL) {
+        if (ivlen < ctx->ivlen_min || ivlen > sizeof(ctx->iv)) {
+            ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH);
+            return 0;
+        }
+        ctx->ivlen = ivlen;
+        memcpy(ctx->iv, iv, ivlen);
+        ctx->iv_state = IV_STATE_BUFFERED;
+    }
+
+    if (key != NULL) {
+        if (keylen != ctx->keylen) {
+            ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
+            return 0;
+        }
+        return ctx->hw->setkey(ctx, key, ctx->keylen);
+    }
+    return 1;
+}
+
+int gcm_einit(void *vctx, const unsigned char *key, size_t keylen,
+              const unsigned char *iv, size_t ivlen)
+{
+    return gcm_init(vctx, key, keylen, iv, ivlen, 1);
+}
+
+int gcm_dinit(void *vctx, const unsigned char *key, size_t keylen,
+              const unsigned char *iv, size_t ivlen)
+{
+    return gcm_init(vctx, key, keylen, iv, ivlen, 0);
+}
+
+int gcm_get_ctx_params(void *vctx, OSSL_PARAM params[])
+{
+    PROV_GCM_CTX *ctx = (PROV_GCM_CTX *)vctx;
+    OSSL_PARAM *p;
+    size_t sz;
+
+    p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IVLEN);
+    if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->ivlen)) {
+        ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+        return 0;
+    }
+    p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_KEYLEN);
+    if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->keylen)) {
+        ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+        return 0;
+    }
+    p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TAGLEN);
+    if (p != NULL) {
+        size_t taglen = (ctx->taglen != UNINITIALISED_SIZET) ? ctx->taglen :
+                         GCM_TAG_MAX_SIZE;
+
+        if (!OSSL_PARAM_set_size_t(p, taglen)) {
+            ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+            return 0;
+        }
+    }
+
+    p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IV);
+    if (p != NULL) {
+        if (ctx->iv_gen != 1 && ctx->iv_gen_rand != 1)
+            return 0;
+        if (ctx->ivlen != p->data_size) {
+            ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH);
+            return 0;
+        }
+        if (!OSSL_PARAM_set_octet_string(p, ctx->iv, ctx->ivlen)) {
+            ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+            return 0;
+        }
+    }
+
+    p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TLS1_AAD_PAD);
+    if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->tls_aad_pad_sz)) {
+        ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+        return 0;
+    }
+    p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TAG);
+    if (p != NULL) {
+        sz = p->data_size;
+        if (sz == 0
+            || sz > EVP_GCM_TLS_TAG_LEN
+            || !ctx->enc
+            || ctx->taglen == UNINITIALISED_SIZET) {
+            ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_TAG);
+            return 0;
+        }
+        if (!OSSL_PARAM_set_octet_string(p, ctx->buf, sz)) {
+            ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+            return 0;
+        }
+    }
+
+    return 1;
+}
+
+int gcm_set_ctx_params(void *vctx, const OSSL_PARAM params[])
+{
+    PROV_GCM_CTX *ctx = (PROV_GCM_CTX *)vctx;
+    const OSSL_PARAM *p;
+    size_t sz;
+    void *vp;
+
+    p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TAG);
+    if (p != NULL) {
+        vp = ctx->buf;
+        if (!OSSL_PARAM_get_octet_string(p, &vp, EVP_GCM_TLS_TAG_LEN, &sz)) {
+            ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
+            return 0;
+        }
+        if (sz == 0 || ctx->enc) {
+            ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_TAG);
+            return 0;
+        }
+        ctx->taglen = sz;
+    }
+
+    p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_IVLEN);
+    if (p != NULL) {
+        if (!OSSL_PARAM_get_size_t(p, &sz)) {
+            ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
+            return 0;
+        }
+        if (sz == 0 || sz > sizeof(ctx->iv)) {
+            ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH);
+            return 0;
+        }
+        ctx->ivlen = sz;
+    }
+
+    p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TLS1_AAD);
+    if (p != NULL) {
+        if (p->data_type != OSSL_PARAM_OCTET_STRING) {
+            ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
+            return 0;
+        }
+        sz = gcm_tls_init(ctx, p->data, p->data_size);
+        if (sz == 0) {
+            ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_AAD);
+            return 0;
+        }
+        ctx->tls_aad_pad_sz = sz;
+    }
+
+    p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TLS1_IV_FIXED);
+    if (p != NULL) {
+        if (p->data_type != OSSL_PARAM_OCTET_STRING) {
+            ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
+            return 0;
+        }
+        if (gcm_tls_iv_set_fixed(ctx, p->data, p->data_size) == 0) {
+            ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
+            return 0;
+        }
+    }
+
+    return 1;
+}
+
+int gcm_stream_update(void *vctx, unsigned char *out, size_t *outl,
+                      size_t outsize, const unsigned char *in, size_t inl)
+{
+    PROV_GCM_CTX *ctx = (PROV_GCM_CTX *)vctx;
+
+    if (inl == 0) {
+        *outl = 0;
+        return 1;
+    }
+
+    if (outsize < inl) {
+        ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
+        return -1;
+    }
+
+    if (gcm_cipher_internal(ctx, out, outl, in, inl) <= 0) {
+        ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);
+        return -1;
+    }
+    return 1;
+}
+
+int gcm_stream_final(void *vctx, unsigned char *out, size_t *outl,
+                     size_t outsize)
+{
+    PROV_GCM_CTX *ctx = (PROV_GCM_CTX *)vctx;
+    int i;
+
+    i = gcm_cipher_internal(ctx, out, outl, NULL, 0);
+    if (i <= 0)
+        return 0;
+
+    *outl = 0;
+    return 1;
+}
+
+int gcm_cipher(void *vctx,
+               unsigned char *out, size_t *outl, size_t outsize,
+               const unsigned char *in, size_t inl)
+{
+    PROV_GCM_CTX *ctx = (PROV_GCM_CTX *)vctx;
+
+    if (outsize < inl) {
+        ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
+        return 0;
+    }
+
+    if (gcm_cipher_internal(ctx, out, outl, in, inl) <= 0)
+        return 0;
+
+    *outl = inl;
+    return 1;
+}
+
+/*
+ * See SP800-38D (GCM) Section 8 "Uniqueness requirement on IVS and keys"
+ *
+ * See also 8.2.2 RBG-based construction.
+ * Random construction consists of a free field (which can be NULL) and a
+ * random field which will use a DRBG that can return at least 96 bits of
+ * entropy strength. (The DRBG must be seeded by the FIPS module).
+ */
+static int gcm_iv_generate(PROV_GCM_CTX *ctx, int offset)
+{
+    int sz = ctx->ivlen - offset;
+
+    /* Must be at least 96 bits */
+    if (sz <= 0 || ctx->ivlen < GCM_IV_DEFAULT_SIZE)
+        return 0;
+
+    /* Use DRBG to generate random iv */
+    if (rand_bytes_ex(ctx->libctx, ctx->iv + offset, sz) <= 0)
+        return 0;
+    ctx->iv_state = IV_STATE_BUFFERED;
+    ctx->iv_gen_rand = 1;
+    return 1;
+}
+
+static int gcm_cipher_internal(PROV_GCM_CTX *ctx, unsigned char *out,
+                               size_t *padlen, const unsigned char *in,
+                               size_t len)
+{
+    size_t olen = 0;
+    int rv = 0;
+    const PROV_GCM_HW *hw = ctx->hw;
+
+    if (ctx->tls_aad_len != UNINITIALISED_SIZET)
+        return gcm_tls_cipher(ctx, out, padlen, in, len);
+
+    if (!ctx->key_set || ctx->iv_state == IV_STATE_FINISHED)
+        goto err;
+
+    /*
+     * FIPS requires generation of AES-GCM IV's inside the FIPS module.
+     * The IV can still be set externally (the security policy will state that
+     * this is not FIPS compliant). There are some applications
+     * where setting the IV externally is the only option available.
+     */
+    if (ctx->iv_state == IV_STATE_UNINITIALISED) {
+        if (!ctx->enc || !gcm_iv_generate(ctx, 0))
+            goto err;
+    }
+
+    if (ctx->iv_state == IV_STATE_BUFFERED) {
+        if (!hw->setiv(ctx, ctx->iv, ctx->ivlen))
+            goto err;
+        ctx->iv_state = IV_STATE_COPIED;
+    }
+
+    if (in != NULL) {
+        /*  The input is AAD if out is NULL */
+        if (out == NULL) {
+            if (!hw->aadupdate(ctx, in, len))
+                goto err;
+        } else {
+            /* The input is ciphertext OR plaintext */
+            if (!hw->cipherupdate(ctx, in, len, out))
+                goto err;
+        }
+    } else {
+        /* The tag must be set before actually decrypting data */
+        if (!ctx->enc && ctx->taglen == UNINITIALISED_SIZET)
+            goto err;
+        if (!hw->cipherfinal(ctx, ctx->buf))
+            goto err;
+        ctx->iv_state = IV_STATE_FINISHED; /* Don't reuse the IV */
+        goto finish;
+    }
+    olen = len;
+finish:
+    rv = 1;
+err:
+    *padlen = olen;
+    return rv;
+}
+
+static int gcm_tls_init(PROV_GCM_CTX *dat, unsigned char *aad, size_t aad_len)
+{
+    unsigned char *buf;
+    size_t len;
+
+    if (aad_len != EVP_AEAD_TLS1_AAD_LEN)
+       return 0;
+
+    /* Save the aad for later use. */
+    buf = dat->buf;
+    memcpy(buf, aad, aad_len);
+    dat->tls_aad_len = aad_len;
+    dat->tls_enc_records = 0;
+
+    len = buf[aad_len - 2] << 8 | buf[aad_len - 1];
+    /* Correct length for explicit iv. */
+    if (len < EVP_GCM_TLS_EXPLICIT_IV_LEN)
+        return 0;
+    len -= EVP_GCM_TLS_EXPLICIT_IV_LEN;
+
+    /* If decrypting correct for tag too. */
+    if (!dat->enc) {
+        if (len < EVP_GCM_TLS_TAG_LEN)
+            return 0;
+        len -= EVP_GCM_TLS_TAG_LEN;
+    }
+    buf[aad_len - 2] = (unsigned char)(len >> 8);
+    buf[aad_len - 1] = (unsigned char)(len & 0xff);
+    /* Extra padding: tag appended to record. */
+    return EVP_GCM_TLS_TAG_LEN;
+}
+
+static int gcm_tls_iv_set_fixed(PROV_GCM_CTX *ctx, unsigned char *iv,
+                                size_t len)
+{
+    /* Special case: -1 length restores whole IV */
+    if (len == (size_t)-1) {
+        memcpy(ctx->iv, iv, ctx->ivlen);
+        ctx->iv_gen = 1;
+        ctx->iv_state = IV_STATE_BUFFERED;
+        return 1;
+    }
+    /* Fixed field must be at least 4 bytes and invocation field at least 8 */
+    if ((len < EVP_GCM_TLS_FIXED_IV_LEN)
+        || (ctx->ivlen - (int)len) < EVP_GCM_TLS_EXPLICIT_IV_LEN)
+            return 0;
+    if (len > 0)
+        memcpy(ctx->iv, iv, len);
+    if (ctx->enc
+        && rand_bytes_ex(ctx->libctx, ctx->iv + len, ctx->ivlen - len) <= 0)
+            return 0;
+    ctx->iv_gen = 1;
+    ctx->iv_state = IV_STATE_BUFFERED;
+    return 1;
+}
+
+/* increment counter (64-bit int) by 1 */
+static void ctr64_inc(unsigned char *counter)
+{
+    int n = 8;
+    unsigned char c;
+
+    do {
+        --n;
+        c = counter[n];
+        ++c;
+        counter[n] = c;
+        if (c > 0)
+            return;
+    } while (n > 0);
+}
+
+/*
+ * Handle TLS GCM packet format. This consists of the last portion of the IV
+ * followed by the payload and finally the tag. On encrypt generate IV,
+ * encrypt payload and write the tag. On verify retrieve IV, decrypt payload
+ * and verify tag.
+ */
+static int gcm_tls_cipher(PROV_GCM_CTX *ctx, unsigned char *out, size_t *padlen,
+                          const unsigned char *in, size_t len)
+{
+    int rv = 0;
+    size_t arg = EVP_GCM_TLS_EXPLICIT_IV_LEN;
+    size_t plen = 0;
+    unsigned char *tag = NULL;
+
+    if (!ctx->key_set)
+        goto err;
+
+    /* Encrypt/decrypt must be performed in place */
+    if (out != in || len < (EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN))
+        goto err;
+
+    /*
+     * Check for too many keys as per FIPS 140-2 IG A.5 "Key/IV Pair Uniqueness
+     * Requirements from SP 800-38D".  The requirements is for one party to the
+     * communication to fail after 2^64 - 1 keys.  We do this on the encrypting
+     * side only.
+     */
+    if (ctx->enc && ++ctx->tls_enc_records == 0) {
+        ERR_raise(ERR_LIB_PROV, EVP_R_TOO_MANY_RECORDS);
+        goto err;
+    }
+
+    if (ctx->iv_gen == 0)
+        goto err;
+    /*
+     * Set IV from start of buffer or generate IV and write to start of
+     * buffer.
+     */
+    if (ctx->enc) {
+        if (!ctx->hw->setiv(ctx, ctx->iv, ctx->ivlen))
+            goto err;
+        if (arg > ctx->ivlen)
+            arg = ctx->ivlen;
+        memcpy(out, ctx->iv + ctx->ivlen - arg, arg);
+        /*
+         * Invocation field will be at least 8 bytes in size and so no need
+         * to check wrap around or increment more than last 8 bytes.
+         */
+        ctr64_inc(ctx->iv + ctx->ivlen - 8);
+    } else {
+        memcpy(ctx->iv + ctx->ivlen - arg, out, arg);
+        if (!ctx->hw->setiv(ctx, ctx->iv, ctx->ivlen))
+            goto err;
+    }
+    ctx->iv_state = IV_STATE_COPIED;
+
+    /* Fix buffer and length to point to payload */
+    in += EVP_GCM_TLS_EXPLICIT_IV_LEN;
+    out += EVP_GCM_TLS_EXPLICIT_IV_LEN;
+    len -= EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN;
+
+    tag = ctx->enc ? out + len : (unsigned char *)in + len;
+    if (!ctx->hw->oneshot(ctx, ctx->buf, ctx->tls_aad_len, in, len, out, tag,
+                          EVP_GCM_TLS_TAG_LEN)) {
+        if (!ctx->enc)
+            OPENSSL_cleanse(out, len);
+        goto err;
+    }
+    if (ctx->enc)
+        plen =  len + EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN;
+    else
+        plen = len;
+
+    rv = 1;
+err:
+    ctx->iv_state = IV_STATE_FINISHED;
+    ctx->tls_aad_len = UNINITIALISED_SIZET;
+    *padlen = plen;
+    return rv;
+}
diff --git a/providers/implementations/ciphers/ciphercommon_gcm_hw.c b/providers/implementations/ciphers/ciphercommon_gcm_hw.c
new file mode 100644 (file)
index 0000000..60c7ac5
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2001-2019 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "prov/ciphercommon.h"
+#include "prov/ciphercommon_gcm.h"
+
+
+int gcm_setiv(PROV_GCM_CTX *ctx, const unsigned char *iv, size_t ivlen)
+{
+    CRYPTO_gcm128_setiv(&ctx->gcm, iv, ivlen);
+    return 1;
+}
+
+int gcm_aad_update(PROV_GCM_CTX *ctx, const unsigned char *aad, size_t aad_len)
+{
+    return CRYPTO_gcm128_aad(&ctx->gcm, aad, aad_len) == 0;
+}
+
+int gcm_cipher_update(PROV_GCM_CTX *ctx, const unsigned char *in,
+                      size_t len, unsigned char *out)
+{
+    if (ctx->enc) {
+        if (ctx->ctr != NULL) {
+#if defined(AES_GCM_ASM)
+            size_t bulk = 0;
+
+            if (len >= 32 && AES_GCM_ASM(ctx)) {
+                size_t res = (16 - ctx->gcm.mres) % 16;
+
+                if (CRYPTO_gcm128_encrypt(&ctx->gcm, in, out, res))
+                    return 0;
+                bulk = aesni_gcm_encrypt(in + res, out + res, len - res,
+                                         ctx->gcm.key,
+                                         ctx->gcm.Yi.c, ctx->gcm.Xi.u);
+                ctx->gcm.len.u[1] += bulk;
+                bulk += res;
+            }
+            if (CRYPTO_gcm128_encrypt_ctr32(&ctx->gcm, in + bulk, out + bulk,
+                                            len - bulk, ctx->ctr))
+                return 0;
+#else
+            if (CRYPTO_gcm128_encrypt_ctr32(&ctx->gcm, in, out, len, ctx->ctr))
+                return 0;
+#endif /* AES_GCM_ASM */
+        } else {
+            if (CRYPTO_gcm128_encrypt(&ctx->gcm, in, out, len))
+                return 0;
+        }
+    } else {
+        if (ctx->ctr != NULL) {
+#if defined(AES_GCM_ASM)
+            size_t bulk = 0;
+
+            if (len >= 16 && AES_GCM_ASM(ctx)) {
+                size_t res = (16 - ctx->gcm.mres) % 16;
+
+                if (CRYPTO_gcm128_decrypt(&ctx->gcm, in, out, res))
+                    return -1;
+
+                bulk = aesni_gcm_decrypt(in + res, out + res, len - res,
+                                         ctx->gcm.key,
+                                         ctx->gcm.Yi.c, ctx->gcm.Xi.u);
+                ctx->gcm.len.u[1] += bulk;
+                bulk += res;
+            }
+            if (CRYPTO_gcm128_decrypt_ctr32(&ctx->gcm, in + bulk, out + bulk,
+                                            len - bulk, ctx->ctr))
+                return 0;
+#else
+            if (CRYPTO_gcm128_decrypt_ctr32(&ctx->gcm, in, out, len, ctx->ctr))
+                return 0;
+#endif /* AES_GCM_ASM */
+        } else {
+            if (CRYPTO_gcm128_decrypt(&ctx->gcm, in, out, len))
+                return 0;
+        }
+    }
+    return 1;
+}
+
+int gcm_cipher_final(PROV_GCM_CTX *ctx, unsigned char *tag)
+{
+    if (ctx->enc) {
+        CRYPTO_gcm128_tag(&ctx->gcm, tag, GCM_TAG_MAX_SIZE);
+        ctx->taglen = GCM_TAG_MAX_SIZE;
+    } else {
+        if (CRYPTO_gcm128_finish(&ctx->gcm, tag, ctx->taglen) != 0)
+            return 0;
+    }
+    return 1;
+}
+
+int gcm_one_shot(PROV_GCM_CTX *ctx, unsigned char *aad, size_t aad_len,
+                 const unsigned char *in, size_t in_len,
+                 unsigned char *out, unsigned char *tag, size_t tag_len)
+{
+    int ret = 0;
+
+    /* Use saved AAD */
+    if (!ctx->hw->aadupdate(ctx, aad, aad_len))
+        goto err;
+    if (!ctx->hw->cipherupdate(ctx, in, in_len, out))
+        goto err;
+    ctx->taglen = GCM_TAG_MAX_SIZE;
+    if (!ctx->hw->cipherfinal(ctx, tag))
+        goto err;
+    ret = 1;
+
+err:
+    return ret;
+}
diff --git a/providers/implementations/ciphers/ciphercommon_hw.c b/providers/implementations/ciphers/ciphercommon_hw.c
new file mode 100644 (file)
index 0000000..f1c466e
--- /dev/null
@@ -0,0 +1,189 @@
+/*
+ * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "prov/ciphercommon.h"
+
+/*-
+ * The generic cipher functions for cipher modes cbc, ecb, ofb, cfb and ctr.
+ * Used if there is no special hardware implementations.
+ */
+int cipher_hw_generic_cbc(PROV_CIPHER_CTX *dat, unsigned char *out,
+                          const unsigned char *in, size_t len)
+{
+    if (dat->stream.cbc)
+        (*dat->stream.cbc) (in, out, len, dat->ks, dat->iv, dat->enc);
+    else if (dat->enc)
+        CRYPTO_cbc128_encrypt(in, out, len, dat->ks, dat->iv, dat->block);
+    else
+        CRYPTO_cbc128_decrypt(in, out, len, dat->ks, dat->iv, dat->block);
+
+    return 1;
+}
+
+int cipher_hw_generic_ecb(PROV_CIPHER_CTX *dat, unsigned char *out,
+                          const unsigned char *in, size_t len)
+{
+    size_t i, bl = dat->blocksize;
+
+    if (len < bl)
+        return 1;
+
+    for (i = 0, len -= bl; i <= len; i += bl)
+        (*dat->block) (in + i, out + i, dat->ks);
+
+    return 1;
+}
+
+int cipher_hw_generic_ofb128(PROV_CIPHER_CTX *dat, unsigned char *out,
+                             const unsigned char *in, size_t len)
+{
+    int num = dat->num;
+
+    CRYPTO_ofb128_encrypt(in, out, len, dat->ks, dat->iv, &num, dat->block);
+    dat->num = num;
+
+    return 1;
+}
+
+int cipher_hw_generic_cfb128(PROV_CIPHER_CTX *dat, unsigned char *out,
+                             const unsigned char *in, size_t len)
+{
+    int num = dat->num;
+
+    CRYPTO_cfb128_encrypt(in, out, len, dat->ks, dat->iv, &num, dat->enc,
+                          dat->block);
+    dat->num = num;
+
+    return 1;
+}
+
+int cipher_hw_generic_cfb8(PROV_CIPHER_CTX *dat, unsigned char *out,
+                           const unsigned char *in, size_t len)
+{
+    int num = dat->num;
+
+    CRYPTO_cfb128_8_encrypt(in, out, len, dat->ks, dat->iv, &num, dat->enc,
+                            dat->block);
+    dat->num = num;
+
+    return 1;
+}
+
+int cipher_hw_generic_cfb1(PROV_CIPHER_CTX *dat, unsigned char *out,
+                           const unsigned char *in, size_t len)
+{
+    int num = dat->num;
+
+    if ((dat->flags & EVP_CIPH_FLAG_LENGTH_BITS) != 0) {
+        CRYPTO_cfb128_1_encrypt(in, out, len, dat->ks, dat->iv, &num,
+                                dat->enc, dat->block);
+        dat->num = num;
+        return 1;
+    }
+
+    while (len >= MAXBITCHUNK) {
+        CRYPTO_cfb128_1_encrypt(in, out, MAXBITCHUNK * 8, dat->ks,
+                                dat->iv, &num, dat->enc, dat->block);
+        len -= MAXBITCHUNK;
+        out += MAXBITCHUNK;
+        in  += MAXBITCHUNK;
+    }
+    if (len)
+        CRYPTO_cfb128_1_encrypt(in, out, len * 8, dat->ks, dat->iv, &num,
+                                dat->enc, dat->block);
+
+    dat->num = num;
+
+    return 1;
+}
+
+int cipher_hw_generic_ctr(PROV_CIPHER_CTX *dat, unsigned char *out,
+                          const unsigned char *in, size_t len)
+{
+    unsigned int num = dat->num;
+
+    if (dat->stream.ctr)
+        CRYPTO_ctr128_encrypt_ctr32(in, out, len, dat->ks, dat->iv, dat->buf,
+                                    &num, dat->stream.ctr);
+    else
+        CRYPTO_ctr128_encrypt(in, out, len, dat->ks, dat->iv, dat->buf,
+                              &num, dat->block);
+    dat->num = num;
+
+    return 1;
+}
+
+/*-
+ * The chunked cipher functions for cipher modes cbc, ecb, ofb, cfb and ctr.
+ * Used if there is no special hardware implementations.
+ */
+
+int cipher_hw_chunked_cbc(PROV_CIPHER_CTX *ctx, unsigned char *out,
+                          const unsigned char *in, size_t inl)
+{
+    while (inl >= MAXCHUNK) {
+        cipher_hw_generic_cbc(ctx, out, in, MAXCHUNK);
+        inl -= MAXCHUNK;
+        in  += MAXCHUNK;
+        out += MAXCHUNK;
+    }
+    if (inl > 0)
+        cipher_hw_generic_cbc(ctx, out, in, inl);
+    return 1;
+}
+
+int cipher_hw_chunked_cfb8(PROV_CIPHER_CTX *ctx, unsigned char *out,
+                           const unsigned char *in, size_t inl)
+{
+    size_t chunk = MAXCHUNK;
+
+    if (inl < chunk)
+        chunk = inl;
+    while (inl > 0 && inl >= chunk) {
+        cipher_hw_generic_cfb8(ctx, out, in, inl);
+        inl -= chunk;
+        in += chunk;
+        out += chunk;
+        if (inl < chunk)
+            chunk = inl;
+    }
+    return 1;
+}
+
+int cipher_hw_chunked_cfb128(PROV_CIPHER_CTX *ctx, unsigned char *out,
+                             const unsigned char *in, size_t inl)
+{
+    size_t chunk = MAXCHUNK;
+
+    if (inl < chunk)
+        chunk = inl;
+    while (inl > 0 && inl >= chunk) {
+        cipher_hw_generic_cfb128(ctx, out, in, inl);
+        inl -= chunk;
+        in += chunk;
+        out += chunk;
+        if (inl < chunk)
+            chunk = inl;
+    }
+    return 1;
+}
+
+int cipher_hw_chunked_ofb128(PROV_CIPHER_CTX *ctx, unsigned char *out,
+                             const unsigned char *in, size_t inl)
+{
+    while (inl >= MAXCHUNK) {
+        cipher_hw_generic_ofb128(ctx, out, in, MAXCHUNK);
+        inl -= MAXCHUNK;
+        in  += MAXCHUNK;
+        out += MAXCHUNK;
+    }
+    if (inl > 0)
+        cipher_hw_generic_ofb128(ctx, out, in, inl);
+    return 1;
+}
diff --git a/providers/implementations/ciphers/ciphercommon_local.h b/providers/implementations/ciphers/ciphercommon_local.h
new file mode 100644 (file)
index 0000000..1c4716f
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+ * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "prov/ciphercommon.h"
+
+void padblock(unsigned char *buf, size_t *buflen, size_t blocksize);
+int unpadblock(unsigned char *buf, size_t *buflen, size_t blocksize);
index 2026de95d7b3744a58530f615dcc1eab86365c40..a90636cbb9dbc9dd6b24c1d9e26337566ee882cb 100644 (file)
@@ -1,6 +1,8 @@
 # We make separate GOAL variables for each algorithm, to make it easy to
 # switch each to the Legacy provider when needed.
 
+$COMMON_GOAL=../../libcommon.a
+
 $SHA1_GOAL=../../libimplementations.a
 $SHA2_GOAL=../../libimplementations.a
 $SHA3_GOAL=../../libimplementations.a
@@ -14,11 +16,12 @@ $MDC2_GOAL=../../liblegacy.a
 $WHIRLPOOL_GOAL=../../liblegacy.a
 $RIPEMD_GOAL=../../liblegacy.a
 
+# This source is common for all digests in all our providers.
+SOURCE[$COMMON_GOAL]=digestcommon.c
+
 SOURCE[$SHA2_GOAL]=sha2_prov.c
 SOURCE[$SHA3_GOAL]=sha3_prov.c
 
-$GOAL=../../libimplementations.a
-
 IF[{- !$disabled{blake2} -}]
   SOURCE[$BLAKE2_GOAL]=blake2_prov.c blake2b_prov.c blake2s_prov.c
 ENDIF
diff --git a/providers/implementations/digests/digestcommon.c b/providers/implementations/digests/digestcommon.c
new file mode 100644 (file)
index 0000000..9d30b2b
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "openssl/err.h"
+#include "prov/digestcommon.h"
+#include "prov/providercommonerr.h"
+
+int digest_default_get_params(OSSL_PARAM params[], size_t blksz, size_t paramsz,
+                              unsigned long flags)
+{
+    OSSL_PARAM *p = NULL;
+
+    p = OSSL_PARAM_locate(params, OSSL_DIGEST_PARAM_BLOCK_SIZE);
+    if (p != NULL && !OSSL_PARAM_set_size_t(p, blksz)) {
+        ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+        return 0;
+    }
+    p = OSSL_PARAM_locate(params, OSSL_DIGEST_PARAM_SIZE);
+    if (p != NULL && !OSSL_PARAM_set_size_t(p, paramsz)) {
+        ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+        return 0;
+    }
+    p = OSSL_PARAM_locate(params, OSSL_DIGEST_PARAM_FLAGS);
+    if (p != NULL && !OSSL_PARAM_set_ulong(p, flags)) {
+        ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
+        return 0;
+    }
+    return 1;
+}
+
+static const OSSL_PARAM digest_default_known_gettable_params[] = {
+    OSSL_PARAM_size_t(OSSL_DIGEST_PARAM_BLOCK_SIZE, NULL),
+    OSSL_PARAM_size_t(OSSL_DIGEST_PARAM_SIZE, NULL),
+    OSSL_PARAM_ulong(OSSL_DIGEST_PARAM_FLAGS, NULL),
+    OSSL_PARAM_END
+};
+const OSSL_PARAM *digest_default_gettable_params(void)
+{
+    return digest_default_known_gettable_params;
+}
diff --git a/providers/implementations/include/prov/ciphercommon.h b/providers/implementations/include/prov/ciphercommon.h
new file mode 100644 (file)
index 0000000..1072b57
--- /dev/null
@@ -0,0 +1,324 @@
+/*
+ * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <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);
+
diff --git a/providers/implementations/include/prov/ciphercommon_aead.h b/providers/implementations/include/prov/ciphercommon_aead.h
new file mode 100644 (file)
index 0000000..db938d7
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#define UNINITIALISED_SIZET ((size_t)-1)
+
+/* TODO(3.0) Figure out what flags are really needed */
+#define AEAD_FLAGS (EVP_CIPH_FLAG_AEAD_CIPHER           \
+                    | EVP_CIPH_CUSTOM_IV                \
+                    | EVP_CIPH_ALWAYS_CALL_INIT         \
+                    | EVP_CIPH_CTRL_INIT                \
+                    | EVP_CIPH_CUSTOM_COPY)
+
+#define IMPLEMENT_aead_cipher(alg, lc, UCMODE, flags, kbits, blkbits, ivbits)  \
+static OSSL_OP_cipher_get_params_fn alg##_##kbits##_##lc##_get_params;         \
+static int alg##_##kbits##_##lc##_get_params(OSSL_PARAM params[])              \
+{                                                                              \
+    return cipher_generic_get_params(params, EVP_CIPH_##UCMODE##_MODE,         \
+                                     flags, kbits, blkbits, ivbits);           \
+}                                                                              \
+static OSSL_OP_cipher_newctx_fn alg##kbits##lc##_newctx;                       \
+static void * alg##kbits##lc##_newctx(void *provctx)                           \
+{                                                                              \
+    return alg##_##lc##_newctx(provctx, kbits);                                \
+}                                                                              \
+const OSSL_DISPATCH alg##kbits##lc##_functions[] = {                           \
+    { OSSL_FUNC_CIPHER_NEWCTX, (void (*)(void))alg##kbits##lc##_newctx },      \
+    { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))alg##_##lc##_freectx },        \
+    { OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void)) lc##_einit },            \
+    { OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void)) lc##_dinit },            \
+    { OSSL_FUNC_CIPHER_UPDATE, (void (*)(void)) lc##_stream_update },          \
+    { OSSL_FUNC_CIPHER_FINAL, (void (*)(void)) lc##_stream_final },            \
+    { OSSL_FUNC_CIPHER_CIPHER, (void (*)(void)) lc##_cipher },                 \
+    { OSSL_FUNC_CIPHER_GET_PARAMS,                                             \
+      (void (*)(void)) alg##_##kbits##_##lc##_get_params },                    \
+    { OSSL_FUNC_CIPHER_GET_CTX_PARAMS,                                         \
+      (void (*)(void)) lc##_get_ctx_params },                                  \
+    { OSSL_FUNC_CIPHER_SET_CTX_PARAMS,                                         \
+      (void (*)(void)) lc##_set_ctx_params },                                  \
+    { OSSL_FUNC_CIPHER_GETTABLE_PARAMS,                                        \
+      (void (*)(void))cipher_generic_gettable_params },                        \
+    { OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS,                                    \
+      (void (*)(void))cipher_aead_gettable_ctx_params },                       \
+    { OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS,                                    \
+      (void (*)(void))cipher_aead_settable_ctx_params },                       \
+    { 0, NULL }                                                                \
+}
diff --git a/providers/implementations/include/prov/ciphercommon_ccm.h b/providers/implementations/include/prov/ciphercommon_ccm.h
new file mode 100644 (file)
index 0000000..0c2af15
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "ciphercommon_aead.h"
+
+typedef struct prov_ccm_hw_st PROV_CCM_HW;
+
+#if defined(OPENSSL_CPUID_OBJ) && defined(__s390__)
+/*-
+ * KMAC-AES parameter block - begin
+ * (see z/Architecture Principles of Operation >= SA22-7832-08)
+ */
+typedef struct S390X_kmac_params_st {
+    union {
+        unsigned long long g[2];
+        unsigned char b[16];
+    } icv;
+    unsigned char k[32];
+} S390X_KMAC_PARAMS;
+/* KMAC-AES parameter block - end */
+#endif
+
+/* Base structure that is shared by AES & ARIA for CCM MODE */
+typedef struct prov_ccm_st {
+    unsigned int enc : 1;
+    unsigned int key_set : 1;  /* Set if key initialised */
+    unsigned int iv_set : 1;   /* Set if an iv is set */
+    unsigned int tag_set : 1;  /* Set if tag is valid */
+    unsigned int len_set : 1;  /* Set if message length set */
+    size_t l, m;               /* L and M parameters from RFC3610 */
+    size_t keylen;
+    size_t tls_aad_len;        /* TLS AAD length */
+    size_t tls_aad_pad_sz;
+    unsigned char iv[AES_BLOCK_SIZE];
+    unsigned char buf[AES_BLOCK_SIZE];
+    CCM128_CONTEXT ccm_ctx;
+    ccm128_f str;
+    const PROV_CCM_HW *hw;     /* hardware specific methods  */
+} PROV_CCM_CTX;
+
+typedef struct prov_aes_ccm_ctx_st {
+    PROV_CCM_CTX base;         /* Must be first */
+    union {
+        OSSL_UNION_ALIGN;
+        /*-
+         * Padding is chosen so that s390x.kmac.k overlaps with ks.ks and
+         * fc with ks.ks.rounds. Remember that on s390x, an AES_KEY's
+         * rounds field is used to store the function code and that the key
+         * schedule is not stored (if aes hardware support is detected).
+         */
+        struct {
+            unsigned char pad[16];
+            AES_KEY ks;
+        } ks;
+#if defined(OPENSSL_CPUID_OBJ) && defined(__s390__)
+        struct {
+            S390X_KMAC_PARAMS kmac;
+            unsigned long long blocks;
+            union {
+                unsigned long long g[2];
+                unsigned char b[AES_BLOCK_SIZE];
+            } nonce;
+            union {
+                unsigned long long g[2];
+                unsigned char b[AES_BLOCK_SIZE];
+            } buf;
+            unsigned char dummy_pad[168];
+            unsigned int fc;   /* fc has same offset as ks.ks.rounds */
+        } s390x;
+#endif /* defined(OPENSSL_CPUID_OBJ) && defined(__s390__) */
+    } ccm;
+} PROV_AES_CCM_CTX;
+
+PROV_CIPHER_FUNC(int, CCM_cipher, (PROV_CCM_CTX *ctx, unsigned char *out,      \
+                                   size_t *padlen, const unsigned char *in,    \
+                                   size_t len));
+PROV_CIPHER_FUNC(int, CCM_setkey, (PROV_CCM_CTX *ctx,                          \
+                                   const unsigned char *key, size_t keylen));
+PROV_CIPHER_FUNC(int, CCM_setiv, (PROV_CCM_CTX *dat,                           \
+                                  const unsigned char *iv, size_t ivlen,       \
+                                  size_t mlen));
+PROV_CIPHER_FUNC(int, CCM_setaad, (PROV_CCM_CTX *ctx,                          \
+                                   const unsigned char *aad, size_t aadlen));
+PROV_CIPHER_FUNC(int, CCM_auth_encrypt, (PROV_CCM_CTX *ctx,                    \
+                                         const unsigned char *in,              \
+                                         unsigned char *out, size_t len,       \
+                                         unsigned char *tag, size_t taglen));
+PROV_CIPHER_FUNC(int, CCM_auth_decrypt, (PROV_CCM_CTX *ctx,                    \
+                                         const unsigned char *in,              \
+                                         unsigned char *out, size_t len,       \
+                                         unsigned char *tag, size_t taglen));
+PROV_CIPHER_FUNC(int, CCM_gettag, (PROV_CCM_CTX *ctx,                          \
+                                   unsigned char *tag,  size_t taglen));
+
+/*
+ * CCM Mode internal method table used to handle hardware specific differences,
+ * (and different algorithms).
+ */
+struct prov_ccm_hw_st {
+    OSSL_CCM_setkey_fn setkey;
+    OSSL_CCM_setiv_fn setiv;
+    OSSL_CCM_setaad_fn setaad;
+    OSSL_CCM_auth_encrypt_fn auth_encrypt;
+    OSSL_CCM_auth_decrypt_fn auth_decrypt;
+    OSSL_CCM_gettag_fn gettag;
+};
+
+const PROV_CCM_HW *PROV_AES_HW_ccm(size_t keylen);
+
+OSSL_OP_cipher_encrypt_init_fn ccm_einit;
+OSSL_OP_cipher_decrypt_init_fn ccm_dinit;
+OSSL_OP_cipher_get_ctx_params_fn ccm_get_ctx_params;
+OSSL_OP_cipher_set_ctx_params_fn ccm_set_ctx_params;
+OSSL_OP_cipher_update_fn ccm_stream_update;
+OSSL_OP_cipher_final_fn ccm_stream_final;
+OSSL_OP_cipher_cipher_fn ccm_cipher;
+void ccm_initctx(PROV_CCM_CTX *ctx, size_t keybits, const PROV_CCM_HW *hw);
+
+int ccm_generic_setiv(PROV_CCM_CTX *ctx, const unsigned char *nonce,
+                      size_t nlen, size_t mlen);
+int ccm_generic_setaad(PROV_CCM_CTX *ctx, const unsigned char *aad, size_t alen);
+int ccm_generic_gettag(PROV_CCM_CTX *ctx, unsigned char *tag, size_t tlen);
+int ccm_generic_auth_encrypt(PROV_CCM_CTX *ctx, const unsigned char *in,
+                             unsigned char *out, size_t len,
+                             unsigned char *tag, size_t taglen);
+int ccm_generic_auth_decrypt(PROV_CCM_CTX *ctx, const unsigned char *in,
+                             unsigned char *out, size_t len,
+                             unsigned char *expected_tag, size_t taglen);
diff --git a/providers/implementations/include/prov/ciphercommon_gcm.h b/providers/implementations/include/prov/ciphercommon_gcm.h
new file mode 100644 (file)
index 0000000..1932e14
--- /dev/null
@@ -0,0 +1,160 @@
+
+/*
+ * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <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;
diff --git a/providers/implementations/include/prov/digestcommon.h b/providers/implementations/include/prov/digestcommon.h
new file mode 100644 (file)
index 0000000..e5b76ff
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_PROVIDERS_DIGESTCOMMON_H
+# define OSSL_PROVIDERS_DIGESTCOMMON_H
+
+# include <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 */