2 * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
3 * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
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
12 * Implementation of the FIPS 140-2 section 4.9.2 Conditional Tests.
16 #include <openssl/evp.h>
17 #include "internal/rand_int.h"
18 #include "internal/thread_once.h"
19 #include "internal/cryptlib.h"
22 typedef struct crng_test_global_st
{
23 unsigned char crngt_prev
[EVP_MAX_MD_SIZE
];
24 RAND_POOL
*crngt_pool
;
27 int (*crngt_get_entropy
)(OPENSSL_CTX
*, RAND_POOL
*, unsigned char *,
28 unsigned char *, unsigned int *)
29 = &rand_crngt_get_entropy_cb
;
31 static void rand_crng_ossl_ctx_free(void *vcrngt_glob
)
33 CRNG_TEST_GLOBAL
*crngt_glob
= vcrngt_glob
;
35 rand_pool_free(crngt_glob
->crngt_pool
);
36 OPENSSL_free(crngt_glob
);
39 static void *rand_crng_ossl_ctx_new(OPENSSL_CTX
*ctx
)
41 unsigned char buf
[CRNGT_BUFSIZ
];
42 CRNG_TEST_GLOBAL
*crngt_glob
= OPENSSL_zalloc(sizeof(*crngt_glob
));
44 if (crngt_glob
== NULL
)
47 if ((crngt_glob
->crngt_pool
48 = rand_pool_new(0, 1, CRNGT_BUFSIZ
, CRNGT_BUFSIZ
)) == NULL
) {
49 OPENSSL_free(crngt_glob
);
52 if (crngt_get_entropy(ctx
, crngt_glob
->crngt_pool
, buf
,
53 crngt_glob
->crngt_prev
, NULL
)) {
54 OPENSSL_cleanse(buf
, sizeof(buf
));
57 rand_pool_free(crngt_glob
->crngt_pool
);
58 OPENSSL_free(crngt_glob
);
62 static const OPENSSL_CTX_METHOD rand_crng_ossl_ctx_method
= {
63 rand_crng_ossl_ctx_new
,
64 rand_crng_ossl_ctx_free
,
67 int rand_crngt_get_entropy_cb(OPENSSL_CTX
*ctx
,
71 unsigned int *md_size
)
80 n
= rand_pool_acquire_entropy(pool
);
81 if (n
>= CRNGT_BUFSIZ
) {
82 EVP_MD
*fmd
= EVP_MD_fetch(ctx
, "SHA256", "");
85 p
= rand_pool_detach(pool
);
86 r
= EVP_Digest(p
, CRNGT_BUFSIZ
, md
, md_size
, fmd
, NULL
);
88 memcpy(buf
, p
, CRNGT_BUFSIZ
);
89 rand_pool_reattach(pool
, p
);
96 size_t rand_crngt_get_entropy(RAND_DRBG
*drbg
,
98 int entropy
, size_t min_len
, size_t max_len
,
99 int prediction_resistance
)
101 unsigned char buf
[CRNGT_BUFSIZ
], md
[EVP_MAX_MD_SIZE
];
104 size_t q
, r
= 0, s
, t
= 0;
106 CRNG_TEST_GLOBAL
*crngt_glob
107 = openssl_ctx_get_data(drbg
->libctx
, OPENSSL_CTX_RAND_CRNGT_INDEX
,
108 &rand_crng_ossl_ctx_method
);
110 if (crngt_glob
== NULL
)
113 if ((pool
= rand_pool_new(entropy
, 1, min_len
, max_len
)) == NULL
)
116 while ((q
= rand_pool_bytes_needed(pool
, 1)) > 0 && attempts
-- > 0) {
117 s
= q
> sizeof(buf
) ? sizeof(buf
) : q
;
118 if (!crngt_get_entropy(drbg
->libctx
, crngt_glob
->crngt_pool
, buf
, md
,
120 || memcmp(crngt_glob
->crngt_prev
, md
, sz
) == 0
121 || !rand_pool_add(pool
, buf
, s
, s
* 8))
123 memcpy(crngt_glob
->crngt_prev
, md
, sz
);
128 *pout
= rand_pool_detach(pool
);
130 OPENSSL_cleanse(buf
, sizeof(buf
));
131 rand_pool_free(pool
);
135 void rand_crngt_cleanup_entropy(RAND_DRBG
*drbg
,
136 unsigned char *out
, size_t outlen
)
138 OPENSSL_secure_clear_free(out
, outlen
);