[openssl] master update

patrick.steuer at de.ibm.com patrick.steuer at de.ibm.com
Thu Aug 15 14:35:32 UTC 2019


The branch master has been updated
       via  3ded2288a45d2cc3a27a1b08d29499cbcec52c0e (commit)
       via  58c35587eacba090414522a6506cb86f2d0e91af (commit)
       via  9bf682f62bd819d2fbceb95eeabd61dd4532240f (commit)
       via  1461e66706f24da657d7322706d1165ae515533f (commit)
       via  9baa4d5f4c9f596faba2b3e219b367a09c472d1d (commit)
      from  5bf2eade559a0d3081013048b1373da460701ba5 (commit)


- Log -----------------------------------------------------------------
commit 3ded2288a45d2cc3a27a1b08d29499cbcec52c0e
Author: Patrick Steuer <patrick.steuer at de.ibm.com>
Date:   Fri Jul 12 13:47:32 2019 +0200

    OPENSSL_s390xcap.pod: list msa9 facility bit (155)
    
    Signed-off-by: Patrick Steuer <patrick.steuer at de.ibm.com>
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/9348)

commit 58c35587eacba090414522a6506cb86f2d0e91af
Author: Patrick Steuer <patrick.steuer at de.ibm.com>
Date:   Thu Jul 11 10:38:18 2019 +0200

    s390x assembly pack: accelerate ECDSA
    
    for NIST P-256, P-384 and P-521 using KDSA instruction.
    
    Signed-off-by: Patrick Steuer <patrick.steuer at de.ibm.com>
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/9348)

commit 9bf682f62bd819d2fbceb95eeabd61dd4532240f
Author: Patrick Steuer <patrick.steuer at de.ibm.com>
Date:   Thu Jul 11 10:23:49 2019 +0200

    Enable curve-spefific ECDSA implementations via EC_METHOD
    
    which are already enabled for ECDH.
    
    Signed-off-by: Patrick Steuer <patrick.steuer at de.ibm.com>
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/9348)

commit 1461e66706f24da657d7322706d1165ae515533f
Author: Patrick Steuer <patrick.steuer at de.ibm.com>
Date:   Tue Jul 9 10:25:04 2019 +0200

    s390x assembly pack: accelerate scalar multiplication
    
    for NIST P-256, P-384 and P-521 using PCC instruction.
    
    Signed-off-by: Patrick Steuer <patrick.steuer at de.ibm.com>
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/9348)

commit 9baa4d5f4c9f596faba2b3e219b367a09c472d1d
Author: Patrick Steuer <patrick.steuer at de.ibm.com>
Date:   Wed Jul 3 18:02:11 2019 +0200

    s390xcpuid.pl: fix comment
    
    Signed-off-by: Patrick Steuer <patrick.steuer at de.ibm.com>
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/9348)

-----------------------------------------------------------------------

Summary of changes:
 crypto/ec/build.info          |   3 +-
 crypto/ec/ec2_smpl.c          |   3 +
 crypto/ec/ec_curve.c          |  42 +++--
 crypto/ec/ec_lcl.h            |  20 +++
 crypto/ec/ecdsa_ossl.c        | 107 ++++++++----
 crypto/ec/ecp_mont.c          |   3 +
 crypto/ec/ecp_nist.c          |   3 +
 crypto/ec/ecp_nistp224.c      |   3 +
 crypto/ec/ecp_nistp256.c      |   3 +
 crypto/ec/ecp_nistp521.c      |   3 +
 crypto/ec/ecp_nistz256.c      |   3 +
 crypto/ec/ecp_s390x_nistp.c   | 394 ++++++++++++++++++++++++++++++++++++++++++
 crypto/ec/ecp_smpl.c          |   3 +
 crypto/err/openssl.txt        |   7 +
 crypto/s390xcpuid.pl          |   6 +-
 doc/man3/OPENSSL_s390xcap.pod |   1 +
 include/openssl/ecerr.h       |   1 +
 17 files changed, 553 insertions(+), 52 deletions(-)
 create mode 100644 crypto/ec/ecp_s390x_nistp.c

diff --git a/crypto/ec/build.info b/crypto/ec/build.info
index 6bc04588e2..449172c704 100644
--- a/crypto/ec/build.info
+++ b/crypto/ec/build.info
@@ -18,7 +18,8 @@ IF[{- !$disabled{asm} -}]
   $ECASM_mips32=
   $ECASM_mips64=
 
-  $ECASM_s390x=
+  $ECASM_s390x=ecp_s390x_nistp.c
+  $ECDEF_s390x=S390X_NISTP_ASM
 
   $ECASM_armv4=ecp_nistz256.c ecp_nistz256-armv4.S
   $ECDEF_armv4=ECP_NISTZ256_ASM
diff --git a/crypto/ec/ec2_smpl.c b/crypto/ec/ec2_smpl.c
index 0cc9c893f8..f377b1f11e 100644
--- a/crypto/ec/ec2_smpl.c
+++ b/crypto/ec/ec2_smpl.c
@@ -984,6 +984,9 @@ const EC_METHOD *EC_GF2m_simple_method(void)
         0, /* keycopy */
         0, /* keyfinish */
         ecdh_simple_compute_key,
+        ecdsa_simple_sign_setup,
+        ecdsa_simple_sign_sig,
+        ecdsa_simple_verify_sig,
         0, /* field_inverse_mod_ord */
         0, /* blind_coordinates */
         ec_GF2m_simple_ladder_pre,
diff --git a/crypto/ec/ec_curve.c b/crypto/ec/ec_curve.c
index e9dac78224..f3a526f126 100644
--- a/crypto/ec/ec_curve.c
+++ b/crypto/ec/ec_curve.c
@@ -2828,16 +2828,23 @@ static const ec_list_element curve_list[] = {
      "NIST/SECG curve over a 224 bit prime field"},
 # endif
     /* SECG secp256r1 is the same as X9.62 prime256v1 and hence omitted */
