[openssl] master update

Matt Caswell matt at openssl.org
Fri Apr 19 08:36:24 UTC 2019


The branch master has been updated
       via  6caf7f3aec5484ee65067e9671299d3411565dc1 (commit)
       via  64adf9aac765f0872c33d225c57e5c128f5d7c69 (commit)
       via  3a7b15e484f950d4cb4061d93839802ecb74f8e5 (commit)
       via  dcd446f1005f5c99768965a11c10dd6c7b6aee59 (commit)
       via  3b94944cf2d6476d1b8ac7949bf8b28abb644426 (commit)
       via  344cfa34e5b07f8b8b7f1e70f47f5d265c9c1185 (commit)
       via  819a7ae9fc7721f675757c0925821f91b20dfc8f (commit)
       via  75dd6d64f1f3afd6fda024d8d91bc2a216bbfcf9 (commit)
       via  ed98df51c69717529dd7d775b35430c036216339 (commit)
       via  718b133a5328108099ecac0bf40d8fd4886e7b64 (commit)
       via  f4a129bb8dc26488e29b06e06e96a76c93f966be (commit)
       via  861b8f8747965bf98d9dd328196b8092e709c99d (commit)
       via  aab26e6f7b437f7d4bace03cd855a33d7a34d927 (commit)
       via  df05f2ce6d496232f3c86acb299a128d0eb3ef42 (commit)
      from  1393722af384cdf310645c598bbd06a3bbaa2f31 (commit)


- Log -----------------------------------------------------------------
commit 6caf7f3aec5484ee65067e9671299d3411565dc1
Author: Matt Caswell <matt at openssl.org>
Date:   Thu Apr 18 17:43:05 2019 +0100

    Create provider errors and use them
    
    Reviewed-by: Paul Dale <paul.dale at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/8700)

commit 64adf9aac765f0872c33d225c57e5c128f5d7c69
Author: Matt Caswell <matt at openssl.org>
Date:   Tue Apr 16 15:37:23 2019 +0100

    Fix the S390X support for the basic AES ciphers
    
    Reviewed-by: Paul Dale <paul.dale at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/8700)

commit 3a7b15e484f950d4cb4061d93839802ecb74f8e5
Author: Matt Caswell <matt at openssl.org>
Date:   Mon Apr 15 15:33:58 2019 +0100

    Add forward declarations of the AES dispatch table functions
    
    Reviewed-by: Paul Dale <paul.dale at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/8700)

commit dcd446f1005f5c99768965a11c10dd6c7b6aee59
Author: Matt Caswell <matt at openssl.org>
Date:   Wed Apr 10 13:54:38 2019 +0100

    Make implementation of blocksize, iv_length and key_length mandatory
    
    Reviewed-by: Paul Dale <paul.dale at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/8700)

commit 3b94944cf2d6476d1b8ac7949bf8b28abb644426
Author: Matt Caswell <matt at openssl.org>
Date:   Wed Apr 10 13:43:45 2019 +0100

    Add a maximum output length to update and final calls
    
    Reviewed-by: Paul Dale <paul.dale at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/8700)

commit 344cfa34e5b07f8b8b7f1e70f47f5d265c9c1185
Author: Matt Caswell <matt at openssl.org>
Date:   Wed Apr 10 13:23:58 2019 +0100

    Add iv length and key length params to the cipher init calls
    
    Reviewed-by: Paul Dale <paul.dale at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/8700)

commit 819a7ae9fc7721f675757c0925821f91b20dfc8f
Author: Matt Caswell <matt at openssl.org>
Date:   Mon Apr 8 17:19:59 2019 +0100

    Implement AES CTR ciphers in the default provider
    
    Reviewed-by: Paul Dale <paul.dale at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/8700)

commit 75dd6d64f1f3afd6fda024d8d91bc2a216bbfcf9
Author: Matt Caswell <matt at openssl.org>
Date:   Mon Apr 8 17:13:01 2019 +0100

    Implement AES CFB ciphers in the default provider
    
    Reviewed-by: Paul Dale <paul.dale at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/8700)

commit ed98df51c69717529dd7d775b35430c036216339
Author: Matt Caswell <matt at openssl.org>
Date:   Mon Apr 8 16:55:34 2019 +0100

    Implement AES OFB ciphers in the default provider
    
    Reviewed-by: Paul Dale <paul.dale at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/8700)

commit 718b133a5328108099ecac0bf40d8fd4886e7b64
Author: Matt Caswell <matt at openssl.org>
Date:   Wed Apr 3 18:01:21 2019 +0100

    Implement AES CBC ciphers in the default provider
    
    Reviewed-by: Paul Dale <paul.dale at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/8700)

commit f4a129bb8dc26488e29b06e06e96a76c93f966be
Author: Matt Caswell <matt at openssl.org>
Date:   Wed Apr 3 16:53:22 2019 +0100

    Add support in the default provider for 192/128 bit AES ECB
    
    Reviewed-by: Paul Dale <paul.dale at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/8700)

commit 861b8f8747965bf98d9dd328196b8092e709c99d
Author: Matt Caswell <matt at openssl.org>
Date:   Wed Apr 3 16:39:34 2019 +0100

    Add the provider_algs.h internal header file
    
    Reviewed-by: Paul Dale <paul.dale at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/8700)

commit aab26e6f7b437f7d4bace03cd855a33d7a34d927
Author: Matt Caswell <matt at openssl.org>
Date:   Wed Apr 3 15:34:08 2019 +0100

    Implement support for AES-256-ECB in the default provider
    
    We also lay the ground work for various of other the basic AES ciphers.
    
    Reviewed-by: Paul Dale <paul.dale at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/8700)

commit df05f2ce6d496232f3c86acb299a128d0eb3ef42
Author: Matt Caswell <matt at openssl.org>
Date:   Wed Apr 3 15:38:07 2019 +0100

    Make EVP_Encrypt*/EVP_Decrypt* and EVP_Cipher* provider aware
    
    Reviewed-by: Paul Dale <paul.dale at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/8700)

-----------------------------------------------------------------------

Summary of changes:
 build.info                                         |   2 +-
 crypto/err/err.c                                   |   1 +
 crypto/err/err_all.c                               |   4 +-
 crypto/err/openssl.ec                              |   1 +
 crypto/err/openssl.txt                             |  27 +
 crypto/evp/cmeth_lib.c                             |  32 +-
 crypto/evp/digest.c                                |   2 +-
 crypto/evp/evp_enc.c                               | 531 ++++++++++++-
 crypto/evp/evp_err.c                               |   7 +
 crypto/evp/evp_lib.c                               | 133 +++-
 crypto/evp/evp_locl.h                              |   4 +
 crypto/include/internal/evp_int.h                  |  24 +
 include/openssl/core_names.h                       |   6 +
 include/openssl/core_numbers.h                     |  55 +-
 include/openssl/err.h                              |   2 +
 include/openssl/evp.h                              |   5 +-
 include/openssl/evperr.h                           |   4 +
 providers/build.info                               |   2 +-
 providers/common/build.info                        |   5 +-
 providers/common/ciphers/aes.c                     | 470 +++++++++++
 providers/common/ciphers/aes_basic.c               | 866 +++++++++++++++++++++
 providers/common/ciphers/block.c                   | 118 +++
 providers/common/ciphers/build.info                |   4 +
 providers/common/ciphers/ciphers_locl.h            | 107 +++
 providers/common/digests/sha2.c                    |   4 +-
 providers/common/include/internal/provider_algs.h  |  34 +
 .../common/include/internal/providercommon.h       |   0
 .../common/include/internal/providercommonerr.h    |  54 ++
 providers/common/provider_err.c                    |  67 ++
 providers/default/defltprov.c                      |  30 +-
 providers/legacy/digests/md2.c                     |   2 +-
 util/ck_errf.pl                                    |   3 +-
 util/libcrypto.num                                 |   3 +
 util/mkerr.pl                                      |   3 +-
 34 files changed, 2550 insertions(+), 62 deletions(-)
 create mode 100644 providers/common/ciphers/aes.c
 create mode 100644 providers/common/ciphers/aes_basic.c
 create mode 100644 providers/common/ciphers/block.c
 create mode 100644 providers/common/ciphers/build.info
 create mode 100644 providers/common/ciphers/ciphers_locl.h
 create mode 100644 providers/common/include/internal/provider_algs.h
 copy fuzz/corpora/ct/e53301b7bba90f14da5195be2e47ec3f88924694 => providers/common/include/internal/providercommon.h (100%)
 create mode 100644 providers/common/include/internal/providercommonerr.h
 create mode 100644 providers/common/provider_err.c

diff --git a/build.info b/build.info
index a0ecb21..ce5dfd0 100644
--- a/build.info
+++ b/build.info
@@ -3,7 +3,7 @@
 SUBDIRS=crypto ssl apps test util tools fuzz engines providers
 
 LIBS=libcrypto libssl
-INCLUDE[libcrypto]=. crypto/include include
+INCLUDE[libcrypto]=. crypto/include include providers/common/include
 INCLUDE[libssl]=. include
 DEPEND[libssl]=libcrypto
 
diff --git a/crypto/err/err.c b/crypto/err/err.c
index 4548854..345d230 100644
--- a/crypto/err/err.c
+++ b/crypto/err/err.c
@@ -66,6 +66,7 @@ static ERR_STRING_DATA ERR_str_libraries[] = {
     {ERR_PACK(ERR_LIB_OSSL_STORE, 0, 0), "STORE routines"},
     {ERR_PACK(ERR_LIB_SM2, 0, 0), "SM2 routines"},
     {ERR_PACK(ERR_LIB_ESS, 0, 0), "ESS routines"},
+    {ERR_PACK(ERR_LIB_PROV, 0, 0), "Provider routines"},
     {0, NULL},
 };
 
diff --git a/crypto/err/err_all.c b/crypto/err/err_all.c
index 1166b01..af44467 100644
--- a/crypto/err/err_all.c
+++ b/crypto/err/err_all.c
@@ -41,6 +41,7 @@
 #include <openssl/storeerr.h>
 #include <openssl/esserr.h>
 #include "internal/propertyerr.h"
+#include "internal/providercommonerr.h"
 
 int err_load_crypto_strings_int(void)
 {
@@ -102,7 +103,8 @@ int err_load_crypto_strings_int(void)
 #endif
         ERR_load_KDF_strings() == 0 ||
         ERR_load_OSSL_STORE_strings() == 0 ||
-        ERR_load_PROP_strings() == 0)
+        ERR_load_PROP_strings() == 0 ||
+        ERR_load_PROV_strings() == 0)
         return 0;
 
     return 1;
diff --git a/crypto/err/openssl.ec b/crypto/err/openssl.ec
index a204434..b28aa49 100644
--- a/crypto/err/openssl.ec
+++ b/crypto/err/openssl.ec
@@ -37,6 +37,7 @@ L SM2           crypto/include/internal/sm2.h   crypto/sm2/sm2_err.c
 L OSSL_STORE    include/openssl/store.h         crypto/store/store_err.c
 L ESS           include/openssl/ess.h           crypto/ess/ess_err.c
 L PROP          include/internal/property.h     crypto/property/property_err.c
+L PROV          providers/common/include/internal/providercommon.h providers/common/provider_err.c
 
 # additional header files to be scanned for function names
 L NONE          include/openssl/x509_vfy.h      NONE
diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt
index 18aa16c..5c444f5 100644
--- a/crypto/err/openssl.txt
+++ b/crypto/err/openssl.txt
@@ -785,6 +785,9 @@ EVP_F_EVP_CIPHER_ASN1_TO_PARAM:204:EVP_CIPHER_asn1_to_param
 EVP_F_EVP_CIPHER_CTX_COPY:163:EVP_CIPHER_CTX_copy
 EVP_F_EVP_CIPHER_CTX_CTRL:124:EVP_CIPHER_CTX_ctrl
 EVP_F_EVP_CIPHER_CTX_SET_KEY_LENGTH:122:EVP_CIPHER_CTX_set_key_length
+EVP_F_EVP_CIPHER_CTX_SET_PADDING:237:EVP_CIPHER_CTX_set_padding
+EVP_F_EVP_CIPHER_FROM_DISPATCH:238:evp_cipher_from_dispatch
+EVP_F_EVP_CIPHER_MODE:239:EVP_CIPHER_mode
 EVP_F_EVP_CIPHER_PARAM_TO_ASN1:205:EVP_CIPHER_param_to_asn1
 EVP_F_EVP_DECRYPTFINAL_EX:101:EVP_DecryptFinal_ex
 EVP_F_EVP_DECRYPTUPDATE:166:EVP_DecryptUpdate
@@ -1102,6 +1105,21 @@ PROP_F_PARSE_NUMBER:104:parse_number
 PROP_F_PARSE_OCT:105:parse_oct
 PROP_F_PARSE_STRING:106:parse_string
 PROP_F_PARSE_UNQUOTED:107:parse_unquoted
+PROV_F_AESNI_INIT_KEY:101:aesni_init_key
+PROV_F_AES_BLOCK_FINAL:102:aes_block_final
+PROV_F_AES_BLOCK_UPDATE:103:aes_block_update
+PROV_F_AES_CIPHER:104:aes_cipher
+PROV_F_AES_CTX_GET_PARAMS:105:aes_ctx_get_params
+PROV_F_AES_CTX_SET_PARAMS:106:aes_ctx_set_params
+PROV_F_AES_DINIT:107:aes_dinit
+PROV_F_AES_DUPCTX:108:aes_dupctx
+PROV_F_AES_EINIT:109:aes_einit
+PROV_F_AES_INIT_KEY:110:aes_init_key
+PROV_F_AES_STREAM_UPDATE:111:aes_stream_update
+PROV_F_AES_T4_INIT_KEY:112:aes_t4_init_key
+PROV_F_PROV_AES_KEY_GENERIC_INIT:113:PROV_AES_KEY_generic_init
+PROV_F_TRAILINGDATA:114:trailingdata
+PROV_F_UNPADBLOCK:100:unpadblock
 RAND_F_DRBG_BYTES:101:drbg_bytes
 RAND_F_DRBG_CTR_INIT:125:drbg_ctr_init
 RAND_F_DRBG_GET_ENTROPY:105:drbg_get_entropy
@@ -2381,6 +2399,7 @@ EVP_R_INVALID_FIPS_MODE:168:invalid fips mode
 EVP_R_INVALID_KEY:163:invalid key
 EVP_R_INVALID_KEY_LENGTH:130:invalid key length
 EVP_R_INVALID_OPERATION:148:invalid operation
+EVP_R_INVALID_PROVIDER_FUNCTIONS:193:invalid provider functions
 EVP_R_INVALID_SALT_LENGTH:186:invalid salt length
 EVP_R_KEYGEN_FAILURE:120:keygen failure
 EVP_R_KEY_SETUP_FAILED:180:key setup failed
@@ -2604,6 +2623,14 @@ PROP_R_NO_VALUE:107:no value
 PROP_R_PARSE_FAILED:108:parse failed
 PROP_R_STRING_TOO_LONG:109:string too long
 PROP_R_TRAILING_CHARACTERS:110:trailing characters
+PROV_R_AES_KEY_SETUP_FAILED:101:aes key setup failed
+PROV_R_BAD_DECRYPT:100:bad decrypt
+PROV_R_CIPHER_OPERATION_FAILED:102:cipher operation failed
+PROV_R_FAILED_TO_GET_PARAMETER:103:failed to get parameter
+PROV_R_FAILED_TO_SET_PARAMETER:104:failed to set parameter
+PROV_R_INVALID_KEYLEN:105:invalid keylen
+PROV_R_OUTPUT_BUFFER_TOO_SMALL:106:output buffer too small
+PROV_R_WRONG_FINAL_BLOCK_LENGTH:107:wrong final block length
 RAND_R_ADDITIONAL_INPUT_TOO_LONG:102:additional input too long
 RAND_R_ALREADY_INSTANTIATED:103:already instantiated
 RAND_R_ARGUMENT_OUT_OF_RANGE:105:argument out of range
diff --git a/crypto/evp/cmeth_lib.c b/crypto/evp/cmeth_lib.c
index 6c328c0..0520157 100644
--- a/crypto/evp/cmeth_lib.c
+++ b/crypto/evp/cmeth_lib.c
@@ -11,6 +11,7 @@
 
 #include <openssl/evp.h>
 #include "internal/evp_int.h"
+#include "internal/provider.h"
 #include "evp_locl.h"
 
 EVP_CIPHER *EVP_CIPHER_meth_new(int cipher_type, int block_size, int key_len)
@@ -21,6 +22,12 @@ EVP_CIPHER *EVP_CIPHER_meth_new(int cipher_type, int block_size, int key_len)
         cipher->nid = cipher_type;
         cipher->block_size = block_size;
         cipher->key_len = key_len;
+        cipher->lock = CRYPTO_THREAD_lock_new();
+        if (cipher->lock == NULL) {
+            OPENSSL_free(cipher);
+            return NULL;
+        }
+        cipher->refcnt = 1;
     }
     return cipher;
 }
@@ -30,14 +37,35 @@ EVP_CIPHER *EVP_CIPHER_meth_dup(const EVP_CIPHER *cipher)
     EVP_CIPHER *to = EVP_CIPHER_meth_new(cipher->nid, cipher->block_size,
                                          cipher->key_len);
 
-    if (to != NULL)
+    if (to != NULL) {
+        CRYPTO_RWLOCK *lock = to->lock;
+
         memcpy(to, cipher, sizeof(*to));
+        to->lock = lock;
+    }
     return to;
 }
 
 void EVP_CIPHER_meth_free(EVP_CIPHER *cipher)
 {
-    OPENSSL_free(cipher);
+    if (cipher != NULL) {
+        int i;
+
+        CRYPTO_DOWN_REF(&cipher->refcnt, &i, cipher->lock);
+        if (i > 0)
+            return;
+        ossl_provider_free(cipher->prov);
+        CRYPTO_THREAD_lock_free(cipher->lock);
+        OPENSSL_free(cipher);
+    }
+}
+
+int EVP_CIPHER_upref(EVP_CIPHER *cipher)
+{
+    int ref = 0;
+
+    CRYPTO_UP_REF(&cipher->refcnt, &ref, cipher->lock);
+    return 1;
 }
 
 int EVP_CIPHER_meth_set_iv_length(EVP_CIPHER *cipher, int iv_len)
