diff --git a/crypto/rand/rand_vms.c b/crypto/rand/rand_vms.c index a00f83bcc4911..ce4f81164330d 100644 --- a/crypto/rand/rand_vms.c +++ b/crypto/rand/rand_vms.c @@ -479,31 +479,6 @@ size_t data_collect_method(RAND_POOL *pool) return rand_pool_entropy_available(pool); } -int rand_pool_add_nonce_data(RAND_POOL *pool) -{ - struct { - pid_t pid; - CRYPTO_THREAD_ID tid; - unsigned __int64 time; - } data = { 0 }; - - /* - * Add process id, thread id, and a high resolution timestamp - * (where available, which is OpenVMS v8.4 and up) to ensure that - * the nonce is unique with high probability for different process - * instances. - */ - data.pid = getpid(); - data.tid = CRYPTO_THREAD_get_current_id(); -#if __CRTL_VER >= 80400000 - sys$gettim_prec(&data.time); -#else - sys$gettim((void*)&data.time); -#endif - - return rand_pool_add(pool, (unsigned char *)&data, sizeof(data), 0); -} - /* * SYS$GET_ENTROPY METHOD * ====================== @@ -577,6 +552,59 @@ size_t rand_pool_acquire_entropy(RAND_POOL *pool) return data_collect_method(pool); } +int rand_pool_add_nonce_data(RAND_POOL *pool) +{ + /* + * Two variables to ensure that two nonces won't ever be the same + */ + static unsigned __int64 last_time = 0; + static unsigned __int32 last_seq = 0; + + struct { + pid_t pid; + CRYPTO_THREAD_ID tid; + unsigned __int64 time; + unsigned __int32 seq; + } data; + + /* Erase the entire structure including any padding */ + memset(&data, 0, sizeof(data)); + + /* + * Add process id, thread id, a timestamp, and a sequence number in case + * the same time stamp is repeated, to ensure that the nonce is unique + * with high probability for different process instances. + * + * The normal OpenVMS time is specified to be high granularity (100ns), + * but the time update granularity given by sys$gettim() may be lower. + * + * OpenVMS version 8.4 (which is the latest for Alpha and Itanium) and + * on have sys$gettim_prec() as well, which is supposedly having a better + * time update granularity, but tests on Itanium (and even Alpha) have + * shown that compared with sys$gettim(), the difference is marginal, + * so of very little significance in terms of entropy. + * Given that, and that it's a high ask to expect everyone to have + * upgraded to OpenVMS version 8.4, only sys$gettim() is used, and a + * sequence number is added as well, in case sys$gettim() returns the + * same time value more than once. + * + * This function is assumed to be called under thread lock, and does + * therefore not take concurrency into account. + */ + data.pid = getpid(); + data.tid = CRYPTO_THREAD_get_current_id(); + data.seq = 0; + sys$gettim((void*)&data.time); + + if (data.time == last_time) { + data.seq = ++last_seq; + } else { + last_time = data.time; + last_seq = 0; + } + + return rand_pool_add(pool, (unsigned char *)&data, sizeof(data), 0); +} int rand_pool_add_additional_data(RAND_POOL *pool) { @@ -586,16 +614,12 @@ int rand_pool_add_additional_data(RAND_POOL *pool) } data = { 0 }; /* - * Add some noise from the thread id and a high resolution timer. - * The thread id adds a little randomness if the drbg is accessed - * concurrently (which is the case for the drbg). + * Add some noise from the thread id and a timer. The thread id adds a + * little randomness if the drbg is accessed concurrently (which is the + * case for the drbg). */ data.tid = CRYPTO_THREAD_get_current_id(); -#if __CRTL_VER >= 80400000 - sys$gettim_prec(&data.time); -#else sys$gettim((void*)&data.time); -#endif return rand_pool_add(pool, (unsigned char *)&data, sizeof(data), 0); }