summaryrefslogtreecommitdiff
path: root/providers
diff options
context:
space:
mode:
authorTomas Mraz <tomas@openssl.org>2022-09-09 14:46:24 +0200
committerTomas Mraz <tomas@openssl.org>2022-09-13 14:41:39 +0200
commit9ab6b64ac856157a31a54c0d12207c2338bfa8e2 (patch)
treee7fba37b552210d0c23423f08f1aa8d530fad208 /providers
parentfabce8090c3ba49527d434a4621c660eedad2aaa (diff)
downloadopenssl-new-9ab6b64ac856157a31a54c0d12207c2338bfa8e2.tar.gz
Fix AES-GCM on Power 8 CPUs
Properly fallback to the default implementation on CPUs missing necessary instructions. Fixes #19163 Reviewed-by: Dmitry Belyavskiy <beldmit@gmail.com> Reviewed-by: Paul Dale <pauli@openssl.org> (Merged from https://github.com/openssl/openssl/pull/19182)
Diffstat (limited to 'providers')
-rw-r--r--providers/implementations/ciphers/cipher_aes_gcm_hw_ppc.inc72
1 files changed, 54 insertions, 18 deletions
diff --git a/providers/implementations/ciphers/cipher_aes_gcm_hw_ppc.inc b/providers/implementations/ciphers/cipher_aes_gcm_hw_ppc.inc
index 5a1c3e4a58..153eb79891 100644
--- a/providers/implementations/ciphers/cipher_aes_gcm_hw_ppc.inc
+++ b/providers/implementations/ciphers/cipher_aes_gcm_hw_ppc.inc
@@ -23,12 +23,6 @@ static int aes_ppc_gcm_initkey(PROV_GCM_CTX *ctx, const unsigned char *key,
return 1;
}
-
-extern size_t ppc_aes_gcm_encrypt(const unsigned char *in, unsigned char *out, size_t len,
- const void *key, unsigned char ivec[16], u64 *Xi);
-extern size_t ppc_aes_gcm_decrypt(const unsigned char *in, unsigned char *out, size_t len,
- const void *key, unsigned char ivec[16], u64 *Xi);
-
static inline u32 UTO32(unsigned char *buf)
{
return ((u32) buf[0] << 24) | ((u32) buf[1] << 16) | ((u32) buf[2] << 8) | ((u32) buf[3]);
@@ -47,7 +41,7 @@ static inline u32 add32TOU(unsigned char buf[4], u32 n)
return r;
}
-static size_t aes_p10_gcm_crypt(const unsigned char *in, unsigned char *out, size_t len,
+static size_t ppc_aes_gcm_crypt(const unsigned char *in, unsigned char *out, size_t len,
const void *key, unsigned char ivec[16], u64 *Xi, int encrypt)
{
int s = 0;
@@ -90,24 +84,66 @@ static size_t aes_p10_gcm_crypt(const unsigned char *in, unsigned char *out, siz
return ndone;
}
-size_t ppc_aes_gcm_encrypt_wrap(const unsigned char *in, unsigned char *out, size_t len,
- const void *key, unsigned char ivec[16], u64 *Xi)
-{
- return aes_p10_gcm_crypt(in, out, len, key, ivec, Xi, 1);
-}
-
-size_t ppc_aes_gcm_decrypt_wrap(const unsigned char *in, unsigned char *out, size_t len,
- const void *key, unsigned char ivec[16], u64 *Xi)
+static int ppc_aes_gcm_cipher_update(PROV_GCM_CTX *ctx, const unsigned char *in,
+ size_t len, unsigned char *out)
{
- return aes_p10_gcm_crypt(in, out, len, key, ivec, Xi, 0);
+ if (ctx->enc) {
+ if (ctx->ctr != NULL) {
+ size_t bulk = 0;
+
+ if (len >= AES_GCM_ENC_BYTES && AES_GCM_ASM_PPC(ctx)) {
+ size_t res = (16 - ctx->gcm.mres) % 16;
+
+ if (CRYPTO_gcm128_encrypt(&ctx->gcm, in, out, res))
+ return 0;
+
+ bulk = ppc_aes_gcm_crypt(in + res, out + res, len - res,
+ ctx->gcm.key,
+ ctx->gcm.Yi.c, ctx->gcm.Xi.u, 1);
+
+ ctx->gcm.len.u[1] += bulk;
+ bulk += res;
+ }
+ if (CRYPTO_gcm128_encrypt_ctr32(&ctx->gcm, in + bulk, out + bulk,
+ len - bulk, ctx->ctr))
+ return 0;
+ } else {
+ if (CRYPTO_gcm128_encrypt(&ctx->gcm, in, out, len))
+ return 0;
+ }
+ } else {
+ if (ctx->ctr != NULL) {
+ size_t bulk = 0;
+
+ if (len >= AES_GCM_DEC_BYTES && AES_GCM_ASM_PPC(ctx)) {
+ size_t res = (16 - ctx->gcm.mres) % 16;
+
+ if (CRYPTO_gcm128_decrypt(&ctx->gcm, in, out, res))
+ return -1;
+
+ bulk = ppc_aes_gcm_crypt(in + res, out + res, len - res,
+ ctx->gcm.key,
+ ctx->gcm.Yi.c, ctx->gcm.Xi.u, 0);
+
+ ctx->gcm.len.u[1] += bulk;
+ bulk += res;
+ }
+ if (CRYPTO_gcm128_decrypt_ctr32(&ctx->gcm, in + bulk, out + bulk,
+ len - bulk, ctx->ctr))
+ return 0;
+ } else {
+ if (CRYPTO_gcm128_decrypt(&ctx->gcm, in, out, len))
+ return 0;
+ }
+ }
+ return 1;
}
-
static const PROV_GCM_HW aes_ppc_gcm = {
aes_ppc_gcm_initkey,
ossl_gcm_setiv,
ossl_gcm_aad_update,
- generic_aes_gcm_cipher_update,
+ ppc_aes_gcm_cipher_update,
ossl_gcm_cipher_final,
ossl_gcm_one_shot
};