diff options
Diffstat (limited to 'providers/common/ciphers/cipher_common_hw.c')
-rw-r--r-- | providers/common/ciphers/cipher_common_hw.c | 192 |
1 files changed, 192 insertions, 0 deletions
diff --git a/providers/common/ciphers/cipher_common_hw.c b/providers/common/ciphers/cipher_common_hw.c new file mode 100644 index 0000000000..47e14afbbb --- /dev/null +++ b/providers/common/ciphers/cipher_common_hw.c @@ -0,0 +1,192 @@ +/* + * 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_locl.h" + +#define MAXCHUNK ((size_t)1 << (sizeof(long) * 8 - 2)) +#define MAXBITCHUNK ((size_t)1 << (sizeof(size_t) * 8 - 4)) + +/*- + * The generic cipher functions for cipher modes cbc, ecb, ofb, cfb and ctr. + * Used if there is no special hardware implementations. + */ +int cipher_hw_generic_cbc(PROV_CIPHER_CTX *dat, unsigned char *out, + const unsigned char *in, size_t len) +{ + if (dat->stream.cbc) + (*dat->stream.cbc) (in, out, len, dat->ks, dat->iv, dat->enc); + else if (dat->enc) + CRYPTO_cbc128_encrypt(in, out, len, dat->ks, dat->iv, dat->block); + else + CRYPTO_cbc128_decrypt(in, out, len, dat->ks, dat->iv, dat->block); + + return 1; +} + +int cipher_hw_generic_ecb(PROV_CIPHER_CTX *dat, unsigned char *out, + const unsigned char *in, size_t len) +{ + size_t i, bl = dat->blocksize; + + if (len < bl) + return 1; + + for (i = 0, len -= bl; i <= len; i += bl) + (*dat->block) (in + i, out + i, dat->ks); + + return 1; +} + +int cipher_hw_generic_ofb128(PROV_CIPHER_CTX *dat, unsigned char *out, + const unsigned char *in, size_t len) +{ + int num = dat->num; + + CRYPTO_ofb128_encrypt(in, out, len, dat->ks, dat->iv, &num, dat->block); + dat->num = num; + + return 1; +} + +int cipher_hw_generic_cfb128(PROV_CIPHER_CTX *dat, unsigned char *out, + const unsigned char *in, size_t len) +{ + int num = dat->num; + + CRYPTO_cfb128_encrypt(in, out, len, dat->ks, dat->iv, &num, dat->enc, + dat->block); + dat->num = num; + + return 1; +} + +int cipher_hw_generic_cfb8(PROV_CIPHER_CTX *dat, unsigned char *out, + const unsigned char *in, size_t len) +{ + int num = dat->num; + + CRYPTO_cfb128_8_encrypt(in, out, len, dat->ks, dat->iv, &num, dat->enc, + dat->block); + dat->num = num; + + return 1; +} + +int cipher_hw_generic_cfb1(PROV_CIPHER_CTX *dat, unsigned char *out, + const unsigned char *in, size_t len) +{ + int num = dat->num; + + if ((dat->flags & EVP_CIPH_FLAG_LENGTH_BITS) != 0) { + CRYPTO_cfb128_1_encrypt(in, out, len, dat->ks, dat->iv, &num, + dat->enc, dat->block); + dat->num = num; + return 1; + } + + while (len >= MAXBITCHUNK) { + CRYPTO_cfb128_1_encrypt(in, out, MAXBITCHUNK * 8, dat->ks, + dat->iv, &num, dat->enc, dat->block); + len -= MAXBITCHUNK; + out += MAXBITCHUNK; + in += MAXBITCHUNK; + } + if (len) + CRYPTO_cfb128_1_encrypt(in, out, len * 8, dat->ks, dat->iv, &num, + dat->enc, dat->block); + + dat->num = num; + + return 1; +} + +int cipher_hw_generic_ctr(PROV_CIPHER_CTX *dat, unsigned char *out, + const unsigned char *in, size_t len) +{ + unsigned int num = dat->num; + + if (dat->stream.ctr) + CRYPTO_ctr128_encrypt_ctr32(in, out, len, dat->ks, dat->iv, dat->buf, + &num, dat->stream.ctr); + else + CRYPTO_ctr128_encrypt(in, out, len, dat->ks, dat->iv, dat->buf, + &num, dat->block); + dat->num = num; + + return 1; +} + +/*- + * The chunked cipher functions for cipher modes cbc, ecb, ofb, cfb and ctr. + * Used if there is no special hardware implementations. + */ + +int cipher_hw_chunked_cbc(PROV_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl) +{ + while (inl >= MAXCHUNK) { + cipher_hw_generic_cbc(ctx, out, in, MAXCHUNK); + inl -= MAXCHUNK; + in += MAXCHUNK; + out += MAXCHUNK; + } + if (inl > 0) + cipher_hw_generic_cbc(ctx, out, in, inl); + return 1; +} + +int cipher_hw_chunked_cfb8(PROV_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl) +{ + size_t chunk = MAXCHUNK; + + if (inl < chunk) + chunk = inl; + while (inl > 0 && inl >= chunk) { + cipher_hw_generic_cfb8(ctx, out, in, inl); + inl -= chunk; + in += chunk; + out += chunk; + if (inl < chunk) + chunk = inl; + } + return 1; +} + +int cipher_hw_chunked_cfb128(PROV_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl) +{ + size_t chunk = MAXCHUNK; + + if (inl < chunk) + chunk = inl; + while (inl > 0 && inl >= chunk) { + cipher_hw_generic_cfb128(ctx, out, in, inl); + inl -= chunk; + in += chunk; + out += chunk; + if (inl < chunk) + chunk = inl; + } + return 1; +} + +int cipher_hw_chunked_ofb128(PROV_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl) +{ + while (inl >= MAXCHUNK) { + cipher_hw_generic_ofb128(ctx, out, in, MAXCHUNK); + inl -= MAXCHUNK; + in += MAXCHUNK; + out += MAXCHUNK; + } + if (inl > 0) + cipher_hw_generic_ofb128(ctx, out, in, inl); + return 1; +} |