-    {NID_secp384r1, &_EC_NIST_PRIME_384.h, 0,
+    {NID_secp384r1, &_EC_NIST_PRIME_384.h,
+# if defined(S390X_NISTP_ASM)
+     EC_GFp_s390x_nistp384_method,
+# else
+     0,
+# endif
      "NIST/SECG curve over a 384 bit prime field"},
 
-# ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
-    {NID_secp521r1, &_EC_NIST_PRIME_521.h, EC_GFp_nistp521_method,
-     "NIST/SECG curve over a 521 bit prime field"},
+    {NID_secp521r1, &_EC_NIST_PRIME_521.h,
+# if defined(S390X_NISTP_ASM)
+     EC_GFp_s390x_nistp521_method,
+# elif !defined(OPENSSL_NO_EC_NISTP_64_GCC_128)
+     EC_GFp_nistp521_method,
 # else
-    {NID_secp521r1, &_EC_NIST_PRIME_521.h, 0,
-     "NIST/SECG curve over a 521 bit prime field"},
+     0,
 # endif
+     "NIST/SECG curve over a 521 bit prime field"},
 
     /* X9.62 curves */
     {NID_X9_62_prime192v1, &_EC_NIST_PRIME_192.h, 0,
@@ -2845,6 +2852,8 @@ static const ec_list_element curve_list[] = {
     {NID_X9_62_prime256v1, &_EC_X9_62_PRIME_256V1.h,
 # if defined(ECP_NISTZ256_ASM)
      EC_GFp_nistz256_method,
+# elif defined(S390X_NISTP_ASM)
+     EC_GFp_s390x_nistp256_method,
 # elif !defined(OPENSSL_NO_EC_NISTP_64_GCC_128)
      EC_GFp_nistp256_method,
 # else
@@ -2912,15 +2921,22 @@ static const ec_list_element curve_list[] = {
     {NID_secp256k1, &_EC_SECG_PRIME_256K1.h, 0,
      "SECG curve over a 256 bit prime field"},
     /* SECG secp256r1 is the same as X9.62 prime256v1 and hence omitted */
-    {NID_secp384r1, &_EC_NIST_PRIME_384.h, 0,
+    {NID_secp384r1, &_EC_NIST_PRIME_384.h,
+# if defined(S390X_NISTP_ASM)
+     EC_GFp_s390x_nistp384_method,
+# else
+     0,
+# endif
      "NIST/SECG curve over a 384 bit prime field"},
-# ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
-    {NID_secp521r1, &_EC_NIST_PRIME_521.h, EC_GFp_nistp521_method,
-     "NIST/SECG curve over a 521 bit prime field"},
+    {NID_secp521r1, &_EC_NIST_PRIME_521.h,
+# if defined(S390X_NISTP_ASM)
+     EC_GFp_s390x_nistp521_method,
+# elif !defined(OPENSSL_NO_EC_NISTP_64_GCC_128)
+     EC_GFp_nistp521_method,
 # else
-    {NID_secp521r1, &_EC_NIST_PRIME_521.h, 0,
-     "NIST/SECG curve over a 521 bit prime field"},
+     0,
 # endif
+     "NIST/SECG curve over a 521 bit prime field"},
     /* X9.62 curves */
     {NID_X9_62_prime192v1, &_EC_NIST_PRIME_192.h, 0,
      "NIST/X9.62/SECG curve over a 192 bit prime field"},
@@ -2937,6 +2953,8 @@ static const ec_list_element curve_list[] = {
     {NID_X9_62_prime256v1, &_EC_X9_62_PRIME_256V1.h,
 # if defined(ECP_NISTZ256_ASM)
      EC_GFp_nistz256_method,
+# elif defined(S390X_NISTP_ASM)
+     EC_GFp_s390x_nistp256_method,
 # elif !defined(OPENSSL_NO_EC_NISTP_64_GCC_128)
      EC_GFp_nistp256_method,
 # else
diff --git a/crypto/ec/ec_lcl.h b/crypto/ec/ec_lcl.h
index 2ff46b6ca6..5dd4d0318c 100644
--- a/crypto/ec/ec_lcl.h
+++ b/crypto/ec/ec_lcl.h
@@ -179,6 +179,14 @@ struct ec_method_st {
     /* custom ECDH operation */
     int (*ecdh_compute_key)(unsigned char **pout, size_t *poutlen,
                             const EC_POINT *pub_key, const EC_KEY *ecdh);
+    /* custom ECDSA */
+    int (*ecdsa_sign_setup)(EC_KEY *eckey, BN_CTX *ctx, BIGNUM **kinvp,
+                            BIGNUM **rp);
+    ECDSA_SIG *(*ecdsa_sign_sig)(const unsigned char *dgst, int dgstlen,
+                                 const BIGNUM *kinv, const BIGNUM *r,
+                                 EC_KEY *eckey);
+    int (*ecdsa_verify_sig)(const unsigned char *dgst, int dgstlen,
+                            const ECDSA_SIG *sig, EC_KEY *eckey);
     /* Inverse modulo order */
     int (*field_inverse_mod_ord)(const EC_GROUP *, BIGNUM *r,
                                  const BIGNUM *x, BN_CTX *);
@@ -589,6 +597,11 @@ int ec_group_simple_order_bits(const EC_GROUP *group);
  */
 const EC_METHOD *EC_GFp_nistz256_method(void);
 #endif
+#ifdef S390X_NISTP_ASM
+const EC_METHOD *EC_GFp_s390x_nistp256_method(void);
+const EC_METHOD *EC_GFp_s390x_nistp384_method(void);
+const EC_METHOD *EC_GFp_s390x_nistp521_method(void);
+#endif
 
 size_t ec_key_simple_priv2oct(const EC_KEY *eckey,
                               unsigned char *buf, size_t len);
@@ -655,6 +668,13 @@ int ossl_ecdsa_verify(int type, const unsigned char *dgst, int dgst_len,
                       const unsigned char *sigbuf, int sig_len, EC_KEY *eckey);
 int ossl_ecdsa_verify_sig(const unsigned char *dgst, int dgst_len,
                           const ECDSA_SIG *sig, EC_KEY *eckey);
+int ecdsa_simple_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp,
+                            BIGNUM **rp);
+ECDSA_SIG *ecdsa_simple_sign_sig(const unsigned char *dgst, int dgst_len,
+                                 const BIGNUM *in_kinv, const BIGNUM *in_r,
+                                 EC_KEY *eckey);
+int ecdsa_simple_verify_sig(const unsigned char *dgst, int dgst_len,
+                            const ECDSA_SIG *sig, EC_KEY *eckey);
 
 int ED25519_sign(uint8_t *out_sig, const uint8_t *message, size_t message_len,
                  const uint8_t public_key[32], const uint8_t private_key[32]);
diff --git a/crypto/ec/ecdsa_ossl.c b/crypto/ec/ecdsa_ossl.c
index 86bdc87721..afa65233be 100644
--- a/crypto/ec/ecdsa_ossl.c
+++ b/crypto/ec/ecdsa_ossl.c
@@ -14,6 +14,41 @@
 #include "internal/bn_int.h"
 #include "ec_lcl.h"
 
+int ossl_ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp,
+                          BIGNUM **rp)
+{
+    if (eckey->group->meth->ecdsa_sign_setup == NULL) {
+        ECerr(EC_F_OSSL_ECDSA_SIGN_SETUP, EC_R_CURVE_DOES_NOT_SUPPORT_ECDSA);
+        return 0;
+    }
+
+    return eckey->group->meth->ecdsa_sign_setup(eckey, ctx_in, kinvp, rp);
+}
+
+ECDSA_SIG *ossl_ecdsa_sign_sig(const unsigned char *dgst, int dgst_len,
+                               const BIGNUM *in_kinv, const BIGNUM *in_r,
+                               EC_KEY *eckey)
+{
+    if (eckey->group->meth->ecdsa_sign_sig == NULL) {
+        ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, EC_R_CURVE_DOES_NOT_SUPPORT_ECDSA);
+        return NULL;
+    }
+
+    return eckey->group->meth->ecdsa_sign_sig(dgst, dgst_len,
+                                              in_kinv, in_r, eckey);
+}
+
+int ossl_ecdsa_verify_sig(const unsigned char *dgst, int dgst_len,
+                          const ECDSA_SIG *sig, EC_KEY *eckey)
+{
+    if (eckey->group->meth->ecdsa_verify_sig == NULL) {
+        ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, EC_R_CURVE_DOES_NOT_SUPPORT_ECDSA);
+        return 0;
+    }
+
+    return eckey->group->meth->ecdsa_verify_sig(dgst, dgst_len, sig, eckey);
+}
+
 int ossl_ecdsa_sign(int type, const unsigned char *dgst, int dlen,
                     unsigned char *sig, unsigned int *siglen,
                     const BIGNUM *kinv, const BIGNUM *r, EC_KEY *eckey)
@@ -145,15 +180,15 @@ static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in,
     return ret;
 }
 
-int ossl_ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp,
-                          BIGNUM **rp)
+int ecdsa_simple_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp,
+                            BIGNUM **rp)
 {
     return ecdsa_sign_setup(eckey, ctx_in, kinvp, rp, NULL, 0);
 }
 
-ECDSA_SIG *ossl_ecdsa_sign_sig(const unsigned char *dgst, int dgst_len,
-                               const BIGNUM *in_kinv, const BIGNUM *in_r,
-                               EC_KEY *eckey)
+ECDSA_SIG *ecdsa_simple_sign_sig(const unsigned char *dgst, int dgst_len,
+                                 const BIGNUM *in_kinv, const BIGNUM *in_r,
+                                 EC_KEY *eckey)
 {
     int ok = 0, i;
     BIGNUM *kinv = NULL, *s, *m = NULL;
@@ -167,35 +202,35 @@ ECDSA_SIG *ossl_ecdsa_sign_sig(const unsigned char *dgst, int dgst_len,
     priv_key = EC_KEY_get0_private_key(eckey);
 
     if (group == NULL) {
-        ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_PASSED_NULL_PARAMETER);
+        ECerr(EC_F_ECDSA_SIMPLE_SIGN_SIG, ERR_R_PASSED_NULL_PARAMETER);
         return NULL;
     }
     if (priv_key == NULL) {
-        ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, EC_R_MISSING_PRIVATE_KEY);
+        ECerr(EC_F_ECDSA_SIMPLE_SIGN_SIG, EC_R_MISSING_PRIVATE_KEY);
         return NULL;
     }
 
     if (!EC_KEY_can_sign(eckey)) {
-        ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, EC_R_CURVE_DOES_NOT_SUPPORT_SIGNING);
+        ECerr(EC_F_ECDSA_SIMPLE_SIGN_SIG, EC_R_CURVE_DOES_NOT_SUPPORT_SIGNING);
         return NULL;
     }
 
     ret = ECDSA_SIG_new();
     if (ret == NULL) {
-        ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_MALLOC_FAILURE);
+        ECerr(EC_F_ECDSA_SIMPLE_SIGN_SIG, ERR_R_MALLOC_FAILURE);
         return NULL;
     }
     ret->r = BN_new();
     ret->s = BN_new();
     if (ret->r == NULL || ret->s == NULL) {
-        ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_MALLOC_FAILURE);
+        ECerr(EC_F_ECDSA_SIMPLE_SIGN_SIG, ERR_R_MALLOC_FAILURE);
         goto err;
     }
     s = ret->s;
 
     if ((ctx = BN_CTX_new_ex(eckey->libctx)) == NULL
         || (m = BN_new()) == NULL) {
-        ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_MALLOC_FAILURE);
+        ECerr(EC_F_ECDSA_SIMPLE_SIGN_SIG, ERR_R_MALLOC_FAILURE);
         goto err;
     }
 
