7007966: Add Brainpool ECC support (RFC 5639)
authorvaleriep
Fri, 22 Jun 2018 23:10:36 +0000
changeset 50731 ed322b4cfe49
parent 50729 7755c93d3923
child 50732 f82821dc7aba
7007966: Add Brainpool ECC support (RFC 5639) Summary: Enhance SunEC provider with the support of brainpool256/320/384/512r1 curves Reviewed-by: valeriep Contributed-by: Tobias Wagner <tobias.wagner@n-design.de>
src/jdk.crypto.ec/share/native/libsunec/impl/ec.h
src/jdk.crypto.ec/share/native/libsunec/impl/ecdecode.c
src/jdk.crypto.ec/share/native/libsunec/impl/ecl-curve.h
src/jdk.crypto.ec/share/native/libsunec/impl/ecl-exp.h
src/jdk.crypto.ec/share/native/libsunec/impl/ecl_gf.c
src/jdk.crypto.ec/share/native/libsunec/impl/oid.c
test/jdk/sun/security/ec/InvalidCurve.java
test/jdk/sun/security/pkcs11/PKCS11Test.java
test/jdk/sun/security/pkcs11/ec/TestECDH.java
--- a/src/jdk.crypto.ec/share/native/libsunec/impl/ec.h	Fri Jun 22 15:58:32 2018 -0700
+++ b/src/jdk.crypto.ec/share/native/libsunec/impl/ec.h	Fri Jun 22 23:10:36 2018 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
  * Use is subject to license terms.
  *
  * This library is free software; you can redistribute it and/or
@@ -47,5 +47,6 @@
 
 #define ANSI_X962_CURVE_OID_TOTAL_LEN    10
 #define SECG_CURVE_OID_TOTAL_LEN          7
+#define BRAINPOOL_CURVE_OID_TOTAL_LEN    11
 
 #endif /* __ec_h_ */
--- a/src/jdk.crypto.ec/share/native/libsunec/impl/ecdecode.c	Fri Jun 22 15:58:32 2018 -0700
+++ b/src/jdk.crypto.ec/share/native/libsunec/impl/ecdecode.c	Fri Jun 22 23:10:36 2018 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
  * Use is subject to license terms.
  *
  * This library is free software; you can redistribute it and/or
@@ -172,7 +172,8 @@
 #endif
 
     if ((encodedParams->len != ANSI_X962_CURVE_OID_TOTAL_LEN) &&
-        (encodedParams->len != SECG_CURVE_OID_TOTAL_LEN)) {
+        (encodedParams->len != SECG_CURVE_OID_TOTAL_LEN) &&
+        (encodedParams->len != BRAINPOOL_CURVE_OID_TOTAL_LEN)) {
             PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
             return SECFailure;
     };
@@ -565,6 +566,30 @@
             params, kmflag) );
         break;
 
+    case ECCurve_BrainpoolP256r1:
+        /* Populate params for brainpoolP256r1 */
+        CHECK_SEC_OK( gf_populate_params(ECCurve_BrainpoolP256r1, ec_field_GFp,
+            params, kmflag) );
+        break;
+
+    case ECCurve_BrainpoolP320r1:
+        /* Populate params for brainpoolP320r1 */
+        CHECK_SEC_OK( gf_populate_params(ECCurve_BrainpoolP320r1, ec_field_GFp,
+            params, kmflag) );
+        break;
+
+    case ECCurve_BrainpoolP384r1:
+        /* Populate params for brainpoolP384r1 */
+        CHECK_SEC_OK( gf_populate_params(ECCurve_BrainpoolP384r1, ec_field_GFp,
+            params, kmflag) );
+        break;
+
+    case ECCurve_BrainpoolP512r1:
+        /* Populate params for brainpoolP512r1 */
+        CHECK_SEC_OK( gf_populate_params(ECCurve_BrainpoolP512r1, ec_field_GFp,
+            params, kmflag) );
+        break;
+
     default:
         break;
     };
--- a/src/jdk.crypto.ec/share/native/libsunec/impl/ecl-curve.h	Fri Jun 22 15:58:32 2018 -0700
+++ b/src/jdk.crypto.ec/share/native/libsunec/impl/ecl-curve.h	Fri Jun 22 23:10:36 2018 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
  * Use is subject to license terms.
  *
  * This library is free software; you can redistribute it and/or
