diff options
author | Werner Koch <wk@gnupg.org> | 2008-09-15 19:21:57 +0000 |
---|---|---|
committer | Werner Koch <wk@gnupg.org> | 2008-09-15 19:21:57 +0000 |
commit | 7627f9646701e88c827bbadd1231221d5f0c89a6 (patch) | |
tree | 51d35bfd172c13ebee77936d7c1df25e54b66268 /random | |
parent | f5c7621d2496563dea8b4670056c229bb7f596f6 (diff) | |
download | libgcrypt-7627f9646701e88c827bbadd1231221d5f0c89a6.tar.gz |
Use syslog to log important messages.
Add an external RNG test hook.
Diffstat (limited to 'random')
-rw-r--r-- | random/ChangeLog | 13 | ||||
-rw-r--r-- | random/rand-internal.h | 10 | ||||
-rw-r--r-- | random/random-fips.c | 124 | ||||
-rw-r--r-- | random/random.c | 38 | ||||
-rw-r--r-- | random/random.h | 12 |
5 files changed, 189 insertions, 8 deletions
diff --git a/random/ChangeLog b/random/ChangeLog index 19042680..ed101f68 100644 --- a/random/ChangeLog +++ b/random/ChangeLog @@ -1,3 +1,16 @@ +2008-09-15 Werner Koch <wk@g10code.com> + + * random.c (_gcry_random_init_external_test): New. + (_gcry_random_run_external_test): New. + (_gcry_random_deinit_external_test): New. + * random-fips.c (struct rng_context): Turn TEST_DT_COUNTER into a + 32 bit integer. + (x931_get_dt): Ditto. + (selftest_kat): Intialize it accordingly. + (_gcry_rngfips_init_external_test): New. + (_gcry_rngfips_run_external_test): New. + (_gcry_rngfips_deinit_external_test): New. + 2008-09-05 Werner Koch <wk@g10code.com> * random.c (_gcry_random_selftest): Return success if not in fips diff --git a/random/rand-internal.h b/random/rand-internal.h index e3c01920..269fad95 100644 --- a/random/rand-internal.h +++ b/random/rand-internal.h @@ -79,6 +79,16 @@ void _gcry_rngfips_create_nonce (void *buffer, size_t length); gcry_error_t _gcry_rngfips_selftest (selftest_report_func_t report); +gcry_err_code_t _gcry_rngfips_init_external_test (void **r_context, + const void *key, + size_t keylen, + const void *seed, + size_t seedlen, + const void *dt, + size_t dtlen); +gcry_err_code_t _gcry_rngfips_run_external_test (void *context, + char *buffer, size_t buflen); +void _gcry_rngfips_deinit_external_test (void *context); diff --git a/random/random-fips.c b/random/random-fips.c index f81ab466..90499db2 100644 --- a/random/random-fips.c +++ b/random/random-fips.c @@ -144,12 +144,12 @@ struct rng_context /* To implement a KAT we need to provide a know DT value. To accomplish this the x931_get_dt function checks whether this field is not NULL and then uses the 16 bytes at this address for - the DT value. However the last byte is will be replaced by the - value of field TEST_DT_COUNTER which will be incremented with + the DT value. However the last 4 bytes are replaced by the + value of field TEST_DT_COUNTER which will be incremented after each invocation of x931_get_dt. We use a pointer and not a buffer because there is no need to put this value into secure memory. */ const unsigned char *test_dt_ptr; - unsigned char test_dt_counter; + u32 test_dt_counter; /* We need to keep track of the process which did the initialization so that we can detect a fork. The volatile modifier is required @@ -283,8 +283,12 @@ x931_get_dt (unsigned char *buffer, size_t length, rng_context_t rng_ctx) && rng_ctx != std_rng_context && rng_ctx != strong_rng_context) { - memcpy (buffer, rng_ctx->test_dt_ptr, 15); - buffer[15] = rng_ctx->test_dt_counter++; + memcpy (buffer, rng_ctx->test_dt_ptr, 16); + buffer[12] = (rng_ctx->test_dt_counter >> 24); + buffer[13] = (rng_ctx->test_dt_counter >> 16); + buffer[14] = (rng_ctx->test_dt_counter >> 8); + buffer[15] = rng_ctx->test_dt_counter; + rng_ctx->test_dt_counter++; return; } @@ -792,7 +796,7 @@ _gcry_rngfips_add_bytes (const void *buf, size_t buflen, int quality) /* Public function to fill the buffer with LENGTH bytes of cryptographically strong random bytes. Level GCRY_WEAK_RANDOM is - here mapped to GCRY_STRING_RANDOM, GCRY_STRONG_RANDOM is strong + here mapped to GCRY_STRONG_RANDOM, GCRY_STRONG_RANDOM is strong enough for most usage, GCRY_VERY_STRONG_RANDOM is good for key generation stuff but may be very slow. */ void @@ -915,9 +919,12 @@ selftest_kat (selftest_report_func_t report) /* Setup a DT value. */ test_ctx->test_dt_ptr = tv[tvidx].dt; - test_ctx->test_dt_counter = tv[tvidx].dt[15]; + test_ctx->test_dt_counter = ( (tv[tvidx].dt[12] << 24) + |(tv[tvidx].dt[13] << 16) + |(tv[tvidx].dt[14] << 8) + |(tv[tvidx].dt[15]) ); - /* Get ant compare the first three results. */ + /* Get and compare the first three results. */ for (ridx=0; ridx < 3; ridx++) { /* Compute the next value. */ @@ -989,3 +996,104 @@ _gcry_rngfips_selftest (selftest_report_func_t report) return gpg_error (ec); } + +/* Create a new test context for an external RNG test driver. On + success the test context is stored at R_CONTEXT; on failure NULL is + stored at R_CONTEXT and an error code is returned. */ +gcry_err_code_t +_gcry_rngfips_init_external_test (void **r_context, + const void *key, size_t keylen, + const void *seed, size_t seedlen, + const void *dt, size_t dtlen) +{ + gpg_error_t err; + rng_context_t test_ctx; + + _gcry_rngfips_initialize (1); /* Auto-initialize if needed. */ + + if (!r_context + || !key || keylen != 16 + || !seed || seedlen != 16 + || !dt || dtlen != 16 ) + return GPG_ERR_INV_ARG; + + test_ctx = gcry_calloc (1, sizeof *test_ctx + dtlen); + if (!test_ctx) + return gpg_err_code_from_syserror (); + setup_guards (test_ctx); + + /* Setup the key. */ + err = gcry_cipher_open (&test_ctx->cipher_hd, + GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_ECB, + GCRY_CIPHER_SECURE); + if (err) + goto leave; + + err = gcry_cipher_setkey (test_ctx->cipher_hd, key, keylen); + if (err) + goto leave; + + test_ctx->key_init_pid = getpid (); + + /* Setup the seed. */ + memcpy (test_ctx->seed_V, seed, seedlen); + test_ctx->is_seeded = 1; + test_ctx->seed_init_pid = getpid (); + + /* Setup a DT value. Because our context structure only stores a + pointer we copy the DT value to the extra space we allocated in + the test_ctx and set the pointer to tehre. */ + memcpy ((char*)test_ctx + sizeof *test_ctx, dt, dtlen); + test_ctx->test_dt_ptr = (unsigned char*)test_ctx + sizeof test_ctx; + test_ctx->test_dt_counter = ( (test_ctx->test_dt_ptr[12] << 24) + |(test_ctx->test_dt_ptr[13] << 16) + |(test_ctx->test_dt_ptr[14] << 8) + |(test_ctx->test_dt_ptr[15]) ); + + check_guards (test_ctx); + /* All fine. */ + err = 0; + + leave: + if (err) + { + gcry_cipher_close (test_ctx->cipher_hd); + gcry_free (test_ctx); + *r_context = NULL; + } + else + *r_context = test_ctx; + return gcry_err_code (err); +} + + +/* Get BUFLEN bytes from the RNG using the test CONTEXT and store them + at BUFFER. Return 0 on success or an error code. */ +gcry_err_code_t +_gcry_rngfips_run_external_test (void *context, char *buffer, size_t buflen) +{ + rng_context_t test_ctx = context; + + if (!test_ctx || !buffer || buflen != 16) + return GPG_ERR_INV_ARG; + + lock_rng (); + get_random (buffer, buflen, test_ctx); + unlock_rng (); + return 0; +} + +/* Release the test CONTEXT. */ +void +_gcry_rngfips_deinit_external_test (void *context) +{ + rng_context_t test_ctx = context; + + if (test_ctx) + { + gcry_cipher_close (test_ctx->cipher_hd); + gcry_free (test_ctx); + } +} + + diff --git a/random/random.c b/random/random.c index 7a286b8e..9da83cf0 100644 --- a/random/random.c +++ b/random/random.c @@ -283,3 +283,41 @@ _gcry_random_selftest (selftest_report_func_t report) return 0; /* No selftests yet. */ } + +/* Create a new test context for an external RNG test driver. On + success the test context is stored at R_CONTEXT; on failure NULL is + stored at R_CONTEXT and an error code is returned. */ +gcry_err_code_t +_gcry_random_init_external_test (void **r_context, + unsigned int flags, + const void *key, size_t keylen, + const void *seed, size_t seedlen, + const void *dt, size_t dtlen) +{ + (void)flags; + if (fips_mode ()) + return _gcry_rngfips_init_external_test (r_context, key, keylen, + seed, seedlen, + dt, dtlen); + else + return GPG_ERR_NOT_SUPPORTED; +} + +/* Get BUFLEN bytes from the RNG using the test CONTEXT and store them + at BUFFER. Return 0 on success or an error code. */ +gcry_err_code_t +_gcry_random_run_external_test (void *context, char *buffer, size_t buflen) +{ + if (fips_mode ()) + return _gcry_rngfips_run_external_test (context, buffer, buflen); + else + return GPG_ERR_NOT_SUPPORTED; +} + +/* Release the test CONTEXT. */ +void +_gcry_random_deinit_external_test (void *context) +{ + if (fips_mode ()) + return _gcry_rngfips_deinit_external_test (context); +} diff --git a/random/random.h b/random/random.h index eda44d36..9075d9a3 100644 --- a/random/random.h +++ b/random/random.h @@ -39,6 +39,18 @@ void _gcry_update_random_seed_file (void); byte *_gcry_get_random_bits( size_t nbits, int level, int secure ); void _gcry_fast_random_poll( void ); +gcry_err_code_t _gcry_random_init_external_test (void **r_context, + unsigned int flags, + const void *key, + size_t keylen, + const void *seed, + size_t seedlen, + const void *dt, + size_t dtlen); +gcry_err_code_t _gcry_random_run_external_test (void *context, + char *buffer, size_t buflen); +void _gcry_random_deinit_external_test (void *context); + /*-- rndegd.c --*/ gpg_error_t _gcry_rndegd_set_socket_name (const char *name); |