@@ -207,25 +242,25 @@ ECDSA_SIG *ossl_ecdsa_sign_sig(const unsigned char *dgst, int dgst_len,
     if (8 * dgst_len > i)
         dgst_len = (i + 7) / 8;
     if (!BN_bin2bn(dgst, dgst_len, m)) {
-        ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_BN_LIB);
+        ECerr(EC_F_ECDSA_SIMPLE_SIGN_SIG, ERR_R_BN_LIB);
         goto err;
     }
     /* If still too long, truncate remaining bits with a shift */
     if ((8 * dgst_len > i) && !BN_rshift(m, m, 8 - (i & 0x7))) {
-        ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_BN_LIB);
+        ECerr(EC_F_ECDSA_SIMPLE_SIGN_SIG, ERR_R_BN_LIB);
         goto err;
     }
     do {
         if (in_kinv == NULL || in_r == NULL) {
             if (!ecdsa_sign_setup(eckey, ctx, &kinv, &ret->r, dgst, dgst_len)) {
-                ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_ECDSA_LIB);
+                ECerr(EC_F_ECDSA_SIMPLE_SIGN_SIG, ERR_R_ECDSA_LIB);
                 goto err;
             }
             ckinv = kinv;
         } else {
             ckinv = in_kinv;
             if (BN_copy(ret->r, in_r) == NULL) {
-                ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_MALLOC_FAILURE);
+                ECerr(EC_F_ECDSA_SIMPLE_SIGN_SIG, ERR_R_MALLOC_FAILURE);
                 goto err;
             }
         }
@@ -239,11 +274,11 @@ ECDSA_SIG *ossl_ecdsa_sign_sig(const unsigned char *dgst, int dgst_len,
          */
         if (!bn_to_mont_fixed_top(s, ret->r, group->mont_data, ctx)
             || !bn_mul_mont_fixed_top(s, s, priv_key, group->mont_data, ctx)) {
-            ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_BN_LIB);
+            ECerr(EC_F_ECDSA_SIMPLE_SIGN_SIG, ERR_R_BN_LIB);
             goto err;
         }
         if (!bn_mod_add_fixed_top(s, s, m, order)) {
-            ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_BN_LIB);
+            ECerr(EC_F_ECDSA_SIMPLE_SIGN_SIG, ERR_R_BN_LIB);
             goto err;
         }
         /*
@@ -252,7 +287,7 @@ ECDSA_SIG *ossl_ecdsa_sign_sig(const unsigned char *dgst, int dgst_len,
          */
         if (!bn_to_mont_fixed_top(s, s, group->mont_data, ctx)
             || !BN_mod_mul_montgomery(s, s, ckinv, group->mont_data, ctx)) {
-            ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_BN_LIB);
+            ECerr(EC_F_ECDSA_SIMPLE_SIGN_SIG, ERR_R_BN_LIB);
             goto err;
         }
 
