EC only uses approved curves in FIPS mode.

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)
This commit is contained in:
Shane Lontis 2019-06-05 08:24:16 +10:00
parent be1dc984e1
commit 10c25644e3
8 changed files with 115 additions and 28 deletions

View 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) 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; int ret = 0;
const BIGNUM *order; const BIGNUM *order;
BN_CTX *new_ctx = NULL; 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); BN_CTX_free(new_ctx);
EC_POINT_free(point); EC_POINT_free(point);
return ret; return ret;
#endif /* FIPS_MODE */
} }

View File

@ -2800,6 +2800,70 @@ typedef struct _ec_list_element_st {
const char *comment; const char *comment;
} ec_list_element; } 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[] = { static const ec_list_element curve_list[] = {
/* prime field curves */ /* prime field curves */
/* secg curves */ /* secg curves */
@ -2822,25 +2886,25 @@ static const ec_list_element curve_list[] = {
"SECG curve over a 192 bit prime field"}, "SECG curve over a 192 bit prime field"},
{NID_secp224k1, &_EC_SECG_PRIME_224K1.h, 0, {NID_secp224k1, &_EC_SECG_PRIME_224K1.h, 0,
"SECG curve over a 224 bit prime field"}, "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, {NID_secp224r1, &_EC_NIST_PRIME_224.h, EC_GFp_nistp224_method,
"NIST/SECG curve over a 224 bit prime field"}, "NIST/SECG curve over a 224 bit prime field"},
#else # else
{NID_secp224r1, &_EC_NIST_PRIME_224.h, 0, {NID_secp224r1, &_EC_NIST_PRIME_224.h, 0,
"NIST/SECG curve over a 224 bit prime field"}, "NIST/SECG curve over a 224 bit prime field"},
#endif # endif
{NID_secp256k1, &_EC_SECG_PRIME_256K1.h, 0, {NID_secp256k1, &_EC_SECG_PRIME_256K1.h, 0,
"SECG curve over a 256 bit prime field"}, "SECG curve over a 256 bit prime field"},
/* SECG secp256r1 is the same as X9.62 prime256v1 and hence omitted */ /* 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, 0,
"NIST/SECG curve over a 384 bit prime field"}, "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, {NID_secp521r1, &_EC_NIST_PRIME_521.h, EC_GFp_nistp521_method,
"NIST/SECG curve over a 521 bit prime field"}, "NIST/SECG curve over a 521 bit prime field"},
#else # else
{NID_secp521r1, &_EC_NIST_PRIME_521.h, 0, {NID_secp521r1, &_EC_NIST_PRIME_521.h, 0,
"NIST/SECG curve over a 521 bit prime field"}, "NIST/SECG curve over a 521 bit prime field"},
#endif # endif
/* X9.62 curves */ /* X9.62 curves */
{NID_X9_62_prime192v1, &_EC_NIST_PRIME_192.h, 0, {NID_X9_62_prime192v1, &_EC_NIST_PRIME_192.h, 0,
"NIST/X9.62/SECG curve over a 192 bit prime field"}, "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, {NID_X9_62_prime239v3, &_EC_X9_62_PRIME_239V3.h, 0,
"X9.62 curve over a 239 bit prime field"}, "X9.62 curve over a 239 bit prime field"},
{NID_X9_62_prime256v1, &_EC_X9_62_PRIME_256V1.h, {NID_X9_62_prime256v1, &_EC_X9_62_PRIME_256V1.h,
#if defined(ECP_NISTZ256_ASM) # if defined(ECP_NISTZ256_ASM)
EC_GFp_nistz256_method, 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, EC_GFp_nistp256_method,
#else # else
0, 0,
#endif # endif
"X9.62/SECG curve over a 256 bit prime field"}, "X9.62/SECG curve over a 256 bit prime field"},
#ifndef OPENSSL_NO_EC2M # ifndef OPENSSL_NO_EC2M
/* characteristic two field curves */ /* characteristic two field curves */
/* NIST/SECG curves */ /* NIST/SECG curves */
{NID_sect113r1, &_EC_SECG_CHAR2_113R1.h, 0, {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"}, "SECG curve over a 113 bit binary field"},
{NID_wap_wsg_idm_ecid_wtls5, &_EC_X9_62_CHAR2_163V1.h, 0, {NID_wap_wsg_idm_ecid_wtls5, &_EC_X9_62_CHAR2_163V1.h, 0,
"X9.62 curve over a 163 bit binary field"}, "X9.62 curve over a 163 bit binary field"},
#endif # endif
{NID_wap_wsg_idm_ecid_wtls6, &_EC_SECG_PRIME_112R1.h, 0, {NID_wap_wsg_idm_ecid_wtls6, &_EC_SECG_PRIME_112R1.h, 0,
"SECG/WTLS curve over a 112 bit prime field"}, "SECG/WTLS curve over a 112 bit prime field"},
{NID_wap_wsg_idm_ecid_wtls7, &_EC_SECG_PRIME_160R2.h, 0, {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"}, "WTLS curve over a 112 bit prime field"},
{NID_wap_wsg_idm_ecid_wtls9, &_EC_WTLS_9.h, 0, {NID_wap_wsg_idm_ecid_wtls9, &_EC_WTLS_9.h, 0,
"WTLS curve over a 160 bit prime field"}, "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, {NID_wap_wsg_idm_ecid_wtls10, &_EC_NIST_CHAR2_233K.h, 0,
"NIST/SECG/WTLS curve over a 233 bit binary field"}, "NIST/SECG/WTLS curve over a 233 bit binary field"},
{NID_wap_wsg_idm_ecid_wtls11, &_EC_NIST_CHAR2_233B.h, 0, {NID_wap_wsg_idm_ecid_wtls11, &_EC_NIST_CHAR2_233B.h, 0,
"NIST/SECG/WTLS curve over a 233 bit binary field"}, "NIST/SECG/WTLS curve over a 233 bit binary field"},
#endif # endif
{NID_wap_wsg_idm_ecid_wtls12, &_EC_WTLS_12.h, 0, {NID_wap_wsg_idm_ecid_wtls12, &_EC_WTLS_12.h, 0,
"WTLS curve over a 224 bit prime field"}, "WTLS curve over a 224 bit prime field"},
#ifndef OPENSSL_NO_EC2M # ifndef OPENSSL_NO_EC2M
/* IPSec curves */ /* IPSec curves */
{NID_ipsec3, &_EC_IPSEC_155_ID3.h, 0, {NID_ipsec3, &_EC_IPSEC_155_ID3.h, 0,
"\n\tIPSec/IKE/Oakley curve #3 over a 155 bit binary field.\n" "\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, {NID_ipsec4, &_EC_IPSEC_185_ID4.h, 0,
"\n\tIPSec/IKE/Oakley curve #4 over a 185 bit binary field.\n" "\n\tIPSec/IKE/Oakley curve #4 over a 185 bit binary field.\n"
"\tNot suitable for ECDSA.\n\tQuestionable extension field!"}, "\tNot suitable for ECDSA.\n\tQuestionable extension field!"},
#endif # endif
/* brainpool curves */ /* brainpool curves */
{NID_brainpoolP160r1, &_EC_brainpoolP160r1.h, 0, {NID_brainpoolP160r1, &_EC_brainpoolP160r1.h, 0,
"RFC 5639 curve over a 160 bit prime field"}, "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"}, "RFC 5639 curve over a 512 bit prime field"},
{NID_brainpoolP512t1, &_EC_brainpoolP512t1.h, 0, {NID_brainpoolP512t1, &_EC_brainpoolP512t1.h, 0,
"RFC 5639 curve over a 512 bit prime field"}, "RFC 5639 curve over a 512 bit prime field"},
#ifndef OPENSSL_NO_SM2 # ifndef OPENSSL_NO_SM2
{NID_sm2, &_EC_sm2p256v1.h, 0, {NID_sm2, &_EC_sm2p256v1.h, 0,
"SM2 curve over a 256 bit prime field"}, "SM2 curve over a 256 bit prime field"},
#endif # endif
}; };
#endif /* FIPS_MODE */
#define curve_list_length OSSL_NELEM(curve_list) #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) if (nid <= 0)
return NULL; 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++) for (i = 0; i < curve_list_length; i++)
if (curve_list[i].nid == nid) { if (curve_list[i].nid == nid) {
ret = ec_group_new_from_data(curve_list[i]); ret = ec_group_new_from_data(curve_list[i]);

View File

@ -118,6 +118,11 @@ static int x9_62_tests(int n)
TEST_info("ECDSA KATs for curve %s", OBJ_nid2sn(nid)); 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()) if (!TEST_ptr(mctx = EVP_MD_CTX_new())
/* get the message digest */ /* get the message digest */
|| !TEST_ptr(message = OPENSSL_hexstr2buf(tbs, &msg_len)) || !TEST_ptr(message = OPENSSL_hexstr2buf(tbs, &msg_len))

View File

@ -1820,7 +1820,7 @@ static int parameter_test(void)
unsigned char *buf = NULL; unsigned char *buf = NULL;
int r = 0, len; 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(ecparameters = EC_GROUP_get_ecparameters(group, NULL))
|| !TEST_ptr(group2 = EC_GROUP_new_from_ecparameters(ecparameters)) || !TEST_ptr(group2 = EC_GROUP_new_from_ecparameters(ecparameters))
|| !TEST_int_eq(EC_GROUP_cmp(group, group2, NULL), 0)) || !TEST_int_eq(EC_GROUP_cmp(group, group2, NULL), 0))

