summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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
-rw-r--r--doc/man3/OSSL_SELF_TEST_new.pod172
-rw-r--r--doc/man3/OSSL_SELF_TEST_set_callback.pod1
-rw-r--r--doc/man7/OSSL_PROVIDER-FIPS.pod58
-rw-r--r--include/crypto/ec.h1
-rw-r--r--include/openssl/self_test.h8
-rw-r--r--include/openssl/types.h2
-rw-r--r--providers/fips/build.info2
-rw-r--r--providers/fips/fipsprov.c8
-rw-r--r--providers/fips/self_test.c21
-rw-r--r--providers/fips/self_test.h26
-rw-r--r--providers/fips/self_test_event.c93
-rw-r--r--providers/fips/self_test_kats.c58
-rw-r--r--util/libcrypto.num5
20 files changed, 577 insertions, 235 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;
+ }
+}
diff --git a/doc/man3/OSSL_SELF_TEST_new.pod b/doc/man3/OSSL_SELF_TEST_new.pod
new file mode 100644
index 0000000000..32155e1cd0
--- /dev/null
+++ b/doc/man3/OSSL_SELF_TEST_new.pod
@@ -0,0 +1,172 @@
+=pod
+
+=head1 NAME
+
+OSSL_SELF_TEST_new,
+OSSL_SELF_TEST_free,
+OSSL_SELF_TEST_onbegin,
+OSSL_SELF_TEST_oncorrupt_byte,
+OSSL_SELF_TEST_onend - functionality to trigger a callback during a self test
+
+=head1 SYNOPSIS
+
+ #include <openssl/self_test.h>
+
+ OSSL_SELF_TEST *OSSL_SELF_TEST_new(OSSL_CALLBACK *cb, void *cbarg);
+ void OSSL_SELF_TEST_free(OSSL_SELF_TEST *st);
+
+ void OSSL_SELF_TEST_onbegin(OSSL_SELF_TEST *st, const char *type,
+ const char *desc);
+ void OSSL_SELF_TEST_oncorrupt_byte(OSSL_SELF_TEST *st, unsigned char *bytes);
+ void OSSL_SELF_TEST_onend(OSSL_SELF_TEST *st, int ret);
+
+=head1 DESCRIPTION
+
+These methods are intended for use by provider implementors, to display
+diagnostic information during self testing.
+
+OSSL_SELF_TEST_new() allocates an opaque B<OSSL_SELF_TEST> object that has a
+callback and callback argument associated with it.
+
+The callback I<cb> may be triggered multiple times by a self test to indicate
+different phases.
+
+OSSL_SELF_TEST_free() frees the space allocated by OSSL_SELF_TEST_new().
+
+OSSL_SELF_TEST_onbegin() may be inserted at the start of a block of self test
+code. It can be used for diagnostic purposes.
+If this method is called the callback I<cb> will receive the following
+B<OSSL_PARAM> object.
+
+=over 4
+
+=item "st-phase" (B<OSSL_PROV_PARAM_SELF_TEST_PHASE>) <UTF8 string>
+
+The value is the string "Start"
+
+=back
+
+OSSL_SELF_TEST_oncorrupt_byte() may be inserted just after the known answer is
+calculated, but before the self test compares the result. The first byte in the
+passed in array of I<bytes> will be corrupted if the callback returns 0,
+otherwise it leaves the array unaltered. It can be used for failure testing.
+The I<type> and I<desc> can be used to identify an individual self test to
+target for failure testing.
+If this method is called the callback I<cb> will receive the following
+B<OSSL_PARAM> object.
+
+=over 4
+
+=item "st-phase" (B<OSSL_PROV_PARAM_SELF_TEST_PHASE>) <UTF8 string>
+
+The value is the string "Corrupt"
+
+=back
+
+OSSL_SELF_TEST_onend() may be inserted at the end of a block of self test code
+just before cleanup to indicate if the test passed or failed. It can be used for
+diagnostic purposes.
+If this method is called the callback I<cb> will receive the following
+B<OSSL_PARAM> object.
+
+=over 4
+
+=item "st-phase" (B<OSSL_PROV_PARAM_SELF_TEST_PHASE>) <UTF8 string>
+
+The value of the string is "Pass" if I<ret> is non zero, otherwise it has the
+value "Fail".
+
+=back
+
+After the callback I<cb> has been called the values that were set by
+OSSL_SELF_TEST_onbegin() for I<type> and I<desc> are set to the value "None".
+
+If OSSL_SELF_TEST_onbegin(), OSSL_SELF_TEST_oncorrupt_byte() or
+OSSL_SELF_TEST_onend() is called the following additional B<OSSL_PARAM> are
+passed to the callback.
+
+=over 4
+
+=item "st-type" (B<OSSL_PROV_PARAM_SELF_TEST_TYPE>) <UTF8 string>
+
+The value is setup by the I<type> passed to OSSL_SELF_TEST_onbegin().
+This allows the callback to identify the type of test being run.
+
+=item "st-desc" (B<OSSL_PROV_PARAM_SELF_TEST_DESC>) <UTF8 string>
+
+The value is setup by the I<type> passed to OSSL_SELF_TEST_onbegin().
+This allows the callback to identify the sub category of the test being run.
+
+=back
+
+=head1 RETURN VALUES
+
+OSSL_SELF_TEST_new() returns the allocated B<OSSL_SELF_TEST> object, or NULL if
+it fails.
+
+=head1 EXAMPLES
+
+A single self test could be set up in the following way:
+
+ OSSL_SELF_TEST *st = NULL;
+ OSSL_CALLBACK *cb;
+ void *cbarg;
+ int ok = 0;
+ unsigned char out[EVP_MAX_MD_SIZE];
+ unsigned int out_len = 0;
+ EVP_MD_CTX *ctx = EVP_MD_CTX_new();
+ EVP_MD *md = EVP_MD_fetch(libctx, t->algorithm, NULL);
+
+ /*
+ * Retrieve the callback - will be NULL if not set by the application via
+ * OSSL_SELF_TEST_set_callback().
+ */
+ OSSL_SELF_TEST_get_callback(libctx, &cb, &cbarg);
+
+ st = OSSL_SELF_TEST_new(cb, cb_arg);
+
+ /* Trigger the optional callback */
+ OSSL_SELF_TEST_onbegin(st, OSSL_SELF_TEST_TYPE_KAT_DIGEST,
+ OSSL_SELF_TEST_DESC_MD_SHA2);
+
+ if (!EVP_DigestInit_ex(ctx, md, NULL)
+ || !EVP_DigestUpdate(ctx, pt, pt_len)
+ || !EVP_DigestFinal(ctx, out, &out_len))
+ goto err;
+
+ /* Optional corruption - If the application callback returns 0 */
+ OSSL_SELF_TEST_oncorrupt_byte(st, out);
+
+ if (out_len != t->expected_len
+ || memcmp(out, t->expected, out_len) != 0)
+ goto err;
+ ok = 1;
+ err:
+ OSSL_SELF_TEST_onend(st, ok);
+ EVP_MD_free(md);
+ EVP_MD_CTX_free(ctx);
+
+Multiple self test's can be set up in a similar way by repeating the pattern of
+OSSL_SELF_TEST_onbegin(), OSSL_SELF_TEST_oncorrupt_byte(), OSSL_SELF_TEST_onend()
+for each test.
+
+=head1 SEE ALSO
+
+L<OSSL_SELF_TEST_set_callback(3)>,
+L<openssl-core.h(7)>,
+L<OSSL_PROVIDER-FIPS(7)>
+
+=head1 HISTORY
+
+The functions described here were added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+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
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/OSSL_SELF_TEST_set_callback.pod b/doc/man3/OSSL_SELF_TEST_set_callback.pod
index b2d38fbf7f..be65eca0fe 100644
--- a/doc/man3/OSSL_SELF_TEST_set_callback.pod
+++ b/doc/man3/OSSL_SELF_TEST_set_callback.pod
@@ -32,6 +32,7 @@ not been called.
L<openssl-core.h(7)>,
L<OSSL_PROVIDER-FIPS(7)>
+L<OSSL_SELF_TEST_new(3)>
L<OPENSSL_CTX(3)>
=head1 HISTORY
diff --git a/doc/man7/OSSL_PROVIDER-FIPS.pod b/doc/man7/OSSL_PROVIDER-FIPS.pod
index c3768da7bc..1cb75e7c87 100644
--- a/doc/man7/OSSL_PROVIDER-FIPS.pod
+++ b/doc/man7/OSSL_PROVIDER-FIPS.pod
@@ -17,59 +17,16 @@ One of the requirements for the FIPS module is self testing. An optional callbac
mechanism is available to return information to the user using
L<OSSL_SELF_TEST_set_callback(3)>.
+The parameters passed to the callback are described in L<OSSL_SELF_TEST_new(3)>
+
The OPENSSL FIPS module uses the following mechanism to provide information
about the self tests as they run.
This is useful for debugging if a self test is failing.
The callback also allows forcing any self test to fail, in order to check that
it operates correctly on failure.
-
-The 'args' parameter of B<OSSL_CALLBACK> contains the B<OPENSSL_CTX> associated
-with the provider that is triggering the self test. This may be useful if
-multiple fips providers are present.
-
-The OSSL_PARAM names used are:
-
-=over 4
-
-=item "st-phase" (B<OSSL_PROV_PARAM_SELF_TEST_PHASE>) <UTF8 string>
-
-Each self test calls the callback 3 times with the following string values
-for the phase.
-
-=over 4
-
-=item "Start" (B<OSSL_SELF_TEST_PHASE_START>)
-
-This is the initial phase before the self test has run.
-This is used for informational purposes only.
-The value returned by the callback is ignored.
-
-=item "Corrupt" (B<OSSL_SELF_TEST_PHASE_CORRUPT>)
-
-The corrupt phase is run after the self test has calculated its known value.
-The callback may be used to force the self test to fail by returning a value
-of 0 from the callback during this phase.
-Returning any other value from the callback causes the self test to run normally.
-
-=item "Pass" (B<OSSL_SELF_TEST_PHASE_PASS>)
-
-=item "Fail" (B<OSSL_SELF_TEST_PHASE_FAIL>)
-
-The final phase runs after the self test is complete and indicates if a self
-test passed or failed. This is used for informational purposes only.
-The value returned by the callback is ignored.
-"Fail" should normally only be returned if any self test was forced to fail
-during the "Corrupt" phase (or if there was an error such as the integrity
-check of the module failed).
-
Note that all self tests run even if a self test failure occurs.
-=back
-
-=item "st-type" (B<OSSL_PROV_PARAM_SELF_TEST_TYPE>) <UTF8 string>
-
-Used as a category to identify the type of self test being run.
-It includes the following string values:
+The FIPS module passes the following type(s) to OSSL_SELF_TEST_onbegin().
=over 4
@@ -126,10 +83,8 @@ All other self test categories are run once at installation time, except for the
There is only one instance of the "Module_Integrity" and "Install_Integrity"
self tests. All other self tests may have multiple instances.
-=item "st-desc" (B<OSSL_PROV_PARAM_SELF_TEST_DESC>) <UTF8 string>
-Used as a sub category to identify an individual self test.
-The following description strings are used.
+The FIPS module passes the following descriptions(s) to OSSL_SELF_TEST_onbegin().
=over 4
@@ -187,8 +142,6 @@ DRBG tests used with the "DRBG" type.
=back
-=back
-
=head1 EXAMPLES
A simple self test callback is shown below for illustrative purposes.
@@ -241,6 +194,7 @@ A simple self test callback is shown below for illustrative purposes.
L<openssl-fipsinstall(1)>,
L<fips_config(5)>,
L<OSSL_SELF_TEST_set_callback(3)>,
+L<OSSL_SELF_TEST_new(3)>,
L<OSSL_PARAM(3)>,
L<openssl-core.h(7)>
@@ -250,7 +204,7 @@ The type and functions described here were added in OpenSSL 3.0.
=head1 COPYRIGHT
-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
diff --git a/include/crypto/ec.h b/include/crypto/ec.h
index 4a0a967629..c4f7d2e778 100644
--- a/include/crypto/ec.h
+++ b/