From 02d6cba14035db3c9ed4d072893e406e625b559d Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Tue, 14 Jan 2025 17:30:28 +0100 Subject: [PATCH 1/6] provider: Add new configuration option assume_fips When OpenSSL runs in FIPS Mode, it will not use any providers that do not provide a property fips=yes, rendering the pkcs11 provider unusable in FIPS Mode. This is a regression and for many users that need to have smart cards working in FIPS Mode. Unfortunately, proper signalization from pkcs11 modules regarding the tokens FIPS certification status is not standardized yet, this will be left up to the user to decide if the pkcs11 modules talk to FIPS certified token or not. This involves adjusting the algorithm lists to contain dynamic properties based on this configuration option, where we previously had hardcoded just provider=pkcs11. Fixes: #469, #164 Signed-off-by: Jakub Jelen --- docs/provider-pkcs11.7 | 192 +++++++++++++----------------- docs/provider-pkcs11.7.md | 25 +++- src/provider.c | 243 ++++++++++++++++++++++---------------- src/provider.h | 7 +- 4 files changed, 247 insertions(+), 220 deletions(-) diff --git a/docs/provider-pkcs11.7 b/docs/provider-pkcs11.7 index 7167e12b..aded3136 100644 --- a/docs/provider-pkcs11.7 +++ b/docs/provider-pkcs11.7 @@ -1,27 +1,10 @@ -.\" Automatically generated by Pandoc 3.1.3 +.\" Automatically generated by Pandoc 3.1.11.1 .\" -.\" Define V font for inline verbatim, using C font in formats -.\" that render this, and otherwise B font. -.ie "\f[CB]x\f[]"x" \{\ -. ftr V B -. ftr VI BI -. ftr VB B -. ftr VBI BI -.\} -.el \{\ -. ftr V CR -. ftr VI CI -. ftr VB CB -. ftr VBI CBI -.\} -.TH "provider-pkcs11" "7" "" "" "Configuration directives" -.hy +.TH "provider\-pkcs11" "7" "" "" "Configuration directives" .SH NAME -.PP -pkcs11-provider - An OpenSSL provider that allows to directly interface -with pkcs11 drivers. +pkcs11\-provider \- An OpenSSL provider that allows to directly +interface with pkcs11 drivers. .SH DESCRIPTION -.PP Starting with version 3.0 the OpenSSL project introduced a new modular system to extend OpenSSL that replaces the deprecated Engines modules. .PP @@ -35,13 +18,11 @@ PKCS#11(2) driver and the use of pkcs11 URIs(3). The pkcs11 provider can be configured to be automatically loaded via openssl.cnf .SH CONFIGURATION -.PP Configuration options recognized by the provider -.SS pkcs11-module-path -.PP +.SS pkcs11\-module\-path A file path to the pkcs11 driver to be used .PP -Default: If compiled with p11-kit defaults to its proxy driver, +Default: If compiled with p11\-kit defaults to its proxy driver, otherwise none. .PP NOTE: See also PKCS11_PROVIDER_MODULE in the environment variables @@ -49,10 +30,9 @@ section. .PP Example: .PP -\f[V]pkcs11-module-path = /usr/lib64/opensc-pkcs11.so\f[R] -.SS pkcs11-module-init-args -.PP -Non-standard initialization arguments some pkcs11 driver may need. +\f[CR]pkcs11\-module\-path = /usr/lib64/opensc\-pkcs11.so\f[R] +.SS pkcs11\-module\-init\-args +Non\-standard initialization arguments some pkcs11 driver may need. Generally not used, but some software tokens like NSS\[cq]s softokn require this. .PP @@ -60,9 +40,8 @@ Default: None .PP Example: .PP -\f[V]pkcs11-module-init-args = configDir=/etc/pki/token\f[R] -.SS pkcs11-module-token-pin -.PP +\f[CR]pkcs11\-module\-init\-args = configDir=/etc/pki/token\f[R] +.SS pkcs11\-module\-token\-pin The user PIN to be used with the token. If a PIN is not set in configuration it can be asked interactively (if the application uses prompters), or it can be specified together with @@ -74,19 +53,16 @@ Default: None .PP Example: .PP -\f[V]pkcs11-module-token-pin = file:/etc/pki/pin.txt\f[R] +\f[CR]pkcs11\-module\-token\-pin = file:/etc/pki/pin.txt\f[R] .IP -.nf -\f[C] +.EX cat /etc/pki/pin.txt 123456 -\f[R] -.fi -.SS pkcs11-module-allow-export -.PP +.EE +.SS pkcs11\-module\-allow\-export Whether the pkcs11 provider will allow to export public keys through OpenSSL. -OpenSSL often tries to export public keys from non-default providers to +OpenSSL often tries to export public keys from non\-default providers to the default provider, and then use OpenSSL own functions to handle whatever operation is associated with the public key. This option can be useful to force public key operations to be executed @@ -98,30 +74,28 @@ Default: 0 (Allow Export) .PP Example: .PP -\f[V]pkcs11-module-allow-export = 1\f[R] (This disallows export of +\f[CR]pkcs11\-module\-allow\-export = 1\f[R] (This disallows export of public keys) -.SS pkcs11-module-cache-keys -.PP -Whether the pkcs11-provider should ask the token to cache token keys in +.SS pkcs11\-module\-cache\-keys +Whether the pkcs11\-provider should ask the token to cache token keys in the session. This is used in some tokens as a performance optimizations. For example software tokens that store keys encrypted can keep a copy of the key in the session to speed up access. Or Networked HSMs that allow exporting key material can cache the key in -the session instead of re-requesting it over the network. +the session instead of re\-requesting it over the network. .PP Two options are available: * true * false .PP Default: true (Note: if the token does not support session caching, then -caching will be auto-disabled after the first attempt) +caching will be auto\-disabled after the first attempt) .PP Example: .PP -\f[V]pkcs11-module-cache-keys = false\f[R] (Disable any attempt of +\f[CR]pkcs11\-module\-cache\-keys = false\f[R] (Disable any attempt of caching keys in the session) -.SS pkcs11-module-cache-pins -.PP -Whether the pkcs11-provider should cache a pin entered interactively. +.SS pkcs11\-module\-cache\-pins +Whether the pkcs11\-provider should cache a pin entered interactively. This is useful to allow starting a service and providing the pin only manually, yet let the service perform multiple logins as needed, for example after forking. @@ -132,10 +106,9 @@ Default: unset (No caching) .PP Example: .PP -\f[V]pkcs11-module-cache-pins = cache\f[R] (Will cache a pin that has -been entered manually) -.SS pkcs11-module-cache-sessions -.PP +\f[CR]pkcs11\-module\-cache\-pins = cache\f[R] (Will cache a pin that +has been entered manually) +.SS pkcs11\-module\-cache\-sessions Allows to tune how many pkcs11 sessions may be kept open and cached for rapid use. This parameter is adjusted based on the maximum number of sessions the @@ -146,9 +119,8 @@ Default: 5 .PP Example: .PP -\f[V]pkcs11-module-cache-sessions = 0\f[R] (Disables caching) -.SS pkcs11-module-login-behavior -.PP +\f[CR]pkcs11\-module\-cache\-sessions = 0\f[R] (Disables caching) +.SS pkcs11\-module\-login\-behavior Whether the pkcs11 provider will attempt to login to the token when a public key is being requested. .PP @@ -161,11 +133,10 @@ Default: \[lq]auto\[rq] .PP Example: .PP -\f[V]pkcs11-module-login-behavior = always\f[R] (Always tries to login -before loading public keys) -.SS pkcs11-module-load-behavior -.PP -Whether the pkcs11-provider immediately loads an initializes the pkcs11 +\f[CR]pkcs11\-module\-login\-behavior = always\f[R] (Always tries to +login before loading public keys) +.SS pkcs11\-module\-load\-behavior +Whether the pkcs11\-provider immediately loads an initializes the pkcs11 module as soon as OpenSSL loads the provider (generally at application startup), or defer initialization until the first time a pkcs11 key is loaded (or some other operation explicitly requiring the pkcs11 provider @@ -178,34 +149,29 @@ Default: unset (Loads only at first use) .PP Example: .PP -\f[V]pkcs11-module-load-behavior = early\f[R] (Loads pkcs11 module +\f[CR]pkcs11\-module\-load\-behavior = early\f[R] (Loads pkcs11 module immediately at application startup) -.SS pkcs11-module-quirks -.PP +.SS pkcs11\-module\-quirks Workarounds that may be needed to deal with some tokens and cannot be autodetcted yet are not appropriate defaults. -.SS no-deinit -.PP -It prevents de-initing when OpenSSL winds down the provider. +.SS no\-deinit +It prevents de\-initing when OpenSSL winds down the provider. NOTE this option may leak memory and may cause some modules to misbehave if the application intentionally unloads and reloads them. -.SS no-operation-state -.PP +.SS no\-operation\-state OpenSSL by default assumes contexts with operations in flight can be easily duplicated. That is only possible if the tokens support getting and setting the operation state. If the quirk is enabled the context duplication is not performed. -.SS no-session-callbacks -.PP +.SS no\-session\-callbacks Some implementatations of PKCS11 don\[cq]t allow setting -\f[V]pApplication\f[R] and \f[V]Notify\f[R] callback functions in -\f[V]C_OpenSession\f[R]. +\f[CR]pApplication\f[R] and \f[CR]Notify\f[R] callback functions in +\f[CR]C_OpenSession\f[R]. This option sets NULL values for both callbacks. -.SS no-allowed-mechanisms -.PP +.SS no\-allowed\-mechanisms Some implementatations of PKCS11 don\[cq]t support -\f[V]CKA_ALLOWED_MECHANISMS\f[R] attribute on keys. +\f[CR]CKA_ALLOWED_MECHANISMS\f[R] attribute on keys. Setting this quirk prevents the provider from attempting to set and read this attribute. .PP @@ -213,10 +179,9 @@ Default: none .PP Example: .PP -\f[V]pkcs11-module-quirks = no-deinit no-operation-state\f[R] (Disables -deinitialization, blocks context duplication) -.SS pkcs11-module-block-operations -.PP +\f[CR]pkcs11\-module\-quirks = no\-deinit no\-operation\-state\f[R] +(Disables deinitialization, blocks context duplication) +.SS pkcs11\-module\-block\-operations Allows to block specific \[lq]provider operations\[rq] even if the token actually supports the necessary mechanisms. This is useful to work around cases where one wants to enforce use of @@ -230,27 +195,39 @@ Use carefully. .PP Default: none .PP -Example: \f[V]pkcs11-module-block-operations = digest\f[R] (Disables +Example: \f[CR]pkcs11\-module\-block\-operations = digest\f[R] (Disables digest mechanisms, which will be instead routed to the OpenSSL default provider in most configurtions) -.SH ENVIRONMENT VARIABLES +.SS pkcs11\-module\-assume\-fips +Assume the token used by the PKCS#11 module is FIPS certified. +.PP +Due to the incomplete specification for signalization of the +certification from the pkcs11 modules, this can not be determined +automatically. +If you know your token is FIPS certified, you need to set this +configuration option to true. +Otherwise the pkcs11\-provider will not work in FIPS Mode. +.PP +Default: False .PP +Example: +.PP +\f[CR]pkcs11\-module\-assume\-fips = true\f[R] +.SH ENVIRONMENT VARIABLES Environment variables recognized by the provider .SS PKCS11_PROVIDER_MODULE -.PP This variable can be used to set a different pkcs11 driver to be used. It is useful when an application needs to use a different driver than the rest of the system. -This environment variable \f[B]overrides\f[R] the pkcs11-module-path +This environment variable \f[B]overrides\f[R] the pkcs11\-module\-path option sets in openssl.cnf .PP Example: .PP -\f[V]PKCS11_PROVIDER_MODULE = /usr/lib64/opensc-pkcs11.so\f[R] +\f[CR]PKCS11_PROVIDER_MODULE = /usr/lib64/opensc\-pkcs11.so\f[R] .SS PKCS11_PROVIDER_DEBUG -.PP This variable can be set to obtain debug information. -Two sub-options can be specified: file, level +Two sub\-options can be specified: file, level .PP The normal debug_level is 1, if a higher level is provider then additional information (like all supported mechanism info for each slot) @@ -262,11 +239,10 @@ cannot be used in values. .PP Examples: .PP -\f[V]PKCS11_PROVIDER_DEBUG=file:/tmp/debug.log\f[R] +\f[CR]PKCS11_PROVIDER_DEBUG=file:/tmp/debug.log\f[R] .PP -\f[V]PKCS11_PROVIDER_DEBUG=file:/dev/stderr,level:2\f[R] +\f[CR]PKCS11_PROVIDER_DEBUG=file:/dev/stderr,level:2\f[R] .SH USE IN OLDER APPLICATIONS (URIs in PEM files) -.PP It is strongly suggested to update applications to use the new OSSL_STORE API provided by OpenSSL 3.0 which accepts URIs to transparenly load keys from either files or any other supported @@ -277,9 +253,9 @@ tool to generate a \[lq]wrapper\[rq] PEM file that contains the PKCS#11 URI needed to identify a key on the a token. .PP This PEM file can be loaded via the clasic methods used to parse PEM/DER -representations of keys and will trigger the use of the pkcs11-provider +representations of keys and will trigger the use of the pkcs11\-provider decoders when the provider is loaded. -An error will be returned if the provider is not pre-loaded or an older +An error will be returned if the provider is not pre\-loaded or an older version of OpenSSL is used. .PP In tools/uri2pem.py there is a sample python script that can take a key @@ -290,17 +266,13 @@ These files are not encrypted. The follwing command can be used to list all keys on a token and print their identifying URI: .IP -.nf -\f[C] -openssl storeutl -keys -text pkcs11: -\f[R] -.fi +.EX +openssl storeutl \-keys \-text pkcs11: +.EE .SH EXAMPLES -.PP openssl.cnf: .IP -.nf -\f[C] +.EX HOME = . # Use this in order to automatically load providers. @@ -317,18 +289,18 @@ pkcs11 = pkcs11_sect activate = 1 [pkcs11_sect] -module = /usr/lib64/ossl-modules/pkcs11.so -pkcs11-module-path = /usr/lib64/pkcs11/vendor_pkcs11.so -pkcs11-module-token-pin = /etc/ssl/pinfile.txt +module = /usr/lib64/ossl\-modules/pkcs11.so +pkcs11\-module\-path = /usr/lib64/pkcs11/vendor_pkcs11.so +pkcs11\-module\-token\-pin = /etc/ssl/pinfile.txt activate = 1 -\f[R] -.fi +.EE .SH SEE ALSO .IP "1." 3 -PROVIDER(7) man page - +PROVIDER(7) man page \- https://www.openssl.org/docs/manmaster/man7/provider.html .IP "2." 3 -PKCS#11 Technical committe and standards - -https://www.oasis-open.org/committees/tc_home.php?wg_abbrev=pkcs11 +PKCS#11 Technical committe and standards \- +https://www.oasis\-open.org/committees/tc_home.php?wg_abbrev=pkcs11 .IP "3." 3 -PKCS#11 URI Scheme - RFC 7512 - https://www.rfc-editor.org/rfc/rfc7512 +PKCS#11 URI Scheme \- RFC 7512 \- +https://www.rfc\-editor.org/rfc/rfc7512 diff --git a/docs/provider-pkcs11.7.md b/docs/provider-pkcs11.7.md index f21776df..c604aa4e 100644 --- a/docs/provider-pkcs11.7.md +++ b/docs/provider-pkcs11.7.md @@ -223,6 +223,21 @@ Example: (Disables digest mechanisms, which will be instead routed to the OpenSSL default provider in most configurtions) +## pkcs11-module-assume-fips + +Assume the token used by the PKCS#11 module is FIPS certified. + +Due to the incomplete specification for signalization of the certification +from the pkcs11 modules, this can not be determined automatically. If you +know your token is FIPS certified, you need to set this configuration option +to true. Otherwise the pkcs11-provider will not work in FIPS Mode. + +Default: False + +Example: + +```pkcs11-module-assume-fips = true``` + ENVIRONMENT VARIABLES ===================== @@ -292,20 +307,20 @@ EXAMPLES openssl.cnf: HOME = . - + # Use this in order to automatically load providers. openssl_conf = openssl_init - + [openssl_init] providers = provider_sect - + [provider_sect] default = default_sect pkcs11 = pkcs11_sect - + [default_sect] activate = 1 - + [pkcs11_sect] module = /usr/lib64/ossl-modules/pkcs11.so pkcs11-module-path = /usr/lib64/pkcs11/vendor_pkcs11.so diff --git a/src/provider.c b/src/provider.c index 1d4495e5..20a19842 100644 --- a/src/provider.c +++ b/src/provider.c @@ -31,6 +31,7 @@ struct p11prov_ctx { int cache_keys; int cache_sessions; bool encode_pkey_as_pk11_uri; + bool assume_fips; /* TODO: ui_method */ /* TODO: fork id */ @@ -52,7 +53,11 @@ struct p11prov_ctx { OSSL_ALGORITHM *op_exchange; OSSL_ALGORITHM *op_signature; OSSL_ALGORITHM *op_asym_cipher; + OSSL_ALGORITHM *op_encoder; + OSSL_ALGORITHM *op_decoder; + OSSL_ALGORITHM *op_keymgmt; + OSSL_ALGORITHM *op_store; pthread_rwlock_t quirk_lock; struct quirk *quirks; @@ -532,12 +537,13 @@ static void p11prov_ctx_free(P11PROV_CTX *ctx) OPENSSL_free(ctx->op_digest); OPENSSL_free(ctx->op_kdf); OPENSSL_free(ctx->op_random); - /* keymgmt is static */ OPENSSL_free(ctx->op_exchange); OPENSSL_free(ctx->op_signature); OPENSSL_free(ctx->op_asym_cipher); OPENSSL_free(ctx->op_encoder); - /* store is static */ + OPENSSL_free(ctx->op_decoder); + OPENSSL_free(ctx->op_keymgmt); + OPENSSL_free(ctx->op_store); OSSL_LIB_CTX_free(ctx->libctx); ctx->libctx = NULL; @@ -803,8 +809,8 @@ static CK_RV alg_set_op(OSSL_ALGORITHM **op, int idx, OSSL_ALGORITHM *alg) operation##_idx++; \ } while (0) -#define ADD_ALGO(NAME, name, operation) \ - ADD_ALGO_EXT(NAME, operation, P11PROV_DEFAULT_PROPERTIES, \ +#define ADD_ALGO(NAME, name, operation, prop) \ + ADD_ALGO_EXT(NAME, operation, prop, \ p11prov_##name##_##operation##_functions) #define TERM_ALGO(operation) \ @@ -872,6 +878,14 @@ static void alg_rm_mechs(CK_ULONG *checklist, CK_ULONG *rmlist, int *clsize, alg_rm_mechs(checklist, rmlist, &cl_size, rmsize); \ } while (0); +static const char *get_default_properties(P11PROV_CTX *ctx) +{ + if (ctx->assume_fips) { + return P11PROV_FIPS_PROPERTIES; + } + return P11PROV_DEFAULT_PROPERTIES; +} + static CK_RV operations_init(P11PROV_CTX *ctx) { P11PROV_SLOTS_CTX *slots; @@ -896,8 +910,8 @@ static CK_RV operations_init(P11PROV_CTX *ctx) int exchange_idx = 0; int signature_idx = 0; int asym_cipher_idx = 0; - int encoder_idx = 0; int slot_idx = 0; + const char *prop = get_default_properties(ctx); CK_RV ret; ret = p11prov_take_slots(ctx, &slots); @@ -980,69 +994,69 @@ static CK_RV operations_init(P11PROV_CTX *ctx) case CKM_ECDSA_SHA3_256: case CKM_ECDSA_SHA3_384: case CKM_ECDSA_SHA3_512: - ADD_ALGO(ECDSA, ecdsa, signature); + ADD_ALGO(ECDSA, ecdsa, signature, prop); UNCHECK_MECHS(CKM_EC_KEY_PAIR_GEN, ECDSA_SIG_MECHS); break; case CKM_ECDH1_DERIVE: case CKM_ECDH1_COFACTOR_DERIVE: - ADD_ALGO(ECDH, ecdh, exchange); + ADD_ALGO(ECDH, ecdh, exchange, prop); UNCHECK_MECHS(CKM_EC_KEY_PAIR_GEN, CKM_ECDH1_DERIVE, CKM_ECDH1_COFACTOR_DERIVE); break; case CKM_HKDF_DERIVE: - ADD_ALGO(HKDF, hkdf, kdf); - ADD_ALGO(TLS13_KDF, tls13, kdf); - ADD_ALGO(HKDF, hkdf, exchange); + ADD_ALGO(HKDF, hkdf, kdf, prop); + ADD_ALGO(TLS13_KDF, tls13, kdf, prop); + ADD_ALGO(HKDF, hkdf, exchange, prop); UNCHECK_MECHS(CKM_HKDF_DERIVE); break; case CKM_SHA_1: - ADD_ALGO(SHA1, sha1, digest); + ADD_ALGO(SHA1, sha1, digest, prop); UNCHECK_MECHS(CKM_SHA_1); break; case CKM_SHA224: - ADD_ALGO(SHA2_224, sha224, digest); + ADD_ALGO(SHA2_224, sha224, digest, prop); UNCHECK_MECHS(CKM_SHA224); break; case CKM_SHA256: - ADD_ALGO(SHA2_256, sha256, digest); + ADD_ALGO(SHA2_256, sha256, digest, prop); UNCHECK_MECHS(CKM_SHA256); break; case CKM_SHA384: - ADD_ALGO(SHA2_384, sha384, digest); + ADD_ALGO(SHA2_384, sha384, digest, prop); UNCHECK_MECHS(CKM_SHA384); break; case CKM_SHA512: - ADD_ALGO(SHA2_512, sha512, digest); + ADD_ALGO(SHA2_512, sha512, digest, prop); UNCHECK_MECHS(CKM_SHA512); break; case CKM_SHA512_224: - ADD_ALGO(SHA2_512_224, sha512_224, digest); + ADD_ALGO(SHA2_512_224, sha512_224, digest, prop); UNCHECK_MECHS(CKM_SHA512_224); break; case CKM_SHA512_256: - ADD_ALGO(SHA2_512_256, sha512_256, digest); + ADD_ALGO(SHA2_512_256, sha512_256, digest, prop); UNCHECK_MECHS(CKM_SHA512_256); break; case CKM_SHA3_224: - ADD_ALGO(SHA3_224, sha3_224, digest); + ADD_ALGO(SHA3_224, sha3_224, digest, prop); UNCHECK_MECHS(CKM_SHA3_224); break; case CKM_SHA3_256: - ADD_ALGO(SHA3_256, sha3_256, digest); + ADD_ALGO(SHA3_256, sha3_256, digest, prop); UNCHECK_MECHS(CKM_SHA3_256); break; case CKM_SHA3_384: - ADD_ALGO(SHA3_384, sha3_384, digest); + ADD_ALGO(SHA3_384, sha3_384, digest, prop); UNCHECK_MECHS(CKM_SHA3_384); break; case CKM_SHA3_512: - ADD_ALGO(SHA3_512, sha3_512, digest); + ADD_ALGO(SHA3_512, sha3_512, digest, prop); UNCHECK_MECHS(CKM_SHA3_512); break; case CKM_EDDSA: - ADD_ALGO_EXT(ED25519, signature, P11PROV_DEFAULT_PROPERTIES, + ADD_ALGO_EXT(ED25519, signature, prop, p11prov_eddsa_signature_functions); - ADD_ALGO_EXT(ED448, signature, P11PROV_DEFAULT_PROPERTIES, + ADD_ALGO_EXT(ED448, signature, prop, p11prov_eddsa_signature_functions); UNCHECK_MECHS(CKM_EC_EDWARDS_KEY_PAIR_GEN, CKM_EDDSA); break; @@ -1057,10 +1071,10 @@ static CK_RV operations_init(P11PROV_CTX *ctx) p11prov_return_slots(slots); if (add_rsasig) { - ADD_ALGO(RSA, rsa, signature); + ADD_ALGO(RSA, rsa, signature, prop); } if (add_rsaenc) { - ADD_ALGO(RSA, rsa, asym_cipher); + ADD_ALGO(RSA, rsa, asym_cipher, prop); } /* terminations */ TERM_ALGO(digest); @@ -1069,121 +1083,121 @@ static CK_RV operations_init(P11PROV_CTX *ctx) TERM_ALGO(signature); TERM_ALGO(asym_cipher); - /* encoder/decoder */ - ADD_ALGO_EXT(RSA, encoder, "provider=pkcs11,output=text", + /* handle random */ + ret = p11prov_check_random(ctx); + if (ret == CKR_OK) { + ADD_ALGO_EXT(RAND, random, prop, p11prov_rand_functions); + TERM_ALGO(random); + } + + return CKR_OK; +} + +static CK_RV static_operations_init(P11PROV_CTX *ctx) +{ + int encoder_idx = 0; + int decoder_idx = 0; + int store_idx = 0; + int keymgmt_idx = 0; + const char *prop = get_default_properties(ctx); + +/* encoder */ +#define DEFAULT_PROPERTY(prop) \ + (ctx->assume_fips ? P11PROV_FIPS_PROPERTIES prop \ + : P11PROV_DEFAULT_PROPERTIES prop) + + ADD_ALGO_EXT(RSA, encoder, DEFAULT_PROPERTY(",output=text"), p11prov_rsa_encoder_text_functions); - ADD_ALGO_EXT(RSA, encoder, "provider=pkcs11,output=der,structure=pkcs1", + ADD_ALGO_EXT(RSA, encoder, DEFAULT_PROPERTY(",output=der,structure=pkcs1"), p11prov_rsa_encoder_pkcs1_der_functions); - ADD_ALGO_EXT(RSA, encoder, "provider=pkcs11,output=pem,structure=pkcs1", + ADD_ALGO_EXT(RSA, encoder, DEFAULT_PROPERTY(",output=pem,structure=pkcs1"), p11prov_rsa_encoder_pkcs1_pem_functions); ADD_ALGO_EXT(RSA, encoder, - "provider=pkcs11,output=der,structure=SubjectPublicKeyInfo", + DEFAULT_PROPERTY(",output=der,structure=SubjectPublicKeyInfo"), p11prov_rsa_encoder_spki_der_functions); ADD_ALGO_EXT(RSA, encoder, - "provider=pkcs11,output=pem,structure=SubjectPublicKeyInfo", + DEFAULT_PROPERTY(",output=pem,structure=SubjectPublicKeyInfo"), p11prov_rsa_encoder_spki_pem_functions); - ADD_ALGO_EXT(RSAPSS, encoder, "provider=pkcs11,output=text", + ADD_ALGO_EXT(RSAPSS, encoder, DEFAULT_PROPERTY(",output=text"), p11prov_rsa_encoder_text_functions); - ADD_ALGO_EXT(RSAPSS, encoder, "provider=pkcs11,output=der,structure=pkcs1", + ADD_ALGO_EXT(RSAPSS, encoder, + DEFAULT_PROPERTY(",output=der,structure=pkcs1"), p11prov_rsa_encoder_pkcs1_der_functions); - ADD_ALGO_EXT(RSAPSS, encoder, "provider=pkcs11,output=pem,structure=pkcs1", + ADD_ALGO_EXT(RSAPSS, encoder, + DEFAULT_PROPERTY(",output=pem,structure=pkcs1"), p11prov_rsa_encoder_pkcs1_pem_functions); ADD_ALGO_EXT(RSAPSS, encoder, - "provider=pkcs11,output=der,structure=SubjectPublicKeyInfo", + DEFAULT_PROPERTY(",output=der,structure=SubjectPublicKeyInfo"), p11prov_rsa_encoder_spki_der_functions); ADD_ALGO_EXT(RSAPSS, encoder, - "provider=pkcs11,output=pem,structure=SubjectPublicKeyInfo", + DEFAULT_PROPERTY(",output=pem,structure=SubjectPublicKeyInfo"), p11prov_rsa_encoder_spki_pem_functions); - ADD_ALGO_EXT(EC, encoder, "provider=pkcs11,output=text", + ADD_ALGO_EXT(EC, encoder, DEFAULT_PROPERTY(",output=text"), p11prov_ec_encoder_text_functions); - ADD_ALGO_EXT(EC, encoder, "provider=pkcs11,output=der,structure=pkcs1", + ADD_ALGO_EXT(EC, encoder, DEFAULT_PROPERTY(",output=der,structure=pkcs1"), p11prov_ec_encoder_pkcs1_der_functions); - ADD_ALGO_EXT(EC, encoder, "provider=pkcs11,output=pem,structure=pkcs1", + ADD_ALGO_EXT(EC, encoder, DEFAULT_PROPERTY(",output=pem,structure=pkcs1"), p11prov_ec_encoder_pkcs1_pem_functions); ADD_ALGO_EXT(EC, encoder, - "provider=pkcs11,output=der,structure=SubjectPublicKeyInfo", + DEFAULT_PROPERTY(",output=der,structure=SubjectPublicKeyInfo"), p11prov_ec_encoder_spki_der_functions); - ADD_ALGO_EXT(ED25519, encoder, "provider=pkcs11,output=text", + ADD_ALGO_EXT(ED25519, encoder, DEFAULT_PROPERTY(",output=text"), p11prov_ec_edwards_encoder_text_functions); - ADD_ALGO_EXT(ED448, encoder, "provider=pkcs11,output=text", + ADD_ALGO_EXT(ED448, encoder, DEFAULT_PROPERTY(",output=text"), p11prov_ec_edwards_encoder_text_functions); if (ctx->encode_pkey_as_pk11_uri) { ADD_ALGO_EXT(RSA, encoder, - "provider=pkcs11,output=pem,structure=PrivateKeyInfo", + DEFAULT_PROPERTY(",output=pem,structure=PrivateKeyInfo"), p11prov_rsa_encoder_priv_key_info_pem_functions); ADD_ALGO_EXT(RSAPSS, encoder, - "provider=pkcs11,output=pem,structure=PrivateKeyInfo", + DEFAULT_PROPERTY(",output=pem,structure=PrivateKeyInfo"), p11prov_rsa_encoder_priv_key_info_pem_functions); ADD_ALGO_EXT(EC, encoder, - "provider=pkcs11,output=pem,structure=PrivateKeyInfo", + DEFAULT_PROPERTY(",output=pem,structure=PrivateKeyInfo"), p11prov_ec_encoder_priv_key_info_pem_functions); ADD_ALGO_EXT(ED25519, encoder, - "provider=pkcs11,output=pem,structure=PrivateKeyInfo", + DEFAULT_PROPERTY(",output=pem,structure=PrivateKeyInfo"), p11prov_ec_edwards_encoder_priv_key_info_pem_functions); ADD_ALGO_EXT(ED448, encoder, - "provider=pkcs11,output=pem,structure=PrivateKeyInfo", + DEFAULT_PROPERTY(",output=pem,structure=PrivateKeyInfo"), p11prov_ec_edwards_encoder_priv_key_info_pem_functions); } TERM_ALGO(encoder); - /* handle random */ - ret = p11prov_check_random(ctx); - if (ret == CKR_OK) { - ADD_ALGO_EXT(RAND, random, "provider=pkcs11", p11prov_rand_functions); - TERM_ALGO(random); - } +#define DER_DECODER_PROP ",input=der,structure=" P11PROV_DER_STRUCTURE + /* decoder */ + ADD_ALGO_EXT(DER, decoder, DEFAULT_PROPERTY(",input=pem"), + p11prov_pem_decoder_p11prov_der_functions); + ADD_ALGO_EXT(RSA, decoder, DEFAULT_PROPERTY(DER_DECODER_PROP), + p11prov_der_decoder_p11prov_rsa_functions); + ADD_ALGO_EXT(RSAPSS, decoder, DEFAULT_PROPERTY(DER_DECODER_PROP), + p11prov_der_decoder_p11prov_rsa_functions); + ADD_ALGO_EXT(EC, decoder, DEFAULT_PROPERTY(DER_DECODER_PROP), + p11prov_der_decoder_p11prov_ec_functions); + ADD_ALGO_EXT(ED25519, decoder, DEFAULT_PROPERTY(DER_DECODER_PROP), + p11prov_der_decoder_p11prov_ed25519_functions); + ADD_ALGO_EXT(ED448, decoder, DEFAULT_PROPERTY(DER_DECODER_PROP), + p11prov_der_decoder_p11prov_ed448_functions); + TERM_ALGO(decoder); +#undef DEFAULT_PROPERTY + + /* store */ + ADD_ALGO_EXT(URI, store, prop, p11prov_store_functions); + TERM_ALGO(store); + + /* keymgmt */ + ADD_ALGO(RSA, rsa, keymgmt, prop); + ADD_ALGO(RSAPSS, rsapss, keymgmt, prop); + ADD_ALGO(EC, ec, keymgmt, prop); + ADD_ALGO(HKDF, hkdf, keymgmt, prop); + ADD_ALGO_EXT(ED25519, keymgmt, prop, p11prov_ed25519_keymgmt_functions); + ADD_ALGO_EXT(ED448, keymgmt, prop, p11prov_ed448_keymgmt_functions); + TERM_ALGO(keymgmt); return CKR_OK; } -static const OSSL_ALGORITHM p11prov_keymgmt[] = { - { P11PROV_NAMES_RSA, P11PROV_DEFAULT_PROPERTIES, - p11prov_rsa_keymgmt_functions, P11PROV_DESCS_RSA }, - { P11PROV_NAMES_RSAPSS, P11PROV_DEFAULT_PROPERTIES, - p11prov_rsapss_keymgmt_functions, P11PROV_DESCS_RSAPSS }, - { P11PROV_NAMES_EC, P11PROV_DEFAULT_PROPERTIES, - p11prov_ec_keymgmt_functions, P11PROV_DESCS_EC }, - { P11PROV_NAMES_HKDF, P11PROV_DEFAULT_PROPERTIES, - p11prov_hkdf_keymgmt_functions, P11PROV_DESCS_HKDF }, - { P11PROV_NAMES_ED25519, P11PROV_DEFAULT_PROPERTIES, - p11prov_ed25519_keymgmt_functions, P11PROV_DESCS_ED25519 }, - { P11PROV_NAMES_ED448, P11PROV_DEFAULT_PROPERTIES, - p11prov_ed448_keymgmt_functions, P11PROV_DESCS_ED448 }, - { NULL, NULL, NULL, NULL }, -}; - -static const OSSL_ALGORITHM p11prov_store[] = { - { - "pkcs11", - P11PROV_DEFAULT_PROPERTIES, - p11prov_store_functions, - P11PROV_DESCS_URI, - }, - { NULL, NULL, NULL, NULL }, -}; - -static const OSSL_ALGORITHM p11prov_decoders[] = { - { "DER", "provider=pkcs11,input=pem", - p11prov_pem_decoder_p11prov_der_functions }, - { P11PROV_NAMES_RSA, - "provider=pkcs11,input=der,structure=" P11PROV_DER_STRUCTURE, - p11prov_der_decoder_p11prov_rsa_functions }, - { P11PROV_NAMES_RSAPSS, - "provider=pkcs11,input=der,structure=" P11PROV_DER_STRUCTURE, - p11prov_der_decoder_p11prov_rsa_functions }, - { P11PROV_NAMES_EC, - "provider=pkcs11,input=der,structure=" P11PROV_DER_STRUCTURE, - p11prov_der_decoder_p11prov_ec_functions }, - { P11PROV_NAMES_ED25519, - "provider=pkcs11,input=der,structure=" P11PROV_DER_STRUCTURE, - p11prov_der_decoder_p11prov_ed25519_functions }, - { P11PROV_NAMES_ED448, - "provider=pkcs11,input=der,structure=" P11PROV_DER_STRUCTURE, - p11prov_der_decoder_p11prov_ed448_functions }, - { NULL, NULL, NULL } -}; - static const char *p11prov_block_ops_names[OSSL_OP__HIGHEST + 1] = { [OSSL_OP_DIGEST] = "digest", [OSSL_OP_CIPHER] = "cipher", @@ -1229,7 +1243,7 @@ p11prov_query_operation(void *provctx, int operation_id, int *no_cache) return ctx->op_random; case OSSL_OP_KEYMGMT: *no_cache = 0; - return p11prov_keymgmt; + return ctx->op_keymgmt; case OSSL_OP_KEYEXCH: *no_cache = ctx->status == P11PROV_UNINITIALIZED ? 1 : 0; return ctx->op_exchange; @@ -1240,14 +1254,14 @@ p11prov_query_operation(void *provctx, int operation_id, int *no_cache) *no_cache = ctx->status == P11PROV_UNINITIALIZED ? 1 : 0; return ctx->op_asym_cipher; case OSSL_OP_ENCODER: - *no_cache = ctx->status == P11PROV_UNINITIALIZED ? 1 : 0; + *no_cache = 0; return ctx->op_encoder; case OSSL_OP_DECODER: *no_cache = 0; - return p11prov_decoders; + return ctx->op_decoder; case OSSL_OP_STORE: *no_cache = 0; - return p11prov_store; + return ctx->op_store; } *no_cache = 0; return NULL; @@ -1409,6 +1423,7 @@ enum p11prov_cfg_enum { P11PROV_CFG_CACHE_SESSIONS, P11PROV_CFG_ENCODE_PROVIDER_URI_TO_PEM, P11PROV_CFG_BLOCK_OPS, + P11PROV_CFG_ASSUME_FIPS, P11PROV_CFG_SIZE, }; @@ -1427,6 +1442,7 @@ static struct p11prov_cfg_names { { "pkcs11-module-cache-sessions" }, { "pkcs11-module-encode-provider-uri-to-pem" }, { "pkcs11-module-block-operations" }, + { "pkcs11-module-assume-fips" }, }; int OSSL_provider_init(const OSSL_CORE_HANDLE *handle, const OSSL_DISPATCH *in, @@ -1647,6 +1663,15 @@ int OSSL_provider_init(const OSSL_CORE_HANDLE *handle, const OSSL_DISPATCH *in, } P11PROV_debug("Cache Sessions: %d", ctx->cache_sessions); + if (cfg[P11PROV_CFG_ASSUME_FIPS] != NULL + && strcmp(cfg[P11PROV_CFG_ASSUME_FIPS], "true") == 0) { + ctx->assume_fips = true; + } else { + ctx->assume_fips = false; + } + P11PROV_debug("Assuming FIPS token is%s used", + ctx->assume_fips ? "" : " not"); + if (cfg[P11PROV_CFG_ENCODE_PROVIDER_URI_TO_PEM] != NULL && strcmp(cfg[P11PROV_CFG_ENCODE_PROVIDER_URI_TO_PEM], "true") == 0) { ctx->encode_pkey_as_pk11_uri = true; @@ -1698,6 +1723,16 @@ int OSSL_provider_init(const OSSL_CORE_HANDLE *handle, const OSSL_DISPATCH *in, P11PROV_debug("Blocked Operations: None"); } + /* These operations need to be initialized when we return here for OpenSSL + * to work. They do not need the token so they will not slow down + * initialization. + */ + ret = static_operations_init(ctx); + if (ret != CKR_OK) { + p11prov_ctx_free(ctx); + return RET_OSSL_ERR; + } + /* PAY ATTENTION: do this as the last thing */ if (cfg[P11PROV_CFG_LOAD_BEHAVIOR] != NULL && strcmp(cfg[P11PROV_CFG_LOAD_BEHAVIOR], "early") == 0) { diff --git a/src/provider.h b/src/provider.h index 418f9d00..b699dfc3 100644 --- a/src/provider.h +++ b/src/provider.h @@ -30,6 +30,8 @@ #define RET_OSSL_BAD -1 #define P11PROV_DEFAULT_PROPERTIES "provider=pkcs11" +#define P11PROV_FIPS_PROPERTIES "provider=pkcs11,fips=yes" + #define P11PROV_NAME_RSA "RSA" #define P11PROV_NAMES_RSA "RSA:rsaEncryption:1.2.840.113549.1.1.1" #define P11PROV_DESCS_RSA "PKCS11 RSA Implementation" @@ -48,7 +50,6 @@ #define P11PROV_NAME_HKDF "HKDF" #define P11PROV_NAMES_HKDF P11PROV_NAME_HKDF #define P11PROV_DESCS_HKDF "PKCS11 HKDF Implementation" -#define P11PROV_DESCS_URI "PKCS11 URI Store" #define P11PROV_NAMES_ED25519 "ED25519:1.3.101.112" #define P11PROV_NAME_ED25519 "ED25519" #define P11PROV_DESCS_ED25519 "PKCS11 ED25519 Implementation" @@ -61,6 +62,10 @@ #define P11PROV_NAME_TLS13_KDF "TLS13-KDF" #define P11PROV_NAMES_TLS13_KDF P11PROV_NAME_TLS13_KDF #define P11PROV_DESCS_TLS13_KDF "PKCS11 TLS 1.3 HKDF Implementation" +#define P11PROV_NAMES_DER "DER" +#define P11PROV_DESCS_DER "DER decoder implementation in PKCS11 provider" +#define P11PROV_NAMES_URI "pkcs11" +#define P11PROV_DESCS_URI "PKCS11 URI Store" #define P11PROV_PARAM_URI "pkcs11_uri" #define P11PROV_PARAM_KEY_USAGE "pkcs11_key_usage" From 2cfdeecdd1db981f654237df710ed0abcbc4ab9f Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Tue, 14 Jan 2025 21:26:57 +0100 Subject: [PATCH 2/6] ci: Add CentOS 10 Signed-off-by: Jakub Jelen --- .github/workflows/build.yml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 177cd897..7b299f00 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -14,7 +14,7 @@ jobs: strategy: fail-fast: false matrix: - name: [fedora, debian, centos, ubuntu] + name: [fedora, debian, centos9, centos10, ubuntu] compiler: [gcc, clang] token: [softokn, softhsm] include: @@ -22,15 +22,17 @@ jobs: container: fedora:latest - name: debian container: debian:sid - - name: centos + - name: centos9 container: quay.io/centos/centos:stream9 + - name: centos10 + container: quay.io/centos/centos:stream10 - name: ubuntu container: ubuntu:latest container: ${{ matrix.container }} steps: - name: Install Dependencies run: | - if [ "${{ matrix.name }}" = centos ]; then + if [ "${{ matrix.name }}" = "centos9" -o "${{ matrix.name }}" = "centos10" ]; then dnf_opts="--enablerepo=crb" fi if [ -f /etc/redhat-release ]; then @@ -59,7 +61,7 @@ jobs: - name: Check NSS version id: nss-version-check run: | - if [ "${{ matrix.name }}" = "centos" ]; then + if [ "${{ matrix.name }}" = "centos9" -o "${{ matrix.name }}" = "centos10" ]; then if [ "${{ matrix.token }}" = "softokn" ]; then NSSMINVER=`nss-config --version nss | cut -d '.' -f 2` if [ $NSSMINVER -lt 101 ]; then From a35b36edbea42f640df8f77d45fa447380d0ef9a Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Tue, 14 Jan 2025 21:31:47 +0100 Subject: [PATCH 3/6] ci: Add newlines between steps to improve readability Signed-off-by: Jakub Jelen --- .github/workflows/address-sanitizer.yml | 4 ++++ .github/workflows/build.yml | 12 ++++++++++++ .github/workflows/distcheck.yml | 4 ++++ .github/workflows/kryoptic.yml | 3 +++ 4 files changed, 23 insertions(+) diff --git a/.github/workflows/address-sanitizer.yml b/.github/workflows/address-sanitizer.yml index 3f3c6daf..4bd07027 100644 --- a/.github/workflows/address-sanitizer.yml +++ b/.github/workflows/address-sanitizer.yml @@ -24,6 +24,7 @@ jobs: steps: - name: Checkout Repository uses: actions/checkout@v4 + - name: Install Dependencies run: | if [ -f /etc/fedora-release ]; then @@ -42,6 +43,7 @@ jobs: libp11-kit-dev p11-kit-modules gnutls-bin \ openssl-dbgsym libssl3t64-dbgsym fi + - name: Setup # The detection on debian works ok, but on Fedora, we get linker script, # that is not compatible with LD_PRELOAD so we force the absolute path. @@ -53,12 +55,14 @@ jobs: CC=gcc \ meson setup builddir -Db_sanitize=address -Dpreload_libasan=/usr/lib/x86_64-linux-gnu/libasan.so.8.0.0 fi + - name: Build and Test # note, that this intentionally does not initialize submodules as # the tlsfuzzer test does not work under address sanitizer well run: | meson compile -C builddir meson test --num-processes 1 -C builddir + - uses: actions/upload-artifact@v4 if: failure() with: diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7b299f00..0755b60f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -58,6 +58,7 @@ jobs: p11-kit-modules fi fi + - name: Check NSS version id: nss-version-check run: | @@ -69,9 +70,11 @@ jobs: fi fi fi + - name: Checkout Repository if : ( steps.nss-version-check.outputs.skiptest != 'true' ) uses: actions/checkout@v4 + - name: Setup if : ( steps.nss-version-check.outputs.skiptest != 'true' ) run: | @@ -83,11 +86,13 @@ jobs: else CC=${{ matrix.compiler }} meson setup builddir -Denable_explicit_EC_test=true fi + - name: Build and Test if : ( steps.nss-version-check.outputs.skiptest != 'true' ) run: | meson compile -C builddir meson test --num-processes 1 -C builddir + - uses: actions/upload-artifact@v4 if: failure() with: @@ -97,12 +102,14 @@ jobs: builddir/tests/tmp.${{ matrix.token }}/p11prov-debug.log builddir/tests/tmp.${{ matrix.token }}/testvars builddir/tests/tmp.${{ matrix.token }}/openssl.cnf + - name: Run tests with valgrind if : ( steps.nss-version-check.outputs.skiptest != 'true' ) run: | if [ "${{ matrix.compiler }}" = "gcc" ]; then meson test --num-processes 1 -C builddir --setup=valgrind fi + - uses: actions/upload-artifact@v4 if: failure() with: @@ -112,6 +119,7 @@ jobs: builddir/tests/tmp.${{ matrix.token }}/p11prov-debug.log builddir/tests/tmp.${{ matrix.token }}/testvars builddir/tests/tmp.${{ matrix.token }}/openssl.cnf + build-macos: name: CI with software token runs-on: ${{ matrix.os }} @@ -135,8 +143,10 @@ jobs: elif [ "${{ matrix.token }}" = "softhsm" ]; then brew install softhsm fi + - name: Checkout Repository uses: actions/checkout@v4 + - name: Setup run: | git config --global --add safe.directory \ @@ -146,12 +156,14 @@ jobs: export PATH=$(brew --prefix openssl@3)/bin:$PATH CC=clang meson setup builddir + - name: Build and Test run: | export PATH=$(brew --prefix openssl@3)/bin:$PATH meson compile -j$(sysctl -n hw.ncpu || echo 2) -C builddir meson test --num-processes 1 -C builddir + - uses: actions/upload-artifact@v4 if: failure() with: diff --git a/.github/workflows/distcheck.yml b/.github/workflows/distcheck.yml index a0c03f27..13460199 100644 --- a/.github/workflows/distcheck.yml +++ b/.github/workflows/distcheck.yml @@ -42,20 +42,24 @@ jobs: softhsm2 opensc p11-kit libp11-kit-dev p11-kit-modules \ gnutls-bin fi + - name: Checkout Repository uses: actions/checkout@v4 + - name: Setup run: | git config --global --add safe.directory \ /__w/pkcs11-provider/pkcs11-provider git submodule update --init meson setup builddir + - name: Distcheck run: | git config --global --add safe.directory \ /__w/pkcs11-provider/pkcs11-provider git ls-files meson.build meson dist --no-tests -C builddir + - name: RPM Build if: ${{ matrix.name == 'fedora' }} run: | diff --git a/.github/workflows/kryoptic.yml b/.github/workflows/kryoptic.yml index b6c9acd0..b8c45a79 100644 --- a/.github/workflows/kryoptic.yml +++ b/.github/workflows/kryoptic.yml @@ -71,14 +71,17 @@ jobs: /__w/pkcs11-provider/pkcs11-provider git submodule update --init meson setup builddir + - name: Build run: meson compile -C builddir + - name: Test env: KRYOPTIC: ${{ steps.kryoptic_setup.outputs.KRYOPTIC }} run: meson test --num-processes 1 -C builddir + - uses: actions/upload-artifact@v4 if: failure() with: From 25c1fbe33912000b8d795b66c988b37a5b418d68 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Wed, 15 Jan 2025 14:15:57 +0100 Subject: [PATCH 4/6] tests: Removed needless repeated configuration change Signed-off-by: Jakub Jelen --- tests/timported | 6 ------ 1 file changed, 6 deletions(-) diff --git a/tests/timported b/tests/timported index 20dd0720..88640ef4 100755 --- a/tests/timported +++ b/tests/timported @@ -45,12 +45,6 @@ ossl 'pkeyutl -verify -pubin -sigfile ${TMPPDIR}/file.ec.sig.bin -in ${TMPPDIR}/sha256.bin' -#After key generation force all operations to happen on the token -ORIG_OPENSSL_CONF=${OPENSSL_CONF} -sed -e "s/#MORECONF/alg_section = algorithm_sec\n\n[algorithm_sec]\ndefault_properties = ?provider=pkcs11/" \ - "${OPENSSL_CONF}" > "${OPENSSL_CONF}.forcetoken" -OPENSSL_CONF=${OPENSSL_CONF}.forcetoken - title LINE "Test Signing with private RSA key imported from file" ossl 'pkeyutl -sign -inkey ${TMPPDIR}/file.rsa.key.pem From 6d8c90f1d8ecd0fd9e43649e361c6e3c6fdaa5a2 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Wed, 15 Jan 2025 15:02:35 +0100 Subject: [PATCH 5/6] tests: Adjust for FIPS support Signed-off-by: Jakub Jelen --- tests/kryoptic.nss-init.sh | 2 +- tests/setup.sh | 99 ++++++++++++++++++++++++++------------ tests/softhsm-init.sh | 2 +- tests/softokn-init.sh | 6 ++- tests/tbasic | 27 ++++++----- tests/tedwards | 14 ++++-- tests/timported | 6 ++- tests/tlsctx.c | 6 ++- tests/ttlsfuzzer | 5 ++ 9 files changed, 112 insertions(+), 55 deletions(-) diff --git a/tests/kryoptic.nss-init.sh b/tests/kryoptic.nss-init.sh index 14c00320..9fd87b8b 100644 --- a/tests/kryoptic.nss-init.sh +++ b/tests/kryoptic.nss-init.sh @@ -23,5 +23,5 @@ export TOKENLABELURI="Kryoptic%20Soft%20Token" source "${TESTSSRCDIR}/kryoptic-init.sh" export TOKENCONFIGVARS="export KRYOPTIC_CONF=${TMPPDIR}/kryoptic.conf" -export TOKENOPTIONS="pkcs11-module-quirks = no-allowed-mechanisms" +export TOKENOPTIONS="${TOKENOPTIONS}\npkcs11-module-quirks = no-allowed-mechanisms" export TESTPORT="36000" diff --git a/tests/setup.sh b/tests/setup.sh index 2b4dbea1..b1062709 100755 --- a/tests/setup.sh +++ b/tests/setup.sh @@ -11,6 +11,41 @@ fi TOKENTYPE=$1 +# defaults -- overridden below or in the per-token setup +SUPPORT_ED25519=1 +SUPPORT_ED448=1 +SUPPORT_RSA_PKCS1_ENCRYPTION=1 +SUPPORT_RSA_KEYGEN_PUBLIC_EXPONENT=1 +SUPPORT_TLSFUZZER=1 + +# Ed448 requires OpenSC 0.26.0, which is not available in Ubuntu and CentOS 9 +if [[ -f /etc/debian_version ]] && grep Ubuntu /etc/lsb-release; then + SUPPORT_ED448=0 +elif [[ -f /etc/redhat-release ]] && grep "release 9" /etc/redhat-release; then + SUPPORT_ED448=0 +fi + +# FIPS Mode +if [[ "${OPENSSL_FORCE_FIPS_MODE}" = "1" || "$(cat /proc/sys/crypto/fips_enabled)" = "1" ]]; then + # We can not use Edwards curves in FIPS mode + SUPPORT_ED25519=0 + SUPPORT_ED448=0 + + # The FIPS does not allow the RSA-PKCS1.5 encryption + SUPPORT_RSA_PKCS1_ENCRYPTION=0 + + # The FIPS does not allow to set custom public exponent during key + # generation + SUPPORT_RSA_KEYGEN_PUBLIC_EXPONENT=0 + + # TLS Fuzzer does not work well in FIPS mode + SUPPORT_TLSFUZZER=0 + + # We also need additional configuration in openssl.cnf to assume the token + # is FIPS token + TOKENOPTIONS="pkcs11-module-assume-fips = true" +fi + # Temporary dir and Token data dir TMPPDIR="${TESTBLDDIR}/${TOKENTYPE}" TOKDIR="$TMPPDIR/tokens" @@ -207,8 +242,7 @@ echo "" ## Softtokn does not support edwards curves yet -if [ "${TOKENTYPE}" != "softokn" ]; then - +if [ "${SUPPORT_ED25519}" -eq 1 ]; then # generate ED25519 KEYID='0004' URIKEYID="%00%04" @@ -232,37 +266,32 @@ if [ "${TOKENTYPE}" != "softokn" ]; then echo "${EDPUBURI}" echo "${EDPRIURI}" echo "${EDCRTURI}" +fi - # this requires OpenSC 0.26.0, which is not available in Ubuntu and CentOS 9 - if [[ -f /etc/debian_version ]] && grep Ubuntu /etc/lsb-release; then - echo "Ed448 not supported in Ubuntu's OpenSC version" - elif [[ -f /etc/redhat-release ]] && grep "release 9" /etc/redhat-release; then - echo "Ed448 not supported in EL9's OpenSC version" - else - # generate ED448 - KEYID='0009' - URIKEYID="%00%09" - ED2CRTN="ed2Cert" - - pkcs11-tool "${P11DEFARGS[@]}" --keypairgen --key-type="EC:Ed448" \ - --label="${ED2CRTN}" --id="$KEYID" - ca_sign $ED2CRTN "My ED448 Cert" $KEYID - - ED2BASEURIWITHPINVALUE="pkcs11:id=${URIKEYID};pin-value=${PINVALUE}" - ED2BASEURIWITHPINSOURCE="pkcs11:id=${URIKEYID};pin-source=file:${PINFILE}" - ED2BASEURI="pkcs11:id=${URIKEYID}" - ED2PUBURI="pkcs11:type=public;id=${URIKEYID}" - ED2PRIURI="pkcs11:type=private;id=${URIKEYID}" - ED2CRTURI="pkcs11:type=cert;object=${ED2CRTN}" - - title LINE "ED448 PKCS11 URIS" - echo "${ED2BASEURIWITHPINVALUE}" - echo "${ED2BASEURIWITHPINSOURCE}" - echo "${ED2BASEURI}" - echo "${ED2PUBURI}" - echo "${ED2PRIURI}" - echo "${ED2CRTURI}" - fi +if [ "${SUPPORT_ED448}" -eq 1 ]; then + # generate ED448 + KEYID='0009' + URIKEYID="%00%09" + ED2CRTN="ed2Cert" + + pkcs11-tool "${P11DEFARGS[@]}" --keypairgen --key-type="EC:Ed448" \ + --label="${ED2CRTN}" --id="$KEYID" + ca_sign $ED2CRTN "My ED448 Cert" $KEYID + + ED2BASEURIWITHPINVALUE="pkcs11:id=${URIKEYID};pin-value=${PINVALUE}" + ED2BASEURIWITHPINSOURCE="pkcs11:id=${URIKEYID};pin-source=file:${PINFILE}" + ED2BASEURI="pkcs11:id=${URIKEYID}" + ED2PUBURI="pkcs11:type=public;id=${URIKEYID}" + ED2PRIURI="pkcs11:type=private;id=${URIKEYID}" + ED2CRTURI="pkcs11:type=cert;object=${ED2CRTN}" + + title LINE "ED448 PKCS11 URIS" + echo "${ED2BASEURIWITHPINVALUE}" + echo "${ED2BASEURIWITHPINSOURCE}" + echo "${ED2BASEURI}" + echo "${ED2PUBURI}" + echo "${ED2PRIURI}" + echo "${ED2CRTURI}" fi title PARA "generate RSA key pair, self-signed certificate, remove public key" @@ -395,6 +424,12 @@ export OPENSSL_CONF="${OPENSSL_CONF}" export TESTSSRCDIR="${TESTSSRCDIR}" export TESTBLDDIR="${TESTBLDDIR}" +export SUPPORT_ED25519="${SUPPORT_ED25519}" +export SUPPORT_ED448="${SUPPORT_ED448}" +export SUPPORT_RSA_PKCS1_ENCRYPTION="${SUPPORT_RSA_PKCS1_ENCRYPTION}" +export SUPPORT_RSA_KEYGEN_PUBLIC_EXPONENT="${SUPPORT_RSA_KEYGEN_PUBLIC_EXPONENT}" +export SUPPORT_TLSFUZZER="${SUPPORT_TLSFUZZER}" + export TESTPORT="${TESTPORT}" export CACRT="${CACRT_PEM}" diff --git a/tests/softhsm-init.sh b/tests/softhsm-init.sh index 41d40437..1bf47412 100755 --- a/tests/softhsm-init.sh +++ b/tests/softhsm-init.sh @@ -62,7 +62,7 @@ export TOKENLABELURI="SoftHSM%20Token" softhsm2-util --init-token --label "${TOKENLABEL}" --free --pin "${PINVALUE}" --so-pin "${PINVALUE}" #softhsm crashes on de-init so we need to default to this quirk -export TOKENOPTIONS="pkcs11-module-quirks = no-deinit no-operation-state" +export TOKENOPTIONS="${TOKENOPTIONS}\npkcs11-module-quirks = no-deinit no-operation-state" export TOKENCONFIGVARS="export SOFTHSM2_CONF=${TMPPDIR}/softhsm.conf" diff --git a/tests/softokn-init.sh b/tests/softokn-init.sh index 026156a2..396b48f5 100755 --- a/tests/softokn-init.sh +++ b/tests/softokn-init.sh @@ -19,7 +19,11 @@ export NSS_LIB_PARAMS="configDir=${TOKDIR}" export TOKENLABEL="NSS Certificate DB" export TOKENLABELURI="NSS%20Certificate%20DB" -export TOKENOPTIONS="pkcs11-module-quirks = no-operation-state no-allowed-mechanisms" +export TOKENOPTIONS="${TOKENOPTIONS}\npkcs11-module-quirks = no-operation-state no-allowed-mechanisms" export TOKENCONFIGVARS="export NSS_LIB_PARAMS=configDir=${TOKDIR}" export TESTPORT="30000" + +# Edward curves are not supported in NSS yet +export SUPPORT_ED25519=0 +export SUPPORT_ED448=0 diff --git a/tests/tbasic b/tests/tbasic index 02c9ac88..6125a749 100755 --- a/tests/tbasic +++ b/tests/tbasic @@ -67,20 +67,21 @@ pkeyutl -verify -inkey "${PUBURI}" -rawin -sigfile ${TMPPDIR}/sha256-dgstsig.bin' +if [[ "$SUPPORT_RSA_PKCS1_ENCRYPTION" = "1" ]]; then + SECRETFILE=${TMPPDIR}/rsasecret.txt + echo "Super Secret" > "${SECRETFILE}" -SECRETFILE=${TMPPDIR}/rsasecret.txt -echo "Super Secret" > "${SECRETFILE}" - -title LINE "RSA basic encrypt and decrypt" -ossl ' -pkeyutl -encrypt -inkey "${PUBURI}" -pubin - -in ${SECRETFILE} - -out ${SECRETFILE}.enc' -ossl ' -pkeyutl -decrypt -inkey "${PRIURI}" - -in ${SECRETFILE}.enc - -out ${SECRETFILE}.dec' -diff "${SECRETFILE}" "${SECRETFILE}.dec" + title LINE "RSA basic encrypt and decrypt" + ossl ' + pkeyutl -encrypt -inkey "${PUBURI}" -pubin + -in ${SECRETFILE} + -out ${SECRETFILE}.enc' + ossl ' + pkeyutl -decrypt -inkey "${PRIURI}" + -in ${SECRETFILE}.enc + -out ${SECRETFILE}.dec' + diff "${SECRETFILE}" "${SECRETFILE}.dec" +fi title PARA "Test Disallow Public Export" ORIG_OPENSSL_CONF=${OPENSSL_CONF} diff --git a/tests/tedwards b/tests/tedwards index b16b6342..198ea4ac 100755 --- a/tests/tedwards +++ b/tests/tedwards @@ -4,6 +4,10 @@ source "${TESTSSRCDIR}/helpers.sh" +if [[ "${SUPPORT_ED25519}" = "0" ]]; then + exit 77; +fi + title PARA "Export ED25519 Public key to a file" ossl 'pkey -in $EDPUBURI -pubin -pubout -out ${TMPPDIR}/edout.pub' @@ -65,7 +69,7 @@ fi if [[ -n $ED2BASEURI ]]; then title PARA "Export ED448 Public key to a file" ossl 'pkey -in $ED2PUBURI -pubin -pubout -out ${TMPPDIR}/ed2out.pub' - + title LINE "Print ED448 Public key from private" ossl 'pkey -in $ED2PRIURI -pubout -text' $helper_emit output="$helper_output" @@ -79,7 +83,7 @@ if [[ -n $ED2BASEURI ]]; then echo exit 1 fi - + title PARA "DigestSign and DigestVerify with ED448" ossl ' pkeyutl -sign -inkey "${ED2BASEURI}" @@ -91,16 +95,16 @@ if [[ -n $ED2BASEURI ]]; then -in ${RAND64FILE} -rawin -sigfile ${TMPPDIR}/sha256-eddgstsig.bin' - + title PARA "Test CSR generation from private ED448 keys" ossl ' req -new -batch -key "${ED2PRIURI}" -out ${TMPPDIR}/ed448_csr.pem' ossl ' req -in ${TMPPDIR}/ed448_csr.pem -verify -noout' - + title PARA "Test EVP_PKEY_eq on public Edwards key both on token" $CHECKER "${TESTBLDDIR}/tcmpkeys" "$ED2PUBURI" "$ED2PUBURI" - + title PARA "Test EVP_PKEY_eq on public ED448 key via import" $CHECKER "${TESTBLDDIR}/tcmpkeys" "$ED2PUBURI" "${TMPPDIR}"/ed2out.pub title PARA "Match private ED448 key against public key" diff --git a/tests/timported b/tests/timported index 88640ef4..692440fe 100755 --- a/tests/timported +++ b/tests/timported @@ -22,8 +22,12 @@ ossl 'pkey -in ${TMPPDIR}/file.ec.key.pem title LINE "Generate RSA keypair in files" # older versions of openssl don't support -outpubkey ... # .. so we'll use two steps +export OPTS="" +if [[ "${SUPPORT_RSA_KEYGEN_PUBLIC_EXPONENT}" = "1" ]]; then + export OPTS="-pkeyopt rsa_keygen_pubexp:3" +fi ossl 'genpkey -algorithm RSA -out ${TMPPDIR}/file.rsa.key.pem - -pkeyopt rsa_keygen_bits:2048 -pkeyopt rsa_keygen_pubexp:3' + -pkeyopt rsa_keygen_bits:2048 ${OPTS}' ossl 'pkey -in ${TMPPDIR}/file.rsa.key.pem -pubout -out ${TMPPDIR}/file.rsa.pub.key.pem' diff --git a/tests/tlsctx.c b/tests/tlsctx.c index 374a6c80..e793729b 100644 --- a/tests/tlsctx.c +++ b/tests/tlsctx.c @@ -107,6 +107,7 @@ static void test_pkcs1_with_tls_padding(void) int main(int argc, char *argv[]) { SSL_CTX *ctx; + char *env; ctx = SSL_CTX_new(TLS_server_method()); if (!ctx) { @@ -119,7 +120,10 @@ int main(int argc, char *argv[]) SSL_CTX_free(ctx); - test_pkcs1_with_tls_padding(); + env = getenv("SUPPORT_RSA_PKCS1_ENCRYPTION"); + if (env && env[0] == "1") { + test_pkcs1_with_tls_padding(); + } exit(EXIT_SUCCESS); } diff --git a/tests/ttlsfuzzer b/tests/ttlsfuzzer index 14dc7048..8ea710d3 100755 --- a/tests/ttlsfuzzer +++ b/tests/ttlsfuzzer @@ -9,6 +9,11 @@ if [[ ! -d "${TESTSSRCDIR}/../tlsfuzzer/tlsfuzzer" ]]; then exit 77; fi +if [[ "${SUPPORT_TLSFUZZER}" = "0" ]]; then + title "TLS fuzzer does not work in FIPS Mode" + exit 77; +fi + TMPFILE="${TMPPDIR}/tls-fuzzer.$$.tmp" PORT="$TESTPORT" PYTHON=$(which python3) From d8066f0e8ccbefbf9a7fb2455374f121d679b7cd Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Wed, 15 Jan 2025 15:02:56 +0100 Subject: [PATCH 6/6] ci: Run the tests also in emulated FIPS mode Signed-off-by: Jakub Jelen --- .github/workflows/build.yml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0755b60f..0a440837 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -120,6 +120,25 @@ jobs: builddir/tests/tmp.${{ matrix.token }}/testvars builddir/tests/tmp.${{ matrix.token }}/openssl.cnf + - name: Run tests in FIPS Mode (on CentOS + gcc only) + if : ( steps.nss-version-check.outputs.skiptest != 'true' ) + run: | + if [ "${{ matrix.compiler }}" = "gcc" -a \( "${{ matrix.name }}" = "centos9" -o "${{ matrix.name }}" = "centos10" \) ]; then + OPENSSL_FORCE_FIPS_MODE=1 \ + meson test --num-processes 1 -C builddir + fi + + - uses: actions/upload-artifact@v4 + if: failure() + with: + name: Test valgrind logs ${{ matrix.name }}, ${{ matrix.compiler }}, ${{ matrix.token }} + path: | + builddir/meson-logs/ + builddir/tests/tmp.${{ matrix.token }}/p11prov-debug.log + builddir/tests/tmp.${{ matrix.token }}/testvars + builddir/tests/tmp.${{ matrix.token }}/openssl.cnf + + build-macos: name: CI with software token runs-on: ${{ matrix.os }}