rand_vxworks.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. /*
  2. * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
  3. *
  4. * Licensed under the OpenSSL license (the "License"). You may not use
  5. * this file except in compliance with the License. You can obtain a copy
  6. * in the file LICENSE in the source distribution or at
  7. * https://www.openssl.org/source/license.html
  8. */
  9. #include <openssl/opensslconf.h>
  10. #ifndef OPENSSL_SYS_VXWORKS
  11. NON_EMPTY_TRANSLATION_UNIT
  12. #else
  13. # include <openssl/rand.h>
  14. # include "rand_local.h"
  15. # include "crypto/rand.h"
  16. # include "internal/cryptlib.h"
  17. # include <version.h>
  18. # include <taskLib.h>
  19. # if defined(OPENSSL_RAND_SEED_NONE)
  20. /* none means none */
  21. # undef OPENSSL_RAND_SEED_OS
  22. # endif
  23. # if defined(OPENSSL_RAND_SEED_OS)
  24. # if _WRS_VXWORKS_MAJOR >= 7
  25. # define RAND_SEED_VXRANDLIB
  26. # else
  27. # error "VxWorks <7 only support RAND_SEED_NONE"
  28. # endif
  29. # endif
  30. # if defined(RAND_SEED_VXRANDLIB)
  31. # include <randomNumGen.h>
  32. # endif
  33. /* Macro to convert two thirty two bit values into a sixty four bit one */
  34. # define TWO32TO64(a, b) ((((uint64_t)(a)) << 32) + (b))
  35. static uint64_t get_time_stamp(void)
  36. {
  37. struct timespec ts;
  38. if (clock_gettime(CLOCK_REALTIME, &ts) == 0)
  39. return TWO32TO64(ts.tv_sec, ts.tv_nsec);
  40. return time(NULL);
  41. }
  42. static uint64_t get_timer_bits(void)
  43. {
  44. uint64_t res = OPENSSL_rdtsc();
  45. struct timespec ts;
  46. if (res != 0)
  47. return res;
  48. if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0)
  49. return TWO32TO64(ts.tv_sec, ts.tv_nsec);
  50. return time(NULL);
  51. }
  52. /*
  53. * empty implementation
  54. * vxworks does not need to init/cleanup or keep open the random lib
  55. */
  56. int rand_pool_init(void)
  57. {
  58. return 1;
  59. }
  60. void rand_pool_cleanup(void)
  61. {
  62. }
  63. void rand_pool_keep_random_devices_open(int keep)
  64. {
  65. }
  66. int rand_pool_add_additional_data(RAND_POOL *pool)
  67. {
  68. struct {
  69. CRYPTO_THREAD_ID tid;
  70. uint64_t time;
  71. } data;
  72. memset(&data, 0, sizeof(data));
  73. /*
  74. * Add some noise from the thread id and a high resolution timer.
  75. * The thread id adds a little randomness if the drbg is accessed
  76. * concurrently (which is the case for the <master> drbg).
  77. */
  78. data.tid = CRYPTO_THREAD_get_current_id();
  79. data.time = get_timer_bits();
  80. return rand_pool_add(pool, (unsigned char *)&data, sizeof(data), 0);
  81. }
  82. int rand_pool_add_nonce_data(RAND_POOL *pool)
  83. {
  84. struct {
  85. pid_t pid;
  86. CRYPTO_THREAD_ID tid;
  87. uint64_t time;
  88. } data;
  89. memset(&data, 0, sizeof(data));
  90. /*
  91. * Add process id, thread id, and a high resolution timestamp to
  92. * ensure that the nonce is unique with high probability for
  93. * different process instances.
  94. */
  95. data.pid = getpid();
  96. data.tid = CRYPTO_THREAD_get_current_id();
  97. data.time = get_time_stamp();
  98. return rand_pool_add(pool, (unsigned char *)&data, sizeof(data), 0);
  99. }
  100. size_t rand_pool_acquire_entropy(RAND_POOL *pool)
  101. {
  102. # if defined(RAND_SEED_VXRANDLIB)
  103. /* vxRandLib based entropy method */
  104. size_t bytes_needed;
  105. bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
  106. if (bytes_needed > 0)
  107. {
  108. int retryCount = 0;
  109. STATUS result = ERROR;
  110. unsigned char *buffer;
  111. buffer = rand_pool_add_begin(pool, bytes_needed);
  112. while ((result != OK) && (retryCount < 10)) {
  113. RANDOM_NUM_GEN_STATUS status = randStatus();
  114. if ((status == RANDOM_NUM_GEN_ENOUGH_ENTROPY)
  115. || (status == RANDOM_NUM_GEN_MAX_ENTROPY) ) {
  116. result = randBytes(buffer, bytes_needed);
  117. if (result == OK)
  118. rand_pool_add_end(pool, bytes_needed, 8 * bytes_needed);
  119. /*
  120. * no else here: randStatus said ok, if randBytes failed
  121. * it will result in another loop or no entropy
  122. */
  123. } else {
  124. /*
  125. * give a minimum delay here to allow OS to collect more
  126. * entropy. taskDelay duration will depend on the system tick,
  127. * this is by design as the sw-random lib uses interrupts
  128. * which will at least happen during ticks
  129. */
  130. taskDelay(5);
  131. }
  132. retryCount++;
  133. }
  134. }
  135. return rand_pool_entropy_available(pool);
  136. # else
  137. /*
  138. * SEED_NONE means none, without randlib we dont have entropy and
  139. * rely on it being added externally
  140. */
  141. return rand_pool_entropy_available(pool);
  142. # endif /* defined(RAND_SEED_VXRANDLIB) */
  143. }
  144. #endif /* OPENSSL_SYS_VXWORKS */