diff options
Diffstat (limited to 'src/lib/crypto/crypto_tests/ytest.c')
-rw-r--r-- | src/lib/crypto/crypto_tests/ytest.c | 385 |
1 files changed, 385 insertions, 0 deletions
diff --git a/src/lib/crypto/crypto_tests/ytest.c b/src/lib/crypto/crypto_tests/ytest.c new file mode 100644 index 000000000..93fb5f25a --- /dev/null +++ b/src/lib/crypto/crypto_tests/ytest.c @@ -0,0 +1,385 @@ +/* -*- Mode: C; c-file-style: "bsd" -*- */ +/* + * Yarrow - Cryptographic Pseudo-Random Number Generator + * Copyright (c) 2000 Zero-Knowledge Systems, Inc. + * + * See the accompanying LICENSE file for license information. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "yarrow.h" +#include "yexcep.h" + +void hex_print( FILE* f, const char* var, void* data, size_t size ); +void dump_yarrow_state( FILE* f, Yarrow_CTX* y ); + +#define YARROW_SEED_FILE "seed" + +static void print_yarrow_status( Yarrow_CTX *y ) +{ + int sid, pool; + Source* source; + + for ( pool = 0; pool < 2; pool++ ) + { + printf( " %s: ", pool == YARROW_SLOW_POOL ? "slow" : "fast" ); + for ( sid = 0; sid < y->num_sources; sid++ ) + { + source = &y->source[ sid ]; + printf( "#%d=%d/%d, ", sid, source->entropy[pool], + pool == YARROW_SLOW_POOL ? + y->slow_thresh : y->fast_thresh ); + } + } + printf( "\n" ); +} + +int yarrow_verbose = 0; +#define VERBOSE( x ) if ( yarrow_verbose ) { x } + +int Instrumented_krb5int_yarrow_input( Yarrow_CTX* y, int sid, void* sample, + size_t size, int entropy ) +{ + int ret; + + VERBOSE( printf( "krb5int_yarrow_input( #%d, %d bits, %s ) = [", sid, entropy, + y->source[sid].pool == + YARROW_SLOW_POOL ? "slow" : "fast" ); ); + ret = krb5int_yarrow_input( y, sid, sample, size, entropy ); + + VERBOSE( printf( "%s]\n", krb5int_yarrow_str_error( ret ) ); ); + VERBOSE( print_yarrow_status( y ); ); + return (ret); +} + +typedef int (*test_fn)( void ); + +int test_1( void ); +int test_2( void ); +int test_3( void ); +int test_4( void ); + +test_fn test_func[] = +{ + test_1, test_2, test_3, test_4 +}; + +#define num_tests ( sizeof(test_func) / sizeof(test_fn) ) + +int do_test( int t ) +{ + EXCEP_DECL; + int ret; + + printf( "doing test %d ... ", t ); fflush( stdout ); + ret = test_func[ t-1 ](); + VERBOSE( printf( "\ndone test %d ", t ); ); + printf( "[%s]\n", krb5int_yarrow_str_error( ret ) ); fflush( stdout ); + THROW( ret ); + + CATCH: + THROW( EXCEP_BOOL ); + EXCEP_RET; +} + +int main( int argc, char* argv[] ) +{ + EXCEP_DECL; + int test = 0; + char** argvp; + char* arg; + char* conv_ok = NULL; + int ok = YARROW_OK; + int done_some_tests = 0; + int i; + int ret; + + for ( argvp = argv+1, i = 1; i < argc; i++, argvp++ ) + { + arg = *argvp; + if ( arg[0] == '-' ) + { + switch ( arg[1] ) + { + case 'v': yarrow_verbose = 1; continue; + default: fprintf( stderr, "usage: test [-v] [[test] ... ]\n" ); + THROW( YARROW_FAIL ); + } + } + conv_ok = NULL; + test = strtoul( arg, &conv_ok, 10 ); + if ( !conv_ok || test < 1 || test > num_tests ) + { + fprintf( stderr, "usage: test [-v] [[test] ... ]\n" ); + THROW( YARROW_FAIL ); + } + else + { + ret = do_test( test ); + if ( ok ) { ok = ret; } + done_some_tests = 1; + } + } + + if ( !done_some_tests ) + { + for ( i = 1; i <= num_tests; i++ ) + { + ret = do_test( i ); + if ( ok ) { ok = ret; } + } + } + THROW( ok ); + + CATCH: + switch (EXCEPTION) + { + case YARROW_OK: + exit (EXIT_SUCCESS); + default: + exit (EXIT_FAILURE); + } +} + +int test_1( void ) +{ + EXCEP_DECL; + +#if defined(YARROW_HASH_SHA1) + VERBOSE( printf( "\nsha1 test\n\n" ); ); + THROW( YARROW_NOT_IMPL ); +#elif defined(YARROW_MD5) + VERBOSE( printf( "\nmd5 test\n\n" ); ); + THROW( YARROW_NOT_IMPL ); +#else + VERBOSE( printf( "\nunknown hash function\n\n" ); ); + THROW( YARROW_NOT_IMPL ); +#endif + CATCH: + EXCEP_RET; +} + +int test_2( void ) +{ + EXCEP_DECL; + +#if defined(YARROW_CIPHER_3DES) + VERBOSE( printf( "\n3des test\n\n" ); ); + THROW( YARROW_NOT_IMPL ); +#elif defined(YARROW_CIPHER_BLOWFISH) + VERBOSE( printf( "\nblowfish test\n\n" ); ); + THROW( YARROW_NOT_IMPL ); +#elif defined(YARROW_CIPHER_IDEA) + VERBOSE( printf( "\nidea test\n\n" ); ); + THROW( YARROW_NOT_IMPL ); +#else + VERBOSE( printf( "\nunknown encryption function\n\n" ); ); + THROW( YARROW_NOT_IMPL ); +#endif + CATCH: + EXCEP_RET; +} + +int test_3( void ) +{ + EXCEP_DECL; + +#if !defined(YARROW_CIPHER_3DES) || !defined(YARROW_HASH_SHA1) + VERBOSE( printf( "\nnot Yarrow-SHA1-3DES (aka Yarrow-160)\n\n" ); ); + THROW( YARROW_NOT_IMPL ); +#endif + + VERBOSE( printf( "\nkrb5int_yarrow_stretch\n\n" ); ); + THROW( YARROW_NOT_IMPL ); + + CATCH: + EXCEP_RET; +} + +int test_4( void ) +{ + EXCEP_DECL; + Yarrow_CTX yarrow; + int initialized = 0; + unsigned user, mouse, keyboard; + int i, ret; + byte user_sample[ 20 ]; + byte mouse_sample[ 4 ]; + byte keyboard_sample[ 2 ]; + byte random[ 30 ]; + byte junk[ 48 ]; + + memset( user_sample, 3, sizeof( user_sample ) ); + memset( mouse_sample, 1, sizeof( mouse_sample ) ); + memset( keyboard_sample, 2, sizeof( keyboard_sample ) ); + + VERBOSE( printf( "\nGeneral workout test\n\n" ); ) + + VERBOSE( printf( "krb5int_yarrow_init() = [" ); ); + ret = krb5int_yarrow_init( &yarrow, YARROW_SEED_FILE ); + VERBOSE( printf( "%s]\n", krb5int_yarrow_str_error( ret ) ); ); + + if ( ret != YARROW_OK && ret != YARROW_NOT_SEEDED ) { THROW( ret ); } + initialized = 1; + +#if defined( YARROW_DEBUG ) + dump_yarrow_state( stdout, &yarrow ); +#endif + + ret = krb5int_yarrow_new_source( &yarrow, &user ); + VERBOSE( printf( "krb5int_yarrow_new_source() = [%s]\n", + krb5int_yarrow_str_error( ret ) ); ); + if ( ret != YARROW_OK ) { THROW( ret ); } + + VERBOSE( printf( "Yarrow_Poll( #%d ) = [", user ); ); + ret = Yarrow_Poll( &yarrow, user ); + VERBOSE( printf( "%s]\n", krb5int_yarrow_str_error( ret ) ); ); + + ret = krb5int_yarrow_new_source( &yarrow, &mouse ); + VERBOSE( printf( "krb5int_yarrow_new_source() = [%s]\n", + krb5int_yarrow_str_error( ret ) ); ); + if ( ret != YARROW_OK ) { THROW( ret ); } + + ret = krb5int_yarrow_new_source( &yarrow, &keyboard ); + VERBOSE( printf( "krb5int_yarrow_new_source() = [%s]\n", + krb5int_yarrow_str_error( ret ) ); ); + if ( ret != YARROW_OK ) { THROW( ret ); } + +/* prematurely try to draw output, to check failure when no + * seed file, or state saving turned off + */ + + VERBOSE( printf( "krb5int_yarrow_output( %d ) = [", sizeof( random ) ); ); + ret = krb5int_yarrow_output( &yarrow, random, sizeof( random ) ); + VERBOSE( printf( "%s]\n", krb5int_yarrow_str_error( ret ) ); ); + +/* do it twice so that we some slow samples + * (first sample goes to fast pool, and then samples alternate) + */ + + for ( i = 0; i < 2; i++ ) + { + TRY( Instrumented_krb5int_yarrow_input( &yarrow, mouse, mouse_sample, + sizeof( mouse_sample ), 2 ) ); + + TRY( Instrumented_krb5int_yarrow_input( &yarrow, keyboard, keyboard_sample, + sizeof( keyboard_sample ), 2 ) ); + + TRY( Instrumented_krb5int_yarrow_input( &yarrow, user, user_sample, + sizeof( user_sample ), 2 ) ); + } + +#if defined( YARROW_DEBUG ) + dump_yarrow_state( stdout, &yarrow ); +#endif + + VERBOSE( printf( "\nInduce user source (#%d) to reach " + "slow threshold\n\n", user ); ); + + /* induce fast reseed */ + + for ( i = 0; i < 7; i++ ) + { + TRY( Instrumented_krb5int_yarrow_input( &yarrow, user, user_sample, + sizeof( user_sample ), + sizeof( user_sample ) * 3 ) ); + } + + VERBOSE( printf( "\nInduce mouse source (#%d) to reach " + "slow threshold reseed\n\n", mouse ); ); + + /* induce slow reseed, by triggering a second source to reach it's + threshold */ + + for ( i = 0; i < 40; i++ ) + { + TRY( Instrumented_krb5int_yarrow_input( &yarrow, mouse, mouse_sample, + sizeof( mouse_sample ), + sizeof( mouse_sample )*2 ) ); + } + + VERBOSE( printf( "\nProduce some output\n\n" ); ); + + for ( i = 0; i < 30; i++ ) + { + VERBOSE( printf( "krb5int_yarrow_output( %d ) = [", sizeof( junk ) ); ); + ret = krb5int_yarrow_output( &yarrow, junk, sizeof( junk ) ); + VERBOSE( printf( "%s]\n", krb5int_yarrow_str_error( ret ) ); ); + if ( ret != YARROW_OK ) { THROW( ret ); } + } + + memset( junk, 0, sizeof( junk ) ); + + VERBOSE( printf( "\nTrigger some fast and slow reseeds\n\n" ); ); + + for ( i = 0; i < 30; i++ ) + { + /* odd input to a different source so there are some slow reseeds */ + + if ( i % 16 == 0 ) + { + TRY( Instrumented_krb5int_yarrow_input( &yarrow, mouse, junk, + sizeof( junk ), + sizeof( junk ) * 3 ) ); + } + else + { + TRY( Instrumented_krb5int_yarrow_input( &yarrow, user, junk, + sizeof( junk ), + sizeof( junk ) * 3 ) ); + } + } + + VERBOSE( printf( "\nPrint some random output\n\n" ); ); + + VERBOSE( printf( "krb5int_yarrow_output( %d ) = [", sizeof( random ) ); ); + ret = krb5int_yarrow_output( &yarrow, random, sizeof( random ) ); + VERBOSE( printf( "%s]\n", krb5int_yarrow_str_error( ret ) ); ); + if ( ret != YARROW_OK ) + { + THROW( ret ); + } + else + { + VERBOSE( hex_print( stdout, "random", random, sizeof( random ) ); ); + } + + VERBOSE( printf( "\nClose down Yarrow\n\n" ); ); + + CATCH: + if ( initialized ) + { + VERBOSE( printf( "krb5int_yarrow_final() = [" ); ); + ret = krb5int_yarrow_final( &yarrow ); + VERBOSE( printf( "%s]\n", krb5int_yarrow_str_error( ret ) ); ); + THROW( ret ); + } + EXCEP_RET; +} + +void hex_print( FILE* f, const char* var, void* data, size_t size ) +{ + const char* conv = "0123456789abcdef"; + size_t i; + char* p = (char*) data; + char c, d; + + fprintf( f, var ); + fprintf( f, " = " ); + for ( i = 0; i < size; i++ ) + { + c = conv[ (p[ i ] >> 4) & 0xf ]; + d = conv[ p[ i ] & 0xf ]; + fprintf( f, "%c%c", c, d ); + } + fprintf( f, "\n" ); +} + +void dump_yarrow_state( FILE* f, Yarrow_CTX* y ) +{ + fprintf( f, "===Yarrow State===\n" ); + hex_print( f, "C", y->C, sizeof( y->C ) ); + hex_print( f, "K", y->K, sizeof( y->K ) ); +} |