You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1220 lines
36 KiB
C
1220 lines
36 KiB
C
/* fips_test.c
|
|
*
|
|
* Copyright (C) 2006-2020 wolfSSL Inc.
|
|
*
|
|
* This file is part of wolfSSL.
|
|
*
|
|
* wolfSSL is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* wolfSSL is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
|
*/
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include <config.h>
|
|
#endif
|
|
|
|
/* in case user set HAVE_FIPS there */
|
|
#include <wolfssl/wolfcrypt/settings.h>
|
|
|
|
#ifdef HAVE_FIPS
|
|
|
|
#include <wolfssl/wolfcrypt/fips_test.h>
|
|
#include <wolfssl/wolfcrypt/aes.h>
|
|
#include <wolfssl/wolfcrypt/des3.h>
|
|
#include <wolfssl/wolfcrypt/sha.h>
|
|
#include <wolfssl/wolfcrypt/sha512.h>
|
|
#include <wolfssl/wolfcrypt/random.h>
|
|
#include <wolfssl/wolfcrypt/sha256.h>
|
|
#include <wolfssl/wolfcrypt/sha3.h>
|
|
#include <wolfssl/wolfcrypt/rsa.h>
|
|
#include <wolfssl/wolfcrypt/hmac.h>
|
|
#include <wolfssl/wolfcrypt/ecc.h>
|
|
#include <wolfssl/wolfcrypt/error-crypt.h>
|
|
#include <wolfssl/wolfcrypt/coding.h>
|
|
#include <wolfssl/wolfcrypt/asn.h>
|
|
|
|
#define USE_CERT_BUFFERS_256
|
|
#define USE_CERT_BUFFERS_2048
|
|
#include <wolfssl/certs_test.h> /* rsa 2048 bit key */
|
|
|
|
|
|
#ifdef USE_WINDOWS_API
|
|
#pragma code_seg(".fipsA$p")
|
|
#pragma const_seg(".fipsB$p")
|
|
#endif
|
|
|
|
enum {
|
|
FIPS_AES_KEY_SZ = 16,
|
|
FIPS_AES_IV_SZ = FIPS_AES_KEY_SZ,
|
|
FIPS_AES_PLAIN_SZ = 64,
|
|
FIPS_AES_CBC_SZ = FIPS_AES_PLAIN_SZ,
|
|
FIPS_AES_CIPHER_SZ = FIPS_AES_PLAIN_SZ,
|
|
|
|
FIPS_GCM_KEY_SZ = 16,
|
|
FIPS_GCM_AUTH_SZ = FIPS_GCM_KEY_SZ,
|
|
FIPS_GCM_CHECK_SZ = FIPS_GCM_KEY_SZ,
|
|
FIPS_GCM_TAG_SZ = FIPS_GCM_KEY_SZ,
|
|
FIPS_GCM_PLAIN_SZ = 32,
|
|
FIPS_GCM_CIPHER_SZ = FIPS_GCM_PLAIN_SZ,
|
|
FIPS_GCM_OUT_SZ = FIPS_GCM_PLAIN_SZ,
|
|
FIPS_GCM_IV_SZ = 12,
|
|
|
|
FIPS_CCM_KEY_SZ = 16,
|
|
FIPS_CCM_AUTH_SZ = 32,
|
|
FIPS_CCM_CHECK_SZ = FIPS_CCM_KEY_SZ,
|
|
FIPS_CCM_TAG_SZ = FIPS_CCM_KEY_SZ,
|
|
FIPS_CCM_PLAIN_SZ = 24,
|
|
FIPS_CCM_CIPHER_SZ = FIPS_CCM_PLAIN_SZ,
|
|
FIPS_CCM_OUT_SZ = FIPS_CCM_PLAIN_SZ,
|
|
FIPS_CCM_IV_SZ = 12,
|
|
|
|
FIPS_DES3_KEY_SZ = 24,
|
|
FIPS_DES3_PLAIN_SZ = FIPS_DES3_KEY_SZ,
|
|
FIPS_DES3_CBC_SZ = FIPS_DES3_KEY_SZ,
|
|
FIPS_DES3_CIPHER_SZ = FIPS_DES3_KEY_SZ,
|
|
FIPS_DES3_IV_SZ = 8,
|
|
|
|
FIPS_MAX_DIGEST_SZ = 64,
|
|
FIPS_HMAC_DIGEST_SZ = 64,
|
|
FIPS_HMAC_KEY_SZ = FIPS_HMAC_DIGEST_SZ,
|
|
|
|
FIPS_DRBG_EA_SZ = 48,
|
|
FIPS_DRBG_EB_SZ = 32,
|
|
FIPS_DRBG_OUT_SZ = 128,
|
|
|
|
FIPS_RSA_SIG_SZ = 256,
|
|
FIPS_RSA_RESULT_SZ = FIPS_RSA_SIG_SZ,
|
|
FIPS_RSA_PRIME_SZ = 1024,
|
|
FIPS_RSA_MOD_SHORT = 128,
|
|
|
|
FIPS_ECC_256_SZ = 32,
|
|
FIPS_FFC_FIELD_SZ = 256,
|
|
FIPS_FFC_ORDER_SZ = 32,
|
|
|
|
FIPS_IN_CORE_KEY_SZ = 32,
|
|
FIPS_IN_CORE_VERIFY_SZ = FIPS_IN_CORE_KEY_SZ
|
|
};
|
|
|
|
extern const unsigned int wolfCrypt_FIPS_ro_start[];
|
|
extern const unsigned int wolfCrypt_FIPS_ro_end[];
|
|
|
|
|
|
int wolfCrypt_FIPS_first(void);
|
|
int wolfCrypt_FIPS_last(void);
|
|
|
|
typedef int (*fips_address_function)(void);
|
|
|
|
|
|
/* sanity size checks */
|
|
#define MAX_FIPS_DATA_SZ 100000
|
|
#define MAX_FIPS_CODE_SZ 1000000
|
|
|
|
static int GenBase16_Hash(const byte* in, int length, char* out, int outSz);
|
|
|
|
|
|
/* convert hex string to binary, store size, 0 success (free mem on failure) */
|
|
static int ConvertHexToBin(const char* h1, byte* b1, word32* b1Sz,
|
|
const char* h2, byte* b2, word32* b2Sz,
|
|
const char* h3, byte* b3, word32* b3Sz,
|
|
const char* h4, byte* b4, word32* b4Sz)
|
|
{
|
|
int ret;
|
|
word32 h1Sz, h2Sz, h3Sz, h4Sz, tempSz;
|
|
(void) h1Sz;
|
|
(void) h2Sz;
|
|
(void) h3Sz;
|
|
(void) h4Sz;
|
|
|
|
/* b1 */
|
|
if (h1 && b1 && b1Sz) {
|
|
h1Sz = (int) XSTRLEN(h1);
|
|
tempSz = h1Sz / 2;
|
|
if (tempSz > *b1Sz || tempSz <= 0) {
|
|
return BUFFER_E;
|
|
}
|
|
*b1Sz = tempSz;
|
|
|
|
ret = Base16_Decode((const byte*)h1, h1Sz, b1, b1Sz);
|
|
|
|
if (ret != 0) {
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
/* b2 */
|
|
if (h2 && b2 && b2Sz) {
|
|
h2Sz = (int)XSTRLEN(h2);
|
|
tempSz = h2Sz / 2;
|
|
if (tempSz > *b2Sz || tempSz <= 0) {
|
|
return BUFFER_E;
|
|
}
|
|
*b2Sz = tempSz;
|
|
|
|
ret = Base16_Decode((const byte*)h2, h2Sz, b2, b2Sz);
|
|
if (ret != 0) {
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
/* b3 */
|
|
if (h3 && b3 && b3Sz) {
|
|
h3Sz = (int)XSTRLEN(h3);
|
|
tempSz = h3Sz / 2;
|
|
if (tempSz > *b3Sz || tempSz <= 0) {
|
|
return BUFFER_E;
|
|
}
|
|
*b3Sz = tempSz;
|
|
|
|
ret = Base16_Decode((const byte*)h3, h3Sz, b3, b3Sz);
|
|
if (ret != 0) {
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
/* b4 */
|
|
if (h4 && b4 && b4Sz) {
|
|
h4Sz = (int)XSTRLEN(h4);
|
|
tempSz = h4Sz / 2;
|
|
if (tempSz > *b4Sz || tempSz <= 0) {
|
|
return BUFFER_E;
|
|
}
|
|
*b4Sz = tempSz;
|
|
|
|
ret = Base16_Decode((const byte*)h4, h4Sz, b4, b4Sz);
|
|
if (ret != 0) {
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
/* 0 on success */
|
|
#if !defined(NO_AES) && !defined(NO_AES_CBC)
|
|
static int AesKnownAnswerTest(const char* key, const char* iv,
|
|
const char* plainText, const char* cbc)
|
|
{
|
|
Aes aes;
|
|
|
|
word32 keySz = FIPS_AES_KEY_SZ;
|
|
word32 ivSz = FIPS_AES_IV_SZ;
|
|
word32 plainSz = FIPS_AES_PLAIN_SZ;
|
|
word32 cbcSz = FIPS_AES_CBC_SZ;
|
|
|
|
byte binKey [FIPS_AES_KEY_SZ]; /* AES_Key is 32 bytes */
|
|
byte binIv [FIPS_AES_IV_SZ]; /* AES_IV is 32 bytes */
|
|
byte binPlain [FIPS_AES_PLAIN_SZ]; /* AES_Plain is 128 bytes */
|
|
byte binCbc [FIPS_AES_CBC_SZ]; /* AES_Cbc is 128 bytes */
|
|
byte cipher [FIPS_AES_CIPHER_SZ]; /* for cipher (same as plainSz */
|
|
|
|
int ret = ConvertHexToBin(key, binKey, &keySz,
|
|
iv, binIv, &ivSz,
|
|
plainText, binPlain, &plainSz,
|
|
cbc, binCbc, &cbcSz);
|
|
if (ret != 0)
|
|
return ret;
|
|
|
|
ret = AesSetKey_fips(&aes, binKey, keySz, binIv, AES_ENCRYPTION);
|
|
if (ret != 0) {
|
|
return ret;
|
|
}
|
|
|
|
ret = AesCbcEncrypt_fips(&aes, cipher, binPlain, plainSz);
|
|
if (ret != 0) {
|
|
return ret;
|
|
}
|
|
|
|
if (XMEMCMP(cipher, binCbc, plainSz) != 0) {
|
|
return -1;
|
|
}
|
|
|
|
ret = AesSetKey_fips(&aes, binKey, keySz, binIv, AES_DECRYPTION);
|
|
if (ret != 0) {
|
|
return ret;
|
|
}
|
|
|
|
/* decrypt cipher in place back to plain for verify */
|
|
ret = AesCbcDecrypt_fips(&aes, cipher, cipher, plainSz);
|
|
if (ret != 0) {
|
|
return ret;
|
|
}
|
|
|
|
if (XMEMCMP(cipher, binPlain, plainSz) != 0) {
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
#endif /* NO_AES */
|
|
|
|
|
|
/* 0 on success */
|
|
#ifdef HAVE_AESGCM
|
|
static int AesGcm_KnownAnswerTest(int decrypt,
|
|
const char* key, const char* iv,
|
|
const char* plain, const char* auth,
|
|
const char* cipher, const char* tag)
|
|
{
|
|
Aes aes;
|
|
|
|
byte binKey [FIPS_GCM_KEY_SZ]; /* key */
|
|
byte binIv [FIPS_GCM_IV_SZ]; /* iv */
|
|
byte binPlain [FIPS_GCM_PLAIN_SZ]; /* plain */
|
|
byte binAuth [FIPS_GCM_AUTH_SZ]; /* auth */
|
|
byte binCipher [FIPS_GCM_CIPHER_SZ]; /* cipher */
|
|
byte binTag [FIPS_GCM_TAG_SZ]; /* tag */
|
|
byte out [FIPS_GCM_OUT_SZ]; /* out */
|
|
byte check [FIPS_GCM_CHECK_SZ]; /* check */
|
|
byte checkIv [FIPS_GCM_IV_SZ]; /* check IV */
|
|
|
|
word32 binKeySz = FIPS_GCM_KEY_SZ, binIvSz = FIPS_GCM_IV_SZ,
|
|
binPlainSz = FIPS_GCM_PLAIN_SZ, binAuthSz = FIPS_GCM_AUTH_SZ,
|
|
binCipherSz = FIPS_GCM_CIPHER_SZ, binTagSz = FIPS_GCM_TAG_SZ;
|
|
|
|
int ret = ConvertHexToBin(key, binKey, &binKeySz, iv, binIv, &binIvSz,
|
|
NULL, NULL, NULL, NULL, NULL, NULL);
|
|
if (ret != 0)
|
|
return ret;
|
|
|
|
ret = ConvertHexToBin(plain, binPlain, &binPlainSz,
|
|
auth, binAuth, &binAuthSz,
|
|
cipher, binCipher, &binCipherSz,
|
|
tag, binTag, &binTagSz);
|
|
if (ret != 0) {
|
|
return ret;
|
|
}
|
|
|
|
ret = AesGcmSetKey_fips(&aes, binKey, binKeySz);
|
|
if (ret != 0) {
|
|
return ret;
|
|
}
|
|
|
|
if (decrypt) {
|
|
ret = AesGcmDecrypt_fips(&aes, out, binCipher,
|
|
binCipherSz, binIv, binIvSz,
|
|
binTag, binTagSz,
|
|
binAuth, binAuthSz);
|
|
if (ret != 0) {
|
|
return ret;
|
|
}
|
|
|
|
if (XMEMCMP(binPlain, out, binPlainSz) != 0) {
|
|
return -1;
|
|
}
|
|
}
|
|
else {
|
|
|
|
ret = AesGcmSetExtIV_fips(&aes, binIv, binIvSz);
|
|
if (ret != 0)
|
|
return ret;
|
|
|
|
ret = AesGcmEncrypt_fips(&aes, out, binPlain, binPlainSz,
|
|
checkIv, sizeof(checkIv),
|
|
check, binTagSz,
|
|
binAuth, binAuthSz);
|
|
if (ret != 0)
|
|
return -1;
|
|
|
|
if (XMEMCMP(binIv, checkIv, binIvSz) != 0 ||
|
|
XMEMCMP(binCipher, out, binCipherSz) != 0 ||
|
|
XMEMCMP(binTag, check, binTagSz) != 0) {
|
|
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
#endif /* HAVE_AESGCM */
|
|
|
|
|
|
/* 0 on success */
|
|
#ifndef NO_DES3
|
|
static int Des3_KnownAnswerTest(const char* key, const char* iv,
|
|
const char* plainText, const char* cbc)
|
|
{
|
|
Des3 des3;
|
|
|
|
word32 keySz = FIPS_DES3_KEY_SZ;
|
|
word32 ivSz = FIPS_DES3_IV_SZ;
|
|
word32 plainSz = FIPS_DES3_PLAIN_SZ;
|
|
word32 cbcSz = FIPS_DES3_CBC_SZ;
|
|
|
|
byte binKey [FIPS_DES3_KEY_SZ]; /* key */
|
|
byte binIv [FIPS_DES3_IV_SZ]; /* iv */
|
|
byte binPlain [FIPS_DES3_PLAIN_SZ]; /* plain */
|
|
byte binCbc [FIPS_DES3_CBC_SZ]; /* cbc */
|
|
byte cipher [FIPS_DES3_CIPHER_SZ]; /* cipher */
|
|
|
|
int ret = ConvertHexToBin(key, binKey, &keySz,
|
|
iv, binIv, &ivSz,
|
|
plainText, binPlain, &plainSz,
|
|
cbc, binCbc, &cbcSz);
|
|
if (ret != 0)
|
|
return ret;
|
|
|
|
ret = Des3_SetKey_fips(&des3, binKey, binIv, DES_ENCRYPTION);
|
|
if (ret != 0) {
|
|
return ret;
|
|
}
|
|
|
|
ret = Des3_CbcEncrypt_fips(&des3, cipher, binPlain, plainSz);
|
|
if (ret != 0) {
|
|
return ret;
|
|
}
|
|
|
|
if (XMEMCMP(cipher, binCbc, plainSz) != 0) {
|
|
return -1;
|
|
}
|
|
|
|
ret = Des3_SetKey_fips(&des3, binKey, binIv, DES_DECRYPTION);
|
|
if (ret != 0) {
|
|
return ret;
|
|
}
|
|
|
|
/* decrypt cipher in place back to plain for verify */
|
|
ret = Des3_CbcDecrypt_fips(&des3, cipher, cipher, plainSz);
|
|
if (ret != 0) {
|
|
return ret;
|
|
}
|
|
|
|
if (XMEMCMP(cipher, binPlain, plainSz) != 0) {
|
|
return -1;
|
|
}
|
|
|
|
|
|
return 0;
|
|
}
|
|
#endif /* NO_DES3 */
|
|
|
|
#if !defined(NO_SHA) || defined(WOLFSSL_SHA512)|| defined(WOLFSSL_SHA3)
|
|
/* 0 on success */
|
|
static int HMAC_KnownAnswerTest(int type, const char* key, const char* msg,
|
|
const char* digest)
|
|
{
|
|
Hmac hmac;
|
|
const byte* binMsg = (const byte*)msg;
|
|
byte final[FIPS_MAX_DIGEST_SZ];
|
|
|
|
word32 msgSz = (word32)XSTRLEN(msg);
|
|
word32 digestSz = FIPS_HMAC_DIGEST_SZ;
|
|
word32 keySz = FIPS_HMAC_KEY_SZ;
|
|
|
|
byte binDigest [FIPS_HMAC_DIGEST_SZ]; /* Longest HMAC Digest 128 bytes */
|
|
byte binKey [FIPS_HMAC_KEY_SZ]; /* Longest HMAC Key is 128 bytes */
|
|
|
|
int ret = ConvertHexToBin(digest, binDigest, &digestSz,
|
|
key, binKey, &keySz,
|
|
NULL, NULL, NULL,
|
|
NULL, NULL, NULL);
|
|
if (ret != 0)
|
|
return ret;
|
|
|
|
ret = HmacSetKey_fips(&hmac, type, binKey, keySz);
|
|
if (ret != 0) {
|
|
return ret;
|
|
}
|
|
|
|
ret = HmacUpdate_fips(&hmac, binMsg, msgSz);
|
|
if (ret != 0) {
|
|
return ret;
|
|
}
|
|
|
|
ret = HmacFinal_fips(&hmac, final);
|
|
if (ret != 0) {
|
|
return ret;
|
|
}
|
|
|
|
if (XMEMCMP(final, binDigest, digestSz) != 0) {
|
|
return -1;
|
|
}
|
|
|
|
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
/* 0 on success */
|
|
#ifdef HAVE_HASHDRBG
|
|
static int DRBG_KnownAnswerTest(int reseed, const char* entropyA,
|
|
const char* entropyB, const char* output)
|
|
{
|
|
word32 binEntropyASz = FIPS_DRBG_EA_SZ;
|
|
word32 binEntropyBSz = FIPS_DRBG_EB_SZ;
|
|
word32 binOutputSz = FIPS_DRBG_OUT_SZ;
|
|
|
|
byte check[WC_SHA256_DIGEST_SIZE * 4];
|
|
|
|
byte binEntropyA [FIPS_DRBG_EA_SZ]; /* entropyA */
|
|
byte binEntropyB [FIPS_DRBG_EB_SZ]; /* entropyB */
|
|
byte binOutput [FIPS_DRBG_OUT_SZ]; /* output */
|
|
|
|
int ret = ConvertHexToBin(entropyA, binEntropyA, &binEntropyASz,
|
|
entropyB, binEntropyB, &binEntropyBSz,
|
|
output, binOutput, &binOutputSz,
|
|
NULL, NULL, NULL);
|
|
|
|
if (ret != 0)
|
|
return ret;
|
|
|
|
/* Test Body */
|
|
ret = RNG_HealthTest_fips(reseed, binEntropyA, binEntropyASz,
|
|
binEntropyB, binEntropyBSz,
|
|
check, sizeof(check));
|
|
if (ret != 0) {
|
|
return ret;
|
|
}
|
|
|
|
if (XMEMCMP(binOutput, check, sizeof(check)) != 0) {
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
#endif /* HAVE_HASHDRBG */
|
|
|
|
|
|
#ifdef HAVE_ECC_CDH
|
|
|
|
static int ECC_CDH_KnownAnswerTest(const char* ax, const char* ay,
|
|
const char* d, const char* ix,
|
|
const char* iy, const char* z)
|
|
{
|
|
ecc_key pub_key, priv_key;
|
|
|
|
word32 aSz = FIPS_ECC_256_SZ;
|
|
word32 bSz = FIPS_ECC_256_SZ;
|
|
|
|
byte sharedA[FIPS_ECC_256_SZ] = {0};
|
|
byte sharedB[FIPS_ECC_256_SZ] = {0};
|
|
#ifdef ECC_TIMING_RESISTANT
|
|
WC_RNG rng;
|
|
#endif
|
|
|
|
/* setup private and public keys */
|
|
int ret = wc_ecc_init(&pub_key);
|
|
if (ret != 0) {
|
|
return ret;
|
|
}
|
|
ret = wc_ecc_init(&priv_key);
|
|
if (ret != 0) {
|
|
wc_ecc_free(&pub_key);
|
|
return ret;
|
|
}
|
|
#ifdef ECC_TIMING_RESISTANT
|
|
if (ret == 0)
|
|
ret = wc_InitRng(&rng);
|
|
if (ret == 0)
|
|
ret = wc_ecc_set_rng(&priv_key, &rng);
|
|
#endif
|
|
ret = wc_ecc_set_flags(&priv_key, WC_ECC_FLAG_COFACTOR);
|
|
if (ret == 0) {
|
|
ret = wc_ecc_import_raw(&pub_key, ax, ay, NULL, "SECP256R1");
|
|
}
|
|
if (ret == 0) {
|
|
ret = wc_ecc_import_raw(&priv_key, ix, iy, d, "SECP256R1");
|
|
}
|
|
|
|
/* compute ECC Cofactor shared secret */
|
|
if (ret == 0) {
|
|
ret = wc_ecc_shared_secret(&priv_key, &pub_key, sharedA, &aSz);
|
|
}
|
|
|
|
/* read in expected Z */
|
|
if (ret == 0) {
|
|
ret = Base16_Decode((const byte*)z, (word32)XSTRLEN(z), sharedB, &bSz);
|
|
}
|
|
|
|
/* compare results */
|
|
if (ret == 0) {
|
|
if (aSz != bSz || XMEMCMP(sharedA, sharedB, aSz) != 0) {
|
|
ret = -1;
|
|
}
|
|
}
|
|
|
|
wc_ecc_free(&priv_key);
|
|
wc_ecc_free(&pub_key);
|
|
#ifdef ECC_TIMING_RESISTANT
|
|
wc_FreeRng(&rng);
|
|
#endif
|
|
|
|
return ret;
|
|
}
|
|
|
|
#endif /* HAVE_ECC_CDH */
|
|
|
|
|
|
#ifndef NO_RSA
|
|
static int RsaSignPKCS1v15_KnownAnswerTest(int type, const char* msg,
|
|
const char* sig)
|
|
{
|
|
RsaKey rsa;
|
|
const byte* binMsg = (const byte*)msg;
|
|
byte final[FIPS_MAX_DIGEST_SZ];
|
|
byte verify[FIPS_MAX_DIGEST_SZ];
|
|
word32 msgSz = (word32)XSTRLEN(msg);
|
|
word32 sigSz = FIPS_RSA_SIG_SZ;
|
|
word32 digestSz = 0;
|
|
word32 verifySz = (word32)sizeof(verify);
|
|
word32 resultSz = 0;
|
|
word32 idx = 0;
|
|
|
|
byte binSig [FIPS_RSA_SIG_SZ]; /* signature */
|
|
byte result [FIPS_RSA_RESULT_SZ]; /* result */
|
|
|
|
int ret = ConvertHexToBin(sig, binSig, &sigSz,
|
|
NULL, NULL, NULL,
|
|
NULL, NULL, NULL,
|
|
NULL, NULL, NULL);
|
|
if (ret != 0)
|
|
return ret;
|
|
|
|
resultSz = sigSz;
|
|
|
|
ret = InitRsaKey_fips(&rsa, NULL);
|
|
if (ret != 0) {
|
|
return ret;
|
|
}
|
|
|
|
switch (type) {
|
|
case WC_SHA256 :
|
|
{
|
|
wc_Sha256 sha256;
|
|
|
|
InitSha256_fips(&sha256);
|
|
Sha256Update_fips(&sha256, binMsg, msgSz);
|
|
Sha256Final_fips(&sha256, final);
|
|
digestSz = WC_SHA256_DIGEST_SIZE;
|
|
|
|
break;
|
|
}
|
|
|
|
default:
|
|
FreeRsaKey_fips(&rsa);
|
|
return -1;
|
|
}
|
|
|
|
ret = wc_RsaPrivateKeyDecode(client_key_der_2048, &idx, &rsa,
|
|
sizeof_client_key_der_2048);
|
|
if (ret != 0) {
|
|
FreeRsaKey_fips(&rsa);
|
|
return ret;
|
|
}
|
|
|
|
ret = RsaSSL_Sign_fips(final, digestSz, result, resultSz, &rsa, NULL);
|
|
if (ret != (int)sigSz) {
|
|
FreeRsaKey_fips(&rsa);
|
|
return ret;
|
|
}
|
|
|
|
if (XMEMCMP(result, binSig, sigSz) != 0) {
|
|
FreeRsaKey_fips(&rsa);
|
|
return -1;
|
|
}
|
|
|
|
ret = RsaSSL_Verify_fips(result, sigSz, verify, verifySz, &rsa);
|
|
if (ret != (int)digestSz) {
|
|
FreeRsaKey_fips(&rsa);
|
|
return ret;
|
|
}
|
|
|
|
if (XMEMCMP(verify, final, digestSz) != 0) {
|
|
FreeRsaKey_fips(&rsa);
|
|
return -1;
|
|
}
|
|
|
|
FreeRsaKey_fips(&rsa);
|
|
|
|
return 0;
|
|
}
|
|
#endif /* NO_RSA */
|
|
|
|
|
|
#ifdef HAVE_ECC_DHE
|
|
static int EccPrimitiveZ_KnownAnswerTest(
|
|
const char* qexServer, const char* qeyServer,
|
|
const char* qexClient, const char* qeyClient,
|
|
const char* deClient, const char* zVerify)
|
|
{
|
|
ecc_key serverKey, clientKey;
|
|
wc_Sha256 sha;
|
|
byte z[FIPS_ECC_256_SZ];
|
|
byte zVerifyFlat[WC_SHA256_DIGEST_SIZE];
|
|
byte zHash[WC_SHA256_DIGEST_SIZE];
|
|
word32 zVerifyFlatSz = sizeof(zVerifyFlat);
|
|
word32 zSz = sizeof(z);
|
|
int ret;
|
|
#ifdef ECC_TIMING_RESISTANT
|
|
WC_RNG rng;
|
|
#endif
|
|
|
|
ret = ConvertHexToBin(zVerify, zVerifyFlat, &zVerifyFlatSz,
|
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
|
|
#ifdef ECC_TIMING_RESISTANT
|
|
if (ret == 0)
|
|
ret = wc_InitRng(&rng);
|
|
#endif
|
|
if (ret == 0)
|
|
ret = wc_ecc_init(&serverKey);
|
|
if (ret == 0)
|
|
ret = wc_ecc_init(&clientKey);
|
|
#ifdef ECC_TIMING_RESISTANT
|
|
if (ret == 0)
|
|
ret = wc_ecc_set_rng(&clientKey, &rng);
|
|
#endif
|
|
if (ret == 0)
|
|
ret = wc_ecc_import_raw_ex(&serverKey, qexServer, qeyServer,
|
|
NULL, ECC_SECP256R1);
|
|
if (ret == 0)
|
|
ret = wc_ecc_check_key(&serverKey);
|
|
if (ret == 0)
|
|
ret = wc_ecc_import_raw_ex(&clientKey, qexClient, qeyClient,
|
|
deClient, ECC_SECP256R1);
|
|
if (ret == 0)
|
|
ret = wc_ecc_check_key(&clientKey);
|
|
if (ret == 0)
|
|
ret = wc_ecc_shared_secret(&clientKey, &serverKey, z, &zSz);
|
|
if (ret == 0)
|
|
ret = wc_InitSha256(&sha);
|
|
if (ret == 0)
|
|
ret = wc_Sha256Update(&sha, z, zSz);
|
|
if (ret == 0)
|
|
ret = wc_Sha256Final(&sha, zHash);
|
|
if (ret == 0) {
|
|
if ((zVerifyFlatSz != zSz) || XMEMCMP(zHash, zVerifyFlat, zSz))
|
|
ret = -1;
|
|
}
|
|
wc_ecc_free(&serverKey);
|
|
wc_ecc_free(&clientKey);
|
|
#ifdef ECC_TIMING_RESISTANT
|
|
wc_FreeRng(&rng);
|
|
#endif
|
|
return ret;
|
|
}
|
|
#endif /* HAVE_ECC_DHE */
|
|
|
|
|
|
#ifndef NO_DH
|
|
|
|
static int DhPrimitiveZ_KnownAnswerTest(const char* p, const char* q, const char* g,
|
|
const char* xClient, const char* yServer,
|
|
const char* zVerify)
|
|
{
|
|
DhKey dh;
|
|
wc_Sha256 sha;
|
|
byte pFlat[FIPS_FFC_FIELD_SZ];
|
|
byte qFlat[FIPS_FFC_ORDER_SZ];
|
|
byte gFlat[FIPS_FFC_FIELD_SZ];
|
|
byte yServerFlat[FIPS_FFC_FIELD_SZ];
|
|
byte xClientFlat[FIPS_FFC_ORDER_SZ];
|
|
byte zVerifyFlat[WC_SHA256_DIGEST_SIZE];
|
|
byte z[FIPS_FFC_FIELD_SZ];
|
|
byte zHash[WC_SHA256_DIGEST_SIZE];
|
|
word32 pFlatSz = sizeof(pFlat);
|
|
word32 qFlatSz = sizeof(qFlat);
|
|
word32 gFlatSz = sizeof(gFlat);
|
|
word32 yServerFlatSz = sizeof(yServerFlat);
|
|
word32 xClientFlatSz = sizeof(xClientFlat);
|
|
word32 zVerifyFlatSz = sizeof(zVerifyFlat);
|
|
word32 zSz = sizeof(z);
|
|
int ret;
|
|
|
|
ret = ConvertHexToBin(yServer, yServerFlat, &yServerFlatSz,
|
|
xClient, xClientFlat, &xClientFlatSz,
|
|
zVerify, zVerifyFlat, &zVerifyFlatSz,
|
|
NULL, NULL, NULL);
|
|
if (ret != 0)
|
|
return ret;
|
|
|
|
ret = ConvertHexToBin(p, pFlat, &pFlatSz, g, gFlat, &gFlatSz,
|
|
q, qFlat, &qFlatSz, NULL, NULL, NULL);
|
|
if (ret != 0)
|
|
return ret;
|
|
|
|
ret = wc_InitDhKey(&dh);
|
|
if (ret != 0) {
|
|
return ret;
|
|
}
|
|
|
|
ret = wc_DhSetKey_ex(&dh, pFlat, pFlatSz, gFlat, gFlatSz, qFlat, qFlatSz);
|
|
if (ret != 0) {
|
|
wc_FreeDhKey(&dh);
|
|
return ret;
|
|
}
|
|
|
|
ret = wc_DhAgree(&dh, z, &zSz, xClientFlat, xClientFlatSz,
|
|
yServerFlat, yServerFlatSz);
|
|
if (ret != 0) {
|
|
wc_FreeDhKey(&dh);
|
|
return ret;
|
|
}
|
|
|
|
wc_InitSha256(&sha);
|
|
wc_Sha256Update(&sha, z, zSz);
|
|
wc_Sha256Final(&sha, zHash);
|
|
|
|
if (XMEMCMP(zHash, zVerifyFlat, zVerifyFlatSz) != 0)
|
|
return -1;
|
|
|
|
wc_FreeDhKey(&dh);
|
|
return 0;
|
|
}
|
|
|
|
#endif /* NO_DH */
|
|
|
|
|
|
#if defined(HAVE_ECC) && defined(HAVE_ECC_SIGN) && defined(HAVE_ECC_VERIFY)
|
|
|
|
static int ECDSA_PairwiseAgreeTest(int type, const char* msg)
|
|
{
|
|
ecc_key ecc;
|
|
WC_RNG rng;
|
|
byte msgDigest[FIPS_MAX_DIGEST_SZ];
|
|
byte msgSigned[(FIPS_ECC_256_SZ+1)*2 + 6];
|
|
word32 msgSz = (word32)XSTRLEN(msg);
|
|
word32 msgDigestSz = 0;
|
|
word32 msgSignedSz = sizeof(msgSigned);
|
|
word32 idx = 0;
|
|
int verify = 0;
|
|
int ret;
|
|
|
|
ret = wc_ecc_init(&ecc);
|
|
if (ret != 0) {
|
|
return ret;
|
|
}
|
|
|
|
ret = wc_EccPrivateKeyDecode(ecc_clikey_der_256, &idx, &ecc,
|
|
(word32)sizeof_ecc_clikey_der_256);
|
|
if (ret != 0) {
|
|
wc_ecc_free(&ecc);
|
|
return ret;
|
|
}
|
|
|
|
ret = wc_InitRng(&rng);
|
|
if (ret != 0) {
|
|
wc_ecc_free(&ecc);
|
|
return ret;
|
|
}
|
|
|
|
switch (type) {
|
|
case WC_SHA256 :
|
|
{
|
|
wc_Sha256 sha256;
|
|
|
|
wc_InitSha256(&sha256);
|
|
wc_Sha256Update(&sha256, (const byte*)msg, msgSz);
|
|
wc_Sha256Final(&sha256, msgDigest);
|
|
msgDigestSz = WC_SHA256_DIGEST_SIZE;
|
|
break;
|
|
}
|
|
|
|
default:
|
|
wc_ecc_free(&ecc);
|
|
wc_FreeRng(&rng);
|
|
return -1;
|
|
}
|
|
|
|
ret = wc_ecc_sign_hash(msgDigest, msgDigestSz, msgSigned, &msgSignedSz,
|
|
&rng, &ecc);
|
|
if (ret != 0) {
|
|
wc_ecc_free(&ecc);
|
|
wc_FreeRng(&rng);
|
|
return ret;
|
|
}
|
|
|
|
ret = wc_ecc_verify_hash(msgSigned, msgSignedSz, msgDigest, msgDigestSz,
|
|
&verify, &ecc);
|
|
if (ret != 0) {
|
|
wc_ecc_free(&ecc);
|
|
wc_FreeRng(&rng);
|
|
return ret;
|
|
}
|
|
|
|
if (verify == 0) {
|
|
wc_ecc_free(&ecc);
|
|
wc_FreeRng(&rng);
|
|
return -1;
|
|
}
|
|
|
|
wc_ecc_free(&ecc);
|
|
wc_FreeRng(&rng);
|
|
|
|
return 0;
|
|
}
|
|
|
|
#endif /* HAVE_ECC && HAVE_ECC_SIGN && HAVE_ECC_VERIFY */
|
|
|
|
|
|
/* dead simple base16 encoder, 0 on success */
|
|
static int GenBase16_Hash(const byte* in, int length, char* out, int outSz)
|
|
{
|
|
int i;
|
|
int index = 0;
|
|
|
|
if ( (length * 2 + 1) > outSz)
|
|
return -1;
|
|
|
|
for (i = 0; i < length; i++) {
|
|
byte a = in[i] >> 4;
|
|
byte b = in[i] & 0x0f;
|
|
|
|
if (a > 9)
|
|
a+=7;
|
|
if (b > 9)
|
|
b+=7;
|
|
|
|
out[index++] = a + 0x30;
|
|
out[index++] = b + 0x30;
|
|
}
|
|
out[index++] = '\0';
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/* hmac-sha256 in memory core verify hash, output to pos callback,
|
|
* copy here when changes */
|
|
static const char verifyCore[] =
|
|
"542F30458624B1C57D6FDDE94A7E28C7A688097F6FB8A7FF647BF418C2D6867A";
|
|
|
|
|
|
#ifdef USE_WINDOWS_API
|
|
#pragma warning(push)
|
|
#pragma warning(disable:4054 4305 4311)
|
|
/* For Windows builds, disable compiler warnings for:
|
|
* - 4305: typecasting pointers into unsigned longs
|
|
* - 4054: typecasting function pointer into char pointer
|
|
* - 4311: typecasting pointer truncation
|
|
*/
|
|
#endif
|
|
|
|
/* Do in core memory integrity check, 0 on success */
|
|
static int DoInCoreCheck(char* base16_hash, int base16_hashSz)
|
|
{
|
|
Hmac hmac;
|
|
byte hash[WC_SHA256_DIGEST_SIZE];
|
|
word32 verifySz = FIPS_IN_CORE_VERIFY_SZ;
|
|
word32 binCoreSz = FIPS_IN_CORE_KEY_SZ;
|
|
int ret;
|
|
|
|
byte binCoreKey [FIPS_IN_CORE_KEY_SZ]; /* CoreKey bin will be 32 */
|
|
byte binVerify [FIPS_IN_CORE_VERIFY_SZ]; /* Verify bin will be 32 */
|
|
|
|
static const char coreKey[] =
|
|
"EAD92D38850B03D7160EA4F5C90EDD49C0B6933FAA4833213ED6F0F1596E356B";
|
|
|
|
fips_address_function first = wolfCrypt_FIPS_first;
|
|
fips_address_function last = wolfCrypt_FIPS_last;
|
|
|
|
char* start = (char*)wolfCrypt_FIPS_ro_start;
|
|
char* end = (char*)wolfCrypt_FIPS_ro_end;
|
|
|
|
unsigned long code_sz = (unsigned long)last - (unsigned long)first;
|
|
unsigned long data_sz = (unsigned long)end - (unsigned long)start;
|
|
|
|
if (data_sz == 0 || data_sz > MAX_FIPS_DATA_SZ)
|
|
return -1; /* bad fips data size */
|
|
|
|
if (code_sz == 0 || code_sz > MAX_FIPS_CODE_SZ)
|
|
return -1; /* bad fips code size */
|
|
|
|
ret = ConvertHexToBin(coreKey, binCoreKey, &binCoreSz,
|
|
NULL, NULL, NULL,
|
|
NULL, NULL, NULL,
|
|
NULL, NULL, NULL);
|
|
if (ret != 0) return ret;
|
|
|
|
HmacSetKey_fips(&hmac, WC_SHA256, binCoreKey, binCoreSz);
|
|
|
|
HmacUpdate_fips(&hmac, (byte*)first, (word32)code_sz);
|
|
|
|
/* don't hash verifyCore or changing verifyCore will change hash */
|
|
if (verifyCore >= start && verifyCore < end) {
|
|
data_sz = (unsigned long)verifyCore - (unsigned long)start;
|
|
HmacUpdate_fips(&hmac, (byte*)start, (word32)data_sz);
|
|
start = (char*)verifyCore + sizeof(verifyCore);
|
|
data_sz = (unsigned long)end - (unsigned long)start;
|
|
}
|
|
HmacUpdate_fips(&hmac, (byte*)start, (word32)data_sz);
|
|
|
|
HmacFinal_fips(&hmac, hash);
|
|
|
|
ret = GenBase16_Hash(hash, sizeof(hash), base16_hash, base16_hashSz);
|
|
if (ret != 0)
|
|
return ret;
|
|
|
|
ret = ConvertHexToBin(verifyCore, binVerify, &verifySz,
|
|
NULL, NULL, NULL,
|
|
NULL, NULL, NULL,
|
|
NULL, NULL, NULL);
|
|
if (ret != 0)
|
|
return ret;
|
|
|
|
if (XMEMCMP(hash, binVerify, sizeof(hash)) != 0) {
|
|
ret = -1;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
#ifdef USE_WINDOWS_API
|
|
#pragma warning(pop)
|
|
#endif
|
|
|
|
|
|
/* do all tests, 0 on success */
|
|
int DoKnownAnswerTests(char* base16_hash, int base16_hashSz)
|
|
{
|
|
if (DoInCoreCheck(base16_hash, base16_hashSz) != 0) {
|
|
printf("In core integrity check error: hash = %s\n", base16_hash);
|
|
return IN_CORE_FIPS_E;
|
|
}
|
|
|
|
#if !defined(NO_AES) && !defined(NO_AES_CBC)
|
|
if (AesKnownAnswerTest(
|
|
"2b7e151628aed2a6abf7158809cf4f3c", /* key */
|
|
"000102030405060708090a0b0c0d0e0f", /* iv */
|
|
"6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac" /* plainText */
|
|
"9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a"
|
|
"52eff69f2445df4f9b17ad2b417be66c3710",
|
|
"7649abac8119b246cee98e9b12e9197d5086cb9b507219" /* cbc */
|
|
"ee95db113a917678b273bed6b8e3c1743b7116e69e2222"
|
|
"95163ff1caa1681fac09120eca307586e1a7"
|
|
) != 0) {
|
|
return AES_KAT_FIPS_E;
|
|
}
|
|
#endif
|
|
|
|
#ifdef HAVE_AESGCM
|
|
if (AesGcm_KnownAnswerTest(0,
|
|
"298efa1ccf29cf62ae6824bfc19557fc", /* key */
|
|
"6f58a93fe1d207fae4ed2f6d", /* iv */
|
|
"cc38bccd6bc536ad919b1395f5d63801f99f8068d65ca5ac" /* plain */
|
|
"63872daf16b93901",
|
|
"021fafd238463973ffe80256e5b1c6b1", /* auth */
|
|
"dfce4e9cd291103d7fe4e63351d9e79d3dfd391e32671046" /* cipher */
|
|
"58212da96521b7db",
|
|
"542465ef599316f73a7a560509a2d9f2" /* tag */
|
|
) != 0) {
|
|
return AESGCM_KAT_FIPS_E;
|
|
}
|
|
|
|
if (AesGcm_KnownAnswerTest(1,
|
|
"afa272c03d0343f882008f6e163d6047", /* key */
|
|
"271ba21f8fdcac34dc93be54", /* iv */
|
|
"f3ee01423f192c36033542221c5545dd939de52ada18b9e8" /* plain */
|
|
"b72ba17d02c5dddd",
|
|
"cdf5496a50214683304aec0a80337f9a", /* auth */
|
|
"36a4029c9e7d0307d31c29cea885bb6c8022452016a29754" /* cipher */
|
|
"ba8a344c5bbfc3e1",
|
|
"ed8d916c171f0688d7e7cca547ab3ab2" /* tag */
|
|
) != 0) {
|
|
return AESGCM_KAT_FIPS_E;
|
|
}
|
|
#endif
|
|
|
|
#ifndef NO_DES3
|
|
if (Des3_KnownAnswerTest(
|
|
"385D7189A5C3D485E1370AA5D408082B5CCCCB5E19F2D90E", /* key */
|
|
"C141B5FCCD28DC8A", /* iv */
|
|
"6E1BD7C6120947A464A6AAB293A0F89A563D8D40D3461B68", /* plain */
|
|
"6235A461AFD312973E3B4F7AA7D23E34E03371F8E8C376C9" /* cbc */
|
|
) != 0) {
|
|
return DES3_KAT_FIPS_E;
|
|
}
|
|
#endif
|
|
|
|
#ifndef NO_SHA
|
|
if (HMAC_KnownAnswerTest(WC_SHA, /* type */
|
|
"303132333435363738393a3b3c3d3e3f40414243", /* key */
|
|
"Sample #2", /* msg */
|
|
"0922D3405FAA3D194F82A45830737D5CC6C75D24" /* digest */
|
|
) != 0) {
|
|
return HMAC_KAT_FIPS_E;
|
|
}
|
|
#endif
|
|
|
|
#ifdef WOLFSSL_SHA512
|
|
if (HMAC_KnownAnswerTest(WC_SHA512, /* type */
|
|
"303132333435363738393a3b3c3d3e3f40414243", /* key */
|
|
"Sample #2", /* msg */
|
|
"809d44057c5b954105bd041316db0fac44d5a4d5d0892bd04e866412c0907768"
|
|
"f187b77c4fae2c2f21a5b5659a4f4ba74702a3de9b51f145bd4f252742989905"
|
|
/* digest */
|
|
) != 0) {
|
|
return HMAC_KAT_FIPS_E;
|
|
}
|
|
#endif
|
|
|
|
#ifdef WOLFSSL_SHA3
|
|
if (HMAC_KnownAnswerTest(WC_SHA3_256, /* type */
|
|
"302132333435363738393a3b3c3d3e3f"
|
|
"302132333435363738393a3b3c3d3e3f", /* key */
|
|
"Sample #2", /* msg */
|
|
"1c91ce1a0cbf7501f432a8e23a17cd98"
|
|
"3c96c9b5a16742016c179ff73eb8aa83" /* digest */
|
|
) != 0) {
|
|
return HMAC_KAT_FIPS_E;
|
|
}
|
|
#endif
|
|
|
|
#ifndef NO_RSA
|
|
if (RsaSignPKCS1v15_KnownAnswerTest(WC_SHA256, /* type */
|
|
"Everyone gets Friday off.", /* msg */
|
|
"8CFA57979578B9D781C7F7EEDD21E962FC45D8B7CCDA68837"
|
|
"D84E8345973856089C025A06F89F77D7C3694C483A6EF6B42"
|
|
"EE69B8C2E01CC113F137F498890752EF6C6094D3819979122"
|
|
"7928ED82D5BB50FB96A754F977D66FE75ABCF70F5D9448352"
|
|
"26D30BF6F62D7B9CAFFA18179C5DABCE58BA497424A5AC8D6"
|
|
"11814B726CF3294D0C238000DC2B775791925CA528F6B4947"
|
|
"D3E4BA1F8CDF4C3E88E1AA2FCDAE461F6DF245DD3C39F980F"
|
|
"D0FEC213FCB7B7D1679F4689D08538E16A8E0F357BADFD1F0"
|
|
"D56C635B9E6E7CBD6E2F32F347AB9E07685166016EEF8F857"
|
|
"37542185635688469BC08AF743B02B5C6FB5CED8924B20C14"
|
|
"7B9F349FAA1943DBF677CA"
|
|
/* signature */
|
|
) != 0) {
|
|
return RSA_KAT_FIPS_E;
|
|
}
|
|
#endif
|
|
|
|
#ifdef HAVE_HASHDRBG
|
|
if (DRBG_KnownAnswerTest(0,
|
|
"a65ad0f345db4e0effe875c3a2e71f42"
|
|
"c7129d620ff5c119a9ef55f05185e0fb"
|
|
"8581f9317517276e06e9607ddbcbcc2e", /* entropy + nonce input */
|
|
NULL, /* no reseed */
|
|
"d3e160c35b99f340b2628264d1751060"
|
|
"e0045da383ff57a57d73a673d2b8d80d"
|
|
"aaf6a6c35a91bb4579d73fd0c8fed111"
|
|
"b0391306828adfed528f018121b3febd"
|
|
"c343e797b87dbb63db1333ded9d1ece1"
|
|
"77cfa6b71fe8ab1da46624ed6415e51c"
|
|
"cde2c7ca86e283990eeaeb9112041552"
|
|
"8b2295910281b02dd431f4c9f70427df" /* pseudorandom output */
|
|
) != 0) {
|
|
return DRBG_KAT_FIPS_E;
|
|
}
|
|
|
|
if (DRBG_KnownAnswerTest(1,
|
|
"63363377e41e86468deb0ab4a8ed683f"
|
|
"6a134e47e014c700454e81e95358a569"
|
|
"808aa38f2a72a62359915a9f8a04ca68", /* entropy + nonce input */
|
|
"e62b8a8ee8f141b6980566e3bfe3c049"
|
|
"03dad4ac2cdf9f2280010a6739bc83d3", /* reseed entropy input */
|
|
"04eec63bb231df2c630a1afbe724949d"
|
|
"005a587851e1aa795e477347c8b05662"
|
|
"1c18bddcdd8d99fc5fc2b92053d8cfac"
|
|
"fb0bb8831205fad1ddd6c071318a6018"
|
|
"f03b73f5ede4d4d071f9de03fd7aea10"
|
|
"5d9299b8af99aa075bdb4db9aa28c18d"
|
|
"174b56ee2a014d098896ff2282c955a8"
|
|
"1969e069fa8ce007a180183a07dfae17" /* pseudorandom output */
|
|
) != 0) {
|
|
return DRBG_KAT_FIPS_E;
|
|
}
|
|
#endif
|
|
|
|
#ifdef HAVE_ECC_CDH
|
|
if (ECC_CDH_KnownAnswerTest(
|
|
/* ax */
|
|
"700c48f77f56584c5cc632ca65640db91b6bacce3a4df6b42ce7cc838833d287",
|
|
/* ay */
|
|
"db71e509e3fd9b060ddb20ba5c51dcc5948d46fbf640dfe0441782cab85fa4ac",
|
|
/* d */
|
|
"7d7dc5f71eb29ddaf80d6214632eeae03d9058af1fb6d22ed80badb62bc1a534",
|
|
/* ix */
|
|
"ead218590119e8876b29146ff89ca61770c4edbbf97d38ce385ed281d8a6b230",
|
|
/* iy */
|
|
"28af61281fd35e2fa7002523acc85a429cb06ee6648325389f59edfce1405141",
|
|
/* z */
|
|
"46fc62106420ff012e54a434fbdd2d25ccc5852060561e68040dd7778997bd7b"
|
|
) != 0) {
|
|
return ECC_CDH_KAT_FIPS_E;
|
|
}
|
|
#endif
|
|
|
|
#ifdef HAVE_ECC_DHE
|
|
if (EccPrimitiveZ_KnownAnswerTest(
|
|
/* qexServer */
|
|
"a2f5af030e280c76512f4591c200a3aac5b3f464fe7b598b2677af1df90f7c16",
|
|
/* qeyServer */
|
|
"0052d0fcf017d89126e51c837705826c6b954cf3ce4513706ab3cd1cf69287f7",
|
|
/* qexClient */
|
|
"6483453e74522854c940d9817e464f846975aeddbde3742e46ff10110178b5d4",
|
|
/* qeyClient */
|
|
"e3a66b3758279713ff594f485e9f7e0c34215090575ac4b4595ebaa301bda0b3",
|
|
/* deClient */
|
|
"02697f40772eb4bc12dd43436b0f8c9f5852e8df1e994f5857e18ef26e78d8e0",
|
|
/* zVerify */
|
|
"322f2e5a51d78300e5ec692e7c592a25e65c960f76de8729ee0b678dc9d0e99e"
|
|
) != 0) {
|
|
return ECDHE_KAT_FIPS_E;
|
|
}
|
|
#endif
|
|
|
|
#ifndef NO_DH
|
|
if (DhPrimitiveZ_KnownAnswerTest(
|
|
/* p */
|
|
"c7a528b2747cd4080d5da193285ef3eddf7bea8be391df9503c9f6a73372f6ee"
|
|
"4e8b2cc0577bf7f8366a29b59286be32e1a13e60bea187e654b6c71268e39c97"
|
|
"3ff220e4a8545cef5a85980d1c9687193faac4355370dee4a37acfc3a29c3e1c"
|
|
"82faad94a2afc004ea1861fde4a9c25950a85264eb87175d047af23ad048d840"
|
|
"50f8f0ea071672a6d210b545656c0556e94d2b4ab0b739eaf4d6c2d8d09c464f"
|
|
"8d6afc1a8283ef3a6227d87ab6fef5e6208645a468bbba478d4b84dedb398689"
|
|
"15e28317a7111ee75c028fe2ecfcf92453b89ff7d8c860e875b266d4455c2ac2"
|
|
"626b6a748af0597ca9907405981d4e9af12451dad23a46f4219da89cc5be7453",
|
|
/* q */
|
|
"bc611c3b67b20c469972651de49b3b879d624d72ea41951615a04cc5b7f04a1f",
|
|
/* g */
|
|
"2fa3f79bb9cfb3fbaa4b19b8c0b5fb1e791da1c3426fb33c979ad2fcde6f984c"
|
|
"c1578fb79125b646694ef937e2a4b1c45ff1ecb7847d4e2cc5761fa483116a9c"
|
|
"cf628aa9c71c15cb37547ec1bd64930fb9a7569e90219b2d6ed82ad2cfee8b04"
|
|
"4aefb475dfd0f89acb690b5021d7cacba9cbdcb517416bdbade00003dd9ea18d"
|
|
"310e9c5734f8508ca57eb523b84b199600c130ce7bd0ab2f3dc151c10301fefc"
|
|
"11bcd7f4fc628a84e58e4b34eb9e17406cfece2db09d7966b76582a13b31ebd7"
|
|
"fd51bf57495144598300c9c1dc2f69237aba4e0d6d6aee1bdff125f5fee62735"
|
|
"6759ba8c2f64dbef44565dde7875362b8e681cdf63aa2add4fa83b0a7509c3cc",
|
|
/* xClient */
|
|
"5b359fb62eea923b26727316a2a54126bd89a5b5015be6ac1b294ffaf180d1cb",
|
|
/* yServer */
|
|
"b503c9e08cf1461540eed4d794a8dc103fa47c3e1689cc3145b8f9bdeb1df99b"
|
|
"d029f4431ce36b5854c7e16b8d076cf58023f7696fad93789a730a8b42d11345"
|
|
"0903cea3555a39b3c1a9756dcd22915e5bb2ac62e4607f0c455da951b43135db"
|
|
"37e171ddb4da8ae671a90f1bd288d634d4f18481d25c139d44672bbef0245928"
|
|
"a9a78d1f5d28665eed690acdf0e06a82a3e4fdb9776a2705248f10ac638f6525"
|
|
"03fd69d73ed46b4d0e47beb738d90913a48840d4a05f059aee4050572d6432c0"
|
|
"a4a50e455d2b92195eadb7193c96f31e89d469b16ef9b5ddef006102652a90cd"
|
|
"1d6d29f366f88321eb6ce0bdf6c567b302670df28ad42424dc8475a6b0153826",
|
|
/* zVerify */
|
|
"288cc3c9b62c6af7ae8ceaa61c1ebe3de7fe8040928b7154428fa3a08e148b27"
|
|
) != 0) {
|
|
return DH_KAT_FIPS_E;
|
|
}
|
|
#endif
|
|
|
|
#ifdef HAVE_ECC
|
|
if (ECDSA_PairwiseAgreeTest(WC_SHA256, "Everyone gets Friday off.") != 0) {
|
|
return ECDSA_PAT_FIPS_E;
|
|
}
|
|
#endif
|
|
|
|
return 0; /* success */
|
|
}
|
|
|
|
|
|
#endif /* HAVE_FIPS */
|