Add pairwise consistency self tests to asym keygenerators

Reviewed-by: Richard Levitte <levitte@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/10952)
This commit is contained in:
Shane Lontis 2020-03-03 14:02:36 +10:00
parent 97ace6c2da
commit 47c239c6b8
20 changed files with 578 additions and 236 deletions

View File

@ -61,9 +61,9 @@ ENDIF
# The Core # The Core
$CORE_COMMON=provider_core.c provider_predefined.c \ $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 SOURCE[../providers/libfips.a]=$CORE_COMMON
# Central utilities # Central utilities

View File

@ -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 * 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 * 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 * DH low level APIs are deprecated for public use, but still ok for
* internal use. * 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" #include "internal/deprecated.h"

View File

@ -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 * 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 * this file except in compliance with the License. You can obtain a copy
@ -17,10 +17,12 @@
#include <time.h> #include <time.h>
#include "internal/cryptlib.h" #include "internal/cryptlib.h"
#include <openssl/bn.h> #include <openssl/bn.h>
#include <openssl/self_test.h>
#include "crypto/dsa.h" #include "crypto/dsa.h"
#include "dsa_local.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) int DSA_generate_key(DSA *dsa)
{ {
@ -28,7 +30,7 @@ int DSA_generate_key(DSA *dsa)
if (dsa->meth->dsa_keygen != NULL) if (dsa->meth->dsa_keygen != NULL)
return dsa->meth->dsa_keygen(dsa); return dsa->meth->dsa_keygen(dsa);
#endif #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, int dsa_generate_public_key(BN_CTX *ctx, const DSA *dsa, const BIGNUM *priv_key,
@ -50,7 +52,7 @@ err:
return ret; return ret;
} }
static int dsa_builtin_keygen(DSA *dsa) static int dsa_keygen(DSA *dsa, int pairwise_test)
{ {
int ok = 0; int ok = 0;
BN_CTX *ctx = NULL; BN_CTX *ctx = NULL;
@ -82,8 +84,26 @@ static int dsa_builtin_keygen(DSA *dsa)
dsa->priv_key = priv_key; dsa->priv_key = priv_key;
dsa->pub_key = pub_key; dsa->pub_key = pub_key;
dsa->dirty_cnt++;
#ifdef FIPS_MODE
pairwise_test = 1;
#endif /* FIPS_MODE */
ok = 1; 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: err:
if (pub_key != dsa->pub_key) if (pub_key != dsa->pub_key)
@ -91,5 +111,42 @@ static int dsa_builtin_keygen(DSA *dsa)
if (priv_key != dsa->priv_key) if (priv_key != dsa->priv_key)
BN_free(priv_key); BN_free(priv_key);
BN_CTX_free(ctx); BN_CTX_free(ctx);
return ok; 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;
}

View File

@ -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 * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
* *
* Licensed under the Apache License 2.0 (the "License"). You may not use * Licensed under the Apache License 2.0 (the "License"). You may not use
@ -20,8 +20,12 @@
#include "internal/refcount.h" #include "internal/refcount.h"
#include <openssl/err.h> #include <openssl/err.h>
#include <openssl/engine.h> #include <openssl/engine.h>
#include <openssl/self_test.h>
#include "crypto/bn.h" #include "crypto/bn.h"
static int ecdsa_keygen_pairwise_test(EC_KEY *eckey, OSSL_CALLBACK *cb,
void *cbarg);
#ifndef FIPS_MODE #ifndef FIPS_MODE
EC_KEY *EC_KEY_new(void) 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" * See SP800-56AR3 5.6.1.2.2 "Key Pair Generation by Testing Candidates"
* *
* Params: * Params:
* libctx A context containing an optional self test callback.
* eckey An EC key object that contains domain params. The generated keypair * eckey An EC key object that contains domain params. The generated keypair
* is stored in this object. * 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. * 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; int ok = 0;
BIGNUM *priv_key = NULL; BIGNUM *priv_key = NULL;
@ -305,8 +312,18 @@ int ec_key_simple_generate_key(EC_KEY *eckey)
eckey->dirty_cnt++; eckey->dirty_cnt++;
ok = 1; #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: err:
/* Step (9): If there is an error return an invalid keypair. */ /* Step (9): If there is an error return an invalid keypair. */
if (!ok) { if (!ok) {
@ -321,6 +338,11 @@ err:
return 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 ec_key_simple_generate_public_key(EC_KEY *eckey)
{ {
int ret; int ret;
@ -849,3 +871,45 @@ int EC_KEY_can_sign(const EC_KEY *eckey)
return 0; return 0;
return 1; 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;
}

View File

@ -169,12 +169,13 @@ static ECDSA_SIG *ecdsa_s390x_nistp_sign_sig(const unsigned char *dgst,
if (r == NULL || kinv == NULL) { 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 * is used instead of BN_priv_rand_range or BN_generate_dsa_nonce
* because kdsa instruction constructs an in-range, invertible nonce * because kdsa instruction constructs an in-range, invertible nonce
* internally implementing counter-measures for RNG weakness. * 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, ECerr(EC_F_ECDSA_S390X_NISTP_SIGN_SIG,
EC_R_RANDOM_NUMBER_GENERATION_FAILED); EC_R_RANDOM_NUMBER_GENERATION_FAILED);
goto ret; goto ret;

View File

@ -23,10 +23,12 @@
#include <time.h> #include <time.h>
#include "internal/cryptlib.h" #include "internal/cryptlib.h"
#include <openssl/bn.h> #include <openssl/bn.h>
#include <openssl/self_test.h>
#include "rsa_local.h" #include "rsa_local.h"
static int rsa_builtin_keygen(RSA *rsa, int bits, int primes, BIGNUM *e_value, static int rsa_keygen_pairwise_test(RSA *rsa, OSSL_CALLBACK *cb, void *cbarg);
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);
/* /*
* NB: this wrapper would normally be placed in rsa_lib.c and the static * 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; return 0;
} }
#endif /* FIPS_MODE */ #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, static int rsa_keygen(OPENSSL_CTX *libctx, RSA *rsa, int bits, int primes,
BN_GENCB *cb) BIGNUM *e_value, BN_GENCB *cb, int pairwise_test)
{ {
int ok = -1;
#ifdef FIPS_MODE #ifdef FIPS_MODE
if (primes != 2) if (primes != 2)
return 0; 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 #else
BIGNUM *r0 = NULL, *r1 = NULL, *r2 = NULL, *tmp, *prime; 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; int i = 0, quo = 0, rmd = 0, adj = 0, retries = 0;
RSA_PRIME_INFO *pinfo = NULL; RSA_PRIME_INFO *pinfo = NULL;
STACK_OF(RSA_PRIME_INFO) *prime_infos = 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) { if (bits < RSA_MIN_MODULUS_BITS) {
ok = 0; /* we set our own err */ 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; goto err;
} }
if (primes < RSA_DEFAULT_PRIME_NUM || primes > rsa_multip_cap(bits)) { if (primes < RSA_DEFAULT_PRIME_NUM || primes > rsa_multip_cap(bits)) {
ok = 0; /* we set our own err */ 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; goto err;
} }
@ -398,11 +402,83 @@ static int rsa_builtin_keygen(RSA *rsa, int bits, int primes, BIGNUM *e_value,
ok = 1; ok = 1;
err: err:
if (ok == -1) { if (ok == -1) {
RSAerr(RSA_F_RSA_BUILTIN_KEYGEN, ERR_LIB_BN); RSAerr(0, ERR_LIB_BN);
ok = 0; ok = 0;
} }
BN_CTX_end(ctx); BN_CTX_end(ctx);
BN_CTX_free(ctx); BN_CTX_free(ctx);
return ok;
#endif /* FIPS_MODE */ #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;
} }

View File

@ -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 * 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 * this file except in compliance with the License. You can obtain a copy
@ -8,6 +8,8 @@
*/ */
#include <openssl/self_test.h> #include <openssl/self_test.h>
#include <openssl/core_names.h>
#include <openssl/params.h>
#include "internal/cryptlib.h" #include "internal/cryptlib.h"
typedef struct self_test_cb_st typedef struct self_test_cb_st
@ -16,6 +18,19 @@ typedef struct self_test_cb_st
void *cbarg; void *cbarg;
} SELF_TEST_CB; } 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) static void *self_test_set_callback_new(OPENSSL_CTX *ctx)
{ {
SELF_TEST_CB *stcb; SELF_TEST_CB *stcb;
@ -40,6 +55,7 @@ static SELF_TEST_CB *get_self_test_callback(OPENSSL_CTX *libctx)
&self_test_set_callback_method); &self_test_set_callback_method);
} }
#ifndef FIPS_MODE
void OSSL_SELF_TEST_set_callback(OPENSSL_CTX *libctx, OSSL_CALLBACK *cb, void OSSL_SELF_TEST_set_callback(OPENSSL_CTX *libctx, OSSL_CALLBACK *cb,
void *cbarg) void *cbarg)
{ {
@ -50,6 +66,8 @@ void OSSL_SELF_TEST_set_callback(OPENSSL_CTX *libctx, OSSL_CALLBACK *cb,
stcb->cbarg = cbarg; stcb->cbarg = cbarg;
} }
} }
#endif /* FIPS_MODE */
void OSSL_SELF_TEST_get_callback(OPENSSL_CTX *libctx, OSSL_CALLBACK **cb, void OSSL_SELF_TEST_get_callback(OPENSSL_CTX *libctx, OSSL_CALLBACK **cb,
void **cbarg) void **cbarg)
{ {
@ -60,3 +78,91 @@ void OSSL_SELF_TEST_get_callback(OPENSSL_CTX *libctx, OSSL_CALLBACK **cb,
if (cbarg != NULL) if (cbarg != NULL)
*cbarg = (stcb != NULL ? stcb->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;
}
}

View File

@ -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

View File

@ -32,6 +32,7 @@ not been called.
L<openssl-core.h(7)>, L<openssl-core.h(7)>,
L<OSSL_PROVIDER-FIPS(7)> L<OSSL_PROVIDER-FIPS(7)>
L<OSSL_SELF_TEST_new(3)>
L<OPENSSL_CTX(3)> L<OPENSSL_CTX(3)>
=head1 HISTORY =head1 HISTORY

View File

@ -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 mechanism is available to return information to the user using
L<OSSL_SELF_TEST_set_callback(3)>. 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 The OPENSSL FIPS module uses the following mechanism to provide information
about the self tests as they run. about the self tests as they run.
This is useful for debugging if a self test is failing. 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 The callback also allows forcing any self test to fail, in order to check that
it operates correctly on failure. 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. Note that all self tests run even if a self test failure occurs.
=back The FIPS module passes the following type(s) to OSSL_SELF_TEST_onbegin().
=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:
=over 4 =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" There is only one instance of the "Module_Integrity" and "Install_Integrity"
self tests. All other self tests may have multiple instances. 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 FIPS module passes the following descriptions(s) to OSSL_SELF_TEST_onbegin().
The following description strings are used.
=over 4 =over 4
@ -187,8 +142,6 @@ DRBG tests used with the "DRBG" type.
=back =back
=back
=head1 EXAMPLES =head1 EXAMPLES
A simple self test callback is shown below for illustrative purposes. 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<openssl-fipsinstall(1)>,
L<fips_config(5)>, L<fips_config(5)>,
L<OSSL_SELF_TEST_set_callback(3)>, L<OSSL_SELF_TEST_set_callback(3)>,
L<OSSL_SELF_TEST_new(3)>,
L<OSSL_PARAM(3)>, L<OSSL_PARAM(3)>,
L<openssl-core.h(7)> L<openssl-core.h(7)>
@ -250,7 +204,7 @@ The type and functions described here were added in OpenSSL 3.0.
=head1 COPYRIGHT =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 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 this file except in compliance with the License. You can obtain a copy

View File

@ -49,5 +49,6 @@ int ecdh_KDF_X9_63(unsigned char *out, size_t outlen,
const unsigned char *sinfo, size_t sinfolen, const unsigned char *sinfo, size_t sinfolen,
const EVP_MD *md); const EVP_MD *md);
int ec_generate_key(OPENSSL_CTX *libctx, EC_KEY *eckey, int pairwise_test);
# endif /* OPENSSL_NO_EC */ # endif /* OPENSSL_NO_EC */
#endif #endif

View File

@ -65,4 +65,12 @@ void OSSL_SELF_TEST_set_callback(OPENSSL_CTX *libctx, OSSL_CALLBACK *cb,
void OSSL_SELF_TEST_get_callback(OPENSSL_CTX *libctx, OSSL_CALLBACK **cb, void OSSL_SELF_TEST_get_callback(OPENSSL_CTX *libctx, OSSL_CALLBACK **cb,
void **cbarg); 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 */ #endif /* OPENSSL_SELF_TEST_H */

View File

@ -209,6 +209,8 @@ typedef int pem_password_cb (char *buf, int size, int rwflag, void *userdata);
typedef struct ossl_serializer_st OSSL_SERIALIZER; typedef struct ossl_serializer_st OSSL_SERIALIZER;
typedef struct ossl_serializer_ctx_st OSSL_SERIALIZER_CTX; 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 && \ #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L && \
defined(INTMAX_MAX) && defined(UINTMAX_MAX) defined(INTMAX_MAX) && defined(UINTMAX_MAX)
typedef intmax_t ossl_intmax_t; typedef intmax_t ossl_intmax_t;

View File

@ -1,2 +1,2 @@
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 ../.. INCLUDE[../fips]=../implementations/include ../common/include ../..

View File

@ -966,12 +966,12 @@ int OSSL_provider_init(const OSSL_PROVIDER *provider,
} }
if (stcbfn != NULL && c_get_libctx != NULL) { if (stcbfn != NULL && c_get_libctx != NULL) {
stcbfn(c_get_libctx(provider), &selftest_params.event_cb, stcbfn(c_get_libctx(provider), &selftest_params.cb,
&selftest_params.event_cb_arg); &selftest_params.cb_arg);
} }
else { else {
selftest_params.event_cb = NULL; selftest_params.cb = NULL;
selftest_params.event_cb_arg = NULL; selftest_params.cb_arg = NULL;
} }
if (!c_get_params(provider, core_params)) if (!c_get_params(provider, core_params))

View File

@ -132,7 +132,7 @@ DEP_FINI_ATTRIBUTE void cleanup(void)
*/ */
static int verify_integrity(BIO *bio, OSSL_BIO_read_ex_fn read_ex_cb, static int verify_integrity(BIO *bio, OSSL_BIO_read_ex_fn read_ex_cb,
unsigned char *expected, size_t expected_len, 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) const char *event_type)
{ {
int ret = 0, status; int ret = 0, status;
@ -143,7 +143,7 @@ static int verify_integrity(BIO *bio, OSSL_BIO_read_ex_fn read_ex_cb,
EVP_MAC_CTX *ctx = NULL; EVP_MAC_CTX *ctx = NULL;
OSSL_PARAM params[3], *p = params; 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); mac = EVP_MAC_fetch(libctx, MAC_NAME, NULL);
ctx = EVP_MAC_CTX_new(mac); ctx = EVP_MAC_CTX_new(mac);
@ -170,13 +170,13 @@ static int verify_integrity(BIO *bio, OSSL_BIO_read_ex_fn read_ex_cb,
if (!EVP_MAC_final(ctx, out, &out_len, sizeof(out))) if (!EVP_MAC_final(ctx, out, &out_len, sizeof(out)))
goto err; goto err;
SELF_TEST_EVENT_oncorrupt_byte(ev, out); OSSL_SELF_TEST_oncorrupt_byte(ev, out);
if (expected_len != out_len if (expected_len != out_len
|| memcmp(expected, out, out_len) != 0) || memcmp(expected, out, out_len) != 0)
goto err; goto err;
ret = 1; ret = 1;
err: err:
SELF_TEST_EVENT_onend(ev, ret); OSSL_SELF_TEST_onend(ev, ret);
EVP_MAC_CTX_free(ctx); EVP_MAC_CTX_free(ctx);
EVP_MAC_free(mac); EVP_MAC_free(mac);
return ret; return ret;
@ -192,7 +192,7 @@ int SELF_TEST_post(SELF_TEST_POST_PARAMS *st, int on_demand_test)
unsigned char *module_checksum = NULL; unsigned char *module_checksum = NULL;
unsigned char *indicator_checksum = NULL; unsigned char *indicator_checksum = NULL;
int loclstate; int loclstate;
OSSL_ST_EVENT ev; OSSL_SELF_TEST *ev = NULL;
if (!RUN_ONCE(&fips_self_test_init, do_fips_self_test_init)) if (!RUN_ONCE(&fips_self_test_init, do_fips_self_test_init))
return 0; return 0;
@ -223,7 +223,9 @@ int SELF_TEST_post(SELF_TEST_POST_PARAMS *st, int on_demand_test)
|| st->module_checksum_data == NULL) || st->module_checksum_data == NULL)
goto end; 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, module_checksum = OPENSSL_hexstr2buf(st->module_checksum_data,
&checksum_len); &checksum_len);
@ -235,7 +237,7 @@ int SELF_TEST_post(SELF_TEST_POST_PARAMS *st, int on_demand_test)
if (bio_module == NULL if (bio_module == NULL
|| !verify_integrity(bio_module, st->bio_read_ex_cb, || !verify_integrity(bio_module, st->bio_read_ex_cb,
module_checksum, checksum_len, st->libctx, module_checksum, checksum_len, st->libctx,
&ev, OSSL_SELF_TEST_TYPE_MODULE_INTEGRITY)) ev, OSSL_SELF_TEST_TYPE_MODULE_INTEGRITY))
goto end; goto end;
/* This will be NULL during installation - so the self test KATS will run */ /* This will be NULL during installation - so the self test KATS will run */
@ -257,7 +259,7 @@ int SELF_TEST_post(SELF_TEST_POST_PARAMS *st, int on_demand_test)
if (bio_indicator == NULL if (bio_indicator == NULL
|| !verify_integrity(bio_indicator, st->bio_read_ex_cb, || !verify_integrity(bio_indicator, st->bio_read_ex_cb,
indicator_checksum, checksum_len, indicator_checksum, checksum_len,
st->libctx, &ev, st->libctx, ev,
OSSL_SELF_TEST_TYPE_INSTALL_INTEGRITY)) OSSL_SELF_TEST_TYPE_INSTALL_INTEGRITY))
goto end; goto end;
else else
@ -266,11 +268,12 @@ int SELF_TEST_post(SELF_TEST_POST_PARAMS *st, int on_demand_test)
/* Only runs the KAT's during installation OR on_demand() */ /* Only runs the KAT's during installation OR on_demand() */
if (on_demand_test || kats_already_passed == 0) { if (on_demand_test || kats_already_passed == 0) {
if (!SELF_TEST_kats(&ev, st->libctx)) if (!SELF_TEST_kats(ev, st->libctx))
goto end; goto end;
} }
ok = 1; ok = 1;
end: end:
OSSL_SELF_TEST_free(ev);
OPENSSL_free(module_checksum); OPENSSL_free(module_checksum);
OPENSSL_free(indicator_checksum); OPENSSL_free(indicator_checksum);

View File

@ -26,31 +26,11 @@ typedef struct self_test_post_params_st {
OSSL_BIO_new_membuf_fn *bio_new_buffer_cb; OSSL_BIO_new_membuf_fn *bio_new_buffer_cb;
OSSL_BIO_read_ex_fn *bio_read_ex_cb; OSSL_BIO_read_ex_fn *bio_read_ex_cb;
OSSL_BIO_free_fn *bio_free_cb; OSSL_BIO_free_fn *bio_free_cb;
OSSL_CALLBACK *event_cb; OSSL_CALLBACK *cb;
void *event_cb_arg; void *cb_arg;
OPENSSL_CTX *libctx; OPENSSL_CTX *libctx;
} SELF_TEST_POST_PARAMS; } 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;
} OSSL_ST_EVENT;
int SELF_TEST_post(SELF_TEST_POST_PARAMS *st, int on_demand_test); int SELF_TEST_post(SELF_TEST_POST_PARAMS *st, int on_demand_test);
int SELF_TEST_kats(OSSL_ST_EVENT *event, OPENSSL_CTX *libctx); int SELF_TEST_kats(OSSL_SELF_TEST *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);

