From a5ad942b707009522555cabec147092e8b88e71c Mon Sep 17 00:00:00 2001 From: Ben Laurie Date: Tue, 17 Feb 2004 11:51:54 +0000 Subject: [PATCH] Improve selftests, check for stuck PRNG(!). --- crypto/rand/rand.h | 1 + crypto/rand/rand_err.c | 3 +- fips/aes/fingerprint.sha1 | 2 +- fips/aes/fips_aes_selftest.c | 15 ++++++++++ fips/des/fingerprint.sha1 | 2 +- fips/des/fips_des_selftest.c | 56 ++++++++++++++++++++++++++++++++++++ fips/rand/fingerprint.sha1 | 2 +- fips/rand/fips_rand.c | 17 +++++++++-- fips/rand/fips_randtest.c | 26 +++++++++++------ fips/rsa/fingerprint.sha1 | 2 +- fips/rsa/fips_rsa_selftest.c | 13 +++++++++ 11 files changed, 123 insertions(+), 16 deletions(-) diff --git a/crypto/rand/rand.h b/crypto/rand/rand.h index 4b998000c8..b22dd613fb 100644 --- a/crypto/rand/rand.h +++ b/crypto/rand/rand.h @@ -128,6 +128,7 @@ void ERR_load_RAND_strings(void); /* Reason codes. */ #define RAND_R_NON_FIPS_METHOD 101 #define RAND_R_PRNG_NOT_SEEDED 100 +#define RAND_R_PRNG_STUCK 102 #ifdef __cplusplus } diff --git a/crypto/rand/rand_err.c b/crypto/rand/rand_err.c index 774ed4df86..b808309496 100644 --- a/crypto/rand/rand_err.c +++ b/crypto/rand/rand_err.c @@ -1,6 +1,6 @@ /* crypto/rand/rand_err.c */ /* ==================================================================== - * Copyright (c) 1999-2002 The OpenSSL Project. All rights reserved. + * Copyright (c) 1999-2003 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 @@ -76,6 +76,7 @@ static ERR_STRING_DATA RAND_str_reasons[]= { {RAND_R_NON_FIPS_METHOD ,"non fips method"}, {RAND_R_PRNG_NOT_SEEDED ,"PRNG not seeded"}, +{RAND_R_PRNG_STUCK ,"prng stuck"}, {0,NULL} }; diff --git a/fips/aes/fingerprint.sha1 b/fips/aes/fingerprint.sha1 index 4d922bd411..60ebbb010d 100644 --- a/fips/aes/fingerprint.sha1 +++ b/fips/aes/fingerprint.sha1 @@ -1,3 +1,3 @@ SHA1(fips_aes_core.c)= 4cad001926dce3593181541ea19207256593171a -SHA1(fips_aes_selftest.c)= b41f520aa90f813de815ee77ade4e7c73ef147b0 +SHA1(fips_aes_selftest.c)= 8f270e559d34a18b3771d7f0098b77dd7bf168c5 SHA1(fips_aes_locl.h)= a3c01d9a4f9d5211e9e785852f6f1a2febfd73b6 diff --git a/fips/aes/fips_aes_selftest.c b/fips/aes/fips_aes_selftest.c index 8d3e9c212f..d47004c171 100644 --- a/fips/aes/fips_aes_selftest.c +++ b/fips/aes/fips_aes_selftest.c @@ -74,6 +74,7 @@ int FIPS_selftest_aes() { int n; + /* Encrypt and check against known ciphertext */ for(n=0 ; n < 1 ; ++n) { AES_KEY key; @@ -87,6 +88,20 @@ int FIPS_selftest_aes() return 0; } } + /* Decrypt and check against known plaintext */ + for(n=0 ; n < 1 ; ++n) + { + AES_KEY key; + unsigned char buf[16]; + + AES_set_decrypt_key(tests[n].key,128,&key); + AES_decrypt(tests[n].ciphertext,buf,&key); + if(memcmp(buf,tests[n].plaintext,sizeof buf)) + { + FIPSerr(FIPS_F_FIPS_SELFTEST_AES,FIPS_R_SELFTEST_FAILED); + return 0; + } + } return 1; } #endif diff --git a/fips/des/fingerprint.sha1 b/fips/des/fingerprint.sha1 index 39a849a6aa..043639e3a9 100644 --- a/fips/des/fingerprint.sha1 +++ b/fips/des/fingerprint.sha1 @@ -1,4 +1,4 @@ SHA1(fips_des_enc.c)= 41388beadcafe125a8025968ff91b7dc60b96c49 -SHA1(fips_des_selftest.c)= d81ee4db762d89cca749138a99100d342f195665 +SHA1(fips_des_selftest.c)= 1236ecc25bcbd5ad6af8c396426d6c7783cfe941 SHA1(fips_set_key.c)= 1e3dc1e0d02f0ab4d8fdd5e1f4db284cad1510f4 SHA1(fips_des_locl.h)= a4cf60ca32476a2483b3e4460ec9a19c0444fd20 diff --git a/fips/des/fips_des_selftest.c b/fips/des/fips_des_selftest.c index bb1966c8fb..79943af9e0 100644 --- a/fips/des/fips_des_selftest.c +++ b/fips/des/fips_des_selftest.c @@ -73,10 +73,36 @@ static struct }, }; +static struct + { + DES_cblock key1; + DES_cblock key2; + DES_cblock key3; + unsigned char plaintext[8]; + unsigned char ciphertext[8]; + } tests3[]= + { + { + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + { 0xFE,0xDC,0xBA,0x98,0x76,0x54,0x32,0x10 }, + { 0x12,0x34,0x56,0x78,0x9a,0xbc,0xde,0xf0 }, + { 0x8f,0x8f,0xbf,0x9b,0x5d,0x48,0xb4,0x1c}, + { 0x59,0x8c,0xe5,0xd3,0x6c,0xa2,0xea,0x1b}, + }, + { + { 0xDC,0xBA,0x98,0x76,0x54,0x32,0x10,0xFE }, + { 0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF }, + { 0xED,0x39,0xD9,0x50,0xFA,0x74,0xBC,0xC4 }, + { 0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF }, + { 0x11,0x25,0xb0,0x35,0xbe,0xa0,0x82,0x86 }, + }, + }; + int FIPS_selftest_des() { int n; + /* Encrypt/decrypt with DES and compare to known answers */ for(n=0 ; n < 2 ; ++n) { DES_key_schedule key; @@ -89,7 +115,37 @@ int FIPS_selftest_des() FIPSerr(FIPS_F_FIPS_SELFTEST_DES,FIPS_R_SELFTEST_FAILED); return 0; } + DES_ecb_encrypt(&tests[n].ciphertext,&buf,&key,0); + if(memcmp(buf,tests[n].plaintext,sizeof buf)) + { + FIPSerr(FIPS_F_FIPS_SELFTEST_DES,FIPS_R_SELFTEST_FAILED); + return 0; + } + } + + /* Encrypt/decrypt with 3DES and compare to known answers */ + for(n=0 ; n < 2 ; ++n) + { + DES_key_schedule key1, key2, key3; + unsigned char buf[8]; + + DES_set_key(&tests3[n].key1,&key1); + DES_set_key(&tests3[n].key2,&key2); + DES_set_key(&tests3[n].key3,&key3); + DES_ecb3_encrypt(tests3[n].plaintext,buf,&key1,&key2,&key3,1); + if(memcmp(buf,tests3[n].ciphertext,sizeof buf)) + { + FIPSerr(FIPS_F_FIPS_SELFTEST_DES,FIPS_R_SELFTEST_FAILED); + return 0; + } + DES_ecb3_encrypt(tests3[n].ciphertext,buf,&key1,&key2,&key3,0); + if(memcmp(buf,tests3[n].plaintext,sizeof buf)) + { + FIPSerr(FIPS_F_FIPS_SELFTEST_DES,FIPS_R_SELFTEST_FAILED); + return 0; + } } + return 1; } #endif diff --git a/fips/rand/fingerprint.sha1 b/fips/rand/fingerprint.sha1 index 861588229c..ffb57a6cc4 100644 --- a/fips/rand/fingerprint.sha1 +++ b/fips/rand/fingerprint.sha1 @@ -1,2 +1,2 @@ -SHA1(fips_rand.c)= 2c86af552515bd1f58b3011d1958ea975afaa816 +SHA1(fips_rand.c)= af88aebd4897e9d2ef593969b50f80c2cdf120d9 SHA1(fips_rand.h)= da5ee76588070c97d47c939d069d250a1476a080 diff --git a/fips/rand/fips_rand.c b/fips/rand/fips_rand.c index 0ddbff6b10..f0d31f6b90 100644 --- a/fips/rand/fips_rand.c +++ b/fips/rand/fips_rand.c @@ -93,11 +93,14 @@ RAND_METHOD rand_fips_meth= fips_rand_status }; +static int second; + void FIPS_set_prng_key(const unsigned char k1[8],const unsigned char k2[8]) { memcpy(&key1,k1,sizeof key1); memcpy(&key2,k2,sizeof key2); key_set=1; + second=0; } void FIPS_test_mode(int test,const unsigned char faketime[8]) @@ -115,9 +118,6 @@ int FIPS_rand_seeded() static void fips_gettime(unsigned char buf[8]) { struct timeval tv; -#ifndef GETPID_IS_MEANINGLESS - long pid; -#endif if(test_mode) { @@ -130,6 +130,7 @@ static void fips_gettime(unsigned char buf[8]) memcpy (&buf[0],&tv.tv_sec,4); memcpy (&buf[4],&tv.tv_usec,4); +#if 0 /* This eminently sensible strategy is not acceptable to NIST. Sigh. */ #ifndef GETPID_IS_MEANINGLESS /* we mix in the PID to ensure that after a fork the children don't give * the same results as each other @@ -139,6 +140,7 @@ static void fips_gettime(unsigned char buf[8]) if((pid&0xffff0000) == 0) pid<<=16; *(long *)&buf[0]^=pid; +#endif #endif } @@ -204,6 +206,7 @@ static int fips_rand_bytes(unsigned char *buf,int num) unsigned char timeseed[8]; unsigned char intermediate[SEED_SIZE]; unsigned char output[SEED_SIZE]; + static unsigned char previous[SEED_SIZE]; if(n_seed < sizeof seed) { @@ -229,6 +232,14 @@ static int fips_rand_bytes(unsigned char *buf,int num) t[l]=output[l]^seed[l]; fips_rand_encrypt(seed,t); + if(second && !memcmp(output,previous,sizeof previous)) + { + RANDerr(RAND_F_FIPS_RAND_BYTES,RAND_R_PRNG_STUCK); + return 0; + } + memcpy(previous,output,sizeof previous); + second=1; + l=SEED_SIZE < num-n ? SEED_SIZE : num-n; memcpy(buf+n,output,l); n+=l; diff --git a/fips/rand/fips_randtest.c b/fips/rand/fips_randtest.c index fa9185010d..3e2f58e16d 100644 --- a/fips/rand/fips_randtest.c +++ b/fips/rand/fips_randtest.c @@ -107,6 +107,7 @@ #include #include #include +#include #include "e_os.h" @@ -138,13 +139,13 @@ typedef struct /* FIXME: these test vectors are made up! */ static PRNGtest t1= { - { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, - { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + { { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07 }, + { 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f }, }, { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, - { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, - { 0x8c,0xa6,0x4d,0xe9,0xc1,0xb1,0x23,0xa7 } + { 0x33,0xc3,0xdf,0xfe,0x60,0x60,0x49,0x9e }, + { 0x40,0x08,0x95,0x4d,0xb1,0x82,0x98,0x86 } }; static PRNGtest t2= { @@ -152,8 +153,8 @@ static PRNGtest t2= { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff } }, { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff }, { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff }, - { 0xcd,0x57,0xcb,0xfa,0x08,0xd8,0xdb,0x3a }, - { 0x05,0xad,0x17,0xbd,0xd8,0x32,0x96,0x79 } + { 0x65,0xf1,0xa4,0x07,0x42,0x38,0xd5,0x25 }, + { 0x99,0xba,0x8f,0xd2,0x88,0xad,0xf8,0x34 } }; static void dump(const unsigned char *b,int n) @@ -190,10 +191,18 @@ static void run_test(const PRNGtest *t) FIPS_test_mode(1,t->time); RAND_seed(t->seed,sizeof t->seed); - RAND_bytes(buf,8); + if(RAND_bytes(buf,8) != 8) + { + ERR_print_errors_fp(stderr); + exit(2); + } compare(buf,t->block1,8); for(n=0 ; n < 99 ; ++n) - RAND_bytes(buf,8); + if(RAND_bytes(buf,8) != 8) + { + ERR_print_errors_fp(stderr); + exit(2); + } compare(buf,t->block100,8); FIPS_test_mode(0,NULL); } @@ -208,6 +217,7 @@ int main() /*double d; */ long d; + ERR_load_crypto_strings(); RAND_set_rand_method(&rand_fips_meth); run_test(&t1); diff --git a/fips/rsa/fingerprint.sha1 b/fips/rsa/fingerprint.sha1 index d36c6be9f9..e03de116ba 100644 --- a/fips/rsa/fingerprint.sha1 +++ b/fips/rsa/fingerprint.sha1 @@ -1,3 +1,3 @@ SHA1(fips_rsa_eay.c)= eacbcc656f1f046509abb9cc0207880b58ae8b90 SHA1(fips_rsa_gen.c)= bfc4d7204f714a354a2e652318c5e82518441427 -SHA1(fips_rsa_selftest.c)= f0a9683b29b3e231067f840424727413e811cbfc +SHA1(fips_rsa_selftest.c)= 0106c4c565833ad2c8975b7d38765038a58f037c diff --git a/fips/rsa/fips_rsa_selftest.c b/fips/rsa/fips_rsa_selftest.c index 12e71b4972..b055d6be26 100644 --- a/fips/rsa/fips_rsa_selftest.c +++ b/fips/rsa/fips_rsa_selftest.c @@ -156,8 +156,13 @@ int FIPS_selftest_rsa() "\xef\x12\x34\x56\x78\x9a\xbc\xde\xf0\x12\x34\x56\x78\x9a\xbc\xde"; int n; + /* Perform pairwise consistency test by: ... */ + key=RSA_new(); clen=setrsakey(key,expected_ctext); + /* ...1) apply public key to plaintext, resulting ciphertext must be + * different + */ n=RSA_public_encrypt(sizeof(original_ptext)-1,original_ptext,ctext,key, RSA_NO_PADDING); if(n < 0) @@ -170,6 +175,14 @@ int FIPS_selftest_rsa() FIPSerr(FIPS_F_FIPS_SELFTEST_RSA,FIPS_R_SELFTEST_FAILED); return 0; } + if(!memcmp(ctext,original_ptext,n)) + { + FIPSerr(FIPS_F_FIPS_SELFTEST_RSA,FIPS_R_SELFTEST_FAILED); + return 0; + } + /* ...2) apply private key to ciphertext and compare result to + * original plaintext; results must be equal + */ n=RSA_private_decrypt(n,ctext,ptext,key,RSA_NO_PADDING); if(n < 0) { -- 2.25.1