diff --git a/crypto/evp/digest.c b/crypto/evp/digest.c
index e4787e6..043e456 100644
--- a/crypto/evp/digest.c
+++ b/crypto/evp/digest.c
@@ -517,7 +517,7 @@ static void *evp_md_from_dispatch(int mdtype, const OSSL_DISPATCH *fns,
             md->dinit = OSSL_get_OP_digest_init(fns);
             fncnt++;
             break;
-        case OSSL_FUNC_DIGEST_UPDDATE:
+        case OSSL_FUNC_DIGEST_UPDATE:
             if (md->dupdate != NULL)
                 break;
             md->dupdate = OSSL_get_OP_digest_update(fns);
diff --git a/crypto/evp/evp_enc.c b/crypto/evp/evp_enc.c
index 641ad19..4426a81 100644
--- a/crypto/evp/evp_enc.c
+++ b/crypto/evp/evp_enc.c
@@ -15,25 +15,46 @@
 #include <openssl/rand.h>
 #include <openssl/rand_drbg.h>
 #include <openssl/engine.h>
+#include <openssl/params.h>
+#include <openssl/core_names.h>
 #include "internal/evp_int.h"
+#include "internal/provider.h"
 #include "evp_locl.h"
 
-int EVP_CIPHER_CTX_reset(EVP_CIPHER_CTX *c)
+int EVP_CIPHER_CTX_reset(EVP_CIPHER_CTX *ctx)
 {
-    if (c == NULL)
+    if (ctx == NULL)
         return 1;
-    if (c->cipher != NULL) {
-        if (c->cipher->cleanup && !c->cipher->cleanup(c))
+
+    if (ctx->cipher == NULL || ctx->cipher->prov == NULL)
+        goto legacy;
+
+    if (ctx->provctx != NULL) {
+        if (ctx->cipher->freectx != NULL)
+            ctx->cipher->freectx(ctx->provctx);
+        ctx->provctx = NULL;
+    }
+    if (ctx->fetched_cipher != NULL)
+        EVP_CIPHER_meth_free(ctx->fetched_cipher);
+    memset(ctx, 0, sizeof(*ctx));
+
+    return 1;
+
+    /* TODO(3.0): Remove legacy code below */
+ legacy:
+
+    if (ctx->cipher != NULL) {
+        if (ctx->cipher->cleanup && !ctx->cipher->cleanup(ctx))
             return 0;
         /* Cleanse cipher context data */
-        if (c->cipher_data && c->cipher->ctx_size)
-            OPENSSL_cleanse(c->cipher_data, c->cipher->ctx_size);
+        if (ctx->cipher_data && ctx->cipher->ctx_size)
+            OPENSSL_cleanse(ctx->cipher_data, ctx->cipher->ctx_size);
     }
-    OPENSSL_free(c->cipher_data);
+    OPENSSL_free(ctx->cipher_data);
 #ifndef OPENSSL_NO_ENGINE
-    ENGINE_finish(c->engine);
+    ENGINE_finish(ctx->engine);
 #endif
-    memset(c, 0, sizeof(*c));
+    memset(ctx, 0, sizeof(*ctx));
     return 1;
 }
 
@@ -60,13 +81,30 @@ int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
                       ENGINE *impl, const unsigned char *key,
                       const unsigned char *iv, int enc)
 {
-    if (enc == -1)
+    EVP_CIPHER *provciph = NULL;
+    ENGINE *tmpimpl = NULL;
+    const EVP_CIPHER *tmpcipher;
+
+    /*
+     * enc == 1 means we are encrypting.
+     * enc == 0 means we are decrypting.
+     * enc == -1 means, use the previously initialised value for encrypt/decrypt
+     */
+    if (enc == -1) {
         enc = ctx->encrypt;
-    else {
+    } else {
         if (enc)
             enc = 1;
         ctx->encrypt = enc;
     }
+
+    if (cipher == NULL && ctx->cipher == NULL) {
+        EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_NO_CIPHER_SET);
+        return 0;
+    }
+
+    /* TODO(3.0): Legacy work around code below. Remove this */
+
 #ifndef OPENSSL_NO_ENGINE
     /*
      * Whether it's nice or not, "Inits" can be used on "Final"'d contexts so
@@ -77,11 +115,157 @@ int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
     if (ctx->engine && ctx->cipher
         && (cipher == NULL || cipher->nid == ctx->cipher->nid))
         goto skip_to_init;
+
+    if (cipher != NULL && impl == NULL) {
+         /* Ask if an ENGINE is reserved for this job */
+        tmpimpl = ENGINE_get_cipher_engine(cipher->nid);
+    }
 #endif
-    if (cipher) {
+
+    /*
+     * If there are engines involved then we should use legacy handling for now.
+     */
+    if (ctx->engine != NULL
+            || impl != NULL
+            || tmpimpl != NULL) {
+        if (ctx->cipher == ctx->fetched_cipher)
+            ctx->cipher = NULL;
+        EVP_CIPHER_meth_free(ctx->fetched_cipher);
+        ctx->fetched_cipher = NULL;
+        goto legacy;
+    }
+
+    tmpcipher = (cipher == NULL) ? ctx->cipher : cipher;
+
+    if (tmpcipher->prov == NULL) {
+        switch(tmpcipher->nid) {
+        case NID_aes_256_ecb:
+        case NID_aes_192_ecb:
+        case NID_aes_128_ecb:
+        case NID_aes_256_cbc:
+        case NID_aes_192_cbc:
+        case NID_aes_128_cbc:
+        case NID_aes_256_ofb128:
+        case NID_aes_192_ofb128:
+        case NID_aes_128_ofb128:
+        case NID_aes_256_cfb128:
+        case NID_aes_192_cfb128:
+        case NID_aes_128_cfb128:
+        case NID_aes_256_cfb1:
+        case NID_aes_192_cfb1:
+        case NID_aes_128_cfb1:
+        case NID_aes_256_cfb8:
+        case NID_aes_192_cfb8:
+        case NID_aes_128_cfb8:
+        case NID_aes_256_ctr:
+        case NID_aes_192_ctr:
+        case NID_aes_128_ctr:
+            break;
+        default:
+            goto legacy;
+        }
+    }
+
+    /*
+     * Ensure a context left lying around from last time is cleared
+     * (legacy code)
+     */
+    if (cipher != NULL && ctx->cipher != NULL) {
+        OPENSSL_clear_free(ctx->cipher_data, ctx->cipher->ctx_size);
+        ctx->cipher_data = NULL;
+    }
+
+
+    /* TODO(3.0): Start of non-legacy code below */
+
+    /* Ensure a context left lying around from last time is cleared */
+    if (cipher != NULL && ctx->cipher != NULL) {
+        unsigned long flags = ctx->flags;
+
+        EVP_CIPHER_CTX_reset(ctx);
+        /* Restore encrypt and flags */
+        ctx->encrypt = enc;
+        ctx->flags = flags;
+    }
+
+    if (cipher != NULL)
+        ctx->cipher = cipher;
+    else
+        cipher = ctx->cipher;
+
+    if (cipher->prov == NULL) {
+        provciph = EVP_CIPHER_fetch(NULL, OBJ_nid2sn(cipher->nid), "");
+        if (provciph == NULL) {
+            EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_INITIALIZATION_ERROR);
+            return 0;
+        }
+        cipher = provciph;
+        EVP_CIPHER_meth_free(ctx->fetched_cipher);
+        ctx->fetched_cipher = provciph;
+    }
+
+    ctx->cipher = cipher;
+    if (ctx->provctx == NULL) {
+        ctx->provctx = ctx->cipher->newctx();
+        if (ctx->provctx == NULL) {
+            EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_INITIALIZATION_ERROR);
+            return 0;
+        }
+    }
+
+    if ((ctx->flags & EVP_CIPH_NO_PADDING) != 0) {
+        /*
+         * If this ctx was already set up for no padding then we need to tell
+         * the new cipher about it.
+         */
+        if (!EVP_CIPHER_CTX_set_padding(ctx, 0))
+            return 0;
+    }
+
+    switch (EVP_CIPHER_mode(ctx->cipher)) {
+    case EVP_CIPH_CFB_MODE:
+    case EVP_CIPH_OFB_MODE:
+    case EVP_CIPH_CBC_MODE:
+        /* For these modes we remember the original IV for later use */
+        if (!ossl_assert(EVP_CIPHER_CTX_iv_length(ctx) <= (int)sizeof(ctx->oiv))) {
+            EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_INITIALIZATION_ERROR);
+            return 0;
+        }
+        if (iv != NULL)
+            memcpy(ctx->oiv, iv, EVP_CIPHER_CTX_iv_length(ctx));
+    }
+
+    if (enc) {
+        if (ctx->cipher->einit == NULL) {
+            EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_INITIALIZATION_ERROR);
+            return 0;
+        }
+
+        return ctx->cipher->einit(ctx->provctx,
+                                  key,
+                                  EVP_CIPHER_CTX_key_length(ctx),
+                                  iv,
+                                  EVP_CIPHER_CTX_iv_length(ctx));
+    }
+
+    if (ctx->cipher->dinit == NULL) {
+        EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_INITIALIZATION_ERROR);
+        return 0;
+    }
+
+    return ctx->cipher->dinit(ctx->provctx,
+                              key,
+                              EVP_CIPHER_CTX_key_length(ctx),
+                              iv,
+                              EVP_CIPHER_CTX_iv_length(ctx));
+
+    /* TODO(3.0): Remove legacy code below */
+ legacy:
+
+    if (cipher != NULL) {
         /*
-         * Ensure a context left lying around from last time is cleared (the
-         * previous check attempted to avoid this if the same ENGINE and
+         * Ensure a context left lying around from last time is cleared (we
+         * previously attempted to avoid this if the same ENGINE and
          * EVP_CIPHER could be used).
          */
         if (ctx->cipher) {
@@ -92,18 +276,19 @@ int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
             ctx->flags = flags;
         }
 #ifndef OPENSSL_NO_ENGINE
-        if (impl) {
+        if (impl != NULL) {
             if (!ENGINE_init(impl)) {
                 EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_INITIALIZATION_ERROR);
                 return 0;
             }
-        } else
-            /* Ask if an ENGINE is reserved for this job */
-            impl = ENGINE_get_cipher_engine(cipher->nid);
-        if (impl) {
+        } else {
+            impl = tmpimpl;
+        }
+        if (impl != NULL) {
             /* There's an ENGINE for this job ... (apparently) */
             const EVP_CIPHER *c = ENGINE_get_cipher(impl, cipher->nid);
-            if (!c) {
+
+            if (c == NULL) {
                 /*
                  * One positive side-effect of US's export control history,
                  * is that we should at least be able to avoid using US
@@ -119,8 +304,9 @@ int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
              * from an ENGINE and we need to release it when done.
              */
             ctx->engine = impl;
-        } else
+        } else {
             ctx->engine = NULL;
+        }
 #endif
 
         ctx->cipher = cipher;
@@ -144,9 +330,6 @@ int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
                 return 0;
             }
         }
-    } else if (!ctx->cipher) {
-        EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_NO_CIPHER_SET);
-        return 0;
     }
 #ifndef OPENSSL_NO_ENGINE
  skip_to_init:
@@ -377,12 +560,39 @@ static int evp_EncryptDecryptUpdate(EVP_CIPHER_CTX *ctx,
 int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
                       const unsigned char *in, int inl)
 {
+    int ret;
+    size_t soutl;
+    int blocksize;
+
     /* Prevent accidental use of decryption context when encrypting */
     if (!ctx->encrypt) {
         EVPerr(EVP_F_EVP_ENCRYPTUPDATE, EVP_R_INVALID_OPERATION);
         return 0;
     }
 
+    if (ctx->cipher == NULL || ctx->cipher->prov == NULL)
+        goto legacy;
+
+    blocksize = EVP_CIPHER_CTX_block_size(ctx);
+
+    if (ctx->cipher->cupdate == NULL  || blocksize < 1) {
+        EVPerr(EVP_F_EVP_ENCRYPTUPDATE, EVP_R_UPDATE_ERROR);
+        return 0;
+    }
+    ret = ctx->cipher->cupdate(ctx->provctx, out, &soutl,
+                               inl + (blocksize == 1 ? 0 : blocksize), in,
+                               (size_t)inl);
+
+    if (soutl > INT_MAX) {
+        EVPerr(EVP_F_EVP_ENCRYPTUPDATE, EVP_R_UPDATE_ERROR);
+        return 0;
+    }
+    *outl = soutl;
+    return ret;
+
+    /* TODO(3.0): Remove legacy code below */
+ legacy:
+
     return evp_EncryptDecryptUpdate(ctx, out, outl, in, inl);
 }
 
@@ -397,6 +607,8 @@ int EVP_EncryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
 {
     int n, ret;
     unsigned int i, b, bl;
+    size_t soutl;
+    int blocksize;
 
     /* Prevent accidental use of decryption context when encrypting */
     if (!ctx->encrypt) {
@@ -404,6 +616,30 @@ int EVP_EncryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
         return 0;
     }
 
+    if (ctx->cipher == NULL || ctx->cipher->prov == NULL)
+        goto legacy;
+
+    blocksize = EVP_CIPHER_CTX_block_size(ctx);
+
+    if (blocksize < 1 || ctx->cipher->cfinal == NULL) {
+        EVPerr(EVP_F_EVP_ENCRYPTFINAL_EX, EVP_R_FINAL_ERROR);
+        return 0;
+    }
+
+    ret = ctx->cipher->cfinal(ctx->provctx, out, &soutl,
+                              blocksize == 1 ? 0 : blocksize);
+
+    if (soutl > INT_MAX) {
+        EVPerr(EVP_F_EVP_ENCRYPTFINAL_EX, EVP_R_FINAL_ERROR);
+        return 0;
+    }
+    *outl = soutl;
+
+    return ret;
+
+    /* TODO(3.0): Remove legacy code below */
+ legacy:
+
     if (ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) {
         ret = ctx->cipher->do_cipher(ctx, out, NULL, 0);
         if (ret < 0)
@@ -444,8 +680,10 @@ int EVP_EncryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
 int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
                       const unsigned char *in, int inl)
 {
-    int fix_len, cmpl = inl;
+    int fix_len, cmpl = inl, ret;
     unsigned int b;
+    size_t soutl;
+    int blocksize;
 
     /* Prevent accidental use of encryption context when decrypting */
     if (ctx->encrypt) {
@@ -453,6 +691,32 @@ int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
         return 0;
     }
 
+    if (ctx->cipher == NULL || ctx->cipher->prov == NULL)
+        goto legacy;
+
+    blocksize = EVP_CIPHER_CTX_block_size(ctx);
+
+    if (ctx->cipher->cupdate == NULL || blocksize < 1) {
+        EVPerr(EVP_F_EVP_DECRYPTUPDATE, EVP_R_UPDATE_ERROR);
+        return 0;
+    }
+    ret = ctx->cipher->cupdate(ctx->provctx, out, &soutl,
+                               inl + (blocksize == 1 ? 0 : blocksize), in,
+                               (size_t)inl);
+
+    if (ret) {
+        if (soutl > INT_MAX) {
+            EVPerr(EVP_F_EVP_DECRYPTUPDATE, EVP_R_UPDATE_ERROR);
+            return 0;
+        }
+        *outl = soutl;
+    }
+
+    return ret;
+
+    /* TODO(3.0): Remove legacy code below */
+ legacy:
+
     b = ctx->cipher->block_size;
 
     if (EVP_CIPHER_CTX_test_flags(ctx, EVP_CIPH_FLAG_LENGTH_BITS))
@@ -527,6 +791,9 @@ int EVP_DecryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
 {
     int i, n;
     unsigned int b;
+    size_t soutl;
+    int ret;
+    int blocksize;
 
     /* Prevent accidental use of encryption context when decrypting */
     if (ctx->encrypt) {
@@ -534,6 +801,32 @@ int EVP_DecryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
         return 0;
     }
 
+    if (ctx->cipher == NULL || ctx->cipher->prov == NULL)
+        goto legacy;
+
+    blocksize = EVP_CIPHER_CTX_block_size(ctx);
+
+    if (blocksize < 1 || ctx->cipher->cfinal == NULL) {
+        EVPerr(EVP_F_EVP_DECRYPTFINAL_EX, EVP_R_FINAL_ERROR);
+        return 0;
+    }
+
+    ret = ctx->cipher->cfinal(ctx->provctx, out, &soutl,
+                              blocksize == 1 ? 0 : blocksize);
+
+    if (ret) {
+        if (soutl > INT_MAX) {
+            EVPerr(EVP_F_EVP_DECRYPTFINAL_EX, EVP_R_FINAL_ERROR);
+            return 0;
+        }
+        *outl = soutl;
+    }
+
+    return ret;
+
+    /* TODO(3.0): Remove legacy code below */
+ legacy:
+
     *outl = 0;
 
     if (ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) {
@@ -590,7 +883,7 @@ int EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *c, int keylen)
 {
     if (c->cipher->flags & EVP_CIPH_CUSTOM_KEY_LENGTH)
         return EVP_CIPHER_CTX_ctrl(c, EVP_CTRL_SET_KEY_LENGTH, keylen, NULL);
-    if (c->key_len == keylen)
+    if (EVP_CIPHER_CTX_key_length(c) == keylen)
         return 1;
     if ((keylen > 0) && (c->cipher->flags & EVP_CIPH_VARIABLE_LENGTH)) {
         c->key_len = keylen;
@@ -606,6 +899,24 @@ int EVP_CIPHER_CTX_set_padding(EVP_CIPHER_CTX *ctx, int pad)
         ctx->flags &= ~EVP_CIPH_NO_PADDING;
     else
         ctx->flags |= EVP_CIPH_NO_PADDING;
+
+    if (ctx->cipher != NULL && ctx->cipher->prov != NULL) {
+        OSSL_PARAM params[] = {
+            OSSL_PARAM_int(OSSL_CIPHER_PARAM_PADDING, NULL),
+            OSSL_PARAM_END
+        };
+
+        params[0].data = &pad;
+
+        if (ctx->cipher->ctx_set_params == NULL) {
+            EVPerr(EVP_F_EVP_CIPHER_CTX_SET_PADDING, EVP_R_CTRL_NOT_IMPLEMENTED);
+            return 0;
+        }
+
+        if (!ctx->cipher->ctx_set_params(ctx->provctx, params))
+            return 0;
+    }
+
     return 1;
 }
 
@@ -647,6 +958,36 @@ int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, const EVP_CIPHER_CTX *in)
         EVPerr(EVP_F_EVP_CIPHER_CTX_COPY, EVP_R_INPUT_NOT_INITIALIZED);
         return 0;
     }
+
+    if (in->cipher->prov == NULL)
+        goto legacy;
+
+    if (in->cipher->dupctx == NULL) {
+        EVPerr(EVP_F_EVP_CIPHER_CTX_COPY, EVP_R_NOT_ABLE_TO_COPY_CTX);
+        return 0;
+    }
+
+    EVP_CIPHER_CTX_reset(out);
+
+    *out = *in;
+    out->provctx = NULL;
+
+    if (in->fetched_cipher != NULL && !EVP_CIPHER_upref(in->fetched_cipher)) {
+        out->fetched_cipher = NULL;
+        return 0;
+    }
+
+    out->provctx = in->cipher->dupctx(in->provctx);
+    if (out->provctx == NULL) {
+        EVPerr(EVP_F_EVP_CIPHER_CTX_COPY, EVP_R_NOT_ABLE_TO_COPY_CTX);
+        return 0;
+    }
+
+    return 1;
+
+    /* TODO(3.0): Remove legacy code below */
+ legacy:
+
 #ifndef OPENSSL_NO_ENGINE
     /* Make sure it's safe to copy a cipher context using an ENGINE */
     if (in->engine && !ENGINE_init(in->engine)) {
@@ -676,3 +1017,141 @@ int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, const EVP_CIPHER_CTX *in)
         }
     return 1;
 }
