# 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
/*
- * 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
/*
* 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"
/*
- * 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
#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)
{
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,
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;
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)
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;
+}
/*
- * 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
#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)
{
* 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;
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) {
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;
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;
+}
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;
#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
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;
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;
}
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;
}
/*
- * 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
*/
#include <openssl/self_test.h>
+#include <openssl/core_names.h>
+#include <openssl/params.h>
#include "internal/cryptlib.h"
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;
&self_test_set_callback_method);
}
+#ifndef FIPS_MODE
void OSSL_SELF_TEST_set_callback(OPENSSL_CTX *libctx, OSSL_CALLBACK *cb,
void *cbarg)
{
stcb->cbarg = cbarg;
}
}
+#endif /* FIPS_MODE */
+
void OSSL_SELF_TEST_get_callback(OPENSSL_CTX *libctx, OSSL_CALLBACK **cb,
void **cbarg)
{
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;
+ }
+}
--- /dev/null
+=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
L<openssl-core.h(7)>,
L<OSSL_PROVIDER-FIPS(7)>
+L<OSSL_SELF_TEST_new(3)>
L<OPENSSL_CTX(3)>
=head1 HISTORY
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
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
=back
-=back
-
=head1 EXAMPLES
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)>
=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
const unsigned char *sinfo, size_t sinfolen,
const EVP_MD *md);
+int ec_generate_key(OPENSSL_CTX *libctx, EC_KEY *eckey, int pairwise_test);
# endif /* OPENSSL_NO_EC */
#endif
void OSSL_SELF_TEST_get_callback(OPENSSL_CTX *libctx, OSSL_CALLBACK **cb,
void **cbarg);
+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);
+
#endif /* OPENSSL_SELF_TEST_H */
typedef struct ossl_serializer_st OSSL_SERIALIZER;
typedef struct ossl_serializer_ctx_st OSSL_SERIALIZER_CTX;
+typedef struct ossl_self_test_st OSSL_SELF_TEST;
+
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L && \
defined(INTMAX_MAX) && defined(UINTMAX_MAX)
typedef intmax_t ossl_intmax_t;
-SOURCE[../fips]=fipsprov.c self_test.c self_test_kats.c self_test_event.c
+SOURCE[../fips]=fipsprov.c self_test.c self_test_kats.c
INCLUDE[../fips]=../implementations/include ../common/include ../..
}
if (stcbfn != NULL && c_get_libctx != NULL) {
- stcbfn(c_get_libctx(provider), &selftest_params.event_cb,
- &selftest_params.event_cb_arg);
+ stcbfn(c_get_libctx(provider), &selftest_params.cb,
+ &selftest_params.cb_arg);
}
else {
- selftest_params.event_cb = NULL;
- selftest_params.event_cb_arg = NULL;
+ selftest_params.cb = NULL;
+ selftest_params.cb_arg = NULL;
}
if (!c_get_params(provider, core_params))
*/
static int verify_integrity(BIO *bio, OSSL_BIO_read_ex_fn read_ex_cb,
unsigned char *expected, size_t expected_len,
- OPENSSL_CTX *libctx, OSSL_ST_EVENT *ev,
+ OPENSSL_CTX *libctx, OSSL_SELF_TEST *ev,
const char *event_type)
{
int ret = 0, status;
EVP_MAC_CTX *ctx = NULL;
OSSL_PARAM params[3], *p = params;
- SELF_TEST_EVENT_onbegin(ev, event_type, OSSL_SELF_TEST_DESC_INTEGRITY_HMAC);
+ OSSL_SELF_TEST_onbegin(ev, event_type, OSSL_SELF_TEST_DESC_INTEGRITY_HMAC);
mac = EVP_MAC_fetch(libctx, MAC_NAME, NULL);
ctx = EVP_MAC_CTX_new(mac);
if (!EVP_MAC_final(ctx, out, &out_len, sizeof(out)))
goto err;
- SELF_TEST_EVENT_oncorrupt_byte(ev, out);
+ OSSL_SELF_TEST_oncorrupt_byte(ev, out);
if (expected_len != out_len
|| memcmp(expected, out, out_len) != 0)
goto err;
ret = 1;
err:
- SELF_TEST_EVENT_onend(ev, ret);
+ OSSL_SELF_TEST_onend(ev, ret);
EVP_MAC_CTX_free(ctx);
EVP_MAC_free(mac);
return ret;
unsigned char *module_checksum = NULL;
unsigned char *indicator_checksum = NULL;
int loclstate;
- OSSL_ST_EVENT ev;
+ OSSL_SELF_TEST *ev = NULL;
if (!RUN_ONCE(&fips_self_test_init, do_fips_self_test_init))
return 0;
|| st->module_checksum_data == NULL)
goto end;
- SELF_TEST_EVENT_init(&ev, st->event_cb, st->event_cb_arg);
+ ev = OSSL_SELF_TEST_new(st->cb, st->cb_arg);
+ if (ev == NULL)
+ goto end;
module_checksum = OPENSSL_hexstr2buf(st->module_checksum_data,
&checksum_len);
if (bio_module == NULL
|| !verify_integrity(bio_module, st->bio_read_ex_cb,
module_checksum, checksum_len, st->libctx,
- &ev, OSSL_SELF_TEST_TYPE_MODULE_INTEGRITY))
+ ev, OSSL_SELF_TEST_TYPE_MODULE_INTEGRITY))
goto end;
/* This will be NULL during installation - so the self test KATS will run */
if (bio_indicator == NULL
|| !verify_integrity(bio_indicator, st->bio_read_ex_cb,
indicator_checksum, checksum_len,
- st->libctx, &ev,
+ st->libctx, ev,
OSSL_SELF_TEST_TYPE_INSTALL_INTEGRITY))
goto end;
else
/* Only runs the KAT's during installation OR on_demand() */
if (on_demand_test || kats_already_passed == 0) {
- if (!SELF_TEST_kats(&ev, st->libctx))
+ if (!SELF_TEST_kats(ev, st->libctx))
goto end;
}
ok = 1;
end:
+ OSSL_SELF_TEST_free(ev);
OPENSSL_free(module_checksum);
OPENSSL_free(indicator_checksum);
OSSL_BIO_new_membuf_fn *bio_new_buffer_cb;
OSSL_BIO_read_ex_fn *bio_read_ex_cb;
OSSL_BIO_free_fn *bio_free_cb;
- OSSL_CALLBACK *event_cb;
- void *event_cb_arg;
- OPENSSL_CTX *libctx;
-
-} SELF_TEST_POST_PARAMS;
-
-typedef struct st_event_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;
+ OPENSSL_CTX *libctx;
-} OSSL_ST_EVENT;
+} SELF_TEST_POST_PARAMS;
int SELF_TEST_post(SELF_TEST_POST_PARAMS *st, int on_demand_test);
-int SELF_TEST_kats(OSSL_ST_EVENT *event, OPENSSL_CTX *libctx);
-
-void SELF_TEST_EVENT_init(OSSL_ST_EVENT *ev, OSSL_CALLBACK *cb, void *cbarg);
-void SELF_TEST_EVENT_onbegin(OSSL_ST_EVENT *ev, const char *type,
- const char *desc);
-void SELF_TEST_EVENT_onend(OSSL_ST_EVENT *ev, int ret);
-void SELF_TEST_EVENT_oncorrupt_byte(OSSL_ST_EVENT *ev, unsigned char *bytes);
+int SELF_TEST_kats(OSSL_SELF_TEST *event, OPENSSL_CTX *libctx);
+++ /dev/null
-/*
- * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the OpenSSL license (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 <openssl/core_names.h>
-#include <openssl/params.h>
-#include "self_test.h"
-
-static void self_test_event_setparams(OSSL_ST_EVENT *ev)
-{
- size_t n = 0;
-
- if (ev->cb != NULL) {
- ev->params[n++] =
- OSSL_PARAM_construct_utf8_string(OSSL_PROV_PARAM_SELF_TEST_PHASE,
- (char *)ev->phase, 0);
- ev->params[n++] =
- OSSL_PARAM_construct_utf8_string(OSSL_PROV_PARAM_SELF_TEST_TYPE,
- (char *)ev->type, 0);
- ev->params[n++] =
- OSSL_PARAM_construct_utf8_string(OSSL_PROV_PARAM_SELF_TEST_DESC,
- (char *)ev->desc, 0);
- }
- ev->params[n++] = OSSL_PARAM_construct_end();
-}
-
-void SELF_TEST_EVENT_init(OSSL_ST_EVENT *ev, OSSL_CALLBACK *cb, void *cbarg)
-{
- if (ev == NULL)
- return;
-
- ev->cb = cb;
- ev->cb_arg = cbarg;
- ev->phase = "";
- ev->type = "";
- ev->desc = "";
- self_test_event_setparams(ev);
-}
-
-/* Can be used during application testing to log that a test has started. */
-void SELF_TEST_EVENT_onbegin(OSSL_ST_EVENT *ev, const char *type,
- const char *desc)
-{
- if (ev != NULL && ev->cb != NULL) {
- ev->phase = OSSL_SELF_TEST_PHASE_START;
- ev->type = type;
- ev->desc = desc;
- self_test_event_setparams(ev);
- (void)ev->cb(ev->params, ev->cb_arg);
- }
-}
-
-/*
- * Can be used during application testing to log that a test has either
- * passed or failed.
- */
-void SELF_TEST_EVENT_onend(OSSL_ST_EVENT *ev, int ret)
-{
- if (ev != NULL && ev->cb != NULL) {
- ev->phase =
- (ret == 1 ? OSSL_SELF_TEST_PHASE_PASS : OSSL_SELF_TEST_PHASE_FAIL);
- self_test_event_setparams(ev);
- (void)ev->cb(ev->params, ev->cb_arg);
-
- ev->phase = OSSL_SELF_TEST_PHASE_NONE;
- ev->type = OSSL_SELF_TEST_TYPE_NONE;
- ev->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 SELF_TEST_EVENT_oncorrupt_byte(OSSL_ST_EVENT *ev, unsigned char *bytes)
-{
- if (ev != NULL && ev->cb != NULL) {
- ev->phase = OSSL_SELF_TEST_PHASE_CORRUPT;
- self_test_event_setparams(ev);
- if (!ev->cb(ev->params, ev->cb_arg))
- bytes[0] ^= 1;
- }
-}
-
#define DRBG_PARAM_ENTROPY "DRBG-ENTROPY"
#define DRBG_PARAM_NONCE "DRBG-NONCE"
-static int self_test_digest(const ST_KAT_DIGEST *t, OSSL_ST_EVENT *event,
+static int self_test_digest(const ST_KAT_DIGEST *t, OSSL_SELF_TEST *st,
OPENSSL_CTX *libctx)
{
int ok = 0;
EVP_MD_CTX *ctx = EVP_MD_CTX_new();
EVP_MD *md = EVP_MD_fetch(libctx, t->algorithm, NULL);
- SELF_TEST_EVENT_onbegin(event, OSSL_SELF_TEST_TYPE_KAT_DIGEST, t->desc);
+ OSSL_SELF_TEST_onbegin(st, OSSL_SELF_TEST_TYPE_KAT_DIGEST, t->desc);
if (ctx == NULL
|| md == NULL
goto err;
/* Optional corruption */
- SELF_TEST_EVENT_oncorrupt_byte(event, out);
+ 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:
- SELF_TEST_EVENT_onend(event, ok);
+ OSSL_SELF_TEST_onend(st, ok);
EVP_MD_free(md);
EVP_MD_CTX_free(ctx);
}
/* Test a single KAT for encrypt/decrypt */
-static int self_test_cipher(const ST_KAT_CIPHER *t, OSSL_ST_EVENT *event,
+static int self_test_cipher(const ST_KAT_CIPHER *t, OSSL_SELF_TEST *st,
OPENSSL_CTX *libctx)
{
int ret = 0, encrypt = 1, len, ct_len = 0, pt_len = 0;
unsigned char ct_buf[256] = { 0 };
unsigned char pt_buf[256] = { 0 };
- SELF_TEST_EVENT_onbegin(event, OSSL_SELF_TEST_TYPE_KAT_CIPHER, t->base.desc);
+ OSSL_SELF_TEST_onbegin(st, OSSL_SELF_TEST_TYPE_KAT_CIPHER, t->base.desc);
ctx = EVP_CIPHER_CTX_new();
if (ctx == NULL)
|| !EVP_CipherFinal_ex(ctx, ct_buf + len, &ct_len))
goto err;
- SELF_TEST_EVENT_oncorrupt_byte(event, ct_buf);
+ OSSL_SELF_TEST_oncorrupt_byte(st, ct_buf);
ct_len += len;
if (ct_len != (int)t->base.expected_len
|| memcmp(t->base.expected, ct_buf, ct_len) != 0)
err:
EVP_CIPHER_free(cipher);
EVP_CIPHER_CTX_free(ctx);
- SELF_TEST_EVENT_onend(event, ret);
+ OSSL_SELF_TEST_onend(st, ret);
return ret;
}
-static int self_test_kdf(const ST_KAT_KDF *t, OSSL_ST_EVENT *event,
+static int self_test_kdf(const ST_KAT_KDF *t, OSSL_SELF_TEST *st,
OPENSSL_CTX *libctx)
{
int ret = 0;
const OSSL_PARAM *settables = NULL;
numparams = OSSL_NELEM(params);
- SELF_TEST_EVENT_onbegin(event, OSSL_SELF_TEST_TYPE_KAT_KDF, t->desc);
+ OSSL_SELF_TEST_onbegin(st, OSSL_SELF_TEST_TYPE_KAT_KDF, t->desc);
/* Zeroize the params array to avoid mem leaks on error */
for (i = 0; i < numparams; ++i)
if (EVP_KDF_derive(ctx, out, t->expected_len) <= 0)
goto err;
- SELF_TEST_EVENT_oncorrupt_byte(event, out);
+ OSSL_SELF_TEST_oncorrupt_byte(st, out);
if (memcmp(out, t->expected, t->expected_len) != 0)
goto err;
OPENSSL_free(params[i].data);
EVP_KDF_free(kdf);
EVP_KDF_CTX_free(ctx);
- SELF_TEST_EVENT_onend(event, ret);
+ OSSL_SELF_TEST_onend(st, ret);
return ret;
}
return p->data_size;
}
-static int self_test_drbg(const ST_KAT_DRBG *t, OSSL_ST_EVENT *event,
+static int self_test_drbg(const ST_KAT_DRBG *t, OSSL_SELF_TEST *st,
OPENSSL_CTX *libctx)
{
int ret = 0;
};
static const unsigned char zero[sizeof(drbg->data)] = { 0 };
- SELF_TEST_EVENT_onbegin(event, OSSL_SELF_TEST_TYPE_DRBG, t->desc);
+ OSSL_SELF_TEST_onbegin(st, OSSL_SELF_TEST_TYPE_DRBG, t->desc);
if (strcmp(t->desc, OSSL_SELF_TEST_DESC_DRBG_HMAC) == 0)
flags |= RAND_DRBG_FLAG_HMAC;
t->entropyaddin2, t->entropyaddin2len))
goto err;
- SELF_TEST_EVENT_oncorrupt_byte(event, out);
+ OSSL_SELF_TEST_oncorrupt_byte(st, out);
if (memcmp(out, t->expected, t->expectedlen) != 0)
goto err;
ret = 1;
err:
RAND_DRBG_free(drbg);
- SELF_TEST_EVENT_onend(event, ret);
+ OSSL_SELF_TEST_onend(st, ret);
return ret;
}
* All tests are run regardless of if they fail or not.
* Return 0 if any test fails.
*/
-static int self_test_digests(OSSL_ST_EVENT *event, OPENSSL_CTX *libctx)
+static int self_test_digests(OSSL_SELF_TEST *st, OPENSSL_CTX *libctx)
{
int i, ret = 1;
for (i = 0; i < (int)OSSL_NELEM(st_kat_digest_tests); ++i) {
- if (!self_test_digest(&st_kat_digest_tests[i], event, libctx))
+ if (!self_test_digest(&st_kat_digest_tests[i], st, libctx))
ret = 0;
}
return ret;
}
-static int self_test_ciphers(OSSL_ST_EVENT *event, OPENSSL_CTX *libctx)
+static int self_test_ciphers(OSSL_SELF_TEST *st, OPENSSL_CTX *libctx)
{
int i, ret = 1;
for (i = 0; i < (int)OSSL_NELEM(st_kat_cipher_tests); ++i) {
- if (!self_test_cipher(&st_kat_cipher_tests[i], event, libctx))
+ if (!self_test_cipher(&st_kat_cipher_tests[i], st, libctx))
ret = 0;
}
return ret;
}
-static int self_test_kdfs(OSSL_ST_EVENT *event, OPENSSL_CTX *libctx)
+static int self_test_kdfs(OSSL_SELF_TEST *st, OPENSSL_CTX *libctx)
{
int i, ret = 1;
for (i = 0; i < (int)OSSL_NELEM(st_kat_kdf_tests); ++i) {
- if (!self_test_kdf(&st_kat_kdf_tests[i], event, libctx))
+ if (!self_test_kdf(&st_kat_kdf_tests[i], st, libctx))
ret = 0;
}
return ret;
}
-static int self_test_drbgs(OSSL_ST_EVENT *event, OPENSSL_CTX *libctx)
+static int self_test_drbgs(OSSL_SELF_TEST *st, OPENSSL_CTX *libctx)
{
int i, ret = 1;
for (i = 0; i < (int)OSSL_NELEM(st_kat_drbg_tests); ++i) {
- if (!self_test_drbg(&st_kat_drbg_tests[i], event, libctx))
+ if (!self_test_drbg(&st_kat_drbg_tests[i], st, libctx))
ret = 0;
}
return ret;
*
* TODO(3.0) Add self tests for KA, Sign/Verify when they become available
*/
-int SELF_TEST_kats(OSSL_ST_EVENT *event, OPENSSL_CTX *libctx)
+int SELF_TEST_kats(OSSL_SELF_TEST *st, OPENSSL_CTX *libctx)
{
int ret = 1;
- if (!self_test_digests(event, libctx))
+ if (!self_test_digests(st, libctx))
ret = 0;
- if (!self_test_ciphers(event, libctx))
+ if (!self_test_ciphers(st, libctx))
ret = 0;
- if (!self_test_kdfs(event, libctx))
+ if (!self_test_kdfs(st, libctx))
ret = 0;
- if (!self_test_drbgs(event, libctx))
+ if (!self_test_drbgs(st, libctx))
ret = 0;
return ret;
EVP_PKEY_CTX_get0_ecdh_kdf_ukm ? 3_0_0 EXIST::FUNCTION:EC
EVP_PKEY_CTX_set_rsa_pss_saltlen ? 3_0_0 EXIST::FUNCTION:RSA
EVP_PKEY_CTX_get_rsa_pss_saltlen ? 3_0_0 EXIST::FUNCTION:RSA
+OSSL_SELF_TEST_new ? 3_0_0 EXIST::FUNCTION:
+OSSL_SELF_TEST_free ? 3_0_0 EXIST::FUNCTION:
+OSSL_SELF_TEST_onbegin ? 3_0_0 EXIST::FUNCTION:
+OSSL_SELF_TEST_oncorrupt_byte ? 3_0_0 EXIST::FUNCTION:
+OSSL_SELF_TEST_onend ? 3_0_0 EXIST::FUNCTION: