2 * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
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
12 #include <openssl/core.h>
13 #include <openssl/core_numbers.h>
14 #include <openssl/core_names.h>
15 #include <openssl/params.h>
16 #include <openssl/err.h>
17 #include <openssl/evp.h>
19 /* TODO(3.0): Needed for dummy_evp_call(). To be removed */
20 #include <openssl/sha.h>
21 #include <openssl/rand_drbg.h>
23 #include "internal/cryptlib.h"
24 #include "internal/property.h"
25 #include "internal/evp_int.h"
26 #include "internal/provider_algs.h"
27 #include "internal/provider_ctx.h"
28 #include "internal/providercommon.h"
31 * TODO(3.0): Should these be stored in the provider side provctx? Could they
32 * ever be different from one init to the next? Unfortunately we can't do this
33 * at the moment because c_put_error/c_add_error_vdata do not provide us with
34 * the OPENSSL_CTX as a parameter.
36 /* Functions provided by the core */
37 static OSSL_core_get_param_types_fn
*c_get_param_types
= NULL
;
38 static OSSL_core_get_params_fn
*c_get_params
= NULL
;
39 extern OSSL_core_thread_start_fn
*c_thread_start
;
40 OSSL_core_thread_start_fn
*c_thread_start
= NULL
;
41 static OSSL_core_put_error_fn
*c_put_error
= NULL
;
42 static OSSL_core_add_error_vdata_fn
*c_add_error_vdata
= NULL
;
44 typedef struct fips_global_st
{
45 const OSSL_PROVIDER
*prov
;
48 static void *fips_prov_ossl_ctx_new(OPENSSL_CTX
*libctx
)
50 FIPS_GLOBAL
*fgbl
= OPENSSL_zalloc(sizeof(*fgbl
));
55 static void fips_prov_ossl_ctx_free(void *fgbl
)
60 static const OPENSSL_CTX_METHOD fips_prov_ossl_ctx_method
= {
61 fips_prov_ossl_ctx_new
,
62 fips_prov_ossl_ctx_free
,
66 /* Parameters we provide to the core */
67 static const OSSL_ITEM fips_param_types
[] = {
68 { OSSL_PARAM_UTF8_PTR
, OSSL_PROV_PARAM_NAME
},
69 { OSSL_PARAM_UTF8_PTR
, OSSL_PROV_PARAM_VERSION
},
70 { OSSL_PARAM_UTF8_PTR
, OSSL_PROV_PARAM_BUILDINFO
},
74 /* TODO(3.0): To be removed */
75 static int dummy_evp_call(void *provctx
)
77 OPENSSL_CTX
*libctx
= PROV_LIBRARY_CONTEXT_OF(provctx
);
78 EVP_MD_CTX
*ctx
= EVP_MD_CTX_new();
79 EVP_MD
*sha256
= EVP_MD_fetch(libctx
, "SHA256", NULL
);
80 char msg
[] = "Hello World!";
81 const unsigned char exptd
[] = {
82 0x7f, 0x83, 0xb1, 0x65, 0x7f, 0xf1, 0xfc, 0x53, 0xb9, 0x2d, 0xc1, 0x81,
83 0x48, 0xa1, 0xd6, 0x5d, 0xfc, 0x2d, 0x4b, 0x1f, 0xa3, 0xd6, 0x77, 0x28,
84 0x4a, 0xdd, 0xd2, 0x00, 0x12, 0x6d, 0x90, 0x69
86 unsigned int dgstlen
= 0;
87 unsigned char dgst
[SHA256_DIGEST_LENGTH
];
90 BIGNUM
*a
= NULL
, *b
= NULL
;
91 unsigned char randbuf
[128];
92 RAND_DRBG
*drbg
= OPENSSL_CTX_get0_public_drbg(libctx
);
94 if (ctx
== NULL
|| sha256
== NULL
|| drbg
== NULL
)
97 if (!EVP_DigestInit_ex(ctx
, sha256
, NULL
))
99 if (!EVP_DigestUpdate(ctx
, msg
, sizeof(msg
) - 1))
101 if (!EVP_DigestFinal(ctx
, dgst
, &dgstlen
))
103 if (dgstlen
!= sizeof(exptd
) || memcmp(dgst
, exptd
, sizeof(exptd
)) != 0)
106 bnctx
= BN_CTX_new_ex(libctx
);
110 a
= BN_CTX_get(bnctx
);
111 b
= BN_CTX_get(bnctx
);
117 || BN_cmp(a
, b
) != 0)
120 if (RAND_DRBG_bytes(drbg
, randbuf
, sizeof(randbuf
)) <= 0)
128 EVP_MD_CTX_free(ctx
);
129 EVP_MD_meth_free(sha256
);
133 static const OSSL_ITEM
*fips_get_param_types(const OSSL_PROVIDER
*prov
)
135 return fips_param_types
;
138 static int fips_get_params(const OSSL_PROVIDER
*prov
, OSSL_PARAM params
[])
142 p
= OSSL_PARAM_locate(params
, OSSL_PROV_PARAM_NAME
);
143 if (p
!= NULL
&& !OSSL_PARAM_set_utf8_ptr(p
, "OpenSSL FIPS Provider"))
145 p
= OSSL_PARAM_locate(params
, OSSL_PROV_PARAM_VERSION
);
146 if (p
!= NULL
&& !OSSL_PARAM_set_utf8_ptr(p
, OPENSSL_VERSION_STR
))
148 p
= OSSL_PARAM_locate(params
, OSSL_PROV_PARAM_BUILDINFO
);
149 if (p
!= NULL
&& !OSSL_PARAM_set_utf8_ptr(p
, OPENSSL_FULL_VERSION_STR
))
155 /* FIPS specific version of the function of the same name in provlib.c */
156 const char *ossl_prov_util_nid_to_name(int nid
)
158 /* We don't have OBJ_nid2n() in FIPS_MODE so we have an explicit list */
186 case NID_aes_256_ecb
:
187 return "AES-256-ECB";
188 case NID_aes_192_ecb
:
189 return "AES-192-ECB";
190 case NID_aes_128_ecb
:
191 return "AES-128-ECB";
192 case NID_aes_256_cbc
:
193 return "AES-256-CBC";
194 case NID_aes_192_cbc
:
195 return "AES-192-CBC";
196 case NID_aes_128_cbc
:
197 return "AES-128-CBC";
198 case NID_aes_256_ctr
:
199 return "AES-256-CTR";
200 case NID_aes_192_ctr
:
201 return "AES-192-CTR";
202 case NID_aes_128_ctr
:
203 return "AES-128-CTR";
209 static const OSSL_ALGORITHM fips_digests
[] = {
210 { "SHA1", "fips=yes", sha1_functions
},
211 { "SHA224", "fips=yes", sha224_functions
},
212 { "SHA256", "fips=yes", sha256_functions
},
213 { "SHA384", "fips=yes", sha384_functions
},
214 { "SHA512", "fips=yes", sha512_functions
},
215 { "SHA512-224", "fips=yes", sha512_224_functions
},
216 { "SHA512-256", "fips=yes", sha512_256_functions
},
217 { "SHA3-224", "fips=yes", sha3_224_functions
},
218 { "SHA3-256", "fips=yes", sha3_256_functions
},
219 { "SHA3-384", "fips=yes", sha3_384_functions
},
220 { "SHA3-512", "fips=yes", sha3_512_functions
},
221 { "KMAC128", "fips=yes", keccak_kmac_128_functions
},
222 { "KMAC256", "fips=yes", keccak_kmac_256_functions
},
227 static const OSSL_ALGORITHM fips_ciphers
[] = {
228 { "AES-256-ECB", "fips=yes", aes256ecb_functions
},
229 { "AES-192-ECB", "fips=yes", aes192ecb_functions
},
230 { "AES-128-ECB", "fips=yes", aes128ecb_functions
},
231 { "AES-256-CBC", "fips=yes", aes256cbc_functions
},
232 { "AES-192-CBC", "fips=yes", aes192cbc_functions
},
233 { "AES-128-CBC", "fips=yes", aes128cbc_functions
},
234 { "AES-256-CTR", "fips=yes", aes256ctr_functions
},
235 { "AES-192-CTR", "fips=yes", aes192ctr_functions
},
236 { "AES-128-CTR", "fips=yes", aes128ctr_functions
},
240 static const OSSL_ALGORITHM
*fips_query(OSSL_PROVIDER
*prov
,
245 switch (operation_id
) {
254 /* Functions we provide to the core */
255 static const OSSL_DISPATCH fips_dispatch_table
[] = {
257 * To release our resources we just need to free the OPENSSL_CTX so we just
258 * use OPENSSL_CTX_free directly as our teardown function
260 { OSSL_FUNC_PROVIDER_TEARDOWN
, (void (*)(void))OPENSSL_CTX_free
},
261 { OSSL_FUNC_PROVIDER_GET_PARAM_TYPES
, (void (*)(void))fips_get_param_types
},
262 { OSSL_FUNC_PROVIDER_GET_PARAMS
, (void (*)(void))fips_get_params
},
263 { OSSL_FUNC_PROVIDER_QUERY_OPERATION
, (void (*)(void))fips_query
},
267 /* Functions we provide to ourself */
268 static const OSSL_DISPATCH intern_dispatch_table
[] = {
269 { OSSL_FUNC_PROVIDER_QUERY_OPERATION
, (void (*)(void))fips_query
},
274 int OSSL_provider_init(const OSSL_PROVIDER
*provider
,
275 const OSSL_DISPATCH
*in
,
276 const OSSL_DISPATCH
**out
,
282 for (; in
->function_id
!= 0; in
++) {
283 switch (in
->function_id
) {
284 case OSSL_FUNC_CORE_GET_PARAM_TYPES
:
285 c_get_param_types
= OSSL_get_core_get_param_types(in
);
287 case OSSL_FUNC_CORE_GET_PARAMS
:
288 c_get_params
= OSSL_get_core_get_params(in
);
290 case OSSL_FUNC_CORE_THREAD_START
:
291 c_thread_start
= OSSL_get_core_thread_start(in
);
293 case OSSL_FUNC_CORE_PUT_ERROR
:
294 c_put_error
= OSSL_get_core_put_error(in
);
296 case OSSL_FUNC_CORE_ADD_ERROR_VDATA
:
297 c_add_error_vdata
= OSSL_get_core_add_error_vdata(in
);
299 /* Just ignore anything we don't understand */
305 ctx
= OPENSSL_CTX_new();
309 fgbl
= openssl_ctx_get_data(ctx
, OPENSSL_CTX_FIPS_PROV_INDEX
,
310 &fips_prov_ossl_ctx_method
);
315 fgbl
->prov
= provider
;
317 *out
= fips_dispatch_table
;
321 * TODO(3.0): Remove me. This is just a dummy call to demonstrate making
322 * EVP calls from within the FIPS module.
324 if (!dummy_evp_call(*provctx
)) {
325 OPENSSL_CTX_free(*provctx
);
333 OPENSSL_CTX_free(ctx
);
338 * The internal init function used when the FIPS module uses EVP to call
339 * another algorithm also in the FIPS module. This is a recursive call that has
340 * been made from within the FIPS module itself. To make this work, we populate
341 * the provider context of this inner instance with the same library context
342 * that was used in the EVP call that initiated this recursive call.
344 OSSL_provider_init_fn fips_intern_provider_init
;
345 int fips_intern_provider_init(const OSSL_PROVIDER
*provider
,
346 const OSSL_DISPATCH
*in
,
347 const OSSL_DISPATCH
**out
,
350 OSSL_core_get_library_context_fn
*c_get_libctx
= NULL
;
352 for (; in
->function_id
!= 0; in
++) {
353 switch (in
->function_id
) {
354 case OSSL_FUNC_CORE_GET_LIBRARY_CONTEXT
:
355 c_get_libctx
= OSSL_get_core_get_library_context(in
);
362 if (c_get_libctx
== NULL
)
365 *provctx
= c_get_libctx(provider
);
368 * Safety measure... we should get the library context that was
369 * created up in OSSL_provider_init().
371 if (*provctx
== NULL
)
374 *out
= intern_dispatch_table
;
378 void ERR_put_error(int lib
, int func
, int reason
, const char *file
, int line
)
381 * TODO(3.0): This works for the FIPS module because we're going to be
382 * using lib/func/reason codes that libcrypto already knows about. This
383 * won't work for third party providers that have their own error mechanisms,
384 * so we'll need to come up with something else for them.
386 c_put_error(lib
, func
, reason
, file
, line
);
387 ERR_add_error_data(1, "(in the FIPS module)");
390 void ERR_add_error_data(int num
, ...)
395 ERR_add_error_vdata(num
, args
);
399 void ERR_add_error_vdata(int num
, va_list args
)
401 c_add_error_vdata(num
, args
);
404 const OSSL_PROVIDER
*FIPS_get_provider(OPENSSL_CTX
*ctx
)
406 FIPS_GLOBAL
*fgbl
= openssl_ctx_get_data(ctx
, OPENSSL_CTX_FIPS_PROV_INDEX
,
407 &fips_prov_ossl_ctx_method
);