summaryrefslogtreecommitdiffstats
path: root/crypto/rsa
diff options
context:
space:
mode:
authorShane Lontis <shane.lontis@oracle.com>2020-06-17 11:33:16 +1000
committerShane Lontis <shane.lontis@oracle.com>2020-06-17 11:33:16 +1000
commit4f2271d58a36b2aee125062ffb9626c6208fa394 (patch)
tree122e6de930647c37a35b5f457448a031e51969b8 /crypto/rsa
parent5a147abd790075cdc97b36ff5084e2eb1d779b95 (diff)
Add ACVP fips module tests
For FIPS validation purposes - Automated Cryptographic Validation Protocol (ACVP) tests need to be performed. (See https://github.com/usnistgov/ACVP). These tests are very similiar to the old CAVS tests. This PR uses a hardwired subset of these test vectors to perform similiar operations, to show the usage and prove that the API's are able to perform the required operations. It may also help with communication with the lab (i.e- The lab could add a test here to show a unworking use case - which we can then address). The EVP layer performs these tests instead of calling lower level API's as was done in the old FOM. Some of these tests require access to internals that are not normally allowed/required. The config option 'acvp_tests' (enabled by default) has been added so that this access may be removed. The mechanism has been implemented as additional OSSL_PARAM values that can be set and get. A callback mechanism did not seem to add any additional benefit. These params will not be added to the gettables lists. Reviewed-by: Matt Caswell <matt@openssl.org> (Merged from https://github.com/openssl/openssl/pull/11572)
Diffstat (limited to 'crypto/rsa')
-rw-r--r--crypto/rsa/build.info4
-rw-r--r--crypto/rsa/rsa_acvp_test_params.c167
-rw-r--r--crypto/rsa/rsa_backend.c8
-rw-r--r--crypto/rsa/rsa_gen.c4
-rw-r--r--crypto/rsa/rsa_lib.c5
-rw-r--r--crypto/rsa/rsa_local.h38
-rw-r--r--crypto/rsa/rsa_sp800_56b_gen.c74
7 files changed, 262 insertions, 38 deletions
diff --git a/crypto/rsa/build.info b/crypto/rsa/build.info
index 984ad775d5..1614996049 100644
--- a/crypto/rsa/build.info
+++ b/crypto/rsa/build.info
@@ -13,3 +13,7 @@ IF[{- !$disabled{'deprecated-0.9.8'} -}]
ENDIF
SOURCE[../../providers/libfips.a]=$COMMON
+
+IF[{- !$disabled{'acvp-tests'} -}]
+ SOURCE[../../providers/libfips.a]=rsa_acvp_test_params.c
+ENDIF \ No newline at end of file
diff --git a/crypto/rsa/rsa_acvp_test_params.c b/crypto/rsa/rsa_acvp_test_params.c
new file mode 100644
index 0000000000..c1d07cb334
--- /dev/null
+++ b/crypto/rsa/rsa_acvp_test_params.c
@@ -0,0 +1,167 @@
+/*
+ * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <string.h> /* memcpy */
+#include <openssl/core_names.h>
+#include <openssl/param_build.h>
+#include "crypto/rsa.h"
+#include "rsa_local.h"
+
+int rsa_acvp_test_gen_params_new(OSSL_PARAM **dst, const OSSL_PARAM src[])
+{
+ const OSSL_PARAM *p, *s;
+ OSSL_PARAM *d, *alloc = NULL;
+ int ret = 1;
+
+ static const OSSL_PARAM settable[] = {
+ OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_TEST_XP, NULL, 0),
+ OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_TEST_XP1, NULL, 0),
+ OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_TEST_XP2, NULL, 0),
+ OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_TEST_XQ, NULL, 0),
+ OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_TEST_XQ1, NULL, 0),
+ OSSL_PARAM_BN(OSSL_PKEY_PARAM_RSA_TEST_XQ2, NULL, 0),
+ OSSL_PARAM_END
+ };
+
+ /* Assume the first element is a required field if this feature is used */
+ p = OSSL_PARAM_locate_const(src, settable[0].key);
+ if (p == NULL)
+ return 1;
+
+ /* Zeroing here means the terminator is always set at the end */
+ alloc = OPENSSL_zalloc(sizeof(settable));
+ if (alloc == NULL)
+ return 0;
+
+ d = alloc;
+ for (s = settable; s->key != NULL; ++s) {
+ /* If src contains a key from settable then copy the src to the dest */
+ p = OSSL_PARAM_locate_const(src, s->key);
+ if (p != NULL) {
+ *d = *s; /* shallow copy from the static settable[] */
+ d->data_size = p->data_size;
+ d->data = OPENSSL_memdup(p->data, p->data_size);
+ if (d->data == NULL)
+ ret = 0;
+ ++d;
+ }
+ }
+ if (ret == 0) {
+ rsa_acvp_test_gen_params_free(alloc);
+ alloc = NULL;
+ }
+ if (*dst != NULL)
+ rsa_acvp_test_gen_params_free(*dst);
+ *dst = alloc;
+ return ret;
+}
+
+void rsa_acvp_test_gen_params_free(OSSL_PARAM *dst)
+{
+ OSSL_PARAM *p;
+
+ if (dst == NULL)
+ return;
+
+ for (p = dst; p->key != NULL; ++p) {
+ OPENSSL_free(p->data);
+ p->data = NULL;
+ }
+ OPENSSL_free(dst);
+}
+
+int rsa_acvp_test_set_params(RSA *r, const OSSL_PARAM params[])
+{
+ RSA_ACVP_TEST *t;
+ const OSSL_PARAM *p;
+
+ if (r->acvp_test != NULL) {
+ rsa_acvp_test_free(r->acvp_test);
+ r->acvp_test = NULL;
+ }
+
+ t = OPENSSL_zalloc(sizeof(*t));
+ if (t == NULL)
+ return 0;
+
+ /* Set the input parameters */
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_TEST_XP1)) != NULL
+ && !OSSL_PARAM_get_BN(p, &t->Xp1))
+ goto err;
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_TEST_XP2)) != NULL
+ && !OSSL_PARAM_get_BN(p, &t->Xp2))
+ goto err;
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_TEST_XP)) != NULL
+ && !OSSL_PARAM_get_BN(p, &t->Xp))
+ goto err;
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_TEST_XQ1)) != NULL
+ && !OSSL_PARAM_get_BN(p, &t->Xq1))
+ goto err;
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_TEST_XQ2)) != NULL
+ && !OSSL_PARAM_get_BN(p, &t->Xq2))
+ goto err;
+ if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_RSA_TEST_XQ)) != NULL
+ && !OSSL_PARAM_get_BN(p, &t->Xq))
+ goto err;
+
+ /* Setup the output parameters */
+ t->p1 = BN_new();
+ t->p2 = BN_new();
+ t->q1 = BN_new();
+ t->q2 = BN_new();
+ r->acvp_test = t;
+ return 1;
+err:
+ rsa_acvp_test_free(t);
+ return 0;
+}
+
+int rsa_acvp_test_get_params(RSA *r, OSSL_PARAM params[])
+{
+ RSA_ACVP_TEST *t;
+ OSSL_PARAM *p;
+
+ if (r == NULL)
+ return 0;
+
+ t = r->acvp_test;
+ if (t != NULL) {
+ if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_RSA_TEST_P1)) != NULL
+ && !OSSL_PARAM_set_BN(p, t->p1))
+ return 0;
+ if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_RSA_TEST_P2)) != NULL
+ && !OSSL_PARAM_set_BN(p, t->p2))
+ return 0;
+ if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_RSA_TEST_Q1)) != NULL
+ && !OSSL_PARAM_set_BN(p, t->q1))
+ return 0;
+ if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_RSA_TEST_Q2)) != NULL
+ && !OSSL_PARAM_set_BN(p, t->q2))
+ return 0;
+ }
+ return 1;
+}
+
+void rsa_acvp_test_free(RSA_ACVP_TEST *t)
+{
+ if (t != NULL) {
+ BN_free(t->Xp1);
+ BN_free(t->Xp2);
+ BN_free(t->Xp);
+ BN_free(t->Xq1);
+ BN_free(t->Xq2);
+ BN_free(t->Xq);
+ BN_free(t->p1);
+ BN_free(t->p2);
+ BN_free(t->q1);
+ BN_free(t->q2);
+ OPENSSL_free(t);
+ }
+}
+
diff --git a/crypto/rsa/rsa_backend.c b/crypto/rsa/rsa_backend.c
index 7497a8579c..985a21127a 100644
--- a/crypto/rsa/rsa_backend.c
+++ b/crypto/rsa/rsa_backend.c
@@ -88,6 +88,7 @@ int rsa_fromdata(RSA *rsa, const OSSL_PARAM params[])
goto err;
}
+
sk_BIGNUM_free(factors);
sk_BIGNUM_free(exps);
sk_BIGNUM_free(coeffs);
@@ -126,7 +127,7 @@ int rsa_todata(RSA *rsa, OSSL_PARAM_BLD *bld, OSSL_PARAM params[])
int numcoeffs = sk_BIGNUM_const_num(coeffs);
/*
- * It's permisssible to have zero primes, i.e. no CRT params.
+ * It's permissible to have zero primes, i.e. no CRT params.
* Otherwise, there must be at least two, as many exponents,
* and one coefficient less.
*/
@@ -145,6 +146,11 @@ int rsa_todata(RSA *rsa, OSSL_PARAM_BLD *bld, OSSL_PARAM params[])
|| !ossl_param_build_set_multi_key_bn(bld, params, rsa_mp_coeff_names,
coeffs))
goto err;
+#if defined(FIPS_MODULE) && !defined(OPENSSL_NO_ACVP_TESTS)
+ /* The acvp test results are not meant for export so check for bld == NULL */
+ if (bld == NULL)
+ rsa_acvp_test_get_params(rsa, params);
+#endif
ret = 1;
err:
sk_BIGNUM_const_free(factors);
diff --git a/crypto/rsa/rsa_gen.c b/crypto/rsa/rsa_gen.c
index e52bce6355..1495cefa83 100644
--- a/crypto/rsa/rsa_gen.c
+++ b/crypto/rsa/rsa_gen.c
@@ -66,8 +66,8 @@ int RSA_generate_multi_prime_key(RSA *rsa, int bits, int primes,
else
return 0;
}
-#endif /* FIPS_MODULE */
- return rsa_keygen(NULL, rsa, bits, primes, e_value, cb, 0);
+#endif /* FIPS_MODUKE */
+ return rsa_keygen(rsa->libctx, rsa, bits, primes, e_value, cb, 0);
}
#ifndef FIPS_MODULE
diff --git a/crypto/rsa/rsa_lib.c b/crypto/rsa/rsa_lib.c
index e80416ed3f..428cd145fa 100644
--- a/crypto/rsa/rsa_lib.c
+++ b/crypto/rsa/rsa_lib.c
@@ -162,6 +162,11 @@ void RSA_free(RSA *r)
BN_clear_free(r->dmp1);
BN_clear_free(r->dmq1);
BN_clear_free(r->iqmp);
+
+#if defined(FIPS_MODULE) && !defined(OPENSSL_NO_ACVP_TESTS)
+ rsa_acvp_test_free(r->acvp_test);
+#endif
+
#ifndef FIPS_MODULE
RSA_PSS_PARAMS_free(r->pss);
sk_RSA_PRIME_INFO_pop_free(r->prime_infos, rsa_multip_info_free);
diff --git a/crypto/rsa/rsa_local.h b/crypto/rsa/rsa_local.h
index 65fd6022f7..666e18ec65 100644
--- a/crypto/rsa/rsa_local.h
+++ b/crypto/rsa/rsa_local.h
@@ -10,7 +10,7 @@
#ifndef OSSL_CRYPTO_RSA_LOCAL_H
#define OSSL_CRYPTO_RSA_LOCAL_H
-#include <openssl/rsa.h>
+#include "crypto/rsa.h"
#include "internal/refcount.h"
#include "crypto/rsa.h"
@@ -29,6 +29,24 @@ typedef struct rsa_prime_info_st {
DECLARE_ASN1_ITEM(RSA_PRIME_INFO)
DEFINE_STACK_OF(RSA_PRIME_INFO)
+#if defined(FIPS_MODULE) && !defined(OPENSSL_NO_ACVP_TESTS)
+struct rsa_acvp_test_st {
+ /* optional inputs */
+ BIGNUM *Xp1;
+ BIGNUM *Xp2;
+ BIGNUM *Xq1;
+ BIGNUM *Xq2;
+ BIGNUM *Xp;
+ BIGNUM *Xq;
+
+ /* optional outputs */
+ BIGNUM *p1;
+ BIGNUM *p2;
+ BIGNUM *q1;
+ BIGNUM *q2;
+};
+#endif
+
struct rsa_st {
/*
* #legacy
@@ -58,12 +76,14 @@ struct rsa_st {
*/
/* This is used uniquely by OpenSSL provider implementations. */
RSA_PSS_PARAMS_30 pss_params;
-#ifndef FIPS_MODULE
- /* This is used uniquely by rsa_ameth.c and rsa_pmeth.c. */
- RSA_PSS_PARAMS *pss;
+
+#if defined(FIPS_MODULE) && !defined(OPENSSL_NO_ACVP_TESTS)
+ RSA_ACVP_TEST *acvp_test;
#endif
#ifndef FIPS_MODULE
+ /* This is used uniquely by rsa_ameth.c and rsa_pmeth.c. */
+ RSA_PSS_PARAMS *pss;
/* for multi-prime RSA, defined in RFC 8017 */
STACK_OF(RSA_PRIME_INFO) *prime_infos;
/* Be careful using this if the RSA structure is shared */
@@ -172,13 +192,9 @@ int rsa_sp800_56b_generate_key(RSA *rsa, int nbits, const BIGNUM *efixed,
int rsa_sp800_56b_derive_params_from_pq(RSA *rsa, int nbits,
const BIGNUM *e, BN_CTX *ctx);
-int rsa_fips186_4_gen_prob_primes(RSA *rsa, BIGNUM *p1, BIGNUM *p2,
- BIGNUM *Xpout, const BIGNUM *Xp,
- const BIGNUM *Xp1, const BIGNUM *Xp2,
- BIGNUM *q1, BIGNUM *q2, BIGNUM *Xqout,
- const BIGNUM *Xq, const BIGNUM *Xq1,
- const BIGNUM *Xq2, int nbits,
- const BIGNUM *e, BN_CTX *ctx, BN_GENCB *cb);
+int rsa_fips186_4_gen_prob_primes(RSA *rsa, RSA_ACVP_TEST *test,
+ int nbits, const BIGNUM *e, BN_CTX *ctx,
+ BN_GENCB *cb);
int rsa_padding_add_SSLv23_with_libctx(OPENSSL_CTX *libctx, unsigned char *to,
int tlen, const unsigned char *from,
diff --git a/crypto/rsa/rsa_sp800_56b_gen.c b/crypto/rsa/rsa_sp800_56b_gen.c
index d1673d5c98..9d7e1f1ebf 100644
--- a/crypto/rsa/rsa_sp800_56b_gen.c
+++ b/crypto/rsa/rsa_sp800_56b_gen.c
@@ -10,6 +10,7 @@
#include <openssl/err.h>
#include <openssl/bn.h>
+#include <openssl/core.h>
#include "crypto/bn.h"
#include "crypto/security_bits.h"
#include "rsa_local.h"
@@ -25,20 +26,23 @@
*
* Params:
* rsa Object used to store primes p & q.
- * p1, p2 The returned auxiliary primes for p. If NULL they are not returned.
- * Xpout An optionally returned random number used during generation of p.
- * Xp An optional passed in value (that is random number used during
- * generation of p).
- * Xp1, Xp2 Optionally passed in randomly generated numbers from which
- * auxiliary primes p1 & p2 are calculated. If NULL these values
- * are generated internally.
- * q1, q2 The returned auxiliary primes for q. If NULL they are not returned.
- * Xqout An optionally returned random number used during generation of q.
- * Xq An optional passed in value (that is random number used during
- * generation of q).
- * Xq1, Xq2 Optionally passed in randomly generated numbers from which
- * auxiliary primes q1 & q2 are calculated. If NULL these values
- * are generated internally.
+ * test Object used for CAVS testing only.that contains..
+ * p1, p2 The returned auxiliary primes for p.
+ * If NULL they are not returned.
+ * Xpout An optionally returned random number used during generation of p.
+ * Xp An optional passed in value (that is random number used during
+ * generation of p).
+ * Xp1, Xp2 Optionally passed in randomly generated numbers from which
+ * auxiliary primes p1 & p2 are calculated. If NULL these values
+ * are generated internally.
+ * q1, q2 The returned auxiliary primes for q.
+ * If NULL they are not returned.
+ * Xqout An optionally returned random number used during generation of q.
+ * Xq An optional passed in value (that is random number used during
+ * generation of q).
+ * Xq1, Xq2 Optionally passed in randomly generated numbers from which
+ * auxiliary primes q1 & q2 are calculated. If NULL these values
+ * are generated internally.
* nbits The key size in bits (The size of the modulus n).
* e The public exponent.
* ctx A BN_CTX object.
@@ -49,16 +53,34 @@
* Xp, Xp1, Xp2, Xq, Xq1, Xq2 are optionally passed in.
* (Required for CAVS testing).
*/
-int rsa_fips186_4_gen_prob_primes(RSA *rsa, BIGNUM *p1, BIGNUM *p2,
- BIGNUM *Xpout, const BIGNUM *Xp,
- const BIGNUM *Xp1, const BIGNUM *Xp2,
- BIGNUM *q1, BIGNUM *q2, BIGNUM *Xqout,
- const BIGNUM *Xq, const BIGNUM *Xq1,
- const BIGNUM *Xq2, int nbits,
+int rsa_fips186_4_gen_prob_primes(RSA *rsa, RSA_ACVP_TEST *test, int nbits,
const BIGNUM *e, BN_CTX *ctx, BN_GENCB *cb)
{
int ret = 0, ok;
+ /* Temp allocated BIGNUMS */
BIGNUM *Xpo = NULL, *Xqo = NULL, *tmp = NULL;
+ /* Intermediate BIGNUMS that can be returned for testing */
+ BIGNUM *p1 = NULL, *p2 = NULL;
+ BIGNUM *q1 = NULL, *q2 = NULL;
+ /* Intermediate BIGNUMS that can be input for testing */
+ BIGNUM *Xpout = NULL, *Xqout = NULL;
+ BIGNUM *Xp = NULL, *Xp1 = NULL, *Xp2 = NULL;
+ BIGNUM *Xq = NULL, *Xq1 = NULL, *Xq2 = NULL;
+
+#if defined(FIPS_MODULE) && !defined(OPENSSL_NO_ACVP_TESTS)
+ if (test != NULL) {
+ Xp1 = test->Xp1;
+ Xp2 = test->Xp2;
+ Xq1 = test->Xq1;
+ Xq2 = test->Xq2;
+ Xp = test->Xp;
+ Xq = test->Xq;
+ p1 = test->p1;
+ p2 = test->p2;
+ q1 = test->q1;
+ q2 = test->q2;
+ }
+#endif
/* (Step 1) Check key length
* NOTE: SP800-131A Rev1 Disallows key lengths of < 2048 bits for RSA
@@ -294,6 +316,11 @@ int rsa_sp800_56b_generate_key(RSA *rsa, int nbits, const BIGNUM *efixed,
int ok;
BN_CTX *ctx = NULL;
BIGNUM *e = NULL;
+ RSA_ACVP_TEST *info = NULL;
+
+#if defined(FIPS_MODULE) && !defined(OPENSSL_NO_ACVP_TESTS)
+ info = rsa->acvp_test;
+#endif
/* (Steps 1a-1b) : Currently ignores the strength check */
if (!rsa_sp800_56b_validate_strength(nbits, -1))
@@ -311,13 +338,12 @@ int rsa_sp800_56b_generate_key(RSA *rsa, int nbits, const BIGNUM *efixed,
} else {
e = (BIGNUM *)efixed;
}
- /* (Step 1c) fixed exponent is checked later . */
+ /* (Step 1c) fixed exponent is checked later .*/
for (;;) {
/* (Step 2) Generate prime factors */
- if (!rsa_fips186_4_gen_prob_primes(rsa, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, nbits, e, ctx, cb))
+ if (!rsa_fips186_4_gen_prob_primes(rsa, info, nbits, e, ctx,
+ cb))
goto err;
/* (Steps 3-5) Compute params d, n, dP, dQ, qInv */
ok = rsa_sp800_56b_derive_params_from_pq(rsa, nbits, e, ctx);