|  | /* | 
|  | * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved. | 
|  | * | 
|  | * Licensed under the Apache License 2.0 (the "License").  You may not use | 
|  | * this file except in compliance with the License.  You can obtain a copy | 
|  | * in the file LICENSE in the source distribution or at | 
|  | * https://www.openssl.org/source/license.html | 
|  | */ | 
|  |  | 
|  | #include "prov/ciphercommon.h" | 
|  |  | 
|  | /*- | 
|  | * The generic cipher functions for cipher modes cbc, ecb, ofb, cfb and ctr. | 
|  | * Used if there is no special hardware implementations. | 
|  | */ | 
|  | int ossl_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 ossl_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; | 
|  |  | 
|  | if (dat->stream.ecb) { | 
|  | (*dat->stream.ecb) (in, out, len, dat->ks, dat->enc); | 
|  | } | 
|  | else { | 
|  | for (i = 0, len -= bl; i <= len; i += bl) | 
|  | (*dat->block) (in + i, out + i, dat->ks); | 
|  | } | 
|  |  | 
|  | return 1; | 
|  | } | 
|  |  | 
|  | int ossl_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 ossl_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 ossl_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 ossl_cipher_hw_generic_cfb1(PROV_CIPHER_CTX *dat, unsigned char *out, | 
|  | const unsigned char *in, size_t len) | 
|  | { | 
|  | int num = dat->num; | 
|  |  | 
|  | if (dat->use_bits) { | 
|  | 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 ossl_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 ossl_cipher_hw_chunked_cbc(PROV_CIPHER_CTX *ctx, unsigned char *out, | 
|  | const unsigned char *in, size_t inl) | 
|  | { | 
|  | while (inl >= MAXCHUNK) { | 
|  | ossl_cipher_hw_generic_cbc(ctx, out, in, MAXCHUNK); | 
|  | inl -= MAXCHUNK; | 
|  | in  += MAXCHUNK; | 
|  | out += MAXCHUNK; | 
|  | } | 
|  | if (inl > 0) | 
|  | ossl_cipher_hw_generic_cbc(ctx, out, in, inl); | 
|  | return 1; | 
|  | } | 
|  |  | 
|  | int ossl_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) { | 
|  | ossl_cipher_hw_generic_cfb8(ctx, out, in, inl); | 
|  | inl -= chunk; | 
|  | in += chunk; | 
|  | out += chunk; | 
|  | if (inl < chunk) | 
|  | chunk = inl; | 
|  | } | 
|  | return 1; | 
|  | } | 
|  |  | 
|  | int ossl_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) { | 
|  | ossl_cipher_hw_generic_cfb128(ctx, out, in, inl); | 
|  | inl -= chunk; | 
|  | in += chunk; | 
|  | out += chunk; | 
|  | if (inl < chunk) | 
|  | chunk = inl; | 
|  | } | 
|  | return 1; | 
|  | } | 
|  |  | 
|  | int ossl_cipher_hw_chunked_ofb128(PROV_CIPHER_CTX *ctx, unsigned char *out, | 
|  | const unsigned char *in, size_t inl) | 
|  | { | 
|  | while (inl >= MAXCHUNK) { | 
|  | ossl_cipher_hw_generic_ofb128(ctx, out, in, MAXCHUNK); | 
|  | inl -= MAXCHUNK; | 
|  | in  += MAXCHUNK; | 
|  | out += MAXCHUNK; | 
|  | } | 
|  | if (inl > 0) | 
|  | ossl_cipher_hw_generic_ofb128(ctx, out, in, inl); | 
|  | return 1; | 
|  | } |