From: Patrick Steuer Date: Wed, 28 Mar 2018 12:09:24 +0000 (+0100) Subject: s390x assembly pack: add KMF code path for aes-cfb/cfb8 X-Git-Tag: OpenSSL_1_1_1-pre4~33 X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=commitdiff_plain;h=74d38a8677ac10f7368c12079af9a27e959ee295 s390x assembly pack: add KMF code path for aes-cfb/cfb8 Signed-off-by: Patrick Steuer Reviewed-by: Richard Levitte Reviewed-by: Andy Polyakov Reviewed-by: Rich Salz (Merged from https://github.com/openssl/openssl/pull/5250) --- diff --git a/crypto/evp/e_aes.c b/crypto/evp/e_aes.c index 9309ec954f..913242e27a 100644 --- a/crypto/evp/e_aes.c +++ b/crypto/evp/e_aes.c @@ -989,6 +989,24 @@ typedef struct { int res; } S390X_AES_OFB_CTX; +typedef struct { + union { + double align; + /*- + * KMF-AES parameter block - begin + * (see z/Architecture Principles of Operation >= SA22-7832-08) + */ + struct { + unsigned char cv[16]; + unsigned char k[32]; + } param; + /* KMF-AES parameter block - end */ + } kmf; + unsigned int fc; + + int res; +} S390X_AES_CFB_CTX; + typedef struct { union { double align; @@ -1208,26 +1226,116 @@ static int s390x_aes_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, return 1; } -# define S390X_aes_128_cfb_CAPABLE 0 -# define S390X_aes_192_cfb_CAPABLE 0 -# define S390X_aes_256_cfb_CAPABLE 0 -# define S390X_AES_CFB_CTX EVP_AES_KEY +# define S390X_aes_128_cfb_CAPABLE (S390X_aes_128_CAPABLE && \ + (OPENSSL_s390xcap_P.kmf[0] & \ + S390X_CAPBIT(S390X_AES_128))) +# define S390X_aes_192_cfb_CAPABLE (S390X_aes_192_CAPABLE && \ + (OPENSSL_s390xcap_P.kmf[0] & \ + S390X_CAPBIT(S390X_AES_192))) +# define S390X_aes_256_cfb_CAPABLE (S390X_aes_256_CAPABLE && \ + (OPENSSL_s390xcap_P.kmf[0] & \ + S390X_CAPBIT(S390X_AES_256))) -# define s390x_aes_cfb_init_key aes_init_key +static int s390x_aes_cfb_init_key(EVP_CIPHER_CTX *ctx, + const unsigned char *key, + const unsigned char *ivec, int enc) +{ + S390X_AES_CFB_CTX *cctx = EVP_C_DATA(S390X_AES_CFB_CTX, ctx); + const unsigned char *iv = EVP_CIPHER_CTX_original_iv(ctx); + const int keylen = EVP_CIPHER_CTX_key_length(ctx); + const int ivlen = EVP_CIPHER_CTX_iv_length(ctx); + + cctx->fc = S390X_AES_FC(keylen); + cctx->fc |= 16 << 24; /* 16 bytes cipher feedback */ + if (!enc) + cctx->fc |= S390X_DECRYPT; + + cctx->res = 0; + memcpy(cctx->kmf.param.cv, iv, ivlen); + memcpy(cctx->kmf.param.k, key, keylen); + return 1; +} -# define s390x_aes_cfb_cipher aes_cfb_cipher static int s390x_aes_cfb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, - const unsigned char *in, size_t len); + const unsigned char *in, size_t len) +{ + S390X_AES_CFB_CTX *cctx = EVP_C_DATA(S390X_AES_CFB_CTX, ctx); + const int keylen = EVP_CIPHER_CTX_key_length(ctx); + const int enc = EVP_CIPHER_CTX_encrypting(ctx); + int n = cctx->res; + int rem; + unsigned char tmp; -# define S390X_aes_128_cfb8_CAPABLE 0 -# define S390X_aes_192_cfb8_CAPABLE 0 -# define S390X_aes_256_cfb8_CAPABLE 0 + while (n && len) { + tmp = *in; + *out = cctx->kmf.param.cv[n] ^ tmp; + cctx->kmf.param.cv[n] = enc ? *out : tmp; + n = (n + 1) & 0xf; + --len; + ++in; + ++out; + } + + rem = len & 0xf; + + len &= ~(size_t)0xf; + if (len) { + s390x_kmf(in, len, out, cctx->fc, &cctx->kmf.param); + + out += len; + in += len; + } + + if (rem) { + s390x_km(cctx->kmf.param.cv, 16, cctx->kmf.param.cv, + S390X_AES_FC(keylen), cctx->kmf.param.k); + + while (rem--) { + tmp = in[n]; + out[n] = cctx->kmf.param.cv[n] ^ tmp; + cctx->kmf.param.cv[n] = enc ? out[n] : tmp; + ++n; + } + } + + cctx->res = n; + return 1; +} + +# define S390X_aes_128_cfb8_CAPABLE (OPENSSL_s390xcap_P.kmf[0] & \ + S390X_CAPBIT(S390X_AES_128)) +# define S390X_aes_192_cfb8_CAPABLE (OPENSSL_s390xcap_P.kmf[0] & \ + S390X_CAPBIT(S390X_AES_192)) +# define S390X_aes_256_cfb8_CAPABLE (OPENSSL_s390xcap_P.kmf[0] & \ + S390X_CAPBIT(S390X_AES_256)) + +static int s390x_aes_cfb8_init_key(EVP_CIPHER_CTX *ctx, + const unsigned char *key, + const unsigned char *ivec, int enc) +{ + S390X_AES_CFB_CTX *cctx = EVP_C_DATA(S390X_AES_CFB_CTX, ctx); + const unsigned char *iv = EVP_CIPHER_CTX_original_iv(ctx); + const int keylen = EVP_CIPHER_CTX_key_length(ctx); + const int ivlen = EVP_CIPHER_CTX_iv_length(ctx); + + cctx->fc = S390X_AES_FC(keylen); + cctx->fc |= 1 << 24; /* 1 byte cipher feedback */ + if (!enc) + cctx->fc |= S390X_DECRYPT; -# define s390x_aes_cfb8_init_key aes_init_key + memcpy(cctx->kmf.param.cv, iv, ivlen); + memcpy(cctx->kmf.param.k, key, keylen); + return 1; +} -# define s390x_aes_cfb8_cipher aes_cfb8_cipher static int s390x_aes_cfb8_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, - const unsigned char *in, size_t len); + const unsigned char *in, size_t len) +{ + S390X_AES_CFB_CTX *cctx = EVP_C_DATA(S390X_AES_CFB_CTX, ctx); + + s390x_kmf(in, len, out, cctx->fc, &cctx->kmf.param); + return 1; +} # define S390X_aes_128_cfb1_CAPABLE 0 # define S390X_aes_192_cfb1_CAPABLE 0 diff --git a/crypto/s390x_arch.h b/crypto/s390x_arch.h index 236f936b57..5042154470 100644 --- a/crypto/s390x_arch.h +++ b/crypto/s390x_arch.h @@ -18,6 +18,8 @@ void s390x_kmac(const unsigned char *in, size_t len, unsigned int fc, void *param); void s390x_kmo(const unsigned char *in, size_t len, unsigned char *out, unsigned int fc, void *param); +void s390x_kmf(const unsigned char *in, size_t len, unsigned char *out, + unsigned int fc, void *param); void s390x_kma(const unsigned char *aad, size_t alen, const unsigned char *in, size_t len, unsigned char *out, unsigned int fc, void *param); diff --git a/crypto/s390xcpuid.pl b/crypto/s390xcpuid.pl index dfef2c129a..e7afb8dcf5 100755 --- a/crypto/s390xcpuid.pl +++ b/crypto/s390xcpuid.pl @@ -325,6 +325,27 @@ s390x_kmo: ___ } +################ +# void s390x_kmf(const unsigned char *in, size_t len, unsigned char *out, +# unsigned int fc, void *param) +{ +my ($in,$len,$out,$fc,$param) = map("%r$_",(2..6)); +$code.=<<___; +.globl s390x_kmf +.type s390x_kmf,\@function +.align 16 +s390x_kmf: + lr %r0,$fc + l${g}r %r1,$param + + .long 0xb92a0042 # kmf $out,$in + brc 1,.-4 # pay attention to "partial completion" + + br $ra +.size s390x_kmf,.-s390x_kmf +___ +} + ################ # void s390x_kma(const unsigned char *aad, size_t alen, # const unsigned char *in, size_t len,