Add S390 support for provider based X25519/X448
authorMatt Caswell <matt@openssl.org>
Tue, 4 Feb 2020 16:41:19 +0000 (16:41 +0000)
committerMatt Caswell <matt@openssl.org>
Tue, 11 Feb 2020 22:32:56 +0000 (22:32 +0000)
Reviewed-by: Patrick Steuer <patrick.steuer@de.ibm.com>
Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/10964)

crypto/ec/ecx_meth.c
include/crypto/ecx.h
providers/implementations/exchange/build.info
providers/implementations/exchange/ecx_exch.c

index 88787e0db6c749feea8eb99b27f375881075b567..32817562bf2db3bf045755ece43e9547ac12f262 100644 (file)
@@ -951,9 +951,9 @@ static void s390x_x448_mod_p(unsigned char u[56])
                                  u, u_red, sizeof(u_red));
 }
 
-static int s390x_x25519_mul(unsigned char u_dst[32],
-                            const unsigned char u_src[32],
-                            const unsigned char d_src[32])
+int s390x_x25519_mul(unsigned char u_dst[32],
+                     const unsigned char u_src[32],
+                     const unsigned char d_src[32])
 {
     union {
         struct {
@@ -984,9 +984,9 @@ static int s390x_x25519_mul(unsigned char u_dst[32],
     return rc;
 }
 
-static int s390x_x448_mul(unsigned char u_dst[56],
-                          const unsigned char u_src[56],
-                          const unsigned char d_src[56])
+int s390x_x448_mul(unsigned char u_dst[56],
+                   const unsigned char u_src[56],
+                   const unsigned char d_src[56])
 {
     union {
         struct {
index 3f0bbe1bb989f2c8c5dc4df1e7bcb7a8ac98abd5..e179db1b535cd7a47038ddc4bd56d8d819f9fd01 100644 (file)
@@ -63,5 +63,12 @@ int X448(uint8_t out_shared_key[56], const uint8_t private_key[56],
 void X448_public_from_private(uint8_t out_public_value[56],
                               const uint8_t private_key[56]);
 
+int s390x_x25519_mul(unsigned char u_dst[32],
+                     const unsigned char u_src[32],
+                     const unsigned char d_src[32]);
+int s390x_x448_mul(unsigned char u_dst[56],
+                   const unsigned char u_src[56],
+                   const unsigned char d_src[56]);
+
 # endif /* OPENSSL_NO_EC */
 #endif
index 0c2b98631b76e1196e1890042bd170ca5eb70583..c74e1228443fa2362c7845b595bc940e89136eab 100644 (file)
@@ -8,4 +8,16 @@ IF[{- !$disabled{dh} -}]
   SOURCE[$DH_GOAL]=dh_exch.c
 ENDIF
 
+IF[{- !$disabled{asm} -}]
+  $ECDEF_s390x=S390X_EC_ASM
+
+  # Now that we have defined all the arch specific variables, use the
+  # appropriate one, and define the appropriate macros
+  IF[$ECASM_{- $target{asm_arch} -}]
+    $ECDEF=$ECDEF_{- $target{asm_arch} -}
+  ENDIF
+ENDIF
+
+
 SOURCE[$ECX_GOAL]=ecx_exch.c
+DEFINE[$ECX_GOAL]=$ECDEF
index b7d1d9e3951247e7a94e48ac1326d429d9a373cc..ea12628937392fd4d420d2eb130bebbfcfc2f953 100644 (file)
@@ -16,6 +16,9 @@
 #include "crypto/ecx.h"
 #include "prov/implementations.h"
 #include "prov/providercommonerr.h"
+#ifdef S390X_EC_ASM
+# include "s390x_arch.h"
+#endif
 
 static OSSL_OP_keyexch_newctx_fn x25519_newctx;
 static OSSL_OP_keyexch_newctx_fn x448_newctx;
@@ -126,11 +129,31 @@ static int ecx_derive(void *vecxctx, unsigned char *secret, size_t *secretlen,
     }
 
     if (ecxctx->keylen == X25519_KEYLEN) {
+#ifdef S390X_EC_ASM
+        if (OPENSSL_s390xcap_P.pcc[1]
+                & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X25519)) {
+            if (s390x_x25519_mul(secret, ecxctx->peerkey->pubkey,
+                                 ecxctx->key->privkey) == 0) {
+                ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_DURING_DERIVATION);
+                return 0;
+            }
+        } else
+#endif
         if (X25519(secret, ecxctx->key->privkey, ecxctx->peerkey->pubkey) == 0) {
             ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_DURING_DERIVATION);
             return 0;
         }
     } else {
+#ifdef S390X_EC_ASM
+        if (OPENSSL_s390xcap_P.pcc[1]
+                & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X448)) {
+            if (s390x_x448_mul(secret, ecxctx->peerkey->pubkey,
+                               ecxctx->key->privkey) == 0) {
+                ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_DURING_DERIVATION);
+                return 0;
+            }
+        } else
+#endif
         if (X448(secret, ecxctx->key->privkey, ecxctx->peerkey->pubkey) == 0) {
             ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_DURING_DERIVATION);
             return 0;