s390x assembly pack: add KMF code path for aes-cfb/cfb8
authorPatrick Steuer <patrick.steuer@de.ibm.com>
Wed, 28 Mar 2018 12:09:24 +0000 (13:09 +0100)
committerAndy Polyakov <appro@openssl.org>
Wed, 28 Mar 2018 21:31:01 +0000 (23:31 +0200)
Signed-off-by: Patrick Steuer <patrick.steuer@de.ibm.com>
Reviewed-by: Richard Levitte <levitte@openssl.org>
Reviewed-by: Andy Polyakov <appro@openssl.org>
Reviewed-by: Rich Salz <rsalz@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/5250)

crypto/evp/e_aes.c
crypto/s390x_arch.h
crypto/s390xcpuid.pl

index 9309ec9..913242e 100644 (file)
@@ -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
index 236f936..5042154 100644 (file)
@@ -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);
 
index dfef2c1..e7afb8d 100755 (executable)
@@ -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,