1 /* 2 * Copyright 2021-2025 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the Apache License 2.0 (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 10 #include <openssl/evp.h> 11 #include <openssl/rand.h> 12 #include <openssl/bio.h> 13 #include <openssl/core_names.h> 14 #include <openssl/params.h> 15 #include "crypto/rand.h" 16 #include "testutil.h" 17 18 static char *configfile; 19 20 static int test_rand(void) 21 { 22 EVP_RAND_CTX *privctx; 23 const OSSL_PROVIDER *prov; 24 int indicator = 1; 25 OSSL_PARAM params[2], *p = params; 26 unsigned char entropy1[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 }; 27 unsigned char entropy2[] = { 0xff, 0xfe, 0xfd }; 28 unsigned char nonce[] = { 0x00, 0x01, 0x02, 0x03, 0x04 }; 29 unsigned char outbuf[3]; 30 31 *p++ = OSSL_PARAM_construct_octet_string(OSSL_RAND_PARAM_TEST_ENTROPY, 32 entropy1, sizeof(entropy1)); 33 *p = OSSL_PARAM_construct_end(); 34 35 if (!TEST_ptr(privctx = RAND_get0_private(NULL)) 36 || !TEST_true(EVP_RAND_CTX_set_params(privctx, params)) 37 || !TEST_int_gt(RAND_priv_bytes(outbuf, sizeof(outbuf)), 0) 38 || !TEST_mem_eq(outbuf, sizeof(outbuf), entropy1, sizeof(outbuf)) 39 || !TEST_int_le(RAND_priv_bytes(outbuf, sizeof(outbuf) + 1), 0) 40 || !TEST_int_gt(RAND_priv_bytes(outbuf, sizeof(outbuf)), 0) 41 || !TEST_mem_eq(outbuf, sizeof(outbuf), 42 entropy1 + sizeof(outbuf), sizeof(outbuf))) 43 return 0; 44 45 *params = OSSL_PARAM_construct_octet_string(OSSL_RAND_PARAM_TEST_ENTROPY, 46 entropy2, sizeof(entropy2)); 47 if (!TEST_true(EVP_RAND_CTX_set_params(privctx, params)) 48 || !TEST_int_gt(RAND_priv_bytes(outbuf, sizeof(outbuf)), 0) 49 || !TEST_mem_eq(outbuf, sizeof(outbuf), entropy2, sizeof(outbuf))) 50 return 0; 51 52 *params = OSSL_PARAM_construct_octet_string(OSSL_RAND_PARAM_TEST_NONCE, 53 nonce, sizeof(nonce)); 54 if (!TEST_true(EVP_RAND_CTX_set_params(privctx, params)) 55 || !TEST_true(EVP_RAND_nonce(privctx, outbuf, sizeof(outbuf))) 56 || !TEST_mem_eq(outbuf, sizeof(outbuf), nonce, sizeof(outbuf))) 57 return 0; 58 59 if (fips_provider_version_lt(NULL, 3, 4, 0)) { 60 /* Skip the rest and pass the test */ 61 return 1; 62 } 63 /* Verify that the FIPS indicator can be read and is false */ 64 prov = EVP_RAND_get0_provider(EVP_RAND_CTX_get0_rand(privctx)); 65 if (prov != NULL 66 && strcmp(OSSL_PROVIDER_get0_name(prov), "fips") == 0) { 67 params[0] = OSSL_PARAM_construct_int(OSSL_RAND_PARAM_FIPS_APPROVED_INDICATOR, 68 &indicator); 69 if (!TEST_true(EVP_RAND_CTX_get_params(privctx, params)) 70 || !TEST_int_eq(indicator, 0)) 71 return 0; 72 } 73 return 1; 74 } 75 76 static int test_rand_uniform(void) 77 { 78 uint32_t x, i, j; 79 int err = 0, res = 0; 80 OSSL_LIB_CTX *ctx; 81 82 if (!test_get_libctx(&ctx, NULL, NULL, NULL, NULL)) 83 goto err; 84 85 for (i = 1; i < 100; i += 13) { 86 x = ossl_rand_uniform_uint32(ctx, i, &err); 87 if (!TEST_int_eq(err, 0) 88 || !TEST_uint_ge(x, 0) 89 || !TEST_uint_lt(x, i)) 90 return 0; 91 } 92 for (i = 1; i < 100; i += 17) 93 for (j = i + 1; j < 150; j += 11) { 94 x = ossl_rand_range_uint32(ctx, i, j, &err); 95 if (!TEST_int_eq(err, 0) 96 || !TEST_uint_ge(x, i) 97 || !TEST_uint_lt(x, j)) 98 return 0; 99 } 100 101 res = 1; 102 err: 103 OSSL_LIB_CTX_free(ctx); 104 return res; 105 } 106 107 /* Test the FIPS health tests */ 108 static int fips_health_test_one(const uint8_t *buf, size_t n, size_t gen) 109 { 110 int res = 0; 111 EVP_RAND *crngt_alg = NULL, *parent_alg = NULL; 112 EVP_RAND_CTX *crngt = NULL, *parent = NULL; 113 OSSL_PARAM p[2]; 114 uint8_t out[1000]; 115 int indicator = -1; 116 117 p[0] = OSSL_PARAM_construct_octet_string(OSSL_RAND_PARAM_TEST_ENTROPY, 118 (void *)buf, n); 119 p[1] = OSSL_PARAM_construct_end(); 120 121 if (!TEST_ptr(parent_alg = EVP_RAND_fetch(NULL, "TEST-RAND", "-fips")) 122 || !TEST_ptr(crngt_alg = EVP_RAND_fetch(NULL, "CRNG-TEST", "-fips")) 123 || !TEST_ptr(parent = EVP_RAND_CTX_new(parent_alg, NULL)) 124 || !TEST_ptr(crngt = EVP_RAND_CTX_new(crngt_alg, parent)) 125 || !TEST_true(EVP_RAND_instantiate(parent, 0, 0, 126 (unsigned char *)"abc", 3, p)) 127 || !TEST_true(EVP_RAND_instantiate(crngt, 0, 0, 128 (unsigned char *)"def", 3, NULL)) 129 || !TEST_size_t_le(gen, sizeof(out))) 130 goto err; 131 132 /* Verify that the FIPS indicator is negative */ 133 p[0] = OSSL_PARAM_construct_int(OSSL_RAND_PARAM_FIPS_APPROVED_INDICATOR, 134 &indicator); 135 if (!TEST_true(EVP_RAND_CTX_get_params(crngt, p)) 136 || !TEST_int_le(indicator, 0)) 137 goto err; 138 139 ERR_set_mark(); 140 res = EVP_RAND_generate(crngt, out, gen, 0, 0, NULL, 0); 141 ERR_pop_to_mark(); 142 err: 143 EVP_RAND_CTX_free(crngt); 144 EVP_RAND_CTX_free(parent); 145 EVP_RAND_free(crngt_alg); 146 EVP_RAND_free(parent_alg); 147 return res; 148 } 149 150 static int fips_health_tests(void) 151 { 152 uint8_t buf[1000]; 153 size_t i; 154 155 /* Verify tests can pass */ 156 for (i = 0; i < sizeof(buf); i++) 157 buf[i] = 0xff & i; 158 if (!TEST_true(fips_health_test_one(buf, i, i))) 159 return 0; 160 161 /* Verify RCT can fail */ 162 for (i = 0; i < 20; i++) 163 buf[i] = 0xff & (i > 10 ? 200 : i); 164 if (!TEST_false(fips_health_test_one(buf, i, i))) 165 return 0; 166 167 /* Verify APT can fail */ 168 for (i = 0; i < sizeof(buf); i++) 169 buf[i] = 0xff & (i >= 512 && i % 8 == 0 ? 0x80 : i); 170 if (!TEST_false(fips_health_test_one(buf, i, i))) 171 return 0; 172 return 1; 173 } 174 175 typedef struct r_test_ctx { 176 const OSSL_CORE_HANDLE *handle; 177 } R_TEST_CTX; 178 179 static void r_teardown(void *provctx) 180 { 181 R_TEST_CTX *ctx = (R_TEST_CTX *)provctx; 182 183 free(ctx); 184 } 185 186 static int r_random_bytes(ossl_unused void *vprov, ossl_unused int which, 187 void *buf, size_t n, ossl_unused unsigned int strength) 188 { 189 while (n-- > 0) 190 ((unsigned char *)buf)[n] = 0xff & n; 191 return 1; 192 } 193 194 static const OSSL_DISPATCH r_test_table[] = { 195 { OSSL_FUNC_PROVIDER_RANDOM_BYTES, (void (*)(void))r_random_bytes }, 196 { OSSL_FUNC_PROVIDER_TEARDOWN, (void (*)(void))r_teardown }, 197 OSSL_DISPATCH_END 198 }; 199 200 static int r_init(const OSSL_CORE_HANDLE *handle, 201 ossl_unused const OSSL_DISPATCH *oin, 202 const OSSL_DISPATCH **out, 203 void **provctx) 204 { 205 R_TEST_CTX *ctx; 206 207 ctx = malloc(sizeof(*ctx)); 208 if (ctx == NULL) 209 return 0; 210 ctx->handle = handle; 211 212 *provctx = (void *)ctx; 213 *out = r_test_table; 214 return 1; 215 } 216 217 static int test_rand_random_provider(void) 218 { 219 OSSL_LIB_CTX *ctx = NULL; 220 OSSL_PROVIDER *prov = NULL; 221 int res = 0; 222 static const unsigned char data[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; 223 unsigned char buf[sizeof(data)], privbuf[sizeof(data)]; 224 225 memset(buf, 255, sizeof(buf)); 226 memset(privbuf, 255, sizeof(privbuf)); 227 228 if (!test_get_libctx(&ctx, NULL, NULL, NULL, NULL) 229 || !TEST_true(OSSL_PROVIDER_add_builtin(ctx, "r_prov", &r_init)) 230 || !TEST_ptr(prov = OSSL_PROVIDER_try_load(ctx, "r_prov", 1)) 231 || !TEST_true(RAND_set1_random_provider(ctx, prov)) 232 || !RAND_bytes_ex(ctx, buf, sizeof(buf), 256) 233 || !TEST_mem_eq(buf, sizeof(buf), data, sizeof(data)) 234 || !RAND_priv_bytes_ex(ctx, privbuf, sizeof(privbuf), 256) 235 || !TEST_mem_eq(privbuf, sizeof(privbuf), data, sizeof(data))) 236 goto err; 237 238 /* Test we can revert to not using the provider based randomness */ 239 if (!TEST_true(RAND_set1_random_provider(ctx, NULL)) 240 || !RAND_bytes_ex(ctx, buf, sizeof(buf), 256) 241 || !TEST_mem_ne(buf, sizeof(buf), data, sizeof(data))) 242 goto err; 243 244 /* And back to the provided randomness */ 245 if (!TEST_true(RAND_set1_random_provider(ctx, prov)) 246 || !RAND_bytes_ex(ctx, buf, sizeof(buf), 256) 247 || !TEST_mem_eq(buf, sizeof(buf), data, sizeof(data))) 248 goto err; 249 250 res = 1; 251 err: 252 OSSL_PROVIDER_unload(prov); 253 OSSL_LIB_CTX_free(ctx); 254 return res; 255 } 256 257 static int test_rand_get0_primary(void) 258 { 259 OSSL_LIB_CTX *ctx = OSSL_LIB_CTX_new(); 260 int res = 0; 261 262 if (!TEST_ptr(ctx)) 263 return 0; 264 265 if (!TEST_true(OSSL_LIB_CTX_load_config(ctx, configfile))) 266 goto err; 267 268 /* We simply test that we get a valid primary */ 269 if (!TEST_ptr(RAND_get0_primary(ctx))) 270 goto err; 271 272 res = 1; 273 err: 274 OSSL_LIB_CTX_free(ctx); 275 return res; 276 } 277 278 int setup_tests(void) 279 { 280 if (!test_skip_common_options()) { 281 TEST_error("Error parsing test options\n"); 282 return 0; 283 } 284 285 if (!TEST_ptr(configfile = test_get_argument(0)) 286 || !TEST_true(RAND_set_DRBG_type(NULL, "TEST-RAND", "fips=no", 287 NULL, NULL)) 288 || (fips_provider_version_ge(NULL, 3, 0, 8) 289 && !TEST_true(OSSL_LIB_CTX_load_config(NULL, configfile)))) 290 return 0; 291 292 ADD_TEST(test_rand); 293 ADD_TEST(test_rand_uniform); 294 295 if (OSSL_PROVIDER_available(NULL, "fips") 296 && fips_provider_version_ge(NULL, 3, 4, 0)) 297 ADD_TEST(fips_health_tests); 298 299 ADD_TEST(test_rand_random_provider); 300 301 if (!OSSL_PROVIDER_available(NULL, "fips") 302 || fips_provider_version_ge(NULL, 3, 5, 1)) 303 ADD_TEST(test_rand_get0_primary); 304 return 1; 305 } 306