@@ -623,6 +623,46 @@
         "0100000000000000000001CDC98AE0E2DE574ABF33", 1
 };
 
+static const ECCurveParams ecCurve_BrainpoolP256r1 = {
+        "brainpoolP256r1", ECField_GFp, 256,
+        "A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377",
+        "7D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9",
+        "26DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B6",
+        "8BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262",
+        "547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997",
+        "A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7", 1
+};
+
+static const ECCurveParams ecCurve_BrainpoolP320r1 = {
+        "brainpoolP320r1", ECField_GFp, 320,
+        "D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412B1F1B32E27",
+        "3EE30B568FBAB0F883CCEBD46D3F3BB8A2A73513F5EB79DA66190EB085FFA9F492F375A97D860EB4",
+        "520883949DFDBC42D3AD198640688A6FE13F41349554B49ACC31DCCD884539816F5EB4AC8FB1F1A6",
+        "43BD7E9AFB53D8B85289BCC48EE5BFE6F20137D10A087EB6E7871E2A10A599C710AF8D0D39E20611",
+        "14FDD05545EC1CC8AB4093247F77275E0743FFED117182EAA9C77877AAAC6AC7D35245D1692E8EE1",
+        "D35E472036BC4FB7E13C785ED201E065F98FCFA5B68F12A32D482EC7EE8658E98691555B44C59311", 1
+};
+
+static const ECCurveParams ecCurve_BrainpoolP384r1 = {
+        "brainpoolP384r1", ECField_GFp, 384,
+        "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC53",
+        "7BC382C63D8C150C3C72080ACE05AFA0C2BEA28E4FB22787139165EFBA91F90F8AA5814A503AD4EB04A8C7DD22CE2826",
+        "04A8C7DD22CE28268B39B55416F0447C2FB77DE107DCD2A62E880EA53EEB62D57CB4390295DBC9943AB78696FA504C11",
+        "1D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10E8E826E03436D646AAEF87B2E247D4AF1E",
+        "8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129280E4646217791811142820341263C5315",
+        "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565", 1
+};
+
+static const ECCurveParams ecCurve_BrainpoolP512r1 = {
+        "brainpoolP512r1", ECField_GFp, 512,
+        "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3",
+        "7830A3318B603B89E2327145AC234CC594CBDD8D3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CA",
+        "3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CADC083E67984050B75EBAE5DD2809BD638016F723",
+        "81AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D0098EFF3B1F78E2D0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F822",
+        "7DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F8111B2DCDE494A5F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892",
+        "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069", 1
+};
+
 /* mapping between ECCurveName enum and pointers to ECCurveParams */
 static const ECCurveParams *ecCurve_map[] = {
     NULL,                               /* ECCurve_noName */
@@ -683,6 +723,10 @@
     &ecCurve_WTLS_1,                    /* ECCurve_WTLS_1 */
     &ecCurve_WTLS_8,                    /* ECCurve_WTLS_8 */
     &ecCurve_WTLS_9,                    /* ECCurve_WTLS_9 */
+    &ecCurve_BrainpoolP256r1,           /* ECCurve_BrainpoolP256r1 */
+    &ecCurve_BrainpoolP320r1,           /* ECCurve_BrainpoolP320r1 */
+    &ecCurve_BrainpoolP384r1,           /* ECCurve_brainpoolP384r1 */
+    &ecCurve_BrainpoolP512r1,           /* ECCurve_brainpoolP512r1 */
     NULL                                /* ECCurve_pastLastCurve */
 };
 
--- a/src/jdk.crypto.ec/share/native/libsunec/impl/ecl-exp.h	Fri Jun 22 15:58:32 2018 -0700
+++ b/src/jdk.crypto.ec/share/native/libsunec/impl/ecl-exp.h	Fri Jun 22 23:10:36 2018 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
  * Use is subject to license terms.
  *
  * This library is free software; you can redistribute it and/or
@@ -161,6 +161,12 @@
         /* ECCurve_WTLS_11 == ECCurve_NIST_B233 */
         /* ECCurve_WTLS_12 == ECCurve_NIST_P224 */
 
+        /* ECC Brainpool prime curves in RFC 5639*/
+        ECCurve_BrainpoolP256r1,
+        ECCurve_BrainpoolP320r1,
+        ECCurve_BrainpoolP384r1,
+        ECCurve_BrainpoolP512r1,
+
         ECCurve_pastLastCurve
 } ECCurveName;
 
--- a/src/jdk.crypto.ec/share/native/libsunec/impl/ecl_gf.c	Fri Jun 22 15:58:32 2018 -0700
+++ b/src/jdk.crypto.ec/share/native/libsunec/impl/ecl_gf.c	Fri Jun 22 23:10:36 2018 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
  * Use is subject to license terms.
  *
  * This library is free software; you can redistribute it and/or
@@ -833,6 +833,7 @@
                 MP_ADD_CARRY(b1, r1, r1, borrow, borrow);
                 MP_ADD_CARRY(b2, r2, r2, borrow, borrow);
                 MP_ADD_CARRY(b3, r3, r3, borrow, borrow);
+                MP_ADD_CARRY(b4, r4, r4, borrow, borrow);
         }
         MP_CHECKOK(s_mp_pad(r, 5));
         MP_DIGIT(r, 4) = r4;
@@ -908,6 +909,7 @@
                 MP_ADD_CARRY(b2, r2, r2, borrow, borrow);
                 MP_ADD_CARRY(b3, r3, r3, borrow, borrow);
                 MP_ADD_CARRY(b4, r4, r4, borrow, borrow);
+                MP_ADD_CARRY(b5, r5, r5, borrow, borrow);
         }
 
         MP_CHECKOK(s_mp_pad(r, 6));
--- a/src/jdk.crypto.ec/share/native/libsunec/impl/oid.c	Fri Jun 22 15:58:32 2018 -0700
+++ b/src/jdk.crypto.ec/share/native/libsunec/impl/oid.c	Fri Jun 22 23:10:36 2018 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
  * Use is subject to license terms.
  *
  * This library is free software; you can redistribute it and/or
@@ -63,6 +63,10 @@
 #define ANSI_X962_GF2m_OID      ANSI_X962_CURVE_OID, 0x00
 #define ANSI_X962_GFp_OID       ANSI_X962_CURVE_OID, 0x01
 
+#define TELETRUST_ALGO_OID             0x2b, 0x24, 0x03
+#define ECC_BRAINPOOL                  TELETRUST_ALGO_OID, 0x03, 0x02, 0x08
+#define ECC_BRAINPOOL_EC_V1            ECC_BRAINPOOL, 0x01, 0x01
+
 #define CONST_OID static const unsigned char
 
 /* ANSI X9.62 prime curve OIDs */
@@ -134,6 +138,22 @@
 CONST_OID ansiX962c2pnb368w1[] = { ANSI_X962_GF2m_OID, 0x13 };
 CONST_OID ansiX962c2tnb431r1[] = { ANSI_X962_GF2m_OID, 0x14 };
 
+/* TeleTrusT ECC Brainpool prime curve OIDs */
+CONST_OID brainpoolP160r1[] = { ECC_BRAINPOOL_EC_V1, 0x01 };
+CONST_OID brainpoolP160t1[] = { ECC_BRAINPOOL_EC_V1, 0x02 };
+CONST_OID brainpoolP192r1[] = { ECC_BRAINPOOL_EC_V1, 0x03 };
+CONST_OID brainpoolP192t1[] = { ECC_BRAINPOOL_EC_V1, 0x04 };
+CONST_OID brainpoolP224r1[] = { ECC_BRAINPOOL_EC_V1, 0x05 };
+CONST_OID brainpoolP224t1[] = { ECC_BRAINPOOL_EC_V1, 0x06 };
+CONST_OID brainpoolP256r1[] = { ECC_BRAINPOOL_EC_V1, 0x07 };
+CONST_OID brainpoolP256t1[] = { ECC_BRAINPOOL_EC_V1, 0x08 };
+CONST_OID brainpoolP320r1[] = { ECC_BRAINPOOL_EC_V1, 0x09 };
+CONST_OID brainpoolP320t1[] = { ECC_BRAINPOOL_EC_V1, 0x0a };
+CONST_OID brainpoolP384r1[] = { ECC_BRAINPOOL_EC_V1, 0x0b };
+CONST_OID brainpoolP384t1[] = { ECC_BRAINPOOL_EC_V1, 0x0c };
+CONST_OID brainpoolP512r1[] = { ECC_BRAINPOOL_EC_V1, 0x0d };
+CONST_OID brainpoolP512t1[] = { ECC_BRAINPOOL_EC_V1, 0x0e };
+
 #define OI(x) { siDEROID, (unsigned char *)x, sizeof x }
 #ifndef SECOID_NO_STRINGS
 #define OD(oid,tag,desc,mech,ext) { OI(oid), tag, desc, mech, ext }
@@ -409,30 +429,98 @@
         INVALID_CERT_EXTENSION )
 };
 
+static SECOidData BRAINPOOL_oids[] = {
+    { { siDEROID, NULL, 0 }, ECCurve_noName,
+        "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
+
+    /* RFC 5639 Brainpool named elliptic curves */
+    { { siDEROID, NULL, 0 }, ECCurve_noName,
+        "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
+    { { siDEROID, NULL, 0 }, ECCurve_noName,
+        "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
+    { { siDEROID, NULL, 0 }, ECCurve_noName,
+        "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
+    { { siDEROID, NULL, 0 }, ECCurve_noName,
+        "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
+    { { siDEROID, NULL, 0 }, ECCurve_noName,
+        "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
+    { { siDEROID, NULL, 0 }, ECCurve_noName,
+        "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
+    OD( brainpoolP256r1, ECCurve_BrainpoolP256r1,
+        "brainpoolP256r1 domain parameter set",
+        CKM_INVALID_MECHANISM,
+        INVALID_CERT_EXTENSION ),
+    { { siDEROID, NULL, 0 }, ECCurve_noName,
+        "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
+    OD( brainpoolP320r1, ECCurve_BrainpoolP320r1,
+        "brainpoolP320r1 domain parameter set",
+        CKM_INVALID_MECHANISM,
+        INVALID_CERT_EXTENSION ),
+    { { siDEROID, NULL, 0 }, ECCurve_noName,
+        "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
+    OD( brainpoolP384r1, ECCurve_BrainpoolP384r1,
+        "brainpoolP384r1 domain parameter set",
+        CKM_INVALID_MECHANISM,
+        INVALID_CERT_EXTENSION ),
+    { { siDEROID, NULL, 0 }, ECCurve_noName,
+        "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
+    OD( brainpoolP512r1, ECCurve_BrainpoolP512r1,
+        "brainpoolP512r1 domain parameter set",
+        CKM_INVALID_MECHANISM,
+        INVALID_CERT_EXTENSION ),
+    { { siDEROID, NULL, 0 }, ECCurve_noName,
+        "Unknown OID", CKM_INVALID_MECHANISM,
+        INVALID_CERT_EXTENSION }
+};
+
+int
+oideql(unsigned char *reqoid, unsigned char *foundoid, size_t reqlen, size_t foundlen)
+{
+    if (!reqoid || !foundoid) {
+        return 0;
+    }
+
+    if (reqlen != foundlen) {
+        return 0;
+    }
+
+    return memcmp(reqoid, foundoid, reqlen) == 0;
+}
+
 SECOidData *
 SECOID_FindOID(const SECItem *oid)
 {
     SECOidData *po;
     SECOidData *ret = NULL;
+    int reqlen = oid->len;
 
-    if (oid->len == 8) {
+    if (reqlen == 8) {
         if (oid->data[6] == 0x00) {
-                /* XXX bounds check */
-                po = &ANSI_oids[oid->data[7]];
-                if (memcmp(oid->data, po->oid.data, 8) == 0)
-                        ret = po;
+            /* XXX bounds check */
+            po = &ANSI_oids[oid->data[7]];
+            if (oideql(oid->data, po->oid.data, reqlen, po->oid.len)) {
+                ret = po;
+            }
         }
         if (oid->data[6] == 0x01) {
-                /* XXX bounds check */
-                po = &ANSI_prime_oids[oid->data[7]];
-                if (memcmp(oid->data, po->oid.data, 8) == 0)
-                        ret = po;
+            /* XXX bounds check */
+            po = &ANSI_prime_oids[oid->data[7]];
+            if (oideql(oid->data, po->oid.data, reqlen, po->oid.len)) {
+                ret = po;
+            }
         }
-    } else if (oid->len == 5) {
+    } else if (reqlen == 5) {
         /* XXX bounds check */
         po = &SECG_oids[oid->data[4]];
-        if (memcmp(oid->data, po->oid.data, 5) == 0)
-                ret = po;
+        if (oideql(oid->data, po->oid.data, reqlen, po->oid.len)) {
+            ret = po;
+        }
+    } else if (reqlen == 9) {
+        /* XXX bounds check */
+        po = &BRAINPOOL_oids[oid->data[8]];
+        if (oideql(oid->data, po->oid.data, reqlen, po->oid.len)) {
+           ret = po;
+        }
     }
     return(ret);
 }
--- a/test/jdk/sun/security/ec/InvalidCurve.java	Fri Jun 22 15:58:32 2018 -0700
+++ b/test/jdk/sun/security/ec/InvalidCurve.java	Fri Jun 22 23:10:36 2018 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -40,7 +40,7 @@
         try {
             keyGen = KeyPairGenerator.getInstance("EC", "SunEC");
             ECGenParameterSpec brainpoolSpec =
-                new ECGenParameterSpec("brainpoolP256r1");
+                new ECGenParameterSpec("brainpoolP160r1");
             keyGen.initialize(brainpoolSpec);
         } catch (InvalidAlgorithmParameterException ex) {
             System.out.println(ex.getMessage());
--- a/test/jdk/sun/security/pkcs11/PKCS11Test.java	Fri Jun 22 15:58:32 2018 -0700
+++ b/test/jdk/sun/security/pkcs11/PKCS11Test.java	Fri Jun 22 23:10:36 2018 +0000
@@ -47,6 +47,7 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 import java.util.Properties;
 import java.util.ServiceConfigurationError;
 import java.util.ServiceLoader;
@@ -576,21 +577,8 @@
             }
 
             curve = kcProp.substring(begin, end);
-            ECParameterSpec e = getECParameterSpec(p, curve);
-            System.out.print("\t "+ curve + ": ");
-            try {
-                KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC", p);
-                kpg.initialize(e);
-                kpg.generateKeyPair();
-                results.add(e);
-                System.out.println("Supported");
-            } catch (ProviderException ex) {
-                System.out.println("Unsupported: PKCS11: " +
-                        ex.getCause().getMessage());
-            } catch (InvalidAlgorithmParameterException ex) {
-                System.out.println("Unsupported: Key Length: " +
-                        ex.getMessage());
-            }
+            getSupportedECParameterSpec(curve, p)
+                .ifPresent(spec -> results.add(spec));
         }
 
         if (results.size() == 0) {
@@ -600,6 +588,27 @@
         return results;
     }
 
+    static Optional<ECParameterSpec> getSupportedECParameterSpec(String curve,
+            Provider p) throws Exception {
+        ECParameterSpec e = getECParameterSpec(p, curve);
+        System.out.print("\t "+ curve + ": ");
+        try {
+            KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC", p);
+            kpg.initialize(e);
+            kpg.generateKeyPair();
+            System.out.println("Supported");
+            return Optional.of(e);
+        } catch (ProviderException ex) {
+            System.out.println("Unsupported: PKCS11: " +
+                    ex.getCause().getMessage());
+            return Optional.empty();
+        } catch (InvalidAlgorithmParameterException ex) {
+            System.out.println("Unsupported: Key Length: " +
+                    ex.getMessage());
+            return Optional.empty();
+        }
+    }
+
     private static ECParameterSpec getECParameterSpec(Provider p, String name)
             throws Exception {
 
--- a/test/jdk/sun/security/pkcs11/ec/TestECDH.java	Fri Jun 22 15:58:32 2018 -0700
+++ b/test/jdk/sun/security/pkcs11/ec/TestECDH.java	Fri Jun 22 23:10:36 2018 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -61,8 +61,37 @@
 
     private final static String secret163 = "04:ae:71:c1:c6:4d:f4:34:4d:72:70:a4:64:65:7f:2d:88:2d:3f:50:be";
 
-    @Override
-    public void main(Provider p) throws Exception {
+
+    // from https://tools.ietf.org/html/rfc7027#appendix-A.1
+    private final static String pubBrainpoolP256r1a = "305a301406072a8648ce3d020106092b24030302080101070342000444106e913f92bc02a1705d9953a8414db95e1aaa49e81d9e85f929a8e3100be58ab4846f11caccb73ce49cbdd120f5a900a69fd32c272223f789ef10eb089bdc";
+    private final static String privBrainpoolP256r1a = "3042020100301406072a8648ce3d020106092b240303020801010704273025020101042081db1ee100150ff2ea338d708271be38300cb54241d79950f77b063039804f1d";
+    private final static String pubBrainpoolP256r1b = "305a301406072a8648ce3d020106092b2403030208010107034200048d2d688c6cf93e1160ad04cc4429117dc2c41825e1e9fca0addd34e6f1b39f7b990c57520812be512641e47034832106bc7d3e8dd0e4c7f1136d7006547cec6a";
+    private final static String privBrainpoolP256r1b = "3042020100301406072a8648ce3d020106092b240303020801010704273025020101042055e40bc41e37e3e2ad25c3c6654511ffa8474a91a0032087593852d3e7d76bd3";
+    private final static String secretBrainpoolP256r1 = "89afc39d41d3b327814b80940b042590f96556ec91e6ae7939bce31f3a18bf2b";
+
+    // from https://tools.ietf.org/html/draft-merkle-ikev2-ke-brainpool-00#appendix-A.5
+    private final static String pubBrainpoolP320r1a = "306a301406072a8648ce3d020106092b240303020801010903520004bc43666c00e4b943fe1c785dd8aa842a42ab54b0b49819f960f77694193cd3afa71b6b3c826c773469e998892c0764468023c8e3a7b8f219a1446042be175d4476b2fdfd85b22ead2f29101a1242a578";
+    private final static String privBrainpoolP320r1a = "304a020100301406072a8648ce3d020106092b2403030208010109042f302d02010104287cd9c454ba907f7617e262a7fd73764c4a3157c13f82279ef9f062be5d49a8e390b66a4dcedfa867";
+    private final static String pubBrainpoolP320r1b = "306a301406072a8648ce3d020106092b240303020801010903520004b1246229429354d1d687bca48bccd6fc733b146dac03642a0ad4b896f5d8bcbd2f4bca16776e4526a41683898f9a76ef36ea2dc7b74d419e55cf3664721890d6a2b2fb8ceb7c113167ed137a358ee37f";
+    private final static String privBrainpoolP320r1b = "304a020100301406072a8648ce3d020106092b2403030208010109042f302d0201010428b832a73da5f671e80d87f09372544801f6812224b19a4bc1b37aa7db0842e6dd3ca11de0f802bfed";
+    private final static String secretBrainpoolP320r1 = "730314d906b2f21dc11be05031b028d665696beec7139328cdf70c718be5d208659bb96743a88067";
+
+    // from https://tools.ietf.org/html/rfc7027#appendix-A.2
+    private final static String pubBrainpoolP384r1a = "307a301406072a8648ce3d020106092b240303020801010b0362000468b665dd91c195800650cdd363c625f4e742e8134667b767b1b476793588f885ab698c852d4a6e77a252d6380fcaf06855bc91a39c9ec01dee36017b7d673a931236d2f1f5c83942d049e3fa20607493e0d038ff2fd30c2ab67d15c85f7faa59";
+    private final static String privBrainpoolP384r1a = "3052020100301406072a8648ce3d020106092b240303020801010b0437303502010104301e20f5e048a5886f1f157c74e91bde2b98c8b52d58e5003d57053fc4b0bd65d6f15eb5d1ee1610df870795143627d042";
+    private final static String pubBrainpoolP384r1b = "307a301406072a8648ce3d020106092b240303020801010b036200044d44326f269a597a5b58bba565da5556ed7fd9a8a9eb76c25f46db69d19dc8ce6ad18e404b15738b2086df37e71d1eb462d692136de56cbe93bf5fa3188ef58bc8a3a0ec6c1e151a21038a42e9185329b5b275903d192f8d4e1f32fe9cc78c48";
+    private final static String privBrainpoolP384r1b = "3052020100301406072a8648ce3d020106092b240303020801010b043730350201010430032640bc6003c59260f7250c3db58ce647f98e1260acce4acda3dd869f74e01f8ba5e0324309db6a9831497abac96670";
+    private final static String secretBrainpoolP384r1 = "0bd9d3a7ea0b3d519d09d8e48d0785fb744a6b355e6304bc51c229fbbce239bbadf6403715c35d4fb2a5444f575d4f42";
+
+
+    // from https://tools.ietf.org/html/rfc7027#appendix-A.3
+    private final static String pubBrainpoolP512r1a = "30819b301406072a8648ce3d020106092b240303020801010d03818200040a420517e406aac0acdce90fcd71487718d3b953efd7fbec5f7f27e28c6149999397e91e029e06457db2d3e640668b392c2a7e737a7f0bf04436d11640fd09fd72e6882e8db28aad36237cd25d580db23783961c8dc52dfa2ec138ad472a0fcef3887cf62b623b2a87de5c588301ea3e5fc269b373b60724f5e82a6ad147fde7";
+    private final static String privBrainpoolP512r1a = "3062020100301406072a8648ce3d020106092b240303020801010d04473045020101044016302ff0dbbb5a8d733dab7141c1b45acbc8715939677f6a56850a38bd87bd59b09e80279609ff333eb9d4c061231fb26f92eeb04982a5f1d1764cad57665422";
+    private final static String pubBrainpoolP512r1b = "30819b301406072a8648ce3d020106092b240303020801010d03818200049d45f66de5d67e2e6db6e93a59ce0bb48106097ff78a081de781cdb31fce8ccbaaea8dd4320c4119f1e9cd437a2eab3731fa9668ab268d871deda55a5473199f2fdc313095bcdd5fb3a91636f07a959c8e86b5636a1e930e8396049cb481961d365cc11453a06c719835475b12cb52fc3c383bce35e27ef194512b71876285fa";
+    private final static String privBrainpoolP512r1b = "3062020100301406072a8648ce3d020106092b240303020801010d044730450201010440230e18e1bcc88a362fa54e4ea3902009292f7f8033624fd471b5d8ace49d12cfabbc19963dab8e2f1eba00bffb29e4d72d13f2224562f405cb80503666b25429";
+    private final static String secretBrainpoolP512r1 = "a7927098655f1f9976fa50a9d566865dc530331846381c87256baf3226244b76d36403c024d7bbf0aa0803eaff405d3d24f11a9b5c0bef679fe1454b21c4cd1f";
+
+    @Override public void main(Provider p) throws Exception {
         if (p.getService("KeyAgreement", "ECDH") == null) {
             System.out.println("Provider does not support ECDH, skipping");
             return;
@@ -93,6 +122,19 @@
         test(p, pub192a, priv192a, pub192b, priv192b, secret192);
         test(p, pub163a, priv163a, pub163b, priv163b, secret163);
 
+        if (getSupportedECParameterSpec("brainpoolP256r1", p).isPresent()) {
+            test(p, pubBrainpoolP256r1a, privBrainpoolP256r1a, pubBrainpoolP256r1b, privBrainpoolP256r1b, secretBrainpoolP256r1);
+        }
+        if (getSupportedECParameterSpec("brainpoolP320r1", p).isPresent()) {
+            test(p, pubBrainpoolP320r1a, privBrainpoolP320r1a, pubBrainpoolP320r1b, privBrainpoolP320r1b, secretBrainpoolP320r1);
+        }
+        if (getSupportedECParameterSpec("brainpoolP384r1", p).isPresent()) {
+            test(p, pubBrainpoolP384r1a, privBrainpoolP384r1a, pubBrainpoolP384r1b, privBrainpoolP384r1b, secretBrainpoolP384r1);
+        }
+        if (getSupportedECParameterSpec("brainpoolP512r1", p).isPresent()) {
+            test(p, pubBrainpoolP512r1a, privBrainpoolP512r1a, pubBrainpoolP512r1b, privBrainpoolP512r1b, secretBrainpoolP512r1);
+        }
+
         System.out.println("OK");
     }