@@ -262,7 +297,7 @@ ECDSA_SIG *ossl_ecdsa_sign_sig(const unsigned char *dgst, int dgst_len,
              * generate new kinv and r values
              */
             if (in_kinv != NULL && in_r != NULL) {
-                ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, EC_R_NEED_NEW_SETUP_VALUES);
+                ECerr(EC_F_ECDSA_SIMPLE_SIGN_SIG, EC_R_NEED_NEW_SETUP_VALUES);
                 goto err;
             }
         } else {
@@ -314,8 +349,8 @@ int ossl_ecdsa_verify(int type, const unsigned char *dgst, int dgst_len,
     return ret;
 }
 
-int ossl_ecdsa_verify_sig(const unsigned char *dgst, int dgst_len,
-                          const ECDSA_SIG *sig, EC_KEY *eckey)
+int ecdsa_simple_verify_sig(const unsigned char *dgst, int dgst_len,
+                            const ECDSA_SIG *sig, EC_KEY *eckey)
 {
     int ret = -1, i;
     BN_CTX *ctx;
@@ -328,18 +363,18 @@ int ossl_ecdsa_verify_sig(const unsigned char *dgst, int dgst_len,
     /* check input values */
     if (eckey == NULL || (group = EC_KEY_get0_group(eckey)) == NULL ||
         (pub_key = EC_KEY_get0_public_key(eckey)) == NULL || sig == NULL) {
-        ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, EC_R_MISSING_PARAMETERS);
+        ECerr(EC_F_ECDSA_SIMPLE_VERIFY_SIG, EC_R_MISSING_PARAMETERS);
         return -1;
     }
 
     if (!EC_KEY_can_sign(eckey)) {
-        ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, EC_R_CURVE_DOES_NOT_SUPPORT_SIGNING);
+        ECerr(EC_F_ECDSA_SIMPLE_VERIFY_SIG, EC_R_CURVE_DOES_NOT_SUPPORT_SIGNING);
         return -1;
     }
 
     ctx = BN_CTX_new_ex(eckey->libctx);
     if (ctx == NULL) {
-        ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_MALLOC_FAILURE);
+        ECerr(EC_F_ECDSA_SIMPLE_VERIFY_SIG, ERR_R_MALLOC_FAILURE);
         return -1;
     }
     BN_CTX_start(ctx);
@@ -348,26 +383,26 @@ int ossl_ecdsa_verify_sig(const unsigned char *dgst, int dgst_len,
     m = BN_CTX_get(ctx);
     X = BN_CTX_get(ctx);
     if (X == NULL) {
-        ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_BN_LIB);
+        ECerr(EC_F_ECDSA_SIMPLE_VERIFY_SIG, ERR_R_BN_LIB);
         goto err;
     }
 
     order = EC_GROUP_get0_order(group);
     if (order == NULL) {
-        ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_EC_LIB);
+        ECerr(EC_F_ECDSA_SIMPLE_VERIFY_SIG, ERR_R_EC_LIB);
         goto err;
     }
 
     if (BN_is_zero(sig->r) || BN_is_negative(sig->r) ||
         BN_ucmp(sig->r, order) >= 0 || BN_is_zero(sig->s) ||
         BN_is_negative(sig->s) || BN_ucmp(sig->s, order) >= 0) {
-        ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, EC_R_BAD_SIGNATURE);
+        ECerr(EC_F_ECDSA_SIMPLE_VERIFY_SIG, EC_R_BAD_SIGNATURE);
         ret = 0;                /* signature is invalid */
         goto err;
     }
     /* calculate tmp1 = inv(S) mod order */
     if (!ec_group_do_inverse_ord(group, u2, sig->s, ctx)) {
-        ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_BN_LIB);
+        ECerr(EC_F_ECDSA_SIMPLE_VERIFY_SIG, ERR_R_BN_LIB);
         goto err;
     }
     /* digest -> m */
@@ -378,41 +413,41 @@ int ossl_ecdsa_verify_sig(const unsigned char *dgst, int dgst_len,
     if (8 * dgst_len > i)
         dgst_len = (i + 7) / 8;
     if (!BN_bin2bn(dgst, dgst_len, m)) {
-        ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_BN_LIB);
+        ECerr(EC_F_ECDSA_SIMPLE_VERIFY_SIG, ERR_R_BN_LIB);
         goto err;
     }
     /* If still too long truncate remaining bits with a shift */
     if ((8 * dgst_len > i) && !BN_rshift(m, m, 8 - (i & 0x7))) {
-        ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_BN_LIB);
+        ECerr(EC_F_ECDSA_SIMPLE_VERIFY_SIG, ERR_R_BN_LIB);
         goto err;
     }
     /* u1 = m * tmp mod order */
     if (!BN_mod_mul(u1, m, u2, order, ctx)) {
-        ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_BN_LIB);
+        ECerr(EC_F_ECDSA_SIMPLE_VERIFY_SIG, ERR_R_BN_LIB);
         goto err;
     }
     /* u2 = r * w mod q */
     if (!BN_mod_mul(u2, sig->r, u2, order, ctx)) {
-        ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_BN_LIB);
+        ECerr(EC_F_ECDSA_SIMPLE_VERIFY_SIG, ERR_R_BN_LIB);
         goto err;
     }
 
     if ((point = EC_POINT_new(group)) == NULL) {
-        ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_MALLOC_FAILURE);
+        ECerr(EC_F_ECDSA_SIMPLE_VERIFY_SIG, ERR_R_MALLOC_FAILURE);
         goto err;
     }
     if (!EC_POINT_mul(group, point, u1, pub_key, u2, ctx)) {
-        ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_EC_LIB);
+        ECerr(EC_F_ECDSA_SIMPLE_VERIFY_SIG, ERR_R_EC_LIB);
         goto err;
     }
 
     if (!EC_POINT_get_affine_coordinates(group, point, X, NULL, ctx)) {
-        ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_EC_LIB);
+        ECerr(EC_F_ECDSA_SIMPLE_VERIFY_SIG, ERR_R_EC_LIB);
         goto err;
     }
 
     if (!BN_nnmod(u1, X, order, ctx)) {
-        ECerr(EC_F_OSSL_ECDSA_VERIFY_SIG, ERR_R_BN_LIB);
+        ECerr(EC_F_ECDSA_SIMPLE_VERIFY_SIG, ERR_R_BN_LIB);
         goto err;
     }
     /*  if the signature is correct u1 is equal to sig->r */
diff --git a/crypto/ec/ecp_mont.c b/crypto/ec/ecp_mont.c
index 308b30629d..61a203c178 100644
--- a/crypto/ec/ecp_mont.c
+++ b/crypto/ec/ecp_mont.c
@@ -63,6 +63,9 @@ const EC_METHOD *EC_GFp_mont_method(void)
         0, /* keycopy */
         0, /* keyfinish */
         ecdh_simple_compute_key,
+        ecdsa_simple_sign_setup,
+        ecdsa_simple_sign_sig,
+        ecdsa_simple_verify_sig,
         0, /* field_inverse_mod_ord */
         ec_GFp_simple_blind_coordinates,
         ec_GFp_simple_ladder_pre,
