From 345c99b6654b8313c792d54f829943068911ddbd Mon Sep 17 00:00:00 2001 From: Danny Tsen Date: Thu, 27 Jan 2022 18:49:59 -0600 Subject: [PATCH] Fixed counter overflow Reviewed-by: Tomas Mraz Reviewed-by: Paul Dale (Merged from https://github.com/openssl/openssl/pull/17607) --- crypto/modes/asm/aes-gcm-ppc.pl | 1 - include/crypto/aes_platform.h | 22 +++-- .../ciphers/cipher_aes_gcm_hw_ppc.inc | 82 ++++++++++++++++++- 3 files changed, 96 insertions(+), 9 deletions(-) diff --git a/crypto/modes/asm/aes-gcm-ppc.pl b/crypto/modes/asm/aes-gcm-ppc.pl index 1ca2a77dc5..6624e6c05b 100644 --- a/crypto/modes/asm/aes-gcm-ppc.pl +++ b/crypto/modes/asm/aes-gcm-ppc.pl @@ -81,7 +81,6 @@ open STDOUT,"| $^X $xlate $flavour \"$output\"" $code=<<___; .machine "any" -.abiversion 2 .text # 4x loops diff --git a/include/crypto/aes_platform.h b/include/crypto/aes_platform.h index 45021dfd9f..11ab823468 100644 --- a/include/crypto/aes_platform.h +++ b/include/crypto/aes_platform.h @@ -77,15 +77,23 @@ void AES_xts_decrypt(const unsigned char *inp, unsigned char *out, size_t len, # define PPC_AES_GCM_CAPABLE (OPENSSL_ppccap_P & PPC_MADD300) # define AES_GCM_ENC_BYTES 128 # define AES_GCM_DEC_BYTES 128 -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); -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); -void gcm_ghash_p8(u64 Xi[2],const u128 Htable[16],const u8 *inp, size_t len); -# define AES_gcm_encrypt ppc_aes_gcm_encrypt -# define AES_gcm_decrypt ppc_aes_gcm_decrypt +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); +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); +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); +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); +# define AES_gcm_encrypt ppc_aes_gcm_encrypt_wrap +# define AES_gcm_decrypt ppc_aes_gcm_decrypt_wrap # define AES_GCM_ASM(gctx) ((gctx)->ctr==aes_p8_ctr32_encrypt_blocks && \ (gctx)->gcm.ghash==gcm_ghash_p8) +void gcm_ghash_p8(u64 Xi[2],const u128 Htable[16],const u8 *inp, size_t len); # endif /* PPC */ # if (defined(__arm__) || defined(__arm) || defined(__aarch64__)) diff --git a/providers/implementations/ciphers/cipher_aes_gcm_hw_ppc.inc b/providers/implementations/ciphers/cipher_aes_gcm_hw_ppc.inc index dfc6bcbf58..4eed0f4ab0 100644 --- a/providers/implementations/ciphers/cipher_aes_gcm_hw_ppc.inc +++ b/providers/implementations/ciphers/cipher_aes_gcm_hw_ppc.inc @@ -13,7 +13,7 @@ */ static int aes_ppc_gcm_initkey(PROV_GCM_CTX *ctx, const unsigned char *key, - size_t keylen) + size_t keylen) { PROV_AES_GCM_CTX *actx = (PROV_AES_GCM_CTX *)ctx; AES_KEY *ks = &actx->ks.ks; @@ -23,6 +23,86 @@ 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]); +} + +static inline u32 add32TOU(unsigned char buf[4], u32 n) +{ + u32 r; + + r = UTO32(buf); + r += n; + buf[0] = (unsigned char) (r >> 24) & 0xFF; + buf[1] = (unsigned char) (r >> 16) & 0xFF; + buf[2] = (unsigned char) (r >> 8) & 0xFF; + buf[3] = (unsigned char) r & 0xFF; + return r; +} + +static size_t aes_p10_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; + int ndone = 0; + int ctr_reset = 0; + u64 blocks_unused; + u64 nb = len / 16; + u64 next_ctr = 0; + unsigned char ctr_saved[12]; + + memcpy(ctr_saved, ivec, 12); + + while (nb) { + blocks_unused = (u64) 0xffffffffU + 1 - (u64) UTO32 (ivec + 12); + if (nb > blocks_unused) { + len = blocks_unused * 16; + nb -= blocks_unused; + next_ctr = blocks_unused; + ctr_reset = 1; + } else { + len = nb * 16; + next_ctr = nb; + nb = 0; + } + + s = encrypt ? ppc_aes_gcm_encrypt(in, out, len, key, ivec, Xi) + : ppc_aes_gcm_decrypt(in, out, len, key, ivec, Xi); + + /* add counter to ivec */ + add32TOU(ivec + 12, (u32) next_ctr); + if (ctr_reset) { + ctr_reset = 0; + in += len; + out += len; + } + memcpy(ivec, ctr_saved, 12); + ndone += s; + } + + 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) +{ + return aes_p10_gcm_crypt(in, out, len, key, ivec, Xi, 0); +} + + static const PROV_GCM_HW aes_ppc_gcm = { aes_ppc_gcm_initkey, ossl_gcm_setiv,