提交 05e24c87 编写于 作者: D Dr. Stephen Henson

Extensive reorganisation of PRNG handling in FIPS module: all calls

now use an internal RAND_METHOD. All dependencies to OpenSSL standard
PRNG are now removed: it is the applications resposibility to setup
the FIPS PRNG and initalise it.

Initial OpenSSL RAND_init_fips() function that will setup the DRBG
for the "FIPS capable OpenSSL".
上级 cab0595c
......@@ -4,6 +4,14 @@
Changes between 1.0.1 and 1.1.0 [xx XXX xxxx]
*) Extensive reorganisation of FIPS PRNG behaviour. Remove all dependencies
to OpenSSL RAND code and replace with a tiny FIPS RAND API which also
performs algorithm blocking for unapproved PRNG types. Also do not
set PRNG type in FIPS_mode_set(): leave this to the application.
Add default OpenSSL DRBG handling: sets up FIPS PRNG and seeds with
the standard OpenSSL PRNG.
[Steve Henson]
*) Rename old X9.31 PRNG functions of the form FIPS_rand* to FIPS_x931*.
This shouldn't present any incompatibility problems because applications
shouldn't be using these directly and any that are will need to rethink
......
......@@ -56,6 +56,8 @@
* [including the GNU Public Licence.]
*/
#define OPENSSL_FIPSAPI
#include <stdio.h>
#include "cryptlib.h"
#ifndef OPENSSL_NO_DES
......
......@@ -96,6 +96,12 @@ static ERR_STRING_DATA FIPS_str_functs[]=
{ERR_FUNC(FIPS_F_FIPS_DSA_CHECK), "FIPS_DSA_CHECK"},
{ERR_FUNC(FIPS_F_FIPS_MODE_SET), "FIPS_mode_set"},
{ERR_FUNC(FIPS_F_FIPS_PKEY_SIGNATURE_TEST), "fips_pkey_signature_test"},
{ERR_FUNC(FIPS_F_FIPS_RAND_ADD), "FIPS_rand_add"},
{ERR_FUNC(FIPS_F_FIPS_RAND_BYTES), "FIPS_rand_bytes"},
{ERR_FUNC(FIPS_F_FIPS_RAND_PSEUDO_BYTES), "FIPS_rand_pseudo_bytes"},
{ERR_FUNC(FIPS_F_FIPS_RAND_SEED), "FIPS_rand_seed"},
{ERR_FUNC(FIPS_F_FIPS_RAND_SET_METHOD), "FIPS_rand_set_method"},
{ERR_FUNC(FIPS_F_FIPS_RAND_STATUS), "FIPS_rand_status"},
{ERR_FUNC(FIPS_F_FIPS_SELFTEST_AES), "FIPS_selftest_aes"},
{ERR_FUNC(FIPS_F_FIPS_SELFTEST_AES_GCM), "FIPS_selftest_aes_gcm"},
{ERR_FUNC(FIPS_F_FIPS_SELFTEST_CMAC), "FIPS_selftest_cmac"},
......@@ -105,6 +111,7 @@ static ERR_STRING_DATA FIPS_str_functs[]=
{ERR_FUNC(FIPS_F_FIPS_SELFTEST_HMAC), "FIPS_selftest_hmac"},
{ERR_FUNC(FIPS_F_FIPS_SELFTEST_RNG), "FIPS_selftest_rng"},
{ERR_FUNC(FIPS_F_FIPS_SELFTEST_SHA1), "FIPS_selftest_sha1"},
{ERR_FUNC(FIPS_F_FIPS_SELFTEST_X931), "FIPS_selftest_x931"},
{ERR_FUNC(FIPS_F_HASH_FINAL), "HASH_FINAL"},
{ERR_FUNC(FIPS_F_RSA_BUILTIN_KEYGEN), "RSA_BUILTIN_KEYGEN"},
{ERR_FUNC(FIPS_F_RSA_EAY_PRIVATE_DECRYPT), "RSA_EAY_PRIVATE_DECRYPT"},
......
......@@ -56,6 +56,7 @@
#include <openssl/err.h>
#ifdef OPENSSL_FIPS
#include <openssl/fips.h>
#include <openssl/rand.h>
#endif
#if defined(__GNUC__) && __GNUC__>=2
......@@ -123,6 +124,7 @@ void OPENSSL_init(void)
FIPS_set_locking_callbacks(CRYPTO_lock, CRYPTO_add_lock);
FIPS_set_error_callbacks(ERR_put_error, ERR_add_error_vdata);
FIPS_set_malloc_callbacks(CRYPTO_malloc, CRYPTO_free);
RAND_init_fips();
#endif
#if 0
fprintf(stderr, "Called OPENSSL_init\n");
......
......@@ -94,7 +94,7 @@ extern int rand_predictable;
int RAND_set_rand_method(const RAND_METHOD *meth);
const RAND_METHOD *RAND_get_rand_method(void);
#if !defined(OPENSSL_NO_ENGINE) && !defined(OPENSSL_FIPS)
#ifndef OPENSSL_NO_ENGINE
int RAND_set_rand_engine(ENGINE *engine);
#endif
RAND_METHOD *RAND_SSLeay(void);
......@@ -119,6 +119,10 @@ int RAND_event(UINT, WPARAM, LPARAM);
#endif
#ifdef OPENSSL_FIPS
int RAND_init_fips(void);
#endif
/* BEGIN ERROR CODES */
/* The following lines are auto generated by the script mkerr.pl. Any changes
* made after this point may be overwritten when the script is next run.
......@@ -132,6 +136,7 @@ void ERR_load_RAND_strings(void);
#define RAND_F_FIPS_RAND_SET_DT 103
#define RAND_F_FIPS_SET_PRNG_SEED 104
#define RAND_F_FIPS_SET_TEST_MODE 105
#define RAND_F_FIPS_X931_SET_DT 106
#define RAND_F_RAND_GET_RAND_METHOD 101
#define RAND_F_SSLEAY_RAND_BYTES 100
......
......@@ -74,6 +74,7 @@ static ERR_STRING_DATA RAND_str_functs[]=
{ERR_FUNC(RAND_F_FIPS_RAND_SET_DT), "FIPS_RAND_SET_DT"},
{ERR_FUNC(RAND_F_FIPS_SET_PRNG_SEED), "FIPS_SET_PRNG_SEED"},
{ERR_FUNC(RAND_F_FIPS_SET_TEST_MODE), "FIPS_SET_TEST_MODE"},
{ERR_FUNC(RAND_F_FIPS_X931_SET_DT), "FIPS_x931_set_dt"},
{ERR_FUNC(RAND_F_RAND_GET_RAND_METHOD), "RAND_get_rand_method"},
{ERR_FUNC(RAND_F_SSLEAY_RAND_BYTES), "SSLEAY_RAND_BYTES"},
{0,NULL}
......
......@@ -61,11 +61,6 @@
#include "cryptlib.h"
#include <openssl/rand.h>
#ifdef OPENSSL_FIPSCANISTER
#define OPENSSL_NO_ENGINE
#include <openssl/fips.h>
#endif
#ifndef OPENSSL_NO_ENGINE
#include <openssl/engine.h>
#endif
......@@ -180,3 +175,70 @@ int RAND_status(void)
return meth->status();
return 0;
}
#ifdef OPENSSL_FIPS
#include <openssl/fips.h>
#include <openssl/fips_rand.h>
/* FIPS DRBG initialisation code. This sets up the DRBG for use by the
* rest of OpenSSL.
*/
/* Entropy gatherer: use standard OpenSSL PRNG to seed (this will gather
* entropy internally through RAND_poll().
*/
static size_t drbg_get_entropy(DRBG_CTX *ctx, unsigned char **pout,
int entropy, size_t min_len, size_t max_len)
{
*pout = OPENSSL_malloc(min_len);
if (!*pout)
return 0;
if (RAND_SSLeay()->bytes(*pout, min_len) <= 0)
{
OPENSSL_free(*pout);
*pout = NULL;
return 0;
}
return min_len;
}
static void drbg_free_entropy(DRBG_CTX *ctx, unsigned char *out, size_t olen)
{
OPENSSL_cleanse(out, olen);
OPENSSL_free(out);
}
/* RAND_add() and RAND_seed() pass through to OpenSSL PRNG so it is
* correctly seeded by RAND_poll().
*/
static int drbg_rand_add(DRBG_CTX *ctx, const void *in, int inlen,
double entropy)
{
return RAND_SSLeay()->add(in, inlen, entropy);
}
static int drbg_rand_seed(DRBG_CTX *ctx, const void *in, int inlen)
{
return RAND_SSLeay()->seed(in, inlen);
}
int RAND_init_fips(void)
{
DRBG_CTX *dctx;
unsigned char pers[16] = {0,0,0};
dctx = FIPS_get_default_drbg();
FIPS_drbg_init(dctx, NID_aes_256_ctr, DRBG_FLAG_CTR_USE_DF);
FIPS_drbg_set_callbacks(dctx,
drbg_get_entropy, drbg_free_entropy,
drbg_get_entropy, drbg_free_entropy);
FIPS_drbg_set_rand_callbacks(dctx, 0, 0,
drbg_rand_seed, drbg_rand_add);
FIPS_drbg_instantiate(dctx, pers, sizeof(pers));
FIPS_rand_set_method(FIPS_drbg_method());
return 1;
}
#endif
......@@ -73,7 +73,6 @@
static int fips_selftest_fail;
static int fips_mode;
static int fips_started = 0;
static const void *fips_rand_check;
static int fips_is_owning_thread(void);
static int fips_set_owning_thread(void);
......@@ -97,18 +96,6 @@ static void fips_set_mode(int onoff)
}
}
static void fips_set_rand_check(const void *rand_check)
{
int owning_thread = fips_is_owning_thread();
if (fips_started)
{
if (!owning_thread) fips_w_lock();
fips_rand_check = rand_check;
if (!owning_thread) fips_w_unlock();
}
}
int FIPS_mode(void)
{
int ret = 0;
......@@ -123,20 +110,6 @@ int FIPS_mode(void)
return ret;
}
const void *FIPS_rand_check(void)
{
const void *ret = 0;
int owning_thread = fips_is_owning_thread();
if (fips_started)
{
if (!owning_thread) fips_r_lock();
ret = fips_rand_check;
if (!owning_thread) fips_r_unlock();
}
return ret;
}
int FIPS_selftest_failed(void)
{
int ret = 0;
......@@ -329,28 +302,7 @@ int FIPS_mode_set(int onoff)
ret = 0;
goto end;
}
#if 0
/* automagically seed PRNG if not already seeded */
if(!FIPS_rand_status())
{
unsigned char buf[48];
if(RAND_bytes(buf,sizeof buf) <= 0)
{
fips_selftest_fail = 1;
ret = 0;
goto end;
}
FIPS_rand_set_key(buf,32);
FIPS_rand_seed(buf+32,16);
}
/* now switch into FIPS mode */
fips_set_rand_check(FIPS_rand_method());
RAND_set_rand_method(FIPS_rand_method());
#else
fips_set_rand_check(FIPS_drbg_method());
RAND_set_rand_method(FIPS_drbg_method());
#endif
if(FIPS_selftest())
fips_set_mode(1);
else
......
......@@ -177,6 +177,12 @@ void FIPS_set_malloc_callbacks(
#define ecdsa_check fips_ecdsa_check
#define ecdh_check fips_ecdh_check
#define RAND_bytes FIPS_rand_bytes
#define RAND_pseudo_bytes FIPS_rand_pseudo_bytes
#define RAND_add FIPS_rand_add
#define RAND_seed FIPS_rand_seed
#define RAND_status FIPS_rand_status
#endif
/* BEGIN ERROR CODES */
......@@ -214,6 +220,12 @@ void ERR_load_FIPS_strings(void);
#define FIPS_F_FIPS_DSA_CHECK 107
#define FIPS_F_FIPS_MODE_SET 108
#define FIPS_F_FIPS_PKEY_SIGNATURE_TEST 109
#define FIPS_F_FIPS_RAND_ADD 143
#define FIPS_F_FIPS_RAND_BYTES 144
#define FIPS_F_FIPS_RAND_PSEUDO_BYTES 145
#define FIPS_F_FIPS_RAND_SEED 148
#define FIPS_F_FIPS_RAND_SET_METHOD 146
#define FIPS_F_FIPS_RAND_STATUS 147
#define FIPS_F_FIPS_SELFTEST_AES 110
#define FIPS_F_FIPS_SELFTEST_AES_GCM 130
#define FIPS_F_FIPS_SELFTEST_CMAC 139
......@@ -223,6 +235,7 @@ void ERR_load_FIPS_strings(void);
#define FIPS_F_FIPS_SELFTEST_HMAC 113
#define FIPS_F_FIPS_SELFTEST_RNG 114
#define FIPS_F_FIPS_SELFTEST_SHA1 115
#define FIPS_F_FIPS_SELFTEST_X931 149
#define FIPS_F_HASH_FINAL 123
#define FIPS_F_RSA_BUILTIN_KEYGEN 116
#define FIPS_F_RSA_EAY_PRIVATE_DECRYPT 117
......
......@@ -678,9 +678,6 @@ int main(int argc,char **argv)
printf("\tFIPS-mode test application\n\n");
/* Load entropy from external file, if any */
RAND_load_file(".rnd", 1024);
if (argv[1]) {
/* Corrupted KAT tests */
if (!strcmp(argv[1], "aes")) {
......
......@@ -118,6 +118,7 @@ static void fips_algtest_init_nofips(void)
FIPS_drbg_init(ctx, NID_aes_256_ctr, DRBG_FLAG_CTR_USE_DF);
FIPS_drbg_set_callbacks(ctx, dummy_cb, 0, dummy_cb, 0);
FIPS_drbg_instantiate(ctx, dummy_entropy, 10);
FIPS_rand_set_method(FIPS_drbg_method());
}
void fips_algtest_init(void)
......
......@@ -24,10 +24,10 @@ APPS=
LIB=$(TOP)/libcrypto.a
LIBSRC= fips_rand.c fips_rand_selftest.c \
fips_drbg_lib.c fips_drbg_hash.c fips_drbg_ctr.c fips_drbg_selftest.c \
fips_drbg_rand.c
fips_drbg_rand.c fips_rand_lib.c
LIBOBJ= fips_rand.o fips_rand_selftest.o \
fips_drbg_lib.o fips_drbg_hash.o fips_drbg_ctr.o fips_drbg_selftest.o \
fips_drbg_rand.o
fips_drbg_rand.o fips_rand_lib.o
SRC= $(LIBSRC)
......
......@@ -145,28 +145,18 @@ static void fips_drbg_cleanup(void)
static int fips_drbg_seed(const void *seed, int seedlen)
{
DRBG_CTX *dctx = &ossl_dctx;
int rv = 1;
if (dctx->rand_seed_cb)
{
CRYPTO_w_lock(CRYPTO_LOCK_RAND);
rv = dctx->rand_seed_cb(dctx, seed, seedlen);
CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
}
return rv;
return dctx->rand_seed_cb(dctx, seed, seedlen);
return 1;
}
static int fips_drbg_add(const void *seed, int seedlen,
double add_entropy)
{
DRBG_CTX *dctx = &ossl_dctx;
int rv = 1;
if (dctx->rand_add_cb)
{
CRYPTO_w_lock(CRYPTO_LOCK_RAND);
rv = dctx->rand_add_cb(dctx, seed, seedlen, add_entropy);
CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
}
return rv;
return dctx->rand_add_cb(dctx, seed, seedlen, add_entropy);
return 1;
}
static const RAND_METHOD rand_drbg_meth =
......
......@@ -214,7 +214,7 @@ int FIPS_x931_set_dt(unsigned char *dt)
{
if (!sctx.test_mode)
{
RANDerr(RAND_F_FIPS_RAND_SET_DT,RAND_R_NOT_IN_TEST_MODE);
RANDerr(RAND_F_FIPS_X931_SET_DT,RAND_R_NOT_IN_TEST_MODE);
return 0;
}
memcpy(sctx.DT, dt, AES_BLOCK_LENGTH);
......
......@@ -112,6 +112,7 @@ int FIPS_drbg_get_strength(DRBG_CTX *dctx);
DRBG_CTX *FIPS_get_default_drbg(void);
const RAND_METHOD *FIPS_drbg_method(void);
int FIPS_rand_set_method(const RAND_METHOD *meth);
#ifdef __cplusplus
}
......
/* ====================================================================
* Copyright (c) 2011 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* openssl-core@openssl.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#define OPENSSL_FIPSAPI
#include <openssl/crypto.h>
#include <openssl/rand.h>
#include <openssl/err.h>
#include <openssl/fips.h>
#include <openssl/fips_rand.h>
#include "e_os.h"
/* FIPS API for PRNG use. Similar to RAND functionality but without
* ENGINE and additional checking for non-FIPS rand methods.
*/
static const RAND_METHOD *fips_rand_meth = NULL;
static int fips_approved_rand_meth = 0;
int FIPS_rand_set_method(const RAND_METHOD *meth)
{
if (meth == FIPS_drbg_method())
fips_approved_rand_meth = 1;
else if (meth == FIPS_x931_method())
fips_approved_rand_meth = 2;
else
fips_approved_rand_meth = 0;
if (!fips_approved_rand_meth && FIPS_mode())
{
FIPSerr(FIPS_F_FIPS_RAND_SET_METHOD, FIPS_R_NON_FIPS_METHOD);
return 0;
}
fips_rand_meth = meth;
return 1;
}
void FIPS_rand_seed(const void *buf, int num)
{
if (!fips_approved_rand_meth && FIPS_mode())
{
FIPSerr(FIPS_F_FIPS_RAND_SEED, FIPS_R_NON_FIPS_METHOD);
return;
}
if (fips_rand_meth && fips_rand_meth->seed)
fips_rand_meth->seed(buf,num);
}
void FIPS_rand_add(const void *buf, int num, double entropy)
{
if (!fips_approved_rand_meth && FIPS_mode())
{
FIPSerr(FIPS_F_FIPS_RAND_ADD, FIPS_R_NON_FIPS_METHOD);
return;
}
if (fips_rand_meth && fips_rand_meth->add)
fips_rand_meth->add(buf,num,entropy);
}
int FIPS_rand_bytes(unsigned char *buf, int num)
{
if (!fips_approved_rand_meth && FIPS_mode())
{
FIPSerr(FIPS_F_FIPS_RAND_BYTES, FIPS_R_NON_FIPS_METHOD);
return 0;
}
if (fips_rand_meth && fips_rand_meth->bytes)
return fips_rand_meth->bytes(buf,num);
return 0;
}
int FIPS_rand_pseudo_bytes(unsigned char *buf, int num)
{
if (!fips_approved_rand_meth && FIPS_mode())
{
FIPSerr(FIPS_F_FIPS_RAND_PSEUDO_BYTES, FIPS_R_NON_FIPS_METHOD);
return 0;
}
if (fips_rand_meth && fips_rand_meth->pseudorand)
return fips_rand_meth->pseudorand(buf,num);
return -1;
}
int FIPS_rand_status(void)
{
if (!fips_approved_rand_meth && FIPS_mode())
{
FIPSerr(FIPS_F_FIPS_RAND_STATUS, FIPS_R_NON_FIPS_METHOD);
return 0;
}
if (fips_rand_meth && fips_rand_meth->status)
return fips_rand_meth->status();
return 0;
}
......@@ -356,14 +356,14 @@ int FIPS_selftest_x931()
FIPS_x931_reset();
if (!FIPS_x931_test_mode())
{
FIPSerr(FIPS_F_FIPS_SELFTEST_RNG,FIPS_R_SELFTEST_FAILED);
FIPSerr(FIPS_F_FIPS_SELFTEST_X931,FIPS_R_SELFTEST_FAILED);
return 0;
}
if (!fips_x931_test(aes_128_key,aes_128_tv)
|| !fips_x931_test(aes_192_key, aes_192_tv)
|| !fips_x931_test(aes_256_key, aes_256_tv))
{
FIPSerr(FIPS_F_FIPS_SELFTEST_RNG,FIPS_R_SELFTEST_FAILED);
FIPSerr(FIPS_F_FIPS_SELFTEST_X931,FIPS_R_SELFTEST_FAILED);
return 0;
}
FIPS_x931_reset();
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册