View File

@ -599,7 +599,7 @@ static int test_EVP_PKCS82PKEY(void)
} }
#endif #endif
#ifndef OPENSSL_NO_SM2 #if !defined(OPENSSL_NO_SM2) && !defined(FIPS_MODE)
static int test_EVP_SM2_verify(void) static int test_EVP_SM2_verify(void)
{ {
@ -1238,7 +1238,7 @@ int setup_tests(void)
#ifndef OPENSSL_NO_EC #ifndef OPENSSL_NO_EC
ADD_TEST(test_EVP_PKCS82PKEY); ADD_TEST(test_EVP_PKCS82PKEY);
#endif #endif
#ifndef OPENSSL_NO_SM2 #if !defined(OPENSSL_NO_SM2) && !defined(FIPS_MODE)
ADD_TEST(test_EVP_SM2); ADD_TEST(test_EVP_SM2);
ADD_TEST(test_EVP_SM2_verify); ADD_TEST(test_EVP_SM2_verify);
#endif #endif

View File

@ -85,7 +85,7 @@ static const unsigned char dsaparam_bin[] = {
#ifndef OPENSSL_NO_EC #ifndef OPENSSL_NO_EC
static const unsigned char ecparam_bin[] = { static const unsigned char ecparam_bin[] = {
0x06,0x05,0x2b,0x81,0x04,0x00,0x0a 0x06,0x08,0x2a,0x86,0x48,0xce,0x3d,0x03,0x01,0x07
}; };
#endif #endif

View File

@ -10,7 +10,7 @@ use strict;
use warnings; use warnings;
use File::Spec; use File::Spec;
use OpenSSL::Test qw/:DEFAULT srctop_file/; use OpenSSL::Test qw/:DEFAULT srctop_file ok_nofips/;
use OpenSSL::Test::Utils; use OpenSSL::Test::Utils;
setup("test_pkeyutl"); setup("test_pkeyutl");
@ -24,13 +24,13 @@ SKIP: {
if disabled("ec") || disabled("sm2") || disabled("sm3"); if disabled("ec") || disabled("sm2") || disabled("sm3");
# SM2 # SM2
ok(run(app(([ 'openssl', 'pkeyutl', '-sign', ok_nofips(run(app(([ 'openssl', 'pkeyutl', '-sign',
'-in', srctop_file('test', 'certs', 'sm2.pem'), '-in', srctop_file('test', 'certs', 'sm2.pem'),
'-inkey', srctop_file('test', 'certs', 'sm2.key'), '-inkey', srctop_file('test', 'certs', 'sm2.key'),
'-out', 'signature.dat', '-rawin', '-out', 'signature.dat', '-rawin',
'-digest', 'sm3', '-pkeyopt', 'sm2_id:someid']))), '-digest', 'sm3', '-pkeyopt', 'sm2_id:someid']))),
"Sign a piece of data using SM2"); "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'), '-in', srctop_file('test', 'certs', 'sm2.pem'),
'-inkey', srctop_file('test', 'certs', 'sm2.pem'), '-inkey', srctop_file('test', 'certs', 'sm2.pem'),
'-sigfile', 'signature.dat', '-rawin', '-sigfile', 'signature.dat', '-rawin',

View File

@ -11,7 +11,7 @@ use strict;
use warnings; use warnings;
use File::Spec::Functions qw/canonpath/; 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; use OpenSSL::Test::Utils;
setup("test_verify"); setup("test_verify");
@ -379,9 +379,9 @@ SKIP: {
if disabled("sm2"); if disabled("sm2");
# Test '-sm2-id' and '-sm2-hex-id' option # 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"); "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"), "31323334353637383132333435363738"),
"SM2 hex ID test"); "SM2 hex ID test");
} }