From: Dr. Stephen Henson Date: Sun, 1 Jul 2007 00:07:25 +0000 (+0000) Subject: Move minimal EVP_CIPHER implementation into FIPS library. Not used by X-Git-Tag: FIPS_098_TEST_1~7 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=49fa74385dd6c4a7a1ca3a23cd2ca962373ab891;p=oweals%2Fopenssl.git Move minimal EVP_CIPHER implementation into FIPS library. Not used by any FIPS applications yet. --- diff --git a/CHANGES b/CHANGES index 85469a6195..0130bfcdb5 100644 --- a/CHANGES +++ b/CHANGES @@ -4,6 +4,10 @@ Changes between 0.9.8e and 0.9.8f-fips [xx XXX xxxx] + *) Move EVP cipher code into enc_min.c to support a minimal implementation + for use by FIPS applications. + [Steve Henson] + *) Add algorithm config module. Currently just handles setting FIPS mode. [Steve Henson] diff --git a/Makefile.org b/Makefile.org index b39e42bf18..3751c1d897 100644 --- a/Makefile.org +++ b/Makefile.org @@ -298,6 +298,7 @@ FIPS_EX_OBJ= ../crypto/aes/aes_cbc.o \ ../crypto/dsa/dsa_vrf.o \ ../crypto/err/err.o \ ../crypto/evp/digest.o \ + ../crypto/evp/enc_min.o \ ../crypto/evp/p_sign.o \ ../crypto/evp/p_verify.o \ ../crypto/mem_clr.o \ diff --git a/crypto/evp/Makefile b/crypto/evp/Makefile index 8167efa5e4..0ff4162969 100644 --- a/crypto/evp/Makefile +++ b/crypto/evp/Makefile @@ -21,7 +21,7 @@ LIB=$(TOP)/libcrypto.a LIBSRC= encode.c digest.c dig_eng.c evp_enc.c evp_key.c evp_acnf.c evp_cnf.c \ e_des.c e_bf.c e_idea.c e_des3.c e_camellia.c\ e_rc4.c e_aes.c names.c e_seed.c \ - e_xcbc_d.c e_rc2.c e_cast.c e_rc5.c \ + e_xcbc_d.c e_rc2.c e_cast.c e_rc5.c enc_min.c \ m_null.c m_md2.c m_md4.c m_md5.c m_sha.c m_sha1.c \ m_dss.c m_dss1.c m_mdc2.c m_ripemd.c m_ecdsa.c\ p_open.c p_seal.c p_sign.c p_verify.c p_lib.c p_enc.c p_dec.c \ @@ -33,7 +33,7 @@ LIBSRC= encode.c digest.c dig_eng.c evp_enc.c evp_key.c evp_acnf.c evp_cnf.c \ LIBOBJ= encode.o digest.o dig_eng.o evp_enc.o evp_key.o evp_acnf.o evp_cnf.o \ e_des.o e_bf.o e_idea.o e_des3.o e_camellia.o\ e_rc4.o e_aes.o names.o e_seed.o \ - e_xcbc_d.o e_rc2.o e_cast.o e_rc5.o \ + e_xcbc_d.o e_rc2.o e_cast.o e_rc5.o enc_min.o \ m_null.o m_md2.o m_md4.o m_md5.o m_sha.o m_sha1.o \ m_dss.o m_dss1.o m_mdc2.o m_ripemd.o m_ecdsa.o\ p_open.o p_seal.o p_sign.o p_verify.o p_lib.o p_enc.o p_dec.o \ diff --git a/crypto/evp/dig_eng.c b/crypto/evp/dig_eng.c index 31e3044502..159b2f7c3c 100644 --- a/crypto/evp/dig_eng.c +++ b/crypto/evp/dig_eng.c @@ -122,9 +122,9 @@ #ifdef OPENSSL_FIPS -static int do_evp_md_engine_full(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl) +static int do_evp_md_engine_full(EVP_MD_CTX *ctx, const EVP_MD **ptype, ENGINE *impl) { - if (type) + if (*ptype) { /* Ensure an ENGINE left lying around from last time is cleared * (the previous check attempted to avoid this if the same @@ -141,11 +141,11 @@ static int do_evp_md_engine_full(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *im } else /* Ask if an ENGINE is reserved for this job */ - impl = ENGINE_get_digest_engine(type->type); + impl = ENGINE_get_digest_engine((*ptype)->type); if(impl) { /* There's an ENGINE for this job ... (apparently) */ - const EVP_MD *d = ENGINE_get_digest(impl, type->type); + const EVP_MD *d = ENGINE_get_digest(impl, (*ptype)->type); if(!d) { /* Same comment from evp_enc.c */ @@ -153,7 +153,7 @@ static int do_evp_md_engine_full(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *im return 0; } /* We'll use the ENGINE's private digest definition */ - type = d; + *ptype = d; /* Store the ENGINE functional reference so we know * 'type' came from an ENGINE and we need to release * it when done. */ diff --git a/crypto/evp/digest.c b/crypto/evp/digest.c index b58c25d265..9c1a8adf0c 100644 --- a/crypto/evp/digest.c +++ b/crypto/evp/digest.c @@ -171,11 +171,13 @@ static const EVP_MD bad_md = #endif +#ifndef OPENSSL_NO_ENGINE + #ifdef OPENSSL_FIPS static int do_engine_null(ENGINE *impl) { return 0;} static int do_evp_md_engine_null(EVP_MD_CTX *ctx, - const EVP_MD *type, ENGINE *impl) + const EVP_MD **ptype, ENGINE *impl) { return 1; } static int (*do_engine_init)(ENGINE *impl) @@ -185,14 +187,14 @@ static int (*do_engine_finish)(ENGINE *impl) = do_engine_null; static int (*do_evp_md_engine) - (EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl) + (EVP_MD_CTX *ctx, const EVP_MD **ptype, ENGINE *impl) = do_evp_md_engine_null; void int_EVP_MD_set_engine_callbacks( int (*eng_md_init)(ENGINE *impl), int (*eng_md_fin)(ENGINE *impl), int (*eng_md_evp) - (EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl)) + (EVP_MD_CTX *ctx, const EVP_MD **ptype, ENGINE *impl)) { do_engine_init = eng_md_init; do_engine_finish = eng_md_fin; @@ -204,9 +206,9 @@ void int_EVP_MD_set_engine_callbacks( #define do_engine_init ENGINE_init #define do_engine_finish ENGINE_finish -static int do_evp_md_engine(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl) +static int do_evp_md_engine(EVP_MD_CTX *ctx, const EVP_MD **ptype, ENGINE *impl) { - if (type) + if (*ptype) { /* Ensure an ENGINE left lying around from last time is cleared * (the previous check attempted to avoid this if the same @@ -223,11 +225,11 @@ static int do_evp_md_engine(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl) } else /* Ask if an ENGINE is reserved for this job */ - impl = ENGINE_get_digest_engine(type->type); + impl = ENGINE_get_digest_engine((*ptype)->type); if(impl) { /* There's an ENGINE for this job ... (apparently) */ - const EVP_MD *d = ENGINE_get_digest(impl, type->type); + const EVP_MD *d = ENGINE_get_digest(impl, (*ptype)->type); if(!d) { /* Same comment from evp_enc.c */ @@ -235,7 +237,7 @@ static int do_evp_md_engine(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl) return 0; } /* We'll use the ENGINE's private digest definition */ - type = d; + *ptype = d; /* Store the ENGINE functional reference so we know * 'type' came from an ENGINE and we need to release * it when done. */ @@ -255,6 +257,8 @@ static int do_evp_md_engine(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl) #endif +#endif + int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl) { M_EVP_MD_CTX_clear_flags(ctx,EVP_MD_CTX_FLAG_CLEANED); @@ -266,7 +270,7 @@ int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl) if (ctx->engine && ctx->digest && (!type || (type && (type->type == ctx->digest->type)))) goto skip_to_init; - if (!do_evp_md_engine(ctx, type, impl)) + if (!do_evp_md_engine(ctx, &type, impl)) return 0; #endif if (ctx->digest != type) diff --git a/crypto/evp/evp.h b/crypto/evp/evp.h index f0a82731c6..7c5184d536 100644 --- a/crypto/evp/evp.h +++ b/crypto/evp/evp.h @@ -929,8 +929,13 @@ void int_EVP_MD_set_engine_callbacks( int (*eng_md_init)(ENGINE *impl), int (*eng_md_fin)(ENGINE *impl), int (*eng_md_evp) - (EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl)); + (EVP_MD_CTX *ctx, const EVP_MD **ptype, ENGINE *impl)); void int_EVP_MD_init_engine_callbacks(void); +void int_EVP_CIPHER_set_engine_callbacks( + int (*eng_ciph_fin)(ENGINE *impl), + int (*eng_ciph_evp) + (EVP_CIPHER_CTX *ctx, const EVP_CIPHER **pciph, ENGINE *impl)); +void int_EVP_CIPHER_init_engine_callbacks(void); #endif #endif diff --git a/crypto/evp/evp_enc.c b/crypto/evp/evp_enc.c index 1e83377ff7..b685a5e99e 100644 --- a/crypto/evp/evp_enc.c +++ b/crypto/evp/evp_enc.c @@ -68,12 +68,6 @@ const char EVP_version[]="EVP" OPENSSL_VERSION_PTEXT; -void EVP_CIPHER_CTX_init(EVP_CIPHER_CTX *ctx) - { - memset(ctx,0,sizeof(EVP_CIPHER_CTX)); - /* ctx->cipher=NULL; */ - } - EVP_CIPHER_CTX *EVP_CIPHER_CTX_new(void) { EVP_CIPHER_CTX *ctx=OPENSSL_malloc(sizeof *ctx); @@ -90,204 +84,6 @@ int EVP_CipherInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, return EVP_CipherInit_ex(ctx,cipher,NULL,key,iv,enc); } -#ifdef OPENSSL_FIPS - -/* The purpose of these is to trap programs that attempt to use non FIPS - * algorithms in FIPS mode and ignore the errors. - */ - -int bad_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, - const unsigned char *iv, int enc) - { FIPS_ERROR_IGNORED("Cipher init"); return 0;} - -int bad_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, - const unsigned char *in, unsigned int inl) - { FIPS_ERROR_IGNORED("Cipher update"); return 0;} - -/* NB: no cleanup because it is allowed after failed init */ - -int bad_set_asn1(EVP_CIPHER_CTX *ctx, ASN1_TYPE *typ) - { FIPS_ERROR_IGNORED("Cipher set_asn1"); return 0;} -int bad_get_asn1(EVP_CIPHER_CTX *ctx, ASN1_TYPE *typ) - { FIPS_ERROR_IGNORED("Cipher get_asn1"); return 0;} -int bad_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr) - { FIPS_ERROR_IGNORED("Cipher ctrl"); return 0;} - -static const EVP_CIPHER bad_cipher = - { - 0, - 0, - 0, - 0, - 0, - bad_init, - bad_do_cipher, - NULL, - 0, - bad_set_asn1, - bad_get_asn1, - bad_ctrl, - NULL - }; - -#endif - -int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, ENGINE *impl, - const unsigned char *key, const unsigned char *iv, int enc) - { - if (enc == -1) - enc = ctx->encrypt; - else - { - if (enc) - enc = 1; - ctx->encrypt = enc; - } -#ifndef OPENSSL_NO_ENGINE - /* Whether it's nice or not, "Inits" can be used on "Final"'d contexts - * so this context may already have an ENGINE! Try to avoid releasing - * the previous handle, re-querying for an ENGINE, and having a - * reinitialisation, when it may all be unecessary. */ - if (ctx->engine && ctx->cipher && (!cipher || - (cipher && (cipher->nid == ctx->cipher->nid)))) - goto skip_to_init; -#endif - if (cipher) - { - /* Ensure a context left lying around from last time is cleared - * (the previous check attempted to avoid this if the same - * ENGINE and EVP_CIPHER could be used). */ - EVP_CIPHER_CTX_cleanup(ctx); - - /* Restore encrypt field: it is zeroed by cleanup */ - ctx->encrypt = enc; -#ifndef OPENSSL_NO_ENGINE - if(impl) - { - if (!ENGINE_init(impl)) - { - EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_INITIALIZATION_ERROR); - return 0; - } - } - else - /* Ask if an ENGINE is reserved for this job */ - impl = ENGINE_get_cipher_engine(cipher->nid); - if(impl) - { - /* There's an ENGINE for this job ... (apparently) */ - const EVP_CIPHER *c = ENGINE_get_cipher(impl, cipher->nid); - if(!c) - { - /* One positive side-effect of US's export - * control history, is that we should at least - * be able to avoid using US mispellings of - * "initialisation"? */ - EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_INITIALIZATION_ERROR); - return 0; - } - /* We'll use the ENGINE's private cipher definition */ - cipher = c; - /* Store the ENGINE functional reference so we know - * 'cipher' came from an ENGINE and we need to release - * it when done. */ - ctx->engine = impl; - } - else - ctx->engine = NULL; -#endif - - ctx->cipher=cipher; - if (ctx->cipher->ctx_size) - { - ctx->cipher_data=OPENSSL_malloc(ctx->cipher->ctx_size); - if (!ctx->cipher_data) - { - EVPerr(EVP_F_EVP_CIPHERINIT_EX, ERR_R_MALLOC_FAILURE); - return 0; - } - } - else - { - ctx->cipher_data = NULL; - } - ctx->key_len = cipher->key_len; - ctx->flags = 0; - if(ctx->cipher->flags & EVP_CIPH_CTRL_INIT) - { - if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_INIT, 0, NULL)) - { - EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_INITIALIZATION_ERROR); - return 0; - } - } - } - else if(!ctx->cipher) - { - EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_NO_CIPHER_SET); - return 0; - } -#ifndef OPENSSL_NO_ENGINE -skip_to_init: -#endif - /* we assume block size is a power of 2 in *cryptUpdate */ - OPENSSL_assert(ctx->cipher->block_size == 1 - || ctx->cipher->block_size == 8 - || ctx->cipher->block_size == 16); - - if(!(EVP_CIPHER_CTX_flags(ctx) & EVP_CIPH_CUSTOM_IV)) { - switch(EVP_CIPHER_CTX_mode(ctx)) { - - case EVP_CIPH_STREAM_CIPHER: - case EVP_CIPH_ECB_MODE: - break; - - case EVP_CIPH_CFB_MODE: - case EVP_CIPH_OFB_MODE: - - ctx->num = 0; - - case EVP_CIPH_CBC_MODE: - - OPENSSL_assert(EVP_CIPHER_CTX_iv_length(ctx) <= - (int)sizeof(ctx->iv)); - if(iv) memcpy(ctx->oiv, iv, EVP_CIPHER_CTX_iv_length(ctx)); - memcpy(ctx->iv, ctx->oiv, EVP_CIPHER_CTX_iv_length(ctx)); - break; - - default: - return 0; - break; - } - } - -#ifdef OPENSSL_FIPS - /* After 'key' is set no further parameters changes are permissible. - * So only check for non FIPS enabling at this point. - */ - if (key && FIPS_mode()) - { - if (!(ctx->cipher->flags & EVP_CIPH_FLAG_FIPS) - & !(ctx->flags & EVP_CIPH_FLAG_NON_FIPS_ALLOW)) - { - EVPerr(EVP_F_EVP_CIPHERINIT, EVP_R_DISABLED_FOR_FIPS); - ERR_add_error_data(2, "cipher=", - EVP_CIPHER_name(ctx->cipher)); - ctx->cipher = &bad_cipher; - return 0; - } - } -#endif - - if(key || (ctx->cipher->flags & EVP_CIPH_ALWAYS_CALL_INIT)) { - if(!ctx->cipher->init(ctx,key,iv,enc)) return 0; - } - ctx->buf_len=0; - ctx->final_used=0; - ctx->block_mask=ctx->cipher->block_size-1; - return 1; - } - int EVP_CipherUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, const unsigned char *in, int inl) { @@ -548,28 +344,6 @@ void EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *ctx) } } -int EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *c) - { - if (c->cipher != NULL) - { - if(c->cipher->cleanup && !c->cipher->cleanup(c)) - return 0; - /* Cleanse cipher context data */ - if (c->cipher_data) - OPENSSL_cleanse(c->cipher_data, c->cipher->ctx_size); - } - if (c->cipher_data) - OPENSSL_free(c->cipher_data); -#ifndef OPENSSL_NO_ENGINE - if (c->engine) - /* The EVP_CIPHER we used belongs to an ENGINE, release the - * functional reference we held for this reason. */ - ENGINE_finish(c->engine); -#endif - memset(c,0,sizeof(EVP_CIPHER_CTX)); - return 1; - } - int EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *c, int keylen) { if(c->cipher->flags & EVP_CIPH_CUSTOM_KEY_LENGTH) @@ -591,27 +365,6 @@ int EVP_CIPHER_CTX_set_padding(EVP_CIPHER_CTX *ctx, int pad) return 1; } -int EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr) -{ - int ret; - if(!ctx->cipher) { - EVPerr(EVP_F_EVP_CIPHER_CTX_CTRL, EVP_R_NO_CIPHER_SET); - return 0; - } - - if(!ctx->cipher->ctrl) { - EVPerr(EVP_F_EVP_CIPHER_CTX_CTRL, EVP_R_CTRL_NOT_IMPLEMENTED); - return 0; - } - - ret = ctx->cipher->ctrl(ctx, type, arg, ptr); - if(ret == -1) { - EVPerr(EVP_F_EVP_CIPHER_CTX_CTRL, EVP_R_CTRL_OPERATION_NOT_IMPLEMENTED); - return 0; - } - return ret; -} - int EVP_CIPHER_CTX_rand_key(EVP_CIPHER_CTX *ctx, unsigned char *key) { if (ctx->cipher->flags & EVP_CIPH_RAND_KEY) @@ -621,3 +374,54 @@ int EVP_CIPHER_CTX_rand_key(EVP_CIPHER_CTX *ctx, unsigned char *key) return 1; } +#ifndef OPENSSL_NO_ENGINE + +#ifdef OPENSSL_FIPS + +static int do_evp_enc_engine_full(EVP_CIPHER_CTX *ctx, const EVP_CIPHER **pcipher, ENGINE *impl) + { + if(impl) + { + if (!ENGINE_init(impl)) + { + EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_INITIALIZATION_ERROR); + return 0; + } + } + else + /* Ask if an ENGINE is reserved for this job */ + impl = ENGINE_get_cipher_engine((*pcipher)->nid); + if(impl) + { + /* There's an ENGINE for this job ... (apparently) */ + const EVP_CIPHER *c = ENGINE_get_cipher(impl, (*pcipher)->nid); + if(!c) + { + /* One positive side-effect of US's export + * control history, is that we should at least + * be able to avoid using US mispellings of + * "initialisation"? */ + EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_INITIALIZATION_ERROR); + return 0; + } + /* We'll use the ENGINE's private cipher definition */ + *pcipher = c; + /* Store the ENGINE functional reference so we know + * 'cipher' came from an ENGINE and we need to release + * it when done. */ + ctx->engine = impl; + } + else + ctx->engine = NULL; + return 1; + } + +void int_EVP_CIPHER_init_engine_callbacks(void) + { + int_EVP_CIPHER_set_engine_callbacks( + ENGINE_finish, do_evp_enc_engine_full); + } + +#endif + +#endif diff --git a/crypto/evp/evp_lib.c b/crypto/evp/evp_lib.c index f8b6342694..a5f6eee352 100644 --- a/crypto/evp/evp_lib.c +++ b/crypto/evp/evp_lib.c @@ -178,11 +178,6 @@ int EVP_CIPHER_CTX_block_size(const EVP_CIPHER_CTX *ctx) return ctx->cipher->block_size; } -int EVP_Cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, unsigned int inl) - { - return ctx->cipher->do_cipher(ctx,out,in,inl); - } - const EVP_CIPHER *EVP_CIPHER_CTX_cipher(const EVP_CIPHER_CTX *ctx) { return ctx->cipher; @@ -193,11 +188,6 @@ unsigned long EVP_CIPHER_flags(const EVP_CIPHER *cipher) return cipher->flags; } -unsigned long EVP_CIPHER_CTX_flags(const EVP_CIPHER_CTX *ctx) - { - return ctx->cipher->flags; - } - void *EVP_CIPHER_CTX_get_app_data(const EVP_CIPHER_CTX *ctx) { return ctx->app_data; @@ -213,11 +203,6 @@ int EVP_CIPHER_iv_length(const EVP_CIPHER *cipher) return cipher->iv_len; } -int EVP_CIPHER_CTX_iv_length(const EVP_CIPHER_CTX *ctx) - { - return ctx->cipher->iv_len; - } - int EVP_CIPHER_key_length(const EVP_CIPHER *cipher) { return cipher->key_len; @@ -228,11 +213,6 @@ int EVP_CIPHER_CTX_key_length(const EVP_CIPHER_CTX *ctx) return ctx->key_len; } -int EVP_CIPHER_nid(const EVP_CIPHER *cipher) - { - return cipher->nid; - } - int EVP_CIPHER_CTX_nid(const EVP_CIPHER_CTX *ctx) { return ctx->cipher->nid; diff --git a/crypto/o_init.c b/crypto/o_init.c index a15244aaae..db496dfaf7 100644 --- a/crypto/o_init.c +++ b/crypto/o_init.c @@ -75,6 +75,7 @@ void OPENSSL_init(void) #endif #ifdef OPENSSL_ENGINE int_EVP_MD_init_engine_callbacks(); + int_EVP_CIPHER_init_engine_callbacks(); int_RAND_init_engine_callbacks(); #endif done = 1; diff --git a/fips-1.0/fips.c b/fips-1.0/fips.c index f75ea4661f..f524bf1eb8 100644 --- a/fips-1.0/fips.c +++ b/fips-1.0/fips.c @@ -134,6 +134,19 @@ int FIPS_selftest_failed(void) return ret; } +/* Selftest failure fatal exit routine. This will be called + * during *any* cryptographic operation. It has the minimum + * overhead possible to avoid too big a performance hit. + */ + +void FIPS_selftest_check(void) + { + if (fips_selftest_fail) + { + OpenSSLDie(__FILE__,__LINE__, "FATAL FIPS SELFTEST FAILURE"); + } + } + int FIPS_selftest() { diff --git a/fips-1.0/fips.h b/fips-1.0/fips.h index a59629e362..d77ff3a32d 100644 --- a/fips-1.0/fips.h +++ b/fips-1.0/fips.h @@ -63,6 +63,7 @@ int FIPS_mode_set(int onoff); int FIPS_mode(void); const void *FIPS_rand_check(void); int FIPS_selftest_failed(void); +void FIPS_selftest_check(void); void FIPS_corrupt_sha1(void); int FIPS_selftest_sha1(void); void FIPS_corrupt_aes(void);