diff options
author | Shane Lontis <shane.lontis@oracle.com> | 2021-03-28 17:22:40 +1000 |
---|---|---|
committer | Matt Caswell <matt@openssl.org> | 2021-05-20 08:44:08 +0100 |
commit | b7140b0604bdfaa034452d97648a9c23a97568e4 (patch) | |
tree | 5388565fe46f81f1b6fc291573c4ea1c08001437 /README-FIPS.md | |
parent | 6e495312fda0e669d105172c1ac8a8c0bf52da6d (diff) |
Add migration guide for 3.0
Reviewed-by: Paul Dale <pauli@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/14710)
Diffstat (limited to 'README-FIPS.md')
-rw-r--r-- | README-FIPS.md | 407 |
1 files changed, 3 insertions, 404 deletions
diff --git a/README-FIPS.md b/README-FIPS.md index 3dc6c35b89..a8be9ddb31 100644 --- a/README-FIPS.md +++ b/README-FIPS.md @@ -58,411 +58,10 @@ If you configured OpenSSL to be installed to a different location, the paths wil vary accordingly. In the rare case that you need to install the fipsmodule.cnf to non-standard location, you can execute the `openssl fipsinstall` command manually. - Using the FIPS Module in applications ===================================== -There are a number of different ways that OpenSSL can be used in conjunction -with the FIPS module. Which is the correct approach to use will depend on your -own specific circumstances and what you are attempting to achieve. Note that the -old functions `FIPS_mode()` and `FIPS_mode_set()` are no longer present so you -must remove them from your application if you use them. - -Applications written to use the OpenSSL 3.0 FIPS module should not use any -legacy APIs or features that avoid the FIPS module. Specifically this includes: - -- Low level cryptographic APIs (use the high level APIs, such as EVP, instead) -- Engines -- Any functions that create or modify custom "METHODS" (for example -`EVP_MD_meth_new`, `EVP_CIPHER_meth_new`, `EVP_PKEY_meth_new`, `RSA_meth_new`, -`EC_KEY_METHOD_new`, etc.) - -All of the above APIs are deprecated in OpenSSL 3.0 - so a simple rule is to -avoid using all deprecated functions. - -Making all applications use the FIPS module by default ------------------------------------------------------- - -One simple approach is to cause all applications that are using OpenSSL to only -use the FIPS module for cryptographic algorithms by default. - -This approach can be done purely via configuration. As long as applications are -built and linked against OpenSSL 3.0 and do not override the loading of the -default config file or its settings then they can automatically start using the -FIPS module without the need for any further code changes. - -To do this the default OpenSSL config file will have to be modified. The -location of this config file will depend on the platform, and any options that -were given during the build process. You can check the location of the config -file by running this command: - - $ openssl version -d - OPENSSLDIR: "/usr/local/ssl" - -Caution: Many Operating Systems install OpenSSL by default. It is a common error -to not have the correct version of OpenSSL on your $PATH. Check that you are -running an OpenSSL 3.0 version like this: - - $ openssl version -v - OpenSSL 3.0.0-dev xx XXX xxxx (Library: OpenSSL 3.0.0-dev xx XXX xxxx) - -The OPENSSLDIR value above gives the directory name for where the default config -file is stored. So in this case the default config file will be called -`/usr/local/ssl/openssl.cnf` - -Edit the config file to add the following lines near the beginning: - - openssl_conf = openssl_init - - .include /usr/local/ssl/fipsmodule.cnf - - [openssl_init] - providers = provider_sect - - [provider_sect] - fips = fips_sect - base = base_sect - - [base_sect] - activate = 1 - -Obviously the include file location above should match the name of the FIPS -module config file that you installed earlier. - -Any applications that use OpenSSL 3.0 and are started after these changes are -made will start using only the FIPS module unless those applications take -explicit steps to avoid this default behaviour. Note that this configuration -also activates the "base" provider. The base provider does not include any -cryptographic algorithms (and therefore does not impact the validation status of -any cryptographic operations), but does include other supporting algorithms that -may be required. It is designed to be used in conjunction with the FIPS module. - -This approach has the primary advantage that it is simple, and no code changes -are required in applications in order to benefit from the FIPS module. There are -some disadvantages to this approach: - -- You may not want all applications to use the FIPS module. It may be the case -that some applications should and some should not. -- If applications take explicit steps to not load the default config file or set -different settings then this method will not work for them -- The algorithms available in the FIPS module are a subset of the algorithms -that are available in the default OpenSSL Provider. If those applications -attempt to use any algorithms that are not present, then they will fail. -- Usage of certain deprecated APIs avoids the use of the FIPS module. If any -applications use those APIs then the FIPS module will not be used. - -Selectively making applications use the FIPS module by default --------------------------------------------------------------- - -A variation on the above approach is to do the same thing on an individual -application basis. The default OpenSSL config file depends on the compiled in -value for OPENSSLDIR as described in the section above. However it is also -possible to override the config file to be used via the `OPENSSL_CONF` -environment variable. For example the following on Unix will cause the -application to be executed with a non-standard config file location: - - $ OPENSSL_CONF=/my/non-default/openssl.cnf myapplication - -Using this mechanism you can control which config file is loaded (and hence -whether the FIPS module is loaded) on an application by application basis. - -This removes the disadvantage listed above that you may not want all -applications to use the FIPS module. All the other advantages and disadvantages -still apply. - -Programmatically loading the FIPS module (default library context) ------------------------------------------------------------------- - -Applications may choose to load the FIPS provider explicitly rather than relying -on config to do this. The config file is still necessary in order to hold the -FIPS module config data (such as its self test status and integrity data). But -in this case we do not automatically activate the FIPS provider via that config -file. - -To do things this way configure as per the section "Making all applications use -the FIPS module by default" above, but edit the `fipsmodule.cnf` file to remove -or comment out the line which says `activate = 1` (note that setting this value -to 0 is **not** sufficient). This means all the required config information will -be available to load the FIPS module, but it is not actually automatically -loaded when the application starts. The FIPS provider can then be loaded -programmatically like this: - - #include <openssl/provider.h> - - int main(void) - { - OSSL_PROVIDER *fips; - OSSL_PROVIDER *base; - - fips = OSSL_PROVIDER_load(NULL, "fips"); - if (fips == NULL) { - printf("Failed to load FIPS provider\n"); - exit(EXIT_FAILURE); - } - base = OSSL_PROVIDER_load(NULL, "base"); - if (base == NULL) { - OSSL_PROVIDER_unload(fips); - printf("Failed to load base provider\n"); - exit(EXIT_FAILURE); - } - - /* Rest of application */ - - OSSL_PROVIDER_unload(base); - OSSL_PROVIDER_unload(fips); - exit(EXIT_SUCCESS); - } - -Note that this should be one of the first things that you do in your -application. If any OpenSSL functions get called that require the use of -cryptographic functions before this occurs then, if no provider has yet been -loaded, then the default provider will be automatically loaded. If you then -later explicitly load the FIPS provider then you will have both the FIPS and the -default provider loaded at the same time. It is undefined which implementation -of an algorithm will be used if multiple implementations are available and you -have not explicitly specified via a property query (see below) which one should -be used. - -Also note that in this example we have additionally loaded the "base" provider. -This loads a sub-set of algorithms that are also available in the default -provider - specifically non cryptographic ones which may be used in conjunction -with the FIPS provider. For example this contains algorithms for encoding and -decoding keys. If you decide not to load the default provider then you -will usually want to load the base provider instead. - -In this example we are using the "default" library context. OpenSSL functions -operate within the scope of a library context. If no library context is -explicitly specified then the default library context is used. For further -details about library contexts see the `OSSL_LIB_CTX(3)` man page. - -Loading the FIPS module at the same time as other providers ------------------------------------------------------------ - -It is possible to have the FIPS provider and other providers (such as the -default provider) all loaded at the same time into the same library context. You -can use a property query string during algorithm fetches to specify which -implementation you would like to use. - -For example to fetch an implementation of SHA256 which conforms to FIPS -standards you can specify the property query `fips=yes` like this: - - EVP_MD *sha256; - - sha256 = EVP_MD_fetch(NULL, "SHA2-256", "fips=yes"); - -If no property query is specified, or more than one implementation matches the -property query then it is undefined which implementation of a particular -algorithm will be returned. - -This example shows an explicit request for an implementation of SHA256 from the -default provider: - - EVP_MD *sha256; - - sha256 = EVP_MD_fetch(NULL, "SHA2-256", "provider=default"); - -It is also possible to set a default property query string. The following -example sets the default property query of "fips=yes" for all fetches within the -default library context: - - EVP_set_default_properties(NULL, "fips=yes"); - -If a fetch function has both an explicit property query specified, and a -default property query is defined then the two queries are merged together and -both apply. The local property query overrides the default properties if the -same property name is specified in both. - -There are two important built-in properties that you should be aware of: - -The "provider" property enables you to specify which provider you want an -implementation to be fetched from, e.g. `provider=default` or `provider=fips`. -All algorithms implemented in a provider have this property set on them. - -There is also the `fips` property. All FIPS algorithms match against the -property query `fips=yes`. There are also some non-cryptographic algorithms -available in the default and base providers that also have the `fips=yes` -property defined for them. These are the encoder and decoder algorithms that -can (for example) be used to write out a key generated in the FIPS provider to a -file. The encoder and decoder algorithms are not in the FIPS module itself but -are allowed to be used in conjunction with the FIPS algorithms. - -It is possible to specify default properties within a config file. For example -the following config file automatically loads the default and fips providers and -sets the default property value to be `fips=yes`. Note that this config file -does not load the "base" provider. All supporting algorithms that are in "base" -are also in "default", so it is unnecessary in this case: - - openssl_conf = openssl_init - - .include /usr/local/ssl/fipsmodule.cnf - - [openssl_init] - providers = provider_sect - alg_section = algorithm_sect - - [provider_sect] - fips = fips_sect - default = default_sect - - [default_sect] - activate = 1 - - [algorithm_sect] - default_properties = fips=yes - -Programmatically loading the FIPS module (non-default library context) ----------------------------------------------------------------------- - -In addition to using properties to separate usage of the FIPS module from other -usages this can also be achieved using library contexts. In this example we -create two library contexts. In one we assume the existence of a config file -called "openssl-fips.cnf" that automatically loads and configures the FIPS and -base providers. The other library context will just use the default provider. - - OSSL_LIB_CTX *fipslibctx, *nonfipslibctx; - OSSL_PROVIDER *defctxnull = NULL; - EVP_MD *fipssha256 = NULL, *nonfipssha256 = NULL; - int ret = 1; - - /* - * Create two non-default library contexts. One for fips usage and one for - * non-fips usage - */ - fipslibctx = OSSL_LIB_CTX_new(); - nonfipslibctx = OSSL_LIB_CTX_new(); - if (fipslibctx == NULL || nonfipslibctx == NULL) - goto err; - - /* Prevent anything from using the default library context */ - defctxnull = OSSL_PROVIDER_load(NULL, "null"); - - /* - * Load config file for the FIPS library context. We assume that this - * config file will automatically activate the FIPS and base providers so we - * don't need to explicitly load them here. - */ - if (!OSSL_LIB_CTX_load_config(fipslibctx, "openssl-fips.cnf")) - goto err; - - /* - * We don't need to do anything special to load the default provider into - * nonfipslibctx. This happens automatically if no other providers are - * loaded. Because we don't call OSSL_LIB_CTX_load_config() explicitly for - * nonfipslibctx it will just use the default config file. - */ - - /* As an example get some digests */ - - /* Get a FIPS validated digest */ - fipssha256 = EVP_MD_fetch(fipslibctx, "SHA2-256", NULL); - if (fipssha256 == NULL) - goto err; - - /* Get a non-FIPS validated digest */ - nonfipssha256 = EVP_MD_fetch(nonfipslibctx, "SHA2-256", NULL); - if (nonfipssha256 == NULL) - goto err; - - /* Use the digests */ - - printf("Success\n"); - ret = 0; - - err: - EVP_MD_free(fipssha256); - EVP_MD_free(nonfipssha256); - OSSL_LIB_CTX_free(fipslibctx); - OSSL_LIB_CTX_free(nonfipslibctx); - OSSL_PROVIDER_unload(defctxnull); - - return ret; - -Note that we have made use of the special "null" provider here which we load -into the default library context. We could have chosen to use the default -library context for FIPS usage, and just create one additional library context -for other usages - or vice versa. However if code has not been converted to use -library contexts then the default library context will be automatically used. -This could be the case for your own existing applications as well as certain -parts of OpenSSL itself. Not all parts of OpenSSL are library context aware. If -this happens then you could "accidentally" use the wrong library context for a -particular operation. To be sure this doesn't happen you can load the "null" -provider into the default library context. Because a provider has been -explicitly loaded, the default provider will not automatically load. This means -code using the default context by accident will fail because no algorithms will -be available. - -Using Encoders and Decoders with the FIPS module ------------------------------------------------- - -Encoders and decoders are used to read and write keys or parameters from or to -some external format (for example a PEM file). If your application generates -keys or parameters that then need to be written into PEM or DER format -then it is likely that you will need to use an encoder to do this. Similarly -you need a decoder to read previously saved keys and parameters. In most cases -this will be invisible to you if you are using APIs that existed in -OpenSSL 1.1.1 or earlier such as i2d_PrivateKey. However the appropriate -encoder/decoder will need to be available in the library context associated with -the key or parameter object. The built-in OpenSSL encoders and decoders are -implemented in both the default and base providers and are not in the FIPS -module boundary. However since they are not cryptographic algorithms themselves -it is still possible to use them in conjunction with the FIPS module, and -therefore these encoders/decoders have the "fips=yes" property against them. -You should ensure that either the default or base provider is loaded into the -library context in this case. - -Using the FIPS module in SSL/TLS --------------------------------- - -Writing an application that uses libssl in conjunction with the FIPS module is -much the same as writing a normal libssl application. If you are using global -properties and the default library context to specify usage of FIPS validated -algorithms then this will happen automatically for all cryptographic algorithms -in libssl. If you are using a non-default library context to load the FIPS -provider then you can supply this to libssl using the function -`SSL_CTX_new_ex()`. This works as a drop in replacement for the function -`SSL_CTX_new()` except it provides you with the capability to specify the -library context to be used. You can also use the same function to specify -libssl specific properties to use. - -In this first example we create two SSL_CTX objects using two different library -contexts. - - /* - * We assume that a non-default library context with the FIPS provider - * loaded has been created called fips_libctx. - / - SSL_CTX *fips_ssl_ctx = SSL_CTX_new_ex(fips_libctx, NULL, TLS_method()); - /* - * We assume that a non-default library context with the default provider - * loaded has been created called non_fips_libctx. - */ - SSL_CTX *non_fips_ssl_ctx = SSL_CTX_new_ex(non_fips_libctx, NULL, - TLS_method()); - -In this second example we create two SSL_CTX objects using different properties -to specify FIPS usage: - - /* - * The "fips=yes" property includes all FIPS approved algorithms as well as - * encoders from the default provider that are allowed to be used. The NULL - * below indicates that we are using the default library context. - */ - SSL_CTX *fips_ssl_ctx = SSL_CTX_new_ex(NULL, "fips=yes", TLS_method()); - /* - * The "provider!=fips" property allows algorithms from any provider except - * the FIPS provider - */ - SSL_CTX *non_fips_ssl_ctx = SSL_CTX_new_ex(NULL, "provider!=fips", - TLS_method()); - -Confirming that an algorithm is being provided by the FIPS module ------------------------------------------------------------------ - -A chain of links needs to be followed to go from an algorithm instance to the -provider that implements it. The process is similar for all algorithms. Here the -example of a digest is used. +Documentation about using the FIPS module is available on the [fips_module(7)] +manual page. -To go from an `EVP_MD_CTX` to an `EVP_MD`, use the `EVP_MD_CTX_md()` call. To go -from the `EVP_MD` to its `OSSL_PROVIDER`, use the `EVP_MD_provider()` call. To -extract the name from the `OSSL_PROVIDER`, use the `OSSL_PROVIDER_name()` call. -Finally, use `strcmp(3)` or `printf(3)` on the name. + [fips_module(7)]: https://www.openssl.org/docs/manmaster/man7/fips_module.html |