Latest update.

This commit is contained in:
2020-01-17 19:45:12 +09:00
parent 016df9f433
commit 0f7abb4eb6
1100 changed files with 47785 additions and 16292 deletions
+2 -3
View File
@@ -1,3 +1,2 @@
SOURCE[../fips]=fipsprov.c selftest.c
INCLUDE[../fips]=../implementations/include ../common/include
SOURCE[../fips]=fipsprov.c self_test.c self_test_kats.c self_test_event.c
INCLUDE[../fips]=../implementations/include ../common/include ../..
+261 -56
View File
@@ -25,11 +25,16 @@
#include "internal/cryptlib.h"
#include "internal/property.h"
#include "internal/nelem.h"
#include "crypto/evp.h"
#include "prov/implementations.h"
#include "prov/provider_ctx.h"
#include "prov/providercommon.h"
#include "selftest.h"
#include "prov/provider_util.h"
#include "self_test.h"
#define ALGC(NAMES, FUNC, CHECK) { { NAMES, "fips=yes", FUNC }, CHECK }
#define ALG(NAMES, FUNC) ALGC(NAMES, FUNC, NULL)
extern OSSL_core_thread_start_fn *c_thread_start;
@@ -116,6 +121,49 @@ static OSSL_PARAM core_params[] =
OSSL_PARAM_END
};
/*
* This routine is currently necessary as bn params are currently processed
* using BN_native2bn when raw data is received. This means we need to do
* magic to reverse the order of the bytes to match native format.
* The array of hexdata is to get around compilers that dont like
* strings longer than 509 bytes,
*/
static int rawnative_fromhex(const char *hex_data[],
unsigned char **native, size_t *nativelen)
{
int ret = 0;
unsigned char *data = NULL;
BIGNUM *bn = NULL;
int i, slen, datalen, sz;
char *str = NULL;
for (slen = 0, i = 0; hex_data[i] != NULL; ++i)
slen += strlen(hex_data[i]);
str = OPENSSL_zalloc(slen + 1);
if (str == NULL)
return 0;
for (i = 0; hex_data[i] != NULL; ++i)
strcat(str, hex_data[i]);
if (BN_hex2bn(&bn, str) <= 0)
return 0;
datalen = slen / 2;
data = (unsigned char *)str; /* reuse the str buffer */
sz = BN_bn2nativepad(bn, data, datalen);
if (sz <= 0)
goto err;
ret = 1;
*native = data;
*nativelen = datalen;
data = NULL; /* so it does not get freed */
err:
BN_free(bn);
OPENSSL_free(data);
return ret;
}
/* TODO(3.0): To be removed */
static int dummy_evp_call(void *provctx)
{
@@ -123,6 +171,58 @@ static int dummy_evp_call(void *provctx)
EVP_MD_CTX *ctx = EVP_MD_CTX_new();
EVP_MD *sha256 = EVP_MD_fetch(libctx, "SHA256", NULL);
EVP_KDF *kdf = EVP_KDF_fetch(libctx, OSSL_KDF_NAME_PBKDF2, NULL);
EVP_PKEY_CTX *sctx = NULL, *kctx = NULL;
EVP_PKEY *pkey = NULL;
OSSL_PARAM *p;
OSSL_PARAM params[16];
unsigned char sig[64];
size_t siglen, sigdgstlen;
unsigned char *dsa_p = NULL, *dsa_q = NULL, *dsa_g = NULL;
unsigned char *dsa_pub = NULL, *dsa_priv = NULL;
size_t dsa_p_len, dsa_q_len, dsa_g_len, dsa_pub_len, dsa_priv_len;
/* dsa 2048 */
static const char *dsa_p_hex[] = {
"a29b8872ce8b8423b7d5d21d4b02f57e03e9e6b8a258dc16611ba098ab543415"
"e415f156997a3ee236658fa093260de3ad422e05e046f9ec29161a375f0eb4ef"
"fcef58285c5d39ed425d7a62ca12896c4a92cb1946f2952a48133f07da364d1b"
"df6b0f7139983e693c80059b0eacd1479ba9f2857754ede75f112b07ebbf3534",
"8bbf3e01e02f2d473de39453f99dd2367541caca3ba01166343d7b5b58a37bd1"
"b7521db2f13b86707132fe09f4cd09dc1618fa3401ebf9cc7b19fa94aa472088"
"133d6cb2d35c1179c8c8ff368758d507d9f9a17d46c110fe3144ce9b022b42e4"
"19eb4f5388613bfc3e26241a432e8706bc58ef76117278deab6cf692618291b7",
NULL
};
static const char *dsa_q_hex[] = {
"a3bfd9ab7884794e383450d5891dc18b65157bdcfcdac51518902867",
NULL
};
static const char *dsa_g_hex[] = {
"6819278869c7fd3d2d7b77f77e8150d9ad433bea3ba85efc80415aa3545f78f7"
"2296f06cb19ceda06c94b0551cfe6e6f863e31d1de6eed7dab8b0c9df231e084"
"34d1184f91d033696bb382f8455e9888f5d31d4784ec40120246f4bea61794bb"
"a5866f09746463bdf8e9e108cd9529c3d0f6df80316e2e70aaeb1b26cdb8ad97",
"bc3d287e0b8d616c42e65b87db20deb7005bc416747a6470147a68a7820388eb"
"f44d52e0628af9cf1b7166d03465f35acc31b6110c43dabc7c5d591e671eaf7c"
"252c1c145336a1a4ddf13244d55e835680cab2533b82df2efe55ec18c1e6cd00"
"7bb089758bb17c2cbe14441bd093ae66e5976d53733f4fa3269701d31d23d467",
NULL
};
static const char *dsa_pub_hex[] = {
"a012b3b170b307227957b7ca2061a816ac7a2b3d9ae995a5119c385b603bf6f6"
"c5de4dc5ecb5dfa4a41c68662eb25b638b7e2620ba898d07da6c4991e76cc0ec"
"d1ad3421077067e47c18f58a92a72ad43199ecb7bd84e7d3afb9019f0e9dd0fb"
"aa487300b13081e33c902876436f7b03c345528481d362815e24fe59dac5ac34",
"660d4c8a76cb99a7c7de93eb956cd6bc88e58d901034944a094b01803a43c672"
"b9688c0e01d8f4fc91c62a3f88021f7bd6a651b1a88f43aa4ef27653d12bf8b7"
"099fdf6b461082f8e939107bfd2f7210087d326c375200f1f51e7e74a3413190"
"1bcd0863521ff8d676c48581868736c5e51b16a4e39215ea0b17c4735974c516",
NULL
};
static const char *dsa_priv_hex[] = {
"6ccaeef6d73b4e80f11c17b8e9627c036635bac39423505e407e5cb7",
NULL
};
char msg[] = "Hello World!";
const unsigned char exptd[] = {
0x7f, 0x83, 0xb1, 0x65, 0x7f, 0xf1, 0xfc, 0x53, 0xb9, 0x2d, 0xc1, 0x81,
@@ -181,7 +281,54 @@ static int dummy_evp_call(void *provctx)
if (!EC_KEY_generate_key(key))
goto err;
#endif
if (!rawnative_fromhex(dsa_p_hex, &dsa_p, &dsa_p_len)
|| !rawnative_fromhex(dsa_q_hex, &dsa_q, &dsa_q_len)
|| !rawnative_fromhex(dsa_g_hex, &dsa_g, &dsa_g_len)
|| !rawnative_fromhex(dsa_pub_hex, &dsa_pub, &dsa_pub_len)
|| !rawnative_fromhex(dsa_priv_hex, &dsa_priv, &dsa_priv_len))
goto err;
p = params;
*p++ = OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_FFC_P, dsa_p, dsa_p_len);
*p++ = OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_FFC_Q, dsa_q, dsa_q_len);
*p++ = OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_FFC_G, dsa_g, dsa_g_len);
*p++ = OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_DSA_PUB_KEY,
dsa_pub, dsa_pub_len);
*p++ = OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_DSA_PRIV_KEY,
dsa_priv, dsa_priv_len);
*p = OSSL_PARAM_construct_end();
kctx = EVP_PKEY_CTX_new_from_name(libctx, SN_dsa, "");
if (kctx == NULL)
goto err;
if (EVP_PKEY_key_fromdata_init(kctx) <= 0
|| EVP_PKEY_fromdata(kctx, &pkey, params) <= 0)
goto err;
sctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey);
if (sctx == NULL)
goto err;;
if (EVP_PKEY_sign_init(sctx) <= 0)
goto err;
/* set signature parameters */
sigdgstlen = SHA256_DIGEST_LENGTH;
p = params;
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST,
SN_sha256,
strlen(SN_sha256) + 1);
*p++ = OSSL_PARAM_construct_size_t(OSSL_SIGNATURE_PARAM_DIGEST_SIZE,
&sigdgstlen);
*p = OSSL_PARAM_construct_end();
if (EVP_PKEY_CTX_set_params(sctx, params) <= 0)
goto err;
if (EVP_PKEY_sign(sctx, sig, &siglen, dgst, sizeof(dgst)) <= 0
|| EVP_PKEY_verify_init(sctx) <= 0
|| EVP_PKEY_verify(sctx, sig, siglen, dgst, sizeof(dgst)) <= 0)
goto err;
ret = 1;
err:
BN_CTX_end(bnctx);
@@ -194,6 +341,14 @@ static int dummy_evp_call(void *provctx)
#ifndef OPENSSL_NO_EC
EC_KEY_free(key);
#endif
OPENSSL_free(dsa_p);
OPENSSL_free(dsa_q);
OPENSSL_free(dsa_g);
OPENSSL_free(dsa_pub);
OPENSSL_free(dsa_priv);
EVP_PKEY_free(pkey);
EVP_PKEY_CTX_free(kctx);
EVP_PKEY_CTX_free(sctx);
return ret;
}
@@ -300,6 +455,14 @@ const char *ossl_prov_util_nid_to_name(int nid)
return "DES-EDE3";
case NID_des_ede3_cbc:
return "DES-EDE3-CBC";
case NID_aes_256_cbc_hmac_sha256:
return "AES-256-CBC-HMAC-SHA256";
case NID_aes_128_cbc_hmac_sha256:
return "AES-128-CBC-HMAC-SHA256";
case NID_aes_256_cbc_hmac_sha1:
return "AES-256-CBC-HMAC-SHA1";
case NID_aes_128_cbc_hmac_sha1:
return "AES-128-CBC-HMAC-SHA1";
default:
break;
}
@@ -349,52 +512,58 @@ static const OSSL_ALGORITHM fips_digests[] = {
{ "SHA3-384", "fips=yes", sha3_384_functions },
{ "SHA3-512", "fips=yes", sha3_512_functions },
/*
* KECCAK_KMAC128 and KECCAK_KMAC256 as hashes are mostly useful for
* KECCAK-KMAC-128 and KECCAK-KMAC-256 as hashes are mostly useful for
* KMAC128 and KMAC256.
*/
{ "KECCAK_KMAC128", "fips=yes", keccak_kmac_128_functions },
{ "KECCAK_KMAC256", "fips=yes", keccak_kmac_256_functions },
{ "KECCAK-KMAC-128:KECCAK-KMAC128", "fips=yes", keccak_kmac_128_functions },
{ "KECCAK-KMAC-256:KECCAK-KMAC256", "fips=yes", keccak_kmac_256_functions },
{ NULL, NULL, NULL }
};
static const OSSL_ALGORITHM fips_ciphers[] = {
static const OSSL_ALGORITHM_CAPABLE fips_ciphers[] = {
/* Our primary name[:ASN.1 OID name][:our older names] */
{ "AES-256-ECB", "fips=yes", aes256ecb_functions },
{ "AES-192-ECB", "fips=yes", aes192ecb_functions },
{ "AES-128-ECB", "fips=yes", aes128ecb_functions },
{ "AES-256-CBC", "fips=yes", aes256cbc_functions },
{ "AES-192-CBC", "fips=yes", aes192cbc_functions },
{ "AES-128-CBC", "fips=yes", aes128cbc_functions },
{ "AES-256-CTR", "fips=yes", aes256ctr_functions },
{ "AES-192-CTR", "fips=yes", aes192ctr_functions },
{ "AES-128-CTR", "fips=yes", aes128ctr_functions },
{ "AES-256-XTS", "fips=yes", aes256xts_functions },
{ "AES-128-XTS", "fips=yes", aes128xts_functions },
{ "AES-256-GCM:id-aes256-GCM", "fips=yes", aes256gcm_functions },
{ "AES-192-GCM:id-aes192-GCM", "fips=yes", aes192gcm_functions },
{ "AES-128-GCM:id-aes128-GCM", "fips=yes", aes128gcm_functions },
{ "AES-256-CCM:id-aes256-CCM", "fips=yes", aes256ccm_functions },
{ "AES-192-CCM:id-aes192-CCM", "fips=yes", aes192ccm_functions },
{ "AES-128-CCM:id-aes128-CCM", "fips=yes", aes128ccm_functions },
{ "AES-256-WRAP:id-aes256-wrap:AES256-WRAP", "fips=yes",
aes256wrap_functions },
{ "AES-192-WRAP:id-aes192-wrap:AES192-WRAP", "fips=yes",
aes192wrap_functions },
{ "AES-128-WRAP:id-aes128-wrap:AES128-WRAP", "fips=yes",
aes128wrap_functions },
{ "AES-256-WRAP-PAD:id-aes256-wrap-pad:AES256-WRAP-PAD", "fips=yes",
aes256wrappad_functions },
{ "AES-192-WRAP-PAD:id-aes192-wrap-pad:AES192-WRAP-PAD", "fips=yes",
aes192wrappad_functions },
{ "AES-128-WRAP-PAD:id-aes128-wrap-pad:AES128-WRAP-PAD", "fips=yes",
aes128wrappad_functions },
ALG("AES-256-ECB", aes256ecb_functions),
ALG("AES-192-ECB", aes192ecb_functions),
ALG("AES-128-ECB", aes128ecb_functions),
ALG("AES-256-CBC", aes256cbc_functions),
ALG("AES-192-CBC", aes192cbc_functions),
ALG("AES-128-CBC", aes128cbc_functions),
ALG("AES-256-CTR", aes256ctr_functions),
ALG("AES-192-CTR", aes192ctr_functions),
ALG("AES-128-CTR", aes128ctr_functions),
ALG("AES-256-XTS", aes256xts_functions),
ALG("AES-128-XTS", aes128xts_functions),
ALG("AES-256-GCM:id-aes256-GCM", aes256gcm_functions),
ALG("AES-192-GCM:id-aes192-GCM", aes192gcm_functions),
ALG("AES-128-GCM:id-aes128-GCM", aes128gcm_functions),
ALG("AES-256-CCM:id-aes256-CCM", aes256ccm_functions),
ALG("AES-192-CCM:id-aes192-CCM", aes192ccm_functions),
ALG("AES-128-CCM:id-aes128-CCM", aes128ccm_functions),
ALG("AES-256-WRAP:id-aes256-wrap:AES256-WRAP", aes256wrap_functions),
ALG("AES-192-WRAP:id-aes192-wrap:AES192-WRAP", aes192wrap_functions),
ALG("AES-128-WRAP:id-aes128-wrap:AES128-WRAP", aes128wrap_functions),
ALG("AES-256-WRAP-PAD:id-aes256-wrap-pad:AES256-WRAP-PAD",
aes256wrappad_functions),
ALG("AES-192-WRAP-PAD:id-aes192-wrap-pad:AES192-WRAP-PAD",
aes192wrappad_functions),
ALG("AES-128-WRAP-PAD:id-aes128-wrap-pad:AES128-WRAP-PAD",
aes128wrappad_functions),
ALGC("AES-128-CBC-HMAC-SHA1", aes128cbc_hmac_sha1_functions,
cipher_capable_aes_cbc_hmac_sha1),
ALGC("AES-256-CBC-HMAC-SHA1", aes256cbc_hmac_sha1_functions,
cipher_capable_aes_cbc_hmac_sha1),
ALGC("AES-128-CBC-HMAC-SHA256", aes128cbc_hmac_sha256_functions,
cipher_capable_aes_cbc_hmac_sha256),
ALGC("AES-256-CBC-HMAC-SHA256", aes256cbc_hmac_sha256_functions,
cipher_capable_aes_cbc_hmac_sha256),
#ifndef OPENSSL_NO_DES
{ "DES-EDE3-ECB:DES-EDE3", "fips=yes", tdes_ede3_ecb_functions },
{ "DES-EDE3-CBC:DES3", "fips=yes", tdes_ede3_cbc_functions },
ALG("DES-EDE3-ECB:DES-EDE3", tdes_ede3_ecb_functions),
ALG("DES-EDE3-CBC:DES3", tdes_ede3_cbc_functions),
#endif /* OPENSSL_NO_DES */
{ NULL, NULL, NULL }
{ { NULL, NULL, NULL }, NULL }
};
static OSSL_ALGORITHM exported_fips_ciphers[OSSL_NELEM(fips_ciphers)];
static const OSSL_ALGORITHM fips_macs[] = {
#ifndef OPENSSL_NO_CMAC
@@ -402,17 +571,31 @@ static const OSSL_ALGORITHM fips_macs[] = {
#endif
{ "GMAC", "fips=yes", gmac_functions },
{ "HMAC", "fips=yes", hmac_functions },
{ "KMAC128", "fips=yes", kmac128_functions },
{ "KMAC256", "fips=yes", kmac256_functions },
{ "KMAC-128:KMAC128", "fips=yes", kmac128_functions },
{ "KMAC-256:KMAC256", "fips=yes", kmac256_functions },
{ NULL, NULL, NULL }
};
static const OSSL_ALGORITHM fips_kdfs[] = {
{ OSSL_KDF_NAME_HKDF, "fips=yes", kdf_hkdf_functions },
{ OSSL_KDF_NAME_SSKDF, "fips=yes", kdf_sskdf_functions },
{ OSSL_KDF_NAME_PBKDF2, "fips=yes", kdf_pbkdf2_functions },
{ OSSL_KDF_NAME_TLS1_PRF, "fips=yes", kdf_tls1_prf_functions },
{ OSSL_KDF_NAME_KBKDF, "fips=yes", kdf_kbkdf_functions },
{ "HKDF", "fips=yes", kdf_hkdf_functions },
{ "SSKDF", "fips=yes", kdf_sskdf_functions },
{ "PBKDF2", "fips=yes", kdf_pbkdf2_functions },
{ "TLS1-PRF", "fips=yes", kdf_tls1_prf_functions },
{ "KBKDF", "fips=yes", kdf_kbkdf_functions },
{ NULL, NULL, NULL }
};
static const OSSL_ALGORITHM fips_signature[] = {
#ifndef OPENSSL_NO_DSA
{ "DSA:dsaEncryption", "fips=yes", dsa_signature_functions },
#endif
{ NULL, NULL, NULL }
};
static const OSSL_ALGORITHM fips_keymgmt[] = {
#ifndef OPENSSL_NO_DSA
{ "DSA", "fips=yes", dsa_keymgmt_functions },
#endif
{ NULL, NULL, NULL }
};
@@ -425,11 +608,16 @@ static const OSSL_ALGORITHM *fips_query(OSSL_PROVIDER *prov,
case OSSL_OP_DIGEST:
return fips_digests;
case OSSL_OP_CIPHER:
return fips_ciphers;
ossl_prov_cache_exported_algorithms(fips_ciphers, exported_fips_ciphers);
return exported_fips_ciphers;
case OSSL_OP_MAC:
return fips_macs;
case OSSL_OP_KDF:
return fips_kdfs;
case OSSL_OP_KEYMGMT:
return fips_keymgmt;
case OSSL_OP_SIGNATURE:
return fips_signature;
}
return NULL;
}
@@ -461,9 +649,14 @@ int OSSL_provider_init(const OSSL_PROVIDER *provider,
{
FIPS_GLOBAL *fgbl;
OPENSSL_CTX *ctx;
OSSL_self_test_cb_fn *stcbfn = NULL;
OSSL_core_get_library_context_fn *c_get_libctx = NULL;
for (; in->function_id != 0; in++) {
switch (in->function_id) {
case OSSL_FUNC_CORE_GET_LIBRARY_CONTEXT:
c_get_libctx = OSSL_get_core_get_library_context(in);
break;
case OSSL_FUNC_CORE_GETTABLE_PARAMS:
c_gettable_params = OSSL_get_core_gettable_params(in);
break;
@@ -527,12 +720,25 @@ int OSSL_provider_init(const OSSL_PROVIDER *provider,
case OSSL_FUNC_BIO_FREE:
selftest_params.bio_free_cb = OSSL_get_BIO_free(in);
break;
case OSSL_FUNC_SELF_TEST_CB: {
stcbfn = OSSL_get_self_test_cb(in);
break;
}
default:
/* Just ignore anything we don't understand */
break;
}
}
if (stcbfn != NULL && c_get_libctx != NULL) {
stcbfn(c_get_libctx(provider), &selftest_params.event_cb,
&selftest_params.event_cb_arg);
}
else {
selftest_params.event_cb = NULL;
selftest_params.event_cb_arg = NULL;
}
if (!c_get_params(provider, core_params))
return 0;
@@ -548,7 +754,16 @@ int OSSL_provider_init(const OSSL_PROVIDER *provider,
fgbl->prov = provider;
selftest_params.libctx = PROV_LIBRARY_CONTEXT_OF(ctx);
if (!SELF_TEST_post(&selftest_params)) {
if (!SELF_TEST_post(&selftest_params, 0)) {
OPENSSL_CTX_free(ctx);
return 0;
}
/*
* TODO(3.0): Remove me. This is just a dummy call to demonstrate making
* EVP calls from within the FIPS module.
*/
if (!dummy_evp_call(ctx)) {
OPENSSL_CTX_free(ctx);
return 0;
}
@@ -556,16 +771,6 @@ int OSSL_provider_init(const OSSL_PROVIDER *provider,
*out = fips_dispatch_table;
*provctx = ctx;
/*
* TODO(3.0): Remove me. This is just a dummy call to demonstrate making
* EVP calls from within the FIPS module.
*/
if (!dummy_evp_call(*provctx)) {
OPENSSL_CTX_free(*provctx);
*provctx = NULL;
return 0;
}
return 1;
}
+285
View File
@@ -0,0 +1,285 @@
/*
* 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 <string.h>
#include <openssl/evp.h>
#include <openssl/params.h>
#include <openssl/crypto.h>
#include "e_os.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 OPENSSL_CTX. That doesn't work with the self test though because
* it should be run once regardless of the number of OPENSSL_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 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_state = FIPS_STATE_INIT;
static CRYPTO_RWLOCK *self_test_lock = NULL;
static unsigned char fixed_key[32] = { 0 };
static CRYPTO_ONCE fips_self_test_init = CRYPTO_ONCE_STATIC_INIT;
DEFINE_RUN_ONCE_STATIC(do_fips_self_test_init)
{
/*
* This lock gets 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. So we temporarily disable the
* mem leak checking while we allocate this.
*/
self_test_lock = CRYPTO_THREAD_lock_new();
return self_test_lock != NULL;
}
#define DEP_DECLARE() \
void init(void); \
void cleanup(void);
/*
* This is the Default Entry Point (DEP) code. Every platform must have a DEP.
* See FIPS 140-2 IG 9.10
*
* If we're run on a platform where we don't know how to define the DEP then
* the self-tests will never get triggered (FIPS_state never moves to
* FIPS_STATE_SELFTEST). This will be detected as an error when SELF_TEST_post()
* is called from OSSL_provider_init(), and so the fips module will be unusable
* on those platforms.
*/
#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
DEP_DECLARE()
# define DEP_INIT_ATTRIBUTE
# define DEP_FINI_ATTRIBUTE
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(__sun)
DEP_DECLARE() /* must be declared before pragma */
# define DEP_INIT_ATTRIBUTE
# define DEP_FINI_ATTRIBUTE
# pragma init(init)
# pragma fini(cleanup)
#elif defined(__hpux)
DEP_DECLARE()
# define DEP_INIT_ATTRIBUTE
# define DEP_FINI_ATTRIBUTE
# pragma init "init"
# pragma fini "cleanup"
#elif defined(__GNUC__)
# define DEP_INIT_ATTRIBUTE static __attribute__((constructor))
# define DEP_FINI_ATTRIBUTE static __attribute__((destructor))
#endif
#if defined(DEP_INIT_ATTRIBUTE) && defined(DEP_FINI_ATTRIBUTE)
DEP_INIT_ATTRIBUTE void init(void)
{
FIPS_state = FIPS_STATE_SELFTEST;
}
DEP_FINI_ATTRIBUTE void cleanup(void)
{
CRYPTO_THREAD_lock_free(self_test_lock);
}
#endif
/*
* 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(BIO *bio, OSSL_BIO_read_ex_fn read_ex_cb,
unsigned char *expected, size_t expected_len,
OPENSSL_CTX *libctx, OSSL_ST_EVENT *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[3], *p = params;
SELF_TEST_EVENT_onbegin(ev, event_type, OSSL_SELF_TEST_DESC_INTEGRITY_HMAC);
mac = EVP_MAC_fetch(libctx, MAC_NAME, NULL);
ctx = EVP_MAC_CTX_new(mac);
if (mac == NULL || ctx == NULL)
goto err;
*p++ = OSSL_PARAM_construct_utf8_string("digest", DIGEST_NAME,
strlen(DIGEST_NAME) + 1);
*p++ = OSSL_PARAM_construct_octet_string("key", fixed_key,
sizeof(fixed_key));
*p = OSSL_PARAM_construct_end();
if (EVP_MAC_CTX_set_params(ctx, params) <= 0
|| !EVP_MAC_init(ctx))
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;
SELF_TEST_EVENT_oncorrupt_byte(ev, out);
if (expected_len != out_len
|| memcmp(expected, out, out_len) != 0)
goto err;
ret = 1;
err:
SELF_TEST_EVENT_onend(ev, ret);
EVP_MAC_CTX_free(ctx);
EVP_MAC_free(mac);
return ret;
}
/* 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 ok = 0;
int kats_already_passed = 0;
long checksum_len;
BIO *bio_module = NULL, *bio_indicator = NULL;
unsigned char *module_checksum = NULL;
unsigned char *indicator_checksum = NULL;
int loclstate;
OSSL_ST_EVENT ev;
if (!RUN_ONCE(&fips_self_test_init, do_fips_self_test_init))
return 0;
CRYPTO_THREAD_read_lock(self_test_lock);
loclstate = FIPS_state;
CRYPTO_THREAD_unlock(self_test_lock);
if (loclstate == FIPS_STATE_RUNNING) {
if (!on_demand_test)
return 1;
} else if (loclstate != FIPS_STATE_SELFTEST) {
return 0;
}
CRYPTO_THREAD_write_lock(self_test_lock);
if (FIPS_state == FIPS_STATE_RUNNING) {
if (!on_demand_test) {
CRYPTO_THREAD_unlock(self_test_lock);
return 1;
}
FIPS_state = FIPS_STATE_SELFTEST;
} else if (FIPS_state != FIPS_STATE_SELFTEST) {
CRYPTO_THREAD_unlock(self_test_lock);
return 0;
}
if (st == NULL
|| st->module_checksum_data == NULL)
goto end;
SELF_TEST_EVENT_init(&ev, st->event_cb, st->event_cb_arg);
module_checksum = OPENSSL_hexstr2buf(st->module_checksum_data,
&checksum_len);
if (module_checksum == NULL)
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))
goto end;
/* This will be NULL during installation - so the self test KATS will run */
if (st->indicator_data != NULL) {
/*
* If the kats have already passed indicator is set - then check the
* integrity of the indicator.
*/
if (st->indicator_checksum_data == NULL)
goto end;
indicator_checksum = OPENSSL_hexstr2buf(st->indicator_checksum_data,
&checksum_len);
if (indicator_checksum == NULL)
goto end;
bio_indicator =
(*st->bio_new_buffer_cb)(st->indicator_data,
strlen(st->indicator_data));
if (bio_indicator == NULL
|| !verify_integrity(bio_indicator, st->bio_read_ex_cb,
indicator_checksum, checksum_len,
st->libctx, &ev,
OSSL_SELF_TEST_TYPE_INSTALL_INTEGRITY))
goto end;
else
kats_already_passed = 1;
}
/* Only runs the KAT's during installation OR on_demand() */
if (on_demand_test || kats_already_passed == 0) {
if (!SELF_TEST_kats(&ev, st->libctx))
goto end;
}
ok = 1;
end:
OPENSSL_free(module_checksum);
OPENSSL_free(indicator_checksum);
if (st != NULL) {
(*st->bio_free_cb)(bio_indicator);
(*st->bio_free_cb)(bio_module);
}
FIPS_state = ok ? FIPS_STATE_RUNNING : FIPS_STATE_ERROR;
CRYPTO_THREAD_unlock(self_test_lock);
return ok;
}
@@ -9,6 +9,7 @@
#include <openssl/core_numbers.h>
#include <openssl/types.h>
#include <openssl/self_test.h>
typedef struct self_test_post_params_st {
/* FIPS module integrity check parameters */
@@ -25,8 +26,31 @@ typedef struct self_test_post_params_st {
OSSL_BIO_new_membuf_fn *bio_new_buffer_cb;
OSSL_BIO_read_ex_fn *bio_read_ex_cb;
OSSL_BIO_free_fn *bio_free_cb;
OSSL_CALLBACK *event_cb;
void *event_cb_arg;
OPENSSL_CTX *libctx;
} SELF_TEST_POST_PARAMS;
int SELF_TEST_post(SELF_TEST_POST_PARAMS *st);
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_kats(OSSL_ST_EVENT *event, OPENSSL_CTX *libctx);
void SELF_TEST_EVENT_init(OSSL_ST_EVENT *ev, OSSL_CALLBACK *cb, void *cbarg);
void SELF_TEST_EVENT_onbegin(OSSL_ST_EVENT *ev, const char *type,
const char *desc);
void SELF_TEST_EVENT_onend(OSSL_ST_EVENT *ev, int ret);
void SELF_TEST_EVENT_oncorrupt_byte(OSSL_ST_EVENT *ev, unsigned char *bytes);
+191
View File
@@ -0,0 +1,191 @@
/*
* 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
*/
typedef struct st_kat_st {
const char *desc;
const char *algorithm;
const unsigned char *pt;
size_t pt_len;
const unsigned char *expected;
size_t expected_len;
} ST_KAT;
typedef ST_KAT ST_KAT_DIGEST;
typedef struct st_kat_cipher_st {
ST_KAT base;
const unsigned char *key;
size_t key_len;
const unsigned char *iv;
size_t iv_len;
const unsigned char *aad;
size_t aad_len;
const unsigned char *tag;
size_t tag_len;
} ST_KAT_CIPHER;
typedef struct st_kat_nvp_st {
const char *name;
const char *value;
} ST_KAT_NVP;
typedef struct st_kat_kdf_st {
const char *desc;
const char *algorithm;
const ST_KAT_NVP *ctrls;
const unsigned char *expected;
size_t expected_len;
} ST_KAT_KDF;
/* Macros to build Self test data */
#define ITM(x) x, sizeof(x)
#define ITM_STR(x) x, sizeof(x) - 1
/*- DIGEST TEST DATA */
static const unsigned char sha1_pt[] = "abc";
static const unsigned char sha1_digest[] = {
0xA9, 0x99, 0x3E, 0x36, 0x47, 0x06, 0x81, 0x6A, 0xBA, 0x3E, 0x25, 0x71,
0x78, 0x50, 0xC2, 0x6C, 0x9C, 0xD0, 0xD8, 0x9D
};
static const unsigned char sha512_pt[] = "abc";
static const unsigned char sha512_digest[] = {
0xDD, 0xAF, 0x35, 0xA1, 0x93, 0x61, 0x7A, 0xBA, 0xCC, 0x41, 0x73, 0x49,
0xAE, 0x20, 0x41, 0x31, 0x12, 0xE6, 0xFA, 0x4E, 0x89, 0xA9, 0x7E, 0xA2,
0x0A, 0x9E, 0xEE, 0xE6, 0x4B, 0x55, 0xD3, 0x9A, 0x21, 0x92, 0x99, 0x2A,
0x27, 0x4F, 0xC1, 0xA8, 0x36, 0xBA, 0x3C, 0x23, 0xA3, 0xFE, 0xEB, 0xBD,
0x45, 0x4D, 0x44, 0x23, 0x64, 0x3C, 0xE8, 0x0E, 0x2A, 0x9A, 0xC9, 0x4F,
0xA5, 0x4C, 0xA4, 0x9F
};
static const unsigned char sha3_256_pt[] = { 0xe7, 0x37, 0x21, 0x05 };
static const unsigned char sha3_256_digest[] = {
0x3a, 0x42, 0xb6, 0x8a, 0xb0, 0x79, 0xf2, 0x8c, 0x4c, 0xa3, 0xc7, 0x52,
0x29, 0x6f, 0x27, 0x90, 0x06, 0xc4, 0xfe, 0x78, 0xb1, 0xeb, 0x79, 0xd9,
0x89, 0x77, 0x7f, 0x05, 0x1e, 0x40, 0x46, 0xae
};
static const ST_KAT_DIGEST st_kat_digest_tests[] =
{
{
OSSL_SELF_TEST_DESC_MD_SHA1,
"SHA1",
ITM_STR(sha1_pt),
ITM(sha1_digest),
},
{
OSSL_SELF_TEST_DESC_MD_SHA2,
"SHA512",
ITM_STR(sha512_pt),
ITM(sha512_digest),
},
{
OSSL_SELF_TEST_DESC_MD_SHA3,
"SHA3-256",
ITM(sha3_256_pt),
ITM(sha3_256_digest),
},
};
/*- CIPHER TEST DATA */
/* DES3 test data */
static const unsigned char des_ede3_cbc_pt[] = {
0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96, 0xE9, 0x3D, 0x7E, 0x11,
0x73, 0x93, 0x17, 0x2A, 0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C,
0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51
};
static const unsigned char des_ede3_cbc_key[] = {
0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01,
0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23
};
static const unsigned char des_ede3_cbc_iv[] = {
0xF6, 0x9F, 0x24, 0x45, 0xDF, 0x4F, 0x9B, 0x17
};
static const unsigned char des_ede3_cbc_ct[] = {
0x20, 0x79, 0xC3, 0xD5, 0x3A, 0xA7, 0x63, 0xE1, 0x93, 0xB7, 0x9E, 0x25,
0x69, 0xAB, 0x52, 0x62, 0x51, 0x65, 0x70, 0x48, 0x1F, 0x25, 0xB5, 0x0F,
0x73, 0xC0, 0xBD, 0xA8, 0x5C, 0x8E, 0x0D, 0xA7
};
static const unsigned char aes_256_gcm_key[] = {
0x92,0xe1,0x1d,0xcd,0xaa,0x86,0x6f,0x5c,0xe7,0x90,0xfd,0x24,
0x50,0x1f,0x92,0x50,0x9a,0xac,0xf4,0xcb,0x8b,0x13,0x39,0xd5,
0x0c,0x9c,0x12,0x40,0x93,0x5d,0xd0,0x8b
};
static const unsigned char aes_256_gcm_iv[] = {
0xac,0x93,0xa1,0xa6,0x14,0x52,0x99,0xbd,0xe9,0x02,0xf2,0x1a
};
static const unsigned char aes_256_gcm_pt[] = {
0x2d,0x71,0xbc,0xfa,0x91,0x4e,0x4a,0xc0,0x45,0xb2,0xaa,0x60,
0x95,0x5f,0xad,0x24
};
static const unsigned char aes_256_gcm_aad[] = {
0x1e,0x08,0x89,0x01,0x6f,0x67,0x60,0x1c,0x8e,0xbe,0xa4,0x94,
0x3b,0xc2,0x3a,0xd6
};
static const unsigned char aes_256_gcm_ct[] = {
0x89,0x95,0xae,0x2e,0x6d,0xf3,0xdb,0xf9,0x6f,0xac,0x7b,0x71,
0x37,0xba,0xe6,0x7f
};
static const unsigned char aes_256_gcm_tag[] = {
0xec,0xa5,0xaa,0x77,0xd5,0x1d,0x4a,0x0a,0x14,0xd9,0xc5,0x1e,
0x1d,0xa4,0x74,0xab
};
static const ST_KAT_CIPHER st_kat_cipher_tests[] = {
{
{
OSSL_SELF_TEST_DESC_CIPHER_TDES,
"DES-EDE3-CBC",
ITM(des_ede3_cbc_pt),
ITM(des_ede3_cbc_ct)
},
ITM(des_ede3_cbc_key),
ITM(des_ede3_cbc_iv),
},
{
{
OSSL_SELF_TEST_DESC_CIPHER_AES_GCM,
"AES-256-GCM",
ITM(aes_256_gcm_pt),
ITM(aes_256_gcm_ct),
},
ITM(aes_256_gcm_key),
ITM(aes_256_gcm_iv),
ITM(aes_256_gcm_aad),
ITM(aes_256_gcm_tag)
}
};
/*- KDF TEST DATA */
static const ST_KAT_NVP hkdf_ctrl[] =
{
{ "digest", "SHA256" },
{ "key", "secret" },
{ "salt", "salt" },
{ "info", "label" },
{ NULL, NULL }
};
static const unsigned char hkdf_expected[] = {
0x2a, 0xc4, 0x36, 0x9f, 0x52, 0x59, 0x96, 0xf8, 0xde, 0x13
};
static const ST_KAT_KDF st_kat_kdf_tests[] =
{
{
OSSL_SELF_TEST_DESC_KDF_HKDF,
"HKDF",
hkdf_ctrl,
ITM(hkdf_expected)
}
};
+93
View File
@@ -0,0 +1,93 @@
/*
* 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;
}
}
+246
View File
@@ -0,0 +1,246 @@
/*
* 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 <string.h>
#include <openssl/evp.h>
#include <openssl/kdf.h>
#include "internal/nelem.h"
#include "self_test.h"
#include "self_test_data.inc"
static int self_test_digest(const ST_KAT_DIGEST *t, OSSL_ST_EVENT *event,
OPENSSL_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);
SELF_TEST_EVENT_onbegin(event, 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 */
SELF_TEST_EVENT_oncorrupt_byte(event, out);
if (out_len != t->expected_len
|| memcmp(out, t->expected, out_len) != 0)
goto err;
ok = 1;
err:
SELF_TEST_EVENT_onend(event, ok);
EVP_MD_free(md);
EVP_MD_CTX_free(ctx);
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)
&& (in_tag == NULL
|| EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, t->tag_len,
in_tag))
&& 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_ST_EVENT *event,
OPENSSL_CTX *libctx)
{
int ret = 0, encrypt = 1, len, 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 };
SELF_TEST_EVENT_onbegin(event, OSSL_SELF_TEST_TYPE_KAT_CIPHER, t->base.desc);
ctx = EVP_CIPHER_CTX_new();
if (ctx == NULL)
goto end;
cipher = EVP_CIPHER_fetch(libctx, t->base.algorithm, "");
if (cipher == NULL)
goto end;
/* Encrypt plain text message */
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 end;
SELF_TEST_EVENT_oncorrupt_byte(event, ct_buf);
ct_len += len;
if (ct_len != (int)t->base.expected_len
|| memcmp(t->base.expected, ct_buf, ct_len) != 0)
goto end;
if (t->tag != NULL) {
unsigned char tag[16] = { 0 };
if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, t->tag_len, tag)
|| memcmp(tag, t->tag, t->tag_len) != 0)
goto end;
}
if (!(cipher_init(ctx, cipher, t, !encrypt)
&& EVP_CipherUpdate(ctx, pt_buf, &len, ct_buf, ct_len)
&& EVP_CipherFinal_ex(ctx, pt_buf + len, &pt_len)))
goto end;
pt_len += len;
if (pt_len != (int)t->base.pt_len
|| memcmp(pt_buf, t->base.pt, pt_len) != 0)
goto end;
ret = 1;
end:
EVP_CIPHER_free(cipher);
EVP_CIPHER_CTX_free(ctx);
SELF_TEST_EVENT_onend(event, ret);
return ret;
}
static int self_test_kdf(const ST_KAT_KDF *t, OSSL_ST_EVENT *event,
OPENSSL_CTX *libctx)
{
int ret = 0;
int i;
unsigned char out[64];
EVP_KDF *kdf = NULL;
EVP_KDF_CTX *ctx = NULL;
OSSL_PARAM params[16];
const OSSL_PARAM *settables = NULL;
SELF_TEST_EVENT_onbegin(event, OSSL_SELF_TEST_TYPE_KAT_KDF, t->desc);
kdf = EVP_KDF_fetch(libctx, t->algorithm, "");
ctx = EVP_KDF_CTX_new(kdf);
if (ctx == NULL)
goto end;
settables = EVP_KDF_settable_ctx_params(kdf);
for (i = 0; t->ctrls[i].name != NULL; ++i) {
if (!OSSL_PARAM_allocate_from_text(&params[i], settables,
t->ctrls[i].name,
t->ctrls[i].value,
strlen(t->ctrls[i].value)))
goto end;
}
params[i] = OSSL_PARAM_construct_end();
if (!EVP_KDF_CTX_set_params(ctx, params))
goto end;
if (t->expected_len > sizeof(out))
goto end;
if (EVP_KDF_derive(ctx, out, t->expected_len) <= 0)
goto end;
SELF_TEST_EVENT_oncorrupt_byte(event, out);
if (memcmp(out, t->expected, t->expected_len) != 0)
goto end;
ret = 1;
end:
for (i = 0; params[i].key != NULL; ++i)
OPENSSL_free(params[i].data);
EVP_KDF_free(kdf);
EVP_KDF_CTX_free(ctx);
SELF_TEST_EVENT_onend(event, 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_ST_EVENT *event, OPENSSL_CTX *libctx)
{
int i, ret = 1;
for (i = 0; i < (int)OSSL_NELEM(st_kat_digest_tests); ++i) {
if (!self_test_digest(&st_kat_digest_tests[i], event, libctx))
ret = 0;
}
return ret;
}
static int self_test_ciphers(OSSL_ST_EVENT *event, OPENSSL_CTX *libctx)
{
int i, ret = 1;
for (i = 0; i < (int)OSSL_NELEM(st_kat_cipher_tests); ++i) {
if (!self_test_cipher(&st_kat_cipher_tests[i], event, libctx))
ret = 0;
}
return ret;
}
static int self_test_kdfs(OSSL_ST_EVENT *event, OPENSSL_CTX *libctx)
{
int i, ret = 1;
for (i = 0; i < (int)OSSL_NELEM(st_kat_kdf_tests); ++i) {
if (!self_test_kdf(&st_kat_kdf_tests[i], event, libctx))
ret = 0;
}
return ret;
}
/*
* Run the algorithm KAT's.
* Return 1 is successful, otherwise return 0.
* This runs all the tests regardless of if any fail.
*
* TODO(3.0) Add self tests for KA, DRBG, Sign/Verify when they become available
*/
int SELF_TEST_kats(OSSL_ST_EVENT *event, OPENSSL_CTX *libctx)
{
int ret = 1;
if (!self_test_digests(event, libctx))
ret = 0;
if (!self_test_ciphers(event, libctx))
ret = 0;
if (!self_test_kdfs(event, libctx))
ret = 0;
return ret;
}
-151
View File
@@ -1,151 +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 <string.h>
#include <openssl/evp.h>
#include <openssl/params.h>
#include "selftest.h"
#define FIPS_STATE_INIT 0
#define FIPS_STATE_RUNNING 1
#define FIPS_STATE_SELFTEST 2
#define FIPS_STATE_ERROR 3
/* 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_state = FIPS_STATE_INIT;
static unsigned char fixed_key[32] = { 0 };
/*
* 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(BIO *bio, OSSL_BIO_read_ex_fn read_ex_cb,
unsigned char *expected, size_t expected_len,
OPENSSL_CTX *libctx)
{
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[3], *p = params;
mac = EVP_MAC_fetch(libctx, MAC_NAME, NULL);
ctx = EVP_MAC_CTX_new(mac);
if (mac == NULL || ctx == NULL)
goto err;
*p++ = OSSL_PARAM_construct_utf8_string("digest", DIGEST_NAME,
strlen(DIGEST_NAME) + 1);
*p++ = OSSL_PARAM_construct_octet_string("key", fixed_key,
sizeof(fixed_key));
*p = OSSL_PARAM_construct_end();
if (EVP_MAC_CTX_set_params(ctx, params) <= 0
|| !EVP_MAC_init(ctx))
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;
if (expected_len != out_len
|| memcmp(expected, out, out_len) != 0)
goto err;
ret = 1;
err:
EVP_MAC_CTX_free(ctx);
EVP_MAC_free(mac);
return ret;
}
/* This API is triggered either on loading of the FIPS module or on demand */
int SELF_TEST_post(SELF_TEST_POST_PARAMS *st)
{
int ok = 0;
int kats_already_passed = 0;
int on_demand_test = (FIPS_state != FIPS_STATE_INIT);
long checksum_len;
BIO *bio_module = NULL, *bio_indicator = NULL;
unsigned char *module_checksum = NULL;
unsigned char *indicator_checksum = NULL;
if (st == NULL
|| FIPS_state == FIPS_STATE_ERROR
|| FIPS_state == FIPS_STATE_SELFTEST
|| st->module_checksum_data == NULL)
goto end;
module_checksum = OPENSSL_hexstr2buf(st->module_checksum_data,
&checksum_len);
if (module_checksum == NULL)
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))
goto end;
/* This will be NULL during installation - so the self test KATS will run */
if (st->indicator_data != NULL) {
/*
* If the kats have already passed indicator is set - then check the
* integrity of the indicator.
*/
if (st->indicator_checksum_data == NULL)
goto end;
indicator_checksum = OPENSSL_hexstr2buf(st->indicator_checksum_data,
&checksum_len);
if (indicator_checksum == NULL)
goto end;
bio_indicator =
(*st->bio_new_buffer_cb)(st->indicator_data,
strlen(st->indicator_data));
if (bio_indicator == NULL
|| !verify_integrity(bio_indicator, st->bio_read_ex_cb,
indicator_checksum, checksum_len,
st->libctx))
goto end;
else
kats_already_passed = 1;
}
/* Only runs the KAT's during installation OR on_demand() */
if (on_demand_test || kats_already_passed == 0) {
/*TODO (3.0) Add self test KATS */
}
ok = 1;
end:
OPENSSL_free(module_checksum);
OPENSSL_free(indicator_checksum);
if (st != NULL) {
(*st->bio_free_cb)(bio_indicator);
(*st->bio_free_cb)(bio_module);
}
FIPS_state = ok ? FIPS_STATE_RUNNING : FIPS_STATE_ERROR;
return ok;
}