summaryrefslogtreecommitdiffstats
path: root/crypto
diff options
context:
space:
mode:
Diffstat (limited to 'crypto')
-rw-r--r--crypto/build.info4
-rw-r--r--crypto/dh/dh_gen.c7
-rw-r--r--crypto/dsa/dsa_key.c67
-rw-r--r--crypto/ec/ec_key.c68
-rw-r--r--crypto/ec/ecp_s390x_nistp.c5
-rw-r--r--crypto/rsa/rsa_gen.c98
-rw-r--r--crypto/self_test_core.c108
7 files changed, 333 insertions, 24 deletions
diff --git a/crypto/build.info b/crypto/build.info
index b21cf3f45a..a688248acf 100644
--- a/crypto/build.info
+++ b/crypto/build.info
@@ -61,9 +61,9 @@ ENDIF
# The Core
$CORE_COMMON=provider_core.c provider_predefined.c \
- core_fetch.c core_algorithm.c core_namemap.c
+ core_fetch.c core_algorithm.c core_namemap.c self_test_core.c
-SOURCE[../libcrypto]=$CORE_COMMON provider_conf.c self_test_core.c
+SOURCE[../libcrypto]=$CORE_COMMON provider_conf.c
SOURCE[../providers/libfips.a]=$CORE_COMMON
# Central utilities
diff --git a/crypto/dh/dh_gen.c b/crypto/dh/dh_gen.c
index 8e2b773703..f8cda1b7e9 100644
--- a/crypto/dh/dh_gen.c
+++ b/crypto/dh/dh_gen.c
@@ -1,5 +1,5 @@
/*
- * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-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
@@ -15,6 +15,11 @@
/*
* DH low level APIs are deprecated for public use, but still ok for
* internal use.
+ *
+ * NOTE: When generating keys for key-agreement schemes - FIPS 140-2 IG 9.9
+ * states that no additional pairwise tests are required (apart from the tests
+ * specified in SP800-56A) when generating keys. Hence DH pairwise tests are
+ * omitted here.
*/
#include "internal/deprecated.h"
diff --git a/crypto/dsa/dsa_key.c b/crypto/dsa/dsa_key.c
index c93ea15b76..2dec35f28f 100644
--- a/crypto/dsa/dsa_key.c
+++ b/crypto/dsa/dsa_key.c
@@ -1,5 +1,5 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-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
@@ -17,10 +17,12 @@
#include <time.h>
#include "internal/cryptlib.h"
#include <openssl/bn.h>
+#include <openssl/self_test.h>
#include "crypto/dsa.h"
#include "dsa_local.h"
-static int dsa_builtin_keygen(DSA *dsa);
+static int dsa_keygen(DSA *dsa, int pairwise_test);
+static int dsa_keygen_pairwise_test(DSA *dsa, OSSL_CALLBACK *cb, void *cbarg);
int DSA_generate_key(DSA *dsa)
{
@@ -28,7 +30,7 @@ int DSA_generate_key(DSA *dsa)
if (dsa->meth->dsa_keygen != NULL)
return dsa->meth->dsa_keygen(dsa);
#endif
- return dsa_builtin_keygen(dsa);
+ return dsa_keygen(dsa, 0);
}
int dsa_generate_public_key(BN_CTX *ctx, const DSA *dsa, const BIGNUM *priv_key,
@@ -50,7 +52,7 @@ err:
return ret;
}
-static int dsa_builtin_keygen(DSA *dsa)
+static int dsa_keygen(DSA *dsa, int pairwise_test)
{
int ok = 0;
BN_CTX *ctx = NULL;
@@ -82,8 +84,26 @@ static int dsa_builtin_keygen(DSA *dsa)
dsa->priv_key = priv_key;
dsa->pub_key = pub_key;
- dsa->dirty_cnt++;
+
+#ifdef FIPS_MODE
+ pairwise_test = 1;
+#endif /* FIPS_MODE */
+
ok = 1;
+ if (pairwise_test) {
+ OSSL_CALLBACK *cb = NULL;
+ void *cbarg = NULL;
+
+ OSSL_SELF_TEST_get_callback(dsa->libctx, &cb, &cbarg);
+ ok = dsa_keygen_pairwise_test(dsa, cb, cbarg);
+ if (!ok) {
+ BN_free(dsa->pub_key);
+ BN_clear_free(dsa->priv_key);
+ BN_CTX_free(ctx);
+ return ok;
+ }
+ }
+ dsa->dirty_cnt++;
err:
if (pub_key != dsa->pub_key)
@@ -91,5 +111,42 @@ static int dsa_builtin_keygen(DSA *dsa)
if (priv_key != dsa->priv_key)
BN_free(priv_key);
BN_CTX_free(ctx);
+
return ok;
}
+
+/*
+ * FIPS 140-2 IG 9.9 AS09.33
+ * Perform a sign/verify operation.
+ */
+static int dsa_keygen_pairwise_test(DSA *dsa, OSSL_CALLBACK *cb, void *cbarg)
+{
+ int ret = 0;
+ unsigned char dgst[16] = {0};
+ unsigned int dgst_len = (unsigned int)sizeof(dgst);
+ DSA_SIG *sig = NULL;
+ OSSL_SELF_TEST *st = NULL;
+
+ st = OSSL_SELF_TEST_new(cb, cbarg);
+ if (st == NULL)
+ goto err;
+
+ OSSL_SELF_TEST_onbegin(st, OSSL_SELF_TEST_TYPE_PCT,
+ OSSL_SELF_TEST_DESC_PCT_DSA);
+
+ sig = DSA_do_sign(dgst, (int)dgst_len, dsa);
+ if (sig == NULL)
+ goto err;
+
+ OSSL_SELF_TEST_oncorrupt_byte(st, dgst);
+
+ if (DSA_do_verify(dgst, dgst_len, sig, dsa) != 1)
+ goto err;
+
+ ret = 1;
+err:
+ OSSL_SELF_TEST_onend(st, ret);
+ OSSL_SELF_TEST_free(st);
+ DSA_SIG_free(sig);
+ return ret;
+}
diff --git a/crypto/ec/ec_key.c b/crypto/ec/ec_key.c
index 4c56777dfe..18b544b9d3 100644
--- a/crypto/ec/ec_key.c
+++ b/crypto/ec/ec_key.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2002-2020 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
@@ -20,8 +20,12 @@
#include "internal/refcount.h"
#include <openssl/err.h>
#include <openssl/engine.h>
+#include <openssl/self_test.h>
#include "crypto/bn.h"
+static int ecdsa_keygen_pairwise_test(EC_KEY *eckey, OSSL_CALLBACK *cb,
+ void *cbarg);
+
#ifndef FIPS_MODE
EC_KEY *EC_KEY_new(void)
{
@@ -241,11 +245,14 @@ int ossl_ec_key_gen(EC_KEY *eckey)
* See SP800-56AR3 5.6.1.2.2 "Key Pair Generation by Testing Candidates"
*
* Params:
+ * libctx A context containing an optional self test callback.
* eckey An EC key object that contains domain params. The generated keypair
* is stored in this object.
+ * pairwise_test Set to non zero to perform a pairwise test. If the test
+ * fails then the keypair is not generated,
* Returns 1 if the keypair was generated or 0 otherwise.
*/
-int ec_key_simple_generate_key(EC_KEY *eckey)
+int ec_generate_key(OPENSSL_CTX *libctx, EC_KEY *eckey, int pairwise_test)
{
int ok = 0;
BIGNUM *priv_key = NULL;
@@ -305,8 +312,18 @@ int ec_key_simple_generate_key(EC_KEY *eckey)
eckey->dirty_cnt++;
+#ifdef FIPS_MODE
+ pairwise_test = 1;
+#endif /* FIPS_MODE */
+
ok = 1;
+ if (pairwise_test) {
+ OSSL_CALLBACK *cb = NULL;
+ void *cbarg = NULL;
+ OSSL_SELF_TEST_get_callback(libctx, &cb, &cbarg);
+ ok = ecdsa_keygen_pairwise_test(eckey, cb, cbarg);
+ }
err:
/* Step (9): If there is an error return an invalid keypair. */
if (!ok) {
@@ -321,6 +338,11 @@ err:
return ok;
}
+int ec_key_simple_generate_key(EC_KEY *eckey)
+{
+ return ec_generate_key(NULL, eckey, 0);
+}
+
int ec_key_simple_generate_public_key(EC_KEY *eckey)
{
int ret;
@@ -849,3 +871,45 @@ int EC_KEY_can_sign(const EC_KEY *eckey)
return 0;
return 1;
}
+
+/*
+ * FIPS 140-2 IG 9.9 AS09.33
+ * Perform a sign/verify operation.
+ *
+ * NOTE: When generating keys for key-agreement schemes - FIPS 140-2 IG 9.9
+ * states that no additional pairwise tests are required (apart from the tests
+ * specified in SP800-56A) when generating keys. Hence pairwise ECDH tests are
+ * omitted here.
+ */
+static int ecdsa_keygen_pairwise_test(EC_KEY *eckey, OSSL_CALLBACK *cb,
+ void *cbarg)
+{
+ int ret = 0;
+ unsigned char dgst[16] = {0};
+ int dgst_len = (int)sizeof(dgst);
+ ECDSA_SIG *sig = NULL;
+ OSSL_SELF_TEST *st = NULL;
+
+ st = OSSL_SELF_TEST_new(cb, cbarg);
+ if (st == NULL)
+ return 0;
+
+ OSSL_SELF_TEST_onbegin(st, OSSL_SELF_TEST_TYPE_PCT,
+ OSSL_SELF_TEST_DESC_PCT_ECDSA);
+
+ sig = ECDSA_do_sign(dgst, dgst_len, eckey);
+ if (sig == NULL)
+ goto err;
+
+ OSSL_SELF_TEST_oncorrupt_byte(st, dgst);
+
+ if (ECDSA_do_verify(dgst, dgst_len, sig, eckey) != 1)
+ goto err;
+
+ ret = 1;
+err:
+ OSSL_SELF_TEST_onend(st, ret);
+ OSSL_SELF_TEST_free(st);
+ ECDSA_SIG_free(sig);
+ return ret;
+}
diff --git a/crypto/ec/ecp_s390x_nistp.c b/crypto/ec/ecp_s390x_nistp.c
index a7cb5d3186..92b199d96a 100644
--- a/crypto/ec/ecp_s390x_nistp.c
+++ b/crypto/ec/ecp_s390x_nistp.c
@@ -169,12 +169,13 @@ static ECDSA_SIG *ecdsa_s390x_nistp_sign_sig(const unsigned char *dgst,
if (r == NULL || kinv == NULL) {
/*
- * Generate random k and copy to param param block. RAND_priv_bytes
+ * Generate random k and copy to param param block. RAND_priv_bytes_ex
* is used instead of BN_priv_rand_range or BN_generate_dsa_nonce
* because kdsa instruction constructs an in-range, invertible nonce
* internally implementing counter-measures for RNG weakness.
*/
- if (RAND_priv_bytes(param + S390X_OFF_RN(len), len) != 1) {
+ if (RAND_priv_bytes_ex(eckey->libctx, param + S390X_OFF_RN(len),
+ len) != 1) {
ECerr(EC_F_ECDSA_S390X_NISTP_SIGN_SIG,
EC_R_RANDOM_NUMBER_GENERATION_FAILED);
goto ret;
diff --git a/crypto/rsa/rsa_gen.c b/crypto/rsa/rsa_gen.c
index 5778bdada5..5d82ae6f34 100644
--- a/crypto/rsa/rsa_gen.c
+++ b/crypto/rsa/rsa_gen.c
@@ -23,10 +23,12 @@
#include <time.h>
#include "internal/cryptlib.h"
#include <openssl/bn.h>
+#include <openssl/self_test.h>
#include "rsa_local.h"
-static int rsa_builtin_keygen(RSA *rsa, int bits, int primes, BIGNUM *e_value,
- BN_GENCB *cb);
+static int rsa_keygen_pairwise_test(RSA *rsa, OSSL_CALLBACK *cb, void *cbarg);
+static int rsa_keygen(OPENSSL_CTX *libctx, RSA *rsa, int bits, int primes,
+ BIGNUM *e_value, BN_GENCB *cb, int pairwise_test);
/*
* NB: this wrapper would normally be placed in rsa_lib.c and the static
@@ -65,19 +67,21 @@ int RSA_generate_multi_prime_key(RSA *rsa, int bits, int primes,
return 0;
}
#endif /* FIPS_MODE */
- return rsa_builtin_keygen(rsa, bits, primes, e_value, cb);
+ return rsa_keygen(NULL, rsa, bits, primes, e_value, cb, 0);
}
-static int rsa_builtin_keygen(RSA *rsa, int bits, int primes, BIGNUM *e_value,
- BN_GENCB *cb)
+static int rsa_keygen(OPENSSL_CTX *libctx, RSA *rsa, int bits, int primes,
+ BIGNUM *e_value, BN_GENCB *cb, int pairwise_test)
{
+ int ok = -1;
#ifdef FIPS_MODE
if (primes != 2)
return 0;
- return rsa_sp800_56b_generate_key(rsa, bits, e_value, cb);
+ ok = rsa_sp800_56b_generate_key(rsa, bits, e_value, cb);
+ pairwise_test = 1; /* FIPS MODE needs to always run the pairwise test */
#else
BIGNUM *r0 = NULL, *r1 = NULL, *r2 = NULL, *tmp, *prime;
- int ok = -1, n = 0, bitsr[RSA_MAX_PRIME_NUM], bitse = 0;
+ int n = 0, bitsr[RSA_MAX_PRIME_NUM], bitse = 0;
int i = 0, quo = 0, rmd = 0, adj = 0, retries = 0;
RSA_PRIME_INFO *pinfo = NULL;
STACK_OF(RSA_PRIME_INFO) *prime_infos = NULL;
@@ -87,13 +91,13 @@ static int rsa_builtin_keygen(RSA *rsa, int bits, int primes, BIGNUM *e_value,
if (bits < RSA_MIN_MODULUS_BITS) {
ok = 0; /* we set our own err */
- RSAerr(RSA_F_RSA_BUILTIN_KEYGEN, RSA_R_KEY_SIZE_TOO_SMALL);
+ RSAerr(0, RSA_R_KEY_SIZE_TOO_SMALL);
goto err;
}
if (primes < RSA_DEFAULT_PRIME_NUM || primes > rsa_multip_cap(bits)) {
ok = 0; /* we set our own err */
- RSAerr(RSA_F_RSA_BUILTIN_KEYGEN, RSA_R_KEY_PRIME_NUM_INVALID);
+ RSAerr(0, RSA_R_KEY_PRIME_NUM_INVALID);
goto err;
}
@@ -398,11 +402,83 @@ static int rsa_builtin_keygen(RSA *rsa, int bits, int primes, BIGNUM *e_value,
ok = 1;
err:
if (ok == -1) {
- RSAerr(RSA_F_RSA_BUILTIN_KEYGEN, ERR_LIB_BN);
+ RSAerr(0, ERR_LIB_BN);
ok = 0;
}
BN_CTX_end(ctx);
BN_CTX_free(ctx);
- return ok;
#endif /* FIPS_MODE */
+
+ if (pairwise_test && ok > 0) {
+ OSSL_CALLBACK *stcb = NULL;
+ void *stcbarg = NULL;
+
+ OSSL_SELF_TEST_get_callback(libctx, &stcb, &stcbarg);
+ ok = rsa_keygen_pairwise_test(rsa, stcb, stcbarg);
+ if (!ok) {
+ /* Clear intermediate results */
+ BN_clear_free(rsa->d);
+ BN_clear_free(rsa->p);
+ BN_clear_free(rsa->q);
+ BN_clear_free(rsa->dmp1);
+ BN_clear_free(rsa->dmq1);
+ BN_clear_free(rsa->iqmp);
+ }
+ }
+ return ok;
+}
+
+/*
+ * For RSA key generation it is not known whether the key pair will be used
+ * for key transport or signatures. FIPS 140-2 IG 9.9 states that in this case
+ * either a signature verification OR an encryption operation may be used to
+ * perform the pairwise consistency check. The simpler encrypt/decrypt operation
+ * has been chosen for this case.
+ */
+static int rsa_keygen_pairwise_test(RSA *rsa, OSSL_CALLBACK *cb, void *cbarg)
+{
+ int ret = 0;
+ unsigned int ciphertxt_len;
+ unsigned char *ciphertxt = NULL;
+ const unsigned char plaintxt[16] = {0};
+ unsigned char decoded[256];
+ unsigned int decoded_len;
+ unsigned int plaintxt_len = (unsigned int)sizeof(plaintxt_len);
+ int padding = RSA_PKCS1_PADDING;
+ OSSL_SELF_TEST *st = NULL;
+
+ st = OSSL_SELF_TEST_new(cb, cbarg);
+ if (st == NULL)
+ goto err;
+ OSSL_SELF_TEST_onbegin(st, OSSL_SELF_TEST_TYPE_PCT,
+ OSSL_SELF_TEST_DESC_PCT_RSA_PKCS1);
+
+ ciphertxt_len = RSA_size(rsa);
+ ciphertxt = OPENSSL_zalloc(ciphertxt_len);
+ if (ciphertxt == NULL)
+ goto err;
+
+ ciphertxt_len = RSA_public_encrypt(plaintxt_len, plaintxt, ciphertxt, rsa,
+ padding);
+ if (ciphertxt_len <= 0)
+ goto err;
+ if (ciphertxt_len == plaintxt_len
+ && memcmp(decoded, plaintxt, plaintxt_len) == 0)
+ goto err;
+
+ OSSL_SELF_TEST_oncorrupt_byte(st, ciphertxt);
+
+ decoded_len = RSA_private_decrypt(ciphertxt_len, ciphertxt, decoded, rsa,
+ padding);
+ if (decoded_len != plaintxt_len
+ || memcmp(decoded, plaintxt, decoded_len) != 0)
+ goto err;
+
+ ret = 1;
+err:
+ OSSL_SELF_TEST_onend(st, ret);
+ OSSL_SELF_TEST_free(st);
+ OPENSSL_free(ciphertxt);
+
+ return ret;
}
diff --git a/crypto/self_test_core.c b/crypto/self_test_core.c
index 77864a230b..bee3161ed5 100644
--- a/crypto/self_test_core.c
+++ b/crypto/self_test_core.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2019-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
@@ -8,6 +8,8 @@
*/
#include <openssl/self_test.h>
+#include <openssl/core_names.h>
+#include <openssl/params.h>
#include "internal/cryptlib.h"
typedef struct self_test_cb_st
@@ -16,6 +18,19 @@ typedef struct self_test_cb_st
void *cbarg;
} SELF_TEST_CB;
+struct ossl_self_test_st
+{
+ /* local state variables */
+ const char *phase;
+ const char *type;
+ const char *desc;
+ OSSL_CALLBACK *cb;
+
+ /* callback related variables used to pass the state back to the user */
+ OSSL_PARAM params[4];
+ void *cb_arg;
+};
+
static void *self_test_set_callback_new(OPENSSL_CTX *ctx)
{
SELF_TEST_CB *stcb;
@@ -40,6 +55,7 @@ static SELF_TEST_CB *get_self_test_callback(OPENSSL_CTX *libctx)
&self_test_set_callback_method);
}
+#ifndef FIPS_MODE
void OSSL_SELF_TEST_set_callback(OPENSSL_CTX *libctx, OSSL_CALLBACK *cb,
void *cbarg)
{
@@ -50,6 +66,8 @@ void OSSL_SELF_TEST_set_callback(OPENSSL_CTX *libctx, OSSL_CALLBACK *cb,
stcb->cbarg = cbarg;
}
}
+#endif /* FIPS_MODE */
+
void OSSL_SELF_TEST_get_callback(OPENSSL_CTX *libctx, OSSL_CALLBACK **cb,
void **cbarg)
{
@@ -60,3 +78,91 @@ void OSSL_SELF_TEST_get_callback(OPENSSL_CTX *libctx, OSSL_CALLBACK **cb,
if (cbarg != NULL)
*cbarg = (stcb != NULL ? stcb->cbarg : NULL);
}
+
+static void self_test_setparams(OSSL_SELF_TEST *st)
+{
+ size_t n = 0;
+
+ if (st->cb != NULL) {
+ st->params[n++] =
+ OSSL_PARAM_construct_utf8_string(OSSL_PROV_PARAM_SELF_TEST_PHASE,
+ (char *)st->phase, 0);
+ st->params[n++] =
+ OSSL_PARAM_construct_utf8_string(OSSL_PROV_PARAM_SELF_TEST_TYPE,
+ (char *)st->type, 0);
+ st->params[n++] =
+ OSSL_PARAM_construct_utf8_string(OSSL_PROV_PARAM_SELF_TEST_DESC,
+ (char *)st->desc, 0);
+ }
+ st->params[n++] = OSSL_PARAM_construct_end();
+}
+
+OSSL_SELF_TEST *OSSL_SELF_TEST_new(OSSL_CALLBACK *cb, void *cbarg)
+{
+ OSSL_SELF_TEST *ret = OPENSSL_zalloc(sizeof(*ret));
+
+ if (ret == NULL)
+ return NULL;
+
+ ret->cb = cb;
+ ret->cb_arg = cbarg;
+ ret->phase = "";
+ ret->type = "";
+ ret->desc = "";
+ self_test_setparams(ret);
+ return ret;
+}
+
+void OSSL_SELF_TEST_free(OSSL_SELF_TEST *st)
+{
+ OPENSSL_free(st);
+}
+
+/* Can be used during application testing to log that a test has started. */
+void OSSL_SELF_TEST_onbegin(OSSL_SELF_TEST *st, const char *type,
+ const char *desc)
+{
+ if (st != NULL && st->cb != NULL) {
+ st->phase = OSSL_SELF_TEST_PHASE_START;
+ st->type = type;
+ st->desc = desc;
+ self_test_setparams(st);
+ (void)st->cb(st->params, st->cb_arg);
+ }
+}
+
+/*
+ * Can be used during application testing to log that a test has either
+ * passed or failed.
+ */
+void OSSL_SELF_TEST_onend(OSSL_SELF_TEST *st, int ret)
+{
+ if (st != NULL && st->cb != NULL) {
+ st->phase =
+ (ret == 1 ? OSSL_SELF_TEST_PHASE_PASS : OSSL_SELF_TEST_PHASE_FAIL);
+ self_test_setparams(st);
+ (void)st->cb(st->params, st->cb_arg);
+
+ st->phase = OSSL_SELF_TEST_PHASE_NONE;
+ st->type = OSSL_SELF_TEST_TYPE_NONE;
+ st->desc = OSSL_SELF_TEST_DESC_NONE;
+ }
+}
+
+/*
+ * Used for failure testing.
+ *
+ * Call the applications SELF_TEST_cb() if it exists.
+ * If the application callback decides to return 0 then the first byte of 'bytes'
+ * is modified (corrupted). This is used to modify output signatures or
+ * ciphertext before they are verified or decrypted.
+ */
+void OSSL_SELF_TEST_oncorrupt_byte(OSSL_SELF_TEST *st, unsigned char *bytes)
+{
+ if (st != NULL && st->cb != NULL) {
+ st->phase = OSSL_SELF_TEST_PHASE_CORRUPT;
+ self_test_setparams(st);
+ if (!st->cb(st->params, st->cb_arg))
+ bytes[0] ^= 1;
+ }
+}