+
+static void *evp_cipher_from_dispatch(int nid, const OSSL_DISPATCH *fns,
+                                      OSSL_PROVIDER *prov)
+{
+    EVP_CIPHER *cipher = NULL;
+    int fnciphcnt = 0, fnctxcnt = 0;
+
+    if ((cipher = EVP_CIPHER_meth_new(nid, 0, 0)) == NULL)
+        return NULL;
+
+    for (; fns->function_id != 0; fns++) {
+        switch (fns->function_id) {
+        case OSSL_FUNC_CIPHER_NEWCTX:
+            if (cipher->newctx != NULL)
+                break;
+            cipher->newctx = OSSL_get_OP_cipher_newctx(fns);
+            fnctxcnt++;
+            break;
+        case OSSL_FUNC_CIPHER_ENCRYPT_INIT:
+            if (cipher->einit != NULL)
+                break;
+            cipher->einit = OSSL_get_OP_cipher_encrypt_init(fns);
+            fnciphcnt++;
+            break;
+        case OSSL_FUNC_CIPHER_DECRYPT_INIT:
+            if (cipher->dinit != NULL)
+                break;
+            cipher->dinit = OSSL_get_OP_cipher_decrypt_init(fns);
+            fnciphcnt++;
+            break;
+        case OSSL_FUNC_CIPHER_UPDATE:
+            if (cipher->cupdate != NULL)
+                break;
+            cipher->cupdate = OSSL_get_OP_cipher_update(fns);
+            fnciphcnt++;
+            break;
+        case OSSL_FUNC_CIPHER_FINAL:
+            if (cipher->cfinal != NULL)
+                break;
+            cipher->cfinal = OSSL_get_OP_cipher_final(fns);
+            fnciphcnt++;
+            break;
+        case OSSL_FUNC_CIPHER_CIPHER:
+            if (cipher->ccipher != NULL)
+                break;
+            cipher->ccipher = OSSL_get_OP_cipher_cipher(fns);
+            break;
+        case OSSL_FUNC_CIPHER_FREECTX:
+            if (cipher->freectx != NULL)
+                break;
+            cipher->freectx = OSSL_get_OP_cipher_freectx(fns);
+            fnctxcnt++;
+            break;
+        case OSSL_FUNC_CIPHER_DUPCTX:
+            if (cipher->dupctx != NULL)
+                break;
+            cipher->dupctx = OSSL_get_OP_cipher_dupctx(fns);
+            break;
+        case OSSL_FUNC_CIPHER_KEY_LENGTH:
+            if (cipher->key_length != NULL)
+                break;
+            cipher->key_length = OSSL_get_OP_cipher_key_length(fns);
+            break;
+        case OSSL_FUNC_CIPHER_IV_LENGTH:
+            if (cipher->iv_length != NULL)
+                break;
+            cipher->iv_length = OSSL_get_OP_cipher_iv_length(fns);
+            break;
+        case OSSL_FUNC_CIPHER_BLOCK_SIZE:
+            if (cipher->blocksize != NULL)
+                break;
+            cipher->blocksize = OSSL_get_OP_cipher_block_size(fns);
+            break;
+        case OSSL_FUNC_CIPHER_GET_PARAMS:
+            if (cipher->get_params != NULL)
+                break;
+            cipher->get_params = OSSL_get_OP_cipher_get_params(fns);
+            break;
+        case OSSL_FUNC_CIPHER_CTX_GET_PARAMS:
+            if (cipher->ctx_get_params != NULL)
+                break;
+            cipher->ctx_get_params = OSSL_get_OP_cipher_ctx_get_params(fns);
+            break;
+        case OSSL_FUNC_CIPHER_CTX_SET_PARAMS:
+            if (cipher->ctx_set_params != NULL)
+                break;
+            cipher->ctx_set_params = OSSL_get_OP_cipher_ctx_set_params(fns);
+            break;
+        }
+    }
+    if ((fnciphcnt != 0 && fnciphcnt != 3 && fnciphcnt != 4)
+            || (fnciphcnt == 0 && cipher->ccipher == NULL)
+            || fnctxcnt != 2
+            || cipher->blocksize == NULL
+            || cipher->iv_length == NULL
+            || cipher->key_length == NULL) {
+        /*
+         * In order to be a consistent set of functions we must have at least
+         * a complete set of "encrypt" functions, or a complete set of "decrypt"
+         * functions, or a single "cipher" function. In all cases we need a
+         * complete set of context management functions, as well as the
+         * blocksize, iv_length and key_length functions.
+         */
+        EVP_CIPHER_meth_free(cipher);
+        EVPerr(EVP_F_EVP_CIPHER_FROM_DISPATCH, EVP_R_INVALID_PROVIDER_FUNCTIONS);
+        return NULL;
+    }
+    cipher->prov = prov;
+    if (prov != NULL)
+        ossl_provider_upref(prov);
+
+    return cipher;
+}
+
+static int evp_cipher_upref(void *cipher)
+{
+    return EVP_CIPHER_upref(cipher);
+}
+
+static void evp_cipher_free(void *cipher)
+{
+    EVP_CIPHER_meth_free(cipher);
+}
+
+static int evp_cipher_nid(void *vcipher)
+{
+    EVP_CIPHER *cipher = vcipher;
+
+    return cipher->nid;
+}
+
+EVP_CIPHER *EVP_CIPHER_fetch(OPENSSL_CTX *ctx, const char *algorithm,
+                             const char *properties)
+{
+    return evp_generic_fetch(ctx, OSSL_OP_CIPHER, algorithm, properties,
+                             evp_cipher_from_dispatch, evp_cipher_upref,
+                             evp_cipher_free, evp_cipher_nid);
+}
diff --git a/crypto/evp/evp_err.c b/crypto/evp/evp_err.c
index a9f8800..3555c0e 100644
--- a/crypto/evp/evp_err.c
+++ b/crypto/evp/evp_err.c
@@ -53,6 +53,11 @@ static const ERR_STRING_DATA EVP_str_functs[] = {
      "EVP_CIPHER_CTX_ctrl"},
     {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_CIPHER_CTX_SET_KEY_LENGTH, 0),
      "EVP_CIPHER_CTX_set_key_length"},
+    {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_CIPHER_CTX_SET_PADDING, 0),
+     "EVP_CIPHER_CTX_set_padding"},
+    {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_CIPHER_FROM_DISPATCH, 0),
+     "evp_cipher_from_dispatch"},
+    {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_CIPHER_MODE, 0), "EVP_CIPHER_mode"},
     {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_CIPHER_PARAM_TO_ASN1, 0),
      "EVP_CIPHER_param_to_asn1"},
     {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_DECRYPTFINAL_EX, 0),
@@ -246,6 +251,8 @@ static const ERR_STRING_DATA EVP_str_reasons[] = {
     {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_KEY), "invalid key"},
     {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_KEY_LENGTH), "invalid key length"},
     {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_OPERATION), "invalid operation"},
+    {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_PROVIDER_FUNCTIONS),
+    "invalid provider functions"},
     {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_SALT_LENGTH),
     "invalid salt length"},
     {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_KEYGEN_FAILURE), "keygen failure"},
diff --git a/crypto/evp/evp_lib.c b/crypto/evp/evp_lib.c
index 914a19c..189c953 100644
--- a/crypto/evp/evp_lib.c
+++ b/crypto/evp/evp_lib.c
@@ -11,6 +11,8 @@
 #include "internal/cryptlib.h"
 #include <openssl/evp.h>
 #include <openssl/objects.h>
+#include <openssl/params.h>
+#include <openssl/core_names.h>
 #include "internal/evp_int.h"
 #include "internal/provider.h"
 #include "evp_locl.h"
@@ -18,13 +20,28 @@
 int EVP_CIPHER_param_to_asn1(EVP_CIPHER_CTX *c, ASN1_TYPE *type)
 {
     int ret;
+    const EVP_CIPHER *cipher = c->cipher;
+
+    if (cipher->prov != NULL) {
+        /*
+         * The cipher has come from a provider and won't have the default flags.
+         * Find the implicit form so we can check the flags.
+         * TODO(3.0): This won't work for 3rd party ciphers we know nothing about
+         * We'll need to think of something else for those.
+         */
+        cipher = EVP_get_cipherbynid(cipher->nid);
+        if (cipher == NULL) {
+            EVPerr(EVP_F_EVP_CIPHER_PARAM_TO_ASN1, ASN1_R_UNSUPPORTED_CIPHER);
+            return -1;
+        }
+    }
 
-    if (c->cipher->set_asn1_parameters != NULL)
-        ret = c->cipher->set_asn1_parameters(c, type);
-    else if (c->cipher->flags & EVP_CIPH_FLAG_DEFAULT_ASN1) {
-        switch (EVP_CIPHER_CTX_mode(c)) {
+    if (cipher->set_asn1_parameters != NULL)
+        ret = cipher->set_asn1_parameters(c, type);
+    else if (cipher->flags & EVP_CIPH_FLAG_DEFAULT_ASN1) {
+        switch (EVP_CIPHER_mode(cipher)) {
         case EVP_CIPH_WRAP_MODE:
-            if (EVP_CIPHER_CTX_nid(c) == NID_id_smime_alg_CMS3DESwrap)
+            if (EVP_CIPHER_nid(cipher) == NID_id_smime_alg_CMS3DESwrap)
                 ASN1_TYPE_set(type, V_ASN1_NULL, NULL);
             ret = 1;
             break;
@@ -53,11 +70,22 @@ int EVP_CIPHER_param_to_asn1(EVP_CIPHER_CTX *c, ASN1_TYPE *type)
 int EVP_CIPHER_asn1_to_param(EVP_CIPHER_CTX *c, ASN1_TYPE *type)
 {
     int ret;
+    const EVP_CIPHER *cipher = c->cipher;
+
+    if (cipher->prov != NULL) {
+        /*
+         * The cipher has come from a provider and won't have the default flags.
+         * Find the implicit form so we can check the flags.
+         */
+        cipher = EVP_get_cipherbynid(cipher->nid);
+        if (cipher == NULL)
+            return -1;
+    }
 
-    if (c->cipher->get_asn1_parameters != NULL)
-        ret = c->cipher->get_asn1_parameters(c, type);
-    else if (c->cipher->flags & EVP_CIPH_FLAG_DEFAULT_ASN1) {
-        switch (EVP_CIPHER_CTX_mode(c)) {
+    if (cipher->get_asn1_parameters != NULL)
+        ret = cipher->get_asn1_parameters(c, type);
+    else if (cipher->flags & EVP_CIPH_FLAG_DEFAULT_ASN1) {
+        switch (EVP_CIPHER_mode(cipher)) {
 
         case EVP_CIPH_WRAP_MODE:
             ret = 1;
@@ -85,19 +113,23 @@ int EVP_CIPHER_asn1_to_param(EVP_CIPHER_CTX *c, ASN1_TYPE *type)
     return ret;
 }
 
-int EVP_CIPHER_get_asn1_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type)
+int EVP_CIPHER_get_asn1_iv(EVP_CIPHER_CTX *ctx, ASN1_TYPE *type)
 {
     int i = 0;
     unsigned int l;
 
     if (type != NULL) {
-        l = EVP_CIPHER_CTX_iv_length(c);
-        OPENSSL_assert(l <= sizeof(c->iv));
-        i = ASN1_TYPE_get_octetstring(type, c->oiv, l);
+        unsigned char iv[EVP_MAX_IV_LENGTH];
+
+        l = EVP_CIPHER_CTX_iv_length(ctx);
+        if (!ossl_assert(l <= sizeof(iv)))
+            return -1;
+        i = ASN1_TYPE_get_octetstring(type, iv, l);
         if (i != (int)l)
             return -1;
-        else if (i > 0)
-            memcpy(c->iv, c->oiv, l);
+
+        if (!EVP_CipherInit_ex(ctx, NULL, NULL, NULL, iv, -1))
+            return -1;
     }
     return i;
 }
@@ -175,14 +207,20 @@ int EVP_CIPHER_type(const EVP_CIPHER *ctx)
     }
 }
 
-int EVP_CIPHER_block_size(const EVP_CIPHER *e)
+int EVP_CIPHER_block_size(const EVP_CIPHER *cipher)
 {
-    return e->block_size;
+    if (cipher->prov != NULL) {
+        if (cipher->blocksize != NULL)
+            return cipher->blocksize();
+        /* We default to a block size of 1 */
+        return 1;
+    }
+    return cipher->block_size;
 }
 
 int EVP_CIPHER_CTX_block_size(const EVP_CIPHER_CTX *ctx)
 {
-    return ctx->cipher->block_size;
+    return EVP_CIPHER_block_size(ctx->cipher);
 }
 
 int EVP_CIPHER_impl_ctx_size(const EVP_CIPHER *e)
@@ -193,6 +231,12 @@ int EVP_CIPHER_impl_ctx_size(const EVP_CIPHER *e)
 int EVP_Cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
                const unsigned char *in, unsigned int inl)
 {
+    if (ctx->cipher->prov != NULL) {
+        if (ctx->cipher->ccipher != NULL)
+            return ctx->cipher->ccipher(ctx->provctx, out, in, (size_t)inl);
+        return 0;
+    }
+
     return ctx->cipher->do_cipher(ctx, out, in, inl);
 }
 
@@ -238,12 +282,18 @@ void *EVP_CIPHER_CTX_set_cipher_data(EVP_CIPHER_CTX *ctx, void *cipher_data)
 
 int EVP_CIPHER_iv_length(const EVP_CIPHER *cipher)
 {
+    if (cipher->prov != NULL) {
+        if (cipher->iv_length != NULL)
+            return (int)cipher->iv_length();
+        return 0;
+    }
+
     return cipher->iv_len;
 }
 
 int EVP_CIPHER_CTX_iv_length(const EVP_CIPHER_CTX *ctx)
 {
-    return ctx->cipher->iv_len;
+    return EVP_CIPHER_iv_length(ctx->cipher);
 }
 
 const unsigned char *EVP_CIPHER_CTX_original_iv(const EVP_CIPHER_CTX *ctx)
@@ -278,11 +328,23 @@ void EVP_CIPHER_CTX_set_num(EVP_CIPHER_CTX *ctx, int num)
 
 int EVP_CIPHER_key_length(const EVP_CIPHER *cipher)
 {
+    if (cipher->prov != NULL) {
+        if (cipher->key_length != NULL)
+            return (int)cipher->key_length();
+        return -1;
+    }
+
     return cipher->key_len;
 }
 
 int EVP_CIPHER_CTX_key_length(const EVP_CIPHER_CTX *ctx)
 {
+    /*
+     * TODO(3.0): This may need to change if/when we introduce variable length
+     * key ciphers into the providers.
+     */
+    if (ctx->cipher != NULL && ctx->cipher->prov != NULL)
+        return EVP_CIPHER_key_length(ctx->cipher);
     return ctx->key_len;
 }
 
@@ -296,6 +358,33 @@ int EVP_CIPHER_CTX_nid(const EVP_CIPHER_CTX *ctx)
     return ctx->cipher->nid;
 }
 
+int EVP_CIPHER_mode(const EVP_CIPHER *cipher)
+{
+    if (cipher->prov != NULL) {
+        int mode;
+
+        /* Cipher comes from a provider - so ask the provider for the mode */
+        OSSL_PARAM params[] = {
+            OSSL_PARAM_int(OSSL_CIPHER_PARAM_MODE, NULL),
+            OSSL_PARAM_END
+        };
+
+        params[0].data = &mode;
+
+        if (cipher->get_params == NULL) {
+            EVPerr(EVP_F_EVP_CIPHER_MODE, EVP_R_CTRL_NOT_IMPLEMENTED);
+            return 0;
+        }
+
+        if (!cipher->get_params(params))
+            return 0;
+
+        return mode;
+    }
+    return EVP_CIPHER_flags(cipher) & EVP_CIPH_MODE;
+}
+
+
 int EVP_MD_block_size(const EVP_MD *md)
 {
     if (md == NULL) {
@@ -353,12 +442,16 @@ EVP_MD *EVP_MD_meth_new(int md_type, int pkey_type)
     }
     return md;
 }
+
 EVP_MD *EVP_MD_meth_dup(const EVP_MD *md)
 {
     EVP_MD *to = EVP_MD_meth_new(md->type, md->pkey_type);
 
-    if (to != NULL)
+    if (to != NULL) {
+        CRYPTO_RWLOCK *lock = to->lock;
         memcpy(to, md, sizeof(*to));
+        to->lock = lock;
+    }
     return to;
 }
 
diff --git a/crypto/evp/evp_locl.h b/crypto/evp/evp_locl.h
index efa2db8..3172c49 100644
--- a/crypto/evp/evp_locl.h
+++ b/crypto/evp/evp_locl.h
@@ -44,6 +44,10 @@ struct evp_cipher_ctx_st {
     int final_used;
     int block_mask;
     unsigned char final[EVP_MAX_BLOCK_LENGTH]; /* possible final block */
+
+    /* Provider ctx */
+    void *provctx;
+    EVP_CIPHER *fetched_cipher;
 } /* EVP_CIPHER_CTX */ ;
 
 struct evp_mac_ctx_st {
diff --git a/crypto/include/internal/evp_int.h b/crypto/include/internal/evp_int.h
index c932898..b3d9694 100644
--- a/crypto/include/internal/evp_int.h
+++ b/crypto/include/internal/evp_int.h
@@ -210,10 +210,14 @@ struct evp_md_st {
 
 struct evp_cipher_st {
     int nid;
+
     int block_size;
     /* Default value for variable length ciphers */
     int key_len;
     int iv_len;
+
+    /* Legacy structure members */
+    /* TODO(3.0): Remove these */
     /* Various flags */
     unsigned long flags;
     /* init key */
@@ -234,6 +238,26 @@ struct evp_cipher_st {
     int (*ctrl) (EVP_CIPHER_CTX *, int type, int arg, void *ptr);
     /* Application data */
     void *app_data;
+
+    /* New structure members */
+    /* TODO(3.0): Remove above comment when legacy has gone */
+    OSSL_PROVIDER *prov;
+    CRYPTO_REF_COUNT refcnt;
+    CRYPTO_RWLOCK *lock;
+    OSSL_OP_cipher_newctx_fn *newctx;
+    OSSL_OP_cipher_encrypt_init_fn *einit;
+    OSSL_OP_cipher_decrypt_init_fn *dinit;
+    OSSL_OP_cipher_update_fn *cupdate;
+    OSSL_OP_cipher_final_fn *cfinal;
+    OSSL_OP_cipher_cipher_fn *ccipher;
+    OSSL_OP_cipher_freectx_fn *freectx;
+    OSSL_OP_cipher_dupctx_fn *dupctx;
+    OSSL_OP_cipher_key_length_fn *key_length;
+    OSSL_OP_cipher_iv_length_fn *iv_length;
+    OSSL_OP_cipher_block_size_fn *blocksize;
+    OSSL_OP_cipher_get_params_fn *get_params;
+    OSSL_OP_cipher_ctx_get_params_fn *ctx_get_params;
+    OSSL_OP_cipher_ctx_set_params_fn *ctx_set_params;
 } /* EVP_CIPHER */ ;
 
 /* Macros to code block cipher wrappers */
diff --git a/include/openssl/core_names.h b/include/openssl/core_names.h
index be4a647..35a23d7 100644
--- a/include/openssl/core_names.h
+++ b/include/openssl/core_names.h
@@ -34,6 +34,12 @@ extern "C" {
  */
 #define OSSL_PROV_PARAM_BUILDINFO   "buildinfo"
 
+
+/* Well known cipher parameters */
+
+#define OSSL_CIPHER_PARAM_PADDING   "padding"
+#define OSSL_CIPHER_PARAM_MODE      "mode"
+
 # ifdef __cplusplus
 }
 # endif
diff --git a/include/openssl/core_numbers.h b/include/openssl/core_numbers.h
index 2054381..d588886 100644
--- a/include/openssl/core_numbers.h
+++ b/include/openssl/core_numbers.h
@@ -78,7 +78,7 @@ OSSL_CORE_MAKE_FUNC(const OSSL_ALGORITHM *,provider_query_operation,
 
 # define OSSL_FUNC_DIGEST_NEWCTX            1
 # define OSSL_FUNC_DIGEST_INIT              2
-# define OSSL_FUNC_DIGEST_UPDDATE           3
+# define OSSL_FUNC_DIGEST_UPDATE            3
 # define OSSL_FUNC_DIGEST_FINAL             4
 # define OSSL_FUNC_DIGEST_DIGEST            5
 # define OSSL_FUNC_DIGEST_FREECTX           6
@@ -86,6 +86,7 @@ OSSL_CORE_MAKE_FUNC(const OSSL_ALGORITHM *,provider_query_operation,
 # define OSSL_FUNC_DIGEST_SIZE              8
 # define OSSL_FUNC_DIGEST_BLOCK_SIZE        9
 
+
 OSSL_CORE_MAKE_FUNC(void *, OP_digest_newctx, (void))
 OSSL_CORE_MAKE_FUNC(int, OP_digest_init, (void *vctx))
 OSSL_CORE_MAKE_FUNC(int, OP_digest_update,
@@ -95,12 +96,64 @@ OSSL_CORE_MAKE_FUNC(int, OP_digest_final,
 OSSL_CORE_MAKE_FUNC(int, OP_digest_digest,
                     (const unsigned char *in, size_t inl, unsigned char *out,
                      size_t *out_l, size_t outsz))
+
 OSSL_CORE_MAKE_FUNC(void, OP_digest_cleanctx, (void *vctx))
 OSSL_CORE_MAKE_FUNC(void, OP_digest_freectx, (void *vctx))
 OSSL_CORE_MAKE_FUNC(void *, OP_digest_dupctx, (void *vctx))
 OSSL_CORE_MAKE_FUNC(size_t, OP_digest_size, (void))
 OSSL_CORE_MAKE_FUNC(size_t, OP_digest_block_size, (void))
 
+
+/* Symmetric Ciphers */
+
+# define OSSL_OP_CIPHER                              2
+
+# define OSSL_FUNC_CIPHER_NEWCTX                     1
+# define OSSL_FUNC_CIPHER_ENCRYPT_INIT               2
+# define OSSL_FUNC_CIPHER_DECRYPT_INIT               3
+# define OSSL_FUNC_CIPHER_UPDATE                     4
+# define OSSL_FUNC_CIPHER_FINAL                      5
+# define OSSL_FUNC_CIPHER_CIPHER                     6
+# define OSSL_FUNC_CIPHER_FREECTX                    7
+# define OSSL_FUNC_CIPHER_DUPCTX                     8
+# define OSSL_FUNC_CIPHER_KEY_LENGTH                 9
+# define OSSL_FUNC_CIPHER_IV_LENGTH                 10
+# define OSSL_FUNC_CIPHER_BLOCK_SIZE                11
+# define OSSL_FUNC_CIPHER_GET_PARAMS                12
+# define OSSL_FUNC_CIPHER_CTX_GET_PARAMS            13
+# define OSSL_FUNC_CIPHER_CTX_SET_PARAMS            14
+
+OSSL_CORE_MAKE_FUNC(void *, OP_cipher_newctx, (void))
+OSSL_CORE_MAKE_FUNC(int, OP_cipher_encrypt_init, (void *vctx,
+                                                  const unsigned char *key,
+                                                  size_t keylen,
+                                                  const unsigned char *iv,
+                                                  size_t ivlen))
+OSSL_CORE_MAKE_FUNC(int, OP_cipher_decrypt_init, (void *vctx,
+                                                  const unsigned char *key,
+                                                  size_t keylen,
+                                                  const unsigned char *iv,
+                                                  size_t ivlen))
+OSSL_CORE_MAKE_FUNC(int, OP_cipher_update,
+                    (void *, unsigned char *out, size_t *outl, size_t outsize,
+                     const unsigned char *in, size_t inl))
+OSSL_CORE_MAKE_FUNC(int, OP_cipher_final,
+                    (void *, unsigned char *out, size_t *outl, size_t outsize))
+OSSL_CORE_MAKE_FUNC(int, OP_cipher_cipher,
+                    (void *, unsigned char *out, const unsigned char *in,
+                     size_t inl))
+OSSL_CORE_MAKE_FUNC(void, OP_cipher_freectx, (void *vctx))
+OSSL_CORE_MAKE_FUNC(void *, OP_cipher_dupctx, (void *vctx))
+OSSL_CORE_MAKE_FUNC(size_t, OP_cipher_key_length, (void))
+OSSL_CORE_MAKE_FUNC(size_t, OP_cipher_iv_length, (void))
+OSSL_CORE_MAKE_FUNC(size_t, OP_cipher_block_size, (void))
+OSSL_CORE_MAKE_FUNC(int, OP_cipher_get_params, (const OSSL_PARAM params[]))
+OSSL_CORE_MAKE_FUNC(int, OP_cipher_ctx_get_params, (void *vctx,
+                                                    const OSSL_PARAM params[]))
+OSSL_CORE_MAKE_FUNC(int, OP_cipher_ctx_set_params, (void *vctx,
+                                                    const OSSL_PARAM params[]))
+
+
 # ifdef __cplusplus
 }
 # endif
diff --git a/include/openssl/err.h b/include/openssl/err.h
index 136b000..8fcdfb4 100644
--- a/include/openssl/err.h
+++ b/include/openssl/err.h
@@ -98,6 +98,7 @@ typedef struct err_state_st {
 # define ERR_LIB_ESS             54
 # define ERR_LIB_PROP            55
 # define ERR_LIB_CRMF            56
+# define ERR_LIB_PROV            57
 
 # define ERR_LIB_USER            128
 
@@ -140,6 +141,7 @@ typedef struct err_state_st {
 # define SM2err(f,r) ERR_PUT_error(ERR_LIB_SM2,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
 # define ESSerr(f,r) ERR_PUT_error(ERR_LIB_ESS,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
 # define PROPerr(f,r) ERR_PUT_error(ERR_LIB_PROP,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
+# define PROVerr(f,r) ERR_PUT_error(ERR_LIB_PROV,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
 
 # define ERR_PACK(l,f,r) ( \
         (((unsigned int)(l) & 0x0FF) << 24L) | \
diff --git a/include/openssl/evp.h b/include/openssl/evp.h
index a903b29..6fc0f35 100644
--- a/include/openssl/evp.h
+++ b/include/openssl/evp.h
@@ -190,6 +190,7 @@ int (*EVP_MD_meth_get_ctrl(const EVP_MD *md))(EVP_MD_CTX *ctx, int cmd,
 EVP_CIPHER *EVP_CIPHER_meth_new(int cipher_type, int block_size, int key_len);
 EVP_CIPHER *EVP_CIPHER_meth_dup(const EVP_CIPHER *cipher);
 void EVP_CIPHER_meth_free(EVP_CIPHER *cipher);
+int EVP_CIPHER_upref(EVP_CIPHER *cipher);
 
 int EVP_CIPHER_meth_set_iv_length(EVP_CIPHER *cipher, int iv_len);
 int EVP_CIPHER_meth_set_flags(EVP_CIPHER *cipher, unsigned long flags);
@@ -473,7 +474,9 @@ int EVP_CIPHER_impl_ctx_size(const EVP_CIPHER *cipher);
 int EVP_CIPHER_key_length(const EVP_CIPHER *cipher);
 int EVP_CIPHER_iv_length(const EVP_CIPHER *cipher);
 unsigned long EVP_CIPHER_flags(const EVP_CIPHER *cipher);
-# define EVP_CIPHER_mode(e)              (EVP_CIPHER_flags(e) & EVP_CIPH_MODE)
+int EVP_CIPHER_mode(const EVP_CIPHER *cipher);
+EVP_CIPHER *EVP_CIPHER_fetch(OPENSSL_CTX *ctx, const char *algorithm,
+                             const char *properties);
 
 const EVP_CIPHER *EVP_CIPHER_CTX_cipher(const EVP_CIPHER_CTX *ctx);
 int EVP_CIPHER_CTX_encrypting(const EVP_CIPHER_CTX *ctx);
diff --git a/include/openssl/evperr.h b/include/openssl/evperr.h
index e62cfb3..d88d4a8 100644
--- a/include/openssl/evperr.h
+++ b/include/openssl/evperr.h
@@ -55,6 +55,9 @@ int ERR_load_EVP_strings(void);
 # define EVP_F_EVP_CIPHER_CTX_COPY                        163
 # define EVP_F_EVP_CIPHER_CTX_CTRL                        124
 # define EVP_F_EVP_CIPHER_CTX_SET_KEY_LENGTH              122
+# define EVP_F_EVP_CIPHER_CTX_SET_PADDING                 237
+# define EVP_F_EVP_CIPHER_FROM_DISPATCH                   238
+# define EVP_F_EVP_CIPHER_MODE                            239
 # define EVP_F_EVP_CIPHER_PARAM_TO_ASN1                   205
 # define EVP_F_EVP_DECRYPTFINAL_EX                        101
 # define EVP_F_EVP_DECRYPTUPDATE                          166
@@ -190,6 +193,7 @@ int ERR_load_EVP_strings(void);
 # define EVP_R_INVALID_KEY                                163
 # define EVP_R_INVALID_KEY_LENGTH                         130
 # define EVP_R_INVALID_OPERATION                          148
+# define EVP_R_INVALID_PROVIDER_FUNCTIONS                 193
 # define EVP_R_INVALID_SALT_LENGTH                        186
 # define EVP_R_KEYGEN_FAILURE                             120
 # define EVP_R_KEY_SETUP_FAILED                           180
diff --git a/providers/build.info b/providers/build.info
index 1628e1f..ef107a7 100644
--- a/providers/build.info
+++ b/providers/build.info
@@ -7,7 +7,7 @@ IF[{- !$disabled{fips} -}]
     SOURCE[fips]=fips.ld
     GENERATE[fips.ld]=../util/providers.num
   ENDIF
-  INCLUDE[fips]=.. ../include ../crypto/include
+  INCLUDE[fips]=.. ../include ../crypto/include common/include
   DEFINE[fips]=FIPS_MODE
 ENDIF
 
diff --git a/providers/common/build.info b/providers/common/build.info
index 5cb7e43..1617467 100644
--- a/providers/common/build.info
+++ b/providers/common/build.info
@@ -1 +1,4 @@
-SUBDIRS=digests
+SUBDIRS=digests ciphers
+
+SOURCE[../../libcrypto]=\
+        provider_err.c
diff --git a/providers/common/ciphers/aes.c b/providers/common/ciphers/aes.c
new file mode 100644
index 0000000..5c6e670
--- /dev/null
+++ b/providers/common/ciphers/aes.c
@@ -0,0 +1,470 @@
+/*
+ * 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 <string.h>
+#include <openssl/crypto.h>
+#include <openssl/core_numbers.h>
+#include <openssl/core_names.h>
+#include <openssl/evp.h>
+#include <openssl/params.h>
+#include "internal/cryptlib.h"
+#include "internal/provider_algs.h"
+#include "ciphers_locl.h"
+#include "internal/providercommonerr.h"
+
+static OSSL_OP_cipher_encrypt_init_fn aes_einit;
+static OSSL_OP_cipher_decrypt_init_fn aes_dinit;
+static OSSL_OP_cipher_update_fn aes_block_update;
+static OSSL_OP_cipher_final_fn aes_block_final;
+static OSSL_OP_cipher_update_fn aes_stream_update;
+static OSSL_OP_cipher_final_fn aes_stream_final;
+static OSSL_OP_cipher_cipher_fn aes_cipher;
+static OSSL_OP_cipher_freectx_fn aes_freectx;
+static OSSL_OP_cipher_dupctx_fn aes_dupctx;
+static OSSL_OP_cipher_key_length_fn key_length_256;
+static OSSL_OP_cipher_key_length_fn key_length_192;
+static OSSL_OP_cipher_key_length_fn key_length_128;
+static OSSL_OP_cipher_iv_length_fn iv_length_16;
+static OSSL_OP_cipher_iv_length_fn iv_length_0;
+static OSSL_OP_cipher_block_size_fn block_size_16;
+static OSSL_OP_cipher_block_size_fn block_size_1;
+static OSSL_OP_cipher_ctx_get_params_fn aes_ctx_get_params;
+static OSSL_OP_cipher_ctx_set_params_fn aes_ctx_set_params;
+
+static int PROV_AES_KEY_generic_init(PROV_AES_KEY *ctx,
+                                      const unsigned char *iv,
+                                      size_t ivlen,
+                                      int enc)
+{
+    if (iv != NULL && ctx->mode != EVP_CIPH_ECB_MODE) {
+        if (ivlen != AES_BLOCK_SIZE) {
+            PROVerr(PROV_F_PROV_AES_KEY_GENERIC_INIT, ERR_R_INTERNAL_ERROR);
+            return 0;
+        }
+        memcpy(ctx->iv, iv, AES_BLOCK_SIZE);
+    }
+    ctx->enc = enc;
+
+    return 1;
+}
+
+static int aes_einit(void *vctx, const unsigned char *key, size_t keylen,
+                           const unsigned char *iv, size_t ivlen)
+{
+    PROV_AES_KEY *ctx = (PROV_AES_KEY *)vctx;
+
+    if (!PROV_AES_KEY_generic_init(ctx, iv, ivlen, 1)) {
+        /* PROVerr already called */
+        return 0;
+    }
+    if (key != NULL) {
+        if (keylen != ctx->keylen) {
+            PROVerr(PROV_F_AES_EINIT, PROV_R_INVALID_KEYLEN);
+            return 0;
+        }
+        return ctx->ciph->init(ctx, key, ctx->keylen);
+    }
+
+    return 1;
+}
+
+static int aes_dinit(void *vctx, const unsigned char *key, size_t keylen,
+                     const unsigned char *iv, size_t ivlen)
+{
+    PROV_AES_KEY *ctx = (PROV_AES_KEY *)vctx;
+
+    if (!PROV_AES_KEY_generic_init(ctx, iv, ivlen, 0)) {
+        /* PROVerr already called */
+        return 0;
+    }
+    if (key != NULL) {
+        if (keylen != ctx->keylen) {
+            PROVerr(PROV_F_AES_DINIT, PROV_R_INVALID_KEYLEN);
+            return 0;
+        }
+        return ctx->ciph->init(ctx, key, ctx->keylen);
+    }
+
+    return 1;
+}
+
+static int aes_block_update(void *vctx, unsigned char *out, size_t *outl,
+                            size_t outsize, const unsigned char *in, size_t inl)
+{
+    PROV_AES_KEY *ctx = (PROV_AES_KEY *)vctx;
+    size_t nextblocks = fillblock(ctx->buf, &ctx->bufsz, AES_BLOCK_SIZE, &in,
+                                  &inl);
+    size_t outlint = 0;
+
+    /*
+     * 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 == AES_BLOCK_SIZE
+            && (ctx->enc || inl > 0 || !ctx->pad)) {
+        if (outsize < AES_BLOCK_SIZE) {
+            PROVerr(PROV_F_AES_BLOCK_UPDATE, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
+            return 0;
+        }
+        if (!ctx->ciph->cipher(ctx, out, ctx->buf, AES_BLOCK_SIZE)) {
+            PROVerr(PROV_F_AES_BLOCK_UPDATE, PROV_R_CIPHER_OPERATION_FAILED);
+            return 0;
+        }
+        ctx->bufsz = 0;
+        outlint = AES_BLOCK_SIZE;
+        out += AES_BLOCK_SIZE;
+    }
+    if (nextblocks > 0) {
+        if (!ctx->enc && ctx->pad && nextblocks == inl) {
+            if (!ossl_assert(inl >= AES_BLOCK_SIZE)) {
+                PROVerr(PROV_F_AES_BLOCK_UPDATE, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
+                return 0;
+            }
+            nextblocks -= AES_BLOCK_SIZE;
+        }
+        outlint += nextblocks;
+        if (outsize < outlint) {
+            PROVerr(PROV_F_AES_BLOCK_UPDATE, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
+            return 0;
+        }
+        if (!ctx->ciph->cipher(ctx, out, in, nextblocks)) {
+            PROVerr(PROV_F_AES_BLOCK_UPDATE, PROV_R_CIPHER_OPERATION_FAILED);
+            return 0;
+        }
+        in += nextblocks;
+        inl -= nextblocks;
+    }
+    if (!trailingdata(ctx->buf, &ctx->bufsz, AES_BLOCK_SIZE, &in, &inl)) {
+        /* PROVerr already called */
+        return 0;
+    }
+
+    *outl = outlint;
+    return inl == 0;
+}
+
+static int aes_block_final(void *vctx, unsigned char *out, size_t *outl,
+                           size_t outsize)
+{
+    PROV_AES_KEY *ctx = (PROV_AES_KEY *)vctx;
+
+    if (ctx->enc) {
+        if (ctx->pad) {
+            padblock(ctx->buf, &ctx->bufsz, AES_BLOCK_SIZE);
+        } else if (ctx->bufsz == 0) {
+            *outl = 0;
+            return 1;
+        } else if (ctx->bufsz != AES_BLOCK_SIZE) {
+            PROVerr(PROV_F_AES_BLOCK_FINAL, PROV_R_WRONG_FINAL_BLOCK_LENGTH);
+            return 0;
+        }
+
+        if (outsize < AES_BLOCK_SIZE) {
+            PROVerr(PROV_F_AES_BLOCK_FINAL, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
+            return 0;
+        }
+        if (!ctx->ciph->cipher(ctx, out, ctx->buf, AES_BLOCK_SIZE)) {
+            PROVerr(PROV_F_AES_BLOCK_FINAL, PROV_R_CIPHER_OPERATION_FAILED);
+            return 0;
+        }
+        ctx->bufsz = 0;
+        *outl = AES_BLOCK_SIZE;
+        return 1;
+    }
+
+    /* Decrypting */
+    if (ctx->bufsz != AES_BLOCK_SIZE) {
+        if (ctx->bufsz == 0 && !ctx->pad) {
+            *outl = 0;
+            return 1;
+        }
+        PROVerr(PROV_F_AES_BLOCK_FINAL, PROV_R_WRONG_FINAL_BLOCK_LENGTH);
+        return 0;
+    }
+
+    if (!ctx->ciph->cipher(ctx, ctx->buf, ctx->buf, AES_BLOCK_SIZE)) {
+        PROVerr(PROV_F_AES_BLOCK_FINAL, PROV_R_CIPHER_OPERATION_FAILED);
+        return 0;
+    }
+
+    if (ctx->pad && !unpadblock(ctx->buf, &ctx->bufsz, AES_BLOCK_SIZE)) {
+        /* PROVerr already called */
+        return 0;
+    }
+
+    if (outsize < ctx->bufsz) {
+        PROVerr(PROV_F_AES_BLOCK_FINAL, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
+        return 0;
+    }
+    memcpy(out, ctx->buf, ctx->bufsz);
+    *outl = ctx->bufsz;
+    ctx->bufsz = 0;
+    return 1;
+}
+
+static int aes_stream_update(void *vctx, unsigned char *out, size_t *outl,
+                             size_t outsize, const unsigned char *in,
+                             size_t inl)
+{
+    PROV_AES_KEY *ctx = (PROV_AES_KEY *)vctx;
+
+    if (outsize < inl) {
+        PROVerr(PROV_F_AES_STREAM_UPDATE, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
+        return 0;
+    }
+
+    if (!ctx->ciph->cipher(ctx, out, in, inl)) {
+        PROVerr(PROV_F_AES_STREAM_UPDATE, PROV_R_CIPHER_OPERATION_FAILED);
+        return 0;
+    }
+
+    *outl = inl;
+    return 1;
+}
+static int aes_stream_final(void *vctx, unsigned char *out, size_t *outl,
+                            size_t outsize)
+{
+    *outl = 0;
+    return 1;
+}
+
+static int aes_cipher(void *vctx, unsigned char *out, const unsigned char *in,
+                      size_t inl)
+{
+    PROV_AES_KEY *ctx = (PROV_AES_KEY *)vctx;
+
+    if (!ctx->ciph->cipher(ctx, out, in, inl)) {
+        PROVerr(PROV_F_AES_CIPHER, PROV_R_CIPHER_OPERATION_FAILED);
+        return 0;
+    }
+
+    return 1;
+}
+
+#define IMPLEMENT_new_params(lcmode, UCMODE) \
+    static OSSL_OP_cipher_get_params_fn aes_##lcmode##_get_params; \
+    static int aes_##lcmode##_get_params(const OSSL_PARAM params[]) \
+    { \
+        const OSSL_PARAM *p; \
+    \
+        p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_MODE); \
+        if (p != NULL && !OSSL_PARAM_set_int(p, EVP_CIPH_##UCMODE##_MODE)) \
+            return 0; \
+    \
+        return 1; \
+    }
+
+#define IMPLEMENT_new_ctx(lcmode, UCMODE, len) \
+    static OSSL_OP_cipher_newctx_fn aes_##len##_##lcmode##_newctx; \
+    static void *aes_##len##_##lcmode##_newctx(void) \
+    { \
+        PROV_AES_KEY *ctx = OPENSSL_zalloc(sizeof(*ctx)); \
+    \
+        ctx->pad = 1; \
+        ctx->keylen = (len / 8); \
+        ctx->ciph = PROV_AES_CIPHER_##lcmode(ctx->keylen); \
+        ctx->mode = EVP_CIPH_##UCMODE##_MODE; \
+        return ctx; \
+    }
+
+/* ECB */
+IMPLEMENT_new_params(ecb, ECB)
+IMPLEMENT_new_ctx(ecb, ECB, 256)
+IMPLEMENT_new_ctx(ecb, ECB, 192)
+IMPLEMENT_new_ctx(ecb, ECB, 128)
+
+/* CBC */
+IMPLEMENT_new_params(cbc, CBC)
+IMPLEMENT_new_ctx(cbc, CBC, 256)
+IMPLEMENT_new_ctx(cbc, CBC, 192)
+IMPLEMENT_new_ctx(cbc, CBC, 128)
+
+/* OFB */
+IMPLEMENT_new_params(ofb, OFB)
+IMPLEMENT_new_ctx(ofb, OFB, 256)
+IMPLEMENT_new_ctx(ofb, OFB, 192)
+IMPLEMENT_new_ctx(ofb, OFB, 128)
+
+/* CFB */
+IMPLEMENT_new_params(cfb, CFB)
+IMPLEMENT_new_params(cfb1, CFB)
+IMPLEMENT_new_params(cfb8, CFB)
+IMPLEMENT_new_ctx(cfb, CFB, 256)
+IMPLEMENT_new_ctx(cfb, CFB, 192)
+IMPLEMENT_new_ctx(cfb, CFB, 128)
+IMPLEMENT_new_ctx(cfb1, CFB, 256)
+IMPLEMENT_new_ctx(cfb1, CFB, 192)
+IMPLEMENT_new_ctx(cfb1, CFB, 128)
+IMPLEMENT_new_ctx(cfb8, CFB, 256)
+IMPLEMENT_new_ctx(cfb8, CFB, 192)
+IMPLEMENT_new_ctx(cfb8, CFB, 128)
+
+/* CTR */
+IMPLEMENT_new_params(ctr, CTR)
+IMPLEMENT_new_ctx(ctr, CTR, 256)
+IMPLEMENT_new_ctx(ctr, CTR, 192)
+IMPLEMENT_new_ctx(ctr, CTR, 128)
+
+static void aes_freectx(void *vctx)
+{
+    PROV_AES_KEY *ctx = (PROV_AES_KEY *)vctx;
+
+    OPENSSL_clear_free(ctx,  sizeof(*ctx));
+}
+
+static void *aes_dupctx(void *ctx)
+{
+    PROV_AES_KEY *in = (PROV_AES_KEY *)ctx;
+    PROV_AES_KEY *ret = OPENSSL_malloc(sizeof(*ret));
+
+    if (ret == NULL) {
+        PROVerr(PROV_F_AES_DUPCTX, ERR_R_MALLOC_FAILURE);
+        return NULL;
+    }
+    *ret = *in;
+
+    return ret;
+}
+
+static size_t key_length_256(void)
+{
+    return 256 / 8;
+}
+
+static size_t key_length_192(void)
+{
+    return 192 / 8;
+}
+
+static size_t key_length_128(void)
+{
+    return 128 / 8;
+}
+
+static size_t iv_length_16(void)
+{
+    return 16;
+}
+
+static size_t iv_length_0(void)
+{
+    return 0;
+}
+
+static size_t block_size_16(void)
+{
+    return 16;
+}
+
+static size_t block_size_1(void)
+{
+    return 1;
+}
+
+static int aes_ctx_get_params(void *vctx, const OSSL_PARAM params[])
+{
+    PROV_AES_KEY *ctx = (PROV_AES_KEY *)vctx;
+    const OSSL_PARAM *p;
+
+    p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_PADDING);
+    if (p != NULL && !OSSL_PARAM_set_int(p, ctx->pad)) {
+        PROVerr(PROV_F_AES_CTX_GET_PARAMS, PROV_R_FAILED_TO_SET_PARAMETER);
+        return 0;
+    }
+
+    return 1;
+}
+
+static int aes_ctx_set_params(void *vctx, const OSSL_PARAM params[])
+{
+    PROV_AES_KEY *ctx = (PROV_AES_KEY *)vctx;
+    const OSSL_PARAM *p;
+
+    p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_PADDING);
+    if (p != NULL) {
+        int pad;
+
+        if (!OSSL_PARAM_get_int(p, &pad)) {
+        PROVerr(PROV_F_AES_CTX_SET_PARAMS, PROV_R_FAILED_TO_GET_PARAMETER);
+            return 0;
+        }
+        ctx->pad = pad ? 1 : 0;
+    }
+    return 1;
+}
+
+#define IMPLEMENT_block_funcs(mode, keylen, ivlen) \
+    const OSSL_DISPATCH aes##keylen##mode##_functions[] = { \
+        { OSSL_FUNC_CIPHER_NEWCTX, (void (*)(void))aes_##keylen##_##mode##_newctx }, \
+        { OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))aes_einit }, \
+        { OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))aes_dinit }, \
+        { OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))aes_block_update }, \
+        { OSSL_FUNC_CIPHER_FINAL, (void (*)(void))aes_block_final }, \
+        { OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))aes_cipher }, \
+        { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))aes_freectx }, \
+        { OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void))aes_dupctx }, \
+        { OSSL_FUNC_CIPHER_KEY_LENGTH, (void (*)(void))key_length_##keylen }, \
+        { OSSL_FUNC_CIPHER_IV_LENGTH, (void (*)(void))iv_length_##ivlen }, \
+        { OSSL_FUNC_CIPHER_BLOCK_SIZE, (void (*)(void))block_size_16 }, \
+        { OSSL_FUNC_CIPHER_GET_PARAMS, (void (*)(void))aes_##mode##_get_params }, \
+        { OSSL_FUNC_CIPHER_CTX_GET_PARAMS, (void (*)(void))aes_ctx_get_params }, \
+        { OSSL_FUNC_CIPHER_CTX_SET_PARAMS, (void (*)(void))aes_ctx_set_params }, \
+        { 0, NULL } \
+    };
+
+#define IMPLEMENT_stream_funcs(mode, keylen, ivlen) \
+    const OSSL_DISPATCH aes##keylen##mode##_functions[] = { \
+        { OSSL_FUNC_CIPHER_NEWCTX, (void (*)(void))aes_##keylen##_##mode##_newctx }, \
+        { OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))aes_einit }, \
+        { OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))aes_dinit }, \
+        { OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))aes_stream_update }, \
+        { OSSL_FUNC_CIPHER_FINAL, (void (*)(void))aes_stream_final }, \
+        { OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))aes_cipher }, \
+        { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))aes_freectx }, \
+        { OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void))aes_dupctx }, \
+        { OSSL_FUNC_CIPHER_KEY_LENGTH, (void (*)(void))key_length_##keylen }, \
+        { OSSL_FUNC_CIPHER_IV_LENGTH, (void (*)(void))iv_length_##ivlen }, \
+        { OSSL_FUNC_CIPHER_BLOCK_SIZE, (void (*)(void))block_size_1 }, \
+        { OSSL_FUNC_CIPHER_GET_PARAMS, (void (*)(void))aes_##mode##_get_params }, \
+        { OSSL_FUNC_CIPHER_CTX_GET_PARAMS, (void (*)(void))aes_ctx_get_params }, \
+        { OSSL_FUNC_CIPHER_CTX_SET_PARAMS, (void (*)(void))aes_ctx_set_params }, \
+        { 0, NULL } \
+    };
+
+/* ECB */
+IMPLEMENT_block_funcs(ecb, 256, 0)
+IMPLEMENT_block_funcs(ecb, 192, 0)
+IMPLEMENT_block_funcs(ecb, 128, 0)
+
+/* CBC */
+IMPLEMENT_block_funcs(cbc, 256, 16)
+IMPLEMENT_block_funcs(cbc, 192, 16)
+IMPLEMENT_block_funcs(cbc, 128, 16)
+
+/* OFB */
+IMPLEMENT_stream_funcs(ofb, 256, 16)
+IMPLEMENT_stream_funcs(ofb, 192, 16)
+IMPLEMENT_stream_funcs(ofb, 128, 16)
+
+/* CFB */
+IMPLEMENT_stream_funcs(cfb, 256, 16)
+IMPLEMENT_stream_funcs(cfb, 192, 16)
+IMPLEMENT_stream_funcs(cfb, 128, 16)
+IMPLEMENT_stream_funcs(cfb1, 256, 16)
+IMPLEMENT_stream_funcs(cfb1, 192, 16)
+IMPLEMENT_stream_funcs(cfb1, 128, 16)
+IMPLEMENT_stream_funcs(cfb8, 256, 16)
+IMPLEMENT_stream_funcs(cfb8, 192, 16)
+IMPLEMENT_stream_funcs(cfb8, 128, 16)
+
+/* CTR */
+IMPLEMENT_stream_funcs(ctr, 256, 16)
+IMPLEMENT_stream_funcs(ctr, 192, 16)
+IMPLEMENT_stream_funcs(ctr, 128, 16)
diff --git a/providers/common/ciphers/aes_basic.c b/providers/common/ciphers/aes_basic.c
new file mode 100644
index 0000000..0f64296
--- /dev/null
+++ b/providers/common/ciphers/aes_basic.c
@@ -0,0 +1,866 @@
+/*
+ * Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/opensslconf.h>
+#include <openssl/crypto.h>
+#include <openssl/err.h>
+#include <string.h>
+#include <assert.h>
+#include <openssl/aes.h>
+#include "internal/evp_int.h"
+#include <openssl/rand.h>
+#include <openssl/cmac.h>
+#include "ciphers_locl.h"
+#include "internal/providercommonerr.h"
+
+#define MAXBITCHUNK     ((size_t)1 << (sizeof(size_t) * 8 - 4))
+
+#ifdef VPAES_ASM
+int vpaes_set_encrypt_key(const unsigned char *userKey, int bits,
+                          AES_KEY *key);
+int vpaes_set_decrypt_key(const unsigned char *userKey, int bits,
+                          AES_KEY *key);
+
+void vpaes_encrypt(const unsigned char *in, unsigned char *out,
+                   const AES_KEY *key);
+void vpaes_decrypt(const unsigned char *in, unsigned char *out,
+                   const AES_KEY *key);
+
+void vpaes_cbc_encrypt(const unsigned char *in,
+                       unsigned char *out,
+                       size_t length,
+                       const AES_KEY *key, unsigned char *ivec, int enc);
+#endif
+#ifdef BSAES_ASM
+void bsaes_cbc_encrypt(const unsigned char *in, unsigned char *out,
+                       size_t length, const AES_KEY *key,
+                       unsigned char ivec[16], int enc);
+void bsaes_ctr32_encrypt_blocks(const unsigned char *in, unsigned char *out,
+                                size_t len, const AES_KEY *key,
+                                const unsigned char ivec[16]);
+#endif
+#ifdef AES_CTR_ASM
+void AES_ctr32_encrypt(const unsigned char *in, unsigned char *out,
+                       size_t blocks, const AES_KEY *key,
+                       const unsigned char ivec[AES_BLOCK_SIZE]);
+#endif
+
+
+#if defined(OPENSSL_CPUID_OBJ) && (defined(__powerpc__) || defined(__ppc__) || defined(_ARCH_PPC))
+# include "ppc_arch.h"
+# ifdef VPAES_ASM
+#  define VPAES_CAPABLE (OPENSSL_ppccap_P & PPC_ALTIVEC)
+# endif
+# define HWAES_CAPABLE  (OPENSSL_ppccap_P & PPC_CRYPTO207)
+# define HWAES_set_encrypt_key aes_p8_set_encrypt_key
+# define HWAES_set_decrypt_key aes_p8_set_decrypt_key
+# define HWAES_encrypt aes_p8_encrypt
+# define HWAES_decrypt aes_p8_decrypt
+# define HWAES_cbc_encrypt aes_p8_cbc_encrypt
+# define HWAES_ctr32_encrypt_blocks aes_p8_ctr32_encrypt_blocks
+# define HWAES_xts_encrypt aes_p8_xts_encrypt
+# define HWAES_xts_decrypt aes_p8_xts_decrypt
+#endif
+
+#if     defined(AES_ASM) && !defined(I386_ONLY) &&      (  \
+        ((defined(__i386)       || defined(__i386__)    || \
+          defined(_M_IX86)) && defined(OPENSSL_IA32_SSE2))|| \
+        defined(__x86_64)       || defined(__x86_64__)  || \
+        defined(_M_AMD64)       || defined(_M_X64)      )
+
+extern unsigned int OPENSSL_ia32cap_P[];
+
+# ifdef VPAES_ASM
+#  define VPAES_CAPABLE   (OPENSSL_ia32cap_P[1]&(1<<(41-32)))
+# endif
+# ifdef BSAES_ASM
+#  define BSAES_CAPABLE   (OPENSSL_ia32cap_P[1]&(1<<(41-32)))
+# endif
+/*
+ * AES-NI section
+ */
+# define AESNI_CAPABLE   (OPENSSL_ia32cap_P[1]&(1<<(57-32)))
+
+int aesni_set_encrypt_key(const unsigned char *userKey, int bits,
+                          AES_KEY *key);
+int aesni_set_decrypt_key(const unsigned char *userKey, int bits,
+                          AES_KEY *key);
+
+void aesni_encrypt(const unsigned char *in, unsigned char *out,
+                   const AES_KEY *key);
+void aesni_decrypt(const unsigned char *in, unsigned char *out,
+                   const AES_KEY *key);
+
+void aesni_ecb_encrypt(const unsigned char *in,
+                       unsigned char *out,
+                       size_t length, const AES_KEY *key, int enc);
+void aesni_cbc_encrypt(const unsigned char *in,
+                       unsigned char *out,
+                       size_t length,
+                       const AES_KEY *key, unsigned char *ivec, int enc);
+
+void aesni_ctr32_encrypt_blocks(const unsigned char *in,
+                                unsigned char *out,
+                                size_t blocks,
+                                const void *key, const unsigned char *ivec);
+
+static int aesni_init_key(PROV_AES_KEY *dat, const unsigned char *key,
+                          size_t keylen)
+{
+    int ret;
+
+    if ((dat->mode == EVP_CIPH_ECB_MODE || dat->mode == EVP_CIPH_CBC_MODE)
+        && !dat->enc) {
+        ret = aesni_set_decrypt_key(key, keylen * 8, &dat->ks.ks);
+        dat->block = (block128_f) aesni_decrypt;
+        dat->stream.cbc = dat->mode == EVP_CIPH_CBC_MODE ?
+            (cbc128_f) aesni_cbc_encrypt : NULL;
+    } else {
+        ret = aesni_set_encrypt_key(key, keylen * 8, &dat->ks.ks);
+        dat->block = (block128_f) aesni_encrypt;
+        if (dat->mode == EVP_CIPH_CBC_MODE)
+            dat->stream.cbc = (cbc128_f) aesni_cbc_encrypt;
+        else if (dat->mode == EVP_CIPH_CTR_MODE)
+            dat->stream.ctr = (ctr128_f) aesni_ctr32_encrypt_blocks;
+        else
+            dat->stream.cbc = NULL;
+    }
+
+    if (ret < 0) {
+        PROVerr(PROV_F_AESNI_INIT_KEY, PROV_R_AES_KEY_SETUP_FAILED);
+        return 0;
+    }
+
+    return 1;
+}
+
+static int aesni_cbc_cipher(PROV_AES_KEY *ctx, unsigned char *out,
+                            const unsigned char *in, size_t len)
+{
+    aesni_cbc_encrypt(in, out, len, &ctx->ks.ks, ctx->iv, ctx->enc);
+
+    return 1;
+}
+
+static int aesni_ecb_cipher(PROV_AES_KEY *ctx, unsigned char *out,
+                            const unsigned char *in, size_t len)
+{
+    if (len < AES_BLOCK_SIZE)
+        return 1;
+
+    aesni_ecb_encrypt(in, out, len, &ctx->ks.ks, ctx->enc);
+
+    return 1;
+}
+
+# define aesni_ofb_cipher aes_ofb_cipher
+static int aesni_ofb_cipher(PROV_AES_KEY *ctx, unsigned char *out,
+                            const unsigned char *in, size_t len);
+
+# define aesni_cfb_cipher aes_cfb_cipher
+static int aesni_cfb_cipher(PROV_AES_KEY *ctx, unsigned char *out,
+                            const unsigned char *in, size_t len);
+
+# define aesni_cfb8_cipher aes_cfb8_cipher
+static int aesni_cfb8_cipher(PROV_AES_KEY *ctx, unsigned char *out,
+                             const unsigned char *in, size_t len);
+
+# define aesni_cfb1_cipher aes_cfb1_cipher
+static int aesni_cfb1_cipher(PROV_AES_KEY *ctx, unsigned char *out,
+                             const unsigned char *in, size_t len);
+
+# define aesni_ctr_cipher aes_ctr_cipher
+static int aesni_ctr_cipher(PROV_AES_KEY *ctx, unsigned char *out,
+                            const unsigned char *in, size_t len);
+
+# define BLOCK_CIPHER_generic_prov(mode) \
+static const PROV_AES_CIPHER aesni_##mode = { \
+        aesni_init_key,                 \
+        aesni_##mode##_cipher};         \
+static const PROV_AES_CIPHER aes_##mode = { \
+        aes_init_key,                   \
+        aes_##mode##_cipher}; \
+const PROV_AES_CIPHER *PROV_AES_CIPHER_##mode(size_t keylen) \
+{ return AESNI_CAPABLE?&aesni_##mode:&aes_##mode; }
+
+
+#elif   defined(AES_ASM) && (defined(__sparc) || defined(__sparc__))
+
+# include "sparc_arch.h"
+
+extern unsigned int OPENSSL_sparcv9cap_P[];
+
+/*
+ * Fujitsu SPARC64 X support
+ */
+# define HWAES_CAPABLE           (OPENSSL_sparcv9cap_P[0] & SPARCV9_FJAESX)
+# define HWAES_set_encrypt_key aes_fx_set_encrypt_key
+# define HWAES_set_decrypt_key aes_fx_set_decrypt_key
+# define HWAES_encrypt aes_fx_encrypt
+# define HWAES_decrypt aes_fx_decrypt
+# define HWAES_cbc_encrypt aes_fx_cbc_encrypt
+# define HWAES_ctr32_encrypt_blocks aes_fx_ctr32_encrypt_blocks
+
+# define SPARC_AES_CAPABLE       (OPENSSL_sparcv9cap_P[1] & CFR_AES)
+
+void aes_t4_set_encrypt_key(const unsigned char *key, int bits, AES_KEY *ks);
+void aes_t4_set_decrypt_key(const unsigned char *key, int bits, AES_KEY *ks);
+void aes_t4_encrypt(const unsigned char *in, unsigned char *out,
+                    const AES_KEY *key);
+void aes_t4_decrypt(const unsigned char *in, unsigned char *out,
+                    const AES_KEY *key);
+/*
+ * Key-length specific subroutines were chosen for following reason.
+ * Each SPARC T4 core can execute up to 8 threads which share core's
+ * resources. Loading as much key material to registers allows to
+ * minimize references to shared memory interface, as well as amount
+ * of instructions in inner loops [much needed on T4]. But then having
+ * non-key-length specific routines would require conditional branches
+ * either in inner loops or on subroutines' entries. Former is hardly
+ * acceptable, while latter means code size increase to size occupied
+ * by multiple key-length specific subroutines, so why fight?
+ */
+void aes128_t4_cbc_encrypt(const unsigned char *in, unsigned char *out,
+                           size_t len, const AES_KEY *key,
+                           unsigned char *ivec);
+void aes128_t4_cbc_decrypt(const unsigned char *in, unsigned char *out,
+                           size_t len, const AES_KEY *key,
+                           unsigned char *ivec);
+void aes192_t4_cbc_encrypt(const unsigned char *in, unsigned char *out,
+                           size_t len, const AES_KEY *key,
+                           unsigned char *ivec);
+void aes192_t4_cbc_decrypt(const unsigned char *in, unsigned char *out,
+                           size_t len, const AES_KEY *key,
+                           unsigned char *ivec);
+void aes256_t4_cbc_encrypt(const unsigned char *in, unsigned char *out,
+                           size_t len, const AES_KEY *key,
+                           unsigned char *ivec);
+void aes256_t4_cbc_decrypt(const unsigned char *in, unsigned char *out,
+                           size_t len, const AES_KEY *key,
+                           unsigned char *ivec);
+void aes128_t4_ctr32_encrypt(const unsigned char *in, unsigned char *out,
+                             size_t blocks, const AES_KEY *key,
+                             unsigned char *ivec);
+void aes192_t4_ctr32_encrypt(const unsigned char *in, unsigned char *out,
+                             size_t blocks, const AES_KEY *key,
+                             unsigned char *ivec);
+void aes256_t4_ctr32_encrypt(const unsigned char *in, unsigned char *out,
+                             size_t blocks, const AES_KEY *key,
+                             unsigned char *ivec);
+
+static int aes_t4_init_key(PROV_AES_KEY *dat, const unsigned char *key,
+                           size_t keylen)
+{
+    int ret, bits;
+
+    bits = keylen * 8;
+    if ((dat->mode == EVP_CIPH_ECB_MODE || dat->mode == EVP_CIPH_CBC_MODE)
+        && !dat->enc) {
+        ret = 0;
+        aes_t4_set_decrypt_key(key, bits, &dat->ks.ks);
+        dat->block = (block128_f) aes_t4_decrypt;
+        switch (bits) {
+        case 128:
+            dat->stream.cbc = dat->mode == EVP_CIPH_CBC_MODE ?
+                (cbc128_f) aes128_t4_cbc_decrypt : NULL;
+            break;
+        case 192:
+            dat->stream.cbc = dat->mode == EVP_CIPH_CBC_MODE ?
+                (cbc128_f) aes192_t4_cbc_decrypt : NULL;
+            break;
+        case 256:
+            dat->stream.cbc = dat->mode == EVP_CIPH_CBC_MODE ?
+                (cbc128_f) aes256_t4_cbc_decrypt : NULL;
+            break;
+        default:
+            ret = -1;
+        }
+    } else {
+        ret = 0;
+        aes_t4_set_encrypt_key(key, bits, &dat->ks.ks);
+        dat->block = (block128_f)aes_t4_encrypt;
+        switch (bits) {
+        case 128:
+            if (dat->mode == EVP_CIPH_CBC_MODE)
+                dat->stream.cbc = (cbc128_f)aes128_t4_cbc_encrypt;
+            else if (dat->mode == EVP_CIPH_CTR_MODE)
+                dat->stream.ctr = (ctr128_f)aes128_t4_ctr32_encrypt;
+            else
+                dat->stream.cbc = NULL;
+            break;
+        case 192:
+            if (dat->mode == EVP_CIPH_CBC_MODE)
+                dat->stream.cbc = (cbc128_f)aes192_t4_cbc_encrypt;
+            else if (dat->mode == EVP_CIPH_CTR_MODE)
+                dat->stream.ctr = (ctr128_f)aes192_t4_ctr32_encrypt;
+            else
+                dat->stream.cbc = NULL;
+            break;
+        case 256:
+            if (dat->mode == EVP_CIPH_CBC_MODE)
+                dat->stream.cbc = (cbc128_f)aes256_t4_cbc_encrypt;
+            else if (dat->mode == EVP_CIPH_CTR_MODE)
+                dat->stream.ctr = (ctr128_f)aes256_t4_ctr32_encrypt;
+            else
+                dat->stream.cbc = NULL;
+            break;
+        default:
+            ret = -1;
+        }
+    }
+
+    if (ret < 0) {
+        PROVerr(PROV_F_AES_T4_INIT_KEY, PROV_R_AES_KEY_SETUP_FAILED);
+        return 0;
+    }
+
+    return 1;
+}
+
+# define aes_t4_cbc_cipher aes_cbc_cipher
+static int aes_t4_cbc_cipher(PROV_AES_KEY *ctx, unsigned char *out,
+                             const unsigned char *in, size_t len);
+
+# define aes_t4_ecb_cipher aes_ecb_cipher
+static int aes_t4_ecb_cipher(PROV_AES_KEY *ctx, unsigned char *out,
+                             const unsigned char *in, size_t len);
+
+# define aes_t4_ofb_cipher aes_ofb_cipher
+static int aes_t4_ofb_cipher(PROV_AES_KEY *ctx, unsigned char *out,
+                             const unsigned char *in, size_t len);
+
+# define aes_t4_cfb_cipher aes_cfb_cipher
+static int aes_t4_cfb_cipher(PROV_AES_KEY *ctx, unsigned char *out,
+                             const unsigned char *in, size_t len);
+
+# define aes_t4_cfb8_cipher aes_cfb8_cipher
+static int aes_t4_cfb8_cipher(PROV_AES_KEY *ctx, unsigned char *out,
+                              const unsigned char *in, size_t len);
+
+# define aes_t4_cfb1_cipher aes_cfb1_cipher
+static int aes_t4_cfb1_cipher(PROV_AES_KEY *ctx, unsigned char *out,
+                              const unsigned char *in, size_t len);
+
+# define aes_t4_ctr_cipher aes_ctr_cipher
+static int aes_t4_ctr_cipher(PROV_AES_KEY *ctx, unsigned char *out,
+                             const unsigned char *in, size_t len);
+
+# define BLOCK_CIPHER_generic_prov(mode) \
+static const PROV_AES_CIPHER aes_t4_##mode = { \
+        aes_t4_init_key,                 \
+        aes_t4_##mode##_cipher};         \
+static const PROV_AES_CIPHER aes_##mode = { \
+        aes_init_key,                   \
+        aes_##mode##_cipher}; \
+const PROV_AES_CIPHER *PROV_AES_CIPHER_##mode(size_t keylen) \
+{ return SPARC_AES_CAPABLE?&aes_t4_##mode:&aes_##mode; }
+
+
+#elif defined(OPENSSL_CPUID_OBJ) && defined(__s390__)
+/*
+ * IBM S390X support
+ */
+# include "s390x_arch.h"
+
+/* Convert key size to function code: [16,24,32] -> [18,19,20]. */
+# define S390X_AES_FC(keylen)  (S390X_AES_128 + ((((keylen) << 3) - 128) >> 6))
+
+/* Most modes of operation need km for partial block processing. */
+# define S390X_aes_128_CAPABLE (OPENSSL_s390xcap_P.km[0] &	\
+                                S390X_CAPBIT(S390X_AES_128))
+# define S390X_aes_192_CAPABLE (OPENSSL_s390xcap_P.km[0] &	\
+                                S390X_CAPBIT(S390X_AES_192))
+# define S390X_aes_256_CAPABLE (OPENSSL_s390xcap_P.km[0] &	\
+                                S390X_CAPBIT(S390X_AES_256))
+
+# define s390x_aes_init_key aes_init_key
+static int s390x_aes_init_key(PROV_AES_KEY *dat, const unsigned char *key,
+                              size_t keylen);
+
+# define S390X_aes_128_cbc_CAPABLE  1	/* checked by callee */
+# define S390X_aes_192_cbc_CAPABLE  1
+# define S390X_aes_256_cbc_CAPABLE  1
+# define S390X_AES_CBC_CTX          PROV_AES_KEY
+
+# define s390x_aes_cbc_init_key aes_init_key
+
+# define s390x_aes_cbc_cipher aes_cbc_cipher
+static int s390x_aes_cbc_cipher(PROV_AES_KEY *dat, unsigned char *out,
+                                const unsigned char *in, size_t len);
+
+# define S390X_aes_128_ecb_CAPABLE  S390X_aes_128_CAPABLE
+# define S390X_aes_192_ecb_CAPABLE  S390X_aes_192_CAPABLE
+# define S390X_aes_256_ecb_CAPABLE  S390X_aes_256_CAPABLE
+
+static int s390x_aes_ecb_init_key(PROV_AES_KEY *dat, const unsigned char *key,
+                                  size_t keylen)
+{
+    dat->plat.s390x.fc = S390X_AES_FC(keylen);
+    if (!dat->enc)
+        dat->plat.s390x.fc |= S390X_DECRYPT;
+
+    memcpy(dat->plat.s390x.param.km.k, key, keylen);
+    return 1;
+}
+
+static int s390x_aes_ecb_cipher(PROV_AES_KEY *dat, unsigned char *out,
+                                const unsigned char *in, size_t len)
+{
+    s390x_km(in, len, out, dat->plat.s390x.fc,
+             &dat->plat.s390x.param.km);
+    return 1;
+}
+
+# define S390X_aes_128_ofb_CAPABLE (S390X_aes_128_CAPABLE &&        \
+                                    (OPENSSL_s390xcap_P.kmo[0] &    \
+                                     S390X_CAPBIT(S390X_AES_128)))
+# define S390X_aes_192_ofb_CAPABLE (S390X_aes_192_CAPABLE &&        \
+                                    (OPENSSL_s390xcap_P.kmo[0] &    \
+                                     S390X_CAPBIT(S390X_AES_192)))
+# define S390X_aes_256_ofb_CAPABLE (S390X_aes_256_CAPABLE &&        \
+                                    (OPENSSL_s390xcap_P.kmo[0] &    \
+                                     S390X_CAPBIT(S390X_AES_256)))
+
+static int s390x_aes_ofb_init_key(PROV_AES_KEY *dat, const unsigned char *key,
+                                  size_t keylen)
+{
+    memcpy(dat->plat.s390x.param.kmo_kmf.cv, dat->iv, AES_BLOCK_SIZE);
+    memcpy(dat->plat.s390x.param.kmo_kmf.k, key, keylen);
+    dat->plat.s390x.fc = S390X_AES_FC(keylen);
+    dat->plat.s390x.res = 0;
+    return 1;
+}
+
+static int s390x_aes_ofb_cipher(PROV_AES_KEY *dat, unsigned char *out,
+                                const unsigned char *in, size_t len)
+{
+    int n = dat->plat.s390x.res;
+    int rem;
+
+    while (n && len) {
+        *out = *in ^ dat->plat.s390x.param.kmo_kmf.cv[n];
+        n = (n + 1) & 0xf;
+        --len;
+        ++in;
+        ++out;
+    }
+
+    rem = len & 0xf;
+
+    len &= ~(size_t)0xf;
+    if (len) {
+        s390x_kmo(in, len, out, dat->plat.s390x.fc,
+                  &dat->plat.s390x.param.kmo_kmf);
+
+        out += len;
+        in += len;
+    }
+
+    if (rem) {
+        s390x_km(dat->plat.s390x.param.kmo_kmf.cv, 16,
+                 dat->plat.s390x.param.kmo_kmf.cv, dat->plat.s390x.fc,
+                 dat->plat.s390x.param.kmo_kmf.k);
+
+        while (rem--) {
+            out[n] = in[n] ^ dat->plat.s390x.param.kmo_kmf.cv[n];
+            ++n;
+        }
+    }
+
+    dat->plat.s390x.res = n;
+    return 1;
+}
+
+# define S390X_aes_128_cfb_CAPABLE (S390X_aes_128_CAPABLE &&        \
+                                    (OPENSSL_s390xcap_P.kmf[0] &    \
+                                     S390X_CAPBIT(S390X_AES_128)))
+# define S390X_aes_192_cfb_CAPABLE (S390X_aes_192_CAPABLE &&        \
+                                    (OPENSSL_s390xcap_P.kmf[0] &    \
+                                     S390X_CAPBIT(S390X_AES_192)))
+# define S390X_aes_256_cfb_CAPABLE (S390X_aes_256_CAPABLE &&        \
+                                    (OPENSSL_s390xcap_P.kmf[0] &    \
+                                     S390X_CAPBIT(S390X_AES_256)))
+
+static int s390x_aes_cfb_init_key(PROV_AES_KEY *dat, const unsigned char *key,
+                                  size_t keylen)
+{
+    dat->plat.s390x.fc = S390X_AES_FC(keylen);
+    dat->plat.s390x.fc |= 16 << 24;   /* 16 bytes cipher feedback */
+    if (!dat->enc)
+        dat->plat.s390x.fc |= S390X_DECRYPT;
+
+    dat->plat.s390x.res = 0;
+    memcpy(dat->plat.s390x.param.kmo_kmf.cv, dat->iv, AES_BLOCK_SIZE);
+    memcpy(dat->plat.s390x.param.kmo_kmf.k, key, keylen);
+    return 1;
+}
+
+static int s390x_aes_cfb_cipher(PROV_AES_KEY *dat, unsigned char *out,
+                                const unsigned char *in, size_t len)
+{
+    int n = dat->plat.s390x.res;
+    int rem;
+    unsigned char tmp;
+
+    while (n && len) {
+        tmp = *in;
+        *out = dat->plat.s390x.param.kmo_kmf.cv[n] ^ tmp;
+        dat->plat.s390x.param.kmo_kmf.cv[n] = dat->enc ? *out : tmp;
+        n = (n + 1) & 0xf;
+        --len;
+        ++in;
+        ++out;
+    }
+
+    rem = len & 0xf;
+
+    len &= ~(size_t)0xf;
+    if (len) {
+        s390x_kmf(in, len, out, dat->plat.s390x.fc,
+                  &dat->plat.s390x.param.kmo_kmf);
+
+        out += len;
+        in += len;
+    }
+
+    if (rem) {
+        s390x_km(dat->plat.s390x.param.kmo_kmf.cv, 16,
+                 dat->plat.s390x.param.kmo_kmf.cv,
+                 S390X_AES_FC(dat->keylen), dat->plat.s390x.param.kmo_kmf.k);
+
+        while (rem--) {
+            tmp = in[n];
+            out[n] = dat->plat.s390x.param.kmo_kmf.cv[n] ^ tmp;
+            dat->plat.s390x.param.kmo_kmf.cv[n] = dat->enc ? out[n] : tmp;
+            ++n;
+        }
+    }
+
+    dat->plat.s390x.res = n;
+    return 1;
+}
+
+# define S390X_aes_128_cfb8_CAPABLE (OPENSSL_s390xcap_P.kmf[0] &    \
+                                     S390X_CAPBIT(S390X_AES_128))
+# define S390X_aes_192_cfb8_CAPABLE (OPENSSL_s390xcap_P.kmf[0] &    \
+                                     S390X_CAPBIT(S390X_AES_192))
+# define S390X_aes_256_cfb8_CAPABLE (OPENSSL_s390xcap_P.kmf[0] &    \
+                                     S390X_CAPBIT(S390X_AES_256))
+
+static int s390x_aes_cfb8_init_key(PROV_AES_KEY *dat, const unsigned char *key,
+                                  size_t keylen)
+{
+    dat->plat.s390x.fc = S390X_AES_FC(keylen);
+    dat->plat.s390x.fc |= 1 << 24;   /* 1 byte cipher feedback */
+    if (!dat->enc)
+        dat->plat.s390x.fc |= S390X_DECRYPT;
+
+    memcpy(dat->plat.s390x.param.kmo_kmf.cv, dat->iv, AES_BLOCK_SIZE);
+    memcpy(dat->plat.s390x.param.kmo_kmf.k, key, keylen);
+    return 1;
+}
+
+static int s390x_aes_cfb8_cipher(PROV_AES_KEY *dat, unsigned char *out,
+                                 const unsigned char *in, size_t len)
+{
+    s390x_kmf(in, len, out, dat->plat.s390x.fc,
+              &dat->plat.s390x.param.kmo_kmf);
+    return 1;
+}
+
+# define S390X_aes_128_cfb1_CAPABLE 0
+# define S390X_aes_192_cfb1_CAPABLE 0
+# define S390X_aes_256_cfb1_CAPABLE 0
+
+# define s390x_aes_cfb1_init_key aes_init_key
+
+# define s390x_aes_cfb1_cipher aes_cfb1_cipher
+static int s390x_aes_cfb1_cipher(PROV_AES_KEY *dat, unsigned char *out,
+                                 const unsigned char *in, size_t len);
+
+# define S390X_aes_128_ctr_CAPABLE  1	/* checked by callee */
+# define S390X_aes_192_ctr_CAPABLE  1
+# define S390X_aes_256_ctr_CAPABLE  1
+# define S390X_AES_CTR_CTX          PROV_AES_KEY
+
+# define s390x_aes_ctr_init_key aes_init_key
+
+# define s390x_aes_ctr_cipher aes_ctr_cipher
+static int s390x_aes_ctr_cipher(PROV_AES_KEY *dat, unsigned char *out,
+                                const unsigned char *in, size_t len);
+
+# define BLOCK_CIPHER_generic_prov(mode) \
+static const PROV_AES_CIPHER s390x_aes_##mode = { \
+        s390x_aes_##mode##_init_key,    \
+        s390x_aes_##mode##_cipher       \
+};  \
+static const PROV_AES_CIPHER aes_##mode = { \
+        aes_init_key,           \
+        aes_##mode##_cipher     \
+}; \
+const PROV_AES_CIPHER *PROV_AES_CIPHER_##mode(size_t keylen) \
+{   \
+    if ((keylen == 128 && S390X_aes_128_##mode##_CAPABLE)           \
+            || (keylen == 192 && S390X_aes_192_##mode##_CAPABLE)    \
+            || (keylen == 256 && S390X_aes_256_##mode##_CAPABLE))   \
+        return &s390x_aes_##mode;   \
+    \
+    return &aes_##mode; \
+}
+
+#else
+
+# define BLOCK_CIPHER_generic_prov(mode) \
+static const PROV_AES_CIPHER aes_##mode = { \
+        aes_init_key,                   \
+        aes_##mode##_cipher}; \
+const PROV_AES_CIPHER *PROV_AES_CIPHER_##mode(size_t keylen) \
+{ return &aes_##mode; }
+
+#endif
+
+#if defined(OPENSSL_CPUID_OBJ) && (defined(__arm__) || defined(__arm) || defined(__aarch64__))
+# include "arm_arch.h"
+# if __ARM_MAX_ARCH__>=7
+#  if defined(BSAES_ASM)
+#   define BSAES_CAPABLE (OPENSSL_armcap_P & ARMV7_NEON)
+#  endif
+#  if defined(VPAES_ASM)
+#   define VPAES_CAPABLE (OPENSSL_armcap_P & ARMV7_NEON)
+#  endif
+#  define HWAES_CAPABLE (OPENSSL_armcap_P & ARMV8_AES)
+#  define HWAES_set_encrypt_key aes_v8_set_encrypt_key
+#  define HWAES_set_decrypt_key aes_v8_set_decrypt_key
+#  define HWAES_encrypt aes_v8_encrypt
+#  define HWAES_decrypt aes_v8_decrypt
+#  define HWAES_cbc_encrypt aes_v8_cbc_encrypt
+#  define HWAES_ctr32_encrypt_blocks aes_v8_ctr32_encrypt_blocks
+# endif
+#endif
+
+#if defined(HWAES_CAPABLE)
+int HWAES_set_encrypt_key(const unsigned char *userKey, const int bits,
+                          AES_KEY *key);
+int HWAES_set_decrypt_key(const unsigned char *userKey, const int bits,
+                          AES_KEY *key);
+void HWAES_encrypt(const unsigned char *in, unsigned char *out,
+                   const AES_KEY *key);
+void HWAES_decrypt(const unsigned char *in, unsigned char *out,
+                   const AES_KEY *key);
+void HWAES_cbc_encrypt(const unsigned char *in, unsigned char *out,
+                       size_t length, const AES_KEY *key,
+                       unsigned char *ivec, const int enc);
+void HWAES_ctr32_encrypt_blocks(const unsigned char *in, unsigned char *out,
+                                size_t len, const AES_KEY *key,
+                                const unsigned char ivec[16]);
+#endif
+
+static int aes_init_key(PROV_AES_KEY *dat, const unsigned char *key,
+                        size_t keylen)
+{
+    int ret;
+
+    if ((dat->mode == EVP_CIPH_ECB_MODE || dat->mode == EVP_CIPH_CBC_MODE)
+        && !dat->enc) {
+#ifdef HWAES_CAPABLE
+        if (HWAES_CAPABLE) {
+            ret = HWAES_set_decrypt_key(key, keylen * 8, &dat->ks.ks);
+            dat->block = (block128_f)HWAES_decrypt;
+            dat->stream.cbc = NULL;
+# ifdef HWAES_cbc_encrypt
+            if (dat->mode == EVP_CIPH_CBC_MODE)
+                dat->stream.cbc = (cbc128_f)HWAES_cbc_encrypt;
+# endif
+        } else
+#endif
+#ifdef BSAES_CAPABLE
+        if (BSAES_CAPABLE && dat->mode == EVP_CIPH_CBC_MODE) {
+            ret = AES_set_decrypt_key(key, keylen * 8, &dat->ks.ks);
+            dat->block = (block128_f)AES_decrypt;
+            dat->stream.cbc = (cbc128_f)bsaes_cbc_encrypt;
+        } else
+#endif
+#ifdef VPAES_CAPABLE
+        if (VPAES_CAPABLE) {
+            ret = vpaes_set_decrypt_key(key, keylen * 8, &dat->ks.ks);
+            dat->block = (block128_f)vpaes_decrypt;
+            dat->stream.cbc = (dat->mode == EVP_CIPH_CBC_MODE)
+                              ?(cbc128_f)vpaes_cbc_encrypt : NULL;
+        } else
+#endif
+        {
+            ret = AES_set_decrypt_key(key, keylen * 8, &dat->ks.ks);
+            dat->block = (block128_f)AES_decrypt;
+            dat->stream.cbc = (dat->mode == EVP_CIPH_CBC_MODE)
+                              ? (cbc128_f)AES_cbc_encrypt : NULL;
+        }
+    } else
+#ifdef HWAES_CAPABLE
+    if (HWAES_CAPABLE) {
+        ret = HWAES_set_encrypt_key(key, keylen * 8, &dat->ks.ks);
+        dat->block = (block128_f)HWAES_encrypt;
+        dat->stream.cbc = NULL;
+# ifdef HWAES_cbc_encrypt
+        if (dat->mode == EVP_CIPH_CBC_MODE)
+            dat->stream.cbc = (cbc128_f)HWAES_cbc_encrypt;
+        else
+# endif
+# ifdef HWAES_ctr32_encrypt_blocks
+        if (dat->mode == EVP_CIPH_CTR_MODE)
+            dat->stream.ctr = (ctr128_f)HWAES_ctr32_encrypt_blocks;
+        else
+# endif
+            (void)0;            /* terminate potentially open 'else' */
+    } else
+#endif
+#ifdef BSAES_CAPABLE
+    if (BSAES_CAPABLE && dat->mode == EVP_CIPH_CTR_MODE) {
+        ret = AES_set_encrypt_key(key, keylen * 8, &dat->ks.ks);
+        dat->block = (block128_f)AES_encrypt;
+        dat->stream.ctr = (ctr128_f)bsaes_ctr32_encrypt_blocks;
+    } else
+#endif
+#ifdef VPAES_CAPABLE
+    if (VPAES_CAPABLE) {
+        ret = vpaes_set_encrypt_key(key, keylen * 8, &dat->ks.ks);
+        dat->block = (block128_f)vpaes_encrypt;
+        dat->stream.cbc = (dat->mode == EVP_CIPH_CBC_MODE)
+                          ? (cbc128_f)vpaes_cbc_encrypt : NULL;
+    } else
+#endif
+    {
+        ret = AES_set_encrypt_key(key, keylen * 8, &dat->ks.ks);
+        dat->block = (block128_f)AES_encrypt;
+        dat->stream.cbc = (dat->mode == EVP_CIPH_CBC_MODE)
+                          ? (cbc128_f)AES_cbc_encrypt : NULL;
+#ifdef AES_CTR_ASM
+        if (dat->mode == EVP_CIPH_CTR_MODE)
+            dat->stream.ctr = (ctr128_f)AES_ctr32_encrypt;
+#endif
+    }
+
+    if (ret < 0) {
+        PROVerr(PROV_F_AES_INIT_KEY, PROV_R_AES_KEY_SETUP_FAILED);
+        return 0;
+    }
+
+    return 1;
+}
+
+static int aes_cbc_cipher(PROV_AES_KEY *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;
+}
+
+static int aes_ecb_cipher(PROV_AES_KEY *dat, unsigned char *out,
+                          const unsigned char *in, size_t len)
+{
+    size_t i;
+
+    if (len < AES_BLOCK_SIZE)
+        return 1;
+
+    for (i = 0, len -= AES_BLOCK_SIZE; i <= len; i += AES_BLOCK_SIZE)
+        (*dat->block) (in + i, out + i, &dat->ks);
+
+    return 1;
+}
+
+static int aes_ofb_cipher(PROV_AES_KEY *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;
+}
+
+static int aes_cfb_cipher(PROV_AES_KEY *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;
+}
+
+static int aes_cfb8_cipher(PROV_AES_KEY *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;
+}
+
+static int aes_cfb1_cipher(PROV_AES_KEY *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;
+}
+
+static int aes_ctr_cipher(PROV_AES_KEY *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;
+}
+
+BLOCK_CIPHER_generic_prov(cbc)
+BLOCK_CIPHER_generic_prov(ecb)
+BLOCK_CIPHER_generic_prov(ofb)
+BLOCK_CIPHER_generic_prov(cfb)
+BLOCK_CIPHER_generic_prov(cfb1)
+BLOCK_CIPHER_generic_prov(cfb8)
+BLOCK_CIPHER_generic_prov(ctr)
+
diff --git a/providers/common/ciphers/block.c b/providers/common/ciphers/block.c
new file mode 100644
index 0000000..03aa429
--- /dev/null
+++ b/providers/common/ciphers/block.c
@@ -0,0 +1,118 @@
+/*
+ * 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 <string.h>
+#include <openssl/evp.h>
+#include <openssl/err.h>
+#include "ciphers_locl.h"
+#include <assert.h>
+#include "internal/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) {
+        PROVerr(PROV_F_TRAILINGDATA, 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) {
+        PROVerr(PROV_F_UNPADBLOCK, 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) {
+        PROVerr(PROV_F_UNPADBLOCK, PROV_R_BAD_DECRYPT);
+        return 0;
+    }
+    for (i = 0; i < pad; i++) {
+        if (buf[--len] != pad) {
+            PROVerr(PROV_F_UNPADBLOCK, PROV_R_BAD_DECRYPT);
+            return 0;
+        }
+    }
+    *buflen = len;
+    return 1;
+}
diff --git a/providers/common/ciphers/build.info b/providers/common/ciphers/build.info
new file mode 100644
index 0000000..f4ff2ce
--- /dev/null
+++ b/providers/common/ciphers/build.info
@@ -0,0 +1,4 @@
+LIBS=../../../libcrypto
+SOURCE[../../../libcrypto]=\
+        block.c aes.c aes_basic.c
+INCLUDE[../../../libcrypto]=. ../../../crypto
diff --git a/providers/common/ciphers/ciphers_locl.h b/providers/common/ciphers/ciphers_locl.h
new file mode 100644
index 0000000..a874bbf
--- /dev/null
+++ b/providers/common/ciphers/ciphers_locl.h
@@ -0,0 +1,107 @@
+/*
+ * 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 <openssl/modes.h>
+
+typedef struct prov_aes_cipher_st PROV_AES_CIPHER;
+
+typedef struct prov_aes_key_st {
+    union {
+        double align;
+        AES_KEY ks;
+    } ks;
+    block128_f block;
+    union {
+        cbc128_f cbc;
+        ctr128_f ctr;
+    } stream;
+
+    /* Platform specific data */
+    union {
+        int dummy;
+#if defined(OPENSSL_CPUID_OBJ) && defined(__s390__)
+        struct {
+            union {
+                double align;
+                /*-
+                 * KM-AES parameter block - begin
+                 * (see z/Architecture Principles of Operation >= SA22-7832-06)
+                 */
+                struct {
+                    unsigned char k[32];
+                } km;
+                /* KM-AES parameter block - end */
+                /*-
+                 * KMO-AES/KMF-AES parameter block - begin
+                 * (see z/Architecture Principles of Operation >= SA22-7832-08)
+                 */
+                struct {
+                    unsigned char cv[16];
+                    unsigned char k[32];
+                } kmo_kmf;
+                /* KMO-AES/KMF-AES parameter block - end */
+            } param;
+            unsigned int fc;
+            int res;
+        } s390x;
+#endif /* defined(OPENSSL_CPUID_OBJ) && defined(__s390__) */
+    } plat;
+
+    /* The cipher functions we are going to use */
+    const PROV_AES_CIPHER *ciph;
+
+    /* The mode that we are using */
+    int mode;
+
+    /* Set to 1 if we are encrypting or 0 otherwise */
+    int enc;
+
+    unsigned char iv[AES_BLOCK_SIZE];
+
+    /*
+     * num contains the number of bytes of |iv| which are valid for modes that
+     * manage partial blocks themselves.
+     */
+    size_t num;
+
+    /* Buffer of partial blocks processed via update calls */
+    unsigned char buf[AES_BLOCK_SIZE];
+
+    /* Number of bytes in buf */
+    size_t bufsz;
+
+    uint64_t flags;
+
+    size_t keylen;
+
+    /* Whether padding should be used or not */
+    unsigned int pad : 1;
+} PROV_AES_KEY;
+
+struct prov_aes_cipher_st {
+  int (*init)(PROV_AES_KEY *dat, const uint8_t *key, size_t keylen);
+  int (*cipher)(PROV_AES_KEY *dat, uint8_t *out, const uint8_t *in,
+                size_t inl);
+};
+
+const PROV_AES_CIPHER *PROV_AES_CIPHER_ecb(size_t keylen);
+const PROV_AES_CIPHER *PROV_AES_CIPHER_cbc(size_t keylen);
+const PROV_AES_CIPHER *PROV_AES_CIPHER_ofb(size_t keylen);
+const PROV_AES_CIPHER *PROV_AES_CIPHER_cfb(size_t keylen);
+const PROV_AES_CIPHER *PROV_AES_CIPHER_cfb1(size_t keylen);
+const PROV_AES_CIPHER *PROV_AES_CIPHER_cfb8(size_t keylen);
+const PROV_AES_CIPHER *PROV_AES_CIPHER_ctr(size_t keylen);
+
+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);
+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/sha2.c b/providers/common/digests/sha2.c
index 3698046..c9f616d 100644
--- a/providers/common/digests/sha2.c
+++ b/providers/common/digests/sha2.c
@@ -10,6 +10,7 @@
 #include <openssl/sha.h>
 #include <openssl/crypto.h>
 #include <openssl/core_numbers.h>
+#include "internal/provider_algs.h"
 
 /*
  * Forward declaration of everything implemented here.  This is not strictly
@@ -73,11 +74,10 @@ static size_t sha256_block_size(void)
     return SHA256_CBLOCK;
 }
 
-extern const OSSL_DISPATCH sha256_functions[];
 const OSSL_DISPATCH sha256_functions[] = {
     { OSSL_FUNC_DIGEST_NEWCTX, (void (*)(void))sha256_newctx },
     { OSSL_FUNC_DIGEST_INIT, (void (*)(void))SHA256_Init },
-    { OSSL_FUNC_DIGEST_UPDDATE, (void (*)(void))SHA256_Update },
+    { OSSL_FUNC_DIGEST_UPDATE, (void (*)(void))SHA256_Update },
     { OSSL_FUNC_DIGEST_FINAL, (void (*)(void))sha256_final },
     { OSSL_FUNC_DIGEST_FREECTX, (void (*)(void))sha256_freectx },
     { OSSL_FUNC_DIGEST_DUPCTX, (void (*)(void))sha256_dupctx },
diff --git a/providers/common/include/internal/provider_algs.h b/providers/common/include/internal/provider_algs.h
new file mode 100644
index 0000000..dd9211b
--- /dev/null
+++ b/providers/common/include/internal/provider_algs.h
@@ -0,0 +1,34 @@
+/*
+ * 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
+ */
+
+/* Digests */
+extern const OSSL_DISPATCH sha256_functions[];
+
+/* Ciphers */
+extern const OSSL_DISPATCH aes256ecb_functions[];
+extern const OSSL_DISPATCH aes192ecb_functions[];
+extern const OSSL_DISPATCH aes128ecb_functions[];
+extern const OSSL_DISPATCH aes256cbc_functions[];
+extern const OSSL_DISPATCH aes192cbc_functions[];
+extern const OSSL_DISPATCH aes128cbc_functions[];
+extern const OSSL_DISPATCH aes256ofb_functions[];
+extern const OSSL_DISPATCH aes192ofb_functions[];
+extern const OSSL_DISPATCH aes128ofb_functions[];
+extern const OSSL_DISPATCH aes256cfb_functions[];
+extern const OSSL_DISPATCH aes192cfb_functions[];
+extern const OSSL_DISPATCH aes128cfb_functions[];
+extern const OSSL_DISPATCH aes256cfb1_functions[];
+extern const OSSL_DISPATCH aes192cfb1_functions[];
+extern const OSSL_DISPATCH aes128cfb1_functions[];
+extern const OSSL_DISPATCH aes256cfb8_functions[];
+extern const OSSL_DISPATCH aes192cfb8_functions[];
+extern const OSSL_DISPATCH aes128cfb8_functions[];
+extern const OSSL_DISPATCH aes256ctr_functions[];
+extern const OSSL_DISPATCH aes192ctr_functions[];
+extern const OSSL_DISPATCH aes128ctr_functions[];
diff --git a/fuzz/corpora/ct/e53301b7bba90f14da5195be2e47ec3f88924694 b/providers/common/include/internal/providercommon.h
similarity index 100%
copy from fuzz/corpora/ct/e53301b7bba90f14da5195be2e47ec3f88924694
copy to providers/common/include/internal/providercommon.h
diff --git a/providers/common/include/internal/providercommonerr.h b/providers/common/include/internal/providercommonerr.h
new file mode 100644
index 0000000..609fd5b
--- /dev/null
+++ b/providers/common/include/internal/providercommonerr.h
@@ -0,0 +1,54 @@
+/*
+ * Generated by util/mkerr.pl DO NOT EDIT
+ * Copyright 1995-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 HEADER_PROVERR_H
+# define HEADER_PROVERR_H
+
+# ifndef HEADER_SYMHACKS_H
+#  include <openssl/symhacks.h>
+# endif
+
+# ifdef  __cplusplus
+extern "C"
+# endif
+int ERR_load_PROV_strings(void);
+
+/*
+ * PROV function codes.
+ */
+# define PROV_F_AESNI_INIT_KEY                            101
+# define PROV_F_AES_BLOCK_FINAL                           102
+# define PROV_F_AES_BLOCK_UPDATE                          103
+# define PROV_F_AES_CIPHER                                104
+# define PROV_F_AES_CTX_GET_PARAMS                        105
+# define PROV_F_AES_CTX_SET_PARAMS                        106
+# define PROV_F_AES_DINIT                                 107
+# define PROV_F_AES_DUPCTX                                108
+# define PROV_F_AES_EINIT                                 109
+# define PROV_F_AES_INIT_KEY                              110
+# define PROV_F_AES_STREAM_UPDATE                         111
+# define PROV_F_AES_T4_INIT_KEY                           112
+# define PROV_F_PROV_AES_KEY_GENERIC_INIT                 113
+# define PROV_F_TRAILINGDATA                              114
+# define PROV_F_UNPADBLOCK                                100
+
+/*
+ * PROV reason codes.
+ */
+# define PROV_R_AES_KEY_SETUP_FAILED                      101
+# define PROV_R_BAD_DECRYPT                               100
+# define PROV_R_CIPHER_OPERATION_FAILED                   102
+# define PROV_R_FAILED_TO_GET_PARAMETER                   103
+# define PROV_R_FAILED_TO_SET_PARAMETER                   104
+# define PROV_R_INVALID_KEYLEN                            105
+# define PROV_R_OUTPUT_BUFFER_TOO_SMALL                   106
+# define PROV_R_WRONG_FINAL_BLOCK_LENGTH                  107
+
+#endif
diff --git a/providers/common/provider_err.c b/providers/common/provider_err.c
new file mode 100644
index 0000000..e6b577f
--- /dev/null
+++ b/providers/common/provider_err.c
@@ -0,0 +1,67 @@
+/*
+ * Generated by util/mkerr.pl DO NOT EDIT
+ * Copyright 1995-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 "internal/providercommonerr.h"
+
+#ifndef OPENSSL_NO_ERR
+
+static const ERR_STRING_DATA PROV_str_functs[] = {
+    {ERR_PACK(ERR_LIB_PROV, PROV_F_AESNI_INIT_KEY, 0), "aesni_init_key"},
+    {ERR_PACK(ERR_LIB_PROV, PROV_F_AES_BLOCK_FINAL, 0), "aes_block_final"},
+    {ERR_PACK(ERR_LIB_PROV, PROV_F_AES_BLOCK_UPDATE, 0), "aes_block_update"},
+    {ERR_PACK(ERR_LIB_PROV, PROV_F_AES_CIPHER, 0), "aes_cipher"},
+    {ERR_PACK(ERR_LIB_PROV, PROV_F_AES_CTX_GET_PARAMS, 0),
+     "aes_ctx_get_params"},
+    {ERR_PACK(ERR_LIB_PROV, PROV_F_AES_CTX_SET_PARAMS, 0),
+     "aes_ctx_set_params"},
+    {ERR_PACK(ERR_LIB_PROV, PROV_F_AES_DINIT, 0), "aes_dinit"},
+    {ERR_PACK(ERR_LIB_PROV, PROV_F_AES_DUPCTX, 0), "aes_dupctx"},
+    {ERR_PACK(ERR_LIB_PROV, PROV_F_AES_EINIT, 0), "aes_einit"},
+    {ERR_PACK(ERR_LIB_PROV, PROV_F_AES_INIT_KEY, 0), "aes_init_key"},
+    {ERR_PACK(ERR_LIB_PROV, PROV_F_AES_STREAM_UPDATE, 0), "aes_stream_update"},
+    {ERR_PACK(ERR_LIB_PROV, PROV_F_AES_T4_INIT_KEY, 0), "aes_t4_init_key"},
+    {ERR_PACK(ERR_LIB_PROV, PROV_F_PROV_AES_KEY_GENERIC_INIT, 0),
+     "PROV_AES_KEY_generic_init"},
+    {ERR_PACK(ERR_LIB_PROV, PROV_F_TRAILINGDATA, 0), "trailingdata"},
+    {ERR_PACK(ERR_LIB_PROV, PROV_F_UNPADBLOCK, 0), "unpadblock"},
+    {0, NULL}
+};
+
+static const ERR_STRING_DATA PROV_str_reasons[] = {
+    {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_AES_KEY_SETUP_FAILED),
+    "aes key setup failed"},
+    {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_BAD_DECRYPT), "bad decrypt"},
+    {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_CIPHER_OPERATION_FAILED),
+    "cipher operation failed"},
+    {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_FAILED_TO_GET_PARAMETER),
+    "failed to get parameter"},
+    {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_FAILED_TO_SET_PARAMETER),
+    "failed to set parameter"},
+    {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_KEYLEN), "invalid keylen"},
+    {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_OUTPUT_BUFFER_TOO_SMALL),
+    "output buffer too small"},
+    {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_WRONG_FINAL_BLOCK_LENGTH),
+    "wrong final block length"},
+    {0, NULL}
+};
+
+#endif
+
+int ERR_load_PROV_strings(void)
+{
+#ifndef OPENSSL_NO_ERR
+    if (ERR_func_error_string(PROV_str_functs[0].error) == NULL) {
+        ERR_load_strings_const(PROV_str_functs);
+        ERR_load_strings_const(PROV_str_reasons);
+    }
+#endif
+    return 1;
+}
diff --git a/providers/default/defltprov.c b/providers/default/defltprov.c
index 9b52429..cba2dcc 100644
--- a/providers/default/defltprov.c
+++ b/providers/default/defltprov.c
@@ -13,6 +13,7 @@
 #include <openssl/core_numbers.h>
 #include <openssl/core_names.h>
 #include <openssl/params.h>
+#include "internal/provider_algs.h"
 
 /* Functions provided by the core */
 static OSSL_core_get_param_types_fn *c_get_param_types = NULL;
@@ -49,13 +50,36 @@ static int deflt_get_params(const OSSL_PROVIDER *prov,
     return 1;
 }
 
-extern const OSSL_DISPATCH sha256_functions[];
-
 static const OSSL_ALGORITHM deflt_digests[] = {
     { "SHA256", "default=yes", sha256_functions },
     { NULL, NULL, NULL }
 };
 
+static const OSSL_ALGORITHM deflt_ciphers[] = {
+    { "AES-256-ECB", "default=yes", aes256ecb_functions },
+    { "AES-192-ECB", "default=yes", aes192ecb_functions },
+    { "AES-128-ECB", "default=yes", aes128ecb_functions },
+    { "AES-256-CBC", "default=yes", aes256cbc_functions },
+    { "AES-192-CBC", "default=yes", aes192cbc_functions },
+    { "AES-128-CBC", "default=yes", aes128cbc_functions },
+    { "AES-256-OFB", "default=yes", aes256ofb_functions },
+    { "AES-192-OFB", "default=yes", aes192ofb_functions },
+    { "AES-128-OFB", "default=yes", aes128ofb_functions },
+    { "AES-256-CFB", "default=yes", aes256cfb_functions },
+    { "AES-192-CFB", "default=yes", aes192cfb_functions },
+    { "AES-128-CFB", "default=yes", aes128cfb_functions },
+    { "AES-256-CFB1", "default=yes", aes256cfb1_functions },
+    { "AES-192-CFB1", "default=yes", aes192cfb1_functions },
+    { "AES-128-CFB1", "default=yes", aes128cfb1_functions },
+    { "AES-256-CFB8", "default=yes", aes256cfb8_functions },
+    { "AES-192-CFB8", "default=yes", aes192cfb8_functions },
+    { "AES-128-CFB8", "default=yes", aes128cfb8_functions },
+    { "AES-256-CTR", "default=yes", aes256ctr_functions },
+    { "AES-192-CTR", "default=yes", aes192ctr_functions },
+    { "AES-128-CTR", "default=yes", aes128ctr_functions },
+    { NULL, NULL, NULL }
+};
+
 static const OSSL_ALGORITHM *deflt_query(OSSL_PROVIDER *prov,
                                          int operation_id,
                                          int *no_cache)
@@ -64,6 +88,8 @@ static const OSSL_ALGORITHM *deflt_query(OSSL_PROVIDER *prov,
     switch (operation_id) {
     case OSSL_OP_DIGEST:
         return deflt_digests;
+    case OSSL_OP_CIPHER:
+        return deflt_ciphers;
     }
     return NULL;
 }
diff --git a/providers/legacy/digests/md2.c b/providers/legacy/digests/md2.c
index c941dd7..017a511 100644
--- a/providers/legacy/digests/md2.c
+++ b/providers/legacy/digests/md2.c
@@ -54,7 +54,7 @@ extern const OSSL_DISPATCH md2_functions[];
 const OSSL_DISPATCH md2_functions[] = {
     { OSSL_FUNC_DIGEST_NEWCTX, (void (*)(void))md2_newctx },
     { OSSL_FUNC_DIGEST_INIT, (void (*)(void))MD2_Init },
-    { OSSL_FUNC_DIGEST_UPDDATE, (void (*)(void))MD2_Update },
+    { OSSL_FUNC_DIGEST_UPDATE, (void (*)(void))MD2_Update },
     { OSSL_FUNC_DIGEST_FINAL, (void (*)(void))md2_final },
     { OSSL_FUNC_DIGEST_FREECTX, (void (*)(void))md2_freectx },
     { OSSL_FUNC_DIGEST_DUPCTX, (void (*)(void))md2_dupctx },
diff --git a/util/ck_errf.pl b/util/ck_errf.pl
index cc7224a..681535e 100755
--- a/util/ck_errf.pl
+++ b/util/ck_errf.pl
@@ -72,7 +72,8 @@ if ( $internal ) {
     die "Extra parameters given.\n" if @ARGV;
     $config = "crypto/err/openssl.ec" unless defined $config;
     @source = ( glob('crypto/*.c'), glob('crypto/*/*.c'),
-                glob('ssl/*.c'), glob('ssl/*/*.c') );
+                glob('ssl/*.c'), glob('ssl/*/*.c'), glob('providers/*.c'),
+                glob('providers/*/*.c'), glob('providers/*/*/*.c') );
 } else {
     die "Configuration file not given.\nSee '$0 -help' for information\n"
         unless defined $config;
diff --git a/util/libcrypto.num b/util/libcrypto.num
index c14523e..b9be349 100644
--- a/util/libcrypto.num
+++ b/util/libcrypto.num
@@ -4796,3 +4796,6 @@ EVP_MD_fetch                            4743	3_0_0	EXIST::FUNCTION:
 EVP_set_default_properties              4744	3_0_0	EXIST::FUNCTION:
 OSSL_PARAM_construct_end                4745	3_0_0	EXIST::FUNCTION:
 EC_GROUP_check_named_curve              4746	3_0_0	EXIST::FUNCTION:EC
+EVP_CIPHER_upref                        4747	3_0_0	EXIST::FUNCTION:
+EVP_CIPHER_fetch                        4748	3_0_0	EXIST::FUNCTION:
+EVP_CIPHER_mode                         4749	3_0_0	EXIST::FUNCTION:
diff --git a/util/mkerr.pl b/util/mkerr.pl
index 7139ee3..f1d9b39 100755
--- a/util/mkerr.pl
+++ b/util/mkerr.pl
@@ -114,7 +114,8 @@ if ( $internal ) {
     die "Cannot mix -internal and -static\n" if $static;
     die "Extra parameters given.\n" if @ARGV;
     @source = ( glob('crypto/*.c'), glob('crypto/*/*.c'),
-                glob('ssl/*.c'), glob('ssl/*/*.c') );
+                glob('ssl/*.c'), glob('ssl/*/*.c'), glob('providers/*.c'),
+                glob('providers/*/*.c'), glob('providers/*/*/*.c') );
 } else {
     die "-module isn't useful without -internal\n" if scalar keys %modules > 0;
     @source = @ARGV;


More information about the openssl-commits mailing list