diff --git a/crypto/ec/ecp_nist.c b/crypto/ec/ecp_nist.c
index 13249b52de..99cc74b66d 100644
--- a/crypto/ec/ecp_nist.c
+++ b/crypto/ec/ecp_nist.c
@@ -65,6 +65,9 @@ const EC_METHOD *EC_GFp_nist_method(void)
         0, /* keycopy */
         0, /* keyfinish */
         ecdh_simple_compute_key,
+        ecdsa_simple_sign_setup,
+        ecdsa_simple_sign_sig,
+        ecdsa_simple_verify_sig,
         0, /* field_inverse_mod_ord */
         ec_GFp_simple_blind_coordinates,
         ec_GFp_simple_ladder_pre,
diff --git a/crypto/ec/ecp_nistp224.c b/crypto/ec/ecp_nistp224.c
index 2ad9903c90..89ea039b2c 100644
--- a/crypto/ec/ecp_nistp224.c
+++ b/crypto/ec/ecp_nistp224.c
@@ -291,6 +291,9 @@ const EC_METHOD *EC_GFp_nistp224_method(void)
         ec_key_simple_generate_public_key,
         0, /* keycopy */
         0, /* keyfinish */
+        ecdsa_simple_sign_setup,
+        ecdsa_simple_sign_sig,
+        ecdsa_simple_verify_sig,
         ecdh_simple_compute_key,
         0, /* field_inverse_mod_ord */
         0, /* blind_coordinates */
diff --git a/crypto/ec/ecp_nistp256.c b/crypto/ec/ecp_nistp256.c
index 624ee1621f..3cc5a833a4 100644
--- a/crypto/ec/ecp_nistp256.c
+++ b/crypto/ec/ecp_nistp256.c
@@ -1823,6 +1823,9 @@ const EC_METHOD *EC_GFp_nistp256_method(void)
         0, /* keycopy */
         0, /* keyfinish */
         ecdh_simple_compute_key,
+        ecdsa_simple_sign_setup,
+        ecdsa_simple_sign_sig,
+        ecdsa_simple_verify_sig,
         0, /* field_inverse_mod_ord */
         0, /* blind_coordinates */
         0, /* ladder_pre */
diff --git a/crypto/ec/ecp_nistp521.c b/crypto/ec/ecp_nistp521.c
index 6de37f663b..29b943598d 100644
--- a/crypto/ec/ecp_nistp521.c
+++ b/crypto/ec/ecp_nistp521.c
@@ -1665,6 +1665,9 @@ const EC_METHOD *EC_GFp_nistp521_method(void)
         0, /* keycopy */
         0, /* keyfinish */
         ecdh_simple_compute_key,
+        ecdsa_simple_sign_setup,
+        ecdsa_simple_sign_sig,
+        ecdsa_simple_verify_sig,
         0, /* field_inverse_mod_ord */
         0, /* blind_coordinates */
         0, /* ladder_pre */
diff --git a/crypto/ec/ecp_nistz256.c b/crypto/ec/ecp_nistz256.c
index df1724c385..a09e9c5d99 100644
--- a/crypto/ec/ecp_nistz256.c
+++ b/crypto/ec/ecp_nistz256.c
@@ -1689,6 +1689,9 @@ const EC_METHOD *EC_GFp_nistz256_method(void)
         0, /* keycopy */
         0, /* keyfinish */
         ecdh_simple_compute_key,
+        ecdsa_simple_sign_setup,
+        ecdsa_simple_sign_sig,
+        ecdsa_simple_verify_sig,
         ecp_nistz256_inv_mod_ord,                   /* can be #define-d NULL */
         0,                                          /* blind_coordinates */
         0,                                          /* ladder_pre */
diff --git a/crypto/ec/ecp_s390x_nistp.c b/crypto/ec/ecp_s390x_nistp.c
new file mode 100644
index 0000000000..be81f0b8f0
--- /dev/null
+++ b/crypto/ec/ecp_s390x_nistp.c
@@ -0,0 +1,394 @@
+/*
+ * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <openssl/err.h>
+#include <openssl/rand.h>
+#include "ec_lcl.h"
+#include "s390x_arch.h"
+
+/* Size of parameter blocks */
+#define S390X_SIZE_PARAM                4096
+
+/* Size of fields in parameter blocks */
+#define S390X_SIZE_P256                 32
+#define S390X_SIZE_P384                 48
+#define S390X_SIZE_P521                 80
+
+/* Offsets of fields in PCC parameter blocks */
+#define S390X_OFF_RES_X(n)              (0 * n)
+#define S390X_OFF_RES_Y(n)              (1 * n)
+#define S390X_OFF_SRC_X(n)              (2 * n)
+#define S390X_OFF_SRC_Y(n)              (3 * n)
+#define S390X_OFF_SCALAR(n)             (4 * n)
+
+/* Offsets of fields in KDSA parameter blocks */
+#define S390X_OFF_R(n)                  (0 * n)
+#define S390X_OFF_S(n)                  (1 * n)
+#define S390X_OFF_H(n)                  (2 * n)
+#define S390X_OFF_K(n)                  (3 * n)
+#define S390X_OFF_X(n)                  (3 * n)
+#define S390X_OFF_RN(n)                 (4 * n)
+#define S390X_OFF_Y(n)                  (4 * n)
+
+static int ec_GFp_s390x_nistp_mul(const EC_GROUP *group, EC_POINT *r,
+                                  const BIGNUM *scalar,
+                                  size_t num, const EC_POINT *points[],
+                                  const BIGNUM *scalars[],
+                                  BN_CTX *ctx, unsigned int fc, int len)
+{
+    unsigned char param[S390X_SIZE_PARAM];
+    BIGNUM *x, *y;
+    const EC_POINT *point_ptr = NULL;
+    const BIGNUM *scalar_ptr = NULL;
+    BN_CTX *new_ctx = NULL;
+    int rc = -1;
+
+    if (ctx == NULL) {
+        ctx = new_ctx = BN_CTX_new_ex(group->libctx);
+        if (ctx == NULL)
+            return 0;
+    }
+
+    BN_CTX_start(ctx);
+
+    x = BN_CTX_get(ctx);
+    y = BN_CTX_get(ctx);
+    if (x == NULL || y == NULL) {
+        rc = 0;
+        goto ret;
+    }
+
+    /*
+     * Use PCC for EC keygen and ECDH key derivation:
+     * scalar * generator and scalar * peer public key,
+     * scalar in [0,order).
+     */
+    if ((scalar != NULL && num == 0 && BN_is_negative(scalar) == 0)
+        || (scalar == NULL && num == 1 && BN_is_negative(scalars[0]) == 0)) {
+
+        if (num == 0) {
+            point_ptr = EC_GROUP_get0_generator(group);
+            scalar_ptr = scalar;
+        } else {
+            point_ptr = points[0];
+            scalar_ptr = scalars[0];
+        }
+
+        if (EC_POINT_is_at_infinity(group, point_ptr) == 1
+            || BN_is_zero(scalar_ptr)) {
+            rc = EC_POINT_set_to_infinity(group, r);
+            goto ret;
+        }
+
+        memset(&param, 0, sizeof(param));
+
+        if (group->meth->point_get_affine_coordinates(group, point_ptr,
+                                                      x, y, ctx) != 1
+            || BN_bn2binpad(x, param + S390X_OFF_SRC_X(len), len) == -1
+            || BN_bn2binpad(y, param + S390X_OFF_SRC_Y(len), len) == -1
+            || BN_bn2binpad(scalar_ptr,
+                            param + S390X_OFF_SCALAR(len), len) == -1
+            || s390x_pcc(fc, param) != 0
+            || BN_bin2bn(param + S390X_OFF_RES_X(len), len, x) == NULL
+            || BN_bin2bn(param + S390X_OFF_RES_Y(len), len, y) == NULL
+            || group->meth->point_set_affine_coordinates(group, r,
+                                                         x, y, ctx) != 1)
+            goto ret;
+
+        rc = 1;
+    }
+
+ret:
+    /* Otherwise use default. */
+    if (rc == -1)
+        rc = ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx);
+    OPENSSL_cleanse(param, sizeof(param));
+    BN_CTX_end(ctx);
+    BN_CTX_free(new_ctx);
+    return rc;
+}
+
+static ECDSA_SIG *ecdsa_s390x_nistp_sign_sig(const unsigned char *dgst,
+                                             int dgstlen,
+                                             const BIGNUM *kinv,
+                                             const BIGNUM *r,
+                                             EC_KEY *eckey,
+                                             unsigned int fc, int len)
+{
+    unsigned char param[S390X_SIZE_PARAM];
+    int ok = 0;
+    BIGNUM *k;
+    ECDSA_SIG *sig;
+    const EC_GROUP *group;
+    const BIGNUM *privkey;
+    int off;
+
+    group = EC_KEY_get0_group(eckey);
+    privkey = EC_KEY_get0_private_key(eckey);
+    if (group == NULL || privkey == NULL) {
+        ECerr(EC_F_ECDSA_S390X_NISTP_SIGN_SIG, EC_R_MISSING_PARAMETERS);
+        return NULL;
+    }
+
+    if (!EC_KEY_can_sign(eckey)) {
+        ECerr(EC_F_ECDSA_S390X_NISTP_SIGN_SIG,
+              EC_R_CURVE_DOES_NOT_SUPPORT_SIGNING);
+        return NULL;
+    }
+
+    k = BN_secure_new();
+    sig = ECDSA_SIG_new();
+    if (k == NULL || sig == NULL) {
+        ECerr(EC_F_ECDSA_S390X_NISTP_SIGN_SIG, ERR_R_MALLOC_FAILURE);
+        goto ret;
+    }
+
+    sig->r = BN_new();
+    sig->s = BN_new();
+    if (sig->r == NULL || sig->s == NULL) {
+        ECerr(EC_F_ECDSA_S390X_NISTP_SIGN_SIG, ERR_R_MALLOC_FAILURE);
+        goto ret;
+    }
+
+    memset(param, 0, sizeof(param));
+    off = len - (dgstlen > len ? len : dgstlen);
+    memcpy(param + S390X_OFF_H(len) + off, dgst, len - off);
+
+    if (BN_bn2binpad(privkey, param + S390X_OFF_K(len), len) == -1) {
+        ECerr(EC_F_ECDSA_S390X_NISTP_SIGN_SIG, ERR_R_BN_LIB);
+        goto ret;
+    }
+
+    if (r == NULL || kinv == NULL) {
+        /*
+         * Generate random k and copy to param param block. RAND_priv_bytes
+         * is used instead of BN_priv_rand_range or BN_generate_dsa_nonce
+         * because kdsa instruction constructs an in-range, invertible nonce
+         * internally implementing counter-measures for RNG weakness.
+         */
+         if (RAND_priv_bytes(param + S390X_OFF_RN(len), len) != 1) {
+             ECerr(EC_F_ECDSA_S390X_NISTP_SIGN_SIG,
+                   EC_R_RANDOM_NUMBER_GENERATION_FAILED);
+             goto ret;
+         }
+    } else {
+        /* Reconstruct k = (k^-1)^-1. */
+        if (ec_group_do_inverse_ord(group, k, kinv, NULL) == 0
+            || BN_bn2binpad(k, param + S390X_OFF_RN(len), len) == -1) {
+            ECerr(EC_F_ECDSA_S390X_NISTP_SIGN_SIG, ERR_R_BN_LIB);
+            goto ret;
+        }
+        /* Turns KDSA internal nonce-generation off. */
+        fc |= S390X_KDSA_D;
+    }
+
+    if (s390x_kdsa(fc, param, NULL, 0) != 0) {
+        ECerr(EC_F_ECDSA_S390X_NISTP_SIGN_SIG, ERR_R_ECDSA_LIB);
+        goto ret;
+    }
+
+    if (BN_bin2bn(param + S390X_OFF_R(len), len, sig->r) == NULL
+        || BN_bin2bn(param + S390X_OFF_S(len), len, sig->s) == NULL) {
+        ECerr(EC_F_ECDSA_S390X_NISTP_SIGN_SIG, ERR_R_BN_LIB);
+        goto ret;
+    }
+
+    ok = 1;
+ret:
+    OPENSSL_cleanse(param, sizeof(param));
+    if (ok != 1) {
+        ECDSA_SIG_free(sig);
+        sig = NULL;
+    }
+    BN_clear_free(k);
+    return sig;
+}
+
+static int ecdsa_s390x_nistp_verify_sig(const unsigned char *dgst, int dgstlen,
+                                        const ECDSA_SIG *sig, EC_KEY *eckey,
+                                        unsigned int fc, int len)
+{
+    unsigned char param[S390X_SIZE_PARAM];
+    int rc = -1;
+    BN_CTX *ctx;
+    BIGNUM *x, *y;
+    const EC_GROUP *group;
+    const EC_POINT *pubkey;
+    int off;
+
+    group = EC_KEY_get0_group(eckey);
+    pubkey = EC_KEY_get0_public_key(eckey);
+    if (eckey == NULL || group == NULL || pubkey == NULL || sig == NULL) {
+        ECerr(EC_F_ECDSA_S390X_NISTP_VERIFY_SIG, EC_R_MISSING_PARAMETERS);
+        return -1;
+    }
+
+    if (!EC_KEY_can_sign(eckey)) {
+        ECerr(EC_F_ECDSA_S390X_NISTP_VERIFY_SIG,
+              EC_R_CURVE_DOES_NOT_SUPPORT_SIGNING);
+        return -1;
+    }
+
+    ctx = BN_CTX_new_ex(group->libctx);
+    if (ctx == NULL) {
+        ECerr(EC_F_ECDSA_S390X_NISTP_VERIFY_SIG, ERR_R_MALLOC_FAILURE);
+        return -1;
+    }
+
+    BN_CTX_start(ctx);
+
+    x = BN_CTX_get(ctx);
+    y = BN_CTX_get(ctx);
+    if (x == NULL || y == NULL) {
+        ECerr(EC_F_ECDSA_S390X_NISTP_VERIFY_SIG, ERR_R_MALLOC_FAILURE);
+        goto ret;
+    }
+
+    memset(param, 0, sizeof(param));
+    off = len - (dgstlen > len ? len : dgstlen);
+    memcpy(param + S390X_OFF_H(len) + off, dgst, len - off);
+
+    if (group->meth->point_get_affine_coordinates(group, pubkey,
+                                                  x, y, ctx) != 1
+        || BN_bn2binpad(sig->r, param + S390X_OFF_R(len), len) == -1
+        || BN_bn2binpad(sig->s, param + S390X_OFF_S(len), len) == -1
+        || BN_bn2binpad(x, param + S390X_OFF_X(len), len) == -1
+        || BN_bn2binpad(y, param + S390X_OFF_Y(len), len) == -1) {
+        ECerr(EC_F_ECDSA_S390X_NISTP_VERIFY_SIG, ERR_R_BN_LIB);
+        goto ret;
+    }
+
+    rc = s390x_kdsa(fc, param, NULL, 0) == 0 ? 1 : 0;
+ret:
+    BN_CTX_end(ctx);
+    BN_CTX_free(ctx);
+    return rc;
+}
+
+#define EC_GFP_S390X_NISTP_METHOD(bits)                                 \
+                                                                        \
+static int ec_GFp_s390x_nistp##bits##_mul(const EC_GROUP *group,        \
+                                          EC_POINT *r,                  \
+                                          const BIGNUM *scalar,         \
+                                          size_t num,                   \
+                                          const EC_POINT *points[],     \
+                                          const BIGNUM *scalars[],      \
+                                          BN_CTX *ctx)                  \
+{                                                                       \
+    return ec_GFp_s390x_nistp_mul(group, r, scalar, num, points,        \
+                                  scalars, ctx,                         \
+                                  S390X_SCALAR_MULTIPLY_P##bits,        \
+                                  S390X_SIZE_P##bits);                  \
+}                                                                       \
+                                                                        \
+static ECDSA_SIG *ecdsa_s390x_nistp##bits##_sign_sig(const unsigned     \
+                                                     char *dgst,        \
+                                                     int dgstlen,       \
+                                                     const BIGNUM *kinv,\
+                                                     const BIGNUM *r,   \
+                                                     EC_KEY *eckey)     \
+{                                                                       \
+    return ecdsa_s390x_nistp_sign_sig(dgst, dgstlen, kinv, r, eckey,    \
+                                      S390X_ECDSA_SIGN_P##bits,         \
+                                      S390X_SIZE_P##bits);              \
+}                                                                       \
+                                                                        \
+static int ecdsa_s390x_nistp##bits##_verify_sig(const                   \
+                                                unsigned char *dgst,    \
+                                                int dgstlen,            \
+                                                const ECDSA_SIG *sig,   \
+                                                EC_KEY *eckey)          \
+{                                                                       \
+    return ecdsa_s390x_nistp_verify_sig(dgst, dgstlen, sig, eckey,      \
+                                        S390X_ECDSA_VERIFY_P##bits,     \
+                                        S390X_SIZE_P##bits);            \
+}                                                                       \
+                                                                        \
+const EC_METHOD *EC_GFp_s390x_nistp##bits##_method(void)                \
+{                                                                       \
+    static const EC_METHOD EC_GFp_s390x_nistp##bits##_meth = {          \
+        EC_FLAGS_DEFAULT_OCT,                                           \
+        NID_X9_62_prime_field,                                          \
+        ec_GFp_simple_group_init,                                       \
+        ec_GFp_simple_group_finish,                                     \
+        ec_GFp_simple_group_clear_finish,                               \
+        ec_GFp_simple_group_copy,                                       \
+        ec_GFp_simple_group_set_curve,                                  \
+        ec_GFp_simple_group_get_curve,                                  \
+        ec_GFp_simple_group_get_degree,                                 \
+        ec_group_simple_order_bits,                                     \
+        ec_GFp_simple_group_check_discriminant,                         \
+        ec_GFp_simple_point_init,                                       \
+        ec_GFp_simple_point_finish,                                     \
+        ec_GFp_simple_point_clear_finish,                               \
+        ec_GFp_simple_point_copy,                                       \
+        ec_GFp_simple_point_set_to_infinity,                            \
+        ec_GFp_simple_set_Jprojective_coordinates_GFp,                  \
+        ec_GFp_simple_get_Jprojective_coordinates_GFp,                  \
+        ec_GFp_simple_point_set_affine_coordinates,                     \
+        ec_GFp_simple_point_get_affine_coordinates,                     \
+        NULL, /* point_set_compressed_coordinates */                    \
+        NULL, /* point2oct */                                           \
+        NULL, /* oct2point */                                           \
+        ec_GFp_simple_add,                                              \
+        ec_GFp_simple_dbl,                                              \
+        ec_GFp_simple_invert,                                           \
+        ec_GFp_simple_is_at_infinity,                                   \
+        ec_GFp_simple_is_on_curve,                                      \
+        ec_GFp_simple_cmp,                                              \
+        ec_GFp_simple_make_affine,                                      \
+        ec_GFp_simple_points_make_affine,                               \
+        ec_GFp_s390x_nistp##bits##_mul,                                 \
+        NULL, /* precompute_mult */                                     \
+        NULL, /* have_precompute_mult */                                \
+        ec_GFp_simple_field_mul,                                        \
+        ec_GFp_simple_field_sqr,                                        \
+        NULL, /* field_div */                                           \
+        ec_GFp_simple_field_inv,                                        \
+        NULL, /* field_encode */                                        \
+        NULL, /* field_decode */                                        \
+        NULL, /* field_set_to_one */                                    \
+        ec_key_simple_priv2oct,                                         \
+        ec_key_simple_oct2priv,                                         \
+        NULL, /* set_private */                                         \
+        ec_key_simple_generate_key,                                     \
+        ec_key_simple_check_key,                                        \
+        ec_key_simple_generate_public_key,                              \
+        NULL, /* keycopy */                                             \
+        NULL, /* keyfinish */                                           \
+        ecdh_simple_compute_key,                                        \
+        ecdsa_simple_sign_setup,                                        \
+        ecdsa_s390x_nistp##bits##_sign_sig,                             \
+        ecdsa_s390x_nistp##bits##_verify_sig,                           \
+        NULL, /* field_inverse_mod_ord */                               \
+        ec_GFp_simple_blind_coordinates,                                \
+        ec_GFp_simple_ladder_pre,                                       \
+        ec_GFp_simple_ladder_step,                                      \
+        ec_GFp_simple_ladder_post                                       \
+    };                                                                  \
+    static const EC_METHOD *ret;                                        \
+                                                                        \
+    if ((OPENSSL_s390xcap_P.pcc[1]                                      \
+         & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_P##bits))                 \
+        && (OPENSSL_s390xcap_P.kdsa[0]                                  \
+            & S390X_CAPBIT(S390X_ECDSA_VERIFY_P##bits))                 \
+        && (OPENSSL_s390xcap_P.kdsa[0]                                  \
+            & S390X_CAPBIT(S390X_ECDSA_SIGN_P##bits)))                  \
+        ret = &EC_GFp_s390x_nistp##bits##_meth;                         \
+    else                                                                \
+        ret = EC_GFp_mont_method();                                     \
+                                                                        \
+    return ret;                                                         \
+}
+
+EC_GFP_S390X_NISTP_METHOD(256)
+EC_GFP_S390X_NISTP_METHOD(384)
+EC_GFP_S390X_NISTP_METHOD(521)
diff --git a/crypto/ec/ecp_smpl.c b/crypto/ec/ecp_smpl.c
index e8295e636a..bf7aeb1017 100644
--- a/crypto/ec/ecp_smpl.c
+++ b/crypto/ec/ecp_smpl.c
@@ -64,6 +64,9 @@ const EC_METHOD *EC_GFp_simple_method(void)
         0, /* keycopy */
         0, /* keyfinish */
         ecdh_simple_compute_key,
+        ecdsa_simple_sign_setup,
+        ecdsa_simple_sign_sig,
+        ecdsa_simple_verify_sig,
         0, /* field_inverse_mod_ord */
         ec_GFp_simple_blind_coordinates,
         ec_GFp_simple_ladder_pre,
diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt
index 61ad994a8d..5d5981035c 100644
--- a/crypto/err/openssl.txt
+++ b/crypto/err/openssl.txt
@@ -551,6 +551,11 @@ EC_F_ECDSA_SIGN_EX:254:ECDSA_sign_ex
 EC_F_ECDSA_SIGN_SETUP:248:ECDSA_sign_setup
 EC_F_ECDSA_SIG_NEW:265:ECDSA_SIG_new
 EC_F_ECDSA_VERIFY:253:ECDSA_verify
+EC_F_ECDSA_SIMPLE_SIGN_SETUP:310:ecdsa_simple_sign_setup
+EC_F_ECDSA_SIMPLE_SIGN_SIG:311:ecdsa_simple_sign_sig
+EC_F_ECDSA_SIMPLE_VERIFY_SIG:312:ecdsa_simple_verify_sig
+EC_F_ECDSA_S390X_NISTP_SIGN_SIG:313:ecdsa_s390x_nistp_sign_sig
+EC_F_ECDSA_S390X_NISTP_VERIFY_SIG:314:ecdsa_s390x_nistp_verify_sig
 EC_F_ECD_ITEM_VERIFY:270:ecd_item_verify
 EC_F_ECKEY_PARAM2TYPE:223:eckey_param2type
 EC_F_ECKEY_PARAM_DECODE:212:eckey_param_decode
@@ -716,6 +721,7 @@ EC_F_NISTP521_PRE_COMP_NEW:237:nistp521_pre_comp_new
 EC_F_O2I_ECPUBLICKEY:152:o2i_ECPublicKey
 EC_F_OLD_EC_PRIV_DECODE:222:old_ec_priv_decode
 EC_F_OSSL_ECDH_COMPUTE_KEY:247:ossl_ecdh_compute_key
+EC_F_OSSL_ECDSA_SIGN_SETUP:300:ossl_ecdsa_sign_setup
 EC_F_OSSL_ECDSA_SIGN_SIG:249:ossl_ecdsa_sign_sig
 EC_F_OSSL_ECDSA_VERIFY_SIG:250:ossl_ecdsa_verify_sig
 EC_F_PKEY_ECD_CTRL:271:pkey_ecd_ctrl
@@ -2327,6 +2333,7 @@ EC_R_BUFFER_TOO_SMALL:100:buffer too small
 EC_R_CANNOT_INVERT:165:cannot invert
 EC_R_COORDINATES_OUT_OF_RANGE:146:coordinates out of range
 EC_R_CURVE_DOES_NOT_SUPPORT_ECDH:160:curve does not support ecdh
+EC_R_CURVE_DOES_NOT_SUPPORT_ECDSA:170:curve does not support ecdsa
 EC_R_CURVE_DOES_NOT_SUPPORT_SIGNING:159:curve does not support signing
 EC_R_D2I_ECPKPARAMETERS_FAILURE:117:d2i ecpkparameters failure
 EC_R_DECODE_ERROR:142:decode error
diff --git a/crypto/s390xcpuid.pl b/crypto/s390xcpuid.pl
index 2678b21ea1..0bb1004245 100755
--- a/crypto/s390xcpuid.pl
+++ b/crypto/s390xcpuid.pl
@@ -443,7 +443,7 @@ ___
 }
 
 ################
-# void s390x_pcc(unsigned int fc, void *param)
+# int s390x_pcc(unsigned int fc, void *param)
 {
 my ($fc,$param) = map("%r$_",(2..3));
 $code.=<<___;
@@ -468,8 +468,8 @@ ___
 }
 
 ################
-# void s390x_kdsa(unsigned int fc, void *param,
-#                 const unsigned char *in, size_t len)
+# int s390x_kdsa(unsigned int fc, void *param,
+#                const unsigned char *in, size_t len)
 {
 my ($fc,$param,$in,$len) = map("%r$_",(2..5));
 $code.=<<___;
diff --git a/doc/man3/OPENSSL_s390xcap.pod b/doc/man3/OPENSSL_s390xcap.pod
index e45da4467f..1f4ee85fdf 100644
--- a/doc/man3/OPENSSL_s390xcap.pod
+++ b/doc/man3/OPENSSL_s390xcap.pod
@@ -72,6 +72,7 @@ the numbering is continuous across 64-bit mask boundaries.
       #134    1<<57    vector packed decimal facility
       #135    1<<56    vector enhancements facility 1
       #146    1<<45    message-security assist extension 8
+      #155    1<<36    message-security assist extension 9
 
  kimd :
       #  1    1<<62    KIMD-SHA-1
diff --git a/include/openssl/ecerr.h b/include/openssl/ecerr.h
index a465a549b8..43d41d8340 100644
--- a/include/openssl/ecerr.h
+++ b/include/openssl/ecerr.h
@@ -214,6 +214,7 @@ int ERR_load_EC_strings(void);
 #  define EC_R_CANNOT_INVERT                               165
 #  define EC_R_COORDINATES_OUT_OF_RANGE                    146
 #  define EC_R_CURVE_DOES_NOT_SUPPORT_ECDH                 160
+#  define EC_R_CURVE_DOES_NOT_SUPPORT_ECDSA                170
 #  define EC_R_CURVE_DOES_NOT_SUPPORT_SIGNING              159
 #  define EC_R_D2I_ECPKPARAMETERS_FAILURE                  117
 #  define EC_R_DECODE_ERROR                                142


More information about the openssl-commits mailing list