File openssl-fips-ECDSA-KAT.patch of Package openssl-1_1.39892
Index: openssl-1.1.1l/crypto/fips/fips_ecdsa_selftest.c
===================================================================
--- openssl-1.1.1l.orig/crypto/fips/fips_ecdsa_selftest.c
+++ openssl-1.1.1l/crypto/fips/fips_ecdsa_selftest.c
@@ -75,8 +75,7 @@ static int fbytes(unsigned char *buf, in
static RAND_METHOD fake_rand;
static const RAND_METHOD *old_rand;
static int use_fake = 0;
-static const unsigned char *numbers[2];
-static int numbers_len[2];
+static const char *numbers[2];
static int change_rand(void)
{
@@ -84,14 +83,14 @@ static int change_rand(void)
old_rand = RAND_get_rand_method();
if (!old_rand)
return 0;
-
+
fake_rand = *old_rand;
/* use own random function */
fake_rand.bytes = fbytes;
/* set new RAND_METHOD */
if (!RAND_set_rand_method(&fake_rand))
return 0;
-
+
return 1;
}
@@ -99,7 +98,7 @@ static int restore_rand(void)
{
if (!RAND_set_rand_method(old_rand))
return 0;
-
+
return 1;
}
@@ -107,276 +106,190 @@ static int fbytes(unsigned char *buf, in
{
int ret = 0;
static int fbytes_counter = 0;
-
+ BIGNUM *tmp = NULL;
+
if (use_fake == 0)
return old_rand->bytes(buf, num);
-
use_fake = 0;
-
- if (fbytes_counter >= OSSL_NELEM(numbers))
+
+ tmp = BN_new();
+ if (!tmp)
+ goto err;
+
+ if (fbytes_counter > OSSL_NELEM(numbers))
goto err;
-
- if (numbers_len[fbytes_counter] > num)
+
+ if (!BN_hex2bn(&tmp, numbers[fbytes_counter]))
goto err;
-
- /* first zero out the buffer */
- memset(buf, 0, num);
-
- /* Now set the "random" values */
- memcpy(buf + (num - numbers_len[fbytes_counter]), numbers[fbytes_counter], numbers_len[fbytes_counter]);
-
+
+ /* tmp might need leading zeros so pad it out */
+ if (BN_num_bytes(tmp) > num)
+ goto err;
+
+ if (!BN_bn2binpad(tmp, buf, num))
+ goto err;
+
fbytes_counter = (fbytes_counter + 1) % OSSL_NELEM(numbers);
+
ret = 1;
err:
+ BN_free(tmp);
return ret;
}
-
-
-/*-
- * NIST CAVP ECDSA KATs
- * 2 X9.62 KATs; one for prime fields and one for binary fields.
- *
- * Taken from:
- * https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/dss/186-3ecdsatestvectors.zip
- */
-
typedef struct {
- const int nid; /* curve NID */
- const int md_nid; /* hash function NID */
- const unsigned char *msg; /* message to sign */
- size_t msglen;
- const unsigned char *d; /* ECDSA private key */
- size_t dlen;
- const unsigned char *Q; /* ECDSA public key: (Qx,Qy) */
- size_t Qlen;
- const unsigned char *k; /* ECDSA nonce */
- size_t klen;
- const unsigned char *r; /* ECDSA signature (r,s) */
- size_t rlen;
- const unsigned char *s;
- size_t slen;
-} ECDSA_KAT_SELFTEST_DATA;
-
-
-static const unsigned char data1_msg[] = {
- 0x59, 0x05, 0x23, 0x88, 0x77, 0xc7, 0x74, 0x21,
- 0xf7, 0x3e, 0x43, 0xee, 0x3d, 0xa6, 0xf2, 0xd9,
- 0xe2, 0xcc, 0xad, 0x5f, 0xc9, 0x42, 0xdc, 0xec,
- 0x0c, 0xbd, 0x25, 0x48, 0x29, 0x35, 0xfa, 0xaf,
- 0x41, 0x69, 0x83, 0xfe, 0x16, 0x5b, 0x1a, 0x04,
- 0x5e, 0xe2, 0xbc, 0xd2, 0xe6, 0xdc, 0xa3, 0xbd,
- 0xf4, 0x6c, 0x43, 0x10, 0xa7, 0x46, 0x1f, 0x9a,
- 0x37, 0x96, 0x0c, 0xa6, 0x72, 0xd3, 0xfe, 0xb5,
- 0x47, 0x3e, 0x25, 0x36, 0x05, 0xfb, 0x1d, 0xdf,
- 0xd2, 0x80, 0x65, 0xb5, 0x3c, 0xb5, 0x85, 0x8a,
- 0x8a, 0xd2, 0x81, 0x75, 0xbf, 0x9b, 0xd3, 0x86,
- 0xa5, 0xe4, 0x71, 0xea, 0x7a, 0x65, 0xc1, 0x7c,
- 0xc9, 0x34, 0xa9, 0xd7, 0x91, 0xe9, 0x14, 0x91,
- 0xeb, 0x37, 0x54, 0xd0, 0x37, 0x99, 0x79, 0x0f,
- 0xe2, 0xd3, 0x08, 0xd1, 0x61, 0x46, 0xd5, 0xc9,
- 0xb0, 0xd0, 0xde, 0xbd, 0x97, 0xd7, 0x9c, 0xe8
+ const int nid; /* curve NID */
+ const int md_nid; /* hash function NID */
+ const char *msg; /* message to sign */
+ const char *d; /* ECDSA private key */
+ const char *Q; /* ECDSA public key: Q = dG */
+ const char *k; /* ECDSA nonce */
+ const char *r; /* ECDSA signature (r,s) */
+ const char *s;
+} ecdsa_cavs_kat_t;
+
+static const ecdsa_cavs_kat_t ecdsa_cavs_kats[] = {
+ /* prime KATs from X9.62 */
+ {NID_X9_62_prime256v1, NID_sha256,
+ "5905238877c77421f73e43ee3da6f2d9e2ccad5fc942dcec0cbd25482935faaf416983fe"
+ "165b1a045ee2bcd2e6dca3bdf46c4310a7461f9a37960ca672d3feb5473e253605fb1ddf"
+ "d28065b53cb5858a8ad28175bf9bd386a5e471ea7a65c17cc934a9d791e91491eb3754d0"
+ "3799790fe2d308d16146d5c9b0d0debd97d79ce8",
+ "519b423d715f8b581f4fa8ee59f4771a5b44c8130b4e3eacca54a56dda72b464",
+ "041ccbe91c075fc7f4f033bfa248db8fccd3565de94bbfb12f3c59ff46c271bf83ce4014"
+ "c68811f9a21a1fdb2c0e6113e06db7ca93b7404e78dc7ccd5ca89a4ca9",
+ "94a1bbb14b906a61a280f245f9e93c7f3b4a6247824f5d33b9670787642a68de",
+ "f3ac8061b514795b8843e3d6629527ed2afd6b1f6a555a7acabb5e6f79c8c2ac",
+ "8bf77819ca05a6b2786c76262bf7371cef97b218e96f175a3ccdda2acc058903"},
};
-static const unsigned char data1_d[] = {
- 0x51, 0x9b, 0x42, 0x3d, 0x71, 0x5f, 0x8b, 0x58,
- 0x1f, 0x4f, 0xa8, 0xee, 0x59, 0xf4, 0x77, 0x1a,
- 0x5b, 0x44, 0xc8, 0x13, 0x0b, 0x4e, 0x3e, 0xac,
- 0xca, 0x54, 0xa5, 0x6d, 0xda, 0x72, 0xb4, 0x64
-};
+int FIPS_selftest_ecdsa()
+{
+ int nid, md_nid, ret = 0;
+ int n = 0;
+ const char *r_in = NULL, *s_in = NULL, *tbs = NULL;
+ unsigned char *pbuf = NULL, *qbuf = NULL, *message = NULL;
+ unsigned char digest[EVP_MAX_MD_SIZE];
+ unsigned int dgst_len = 0;
+ long q_len, msg_len = 0;
+ size_t p_len;
+ EVP_MD_CTX *mctx = NULL;
+ EC_KEY *key = NULL;
+ ECDSA_SIG *signature = NULL;
+ BIGNUM *r = NULL, *s = NULL;
+ BIGNUM *kinv = NULL, *rp = NULL;
+ const BIGNUM *sig_r = NULL, *sig_s = NULL;
-static const unsigned char data1_Q[] = {
- 0x04, 0x0c, 0xec, 0x02, 0x8e, 0xe0, 0x8d, 0x09,
- 0xe0, 0x26, 0x72, 0xa6, 0x83, 0x10, 0x81, 0x43,
- 0x54, 0xf9, 0xea, 0xbf, 0xff, 0x0d, 0xe6, 0xda,
- 0xcc, 0x1c, 0xd3, 0xa7, 0x74, 0x49, 0x60, 0x76,
- 0xae, 0xef, 0xf4, 0x71, 0xfb, 0xa0, 0x40, 0x98,
- 0x97, 0xb6, 0xa4, 0x8e, 0x88, 0x01, 0xad, 0x12,
- 0xf9, 0x5d, 0x00, 0x09, 0xb7, 0x53, 0xcf, 0x8f,
- 0x51, 0xc1, 0x28, 0xbf, 0x6b, 0x0b, 0xd2, 0x7f,
- 0xbd
-};
+ nid = ecdsa_cavs_kats[n].nid;
+ md_nid = ecdsa_cavs_kats[n].md_nid;
+ r_in = ecdsa_cavs_kats[n].r;
+ s_in = ecdsa_cavs_kats[n].s;
+ tbs = ecdsa_cavs_kats[n].msg;
+ numbers[0] = ecdsa_cavs_kats[n].d;
+ numbers[1] = ecdsa_cavs_kats[n].k;
-static const unsigned char data1_k[] = {
- 0x94, 0xa1, 0xbb, 0xb1, 0x4b, 0x90, 0x6a, 0x61,
- 0xa2, 0x80, 0xf2, 0x45, 0xf9, 0xe9, 0x3c, 0x7f,
- 0x3b, 0x4a, 0x62, 0x47, 0x82, 0x4f, 0x5d, 0x33,
- 0xb9, 0x67, 0x07, 0x87, 0x64, 0x2a, 0x68, 0xde
-};
+ mctx = EVP_MD_CTX_new();
+ if (!mctx) goto err;
-static const unsigned char data1_r[] = {
- 0xe3, 0x95, 0xf6, 0xdb, 0x12, 0x71, 0x90, 0xfa,
- 0x70, 0xa6, 0x80, 0xeb, 0xf6, 0x8a, 0x18, 0x35,
- 0x6f, 0xef, 0xf2, 0x36, 0x65, 0xb9, 0x31, 0xc3,
- 0xa2, 0x14, 0x80, 0xdf, 0x86, 0xc4, 0xec, 0xbc
-};
+ /* get the message digest */
+ message = OPENSSL_hexstr2buf(tbs, &msg_len);
+ if (!message) goto err;
-static const unsigned char data1_s[] = {
- 0xa5, 0x01, 0x04, 0x78, 0x93, 0xd9, 0x60, 0xcc,
- 0x20, 0xce, 0xbd, 0xbb, 0x6f, 0x79, 0xb9, 0x7e,
- 0x45, 0x23, 0x80, 0x73, 0x87, 0x83, 0x53, 0x63,
- 0xe3, 0x80, 0x2b, 0x68, 0xcf, 0x32, 0xa1, 0xa2
-};
+ if (!EVP_DigestInit_ex(mctx, EVP_get_digestbynid(md_nid), NULL))
+ goto err;
+ if (!EVP_DigestUpdate(mctx, message, msg_len))
+ goto err;
-# define make_ecdsa_kat_test(nid, md_nid, pr) { \
-nid, md_nid, \
-pr##_msg, sizeof(pr##_msg), \
-pr##_d, sizeof(pr##_d), \
-pr##_Q, sizeof(pr##_Q), \
-pr##_k, sizeof(pr##_k), \
-pr##_r, sizeof(pr##_r), \
-pr##_s, sizeof(pr##_s) \
-}
+ if (!EVP_DigestFinal_ex(mctx, digest, &dgst_len))
+ goto err;
-static ECDSA_KAT_SELFTEST_DATA test_ecdsa_data[] = {
- make_ecdsa_kat_test(NID_secp256k1, NID_sha256, data1)
-};
+ /* create the key */
+ key = EC_KEY_new_by_curve_name(nid);
+ if (!key)
+ goto err;
+
+ /* load KAT variables */
+ r = BN_new();
+ s = BN_new();
+ BN_hex2bn(&r, r_in);
+ BN_hex2bn(&s, s_in);
+ if (!r || !s || !r_in || !s_in)
+ goto err;
-int FIPS_selftest_ecdsa()
-{
- int rv;
- size_t i, siglen, p_len;
-
- for (i = 0; i < sizeof(test_ecdsa_data) / sizeof(ECDSA_KAT_SELFTEST_DATA); i++) {
- EC_KEY *ec = NULL;
- BIGNUM *r = NULL, *s = NULL;
- BIGNUM *sig_r = NULL, *sig_s = NULL;
- EVP_PKEY *pk = NULL;
- unsigned char *sig = NULL;
- unsigned char *tsig = NULL;
- unsigned char *p_buf = NULL;
- ECDSA_SIG *dsa_sig = NULL;
- rv = 0;
-
- ECDSA_KAT_SELFTEST_DATA *ecd = test_ecdsa_data + i;
-
- /* Create the Message Digest Context */
- EVP_MD_CTX *mdctx = EVP_MD_CTX_new();
- if (!mdctx) goto err;
-
- r = BN_bin2bn(ecd->r, ecd->rlen, r);
- s = BN_bin2bn(ecd->s, ecd->slen, s);
-
- if (!r || !s)
- goto err;
-
- /* d[] will be used to generate a key. */
- /* k[] will be used for signature generation. */
- numbers[0] = ecd->d;
- numbers_len[0] = ecd->dlen;
- numbers[1] = ecd->k;
- numbers_len[1] = ecd->klen;
/* swap the RNG source */
if (!change_rand())
goto err;
-
- ec = EC_KEY_new_by_curve_name(ecd->nid);
- if (!ec)
- goto err;
-
- /* Use d[] to generate key. */
+
+ /* public key must match KAT */
use_fake = 1;
- if (EC_KEY_generate_key(ec) != 1)
+ if (!EC_KEY_generate_key(key))
goto err;
-
- if ((pk = EVP_PKEY_new()) == NULL)
- goto err;
-
- EVP_PKEY_assign_EC_KEY(pk, ec);
-
- p_len = EC_KEY_key2buf(ec, POINT_CONVERSION_UNCOMPRESSED, &p_buf, NULL);
+
+ p_len = EC_KEY_key2buf(key, POINT_CONVERSION_UNCOMPRESSED, &pbuf, NULL);
if (!p_len)
goto err;
-
- /* Make sure generated public key matches */
- if (p_len != ecd->Qlen)
- goto err;
- if (memcmp(p_buf, ecd->Q, p_len))
- goto err;
-
- /* Initialise the DigestSign operation */
- if(1 != EVP_DigestSignInit(mdctx, NULL, EVP_get_digestbynid(ecd->md_nid), NULL, pk))
- goto err;
-
- /* Call update with the message */
- if(1 != EVP_DigestSignUpdate(mdctx, ecd->msg, ecd->msglen))
- goto err;
-
- /* Finalise the DigestSign operation */
- /* First call EVP_DigestSignFinal with a NULL sig parameter to */
- /* obtain the length of the signature. Length is returned in slen */
- if(1 != EVP_DigestSignFinal(mdctx, NULL, &siglen))
- goto err;
-
- /* Allocate memory for the signature based on size in slen */
- if(!(sig = OPENSSL_malloc(siglen)))
+
+ if (!(qbuf = OPENSSL_hexstr2buf(ecdsa_cavs_kats[n].Q, &q_len)))
+ goto err;
+
+ if (p_len != q_len)
+ goto err;
+
+ if (memcmp(pbuf, qbuf, p_len))
goto err;
-
- /* Use k[] for signature. */
+
+ /* create the signature via ECDSA_sign_setup to avoid use of ECDSA nonces */
use_fake = 1;
-
- /* Obtain the signature */
- if(1 != EVP_DigestSignFinal(mdctx, sig, &siglen))
+ if (!ECDSA_sign_setup(key, NULL, &kinv, &rp))
+ goto err;
+
+ if (!(signature = ECDSA_do_sign_ex(digest, dgst_len, kinv, rp, key)))
+ goto err;
+
+ if (!EVP_MD_CTX_reset(mctx))
+ goto err;
+
+ if (!EVP_DigestInit_ex(mctx, EVP_get_digestbynid(md_nid), NULL))
goto err;
- /* extract r and s */
- tsig = sig;
- dsa_sig = d2i_ECDSA_SIG(NULL, &tsig, siglen);
- if (dsa_sig == NULL)
- goto err;
-
- sig_r = ECDSA_SIG_get0_r(dsa_sig);
- sig_s = ECDSA_SIG_get0_s(dsa_sig);
+ if (!EVP_DigestUpdate(mctx, message, msg_len))
+ goto err;
+
+ if (!EVP_DigestFinal_ex(mctx, digest, &dgst_len))
+ goto err;
+
+ /* verify the signature */
+ if (!ECDSA_do_verify(digest, dgst_len, signature, key))
+ goto err;
+
+ /* compare the created signature with the expected signature */
+ ECDSA_SIG_get0(signature, &sig_r, &sig_s);
if ((sig_r == NULL) || (sig_s == NULL))
goto err;
- /* Compare r and s against known. */
+ /* Compare r and s against known */
if ((BN_cmp(sig_r, r) != 0) || (BN_cmp(sig_s, s) != 0))
goto err;
-
- /* Verify signature */
- if(1 != EVP_DigestVerifyInit(mdctx, NULL, EVP_get_digestbynid(ecd->md_nid), NULL, pk))
- goto err;
-
- if (EVP_DigestVerify(mdctx, sig, siglen, ecd->msg, ecd->msglen) != 1)
- goto err;
-
- if (1 != restore_rand())
- goto err;
-
- /* Success */
- rv = 1;
-
-
- err:
-
- if (mdctx)
- EVP_MD_CTX_free(mdctx);
- if (r)
- BN_clear_free(r);
- if (s)
- BN_clear_free(s);
- if (sig)
- OPENSSL_free(sig);
- if (dsa_sig)
- ECDSA_SIG_free(dsa_sig);
- if (p_buf)
- OPENSSL_free(p_buf);
- if (pk)
- EVP_PKEY_free(pk);
- else if (ec)
- EC_KEY_free(ec);
-
- if (rv != 1) {
- FIPSerr(FIPS_F_FIPS_SELFTEST_ECDSA, FIPS_R_SELFTEST_FAILED);
- break;
- }
-
- }
- return rv;
-
+ ret = 1;
+ err:
+ /* restore the RNG source */
+ if (!restore_rand())
+ ret = 0;
+
+ OPENSSL_free(message);
+ OPENSSL_free(pbuf);
+ OPENSSL_free(qbuf);
+ EC_KEY_free(key);
+ ECDSA_SIG_free(signature);
+ BN_free(r);
+ BN_free(s);
+ EVP_MD_CTX_free(mctx);
+ BN_clear_free(kinv);
+ BN_clear_free(rp);
+
+ return ret;
}