rand_crng_test.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  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 "crypto/rand.h"
  16. #include "internal/thread_once.h"
  17. #include "internal/cryptlib.h"
  18. #include "rand_local.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 *, RAND_POOL *, unsigned char *,
  24. unsigned char *, 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, 1, CRNGT_BUFSIZ, CRNGT_BUFSIZ)) == NULL) {
  40. OPENSSL_free(crngt_glob);
  41. return NULL;
  42. }
  43. if (crngt_get_entropy(ctx, crngt_glob->crngt_pool, buf,
  44. crngt_glob->crngt_prev, NULL)) {
  45. OPENSSL_cleanse(buf, sizeof(buf));
  46. return crngt_glob;
  47. }
  48. rand_pool_free(crngt_glob->crngt_pool);
  49. OPENSSL_free(crngt_glob);
  50. return NULL;
  51. }
  52. static const OPENSSL_CTX_METHOD rand_crng_ossl_ctx_method = {
  53. rand_crng_ossl_ctx_new,
  54. rand_crng_ossl_ctx_free,
  55. };
  56. int rand_crngt_get_entropy_cb(OPENSSL_CTX *ctx,
  57. RAND_POOL *pool,
  58. unsigned char *buf,
  59. unsigned char *md,
  60. unsigned int *md_size)
  61. {
  62. int r;
  63. size_t n;
  64. unsigned char *p;
  65. if (pool == NULL)
  66. return 0;
  67. n = rand_pool_acquire_entropy(pool);
  68. if (n >= CRNGT_BUFSIZ) {
  69. EVP_MD *fmd = EVP_MD_fetch(ctx, "SHA256", "");
  70. if (fmd == NULL)
  71. return 0;
  72. p = rand_pool_detach(pool);
  73. r = EVP_Digest(p, CRNGT_BUFSIZ, md, md_size, fmd, NULL);
  74. if (r != 0)
  75. memcpy(buf, p, CRNGT_BUFSIZ);
  76. rand_pool_reattach(pool, p);
  77. EVP_MD_free(fmd);
  78. return r;
  79. }
  80. return 0;
  81. }
  82. size_t rand_crngt_get_entropy(RAND_DRBG *drbg,
  83. unsigned char **pout,
  84. int entropy, size_t min_len, size_t max_len,
  85. int prediction_resistance)
  86. {
  87. unsigned char buf[CRNGT_BUFSIZ], md[EVP_MAX_MD_SIZE];
  88. unsigned int sz;
  89. RAND_POOL *pool;
  90. size_t q, r = 0, s, t = 0;
  91. int attempts = 3;
  92. CRNG_TEST_GLOBAL *crngt_glob
  93. = openssl_ctx_get_data(drbg->libctx, OPENSSL_CTX_RAND_CRNGT_INDEX,
  94. &rand_crng_ossl_ctx_method);
  95. if (crngt_glob == NULL)
  96. return 0;
  97. if ((pool = rand_pool_new(entropy, 1, min_len, max_len)) == NULL)
  98. return 0;
  99. while ((q = rand_pool_bytes_needed(pool, 1)) > 0 && attempts-- > 0) {
  100. s = q > sizeof(buf) ? sizeof(buf) : q;
  101. if (!crngt_get_entropy(drbg->libctx, crngt_glob->crngt_pool, buf, md,
  102. &sz)
  103. || memcmp(crngt_glob->crngt_prev, md, sz) == 0
  104. || !rand_pool_add(pool, buf, s, s * 8))
  105. goto err;
  106. memcpy(crngt_glob->crngt_prev, md, sz);
  107. t += s;
  108. attempts++;
  109. }
  110. r = t;
  111. *pout = rand_pool_detach(pool);
  112. err:
  113. OPENSSL_cleanse(buf, sizeof(buf));
  114. rand_pool_free(pool);
  115. return r;
  116. }
  117. void rand_crngt_cleanup_entropy(RAND_DRBG *drbg,
  118. unsigned char *out, size_t outlen)
  119. {
  120. OPENSSL_secure_clear_free(out, outlen);
  121. }