View File

@ -1,93 +0,0 @@
/*
* 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;
}
}

View File

@ -20,7 +20,7 @@
#define DRBG_PARAM_ENTROPY "DRBG-ENTROPY" #define DRBG_PARAM_ENTROPY "DRBG-ENTROPY"
#define DRBG_PARAM_NONCE "DRBG-NONCE" #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) OPENSSL_CTX *libctx)
{ {
int ok = 0; int ok = 0;
@ -29,7 +29,7 @@ static int self_test_digest(const ST_KAT_DIGEST *t, OSSL_ST_EVENT *event,
EVP_MD_CTX *ctx = EVP_MD_CTX_new(); EVP_MD_CTX *ctx = EVP_MD_CTX_new();
EVP_MD *md = EVP_MD_fetch(libctx, t->algorithm, NULL); 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 if (ctx == NULL
|| md == NULL || md == NULL
@ -39,14 +39,14 @@ static int self_test_digest(const ST_KAT_DIGEST *t, OSSL_ST_EVENT *event,
goto err; goto err;
/* Optional corruption */ /* Optional corruption */
SELF_TEST_EVENT_oncorrupt_byte(event, out); OSSL_SELF_TEST_oncorrupt_byte(st, out);
if (out_len != t->expected_len if (out_len != t->expected_len
|| memcmp(out, t->expected, out_len) != 0) || memcmp(out, t->expected, out_len) != 0)
goto err; goto err;
ok = 1; ok = 1;
err: err:
SELF_TEST_EVENT_onend(event, ok); OSSL_SELF_TEST_onend(st, ok);
EVP_MD_free(md); EVP_MD_free(md);
EVP_MD_CTX_free(ctx); EVP_MD_CTX_free(ctx);
@ -86,7 +86,7 @@ static int cipher_init(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
} }
/* Test a single KAT for encrypt/decrypt */ /* 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) OPENSSL_CTX *libctx)
{ {
int ret = 0, encrypt = 1, len, ct_len = 0, pt_len = 0; int ret = 0, encrypt = 1, len, ct_len = 0, pt_len = 0;
@ -95,7 +95,7 @@ static int self_test_cipher(const ST_KAT_CIPHER *t, OSSL_ST_EVENT *event,
unsigned char ct_buf[256] = { 0 }; unsigned char ct_buf[256] = { 0 };
unsigned char pt_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(); ctx = EVP_CIPHER_CTX_new();
if (ctx == NULL) if (ctx == NULL)
@ -110,7 +110,7 @@ static int self_test_cipher(const ST_KAT_CIPHER *t, OSSL_ST_EVENT *event,
|| !EVP_CipherFinal_ex(ctx, ct_buf + len, &ct_len)) || !EVP_CipherFinal_ex(ctx, ct_buf + len, &ct_len))
goto err; goto err;
SELF_TEST_EVENT_oncorrupt_byte(event, ct_buf); OSSL_SELF_TEST_oncorrupt_byte(st, ct_buf);
ct_len += len; ct_len += len;
if (ct_len != (int)t->base.expected_len if (ct_len != (int)t->base.expected_len
|| memcmp(t->base.expected, ct_buf, ct_len) != 0) || memcmp(t->base.expected, ct_buf, ct_len) != 0)
@ -138,11 +138,11 @@ static int self_test_cipher(const ST_KAT_CIPHER *t, OSSL_ST_EVENT *event,
err: err:
EVP_CIPHER_free(cipher); EVP_CIPHER_free(cipher);
EVP_CIPHER_CTX_free(ctx); EVP_CIPHER_CTX_free(ctx);
SELF_TEST_EVENT_onend(event, ret); OSSL_SELF_TEST_onend(st, ret);
return 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) OPENSSL_CTX *libctx)
{ {
int ret = 0; int ret = 0;
@ -154,7 +154,7 @@ static int self_test_kdf(const ST_KAT_KDF *t, OSSL_ST_EVENT *event,
const OSSL_PARAM *settables = NULL; const OSSL_PARAM *settables = NULL;
numparams = OSSL_NELEM(params); 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 */ /* Zeroize the params array to avoid mem leaks on error */
for (i = 0; i < numparams; ++i) for (i = 0; i < numparams; ++i)
@ -183,7 +183,7 @@ static int self_test_kdf(const ST_KAT_KDF *t, OSSL_ST_EVENT *event,
if (EVP_KDF_derive(ctx, out, t->expected_len) <= 0) if (EVP_KDF_derive(ctx, out, t->expected_len) <= 0)
goto err; 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) if (memcmp(out, t->expected, t->expected_len) != 0)
goto err; goto err;
@ -194,7 +194,7 @@ err:
OPENSSL_free(params[i].data); OPENSSL_free(params[i].data);
EVP_KDF_free(kdf); EVP_KDF_free(kdf);
EVP_KDF_CTX_free(ctx); EVP_KDF_CTX_free(ctx);
SELF_TEST_EVENT_onend(event, ret); OSSL_SELF_TEST_onend(st, ret);
return ret; return ret;
} }
@ -223,7 +223,7 @@ static size_t drbg_kat_nonce_cb(RAND_DRBG *drbg, unsigned char **pout,
return p->data_size; 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) OPENSSL_CTX *libctx)
{ {
int ret = 0; int ret = 0;
@ -236,7 +236,7 @@ static int self_test_drbg(const ST_KAT_DRBG *t, OSSL_ST_EVENT *event,
}; };
static const unsigned char zero[sizeof(drbg->data)] = { 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) if (strcmp(t->desc, OSSL_SELF_TEST_DESC_DRBG_HMAC) == 0)
flags |= RAND_DRBG_FLAG_HMAC; flags |= RAND_DRBG_FLAG_HMAC;
@ -280,7 +280,7 @@ static int self_test_drbg(const ST_KAT_DRBG *t, OSSL_ST_EVENT *event,
t->entropyaddin2, t->entropyaddin2len)) t->entropyaddin2, t->entropyaddin2len))
goto err; goto err;
SELF_TEST_EVENT_oncorrupt_byte(event, out); OSSL_SELF_TEST_oncorrupt_byte(st, out);
if (memcmp(out, t->expected, t->expectedlen) != 0) if (memcmp(out, t->expected, t->expectedlen) != 0)
goto err; goto err;
@ -296,7 +296,7 @@ static int self_test_drbg(const ST_KAT_DRBG *t, OSSL_ST_EVENT *event,
ret = 1; ret = 1;
err: err:
RAND_DRBG_free(drbg); RAND_DRBG_free(drbg);
SELF_TEST_EVENT_onend(event, ret); OSSL_SELF_TEST_onend(st, ret);
return ret; return ret;
} }
@ -305,45 +305,45 @@ err:
* All tests are run regardless of if they fail or not. * All tests are run regardless of if they fail or not.
* Return 0 if any test fails. * 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; int i, ret = 1;
for (i = 0; i < (int)OSSL_NELEM(st_kat_digest_tests); ++i) { 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; ret = 0;
} }
return ret; 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; int i, ret = 1;
for (i = 0; i < (int)OSSL_NELEM(st_kat_cipher_tests); ++i) { 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; ret = 0;
} }
return ret; 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; int i, ret = 1;
for (i = 0; i < (int)OSSL_NELEM(st_kat_kdf_tests); ++i) { 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; ret = 0;
} }
return ret; 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; int i, ret = 1;
for (i = 0; i < (int)OSSL_NELEM(st_kat_drbg_tests); ++i) { 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; ret = 0;
} }
return ret; return ret;
@ -356,17 +356,17 @@ static int self_test_drbgs(OSSL_ST_EVENT *event, OPENSSL_CTX *libctx)
* *
* TODO(3.0) Add self tests for KA, Sign/Verify when they become available * 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; int ret = 1;
if (!self_test_digests(event, libctx)) if (!self_test_digests(st, libctx))
ret = 0; ret = 0;
if (!self_test_ciphers(event, libctx)) if (!self_test_ciphers(st, libctx))
ret = 0; ret = 0;
if (!self_test_kdfs(event, libctx)) if (!self_test_kdfs(st, libctx))
ret = 0; ret = 0;
if (!self_test_drbgs(event, libctx)) if (!self_test_drbgs(st, libctx))
ret = 0; ret = 0;
return ret; return ret;

View File

@ -4947,3 +4947,8 @@ EVP_PKEY_CTX_set0_ecdh_kdf_ukm ? 3_0_0 EXIST::FUNCTION:EC
EVP_PKEY_CTX_get0_ecdh_kdf_ukm ? 3_0_0 EXIST::FUNCTION:EC 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_set_rsa_pss_saltlen ? 3_0_0 EXIST::FUNCTION:RSA
EVP_PKEY_CTX_get_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: