openssl-1_1/bsc1185319-FIPS-KAT-for-ECDSA.patch
Pedro Monreal Gonzalez 8f01c56ec8 Accepting request 1111331 from home:ohollmann:branches:security:tls
- Update to 1.1.1w:
 * Fix POLY1305 MAC implementation corrupting XMM registers on Windows.
   The POLY1305 MAC (message authentication code) implementation in OpenSSL
   does not save the contents of non-volatile XMM registers on Windows 64
   platform when calculating the MAC of data larger than 64 bytes. Before
   returning to the caller all the XMM registers are set to zero rather than
   restoring their previous content. The vulnerable code is used only on newer
   x86_64 processors supporting the AVX512-IFMA instructions.
   The consequences of this kind of internal application state corruption can
   be various - from no consequences, if the calling application does not
   depend on the contents of non-volatile XMM registers at all, to the worst
   consequences, where the attacker could get complete control of the
   application process. However given the contents of the registers are just
   zeroized so the attacker cannot put arbitrary values inside, the most likely
   consequence, if any, would be an incorrect result of some application
   dependent calculations or a crash leading to a denial of service.
   (CVE-2023-4807)

- Add missing FIPS patches from SLE:
  * Add patches:
    - bsc1185319-FIPS-KAT-for-ECDSA.patch
    - bsc1198207-FIPS-add-hash_hmac-drbg-kat.patch
    - openssl-1.1.1-fips-fix-memory-leaks.patch
    - openssl-1_1-FIPS-PBKDF2-KAT-requirements.patch
    - openssl-1_1-FIPS_drbg-rewire.patch
    - openssl-1_1-Zeroization.patch
    - openssl-1_1-fips-drbg-selftest.patch
    - openssl-1_1-fips-list-only-approved-digest-and-pubkey-algorithms.patch
    - openssl-1_1-jitterentropy-3.4.0.patch
    - openssl-1_1-ossl-sli-000-fix-build-error.patch

OBS-URL: https://build.opensuse.org/request/show/1111331
OBS-URL: https://build.opensuse.org/package/show/security:tls/openssl-1_1?expand=0&rev=144
2023-09-14 19:44:42 +00:00

400 lines
11 KiB
Diff

