crngt.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. /*
  2. * Copyright 2019-2020 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 <openssl/core_dispatch.h>
  16. #include <openssl/params.h>
  17. #include "prov/providercommon.h"
  18. #include "prov/provider_ctx.h"
  19. #include "internal/cryptlib.h"
  20. #include "prov/rand_pool.h"
  21. #include "drbg_local.h"
  22. #include "prov/seeding.h"
  23. typedef struct crng_test_global_st {
  24. unsigned char crngt_prev[EVP_MAX_MD_SIZE];
  25. RAND_POOL *crngt_pool;
  26. } CRNG_TEST_GLOBAL;
  27. static int crngt_get_entropy(OPENSSL_CTX *ctx, RAND_POOL *pool,
  28. unsigned char *buf, unsigned char *md,
  29. unsigned int *md_size)
  30. {
  31. int r;
  32. size_t n;
  33. unsigned char *p;
  34. EVP_MD *fmd;
  35. if (pool == NULL)
  36. return 0;
  37. n = prov_pool_acquire_entropy(pool);
  38. if (n >= CRNGT_BUFSIZ) {
  39. fmd = EVP_MD_fetch(ctx, "SHA256", "");
  40. if (fmd == NULL)
  41. return 0;
  42. p = rand_pool_detach(pool);
  43. r = EVP_Digest(p, CRNGT_BUFSIZ, md, md_size, fmd, NULL);
  44. if (r != 0)
  45. memcpy(buf, p, CRNGT_BUFSIZ);
  46. rand_pool_reattach(pool, p);
  47. EVP_MD_free(fmd);
  48. return r;
  49. }
  50. return 0;
  51. }
  52. static void rand_crng_ossl_ctx_free(void *vcrngt_glob)
  53. {
  54. CRNG_TEST_GLOBAL *crngt_glob = vcrngt_glob;
  55. rand_pool_free(crngt_glob->crngt_pool);
  56. OPENSSL_free(crngt_glob);
  57. }
  58. static void *rand_crng_ossl_ctx_new(OPENSSL_CTX *ctx)
  59. {
  60. unsigned char buf[CRNGT_BUFSIZ];
  61. CRNG_TEST_GLOBAL *crngt_glob = OPENSSL_zalloc(sizeof(*crngt_glob));
  62. if (crngt_glob == NULL)
  63. return NULL;
  64. if ((crngt_glob->crngt_pool
  65. = rand_pool_new(0, 1, CRNGT_BUFSIZ, CRNGT_BUFSIZ)) == NULL) {
  66. OPENSSL_free(crngt_glob);
  67. return NULL;
  68. }
  69. if (crngt_get_entropy(ctx, crngt_glob->crngt_pool, buf,
  70. crngt_glob->crngt_prev, NULL)) {
  71. OPENSSL_cleanse(buf, sizeof(buf));
  72. return crngt_glob;
  73. }
  74. rand_pool_free(crngt_glob->crngt_pool);
  75. OPENSSL_free(crngt_glob);
  76. return NULL;
  77. }
  78. static const OPENSSL_CTX_METHOD rand_crng_ossl_ctx_method = {
  79. rand_crng_ossl_ctx_new,
  80. rand_crng_ossl_ctx_free,
  81. };
  82. size_t prov_crngt_get_entropy(PROV_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. OPENSSL_CTX *libctx = PROV_LIBRARY_CONTEXT_OF(drbg->provctx);
  93. CRNG_TEST_GLOBAL *crngt_glob
  94. = openssl_ctx_get_data(libctx, OPENSSL_CTX_RAND_CRNGT_INDEX,
  95. &rand_crng_ossl_ctx_method);
  96. if (crngt_glob == NULL)
  97. return 0;
  98. if ((pool = rand_pool_new(entropy, 1, min_len, max_len)) == NULL)
  99. return 0;
  100. while ((q = rand_pool_bytes_needed(pool, 1)) > 0 && attempts-- > 0) {
  101. s = q > sizeof(buf) ? sizeof(buf) : q;
  102. if (!crngt_get_entropy(libctx, crngt_glob->crngt_pool, buf, md,
  103. &sz)
  104. || memcmp(crngt_glob->crngt_prev, md, sz) == 0
  105. || !rand_pool_add(pool, buf, s, s * 8))
  106. goto err;
  107. memcpy(crngt_glob->crngt_prev, md, sz);
  108. t += s;
  109. attempts++;
  110. }
  111. r = t;
  112. *pout = rand_pool_detach(pool);
  113. err:
  114. OPENSSL_cleanse(buf, sizeof(buf));
  115. rand_pool_free(pool);
  116. return r;
  117. }
  118. void prov_crngt_cleanup_entropy(PROV_DRBG *drbg,
  119. unsigned char *out, size_t outlen)
  120. {
  121. OPENSSL_secure_clear_free(out, outlen);
  122. }