mirror of
https://github.com/openssl/openssl.git
synced 2024-12-21 06:09:35 +08:00
eec0ad10b9
Reviewed-by: Nicola Tuveri <nic.tuv@gmail.com> (Merged from https://github.com/openssl/openssl/pull/13144)
195 lines
5.4 KiB
C
195 lines
5.4 KiB
C
/*
|
|
* Copyright 2019-2020 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->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 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;
|
|
}
|