1 /* 2 * Copyright 2019-2021 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 /* 12 * Implementation of the FIPS 140-2 section 4.9.2 Conditional Tests. 13 */ 14 15 #include <string.h> 16 #include <openssl/evp.h> 17 #include <openssl/core_dispatch.h> 18 #include <openssl/params.h> 19 #include <openssl/self_test.h> 20 #include "prov/providercommon.h" 21 #include "prov/provider_ctx.h" 22 #include "internal/cryptlib.h" 23 #include "crypto/rand_pool.h" 24 #include "drbg_local.h" 25 #include "prov/seeding.h" 26 27 typedef struct crng_test_global_st { 28 unsigned char crngt_prev[EVP_MAX_MD_SIZE]; 29 EVP_MD *md; 30 int preloaded; 31 CRYPTO_RWLOCK *lock; 32 } CRNG_TEST_GLOBAL; 33 34 static int crngt_get_entropy(PROV_CTX *provctx, const EVP_MD *digest, 35 unsigned char *buf, unsigned char *md, 36 unsigned int *md_size) 37 { 38 int r; 39 size_t n; 40 unsigned char *p; 41 42 n = ossl_prov_get_entropy(provctx, &p, 0, CRNGT_BUFSIZ, CRNGT_BUFSIZ); 43 if (n == CRNGT_BUFSIZ) { 44 r = EVP_Digest(p, CRNGT_BUFSIZ, md, md_size, digest, NULL); 45 if (r != 0) 46 memcpy(buf, p, CRNGT_BUFSIZ); 47 ossl_prov_cleanup_entropy(provctx, p, n); 48 return r != 0; 49 } 50 if (n != 0) 51 ossl_prov_cleanup_entropy(provctx, p, n); 52 return 0; 53 } 54 55 static void rand_crng_ossl_ctx_free(void *vcrngt_glob) 56 { 57 CRNG_TEST_GLOBAL *crngt_glob = vcrngt_glob; 58 59 CRYPTO_THREAD_lock_free(crngt_glob->lock); 60 EVP_MD_free(crngt_glob->md); 61 OPENSSL_free(crngt_glob); 62 } 63 64 static void *rand_crng_ossl_ctx_new(OSSL_LIB_CTX *ctx) 65 { 66 CRNG_TEST_GLOBAL *crngt_glob = OPENSSL_zalloc(sizeof(*crngt_glob)); 67 68 if (crngt_glob == NULL) 69 return NULL; 70 71 if ((crngt_glob->md = EVP_MD_fetch(ctx, "SHA256", "")) == NULL) { 72 OPENSSL_free(crngt_glob); 73 return NULL; 74 } 75 76 if ((crngt_glob->lock = CRYPTO_THREAD_lock_new()) == NULL) { 77 EVP_MD_free(crngt_glob->md); 78 OPENSSL_free(crngt_glob); 79 return NULL; 80 } 81 82 return crngt_glob; 83 } 84 85 static const OSSL_LIB_CTX_METHOD rand_crng_ossl_ctx_method = { 86 OSSL_LIB_CTX_METHOD_DEFAULT_PRIORITY, 87 rand_crng_ossl_ctx_new, 88 rand_crng_ossl_ctx_free, 89 }; 90 91 static int prov_crngt_compare_previous(const unsigned char *prev, 92 const unsigned char *cur, 93 size_t sz) 94 { 95 const int res = memcmp(prev, cur, sz) != 0; 96 97 if (!res) 98 ossl_set_error_state(OSSL_SELF_TEST_TYPE_CRNG); 99 return res; 100 } 101 102 size_t ossl_crngt_get_entropy(PROV_DRBG *drbg, 103 unsigned char **pout, 104 int entropy, size_t min_len, size_t max_len, 105 int prediction_resistance) 106 { 107 unsigned char md[EVP_MAX_MD_SIZE]; 108 unsigned char buf[CRNGT_BUFSIZ]; 109 unsigned char *ent, *entp, *entbuf; 110 unsigned int sz; 111 size_t bytes_needed; 112 size_t r = 0, s, t; 113 int crng_test_pass = 1; 114 OSSL_LIB_CTX *libctx = ossl_prov_ctx_get0_libctx(drbg->provctx); 115 CRNG_TEST_GLOBAL *crngt_glob 116 = ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_RAND_CRNGT_INDEX, 117 &rand_crng_ossl_ctx_method); 118 OSSL_CALLBACK *stcb = NULL; 119 void *stcbarg = NULL; 120 OSSL_SELF_TEST *st = NULL; 121 122 if (crngt_glob == NULL) 123 return 0; 124 125 if (!CRYPTO_THREAD_write_lock(crngt_glob->lock)) 126 return 0; 127 128 if (!crngt_glob->preloaded) { 129 if (!crngt_get_entropy(drbg->provctx, crngt_glob->md, buf, 130 crngt_glob->crngt_prev, NULL)) { 131 OPENSSL_cleanse(buf, sizeof(buf)); 132 goto unlock_return; 133 } 134 crngt_glob->preloaded = 1; 135 } 136 137 /* 138 * Calculate how many bytes of seed material we require, rounded up 139 * to the nearest byte. If the entropy is of less than full quality, 140 * the amount required should be scaled up appropriately here. 141 */ 142 bytes_needed = (entropy + 7) / 8; 143 if (bytes_needed < min_len) 144 bytes_needed = min_len; 145 if (bytes_needed > max_len) 146 goto unlock_return; 147 entp = ent = OPENSSL_secure_malloc(bytes_needed); 148 if (ent == NULL) 149 goto unlock_return; 150 151 OSSL_SELF_TEST_get_callback(libctx, &stcb, &stcbarg); 152 if (stcb != NULL) { 153 st = OSSL_SELF_TEST_new(stcb, stcbarg); 154 if (st == NULL) 155 goto err; 156 OSSL_SELF_TEST_onbegin(st, OSSL_SELF_TEST_TYPE_CRNG, 157 OSSL_SELF_TEST_DESC_RNG); 158 } 159 160 for (t = bytes_needed; t > 0;) { 161 /* Care needs to be taken to avoid overrunning the buffer */ 162 s = t >= CRNGT_BUFSIZ ? CRNGT_BUFSIZ : t; 163 entbuf = t >= CRNGT_BUFSIZ ? entp : buf; 164 if (!crngt_get_entropy(drbg->provctx, crngt_glob->md, entbuf, md, &sz)) 165 goto err; 166 if (t < CRNGT_BUFSIZ) 167 memcpy(entp, buf, t); 168 /* Force a failure here if the callback returns 1 */ 169 if (OSSL_SELF_TEST_oncorrupt_byte(st, md)) 170 memcpy(md, crngt_glob->crngt_prev, sz); 171 if (!prov_crngt_compare_previous(crngt_glob->crngt_prev, md, sz)) { 172 crng_test_pass = 0; 173 goto err; 174 } 175 /* Update for next block */ 176 memcpy(crngt_glob->crngt_prev, md, sz); 177 entp += s; 178 t -= s; 179 } 180 r = bytes_needed; 181 *pout = ent; 182 ent = NULL; 183 184 err: 185 OSSL_SELF_TEST_onend(st, crng_test_pass); 186 OSSL_SELF_TEST_free(st); 187 OPENSSL_secure_clear_free(ent, bytes_needed); 188 189 unlock_return: 190 CRYPTO_THREAD_unlock(crngt_glob->lock); 191 return r; 192 } 193 194 void ossl_crngt_cleanup_entropy(ossl_unused PROV_DRBG *drbg, 195 unsigned char *out, size_t outlen) 196 { 197 OPENSSL_secure_clear_free(out, outlen); 198 } 199