diff --git a/crypto/fips/fips_ecdsa_selftest.c b/crypto/fips/fips_ecdsa_selftest.c
index 9895aa8..77a1c77 100644
--- a/crypto/fips/fips_ecdsa_selftest.c
+++ b/crypto/fips/fips_ecdsa_selftest.c
@@ -65,102 +65,319 @@
#include <openssl/bn.h>
#ifdef OPENSSL_FIPS
+#include <openssl/rand.h>
+#include "internal/nelem.h"
+#include "fips_locl.h"
-static const char P_256_name[] = "ECDSA P-256";
+/* functions to change the RAND_METHOD */
+static int fbytes(unsigned char *buf, int num);
-static const unsigned char P_256_d[] = {
- 0x51, 0xbd, 0x06, 0xa1, 0x1c, 0xda, 0xe2, 0x12, 0x99, 0xc9, 0x52, 0x3f,
- 0xea, 0xa4, 0xd2, 0xd1, 0xf4, 0x7f, 0xd4, 0x3e, 0xbd, 0xf8, 0xfc, 0x87,
- 0xdc, 0x82, 0x53, 0x21, 0xee, 0xa0, 0xdc, 0x64
-};
+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 unsigned char P_256_qx[] = {
- 0x23, 0x89, 0xe0, 0xf4, 0x69, 0xe0, 0x49, 0xe5, 0xc7, 0xe5, 0x40, 0x6e,
- 0x8f, 0x25, 0xdd, 0xad, 0x11, 0x16, 0x14, 0x9b, 0xab, 0x44, 0x06, 0x31,
- 0xbf, 0x5e, 0xa6, 0x44, 0xac, 0x86, 0x00, 0x07
-};
+static int change_rand(void)
+{
+ /* save old rand method */
+ 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;
+}
-static const unsigned char P_256_qy[] = {
- 0xb3, 0x05, 0x0d, 0xd0, 0xdc, 0xf7, 0x40, 0xe6, 0xf9, 0xd8, 0x6d, 0x7b,
- 0x63, 0xca, 0x97, 0xe6, 0x12, 0xf9, 0xd4, 0x18, 0x59, 0xbe, 0xb2, 0x5e,
- 0x4a, 0x6a, 0x77, 0x23, 0xf4, 0x11, 0x9d, 0xeb
-};
+static int restore_rand(void)
+{
+ if (!RAND_set_rand_method(old_rand))
+ return 0;
+
+ return 1;
+}
+
+static int fbytes(unsigned char *buf, int num)
+{
+ int ret = 0;
+ static int fbytes_counter = 0;
+
+ if (use_fake == 0)
+ return old_rand->bytes(buf, num);
+
+ use_fake = 0;
+
+ if (fbytes_counter >= OSSL_NELEM(numbers))
+ goto err;
+
+ if (numbers_len[fbytes_counter] > num)
+ 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]);
+
+ fbytes_counter = (fbytes_counter + 1) % OSSL_NELEM(numbers);
+ ret = 1;
+err:
+ 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 {
- int curve;
- const char *name;
- const unsigned char *x;
- size_t xlen;
- const unsigned char *y;
- size_t ylen;
- const unsigned char *d;
- size_t dlen;
-} EC_SELFTEST_DATA;
-
-# define make_ecdsa_test(nid, pr) { nid, pr##_name, \
- pr##_qx, sizeof(pr##_qx), \
- pr##_qy, sizeof(pr##_qy), \
- pr##_d, sizeof(pr##_d)}
-
-static EC_SELFTEST_DATA test_ec_data[] = {
- make_ecdsa_test(NID_X9_62_prime256v1, P_256),
-};
+ 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;
-int FIPS_selftest_ecdsa()
-{
- EC_KEY *ec = NULL;
- BIGNUM *x = NULL, *y = NULL, *d = NULL;
- EVP_PKEY *pk = NULL;
- int rv = 0;
- size_t i;
- for (i = 0; i < sizeof(test_ec_data) / sizeof(EC_SELFTEST_DATA); i++) {
- EC_SELFTEST_DATA *ecd = test_ec_data + i;
+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
+};
- x = BN_bin2bn(ecd->x, ecd->xlen, x);
- y = BN_bin2bn(ecd->y, ecd->ylen, y);
- d = BN_bin2bn(ecd->d, ecd->dlen, d);
+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
+};
- if (!x || !y || !d)
- goto err;
+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
+};
- ec = EC_KEY_new_by_curve_name(ecd->curve);
- if (!ec)
- goto err;
+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
+};
- if (!EC_KEY_set_public_key_affine_coordinates(ec, x, y))
- 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
+};
- if (!EC_KEY_set_private_key(ec, d))
- 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 ((pk = EVP_PKEY_new()) == NULL)
- goto err;
- EVP_PKEY_assign_EC_KEY(pk, ec);
+# 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 (!fips_pkey_signature_test(pk, NULL, 0,
- NULL, 0, EVP_sha256(), 0, ecd->name))
- goto err;
- }
+static ECDSA_KAT_SELFTEST_DATA test_ecdsa_data[] = {
+ make_ecdsa_kat_test(NID_secp256k1, NID_sha256, data1)
+};
- rv = 1;
+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. */
+ use_fake = 1;
+ if (EC_KEY_generate_key(ec) != 1)
+ 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);
+ 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)))
+ goto err;
+
+ /* Use k[] for signature. */
+ use_fake = 1;
+
+ /* Obtain the signature */
+ if(1 != EVP_DigestSignFinal(mdctx, sig, &siglen))
+ goto err;
- 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 ((sig_r == NULL) || (sig_s == NULL))
+ goto err;
- if (x)
- BN_clear_free(x);
- if (y)
- BN_clear_free(y);
- if (d)
- BN_clear_free(d);
+ /* 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);
+ EVP_PKEY_free(pk);
else if (ec)
- EC_KEY_free(ec);
-
- return rv;
+ EC_KEY_free(ec);
+
+ if (rv != 1) {
+ FIPSerr(FIPS_F_FIPS_SELFTEST_ECDSA, FIPS_R_SELFTEST_FAILED);
+ break;
+ }
+
+ }
+ return rv;
+
}
+
#endif