From 55c7dc79274f7256f573d99353f887263b162b7b Mon Sep 17 00:00:00 2001 From: Shane Lontis Date: Sun, 15 Sep 2019 20:06:28 +1000 Subject: [PATCH] Add blowfish ciphers to default provider Reviewed-by: Richard Levitte (Merged from https://github.com/openssl/openssl/pull/9887) --- crypto/evp/evp_enc.c | 4 + providers/common/ciphers/cipher_aes_xts.c | 8 +- providers/common/ciphers/cipher_common.c | 13 ++- providers/common/ciphers/cipher_tdes.c | 5 +- .../include/internal/ciphers/cipher_tdes.h | 4 +- .../include/internal/ciphers/ciphercommon.h | 82 ++++++++++++++++++- .../common/include/internal/provider_algs.h | 6 ++ providers/default/ciphers/build.info | 5 ++ providers/default/ciphers/cipher_blowfish.c | 46 +++++++++++ providers/default/ciphers/cipher_blowfish.h | 24 ++++++ .../default/ciphers/cipher_blowfish_hw.c | 36 ++++++++ providers/default/ciphers/cipher_tdes_wrap.c | 2 +- providers/default/defltprov.c | 6 ++ 13 files changed, 225 insertions(+), 16 deletions(-) create mode 100644 providers/default/ciphers/cipher_blowfish.c create mode 100644 providers/default/ciphers/cipher_blowfish.h create mode 100644 providers/default/ciphers/cipher_blowfish_hw.c diff --git a/crypto/evp/evp_enc.c b/crypto/evp/evp_enc.c index 6d657f76cd..9a4e40d9a9 100644 --- a/crypto/evp/evp_enc.c +++ b/crypto/evp/evp_enc.c @@ -231,6 +231,10 @@ int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, case NID_des_ede_cfb64: case NID_desx_cbc: case NID_id_smime_alg_CMS3DESwrap: + case NID_bf_cbc: + case NID_bf_ecb: + case NID_bf_cfb64: + case NID_bf_ofb64: break; default: goto legacy; diff --git a/providers/common/ciphers/cipher_aes_xts.c b/providers/common/ciphers/cipher_aes_xts.c index feaa36991f..c85475442b 100644 --- a/providers/common/ciphers/cipher_aes_xts.c +++ b/providers/common/ciphers/cipher_aes_xts.c @@ -106,13 +106,13 @@ static int aes_xts_dinit(void *vctx, const unsigned char *key, size_t keylen, return aes_xts_init(vctx, key, keylen, iv, ivlen, 0); } -static void *aes_xts_newctx(void *provctx, unsigned int mode, size_t kbits, - size_t blkbits, size_t ivbits) +static void *aes_xts_newctx(void *provctx, unsigned int mode, uint64_t flags, + size_t kbits, size_t blkbits, size_t ivbits) { PROV_AES_XTS_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx)); if (ctx != NULL) { - cipher_generic_initkey(&ctx->base, kbits, blkbits, ivbits, mode, + cipher_generic_initkey(&ctx->base, kbits, blkbits, ivbits, mode, flags, PROV_CIPHER_HW_aes_xts(kbits), NULL); } return ctx; @@ -255,7 +255,7 @@ static int aes_##kbits##_##lcmode##_get_params(OSSL_PARAM params[]) \ static OSSL_OP_cipher_newctx_fn aes_##kbits##_xts_newctx; \ static void *aes_##kbits##_xts_newctx(void *provctx) \ { \ - return aes_xts_newctx(provctx, EVP_CIPH_##UCMODE##_MODE, 2 * kbits, \ + return aes_xts_newctx(provctx, EVP_CIPH_##UCMODE##_MODE, flags, 2 * kbits, \ AES_XTS_BLOCK_BITS, AES_XTS_IV_BITS); \ } \ const OSSL_DISPATCH aes##kbits##xts_functions[] = { \ diff --git a/providers/common/ciphers/cipher_common.c b/providers/common/ciphers/cipher_common.c index 18d6dd9ca5..3c45dd5b9a 100644 --- a/providers/common/ciphers/cipher_common.c +++ b/providers/common/ciphers/cipher_common.c @@ -124,9 +124,13 @@ static int cipher_generic_init_internal(PROV_CIPHER_CTX *ctx, memcpy(ctx->iv, iv, ctx->ivlen); } if (key != NULL) { - if (keylen != ctx->keylen) { - ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEYLEN); - return 0; + if ((ctx->flags & EVP_CIPH_VARIABLE_LENGTH) == 0) { + if (keylen != ctx->keylen) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEYLEN); + return 0; + } + } else { + ctx->keylen = keylen; } return ctx->hw->init(ctx, key, ctx->keylen); } @@ -384,11 +388,12 @@ int cipher_generic_set_ctx_params(void *vctx, const OSSL_PARAM params[]) } void cipher_generic_initkey(void *vctx, size_t kbits, size_t blkbits, - size_t ivbits, unsigned int mode, + size_t ivbits, unsigned int mode, uint64_t flags, const PROV_CIPHER_HW *hw, void *provctx) { PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx; + ctx->flags = flags; ctx->pad = 1; ctx->keylen = ((kbits) / 8); ctx->ivlen = ((ivbits) / 8); diff --git a/providers/common/ciphers/cipher_tdes.c b/providers/common/ciphers/cipher_tdes.c index 91df2ce194..e3e80d186a 100644 --- a/providers/common/ciphers/cipher_tdes.c +++ b/providers/common/ciphers/cipher_tdes.c @@ -14,12 +14,13 @@ #include "internal/providercommonerr.h" void *tdes_newctx(void *provctx, int mode, size_t kbits, size_t blkbits, - size_t ivbits, const PROV_CIPHER_HW *hw) + size_t ivbits, uint64_t flags, const PROV_CIPHER_HW *hw) { PROV_TDES_CTX *tctx = OPENSSL_zalloc(sizeof(*tctx)); if (tctx != NULL) - cipher_generic_initkey(tctx, kbits, blkbits, ivbits, mode, hw, provctx); + cipher_generic_initkey(tctx, kbits, blkbits, ivbits, mode, flags, hw, + provctx); return tctx; } diff --git a/providers/common/include/internal/ciphers/cipher_tdes.h b/providers/common/include/internal/ciphers/cipher_tdes.h index 0d3c90c0af..120201d1ad 100644 --- a/providers/common/include/internal/ciphers/cipher_tdes.h +++ b/providers/common/include/internal/ciphers/cipher_tdes.h @@ -35,7 +35,7 @@ static OSSL_OP_cipher_newctx_fn tdes_##type##_##lcmode##_newctx; \ static void *tdes_##type##_##lcmode##_newctx(void *provctx) \ { \ return tdes_newctx(provctx, EVP_CIPH_##UCMODE##_MODE, kbits, blkbits, \ - ivbits, PROV_CIPHER_HW_tdes_##type##_##lcmode()); \ + ivbits, flags, PROV_CIPHER_HW_tdes_##type##_##lcmode());\ } \ static OSSL_OP_cipher_get_params_fn tdes_##type##_##lcmode##_get_params; \ static int tdes_##type##_##lcmode##_get_params(OSSL_PARAM params[]) \ @@ -68,7 +68,7 @@ const OSSL_DISPATCH tdes_##type##_##lcmode##_functions[] = { \ } void *tdes_newctx(void *provctx, int mode, size_t kbits, size_t blkbits, - size_t ivbits, const PROV_CIPHER_HW *hw); + size_t ivbits, uint64_t flags, const PROV_CIPHER_HW *hw); OSSL_OP_cipher_freectx_fn tdes_freectx; OSSL_OP_cipher_encrypt_init_fn tdes_einit; OSSL_OP_cipher_decrypt_init_fn tdes_dinit; diff --git a/providers/common/include/internal/ciphers/ciphercommon.h b/providers/common/include/internal/ciphers/ciphercommon.h index 5593447264..fe55342e19 100644 --- a/providers/common/include/internal/ciphers/ciphercommon.h +++ b/providers/common/include/internal/ciphers/ciphercommon.h @@ -85,7 +85,7 @@ int cipher_generic_get_params(OSSL_PARAM params[], unsigned int md, unsigned long flags, size_t kbits, size_t blkbits, size_t ivbits); void cipher_generic_initkey(void *vctx, size_t kbits, size_t blkbits, - size_t ivbits, unsigned int mode, + size_t ivbits, unsigned int mode, uint64_t flags, const PROV_CIPHER_HW *hw, void *provctx); #define IMPLEMENT_generic_cipher(alg, UCALG, lcmode, UCMODE, flags, kbits, \ @@ -102,7 +102,7 @@ static void * alg##_##kbits##_##lcmode##_newctx(void *provctx) \ PROV_##UCALG##_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx)); \ if (ctx != NULL) { \ cipher_generic_initkey(ctx, kbits, blkbits, ivbits, \ - EVP_CIPH_##UCMODE##_MODE, \ + EVP_CIPH_##UCMODE##_MODE, flags, \ PROV_CIPHER_HW_##alg##_##lcmode(kbits), NULL); \ } \ return ctx; \ @@ -147,4 +147,80 @@ PROV_CIPHER_HW_FN cipher_hw_chunked_ofb128; #define cipher_hw_chunked_ctr cipher_hw_generic_ctr #define cipher_hw_chunked_cfb1 cipher_hw_generic_cfb1 - +#define IMPLEMENT_CIPHER_HW_OFB(MODE, NAME, CTX_NAME, KEY_NAME, FUNC_PREFIX) \ +static int cipher_hw_##NAME##_##MODE##_cipher(PROV_CIPHER_CTX *ctx, \ + unsigned char *out, \ + const unsigned char *in, size_t len) \ +{ \ + int num = ctx->num; \ + KEY_NAME *key = &(((CTX_NAME *)ctx)->ks.ks); \ + \ + while (len >= MAXCHUNK) { \ + FUNC_PREFIX##_encrypt(in, out, MAXCHUNK, key, ctx->iv, &num); \ + len -= MAXCHUNK; \ + in += MAXCHUNK; \ + out += MAXCHUNK; \ + } \ + if (len > 0) { \ + FUNC_PREFIX##_encrypt(in, out, (long)len, key, ctx->iv, &num); \ + } \ + ctx->num = num; \ + return 1; \ +} + +#define IMPLEMENT_CIPHER_HW_ECB(MODE, NAME, CTX_NAME, KEY_NAME, FUNC_PREFIX) \ +static int cipher_hw_##NAME##_##MODE##_cipher(PROV_CIPHER_CTX *ctx, \ + unsigned char *out, \ + const unsigned char *in, size_t len) \ +{ \ + size_t i, bl = ctx->blocksize; \ + KEY_NAME *key = &(((CTX_NAME *)ctx)->ks.ks); \ + \ + if (len < bl) \ + return 1; \ + for (i = 0, len -= bl; i <= len; i += bl) \ + FUNC_PREFIX##_encrypt(in + i, out + i, key, ctx->enc); \ + return 1; \ +} + +#define IMPLEMENT_CIPHER_HW_CBC(MODE, NAME, CTX_NAME, KEY_NAME, FUNC_PREFIX) \ +static int cipher_hw_##NAME##_##MODE##_cipher(PROV_CIPHER_CTX *ctx, \ + unsigned char *out, \ + const unsigned char *in, size_t len) \ +{ \ + KEY_NAME *key = &(((CTX_NAME *)ctx)->ks.ks); \ + \ + while (len >= MAXCHUNK) { \ + FUNC_PREFIX##_encrypt(in, out, MAXCHUNK, key, ctx->iv, ctx->enc); \ + len -= MAXCHUNK; \ + in += MAXCHUNK; \ + out += MAXCHUNK; \ + } \ + if (len > 0) \ + FUNC_PREFIX##_encrypt(in, out, (long)len, key, ctx->iv, ctx->enc); \ + return 1; \ +} + +#define IMPLEMENT_CIPHER_HW_CFB(MODE, NAME, CTX_NAME, KEY_NAME, FUNC_PREFIX) \ +static int cipher_hw_##NAME##_##MODE##_cipher(PROV_CIPHER_CTX *ctx, \ + unsigned char *out, \ + const unsigned char *in, size_t len) \ +{ \ + size_t chunk = MAXCHUNK; \ + KEY_NAME *key = &(((CTX_NAME *)ctx)->ks.ks); \ + int num = ctx->num; \ + \ + if (len < chunk) \ + chunk = len; \ + while (len > 0 && len >= chunk) { \ + FUNC_PREFIX##_encrypt(in, out, (long)chunk, key, ctx->iv, &num, \ + ctx->enc); \ + len -= chunk; \ + in += chunk; \ + out += chunk; \ + if (len < chunk) \ + chunk = len; \ + } \ + ctx->num = num; \ + return 1; \ +} diff --git a/providers/common/include/internal/provider_algs.h b/providers/common/include/internal/provider_algs.h index e6da5f32a8..5f54612b0a 100644 --- a/providers/common/include/internal/provider_algs.h +++ b/providers/common/include/internal/provider_algs.h @@ -116,6 +116,12 @@ extern const OSSL_DISPATCH camellia256ctr_functions[]; extern const OSSL_DISPATCH camellia192ctr_functions[]; extern const OSSL_DISPATCH camellia128ctr_functions[]; #endif /* OPENSSL_NO_CAMELLIA */ +#ifndef OPENSSL_NO_BF +extern const OSSL_DISPATCH blowfish128ecb_functions[]; +extern const OSSL_DISPATCH blowfish128cbc_functions[]; +extern const OSSL_DISPATCH blowfish64ofb64_functions[]; +extern const OSSL_DISPATCH blowfish64cfb64_functions[]; +#endif /* OPENSSL_NO_BF */ extern const OSSL_DISPATCH tdes_ede3_ecb_functions[]; extern const OSSL_DISPATCH tdes_ede3_cbc_functions[]; diff --git a/providers/default/ciphers/build.info b/providers/default/ciphers/build.info index 92f87e0301..a4ca5cc6c8 100644 --- a/providers/default/ciphers/build.info +++ b/providers/default/ciphers/build.info @@ -19,4 +19,9 @@ IF[{- !$disabled{camellia} -}] cipher_camellia.c cipher_camellia_hw.c ENDIF +IF[{- !$disabled{bf} -}] + SOURCE[../../../libcrypto]=\ + cipher_blowfish.c cipher_blowfish_hw.c +ENDIF + INCLUDE[../../../libcrypto]=. ../../../crypto diff --git a/providers/default/ciphers/cipher_blowfish.c b/providers/default/ciphers/cipher_blowfish.c new file mode 100644 index 0000000000..9e2920df96 --- /dev/null +++ b/providers/default/ciphers/cipher_blowfish.c @@ -0,0 +1,46 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* Dispatch functions for Blowfish cipher modes ecb, cbc, ofb, cfb */ + +#include "cipher_blowfish.h" +#include "internal/provider_algs.h" + +static OSSL_OP_cipher_freectx_fn blowfish_freectx; +static OSSL_OP_cipher_dupctx_fn blowfish_dupctx; + +static void blowfish_freectx(void *vctx) +{ + PROV_BLOWFISH_CTX *ctx = (PROV_BLOWFISH_CTX *)vctx; + + OPENSSL_clear_free(ctx, sizeof(*ctx)); +} + +static void *blowfish_dupctx(void *ctx) +{ + PROV_BLOWFISH_CTX *in = (PROV_BLOWFISH_CTX *)ctx; + PROV_BLOWFISH_CTX *ret = OPENSSL_malloc(sizeof(*ret)); + + if (ret == NULL) { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + return NULL; + } + *ret = *in; + + return ret; +} + +/* bf_ecb_functions */ +IMPLEMENT_generic_cipher(blowfish, BLOWFISH, ecb, ECB, EVP_CIPH_VARIABLE_LENGTH, 128, 64, 0, block) +/* bf_cbc_functions */ +IMPLEMENT_generic_cipher(blowfish, BLOWFISH, cbc, CBC, EVP_CIPH_VARIABLE_LENGTH, 128, 64, 64, block) +/* bf_ofb_functions */ +IMPLEMENT_generic_cipher(blowfish, BLOWFISH, ofb64, OFB, EVP_CIPH_VARIABLE_LENGTH, 64, 8, 64, stream) +/* bf_cfb_functions */ +IMPLEMENT_generic_cipher(blowfish, BLOWFISH, cfb64, CFB, EVP_CIPH_VARIABLE_LENGTH, 64, 8, 64, stream) diff --git a/providers/default/ciphers/cipher_blowfish.h b/providers/default/ciphers/cipher_blowfish.h new file mode 100644 index 0000000000..819a61f140 --- /dev/null +++ b/providers/default/ciphers/cipher_blowfish.h @@ -0,0 +1,24 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/ciphers/ciphercommon.h" + +typedef struct prov_blowfish_ctx_st { + PROV_CIPHER_CTX base; /* Must be first */ + union { + OSSL_UNION_ALIGN; + BF_KEY ks; + } ks; +} PROV_BLOWFISH_CTX; + +const PROV_CIPHER_HW *PROV_CIPHER_HW_blowfish_cbc(size_t keybits); +const PROV_CIPHER_HW *PROV_CIPHER_HW_blowfish_ecb(size_t keybits); +const PROV_CIPHER_HW *PROV_CIPHER_HW_blowfish_ofb64(size_t keybits); +const PROV_CIPHER_HW *PROV_CIPHER_HW_blowfish_cfb64(size_t keybits); diff --git a/providers/default/ciphers/cipher_blowfish_hw.c b/providers/default/ciphers/cipher_blowfish_hw.c new file mode 100644 index 0000000000..137aeef5ca --- /dev/null +++ b/providers/default/ciphers/cipher_blowfish_hw.c @@ -0,0 +1,36 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "cipher_blowfish.h" + +static int cipher_hw_blowfish_initkey(PROV_CIPHER_CTX *ctx, + const unsigned char *key, size_t keylen) +{ + PROV_BLOWFISH_CTX *bctx = (PROV_BLOWFISH_CTX *)ctx; + + BF_set_key(&bctx->ks.ks, keylen, key); + return 1; +} + +# define PROV_CIPHER_HW_blowfish_mode(mode, UCMODE) \ +IMPLEMENT_CIPHER_HW_##UCMODE(mode, blowfish, PROV_BLOWFISH_CTX, BF_KEY, \ + BF_##mode) \ +static const PROV_CIPHER_HW bf_##mode = { \ + cipher_hw_blowfish_initkey, \ + cipher_hw_blowfish_##mode##_cipher \ +}; \ +const PROV_CIPHER_HW *PROV_CIPHER_HW_blowfish_##mode(size_t keybits) \ +{ \ + return &bf_##mode; \ +} + +PROV_CIPHER_HW_blowfish_mode(cbc, CBC) +PROV_CIPHER_HW_blowfish_mode(ecb, ECB) +PROV_CIPHER_HW_blowfish_mode(ofb64, OFB) +PROV_CIPHER_HW_blowfish_mode(cfb64, CFB) diff --git a/providers/default/ciphers/cipher_tdes_wrap.c b/providers/default/ciphers/cipher_tdes_wrap.c index 833e18190a..08662dbdb0 100644 --- a/providers/default/ciphers/cipher_tdes_wrap.c +++ b/providers/default/ciphers/cipher_tdes_wrap.c @@ -165,7 +165,7 @@ static OSSL_OP_cipher_newctx_fn tdes_wrap_newctx; \ static void *tdes_wrap_newctx(void *provctx) \ { \ return tdes_newctx(provctx, EVP_CIPH_WRAP_MODE, kbits, blkbits, ivbits, \ - PROV_CIPHER_HW_tdes_wrap_cbc()); \ + flags, PROV_CIPHER_HW_tdes_wrap_cbc()); \ } \ static OSSL_OP_cipher_get_params_fn tdes_wrap_get_params; \ static int tdes_wrap_get_params(OSSL_PARAM params[]) \ diff --git a/providers/default/defltprov.c b/providers/default/defltprov.c index e829dbfac0..59a7b60e83 100644 --- a/providers/default/defltprov.c +++ b/providers/default/defltprov.c @@ -189,6 +189,12 @@ static const OSSL_ALGORITHM deflt_ciphers[] = { { "DESX-CBC", "default=yes", tdes_desx_cbc_functions }, { "id-smime-alg-CMS3DESwrap", "default=yes", tdes_wrap_cbc_functions }, #endif /* OPENSSL_NO_DES */ +#ifndef OPENSSL_NO_BF + { "BF-ECB", "default=yes", blowfish128ecb_functions }, + { "BF-CBC", "default=yes", blowfish128cbc_functions }, + { "BF-OFB", "default=yes", blowfish64ofb64_functions }, + { "BF-CFB", "default=yes", blowfish64cfb64_functions }, +#endif /* OPENSSL_NO_BF */ { NULL, NULL, NULL } }; -- 2.25.1