summaryrefslogtreecommitdiff
path: root/providers
diff options
context:
space:
mode:
authorRichard Levitte <levitte@openssl.org>2022-07-06 06:09:01 +0200
committerRichard Levitte <levitte@openssl.org>2022-10-27 12:35:38 +0200
commit7056dc9c50baa4af5152c625c4735806d51c67cd (patch)
tree5eb5fb1d03ae65f6ebe4d0686d5b2be2bbd44531 /providers
parentee05588dabeac7b9d034bf16dad122a93d1688a4 (diff)
downloadopenssl-new-7056dc9c50baa4af5152c625c4735806d51c67cd.tar.gz
Make openVMS seeding less dependent of OpenVMS version
SYS$GETTIM_PREC is a very new function, only available on OpenVMS v8.4. OpenSSL binaries built on OpenVMS v8.4 become unusable on older OpenVM versions, but building for the older CRTL version will make the high precision time functions unavailable. Tests have shown that on Alpha and Itanium, the time update granularity between SYS$GETTIM and SYS$GETTIM_PREC is marginal, so the former plus a sequence number turns out to be better to guarantee a unique nonce. Fixes #18727 Reviewed-by: Hugo Landau <hlandau@openssl.org> Reviewed-by: Tomas Mraz <tomas@openssl.org> (Merged from https://github.com/openssl/openssl/pull/18731)
Diffstat (limited to 'providers')
-rw-r--r--providers/implementations/rands/seeding/rand_vms.c82
1 files changed, 54 insertions, 28 deletions
diff --git a/providers/implementations/rands/seeding/rand_vms.c b/providers/implementations/rands/seeding/rand_vms.c
index a0531b32b7..07814a43dc 100644
--- a/providers/implementations/rands/seeding/rand_vms.c
+++ b/providers/implementations/rands/seeding/rand_vms.c
@@ -474,34 +474,6 @@ size_t data_collect_method(RAND_POOL *pool)
return ossl_rand_pool_entropy_available(pool);
}
-int ossl_pool_add_nonce_data(RAND_POOL *pool)
-{
- struct {
- pid_t pid;
- CRYPTO_THREAD_ID tid;
- unsigned __int64 time;
- } data;
-
- /* Erase the entire structure including any padding */
- memset(&data, 0, sizeof(data));
-
- /*
- * 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 ossl_rand_pool_add(pool, (unsigned char *)&data, sizeof(data), 0);
-}
-
/*
* SYS$GET_ENTROPY METHOD
* ======================
@@ -575,6 +547,60 @@ size_t ossl_pool_acquire_entropy(RAND_POOL *pool)
return data_collect_method(pool);
}
+int ossl_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 ossl_rand_pool_add(pool, (unsigned char *)&data, sizeof(data), 0);
+}
+
int ossl_rand_pool_init(void)
{
return 1;