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 <openssl/core_dispatch.h>
18 #include <openssl/params.h>
19 #include "prov/providercommon.h"
20 #include "prov/provider_ctx.h"
21 #include "internal/cryptlib.h"
22 #include "prov/rand_pool.h"
23 #include "drbg_local.h"
24 #include "prov/seeding.h"
26 typedef struct crng_test_global_st
{
27 unsigned char crngt_prev
[EVP_MAX_MD_SIZE
];
28 RAND_POOL
*crngt_pool
;
31 static int crngt_get_entropy(OPENSSL_CTX
*ctx
, RAND_POOL
*pool
,
32 unsigned char *buf
, unsigned char *md
,
33 unsigned int *md_size
)
43 n
= prov_pool_acquire_entropy(pool
);
44 if (n
>= CRNGT_BUFSIZ
) {
45 fmd
= EVP_MD_fetch(ctx
, "SHA256", "");
48 p
= rand_pool_detach(pool
);
49 r
= EVP_Digest(p
, CRNGT_BUFSIZ
, md
, md_size
, fmd
, NULL
);
51 memcpy(buf
, p
, CRNGT_BUFSIZ
);
52 rand_pool_reattach(pool
, p
);
59 static void rand_crng_ossl_ctx_free(void *vcrngt_glob
)
61 CRNG_TEST_GLOBAL
*crngt_glob
= vcrngt_glob
;
63 rand_pool_free(crngt_glob
->crngt_pool
);
64 OPENSSL_free(crngt_glob
);
67 static void *rand_crng_ossl_ctx_new(OPENSSL_CTX
*ctx
)
69 unsigned char buf
[CRNGT_BUFSIZ
];
70 CRNG_TEST_GLOBAL
*crngt_glob
= OPENSSL_zalloc(sizeof(*crngt_glob
));
72 if (crngt_glob
== NULL
)
75 if ((crngt_glob
->crngt_pool
76 = rand_pool_new(0, 1, CRNGT_BUFSIZ
, CRNGT_BUFSIZ
)) == NULL
) {
77 OPENSSL_free(crngt_glob
);
80 if (crngt_get_entropy(ctx
, crngt_glob
->crngt_pool
, buf
,
81 crngt_glob
->crngt_prev
, NULL
)) {
82 OPENSSL_cleanse(buf
, sizeof(buf
));
85 rand_pool_free(crngt_glob
->crngt_pool
);
86 OPENSSL_free(crngt_glob
);
90 static const OPENSSL_CTX_METHOD rand_crng_ossl_ctx_method
= {
91 rand_crng_ossl_ctx_new
,
92 rand_crng_ossl_ctx_free
,
95 size_t prov_crngt_get_entropy(PROV_DRBG
*drbg
,
97 int entropy
, size_t min_len
, size_t max_len
,
98 int prediction_resistance
)
100 unsigned char buf
[CRNGT_BUFSIZ
], md
[EVP_MAX_MD_SIZE
];
103 size_t q
, r
= 0, s
, t
= 0;
105 OPENSSL_CTX
*libctx
= PROV_LIBRARY_CONTEXT_OF(drbg
->provctx
);
106 CRNG_TEST_GLOBAL
*crngt_glob
107 = openssl_ctx_get_data(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(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 prov_crngt_cleanup_entropy(PROV_DRBG
*drbg
,
136 unsigned char *out
, size_t outlen
)
138 OPENSSL_secure_clear_free(out
, outlen
);