EC only uses approved curves in FIPS mode.
authorShane Lontis <shane.lontis@oracle.com>
Tue, 4 Jun 2019 22:24:16 +0000 (08:24 +1000)
committerShane Lontis <shane.lontis@oracle.com>
Tue, 25 Jun 2019 02:00:25 +0000 (12:00 +1000)
Once there are buildable fips tests, some tests that are data driven
from files will need to be modified to exclude non approved curves in
fips mode.

These changes were tested by temporarily adding #define FIPS_MODE 1 to
all the modified source files.

Reviewed-by: Nicola Tuveri <nic.tuv@gmail.com>
Reviewed-by: Tomas Mraz <tmraz@fedoraproject.org>
Reviewed-by: Paul Dale <paul.dale@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/9081)

crypto/ec/ec_check.c
crypto/ec/ec_curve.c
test/ecdsatest.c
test/ectest.c
test/evp_extra_test.c
test/evp_pkey_dparams_test.c
test/recipes/20-test_pkeyutl.t
test/recipes/25-test_verify.t

index 097d7e1cc542b7d46f2ce8ba44b509edf01bd521..315b9fd4dfadfed9eb956c47ba2e40d47644fd25 100644 (file)
@@ -22,6 +22,13 @@ int EC_GROUP_check_named_curve(const EC_GROUP *group, int nist_only)
 
 int EC_GROUP_check(const EC_GROUP *group, BN_CTX *ctx)
 {
+#ifdef FIPS_MODE
+    /*
+    * ECC domain parameter validation.
+    * See SP800-56A R3 5.5.2 "Assurances of Domain-Parameter Validity" Part 1b.
+    */
+    return EC_GROUP_check_named_curve(group, 1) >= 0 ? 1 : 0;
+#else
     int ret = 0;
     const BIGNUM *order;
     BN_CTX *new_ctx = NULL;
@@ -84,4 +91,5 @@ int EC_GROUP_check(const EC_GROUP *group, BN_CTX *ctx)
     BN_CTX_free(new_ctx);
     EC_POINT_free(point);
     return ret;
+#endif /* FIPS_MODE */
 }
index 1ea85946d6a6424f5cb00893c9b9a5b72523e1a7..8b44c251badb3313bb75f652e9348bf962286f4d 100644 (file)
@@ -2800,6 +2800,70 @@ typedef struct _ec_list_element_st {
     const char *comment;
 } ec_list_element;
 
