Adding in curl and openssl repos

This commit is contained in:
2025-08-14 12:09:30 -04:00
parent af2117b574
commit 0ace93e303
21174 changed files with 3607720 additions and 2 deletions

View File

@@ -0,0 +1,6 @@
# We include the provider implementation into ../libfips.a, so that all
# platforms can resolve symbols in other members of that library.
SOURCE[../libfips.a]=fipsprov.c self_test.c self_test_kats.c fipsindicator.c
# It is necessary to have an explicit entry point
SOURCE[../fips]=fips_entry.c

View File

@@ -0,0 +1,19 @@
/*
* Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <openssl/core.h>
OSSL_provider_init_fn OSSL_provider_init_int;
int OSSL_provider_init(const OSSL_CORE_HANDLE *handle,
const OSSL_DISPATCH *in,
const OSSL_DISPATCH **out,
void **provctx)
{
return OSSL_provider_init_int(handle, in, out, provctx);
}

View File

@@ -0,0 +1,116 @@
/*
* Copyright 2024 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <openssl/indicator.h>
#include <openssl/params.h>
#include <openssl/core_names.h>
#include "internal/common.h" /* for ossl_assert() */
#include "fips/fipsindicator.h"
void ossl_FIPS_IND_init(OSSL_FIPS_IND *ind)
{
int i;
ossl_FIPS_IND_set_approved(ind); /* Assume we are approved by default */
for (i = 0; i < OSSL_FIPS_IND_SETTABLE_MAX; i++)
ind->settable[i] = OSSL_FIPS_IND_STATE_UNKNOWN;
}
void ossl_FIPS_IND_set_approved(OSSL_FIPS_IND *ind)
{
ind->approved = 1;
}
void ossl_FIPS_IND_copy(OSSL_FIPS_IND *dst, const OSSL_FIPS_IND *src)
{
*dst = *src;
}
void ossl_FIPS_IND_set_settable(OSSL_FIPS_IND *ind, int id, int state)
{
if (!ossl_assert(id < OSSL_FIPS_IND_SETTABLE_MAX))
return;
if (!ossl_assert(state == OSSL_FIPS_IND_STATE_STRICT
|| state == OSSL_FIPS_IND_STATE_TOLERANT))
return;
ind->settable[id] = state;
}
int ossl_FIPS_IND_get_settable(const OSSL_FIPS_IND *ind, int id)
{
if (!ossl_assert(id < OSSL_FIPS_IND_SETTABLE_MAX))
return OSSL_FIPS_IND_STATE_UNKNOWN;
return ind->settable[id];
}
/*
* This should only be called when a strict FIPS algorithm check fails.
* It assumes that we are in strict mode by default.
* If the logic here is not sufficient for all cases, then additional
* ossl_FIPS_IND_on_unapproved() functions may be required.
*/
int ossl_FIPS_IND_on_unapproved(OSSL_FIPS_IND *ind, int id,
OSSL_LIB_CTX *libctx,
const char *algname, const char *opname,
OSSL_FIPS_IND_CHECK_CB *config_check_fn)
{
/* Set to unapproved. Once unapproved mode is set this will not be reset */
ind->approved = 0;
/*
* We only trigger the indicator callback if the ctx variable is cleared OR
* the configurable item is cleared. If the values are unknown they are
* assumed to be strict.
*/
if (ossl_FIPS_IND_get_settable(ind, id) == OSSL_FIPS_IND_STATE_TOLERANT
|| (config_check_fn != NULL
&& config_check_fn(libctx) == OSSL_FIPS_IND_STATE_TOLERANT)) {
return ossl_FIPS_IND_callback(libctx, algname, opname);
}
/* Strict mode gets here: This returns an error */
return 0;
}
int ossl_FIPS_IND_set_ctx_param(OSSL_FIPS_IND *ind, int id,
const OSSL_PARAM params[], const char *name)
{
int in = 0;
const OSSL_PARAM *p = OSSL_PARAM_locate_const(params, name);
if (p != NULL) {
if (!OSSL_PARAM_get_int(p, &in))
return 0;
ossl_FIPS_IND_set_settable(ind, id, in);
}
return 1;
}
int ossl_FIPS_IND_get_ctx_param(const OSSL_FIPS_IND *ind, OSSL_PARAM params[])
{
OSSL_PARAM *p = OSSL_PARAM_locate(params, OSSL_ALG_PARAM_FIPS_APPROVED_INDICATOR);
return p == NULL || OSSL_PARAM_set_int(p, ind->approved);
}
/*
* Can be used during application testing to log that an indicator was
* triggered. The callback will return 1 if the application wants an error
* to occur based on the indicator type and description.
*/
int ossl_FIPS_IND_callback(OSSL_LIB_CTX *libctx, const char *type,
const char *desc)
{
OSSL_INDICATOR_CALLBACK *cb = NULL;
OSSL_INDICATOR_get_callback(libctx, &cb);
if (cb == NULL)
return 1;
return cb(type, desc, NULL);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,151 @@
/*
* Copyright 2023-2024 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#ifdef FIPS_MODULE
# include <openssl/core.h> /* OSSL_CALLBACK, OSSL_LIB_CTX */
# include <openssl/indicator.h>
# include "crypto/types.h"
# include <openssl/ec.h>
# include "fipscommon.h"
/*
* There may be multiple settables associated with an algorithm that allow
* overriding the default status.
* We associate an id with each of these.
*/
# define OSSL_FIPS_IND_SETTABLE0 0
# define OSSL_FIPS_IND_SETTABLE1 1
# define OSSL_FIPS_IND_SETTABLE2 2
# define OSSL_FIPS_IND_SETTABLE3 3
# define OSSL_FIPS_IND_SETTABLE4 4
# define OSSL_FIPS_IND_SETTABLE5 5
# define OSSL_FIPS_IND_SETTABLE6 6
# define OSSL_FIPS_IND_SETTABLE7 7
# define OSSL_FIPS_IND_SETTABLE_MAX (1 + OSSL_FIPS_IND_SETTABLE7)
/* Each settable is in one of 3 states */
#define OSSL_FIPS_IND_STATE_UNKNOWN -1 /* Initial unknown state */
#define OSSL_FIPS_IND_STATE_STRICT 1 /* Strict enforcement */
#define OSSL_FIPS_IND_STATE_TOLERANT 0 /* Relaxation of rules */
/*
* For each algorithm context there may be multiple checks that determine if
* the algorithm is approved or not. These checks may be in different stages.
* To keep it simple it is assumed that the algorithm is initially approved,
* and may be unapproved when each check happens. Once unapproved the operation
* will remain unapproved (otherwise we need to maintain state for each check).
* The approved state should only be queried after the operation has completed
* e.g. A digest final, or a KDF derive.
*
* If a FIPS approved check fails then we must decide what to do in this case.
* In strict mode we would just return an error.
* To override strict mode we either need to have a settable variable or have a
* fips config flag that overrides strict mode.
* If there are multiple checks, each one could possible have a different
* configurable item. Each configurable item can be overridden by a different
* settable.
*/
typedef struct ossl_fips_ind_st {
unsigned char approved;
signed char settable[OSSL_FIPS_IND_SETTABLE_MAX]; /* See OSSL_FIPS_IND_STATE */
} OSSL_FIPS_IND;
typedef int (OSSL_FIPS_IND_CHECK_CB)(OSSL_LIB_CTX *libctx);
int ossl_FIPS_IND_callback(OSSL_LIB_CTX *libctx, const char *type,
const char *desc);
void ossl_FIPS_IND_init(OSSL_FIPS_IND *ind);
void ossl_FIPS_IND_set_approved(OSSL_FIPS_IND *ind);
void ossl_FIPS_IND_set_settable(OSSL_FIPS_IND *ind, int id, int enable);
int ossl_FIPS_IND_get_settable(const OSSL_FIPS_IND *ind, int id);
int ossl_FIPS_IND_on_unapproved(OSSL_FIPS_IND *ind, int id, OSSL_LIB_CTX *libctx,
const char *algname, const char *opname,
OSSL_FIPS_IND_CHECK_CB *config_check_fn);
int ossl_FIPS_IND_set_ctx_param(OSSL_FIPS_IND *ind, int id,
const OSSL_PARAM params[], const char *name);
int ossl_FIPS_IND_get_ctx_param(const OSSL_FIPS_IND *ind,
OSSL_PARAM params[]);
void ossl_FIPS_IND_copy(OSSL_FIPS_IND *dst, const OSSL_FIPS_IND *src);
/* Place this in the algorithm ctx structure */
# define OSSL_FIPS_IND_DECLARE OSSL_FIPS_IND indicator;
/* Call this to initialize the indicator */
# define OSSL_FIPS_IND_INIT(ctx) ossl_FIPS_IND_init(&ctx->indicator);
/*
* Use the copy if an algorithm has a dup function that does not copy the src to
* the dst.
*/
# define OSSL_FIPS_IND_COPY(dst, src) ossl_FIPS_IND_copy(&dst->indicator, &src->indicator);
/*
* Required for reset - since once something becomes unapproved it will remain
* unapproved unless this is used. This should be used in the init before
* params are set into the ctx & before any FIPS checks are done.
*/
# define OSSL_FIPS_IND_SET_APPROVED(ctx) ossl_FIPS_IND_set_approved(&ctx->indicator);
/*
* This should be called if a FIPS check fails, to indicate the operation is not approved
* If there is more than 1 strict check flag per algorithm ctx, the id represents
* the index.
*/
# define OSSL_FIPS_IND_ON_UNAPPROVED(ctx, id, libctx, algname, opname, config_check_fn) \
ossl_FIPS_IND_on_unapproved(&ctx->indicator, id, libctx, algname, opname, config_check_fn)
# define OSSL_FIPS_IND_SETTABLE_CTX_PARAM(name) \
OSSL_PARAM_int(name, NULL),
/*
* The id here must match the one used by OSSL_FIPS_IND_ON_UNAPPROVED
* The name must match the param used by OSSL_FIPS_IND_SETTABLE_CTX_PARAM
*/
# define OSSL_FIPS_IND_SET_CTX_PARAM(ctx, id, params, name) \
ossl_FIPS_IND_set_ctx_param(&((ctx)->indicator), id, params, name)
# define OSSL_FIPS_IND_GETTABLE_CTX_PARAM() \
OSSL_PARAM_int(OSSL_ALG_PARAM_FIPS_APPROVED_INDICATOR, NULL),
# define OSSL_FIPS_IND_GET_CTX_PARAM(ctx, prms) \
ossl_FIPS_IND_get_ctx_param(&((ctx)->indicator), prms)
# define OSSL_FIPS_IND_GET(ctx) (&((ctx)->indicator))
# define OSSL_FIPS_IND_GET_PARAM(ctx, p, settable, id, name) \
*settable = ossl_FIPS_IND_get_settable(&((ctx)->indicator), id); \
if (*settable != OSSL_FIPS_IND_STATE_UNKNOWN) \
*p = OSSL_PARAM_construct_int(name, settable);
int ossl_fips_ind_rsa_key_check(OSSL_FIPS_IND *ind, int id, OSSL_LIB_CTX *libctx,
const RSA *rsa, const char *desc, int protect);
# ifndef OPENSSL_NO_EC
int ossl_fips_ind_ec_key_check(OSSL_FIPS_IND *ind, int id, OSSL_LIB_CTX *libctx,
const EC_GROUP *group, const char *desc,
int protect);
# endif
int ossl_fips_ind_digest_exch_check(OSSL_FIPS_IND *ind, int id, OSSL_LIB_CTX *libctx,
const EVP_MD *md, const char *desc);
int ossl_fips_ind_digest_sign_check(OSSL_FIPS_IND *ind, int id,
OSSL_LIB_CTX *libctx,
int nid, int sha1_allowed,
const char *desc,
OSSL_FIPS_IND_CHECK_CB *config_check_f);
#else
# define OSSL_FIPS_IND_DECLARE
# define OSSL_FIPS_IND_INIT(ctx)
# define OSSL_FIPS_IND_SET_APPROVED(ctx)
# define OSSL_FIPS_IND_ON_UNAPPROVED(ctx, id, libctx, algname, opname, configopt_fn)
# define OSSL_FIPS_IND_SETTABLE_CTX_PARAM(name)
# define OSSL_FIPS_IND_SET_CTX_PARAM(ctx, id, params, name) 1
# define OSSL_FIPS_IND_GETTABLE_CTX_PARAM()
# define OSSL_FIPS_IND_GET_CTX_PARAM(ctx, params) 1
# define OSSL_FIPS_IND_COPY(dst, src)
#endif

View File

@@ -0,0 +1,28 @@
OSSL_FIPS_PARAM(security_checks, SECURITY_CHECKS, 1)
OSSL_FIPS_PARAM(tls1_prf_ems_check, TLS1_PRF_EMS_CHECK, 0)
OSSL_FIPS_PARAM(no_short_mac, NO_SHORT_MAC, 1)
OSSL_FIPS_PARAM(hmac_key_check, HMAC_KEY_CHECK, 0)
OSSL_FIPS_PARAM(kmac_key_check, KMAC_KEY_CHECK, 0)
OSSL_FIPS_PARAM(restricted_drbg_digests, DRBG_TRUNC_DIGEST, 0)
OSSL_FIPS_PARAM(signature_digest_check, SIGNATURE_DIGEST_CHECK, 0)
OSSL_FIPS_PARAM(hkdf_digest_check, HKDF_DIGEST_CHECK, 0)
OSSL_FIPS_PARAM(tls13_kdf_digest_check, TLS13_KDF_DIGEST_CHECK, 0)
OSSL_FIPS_PARAM(tls1_prf_digest_check, TLS1_PRF_DIGEST_CHECK, 0)
OSSL_FIPS_PARAM(sshkdf_digest_check, SSHKDF_DIGEST_CHECK, 0)
OSSL_FIPS_PARAM(sskdf_digest_check, SSKDF_DIGEST_CHECK, 0)
OSSL_FIPS_PARAM(x963kdf_digest_check, X963KDF_DIGEST_CHECK, 0)
OSSL_FIPS_PARAM(dsa_sign_disallowed, DSA_SIGN_DISABLED, 0)
OSSL_FIPS_PARAM(tdes_encrypt_disallowed, TDES_ENCRYPT_DISABLED, 0)
OSSL_FIPS_PARAM(rsa_pkcs15_padding_disabled, RSA_PKCS15_PAD_DISABLED, 0)
OSSL_FIPS_PARAM(rsa_pss_saltlen_check, RSA_PSS_SALTLEN_CHECK, 0)
OSSL_FIPS_PARAM(rsa_sign_x931_disallowed, RSA_SIGN_X931_PAD_DISABLED, 0)
OSSL_FIPS_PARAM(hkdf_key_check, HKDF_KEY_CHECK, 0)
OSSL_FIPS_PARAM(kbkdf_key_check, KBKDF_KEY_CHECK, 0)
OSSL_FIPS_PARAM(tls13_kdf_key_check, TLS13_KDF_KEY_CHECK, 0)
OSSL_FIPS_PARAM(tls1_prf_key_check, TLS1_PRF_KEY_CHECK, 0)
OSSL_FIPS_PARAM(sshkdf_key_check, SSHKDF_KEY_CHECK, 0)
OSSL_FIPS_PARAM(sskdf_key_check, SSKDF_KEY_CHECK, 0)
OSSL_FIPS_PARAM(x963kdf_key_check, X963KDF_KEY_CHECK, 0)
OSSL_FIPS_PARAM(x942kdf_key_check, X942KDF_KEY_CHECK, 0)
OSSL_FIPS_PARAM(pbkdf2_lower_bound_check, PBKDF2_LOWER_BOUND_CHECK, 1)
OSSL_FIPS_PARAM(ecdh_cofactor_check, ECDH_COFACTOR_CHECK, 0)

View File

@@ -0,0 +1,3 @@
OSSL_FIPS_PARAM(module_filename, OSSL_PROV_PARAM_CORE_MODULE_FILENAME)
OSSL_FIPS_PARAM(module_checksum_data, OSSL_PROV_FIPS_PARAM_MODULE_MAC)
OSSL_FIPS_PARAM(conditional_error_check, OSSL_PROV_FIPS_PARAM_CONDITIONAL_ERRORS)

View File

@@ -0,0 +1,18 @@
/*
* Copyright 2023-2024 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#ifdef FIPS_MODULE
# include <openssl/types.h>
# define OSSL_FIPS_PARAM(structname, paramname, unused) \
int ossl_fips_config_##structname(OSSL_LIB_CTX *libctx);
# include "fips_indicator_params.inc"
# undef OSSL_FIPS_PARAM
#endif

View File

@@ -0,0 +1,438 @@
/*
* Copyright 2019-2024 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <string.h>
#include <openssl/evp.h>
#include <openssl/params.h>
#include <openssl/crypto.h>
#include "internal/cryptlib.h"
#include <openssl/fipskey.h>
#include <openssl/err.h>
#include <openssl/proverr.h>
#include <openssl/rand.h>
#include "internal/e_os.h"
#include "internal/tsan_assist.h"
#include "prov/providercommon.h"
#include "crypto/rand.h"
/*
* We're cheating here. Normally we don't allow RUN_ONCE usage inside the FIPS
* module because all such initialisation should be associated with an
* individual OSSL_LIB_CTX. That doesn't work with the self test though because
* it should be run once regardless of the number of OSSL_LIB_CTXs we have.
*/
#define ALLOW_RUN_ONCE_IN_FIPS
#include "internal/thread_once.h"
#include "self_test.h"
#define FIPS_STATE_INIT 0
#define FIPS_STATE_SELFTEST 1
#define FIPS_STATE_RUNNING 2
#define FIPS_STATE_ERROR 3
/*
* The number of times the module will report it is in the error state
* before going quiet.
*/
#define FIPS_ERROR_REPORTING_RATE_LIMIT 10
/* The size of a temp buffer used to read in data */
#define INTEGRITY_BUF_SIZE (4096)
#define MAX_MD_SIZE 64
#define MAC_NAME "HMAC"
#define DIGEST_NAME "SHA256"
static int FIPS_conditional_error_check = 1;
static CRYPTO_RWLOCK *self_test_lock = NULL;
static CRYPTO_ONCE fips_self_test_init = CRYPTO_ONCE_STATIC_INIT;
#if !defined(OPENSSL_NO_FIPS_POST)
static unsigned char fixed_key[32] = { FIPS_KEY_ELEMENTS };
#endif
DEFINE_RUN_ONCE_STATIC(do_fips_self_test_init)
{
/*
* These locks get freed in platform specific ways that may occur after we
* do mem leak checking. If we don't know how to free it for a particular
* platform then we just leak it deliberately.
*/
self_test_lock = CRYPTO_THREAD_lock_new();
return self_test_lock != NULL;
}
/*
* Declarations for the DEP entry/exit points.
* Ones not required or incorrect need to be undefined or redefined respectively.
*/
#define DEP_INITIAL_STATE FIPS_STATE_INIT
#define DEP_INIT_ATTRIBUTE static
#define DEP_FINI_ATTRIBUTE static
static void init(void);
static void cleanup(void);
/*
* This is the Default Entry Point (DEP) code.
* See FIPS 140-2 IG 9.10
*/
#if defined(_WIN32) || defined(__CYGWIN__)
# ifdef __CYGWIN__
/* pick DLL_[PROCESS|THREAD]_[ATTACH|DETACH] definitions */
# include <windows.h>
/*
* this has side-effect of _WIN32 getting defined, which otherwise is
* mutually exclusive with __CYGWIN__...
*/
# endif
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved);
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
switch (fdwReason) {
case DLL_PROCESS_ATTACH:
init();
break;
case DLL_PROCESS_DETACH:
cleanup();
break;
default:
break;
}
return TRUE;
}
#elif defined(__GNUC__) && !defined(_AIX)
# undef DEP_INIT_ATTRIBUTE
# undef DEP_FINI_ATTRIBUTE
# define DEP_INIT_ATTRIBUTE static __attribute__((constructor))
# define DEP_FINI_ATTRIBUTE static __attribute__((destructor))
#elif defined(__sun)
# pragma init(init)
# pragma fini(cleanup)
#elif defined(_AIX) && !defined(__GNUC__)
void _init(void);
void _cleanup(void);
# pragma init(_init)
# pragma fini(_cleanup)
void _init(void)
{
init();
}
void _cleanup(void)
{
cleanup();
}
#elif defined(__hpux)
# pragma init "init"
# pragma fini "cleanup"
#elif defined(__TANDEM)
/* Method automatically called by the NonStop OS when the DLL loads */
void __INIT__init(void) {
init();
}
/* Method automatically called by the NonStop OS prior to unloading the DLL */
void __TERM__cleanup(void) {
cleanup();
}
#else
/*
* This build does not support any kind of DEP.
* We force the self-tests to run as part of the FIPS provider initialisation
* rather than being triggered by the DEP.
*/
# undef DEP_INIT_ATTRIBUTE
# undef DEP_FINI_ATTRIBUTE
# undef DEP_INITIAL_STATE
# define DEP_INITIAL_STATE FIPS_STATE_SELFTEST
#endif
static TSAN_QUALIFIER int FIPS_state = DEP_INITIAL_STATE;
#if defined(DEP_INIT_ATTRIBUTE)
DEP_INIT_ATTRIBUTE void init(void)
{
tsan_store(&FIPS_state, FIPS_STATE_SELFTEST);
}
#endif
#if defined(DEP_FINI_ATTRIBUTE)
DEP_FINI_ATTRIBUTE void cleanup(void)
{
CRYPTO_THREAD_lock_free(self_test_lock);
}
#endif
#if !defined(OPENSSL_NO_FIPS_POST)
/*
* We need an explicit HMAC-SHA-256 KAT even though it is also
* checked as part of the KDF KATs. Refer IG 10.3.
*/
static const unsigned char hmac_kat_pt[] = {
0xdd, 0x0c, 0x30, 0x33, 0x35, 0xf9, 0xe4, 0x2e,
0xc2, 0xef, 0xcc, 0xbf, 0x07, 0x95, 0xee, 0xa2
};
static const unsigned char hmac_kat_key[] = {
0xf4, 0x55, 0x66, 0x50, 0xac, 0x31, 0xd3, 0x54,
0x61, 0x61, 0x0b, 0xac, 0x4e, 0xd8, 0x1b, 0x1a,
0x18, 0x1b, 0x2d, 0x8a, 0x43, 0xea, 0x28, 0x54,
0xcb, 0xae, 0x22, 0xca, 0x74, 0x56, 0x08, 0x13
};
static const unsigned char hmac_kat_digest[] = {
0xf5, 0xf5, 0xe5, 0xf2, 0x66, 0x49, 0xe2, 0x40,
0xfc, 0x9e, 0x85, 0x7f, 0x2b, 0x9a, 0xbe, 0x28,
0x20, 0x12, 0x00, 0x92, 0x82, 0x21, 0x3e, 0x51,
0x44, 0x5d, 0xe3, 0x31, 0x04, 0x01, 0x72, 0x6b
};
static int integrity_self_test(OSSL_SELF_TEST *ev, OSSL_LIB_CTX *libctx)
{
int ok = 0;
unsigned char out[EVP_MAX_MD_SIZE];
size_t out_len = 0;
OSSL_PARAM params[2];
EVP_MAC *mac = EVP_MAC_fetch(libctx, MAC_NAME, NULL);
EVP_MAC_CTX *ctx = EVP_MAC_CTX_new(mac);
OSSL_SELF_TEST_onbegin(ev, OSSL_SELF_TEST_TYPE_KAT_INTEGRITY,
OSSL_SELF_TEST_DESC_INTEGRITY_HMAC);
params[0] = OSSL_PARAM_construct_utf8_string("digest", DIGEST_NAME, 0);
params[1] = OSSL_PARAM_construct_end();
if (ctx == NULL
|| mac == NULL
|| !EVP_MAC_init(ctx, hmac_kat_key, sizeof(hmac_kat_key), params)
|| !EVP_MAC_update(ctx, hmac_kat_pt, sizeof(hmac_kat_pt))
|| !EVP_MAC_final(ctx, out, &out_len, MAX_MD_SIZE))
goto err;
/* Optional corruption */
OSSL_SELF_TEST_oncorrupt_byte(ev, out);
if (out_len != sizeof(hmac_kat_digest)
|| memcmp(out, hmac_kat_digest, out_len) != 0)
goto err;
ok = 1;
err:
OSSL_SELF_TEST_onend(ev, ok);
EVP_MAC_free(mac);
EVP_MAC_CTX_free(ctx);
return ok;
}
/*
* Calculate the HMAC SHA256 of data read using a BIO and read_cb, and verify
* the result matches the expected value.
* Return 1 if verified, or 0 if it fails.
*/
static int verify_integrity(OSSL_CORE_BIO *bio, OSSL_FUNC_BIO_read_ex_fn read_ex_cb,
unsigned char *expected, size_t expected_len,
OSSL_LIB_CTX *libctx, OSSL_SELF_TEST *ev,
const char *event_type)
{
int ret = 0, status;
unsigned char out[MAX_MD_SIZE];
unsigned char buf[INTEGRITY_BUF_SIZE];
size_t bytes_read = 0, out_len = 0;
EVP_MAC *mac = NULL;
EVP_MAC_CTX *ctx = NULL;
OSSL_PARAM params[2], *p = params;
if (!integrity_self_test(ev, libctx))
goto err;
OSSL_SELF_TEST_onbegin(ev, event_type, OSSL_SELF_TEST_DESC_INTEGRITY_HMAC);
mac = EVP_MAC_fetch(libctx, MAC_NAME, NULL);
if (mac == NULL)
goto err;
ctx = EVP_MAC_CTX_new(mac);
if (ctx == NULL)
goto err;
*p++ = OSSL_PARAM_construct_utf8_string("digest", DIGEST_NAME, 0);
*p = OSSL_PARAM_construct_end();
if (!EVP_MAC_init(ctx, fixed_key, sizeof(fixed_key), params))
goto err;
while (1) {
status = read_ex_cb(bio, buf, sizeof(buf), &bytes_read);
if (status != 1)
break;
if (!EVP_MAC_update(ctx, buf, bytes_read))
goto err;
}
if (!EVP_MAC_final(ctx, out, &out_len, sizeof(out)))
goto err;
OSSL_SELF_TEST_oncorrupt_byte(ev, out);
if (expected_len != out_len
|| memcmp(expected, out, out_len) != 0)
goto err;
ret = 1;
err:
OSSL_SELF_TEST_onend(ev, ret);
EVP_MAC_CTX_free(ctx);
EVP_MAC_free(mac);
return ret;
}
#endif /* OPENSSL_NO_FIPS_POST */
static void set_fips_state(int state)
{
tsan_store(&FIPS_state, state);
}
/* This API is triggered either on loading of the FIPS module or on demand */
int SELF_TEST_post(SELF_TEST_POST_PARAMS *st, int on_demand_test)
{
int loclstate;
#if !defined(OPENSSL_NO_FIPS_POST)
int ok = 0;
long checksum_len;
OSSL_CORE_BIO *bio_module = NULL;
unsigned char *module_checksum = NULL;
OSSL_SELF_TEST *ev = NULL;
EVP_RAND *testrand = NULL;
EVP_RAND_CTX *rng;
#endif
if (!RUN_ONCE(&fips_self_test_init, do_fips_self_test_init))
return 0;
loclstate = tsan_load(&FIPS_state);
if (loclstate == FIPS_STATE_RUNNING) {
if (!on_demand_test)
return 1;
} else if (loclstate != FIPS_STATE_SELFTEST) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_STATE);
return 0;
}
if (!CRYPTO_THREAD_write_lock(self_test_lock))
return 0;
#if !defined(OPENSSL_NO_FIPS_POST)
loclstate = tsan_load(&FIPS_state);
if (loclstate == FIPS_STATE_RUNNING) {
if (!on_demand_test) {
CRYPTO_THREAD_unlock(self_test_lock);
return 1;
}
set_fips_state(FIPS_STATE_SELFTEST);
} else if (loclstate != FIPS_STATE_SELFTEST) {
CRYPTO_THREAD_unlock(self_test_lock);
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_STATE);
return 0;
}
if (st == NULL
|| st->module_checksum_data == NULL) {
ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_CONFIG_DATA);
goto end;
}
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 (module_checksum == NULL) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_CONFIG_DATA);
goto end;
}
bio_module = (*st->bio_new_file_cb)(st->module_filename, "rb");
/* Always check the integrity of the fips module */
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)) {
ERR_raise(ERR_LIB_PROV, PROV_R_MODULE_INTEGRITY_FAILURE);
goto end;
}
if (!SELF_TEST_kats(ev, st->libctx)) {
ERR_raise(ERR_LIB_PROV, PROV_R_SELF_TEST_KAT_FAILURE);
goto end;
}
/* Verify that the RNG has been restored properly */
rng = ossl_rand_get0_private_noncreating(st->libctx);
if (rng != NULL)
if ((testrand = EVP_RAND_fetch(st->libctx, "TEST-RAND", NULL)) == NULL
|| strcmp(EVP_RAND_get0_name(EVP_RAND_CTX_get0_rand(rng)),
EVP_RAND_get0_name(testrand)) == 0) {
ERR_raise(ERR_LIB_PROV, PROV_R_SELF_TEST_KAT_FAILURE);
goto end;
}
ok = 1;
end:
EVP_RAND_free(testrand);
OSSL_SELF_TEST_free(ev);
OPENSSL_free(module_checksum);
if (st != NULL)
(*st->bio_free_cb)(bio_module);
if (ok)
set_fips_state(FIPS_STATE_RUNNING);
else
ossl_set_error_state(OSSL_SELF_TEST_TYPE_NONE);
CRYPTO_THREAD_unlock(self_test_lock);
return ok;
#else
set_fips_state(FIPS_STATE_RUNNING);
CRYPTO_THREAD_unlock(self_test_lock);
return 1;
#endif /* !defined(OPENSSL_NO_FIPS_POST) */
}
void SELF_TEST_disable_conditional_error_state(void)
{
FIPS_conditional_error_check = 0;
}
void ossl_set_error_state(const char *type)
{
int cond_test = (type != NULL && strcmp(type, OSSL_SELF_TEST_TYPE_PCT) == 0);
if (!cond_test || (FIPS_conditional_error_check == 1)) {
set_fips_state(FIPS_STATE_ERROR);
ERR_raise(ERR_LIB_PROV, PROV_R_FIPS_MODULE_ENTERING_ERROR_STATE);
} else {
ERR_raise(ERR_LIB_PROV, PROV_R_FIPS_MODULE_CONDITIONAL_ERROR);
}
}
int ossl_prov_is_running(void)
{
int res, loclstate;
static TSAN_QUALIFIER unsigned int rate_limit = 0;
loclstate = tsan_load(&FIPS_state);
res = loclstate == FIPS_STATE_RUNNING || loclstate == FIPS_STATE_SELFTEST;
if (loclstate == FIPS_STATE_ERROR)
if (tsan_counter(&rate_limit) < FIPS_ERROR_REPORTING_RATE_LIMIT)
ERR_raise(ERR_LIB_PROV, PROV_R_FIPS_MODULE_IN_ERROR_STATE);
return res;
}

