rand_crng_test.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. /*
  2. * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
  3. * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
  4. *
  5. * Licensed under the Apache License 2.0 (the "License"). You may not use
  6. * this file except in compliance with the License. You can obtain a copy
  7. * in the file LICENSE in the source distribution or at
  8. * https://www.openssl.org/source/license.html
  9. */
  10. /*
  11. * Implementation of the FIPS 140-2 section 4.9.2 Conditional Tests.
  12. */
  13. #include <string.h>
  14. #include <openssl/evp.h>
  15. #include "internal/rand_int.h"
  16. #include "internal/thread_once.h"
  17. #include "internal/cryptlib.h"
  18. #include "rand_lcl.h"
  19. typedef struct crng_test_global_st {
  20. unsigned char crngt_prev[EVP_MAX_MD_SIZE];
  21. RAND_POOL *crngt_pool;
  22. } CRNG_TEST_GLOBAL;
  23. int (*crngt_get_entropy)(OPENSSL_CTX *, unsigned char *, unsigned char *,
  24. unsigned int *)
  25. = &rand_crngt_get_entropy_cb;
  26. static void rand_crng_ossl_ctx_free(void *vcrngt_glob)
  27. {
  28. CRNG_TEST_GLOBAL *crngt_glob = vcrngt_glob;
  29. rand_pool_free(crngt_glob->crngt_pool);
  30. OPENSSL_free(crngt_glob);
  31. }
  32. static void *rand_crng_ossl_ctx_new(OPENSSL_CTX *ctx)
  33. {
  34. unsigned char buf[CRNGT_BUFSIZ];
  35. CRNG_TEST_GLOBAL *crngt_glob = OPENSSL_zalloc(sizeof(*crngt_glob));
  36. if (crngt_glob == NULL)
  37. return NULL;
  38. if ((crngt_glob->crngt_pool
  39. = rand_pool_new(0, CRNGT_BUFSIZ, CRNGT_BUFSIZ)) == NULL) {
  40. OPENSSL_free(crngt_glob);
  41. return NULL;
  42. }
  43. if (crngt_get_entropy(ctx, buf, crngt_glob->crngt_prev, NULL)) {
  44. OPENSSL_cleanse(buf, sizeof(buf));
  45. return crngt_glob;
  46. }
  47. rand_pool_free(crngt_glob->crngt_pool);
  48. OPENSSL_free(crngt_glob);
  49. return NULL;
  50. }
  51. static const OPENSSL_CTX_METHOD rand_crng_ossl_ctx_method = {
  52. rand_crng_ossl_ctx_new,
  53. rand_crng_ossl_ctx_free,
  54. };
  55. int rand_crngt_get_entropy_cb(OPENSSL_CTX *ctx,
  56. unsigned char *buf,
  57. unsigned char *md,
  58. unsigned int *md_size)
  59. {
  60. int r;
  61. size_t n;
  62. unsigned char *p;
  63. CRNG_TEST_GLOBAL *crngt_glob
  64. = openssl_ctx_get_data(ctx, OPENSSL_CTX_RAND_CRNGT_INDEX,
  65. &rand_crng_ossl_ctx_method);
  66. if (crngt_glob == NULL)
  67. return 0;
  68. n = rand_pool_acquire_entropy(crngt_glob->crngt_pool);
  69. if (n >= CRNGT_BUFSIZ) {
  70. p = rand_pool_detach(crngt_glob->crngt_pool);
  71. r = EVP_Digest(p, CRNGT_BUFSIZ, md, md_size, EVP_sha256(), NULL);
  72. if (r != 0)
  73. memcpy(buf, p, CRNGT_BUFSIZ);
  74. rand_pool_reattach(crngt_glob->crngt_pool, p);
  75. return r;
  76. }
  77. return 0;
  78. }
  79. size_t rand_crngt_get_entropy(RAND_DRBG *drbg,
  80. unsigned char **pout,
  81. int entropy, size_t min_len, size_t max_len,
  82. int prediction_resistance)
  83. {
  84. unsigned char buf[CRNGT_BUFSIZ], md[EVP_MAX_MD_SIZE];
  85. unsigned int sz;
  86. RAND_POOL *pool;
  87. size_t q, r = 0, s, t = 0;
  88. int attempts = 3;
  89. CRNG_TEST_GLOBAL *crngt_glob
  90. = openssl_ctx_get_data(drbg->libctx, OPENSSL_CTX_RAND_CRNGT_INDEX,
  91. &rand_crng_ossl_ctx_method);
  92. if (crngt_glob == NULL)
  93. return 0;
  94. if ((pool = rand_pool_new(entropy, min_len, max_len)) == NULL)
  95. return 0;
  96. while ((q = rand_pool_bytes_needed(pool, 1)) > 0 && attempts-- > 0) {
  97. s = q > sizeof(buf) ? sizeof(buf) : q;
  98. if (!crngt_get_entropy(drbg->libctx, buf, md, &sz)
  99. || memcmp(crngt_glob->crngt_prev, md, sz) == 0
  100. || !rand_pool_add(pool, buf, s, s * 8))
  101. goto err;
  102. memcpy(crngt_glob->crngt_prev, md, sz);
  103. t += s;
  104. attempts++;
  105. }
  106. r = t;
  107. *pout = rand_pool_detach(pool);
  108. err:
  109. OPENSSL_cleanse(buf, sizeof(buf));
  110. rand_pool_free(pool);
  111. return r;
  112. }
  113. void rand_crngt_cleanup_entropy(RAND_DRBG *drbg,
  114. unsigned char *out, size_t outlen)
  115. {
  116. OPENSSL_secure_clear_free(out, outlen);
  117. }