+#ifdef FIPS_MODE
+static const ec_list_element curve_list[] = {
+    /* prime field curves */
+    /* secg curves */
+# ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
+    {NID_secp224r1, &_EC_NIST_PRIME_224.h, EC_GFp_nistp224_method,
+     "NIST/SECG curve over a 224 bit prime field"},
+# else
+    {NID_secp224r1, &_EC_NIST_PRIME_224.h, 0,
+     "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,
+     "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"},
+# else
+    {NID_secp521r1, &_EC_NIST_PRIME_521.h, 0,
+     "NIST/SECG curve over a 521 bit prime field"},
+# endif
+
+    /* X9.62 curves */
+    {NID_X9_62_prime192v1, &_EC_NIST_PRIME_192.h, 0,
+     "NIST/X9.62/SECG curve over a 192 bit prime field"},
+    {NID_X9_62_prime256v1, &_EC_X9_62_PRIME_256V1.h,
+# if defined(ECP_NISTZ256_ASM)
+     EC_GFp_nistz256_method,
+# elif !defined(OPENSSL_NO_EC_NISTP_64_GCC_128)
+     EC_GFp_nistp256_method,
+# else
+     0,
+# endif
+     "X9.62/SECG curve over a 256 bit prime field"},
+
+# ifndef OPENSSL_NO_EC2M
+    /* characteristic two field curves */
+    /* NIST/SECG curves */
+    {NID_sect163k1, &_EC_NIST_CHAR2_163K.h, 0,
+     "NIST/SECG/WTLS curve over a 163 bit binary field"},
+    {NID_sect163r2, &_EC_NIST_CHAR2_163B.h, 0,
+     "NIST/SECG curve over a 163 bit binary field"},
+    {NID_sect233k1, &_EC_NIST_CHAR2_233K.h, 0,
+     "NIST/SECG/WTLS curve over a 233 bit binary field"},
+    {NID_sect233r1, &_EC_NIST_CHAR2_233B.h, 0,
+     "NIST/SECG/WTLS curve over a 233 bit binary field"},
+    {NID_sect283k1, &_EC_NIST_CHAR2_283K.h, 0,
+     "NIST/SECG curve over a 283 bit binary field"},
+    {NID_sect283r1, &_EC_NIST_CHAR2_283B.h, 0,
+     "NIST/SECG curve over a 283 bit binary field"},
+    {NID_sect409k1, &_EC_NIST_CHAR2_409K.h, 0,
+     "NIST/SECG curve over a 409 bit binary field"},
+    {NID_sect409r1, &_EC_NIST_CHAR2_409B.h, 0,
+     "NIST/SECG curve over a 409 bit binary field"},
+    {NID_sect571k1, &_EC_NIST_CHAR2_571K.h, 0,
+     "NIST/SECG curve over a 571 bit binary field"},
+    {NID_sect571r1, &_EC_NIST_CHAR2_571B.h, 0,
+     "NIST/SECG curve over a 571 bit binary field"},
+# endif
+};
+
+#else
+
 static const ec_list_element curve_list[] = {
     /* prime field curves */
     /* secg curves */
@@ -2822,25 +2886,25 @@ static const ec_list_element curve_list[] = {
      "SECG curve over a 192 bit prime field"},
     {NID_secp224k1, &_EC_SECG_PRIME_224K1.h, 0,
      "SECG curve over a 224 bit prime field"},
-#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
+# ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
     {NID_secp224r1, &_EC_NIST_PRIME_224.h, EC_GFp_nistp224_method,
      "NIST/SECG curve over a 224 bit prime field"},
-#else
+# else
     {NID_secp224r1, &_EC_NIST_PRIME_224.h, 0,
      "NIST/SECG curve over a 224 bit prime field"},
-#endif
+# endif
     {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,
      "NIST/SECG curve over a 384 bit prime field"},
-#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
+# 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"},
-#else
+# else
     {NID_secp521r1, &_EC_NIST_PRIME_521.h, 0,
      "NIST/SECG curve over a 521 bit prime field"},
-#endif
+# endif
     /* X9.62 curves */
     {NID_X9_62_prime192v1, &_EC_NIST_PRIME_192.h, 0,
      "NIST/X9.62/SECG curve over a 192 bit prime field"},
@@ -2855,15 +2919,15 @@ static const ec_list_element curve_list[] = {
     {NID_X9_62_prime239v3, &_EC_X9_62_PRIME_239V3.h, 0,
      "X9.62 curve over a 239 bit prime field"},
     {NID_X9_62_prime256v1, &_EC_X9_62_PRIME_256V1.h,
-#if defined(ECP_NISTZ256_ASM)
+# if defined(ECP_NISTZ256_ASM)
      EC_GFp_nistz256_method,
-#elif !defined(OPENSSL_NO_EC_NISTP_64_GCC_128)
+# elif !defined(OPENSSL_NO_EC_NISTP_64_GCC_128)
      EC_GFp_nistp256_method,
-#else
+# else
      0,
-#endif
+# endif
      "X9.62/SECG curve over a 256 bit prime field"},
-#ifndef OPENSSL_NO_EC2M
+# ifndef OPENSSL_NO_EC2M
     /* characteristic two field curves */
     /* NIST/SECG curves */
     {NID_sect113r1, &_EC_SECG_CHAR2_113R1.h, 0,
@@ -2947,7 +3011,7 @@ static const ec_list_element curve_list[] = {
      "SECG curve over a 113 bit binary field"},
     {NID_wap_wsg_idm_ecid_wtls5, &_EC_X9_62_CHAR2_163V1.h, 0,
      "X9.62 curve over a 163 bit binary field"},
-#endif
+# endif
     {NID_wap_wsg_idm_ecid_wtls6, &_EC_SECG_PRIME_112R1.h, 0,
      "SECG/WTLS curve over a 112 bit prime field"},
     {NID_wap_wsg_idm_ecid_wtls7, &_EC_SECG_PRIME_160R2.h, 0,
@@ -2956,15 +3020,15 @@ static const ec_list_element curve_list[] = {
      "WTLS curve over a 112 bit prime field"},
     {NID_wap_wsg_idm_ecid_wtls9, &_EC_WTLS_9.h, 0,
      "WTLS curve over a 160 bit prime field"},
-#ifndef OPENSSL_NO_EC2M
+# ifndef OPENSSL_NO_EC2M
     {NID_wap_wsg_idm_ecid_wtls10, &_EC_NIST_CHAR2_233K.h, 0,
      "NIST/SECG/WTLS curve over a 233 bit binary field"},
     {NID_wap_wsg_idm_ecid_wtls11, &_EC_NIST_CHAR2_233B.h, 0,
      "NIST/SECG/WTLS curve over a 233 bit binary field"},
-#endif
+# endif
     {NID_wap_wsg_idm_ecid_wtls12, &_EC_WTLS_12.h, 0,
      "WTLS curve over a 224 bit prime field"},
-#ifndef OPENSSL_NO_EC2M
+# ifndef OPENSSL_NO_EC2M
     /* IPSec curves */
     {NID_ipsec3, &_EC_IPSEC_155_ID3.h, 0,
      "\n\tIPSec/IKE/Oakley curve #3 over a 155 bit binary field.\n"
@@ -2972,7 +3036,7 @@ static const ec_list_element curve_list[] = {
     {NID_ipsec4, &_EC_IPSEC_185_ID4.h, 0,
      "\n\tIPSec/IKE/Oakley curve #4 over a 185 bit binary field.\n"
      "\tNot suitable for ECDSA.\n\tQuestionable extension field!"},
-#endif
+# endif
     /* brainpool curves */
     {NID_brainpoolP160r1, &_EC_brainpoolP160r1.h, 0,
      "RFC 5639 curve over a 160 bit prime field"},
@@ -3002,11 +3066,12 @@ static const ec_list_element curve_list[] = {
      "RFC 5639 curve over a 512 bit prime field"},
     {NID_brainpoolP512t1, &_EC_brainpoolP512t1.h, 0,
      "RFC 5639 curve over a 512 bit prime field"},
-#ifndef OPENSSL_NO_SM2
+# ifndef OPENSSL_NO_SM2
     {NID_sm2, &_EC_sm2p256v1.h, 0,
      "SM2 curve over a 256 bit prime field"},
-#endif
+# endif
 };
+#endif /* FIPS_MODE */
 
 #define curve_list_length OSSL_NELEM(curve_list)
 
@@ -3125,6 +3190,15 @@ EC_GROUP *EC_GROUP_new_by_curve_name(int nid)
     if (nid <= 0)
         return NULL;
 
+#ifdef FIPS_MODE
+    /*
+     * Only use approved NIST curves in FIPS.
+     * NOTE: "B-163", "K-163" & "P-192" can only be used for legacy use
+     * (i.e- ECDSA signature verification).
+     */
+    if (EC_curve_nid2nist(nid) == NULL)
+        return NULL;
+#endif /* FIPS_MODE */
     for (i = 0; i < curve_list_length; i++)
         if (curve_list[i].nid == nid) {
             ret = ec_group_new_from_data(curve_list[i]);
index 761832ff81cb232157da129c399a4dfc3bb5a429..a62efad1cfdfcf12aebb6194f5b2b8dffca5333c 100644 (file)
@@ -118,6 +118,11 @@ static int x9_62_tests(int n)
 
     TEST_info("ECDSA KATs for curve %s", OBJ_nid2sn(nid));
 
+#ifdef FIPS_MODE
+    if (EC_curve_nid2nist(nid) == NULL)
+        return TEST_skip("skip non approved curves");
+#endif /* FIPS_MODE */
+
     if (!TEST_ptr(mctx = EVP_MD_CTX_new())
         /* get the message digest */
         || !TEST_ptr(message = OPENSSL_hexstr2buf(tbs, &msg_len))
index 3f7747e5e793102ecd6114daf592a10f21ebc713..50f8c63f0a16e06fa592ab347cde3475ee55f860 100644 (file)
@@ -1820,7 +1820,7 @@ static int parameter_test(void)
     unsigned char *buf = NULL;
     int r = 0, len;
 
-    if (!TEST_ptr(group = EC_GROUP_new_by_curve_name(NID_secp112r1))
+    if (!TEST_ptr(group = EC_GROUP_new_by_curve_name(NID_secp224r1))
         || !TEST_ptr(ecparameters = EC_GROUP_get_ecparameters(group, NULL))
         || !TEST_ptr(group2 = EC_GROUP_new_from_ecparameters(ecparameters))
         || !TEST_int_eq(EC_GROUP_cmp(group, group2, NULL), 0))
index 5bf4a8c1f3d7cf221aaf2d06f6e8b14fa4e64d5e..48376a79512f762edbd9ef44a413d65a9dfd2a0f 100644 (file)
@@ -599,7 +599,7 @@ static int test_EVP_PKCS82PKEY(void)
 }
 #endif
 
-#ifndef OPENSSL_NO_SM2
+#if !defined(OPENSSL_NO_SM2) && !defined(FIPS_MODE)
 
 static int test_EVP_SM2_verify(void)
 {
@@ -1238,7 +1238,7 @@ int setup_tests(void)
 #ifndef OPENSSL_NO_EC
     ADD_TEST(test_EVP_PKCS82PKEY);
 #endif
-#ifndef OPENSSL_NO_SM2
+#if !defined(OPENSSL_NO_SM2) && !defined(FIPS_MODE)
     ADD_TEST(test_EVP_SM2);
     ADD_TEST(test_EVP_SM2_verify);
 #endif
index e11d225b594b01cf3879abd3ee28bb2f5bce7a00..f1d528eb271858ec4d7cb66b1854967e2077d72f 100644 (file)
@@ -85,7 +85,7 @@ static const unsigned char dsaparam_bin[] = {
 
 #ifndef OPENSSL_NO_EC
 static const unsigned char ecparam_bin[] = {
-0x06,0x05,0x2b,0x81,0x04,0x00,0x0a
+0x06,0x08,0x2a,0x86,0x48,0xce,0x3d,0x03,0x01,0x07
 };
 #endif
 
index 5dbed9835c7735bdccdca67d4d77e25680b8dfc2..83804d69ad3e30c6f8292b4319b0cb4c784dee4c 100644 (file)
@@ -10,7 +10,7 @@ use strict;
 use warnings;
 
 use File::Spec;
-use OpenSSL::Test qw/:DEFAULT srctop_file/;
+use OpenSSL::Test qw/:DEFAULT srctop_file ok_nofips/;
 use OpenSSL::Test::Utils;
 
 setup("test_pkeyutl");
@@ -24,13 +24,13 @@ SKIP: {
         if disabled("ec") || disabled("sm2") || disabled("sm3");
 
     # SM2
-    ok(run(app(([ 'openssl', 'pkeyutl', '-sign',
+    ok_nofips(run(app(([ 'openssl', 'pkeyutl', '-sign',
                       '-in', srctop_file('test', 'certs', 'sm2.pem'),
                       '-inkey', srctop_file('test', 'certs', 'sm2.key'),
                       '-out', 'signature.dat', '-rawin',
                       '-digest', 'sm3', '-pkeyopt', 'sm2_id:someid']))),
                       "Sign a piece of data using SM2");
-    ok(run(app(([ 'openssl', 'pkeyutl', '-verify', '-certin',
+    ok_nofips(run(app(([ 'openssl', 'pkeyutl', '-verify', '-certin',
                       '-in', srctop_file('test', 'certs', 'sm2.pem'),
                       '-inkey', srctop_file('test', 'certs', 'sm2.pem'),
                       '-sigfile', 'signature.dat', '-rawin',
index 96bfd03e2cd05f05d93c658c52baab7001e49fb7..915c902b159c8f0492dc7dffb5a3b07c66e72dd4 100644 (file)
@@ -11,7 +11,7 @@ use strict;
 use warnings;
 
 use File::Spec::Functions qw/canonpath/;
-use OpenSSL::Test qw/:DEFAULT srctop_file/;
+use OpenSSL::Test qw/:DEFAULT srctop_file ok_nofips/;
 use OpenSSL::Test::Utils;
 
 setup("test_verify");
@@ -379,9 +379,9 @@ SKIP: {
              if disabled("sm2");
 
    # Test '-sm2-id' and '-sm2-hex-id'  option
-   ok(verify("sm2", "any", ["sm2-ca-cert"], [], "-sm2-id", "1234567812345678"),
+   ok_nofips(verify("sm2", "any", ["sm2-ca-cert"], [], "-sm2-id", "1234567812345678"),
        "SM2 ID test");
-   ok(verify("sm2", "any", ["sm2-ca-cert"], [], "-sm2-hex-id",
+   ok_nofips(verify("sm2", "any", ["sm2-ca-cert"], [], "-sm2-hex-id",
              "31323334353637383132333435363738"),
        "SM2 hex ID test");
 }