View File

@@ -0,0 +1,36 @@
/*
* Copyright 2019-2024 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <openssl/core_dispatch.h>
#include <openssl/types.h>
#include <openssl/self_test.h>
typedef struct self_test_post_params_st {
/* FIPS module integrity check parameters */
const char *module_filename; /* Module file to perform MAC on */
const char *module_checksum_data; /* Expected module MAC integrity */
/* Used for continuous tests */
const char *conditional_error_check;
/* BIO callbacks supplied to the FIPS provider */
OSSL_FUNC_BIO_new_file_fn *bio_new_file_cb;
OSSL_FUNC_BIO_new_membuf_fn *bio_new_buffer_cb;
OSSL_FUNC_BIO_read_ex_fn *bio_read_ex_cb;
OSSL_FUNC_BIO_free_fn *bio_free_cb;
OSSL_CALLBACK *cb;
void *cb_arg;
OSSL_LIB_CTX *libctx;
} SELF_TEST_POST_PARAMS;
int SELF_TEST_post(SELF_TEST_POST_PARAMS *st, int on_demand_test);
int SELF_TEST_kats(OSSL_SELF_TEST *event, OSSL_LIB_CTX *libctx);
void SELF_TEST_disable_conditional_error_state(void);

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,912 @@
/*
* Copyright 2019-2024 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <string.h>
#include <openssl/evp.h>
#include <openssl/kdf.h>
#include <openssl/core_names.h>
#include <openssl/param_build.h>
#include <openssl/rand.h>
#include "crypto/rand.h"
#include "internal/cryptlib.h"
#include "internal/nelem.h"
#include "self_test.h"
#include "self_test_data.inc"
static int set_kat_drbg(OSSL_LIB_CTX *ctx,
const unsigned char *entropy, size_t entropy_len,
const unsigned char *nonce, size_t nonce_len,
const unsigned char *persstr, size_t persstr_len);
static int reset_main_drbg(OSSL_LIB_CTX *ctx);
static int self_test_digest(const ST_KAT_DIGEST *t, OSSL_SELF_TEST *st,
OSSL_LIB_CTX *libctx)
{
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);
OSSL_SELF_TEST_onbegin(st, OSSL_SELF_TEST_TYPE_KAT_DIGEST, t->desc);
if (ctx == NULL
|| md == NULL
|| !EVP_DigestInit_ex(ctx, md, NULL)
|| !EVP_DigestUpdate(ctx, t->pt, t->pt_len)
|| !EVP_DigestFinal(ctx, out, &out_len))
goto err;
/* Optional corruption */
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:
EVP_MD_free(md);
EVP_MD_CTX_free(ctx);
OSSL_SELF_TEST_onend(st, ok);
return ok;
}
/*
* Helper function to setup a EVP_CipherInit
* Used to hide the complexity of Authenticated ciphers.
*/
static int cipher_init(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
const ST_KAT_CIPHER *t, int enc)
{
unsigned char *in_tag = NULL;
int pad = 0, tmp;
/* Flag required for Key wrapping */
EVP_CIPHER_CTX_set_flags(ctx, EVP_CIPHER_CTX_FLAG_WRAP_ALLOW);
if (t->tag == NULL) {
/* Use a normal cipher init */
return EVP_CipherInit_ex(ctx, cipher, NULL, t->key, t->iv, enc)
&& EVP_CIPHER_CTX_set_padding(ctx, pad);
}
/* The authenticated cipher init */
if (!enc)
in_tag = (unsigned char *)t->tag;
return EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, enc)
&& (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, t->iv_len, NULL) > 0)
&& (in_tag == NULL
|| EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, t->tag_len,
in_tag) > 0)
&& EVP_CipherInit_ex(ctx, NULL, NULL, t->key, t->iv, enc)
&& EVP_CIPHER_CTX_set_padding(ctx, pad)
&& EVP_CipherUpdate(ctx, NULL, &tmp, t->aad, t->aad_len);
}
/* Test a single KAT for encrypt/decrypt */
static int self_test_cipher(const ST_KAT_CIPHER *t, OSSL_SELF_TEST *st,
OSSL_LIB_CTX *libctx)
{
int ret = 0, encrypt = 1, len = 0, ct_len = 0, pt_len = 0;
EVP_CIPHER_CTX *ctx = NULL;
EVP_CIPHER *cipher = NULL;
unsigned char ct_buf[256] = { 0 };
unsigned char pt_buf[256] = { 0 };
OSSL_SELF_TEST_onbegin(st, OSSL_SELF_TEST_TYPE_KAT_CIPHER, t->base.desc);
ctx = EVP_CIPHER_CTX_new();
if (ctx == NULL)
goto err;
cipher = EVP_CIPHER_fetch(libctx, t->base.algorithm, NULL);
if (cipher == NULL)
goto err;
/* Encrypt plain text message */
if ((t->mode & CIPHER_MODE_ENCRYPT) != 0) {
if (!cipher_init(ctx, cipher, t, encrypt)
|| !EVP_CipherUpdate(ctx, ct_buf, &len, t->base.pt,
t->base.pt_len)
|| !EVP_CipherFinal_ex(ctx, ct_buf + len, &ct_len))
goto err;
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)
goto err;
if (t->tag != NULL) {
unsigned char tag[16] = { 0 };
if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, t->tag_len,
tag) <= 0
|| memcmp(tag, t->tag, t->tag_len) != 0)
goto err;
}
}
/* Decrypt cipher text */
if ((t->mode & CIPHER_MODE_DECRYPT) != 0) {
if (!(cipher_init(ctx, cipher, t, !encrypt)
&& EVP_CipherUpdate(ctx, pt_buf, &len,
t->base.expected, t->base.expected_len)
&& EVP_CipherFinal_ex(ctx, pt_buf + len, &pt_len)))
goto err;
OSSL_SELF_TEST_oncorrupt_byte(st, pt_buf);
pt_len += len;
if (pt_len != (int)t->base.pt_len
|| memcmp(pt_buf, t->base.pt, pt_len) != 0)
goto err;
}
ret = 1;
err:
EVP_CIPHER_free(cipher);
EVP_CIPHER_CTX_free(ctx);
OSSL_SELF_TEST_onend(st, ret);
return ret;
}
static int add_params(OSSL_PARAM_BLD *bld, const ST_KAT_PARAM *params,
BN_CTX *ctx)
{
int ret = 0;
const ST_KAT_PARAM *p;
if (params == NULL)
return 1;
for (p = params; p->data != NULL; ++p) {
switch (p->type) {
case OSSL_PARAM_UNSIGNED_INTEGER: {
BIGNUM *bn = BN_CTX_get(ctx);
if (bn == NULL
|| (BN_bin2bn(p->data, p->data_len, bn) == NULL)
|| !OSSL_PARAM_BLD_push_BN(bld, p->name, bn))
goto err;
break;
}
case OSSL_PARAM_UTF8_STRING: {
if (!OSSL_PARAM_BLD_push_utf8_string(bld, p->name, p->data,
p->data_len))
goto err;
break;
}
case OSSL_PARAM_OCTET_STRING: {
if (!OSSL_PARAM_BLD_push_octet_string(bld, p->name, p->data,
p->data_len))
goto err;
break;
}
case OSSL_PARAM_INTEGER: {
if (!OSSL_PARAM_BLD_push_int(bld, p->name, *(int *)p->data))
goto err;
break;
}
default:
break;
}
}
ret = 1;
err:
return ret;
}
static int self_test_kdf(const ST_KAT_KDF *t, OSSL_SELF_TEST *st,
OSSL_LIB_CTX *libctx)
{
int ret = 0;
unsigned char out[128];
EVP_KDF *kdf = NULL;
EVP_KDF_CTX *ctx = NULL;
BN_CTX *bnctx = NULL;
OSSL_PARAM *params = NULL;
OSSL_PARAM_BLD *bld = NULL;
OSSL_SELF_TEST_onbegin(st, OSSL_SELF_TEST_TYPE_KAT_KDF, t->desc);
bld = OSSL_PARAM_BLD_new();
if (bld == NULL)
goto err;
kdf = EVP_KDF_fetch(libctx, t->algorithm, "");
if (kdf == NULL)
goto err;
ctx = EVP_KDF_CTX_new(kdf);
if (ctx == NULL)
goto err;
bnctx = BN_CTX_new_ex(libctx);
if (bnctx == NULL)
goto err;
if (!add_params(bld, t->params, bnctx))
goto err;
params = OSSL_PARAM_BLD_to_param(bld);
if (params == NULL)
goto err;
if (t->expected_len > sizeof(out))
goto err;
if (EVP_KDF_derive(ctx, out, t->expected_len, params) <= 0)
goto err;
OSSL_SELF_TEST_oncorrupt_byte(st, out);
if (memcmp(out, t->expected, t->expected_len) != 0)
goto err;
ret = 1;
err:
EVP_KDF_free(kdf);
EVP_KDF_CTX_free(ctx);
BN_CTX_free(bnctx);
OSSL_PARAM_free(params);
OSSL_PARAM_BLD_free(bld);
OSSL_SELF_TEST_onend(st, ret);
return ret;
}
static int self_test_drbg(const ST_KAT_DRBG *t, OSSL_SELF_TEST *st,
OSSL_LIB_CTX *libctx)
{
int ret = 0;
unsigned char out[256];
EVP_RAND *rand;
EVP_RAND_CTX *test = NULL, *drbg = NULL;
unsigned int strength = 256;
int prediction_resistance = 1; /* Causes a reseed */
OSSL_PARAM drbg_params[3] = {
OSSL_PARAM_END, OSSL_PARAM_END, OSSL_PARAM_END
};
OSSL_SELF_TEST_onbegin(st, OSSL_SELF_TEST_TYPE_DRBG, t->desc);
rand = EVP_RAND_fetch(libctx, "TEST-RAND", NULL);
if (rand == NULL)
goto err;
test = EVP_RAND_CTX_new(rand, NULL);
EVP_RAND_free(rand);
if (test == NULL)
goto err;
drbg_params[0] = OSSL_PARAM_construct_uint(OSSL_RAND_PARAM_STRENGTH,
&strength);
if (!EVP_RAND_CTX_set_params(test, drbg_params))
goto err;
rand = EVP_RAND_fetch(libctx, t->algorithm, NULL);
if (rand == NULL)
goto err;
drbg = EVP_RAND_CTX_new(rand, test);
EVP_RAND_free(rand);
if (drbg == NULL)
goto err;
strength = EVP_RAND_get_strength(drbg);
drbg_params[0] = OSSL_PARAM_construct_utf8_string(t->param_name,
t->param_value, 0);
/* This is only used by HMAC-DRBG but it is ignored by the others */
drbg_params[1] =
OSSL_PARAM_construct_utf8_string(OSSL_DRBG_PARAM_MAC, "HMAC", 0);
if (!EVP_RAND_CTX_set_params(drbg, drbg_params))
goto err;
drbg_params[0] =
OSSL_PARAM_construct_octet_string(OSSL_RAND_PARAM_TEST_ENTROPY,
(void *)t->entropyin,
t->entropyinlen);
drbg_params[1] =
OSSL_PARAM_construct_octet_string(OSSL_RAND_PARAM_TEST_NONCE,
(void *)t->nonce, t->noncelen);
if (!EVP_RAND_instantiate(test, strength, 0, NULL, 0, drbg_params))
goto err;
if (!EVP_RAND_instantiate(drbg, strength, 0, t->persstr, t->persstrlen,
NULL))
goto err;
drbg_params[0] =
OSSL_PARAM_construct_octet_string(OSSL_RAND_PARAM_TEST_ENTROPY,
(void *)t->entropyinpr1,
t->entropyinpr1len);
if (!EVP_RAND_CTX_set_params(test, drbg_params))
goto err;
if (!EVP_RAND_generate(drbg, out, t->expectedlen, strength,
prediction_resistance,
t->entropyaddin1, t->entropyaddin1len))
goto err;
drbg_params[0] =
OSSL_PARAM_construct_octet_string(OSSL_RAND_PARAM_TEST_ENTROPY,
(void *)t->entropyinpr2,
t->entropyinpr2len);
if (!EVP_RAND_CTX_set_params(test, drbg_params))
goto err;
/*
* This calls ossl_prov_drbg_reseed() internally when
* prediction_resistance = 1
*/
if (!EVP_RAND_generate(drbg, out, t->expectedlen, strength,
prediction_resistance,
t->entropyaddin2, t->entropyaddin2len))
goto err;
OSSL_SELF_TEST_oncorrupt_byte(st, out);
if (memcmp(out, t->expected, t->expectedlen) != 0)
goto err;
if (!EVP_RAND_uninstantiate(drbg))
goto err;
/*
* Check that the DRBG data has been zeroized after
* ossl_prov_drbg_uninstantiate.
*/
if (!EVP_RAND_verify_zeroization(drbg))
goto err;
ret = 1;
err:
EVP_RAND_CTX_free(drbg);
EVP_RAND_CTX_free(test);
OSSL_SELF_TEST_onend(st, ret);
return ret;
}
#if !defined(OPENSSL_NO_DH) || !defined(OPENSSL_NO_EC)
static int self_test_ka(const ST_KAT_KAS *t,
OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx)
{
int ret = 0;
EVP_PKEY_CTX *kactx = NULL, *dctx = NULL;
EVP_PKEY *pkey = NULL, *peerkey = NULL;
OSSL_PARAM *params = NULL;
OSSL_PARAM *params_peer = NULL;
unsigned char secret[256];
size_t secret_len = t->expected_len;
OSSL_PARAM_BLD *bld = NULL;
BN_CTX *bnctx = NULL;
OSSL_SELF_TEST_onbegin(st, OSSL_SELF_TEST_TYPE_KAT_KA, t->desc);
if (secret_len > sizeof(secret))
goto err;
bnctx = BN_CTX_new_ex(libctx);
if (bnctx == NULL)
goto err;
bld = OSSL_PARAM_BLD_new();
if (bld == NULL)
goto err;
if (!add_params(bld, t->key_group, bnctx)
|| !add_params(bld, t->key_host_data, bnctx))
goto err;
params = OSSL_PARAM_BLD_to_param(bld);
if (!add_params(bld, t->key_group, bnctx)
|| !add_params(bld, t->key_peer_data, bnctx))
goto err;
params_peer = OSSL_PARAM_BLD_to_param(bld);
if (params == NULL || params_peer == NULL)
goto err;
/* Create a EVP_PKEY_CTX to load the DH keys into */
kactx = EVP_PKEY_CTX_new_from_name(libctx, t->algorithm, "");
if (kactx == NULL)
goto err;
if (EVP_PKEY_fromdata_init(kactx) <= 0
|| EVP_PKEY_fromdata(kactx, &pkey, EVP_PKEY_KEYPAIR, params) <= 0)
goto err;
if (EVP_PKEY_fromdata_init(kactx) <= 0
|| EVP_PKEY_fromdata(kactx, &peerkey, EVP_PKEY_KEYPAIR, params_peer) <= 0)
goto err;
/* Create a EVP_PKEY_CTX to perform key derivation */
dctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey, NULL);
if (dctx == NULL)
goto err;
if (EVP_PKEY_derive_init(dctx) <= 0
|| EVP_PKEY_derive_set_peer(dctx, peerkey) <= 0
|| EVP_PKEY_derive(dctx, secret, &secret_len) <= 0)
goto err;
OSSL_SELF_TEST_oncorrupt_byte(st, secret);
if (secret_len != t->expected_len
|| memcmp(secret, t->expected, t->expected_len) != 0)
goto err;
ret = 1;
err:
BN_CTX_free(bnctx);
EVP_PKEY_free(pkey);
EVP_PKEY_free(peerkey);
EVP_PKEY_CTX_free(kactx);
EVP_PKEY_CTX_free(dctx);
OSSL_PARAM_free(params_peer);
OSSL_PARAM_free(params);
OSSL_PARAM_BLD_free(bld);
OSSL_SELF_TEST_onend(st, ret);
return ret;
}
#endif /* !defined(OPENSSL_NO_DH) || !defined(OPENSSL_NO_EC) */
static int self_test_digest_sign(const ST_KAT_SIGN *t,
OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx)
{
int ret = 0;
OSSL_PARAM *paramskey = NULL, *paramsinit = NULL;
OSSL_PARAM_BLD *bldkey = NULL, *bldinit = NULL;
EVP_MD_CTX *mctx = NULL;
EVP_PKEY_CTX *fromctx = NULL;
EVP_PKEY *pkey = NULL;
unsigned char sig[256];
BN_CTX *bnctx = NULL;
size_t siglen = sizeof(sig);
int oneshot = 0;
const char *typ = OSSL_SELF_TEST_TYPE_KAT_SIGNATURE;
if (t->sig_expected == NULL)
typ = OSSL_SELF_TEST_TYPE_PCT_SIGNATURE;
OSSL_SELF_TEST_onbegin(st, typ, t->desc);
if (t->entropy != NULL) {
if (!set_kat_drbg(libctx, t->entropy, t->entropy_len,
t->nonce, t->nonce_len, t->persstr, t->persstr_len))
goto err;
}
bnctx = BN_CTX_new_ex(libctx);
if (bnctx == NULL)
goto err;
bldkey = OSSL_PARAM_BLD_new();
bldinit = OSSL_PARAM_BLD_new();
if (bldkey == NULL || bldinit == NULL)
goto err;
if (!add_params(bldkey, t->key, bnctx))
goto err;
if (!add_params(bldinit, t->init, bnctx))
goto err;
paramskey = OSSL_PARAM_BLD_to_param(bldkey);
paramsinit = OSSL_PARAM_BLD_to_param(bldinit);
fromctx = EVP_PKEY_CTX_new_from_name(libctx, t->algorithm, "");
if (fromctx == NULL
|| paramskey == NULL
|| paramsinit == NULL)
goto err;
if (EVP_PKEY_fromdata_init(fromctx) <= 0
|| EVP_PKEY_fromdata(fromctx, &pkey, EVP_PKEY_KEYPAIR, paramskey) <= 0)
goto err;
mctx = EVP_MD_CTX_new();
if (mctx == NULL)
goto err;
oneshot = ((t->mode & SIGNATURE_MODE_ONESHOT) != 0);
if ((t->mode & SIGNATURE_MODE_VERIFY_ONLY) != 0) {
memcpy(sig, t->sig_expected, t->sig_expected_len);
siglen = t->sig_expected_len;
} else {
if (EVP_DigestSignInit_ex(mctx, NULL, t->mdalgorithm, libctx, NULL,
pkey, paramsinit) <= 0)
goto err;
if (oneshot) {
if (EVP_DigestSign(mctx, sig, &siglen, t->msg, t->msg_len) <= 0)
goto err;
} else {
if (EVP_DigestSignUpdate(mctx, t->msg, t->msg_len) <= 0
|| EVP_DigestSignFinal(mctx, sig, &siglen) <= 0)
goto err;
}
if (t->sig_expected != NULL
&& (siglen != t->sig_expected_len
|| memcmp(sig, t->sig_expected, t->sig_expected_len) != 0))
goto err;
}
if ((t->mode & SIGNATURE_MODE_SIGN_ONLY) == 0) {
if (EVP_DigestVerifyInit_ex(mctx, NULL, t->mdalgorithm, libctx, NULL,
pkey, paramsinit) <= 0)
goto err;
OSSL_SELF_TEST_oncorrupt_byte(st, sig);
if (oneshot) {
if (EVP_DigestVerify(mctx, sig, siglen, t->msg, t->msg_len) <= 0)
goto err;
} else {
if (EVP_DigestVerifyUpdate(mctx, t->msg, t->msg_len) <= 0
|| EVP_DigestVerifyFinal(mctx, sig, siglen) <= 0)
goto err;
}
}
ret = 1;
err:
BN_CTX_free(bnctx);
EVP_PKEY_free(pkey);
EVP_PKEY_CTX_free(fromctx);
EVP_MD_CTX_free(mctx);
OSSL_PARAM_free(paramskey);
OSSL_PARAM_free(paramsinit);
OSSL_PARAM_BLD_free(bldkey);
OSSL_PARAM_BLD_free(bldinit);
if (t->entropy != NULL) {
if (!reset_main_drbg(libctx))
ret = 0;
}
OSSL_SELF_TEST_onend(st, ret);
return ret;
}
/*
* Test an encrypt or decrypt KAT..
*
* FIPS 140-2 IG D.9 states that separate KAT tests are needed for encrypt
* and decrypt..
*/
static int self_test_asym_cipher(const ST_KAT_ASYM_CIPHER *t, OSSL_SELF_TEST *st,
OSSL_LIB_CTX *libctx)
{
int ret = 0;
OSSL_PARAM *keyparams = NULL, *initparams = NULL;
OSSL_PARAM_BLD *keybld = NULL, *initbld = NULL;
EVP_PKEY_CTX *encctx = NULL, *keyctx = NULL;
EVP_PKEY *key = NULL;
BN_CTX *bnctx = NULL;
unsigned char out[256];
size_t outlen = sizeof(out);
OSSL_SELF_TEST_onbegin(st, OSSL_SELF_TEST_TYPE_KAT_ASYM_CIPHER, t->desc);
bnctx = BN_CTX_new_ex(libctx);
if (bnctx == NULL)
goto err;
/* Load a public or private key from data */
keybld = OSSL_PARAM_BLD_new();
if (keybld == NULL
|| !add_params(keybld, t->key, bnctx))
goto err;
keyparams = OSSL_PARAM_BLD_to_param(keybld);
keyctx = EVP_PKEY_CTX_new_from_name(libctx, t->algorithm, NULL);
if (keyctx == NULL || keyparams == NULL)
goto err;
if (EVP_PKEY_fromdata_init(keyctx) <= 0
|| EVP_PKEY_fromdata(keyctx, &key, EVP_PKEY_KEYPAIR, keyparams) <= 0)
goto err;
/* Create a EVP_PKEY_CTX to use for the encrypt or decrypt operation */
encctx = EVP_PKEY_CTX_new_from_pkey(libctx, key, NULL);
if (encctx == NULL
|| (t->encrypt && EVP_PKEY_encrypt_init(encctx) <= 0)
|| (!t->encrypt && EVP_PKEY_decrypt_init(encctx) <= 0))
goto err;
/* Add any additional parameters such as padding */
if (t->postinit != NULL) {
initbld = OSSL_PARAM_BLD_new();
if (initbld == NULL)
goto err;
if (!add_params(initbld, t->postinit, bnctx))
goto err;
initparams = OSSL_PARAM_BLD_to_param(initbld);
if (initparams == NULL)
goto err;
if (EVP_PKEY_CTX_set_params(encctx, initparams) <= 0)
goto err;
}
if (t->encrypt) {
if (EVP_PKEY_encrypt(encctx, out, &outlen,
t->in, t->in_len) <= 0)
goto err;
} else {
if (EVP_PKEY_decrypt(encctx, out, &outlen,
t->in, t->in_len) <= 0)
goto err;
}
/* Check the KAT */
OSSL_SELF_TEST_oncorrupt_byte(st, out);
if (outlen != t->expected_len
|| memcmp(out, t->expected, t->expected_len) != 0)
goto err;
ret = 1;
err:
BN_CTX_free(bnctx);
EVP_PKEY_free(key);
EVP_PKEY_CTX_free(encctx);
EVP_PKEY_CTX_free(keyctx);
OSSL_PARAM_free(keyparams);
OSSL_PARAM_BLD_free(keybld);
OSSL_PARAM_free(initparams);
OSSL_PARAM_BLD_free(initbld);
OSSL_SELF_TEST_onend(st, ret);
return ret;
}
/*
* Test a data driven list of KAT's for digest algorithms.
* All tests are run regardless of if they fail or not.
* Return 0 if any test fails.
*/
static int self_test_digests(OSSL_SELF_TEST *st, OSSL_LIB_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], st, libctx))
ret = 0;
}
return ret;
}
static int self_test_ciphers(OSSL_SELF_TEST *st, OSSL_LIB_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], st, libctx))
ret = 0;
}
return ret;
}
static int self_test_asym_ciphers(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx)
{
int i, ret = 1;
for (i = 0; i < (int)OSSL_NELEM(st_kat_asym_cipher_tests); ++i) {
if (!self_test_asym_cipher(&st_kat_asym_cipher_tests[i], st, libctx))
ret = 0;
}
return ret;
}
static int self_test_kdfs(OSSL_SELF_TEST *st, OSSL_LIB_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], st, libctx))
ret = 0;
}
return ret;
}
static int self_test_drbgs(OSSL_SELF_TEST *st, OSSL_LIB_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], st, libctx))
ret = 0;
}
return ret;
}
static int self_test_kas(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx)
{
int ret = 1;
#if !defined(OPENSSL_NO_DH) || !defined(OPENSSL_NO_EC)
int i;
for (i = 0; i < (int)OSSL_NELEM(st_kat_kas_tests); ++i) {
if (!self_test_ka(&st_kat_kas_tests[i], st, libctx))
ret = 0;
}
#endif
return ret;
}
static int self_test_signatures(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx)
{
int i, ret = 1;
for (i = 0; i < (int)OSSL_NELEM(st_kat_sign_tests); ++i) {
if (!self_test_digest_sign(&st_kat_sign_tests[i], st, libctx))
ret = 0;
}
return ret;
}
/*
* Swap the library context DRBG for KAT testing
*
* In FIPS 140-3, the asymmetric POST must be a KAT, not a PCT. For DSA and ECDSA,
* the sign operation includes the random value 'k'. For a KAT to work, we
* have to have control of the DRBG to make sure it is in a "test" state, where
* its output is truly deterministic.
*
*/
/*
* Replacement "random" sources
* main_rand is used for most tests and it's set to generate mode.
* kat_rand is used for KATs where specific input is mandated.
*/
static EVP_RAND_CTX *kat_rand = NULL;
static EVP_RAND_CTX *main_rand = NULL;
static int set_kat_drbg(OSSL_LIB_CTX *ctx,
const unsigned char *entropy, size_t entropy_len,
const unsigned char *nonce, size_t nonce_len,
const unsigned char *persstr, size_t persstr_len) {
EVP_RAND *rand;
unsigned int strength = 256;
EVP_RAND_CTX *parent_rand = NULL;
OSSL_PARAM drbg_params[3] = {
OSSL_PARAM_END, OSSL_PARAM_END, OSSL_PARAM_END
};
/* If not NULL, we didn't cleanup from last call: BAD */
if (kat_rand != NULL)
return 0;
rand = EVP_RAND_fetch(ctx, "TEST-RAND", NULL);
if (rand == NULL)
return 0;
parent_rand = EVP_RAND_CTX_new(rand, NULL);
EVP_RAND_free(rand);
if (parent_rand == NULL)
goto err;
drbg_params[0] = OSSL_PARAM_construct_uint(OSSL_RAND_PARAM_STRENGTH,
&strength);
if (!EVP_RAND_CTX_set_params(parent_rand, drbg_params))
goto err;
rand = EVP_RAND_fetch(ctx, "HASH-DRBG", NULL);
if (rand == NULL)
goto err;
kat_rand = EVP_RAND_CTX_new(rand, parent_rand);
EVP_RAND_free(rand);
if (kat_rand == NULL)
goto err;
drbg_params[0] = OSSL_PARAM_construct_utf8_string("digest", "SHA256", 0);
if (!EVP_RAND_CTX_set_params(kat_rand, drbg_params))
goto err;
/* Instantiate the RNGs */
drbg_params[0] =
OSSL_PARAM_construct_octet_string(OSSL_RAND_PARAM_TEST_ENTROPY,
(void *)entropy, entropy_len);
drbg_params[1] =
OSSL_PARAM_construct_octet_string(OSSL_RAND_PARAM_TEST_NONCE,
(void *)nonce, nonce_len);
if (!EVP_RAND_instantiate(parent_rand, strength, 0, NULL, 0, drbg_params))
goto err;
EVP_RAND_CTX_free(parent_rand);
parent_rand = NULL;
if (!EVP_RAND_instantiate(kat_rand, strength, 0, persstr, persstr_len, NULL))
goto err;
/* When we set the new private generator this one is freed, so upref it */
if (!EVP_RAND_CTX_up_ref(main_rand))
goto err;
/* Update the library context DRBG */
if (RAND_set0_private(ctx, kat_rand) > 0) {
/* Keeping a copy to verify zeroization */
if (EVP_RAND_CTX_up_ref(kat_rand))
return 1;
RAND_set0_private(ctx, main_rand);
}
err:
EVP_RAND_CTX_free(parent_rand);
EVP_RAND_CTX_free(kat_rand);
kat_rand = NULL;
return 0;
}
static int reset_main_drbg(OSSL_LIB_CTX *ctx) {
int ret = 1;
if (!RAND_set0_private(ctx, main_rand))
ret = 0;
if (kat_rand != NULL) {
if (!EVP_RAND_uninstantiate(kat_rand)
|| !EVP_RAND_verify_zeroization(kat_rand))
ret = 0;
EVP_RAND_CTX_free(kat_rand);
kat_rand = NULL;
}
return ret;
}
static int setup_main_random(OSSL_LIB_CTX *libctx)
{
OSSL_PARAM drbg_params[3] = {
OSSL_PARAM_END, OSSL_PARAM_END, OSSL_PARAM_END
};
unsigned int strength = 256, generate = 1;
EVP_RAND *rand;
rand = EVP_RAND_fetch(libctx, "TEST-RAND", NULL);
if (rand == NULL)
return 0;
main_rand = EVP_RAND_CTX_new(rand, NULL);
EVP_RAND_free(rand);
if (main_rand == NULL)
goto err;
drbg_params[0] = OSSL_PARAM_construct_uint(OSSL_RAND_PARAM_GENERATE,
&generate);
drbg_params[1] = OSSL_PARAM_construct_uint(OSSL_RAND_PARAM_STRENGTH,
&strength);
if (!EVP_RAND_instantiate(main_rand, strength, 0, NULL, 0, drbg_params))
goto err;
return 1;
err:
EVP_RAND_CTX_free(main_rand);
return 0;
}
/*
* Run the algorithm KAT's.
* Return 1 is successful, otherwise return 0.
* This runs all the tests regardless of if any fail.
*/
int SELF_TEST_kats(OSSL_SELF_TEST *st, OSSL_LIB_CTX *libctx)
{
EVP_RAND_CTX *saved_rand = ossl_rand_get0_private_noncreating(libctx);
int ret = 1;
if (saved_rand != NULL && !EVP_RAND_CTX_up_ref(saved_rand))
return 0;
if (!setup_main_random(libctx)
|| !RAND_set0_private(libctx, main_rand)) {
/* Decrement saved_rand reference counter */
EVP_RAND_CTX_free(saved_rand);
EVP_RAND_CTX_free(main_rand);
return 0;
}
if (!self_test_digests(st, libctx))
ret = 0;
if (!self_test_ciphers(st, libctx))
ret = 0;
if (!self_test_signatures(st, libctx))
ret = 0;
if (!self_test_kdfs(st, libctx))
ret = 0;
if (!self_test_drbgs(st, libctx))
ret = 0;
if (!self_test_kas(st, libctx))
ret = 0;
if (!self_test_asym_ciphers(st, libctx))
ret = 0;
RAND_set0_private(libctx, saved_rand);
return ret;
}