Commit 718b133a authored by Matt Caswell's avatar Matt Caswell
Browse files

Implement AES CBC ciphers in the default provider

parent f4a129bb
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -787,6 +787,7 @@ 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
+46 −9
Original line number Diff line number Diff line
@@ -142,6 +142,9 @@ int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
        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:
            break;
        default:
            goto legacy;
@@ -204,6 +207,19 @@ int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
            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);
@@ -851,12 +867,12 @@ int EVP_CIPHER_CTX_set_padding(EVP_CIPHER_CTX *ctx, int pad)

        params[0].data = &pad;

        if (ctx->cipher->set_params == NULL) {
        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->set_params(ctx->provctx, params))
        if (!ctx->cipher->ctx_set_params(ctx->provctx, params))
            return 0;
    }

@@ -915,7 +931,7 @@ int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, const EVP_CIPHER_CTX *in)
    *out = *in;
    out->provctx = NULL;

    if (in->fetched_cipher != NULL || !EVP_CIPHER_upref(in->fetched_cipher)) {
    if (in->fetched_cipher != NULL && !EVP_CIPHER_upref(in->fetched_cipher)) {
        out->fetched_cipher = NULL;
        return 0;
    }
@@ -1002,6 +1018,11 @@ static void *evp_cipher_from_dispatch(int nid, const OSSL_DISPATCH *fns,
            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;
@@ -1018,25 +1039,41 @@ static void *evp_cipher_from_dispatch(int nid, const OSSL_DISPATCH *fns,
                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_SET_PARAMS:
            if (cipher->set_params != NULL)
        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->set_params = OSSL_get_OP_cipher_set_params(fns);
            cipher->ctx_set_params = OSSL_get_OP_cipher_ctx_set_params(fns);
            break;
        }
    }
    if ((fnciphcnt != 3 && fnciphcnt != 4)
    if ((fnciphcnt != 0 && fnciphcnt != 3 && fnciphcnt != 4)
            || (fnciphcnt == 0 && cipher->ccipher == NULL)
            || fnctxcnt != 2) {
        /*
         * 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. In both cases we need a complete set of context management
         * functions
         * functions, or a single "cipher" function. In all cases we need a
         * complete set of context management functions
         */
        EVP_CIPHER_meth_free(cipher);
        EVPerr(EVP_F_EVP_CIPHER_FROM_DISPATCH, EVP_R_INVALID_PROVIDER_FUNCTIONS);
+1 −0
Original line number Diff line number Diff line
@@ -57,6 +57,7 @@ static const ERR_STRING_DATA EVP_str_functs[] = {
     "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),
+96 −19
Original line number Diff line number Diff line
@@ -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 (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->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 (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 (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->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 (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)
@@ -308,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) {
+5 −1
Original line number Diff line number Diff line
@@ -249,11 +249,15 @@ struct evp_cipher_st {
    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_get_params_fn *set_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 */
Loading