From 8b08b372c889f96890b38fd067686c1733c348a4 Mon Sep 17 00:00:00 2001 From: Clemens Lang Date: Wed, 8 Jun 2022 14:05:50 +0200 Subject: [PATCH] FIPS: Expose explicit indicator from fips.so FIPS 140-3 requires us to indicate whether an operation was using approved services or not. The FIPS 140-3 implementation guidelines provide two basic approaches to doing this: implicit indicators, and explicit indicators. Implicit indicators are basically the concept of "if the operation passes, it was approved". We were originally aiming for implicit indicators in our copy of OpenSSL. However, this proved to be a problem, because we wanted to certify a signature service, and FIPS 140-3 requires that a signature service computes the digest to be signed within the boundaries of the FIPS module. Since we were planning to certify fips.so only, this means that EVP_PKEY_sign/EVP_PKEY_verify would have to be blocked. Unfortunately, EVP_SignFinal uses EVP_PKEY_sign internally, but outside of fips.so and thus outside of the FIPS module boundary. This means that using implicit indicators in combination with certifying only fips.so would require us to block both EVP_PKEY_sign and EVP_SignFinal, which are the two APIs currently used by most users of OpenSSL for signatures. EVP_DigestSign would be acceptable, but has only been added in 3.0 and is thus not yet widely used. As a consequence, we've decided to introduce explicit indicators so that EVP_PKEY_sign and EVP_SignFinal can continue to work for now, but FIPS-aware applications can query the explicit indicator to check whether the operation was approved. To avoid affecting the ABI and public API too much, this is implemented as an exported symbol in fips.so and a private header, so applications that wish to use this will have to dlopen(3) fips.so, locate the function using dlsym(3), and then call it. These applications will have to build against the private header in order to use the returned pointer. Modify util/mkdef.pl to support exposing a symbol only for a specific provider identified by its name and path. Signed-off-by: Clemens Lang Resolves: rhbz#2087147 --- ...P_PKEY_-sign-verify-in-FIPS-provider.patch | 449 ----------------- 0062-fips-Expose-a-FIPS-indicator.patch | 466 ++++++++++++++++++ openssl.spec | 10 +- 3 files changed, 473 insertions(+), 452 deletions(-) delete mode 100644 0062-Disable-EVP_PKEY_-sign-verify-in-FIPS-provider.patch create mode 100644 0062-fips-Expose-a-FIPS-indicator.patch diff --git a/0062-Disable-EVP_PKEY_-sign-verify-in-FIPS-provider.patch b/0062-Disable-EVP_PKEY_-sign-verify-in-FIPS-provider.patch deleted file mode 100644 index a259f07..0000000 --- a/0062-Disable-EVP_PKEY_-sign-verify-in-FIPS-provider.patch +++ /dev/null @@ -1,449 +0,0 @@ -From 6f7111801d960952b15cda98d9a95f79f6f0bf7e Mon Sep 17 00:00:00 2001 -From: Clemens Lang -Date: Mon, 23 May 2022 13:09:08 +0200 -Subject: [PATCH] Disable EVP_PKEY_{sign,verify} in FIPS provider - -The APIs to compute both digest and signature in one step, -EVP_DigestSign*/EVP_DigestVerify* and EVP_Sign*/EVP_Verify*, should be -used instead. This ensures that the digest is computed inside of the -FIPS module, and that only approved digests are used. - -Update documentation for EVP_PKEY_{sign,verify} to reflect this. - -Since the KATs use EVP_PKEY_sign/EVP_PKEY_verify, modify the tests to -set the OSSL_SIGNATURE_PARAM_KAT parameter and use EVP_PKEY_sign_init_ex -and EVP_PKEY_verify_init_ex where these parameters can be passed on -creation and allow EVP_PKEY_sign/EVP_PKEY_verify when this parameter is -set and evaluates as true. - -Move tests that use the EVP_PKEY API to only run in the default -provider, since they would fail in the FIPS provider. This also affects -a number of CMS tests where error handling is insufficient and failure -to sign would only show up when verifying the CMS structure due to -a parse error. - -Resolves: rhbz#2087147 -Signed-off-by: Clemens Lang ---- - doc/man3/EVP_PKEY_sign.pod | 5 ++++ - doc/man3/EVP_PKEY_verify.pod | 5 ++++ - providers/fips/self_test_kats.c | 19 ++++++------- - .../implementations/signature/ecdsa_sig.c | 28 +++++++++++++++++++ - providers/implementations/signature/rsa_sig.c | 28 +++++++++++++++++++ - .../30-test_evp_data/evppkey_ecdsa.txt | 9 +----- - .../30-test_evp_data/evppkey_rsa_common.txt | 14 ++++++++++ - test/recipes/80-test_cms.t | 22 +++++++-------- - 8 files changed, 101 insertions(+), 29 deletions(-) - -diff --git a/doc/man3/EVP_PKEY_sign.pod b/doc/man3/EVP_PKEY_sign.pod -index 6752432bd5..f9d2b4f5d1 100644 ---- a/doc/man3/EVP_PKEY_sign.pod -+++ b/doc/man3/EVP_PKEY_sign.pod -@@ -41,6 +41,11 @@ normally used to sign digests. For signing arbitrary messages, see the - L and - L signing interfaces instead. - -+B: Because FIPS 140-3 requires that a signed digest is computed in the -+same module as the signature, this API is disabled on CentOS 9 Stream and Red -+Hat Enterprise Linux in FIPS mode. Use L and -+L instead. -+ - After the call to EVP_PKEY_sign_init() algorithm specific control - operations can be performed to set any appropriate parameters for the - operation (see L). -diff --git a/doc/man3/EVP_PKEY_verify.pod b/doc/man3/EVP_PKEY_verify.pod -index 77023cab87..344c39fe07 100644 ---- a/doc/man3/EVP_PKEY_verify.pod -+++ b/doc/man3/EVP_PKEY_verify.pod -@@ -33,6 +33,11 @@ signed) is specified using the I and I parameters. - - =head1 NOTES - -+B: Because FIPS 140-3 requires that a signed digest is computed in the -+same module as the signature, this API is disabled on CentOS 9 Stream and Red -+Hat Enterprise Linux in FIPS mode. Use L and -+L instead. -+ - After the call to EVP_PKEY_verify_init() algorithm specific control - operations can be performed to set any appropriate parameters for the - operation. -diff --git a/providers/fips/self_test_kats.c b/providers/fips/self_test_kats.c -index 064794d9bf..a60cb99983 100644 ---- a/providers/fips/self_test_kats.c -+++ b/providers/fips/self_test_kats.c -@@ -488,24 +488,23 @@ static int self_test_sign(const ST_KAT_SIGN *t, - || EVP_PKEY_fromdata(kctx, &pkey, EVP_PKEY_KEYPAIR, params) <= 0) - goto err; - -- /* Create a EVP_PKEY_CTX to use for the signing operation */ -- sctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey, NULL); -- if (sctx == NULL -- || EVP_PKEY_sign_init(sctx) <= 0) -- goto err; -- -- /* set signature parameters */ -+ /* prepare signature parameters */ - if (!OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_SIGNATURE_PARAM_DIGEST, - t->mdalgorithm, - strlen(t->mdalgorithm) + 1)) - goto err; -+ if (!OSSL_PARAM_BLD_push_int(bld, OSSL_SIGNATURE_PARAM_KAT, 1)) -+ goto err; - params_sig = OSSL_PARAM_BLD_to_param(bld); -- if (EVP_PKEY_CTX_set_params(sctx, params_sig) <= 0) -+ -+ /* Create a EVP_PKEY_CTX to use for the signing operation */ -+ sctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey, NULL); -+ if (sctx == NULL -+ || EVP_PKEY_sign_init_ex(sctx, params_sig) <= 0) - goto err; - - if (EVP_PKEY_sign(sctx, sig, &siglen, dgst, sizeof(dgst)) <= 0 -- || EVP_PKEY_verify_init(sctx) <= 0 -- || EVP_PKEY_CTX_set_params(sctx, params_sig) <= 0) -+ || EVP_PKEY_verify_init_ex(sctx, params_sig) <= 0) - goto err; - - /* -diff --git a/providers/implementations/signature/ecdsa_sig.c b/providers/implementations/signature/ecdsa_sig.c -index 44a22832ec..8f10208b59 100644 ---- a/providers/implementations/signature/ecdsa_sig.c -+++ b/providers/implementations/signature/ecdsa_sig.c -@@ -73,6 +73,9 @@ typedef struct { - * by their Final function. - */ - unsigned int flag_allow_md : 1; -+ /* Flag indicating that this context is used in a combined digest/sign or -+ * digest/verify operation. */ -+ unsigned int flag_is_digest_sigver : 1; - - /* The Algorithm Identifier of the combined signature algorithm */ - unsigned char aid_buf[OSSL_MAX_ALGORITHM_ID_SIZE]; -@@ -134,6 +137,26 @@ static int ecdsa_signverify_init(void *vctx, void *ec, - || ctx == NULL) - return 0; - -+#ifdef FIPS_MODULE -+ { -+ const OSSL_PARAM *katparam = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_KAT); -+ if (katparam != NULL) { -+ int kattests = 0; -+ if (OSSL_PARAM_get_int(katparam, &kattests) && kattests) { -+ ctx->flag_is_digest_sigver = 1; -+ } -+ } -+ } -+ -+ if (!ctx->flag_is_digest_sigver) { -+ ERR_raise_data(ERR_LIB_PROV, PROV_R_NOT_SUPPORTED, -+ "ECDSA signatures are not supported using the " -+ "EVP_PKEY_sign/EVP_PKEY_verify API in FIPS mode, use " -+ "EVP_DigestSign and EVP_DigestVerify."); -+ return 0; -+ } -+#endif -+ - if (ec == NULL && ctx->ec == NULL) { - ERR_raise(ERR_LIB_PROV, PROV_R_NO_KEY_SET); - return 0; -@@ -287,6 +310,11 @@ static int ecdsa_digest_signverify_init(void *vctx, const char *mdname, - if (!ossl_prov_is_running()) - return 0; - -+ if (ctx == NULL) -+ return 0; -+ -+ ctx->flag_is_digest_sigver = 1; -+ - if (!ecdsa_signverify_init(vctx, ec, params, operation) - || !ecdsa_setup_md(ctx, mdname, NULL)) - return 0; -diff --git a/providers/implementations/signature/rsa_sig.c b/providers/implementations/signature/rsa_sig.c -index 9a25b6a3de..a0d7b4707d 100644 ---- a/providers/implementations/signature/rsa_sig.c -+++ b/providers/implementations/signature/rsa_sig.c -@@ -88,6 +88,9 @@ typedef struct { - */ - unsigned int flag_allow_md : 1; - unsigned int mgf1_md_set : 1; -+ /* Flag indicating that this context is used in a combined digest/sign or -+ * digest/verify operation. */ -+ unsigned int flag_is_digest_sigver : 1; - - /* main digest */ - EVP_MD *md; -@@ -394,6 +397,26 @@ static int rsa_signverify_init(void *vprsactx, void *vrsa, - if (!ossl_prov_is_running() || prsactx == NULL) - return 0; - -+#ifdef FIPS_MODULE -+ { -+ const OSSL_PARAM *katparam = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_KAT); -+ if (katparam != NULL) { -+ int kattests = 0; -+ if (OSSL_PARAM_get_int(katparam, &kattests) && kattests) { -+ prsactx->flag_is_digest_sigver = 1; -+ } -+ } -+ } -+ -+ if (!prsactx->flag_is_digest_sigver) { -+ ERR_raise_data(ERR_LIB_PROV, PROV_R_NOT_SUPPORTED, -+ "RSA signatures are not supported using the " -+ "EVP_PKEY_sign/EVP_PKEY_verify API in FIPS mode, use " -+ "EVP_DigestSign and EVP_DigestVerify."); -+ return 0; -+ } -+#endif -+ - if (vrsa == NULL && prsactx->rsa == NULL) { - ERR_raise(ERR_LIB_PROV, PROV_R_NO_KEY_SET); - return 0; -@@ -851,6 +874,11 @@ static int rsa_digest_signverify_init(void *vprsactx, const char *mdname, - if (!ossl_prov_is_running()) - return 0; - -+ if (prsactx == NULL) -+ return 0; -+ -+ prsactx->flag_is_digest_sigver = 1; -+ - if (!rsa_signverify_init(vprsactx, vrsa, params, operation)) - return 0; - -diff --git a/test/recipes/30-test_evp_data/evppkey_ecdsa.txt b/test/recipes/30-test_evp_data/evppkey_ecdsa.txt -index a96940f026..ac934a2096 100644 ---- a/test/recipes/30-test_evp_data/evppkey_ecdsa.txt -+++ b/test/recipes/30-test_evp_data/evppkey_ecdsa.txt -@@ -111,6 +111,7 @@ Input = "Hello World" - Output = 3046022100e7515177ec3817b77a4a94066ab3070817b7aa9d44a8a09f040da250116e8972022100ba59b0f631258e59a9026be5d84f60685f4cf22b9165a0c2736d5c21c8ec1862 - - # Test that mdsize != tbssize fails -+Availablein = default - Sign = P-256 - Ctrl = digest:SHA256 - Input = "0123456789ABCDEF1234" -@@ -197,14 +198,6 @@ Key = B-163 - Input = "Hello World" - Result = DIGESTSIGNINIT_ERROR - --# Test that SHA1 is not allowed in fips mode for signing --Availablein = fips --Sign = P-256 --Securitycheck = 1 --Ctrl = digest:SHA1 --Input = "0123456789ABCDEF1234" --Result = PKEY_CTRL_ERROR -- - # Invalid non-approved digest - Availablein = fips - DigestVerify = MD5 -diff --git a/test/recipes/30-test_evp_data/evppkey_rsa_common.txt b/test/recipes/30-test_evp_data/evppkey_rsa_common.txt -index 37e542e1c2..e8209996ef 100644 ---- a/test/recipes/30-test_evp_data/evppkey_rsa_common.txt -+++ b/test/recipes/30-test_evp_data/evppkey_rsa_common.txt -@@ -103,11 +103,13 @@ Input = "0123456789ABCDEF1234" - Output = c09d402423cbf233d26cae21f954547bc43fe80fd41360a0336cfdbe9aedad05bef6fd2eaee6cd60089a52482d4809a238149520df3bdde4cb9e23d9307b05c0a6f327052325a29adf2cc95b66523be7024e2a585c3d4db15dfbe146efe0ecdc0402e33fe5d40324ee96c5c3edd374a15cdc0f5d84aa243c0f07e188c6518fbfceae158a9943be398e31097da81b62074f626eff738be6160741d5a26957a482b3251fd85d8df78b98148459de10aa93305dbb4a5230aa1da291a9b0e481918f99b7638d72bb687f97661d304ae145d64a474437a4ef39d7b8059332ddeb07e92bf6e0e3acaf8afedc93795e4511737ec1e7aab6d5bc9466afc950c1c17b48ad - - # Truncated digest -+Availablein = default - Sign = RSA-2048 - Ctrl = digest:SHA512-224 - Input = "0123456789ABCDEF123456789ABC" - Output = 5f720e9488139bb21e1c2f027fd5ce5993e6d31c5a8faaee833487b3a944d66891178868ace8070cad3ee2ffbe54aa4885a15fd1a7cc5166970fe1fd8c0423e72bd3e3b56fc4a53ed80aaaeca42497f0ec3c62113edc05cd006608f5eef7ce3ad4cba1069f68731dd28a524a1f93fcdc5547112d48d45586dd943ba0d443be9635720d8a61697c54c96627f0d85c5fbeaa3b4af86a65cf2fc3800dd5de34c046985f25d0efc0bb6edccc1d08b3a4fb9c8faffe181c7e68b31e374ad1440a4a664eec9ca0dc53a9d2f5bc7d9940d866f64201bcbc63612754df45727ea24b531d7de83d1bb707444859fa35521320c33bf6f4dbeb6fb56e653adbf7af15843f17 - -+Availablein = default - Verify = RSA-2048 - Ctrl = digest:SHA512-224 - Input = "0123456789ABCDEF123456789ABC" -@@ -218,6 +220,7 @@ Output = c09d402423cbf233d26cae21f954547bc43fe80fd41360a0336cfdbe9aedad05bef6fd2 - # no padding - - # Too small input -+Availablein = default - Sign = RSA-2048 - Ctrl = rsa_padding_mode:none - Input = "0123456789ABCDEF123456789ABC" -@@ -225,6 +228,7 @@ Output = c09d402423cbf233d26cae21f954547bc43fe80fd41360a0336cfdbe9aedad05bef6fd2 - Result = KEYOP_ERROR - - # Digest set before padding -+Availablein = default - Sign = RSA-2048 - Ctrl = digest:sha256 - Ctrl = rsa_padding_mode:none -@@ -233,6 +237,7 @@ Output = 64b0e9f9892371110c40ba5739dc0974002aa6e6160b481447c6819947c2d3b537a6e37 - Result = PKEY_CTRL_ERROR - - # Digest set after padding -+Availablein = default - Sign = RSA-2048 - Ctrl = rsa_padding_mode:none - Ctrl = digest:sha256 -@@ -240,23 +245,27 @@ Input = 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef01234567 - Output = 64b0e9f9892371110c40ba5739dc0974002aa6e6160b481447c6819947c2d3b537a6e3775a85ae8ef75e000ca5498d772e3e797012ac8e462d72e567eb4afae0d1df72ffc84b3117045c58eb13aabb427fd6591577089dfa36d8d07ebd0670e4473683659b53b050c32397752cdee7c08de667f8de0ec01db01d440e433986e57ead2f877356b7d4985daf6c7ba09e46c061fe2372baa90cbd77557ef1143f46e27abf65c276f165a753e1f09e3719d1bfd8b32efe4aed2e97b502aa96ce472d3d91a09fae47b1a5103c448039ada73a57d7a001542bfb0b58c8b4bcb705a108a643434bb7ff997b58ba8b76425d7510aeff3e60f17af82191500517653fa5f3 - Result = PKEY_CTRL_ERROR - -+Availablein = default - Sign = RSA-2048 - Ctrl = rsa_padding_mode:none - Input = 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef - Output = 64b0e9f9892371110c40ba5739dc0974002aa6e6160b481447c6819947c2d3b537a6e3775a85ae8ef75e000ca5498d772e3e797012ac8e462d72e567eb4afae0d1df72ffc84b3117045c58eb13aabb427fd6591577089dfa36d8d07ebd0670e4473683659b53b050c32397752cdee7c08de667f8de0ec01db01d440e433986e57ead2f877356b7d4985daf6c7ba09e46c061fe2372baa90cbd77557ef1143f46e27abf65c276f165a753e1f09e3719d1bfd8b32efe4aed2e97b502aa96ce472d3d91a09fae47b1a5103c448039ada73a57d7a001542bfb0b58c8b4bcb705a108a643434bb7ff997b58ba8b76425d7510aeff3e60f17af82191500517653fa5f3 - -+Availablein = default - Verify = RSA-2048-PUBLIC - Ctrl = rsa_padding_mode:none - Input = 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef - Output = 64b0e9f9892371110c40ba5739dc0974002aa6e6160b481447c6819947c2d3b537a6e3775a85ae8ef75e000ca5498d772e3e797012ac8e462d72e567eb4afae0d1df72ffc84b3117045c58eb13aabb427fd6591577089dfa36d8d07ebd0670e4473683659b53b050c32397752cdee7c08de667f8de0ec01db01d440e433986e57ead2f877356b7d4985daf6c7ba09e46c061fe2372baa90cbd77557ef1143f46e27abf65c276f165a753e1f09e3719d1bfd8b32efe4aed2e97b502aa96ce472d3d91a09fae47b1a5103c448039ada73a57d7a001542bfb0b58c8b4bcb705a108a643434bb7ff997b58ba8b76425d7510aeff3e60f17af82191500517653fa5f3 - - # Plaintext modified -+Availablein = default - Verify = RSA-2048-PUBLIC - Ctrl = rsa_padding_mode:none - Input = 0223456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef - Output = 64b0e9f9892371110c40ba5739dc0974002aa6e6160b481447c6819947c2d3b537a6e3775a85ae8ef75e000ca5498d772e3e797012ac8e462d72e567eb4afae0d1df72ffc84b3117045c58eb13aabb427fd6591577089dfa36d8d07ebd0670e4473683659b53b050c32397752cdee7c08de667f8de0ec01db01d440e433986e57ead2f877356b7d4985daf6c7ba09e46c061fe2372baa90cbd77557ef1143f46e27abf65c276f165a753e1f09e3719d1bfd8b32efe4aed2e97b502aa96ce472d3d91a09fae47b1a5103c448039ada73a57d7a001542bfb0b58c8b4bcb705a108a643434bb7ff997b58ba8b76425d7510aeff3e60f17af82191500517653fa5f3 - Result = VERIFY_ERROR - -+Availablein = default - VerifyRecover = RSA-2048-PUBLIC - Ctrl = rsa_padding_mode:none - Input = 64b0e9f9892371110c40ba5739dc0974002aa6e6160b481447c6819947c2d3b537a6e3775a85ae8ef75e000ca5498d772e3e797012ac8e462d72e567eb4afae0d1df72ffc84b3117045c58eb13aabb427fd6591577089dfa36d8d07ebd0670e4473683659b53b050c32397752cdee7c08de667f8de0ec01db01d440e433986e57ead2f877356b7d4985daf6c7ba09e46c061fe2372baa90cbd77557ef1143f46e27abf65c276f165a753e1f09e3719d1bfd8b32efe4aed2e97b502aa96ce472d3d91a09fae47b1a5103c448039ada73a57d7a001542bfb0b58c8b4bcb705a108a643434bb7ff997b58ba8b76425d7510aeff3e60f17af82191500517653fa5f3 -@@ -370,6 +379,7 @@ rQPeR+HETwIDAQAB - PrivPubKeyPair = RSA-PSS:RSA-PSS-BAD2 - - # Zero salt length makes output deterministic -+Availablein = default - Sign = RSA-2048 - Ctrl = digest:sha256 - Ctrl = rsa_padding_mode:pss -@@ -378,6 +388,7 @@ Input="0123456789ABCDEF0123456789ABCDEF" - Output=4DE433D5844043EF08D354DA03CB29068780D52706D7D1E4D50EFB7D58C9D547D83A747DDD0635A96B28F854E50145518482CB49E963054621B53C60C498D07C16E9C2789C893CF38D4D86900DE71BDE463BD2761D1271E358C7480A1AC0BAB930DDF39602AD1BC165B5D7436B516B7A7858E8EB7AB1C420EEB482F4D207F0E462B1724959320A084E13848D11D10FB593E66BF680BF6D3F345FC3E9C3DE60ABBAC37E1C6EC80A268C8D9FC49626C679097AA690BC1AA662B95EB8DB70390861AA0898229F9349B4B5FDD030D4928C47084708A933144BE23BD3C6E661B85B2C0EF9ED36D498D5B7320E8194D363D4AD478C059BAE804181965E0B81B663158A - - # Verify of above signature -+Availablein = default - Verify = RSA-2048-PUBLIC - Ctrl = rsa_padding_mode:pss - Ctrl = rsa_pss_saltlen:0 -@@ -395,6 +406,7 @@ Input="0123456789ABCDEF0123" - Output = 6BF7EDC63A0BA184EEEC7F3020FEC8F5EBF38C2B76481881F48BCCE5796E7AB294548BA9AE810457C7723CABD1BDE94CF59CF7C0FC7461B22760C8ED703DD98E97BFDD61FA8D1181C411F6DEE5FF159F4850746D78EDEE385A363DC28E2CB373D5CAD7953F3BD5E639BE345732C03A1BDEA268814DA036EB1891C82D4012F3B903D86636055F87B96FC98806AD1B217685A4D754046A5DE0B0D7870664BE07902153EC85BA457BE7D7F89D7FE0F626D02A9CBBB2BB479DDA1A5CAE75247FB7BF6BFB15C1D3FD9E6B1573CCDBC72011C3B97716058BB11C7EA2E4E56ADAFE1F5DE6A7FD405AC5890100F9C3408EFFB5C73BF73F48177FF743B4B819D0699D507B - - # Digest too short -+Availablein = default - Verify = RSA-2048-PUBLIC - Ctrl = rsa_padding_mode:pss - Ctrl = rsa_pss_saltlen:0 -@@ -404,6 +416,7 @@ Output=4DE433D5844043EF08D354DA03CB29068780D52706D7D1E4D50EFB7D58C9D547D83A747DD - Result = VERIFY_ERROR - - # Digest too long -+Availablein = default - Verify = RSA-2048-PUBLIC - Ctrl = rsa_padding_mode:pss - Ctrl = rsa_pss_saltlen:0 -@@ -413,6 +426,7 @@ Output=4DE433D5844043EF08D354DA03CB29068780D52706D7D1E4D50EFB7D58C9D547D83A747DD - Result = VERIFY_ERROR - - # Wrong salt length -+Availablein = default - Verify = RSA-2048 - Ctrl = rsa_padding_mode:pss - Ctrl = rsa_pss_saltlen:2 -diff --git a/test/recipes/80-test_cms.t b/test/recipes/80-test_cms.t -index 9e7c721eab..d32833f42c 100644 ---- a/test/recipes/80-test_cms.t -+++ b/test/recipes/80-test_cms.t -@@ -72,7 +72,7 @@ my @smime_pkcs7_tests = ( - [ "signed content DER format, RSA key", - [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "DER", "-nodetach", - "-certfile", $smroot, "-signer", $smrsa1, "-out", "{output}.cms" ], -- [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms", "-inform", "DER", -+ [ "{cmd2}", @defaultprov, "-verify", "-in", "{output}.cms", "-inform", "DER", - "-CAfile", $smroot, "-out", "{output}.txt" ], - \&final_compare - ], -@@ -80,7 +80,7 @@ my @smime_pkcs7_tests = ( - [ "signed detached content DER format, RSA key", - [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "DER", - "-signer", $smrsa1, "-out", "{output}.cms" ], -- [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms", "-inform", "DER", -+ [ "{cmd2}", @defaultprov, "-verify", "-in", "{output}.cms", "-inform", "DER", - "-CAfile", $smroot, "-out", "{output}.txt", - "-content", $smcont ], - \&final_compare -@@ -90,7 +90,7 @@ my @smime_pkcs7_tests = ( - [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "DER", "-nodetach", - "-stream", - "-signer", $smrsa1, "-out", "{output}.cms" ], -- [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms", "-inform", "DER", -+ [ "{cmd2}", @defaultprov, "-verify", "-in", "{output}.cms", "-inform", "DER", - "-CAfile", $smroot, "-out", "{output}.txt" ], - \&final_compare - ], -@@ -117,7 +117,7 @@ my @smime_pkcs7_tests = ( - "-signer", catfile($smdir, "smdsa1.pem"), "-out", "{output}.cms" ], - [ "{cmd1}", @prov, "-resign", "-in", "{output}.cms", "-inform", "DER", "-outform", "DER", - "-signer", $smrsa1, "-out", "{output}2.cms" ], -- [ "{cmd2}", @prov, "-verify", "-in", "{output}2.cms", "-inform", "DER", -+ [ "{cmd2}", @defaultprov, "-verify", "-in", "{output}2.cms", "-inform", "DER", - "-CAfile", $smroot, "-out", "{output}.txt", - "-content", $smcont ], - \&final_compare -@@ -140,20 +140,20 @@ my @smime_pkcs7_tests = ( - "-signer", catfile($smdir, "smdsa1.pem"), - "-signer", catfile($smdir, "smdsa2.pem"), - "-out", "{output}.cms" ], -- [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms", "-inform", "DER", -+ [ "{cmd2}", @defaultprov, "-verify", "-in", "{output}.cms", "-inform", "DER", - "-CAfile", $smroot, "-out", "{output}.txt" ], - \&final_compare - ], - - [ "signed content test streaming BER format, 2 DSA and 2 RSA keys, no attributes, no Red Hat FIPS", -- [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "DER", -+ [ "{cmd1}", @defaultprov, "-sign", "-in", $smcont, "-outform", "DER", - "-noattr", "-nodetach", "-stream", - "-signer", $smrsa1, - "-signer", catfile($smdir, "smrsa2.pem"), - "-signer", catfile($smdir, "smdsa1.pem"), - "-signer", catfile($smdir, "smdsa2.pem"), - "-out", "{output}.cms" ], -- [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms", "-inform", "DER", -+ [ "{cmd2}", @defaultprov, "-verify", "-in", "{output}.cms", "-inform", "DER", - "-CAfile", $smroot, "-out", "{output}.txt" ], - \&final_compare - ], -@@ -182,7 +182,7 @@ my @smime_pkcs7_tests = ( - "-signer", catfile($smdir, "smdsa1.pem"), - "-signer", catfile($smdir, "smdsa2.pem"), - "-stream", "-out", "{output}.cms" ], -- [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms", -+ [ "{cmd2}", @defaultprov, "-verify", "-in", "{output}.cms", - "-CAfile", $smroot, "-out", "{output}.txt" ], - \&final_compare - ], -@@ -194,7 +194,7 @@ my @smime_pkcs7_tests = ( - "-signer", catfile($smdir, "smdsa1.pem"), - "-signer", catfile($smdir, "smdsa2.pem"), - "-stream", "-out", "{output}.cms" ], -- [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms", -+ [ "{cmd2}", @defaultprov, "-verify", "-in", "{output}.cms", - "-CAfile", $smroot, "-out", "{output}.txt" ], - \&final_compare - ], -@@ -504,11 +504,11 @@ my @smime_cms_param_tests = ( - ], - - [ "signed content test streaming PEM format, RSA keys, PSS signature, no attributes", -- [ "{cmd1}", @prov, "-sign", "-in", $smcont, "-outform", "PEM", "-nodetach", -+ [ "{cmd1}", @defaultprov, "-sign", "-in", $smcont, "-outform", "PEM", "-nodetach", - "-noattr", "-signer", $smrsa1, - "-keyopt", "rsa_padding_mode:pss", - "-out", "{output}.cms" ], -- [ "{cmd2}", @prov, "-verify", "-in", "{output}.cms", "-inform", "PEM", -+ [ "{cmd2}", @defaultprov, "-verify", "-in", "{output}.cms", "-inform", "PEM", - "-CAfile", $smroot, "-out", "{output}.txt" ], - \&final_compare - ], --- -2.35.3 - diff --git a/0062-fips-Expose-a-FIPS-indicator.patch b/0062-fips-Expose-a-FIPS-indicator.patch new file mode 100644 index 0000000..6d368d8 --- /dev/null +++ b/0062-fips-Expose-a-FIPS-indicator.patch @@ -0,0 +1,466 @@ +From e3d6fca1af033d00c47bcd8f9ba28fcf1aa476aa Mon Sep 17 00:00:00 2001 +From: Clemens Lang +Date: Tue, 7 Jun 2022 12:02:49 +0200 +Subject: [PATCH] fips: Expose a FIPS indicator + +FIPS 140-3 requires us to indicate whether an operation was using +approved services or not. The FIPS 140-3 implementation guidelines +provide two basic approaches to doing this: implicit indicators, and +explicit indicators. + +Implicit indicators are basically the concept of "if the operation +passes, it was approved". We were originally aiming for implicit +indicators in our copy of OpenSSL. However, this proved to be a problem, +because we wanted to certify a signature service, and FIPS 140-3 +requires that a signature service computes the digest to be signed +within the boundaries of the FIPS module. Since we were planning to +certify fips.so only, this means that EVP_PKEY_sign/EVP_PKEY_verify +would have to be blocked. Unfortunately, EVP_SignFinal uses +EVP_PKEY_sign internally, but outside of fips.so and thus outside of the +FIPS module boundary. This means that using implicit indicators in +combination with certifying only fips.so would require us to block both +EVP_PKEY_sign and EVP_SignFinal, which are the two APIs currently used +by most users of OpenSSL for signatures. + +EVP_DigestSign would be acceptable, but has only been added in 3.0 and +is thus not yet widely used. + +As a consequence, we've decided to introduce explicit indicators so that +EVP_PKEY_sign and EVP_SignFinal can continue to work for now, but +FIPS-aware applications can query the explicit indicator to check +whether the operation was approved. + +To avoid affecting the ABI and public API too much, this is implemented +as an exported symbol in fips.so and a private header, so applications +that wish to use this will have to dlopen(3) fips.so, locate the +function using dlsym(3), and then call it. These applications will have +to build against the private header in order to use the returned +pointer. + +Modify util/mkdef.pl to support exposing a symbol only for a specific +provider identified by its name and path. + +Signed-off-by: Clemens Lang +--- + doc/build.info | 6 ++ + doc/man7/fips_module_indicators.pod | 154 ++++++++++++++++++++++++++++ + providers/fips/fipsprov.c | 71 +++++++++++++ + providers/fips/indicator.h | 66 ++++++++++++ + util/mkdef.pl | 25 ++++- + util/providers.num | 1 + + 6 files changed, 322 insertions(+), 1 deletion(-) + create mode 100644 doc/man7/fips_module_indicators.pod + create mode 100644 providers/fips/indicator.h + +diff --git a/doc/build.info b/doc/build.info +index b0aa4297a4..af235113bb 100644 +--- a/doc/build.info ++++ b/doc/build.info +@@ -4389,6 +4389,10 @@ DEPEND[html/man7/fips_module.html]=man7/fips_module.pod + GENERATE[html/man7/fips_module.html]=man7/fips_module.pod + DEPEND[man/man7/fips_module.7]=man7/fips_module.pod + GENERATE[man/man7/fips_module.7]=man7/fips_module.pod ++DEPEND[html/man7/fips_module_indicators.html]=man7/fips_module_indicators.pod ++GENERATE[html/man7/fips_module_indicators.html]=man7/fips_module_indicators.pod ++DEPEND[man/man7/fips_module_indicators.7]=man7/fips_module_indicators.pod ++GENERATE[man/man7/fips_module_indicators.7]=man7/fips_module_indicators.pod + DEPEND[html/man7/life_cycle-cipher.html]=man7/life_cycle-cipher.pod + GENERATE[html/man7/life_cycle-cipher.html]=man7/life_cycle-cipher.pod + DEPEND[man/man7/life_cycle-cipher.7]=man7/life_cycle-cipher.pod +@@ -4631,6 +4635,7 @@ html/man7/ct.html \ + html/man7/des_modes.html \ + html/man7/evp.html \ + html/man7/fips_module.html \ ++html/man7/fips_module_indicators.html \ + html/man7/life_cycle-cipher.html \ + html/man7/life_cycle-digest.html \ + html/man7/life_cycle-kdf.html \ +@@ -4754,6 +4759,7 @@ man/man7/ct.7 \ + man/man7/des_modes.7 \ + man/man7/evp.7 \ + man/man7/fips_module.7 \ ++man/man7/fips_module_indicators.7 \ + man/man7/life_cycle-cipher.7 \ + man/man7/life_cycle-digest.7 \ + man/man7/life_cycle-kdf.7 \ +diff --git a/doc/man7/fips_module_indicators.pod b/doc/man7/fips_module_indicators.pod +new file mode 100644 +index 0000000000..23db2b395c +--- /dev/null ++++ b/doc/man7/fips_module_indicators.pod +@@ -0,0 +1,154 @@ ++=pod ++ ++=head1 NAME ++ ++fips_module_indicators - Red Hat OpenSSL FIPS module indicators guide ++ ++=head1 DESCRIPTION ++ ++This guide documents how the Red Hat Enterprise Linux 9 OpenSSL FIPS provider ++implements Approved Security Service Indicators according to the FIPS 140-3 ++Implementation Guidelines, section 2.4.C. See ++L ++for the FIPS 140-3 Implementation Guidelines. ++ ++For all approved services except signatures, the Red Hat OpenSSL FIPS provider ++uses the return code as the indicator as understood by FIPS 140-3. That means ++that every operation that succeeds denotes use of an approved security service. ++Operations that do not succeed may not have been approved security services, or ++may have been used incorrectly. ++ ++For signatures, an explicit indicator API is available to determine whether ++a selected operation is an approved security service, in combination with the ++return code of the operation. For a signature operation to be approved, the ++explicit indicator must claim it as approved, and it must succeed. ++ ++=head2 Querying the explicit indicator ++ ++The Red Hat OpenSSL FIPS provider exports a symbol named ++I that provides information on which signature ++operations are approved security functions. To use this function, either link ++against I directly, or load it at runtime using dlopen(3) and ++dlsym(3). ++ ++ #include ++ #include "providers/fips/indicator.h" ++ ++ void *provider = dlopen("/usr/lib64/ossl-modules/fips.so", RTLD_LAZY); ++ if (provider == NULL) { ++ fprintf(stderr, "%s\n", dlerror()); ++ // handle error ++ } ++ ++ const OSSL_RH_FIPSINDICATOR_ALORITHM *(*redhat_ossl_query_fipsindicator)(int) \ ++ = dlsym(provider, "redhat_ossl_query_fipsindicator"); ++ if (redhat_ossl_query_fipsindicator == NULL) { ++ fprintf(stderr, "%s\n", dlerror()); ++ fprintf(stderr, "Does your copy of fips.so have the required Red Hat" ++ " patches?\n"); ++ // handle error ++ } ++ ++Note that this uses the I header, which is not ++public. Install the I package from the I ++repository using I and include ++I in the compiler's include path. ++ ++I expects an operation ID as its only ++argument. Currently, the only supported operation ID is I to ++obtain the indicators for signature operations. On success, the return value is ++a pointer to an array of Is. On failure, NULL is ++returned. The last entry in the array is indicated by I being ++NULL. ++ ++ typedef struct ossl_rh_fipsindicator_algorithm_st { ++ const char *algorithm_names; /* key */ ++ const char *property_definition; /* key */ ++ const OSSL_RH_FIPSINDICATOR_DISPATCH *indicators; ++ } OSSL_RH_FIPSINDICATOR_ALGORITHM; ++ ++ typedef struct ossl_rh_fipsindicator_dispatch_st { ++ int function_id; ++ int approved; ++ } OSSL_RH_FIPSINDICATOR_DISPATCH; ++ ++The I field is a colon-separated list of algorithm names from ++one of the I constants, e.g., I. strtok(3) can ++be used to locate the appropriate entry. See the example below, where ++I contains the algorithm name to search for: ++ ++ const OSSL_RH_FIPSINDICATOR_DISPATCH *indicator_dispatch = NULL; ++ const OSSL_RH_FIPSINDICATOR_ALGORITHM *indicator = ++ redhat_ossl_query_fipsindicator(operation_id); ++ if (indicator == NULL) { ++ fprintf(stderr, "No indicator for operation, probably using implicit" ++ " indicators.\n"); ++ // handle error ++ } ++ ++ for (; indicator->algorithm_names != NULL; ++indicator) { ++ char *algorithm_names = strdup(indicator->algorithm_names); ++ if (algorithm_names == NULL) { ++ perror("strdup(3)"); ++ // handle error ++ } ++ ++ const char *algorithm_name = strtok(algorithm_names, ":"); ++ for (; algorithm_name != NULL; algorithm_name = strtok(NULL, ":")) { ++ if (strcasecmp(algorithm_name, algorithm) == 0) { ++ indicator_dispatch = indicator->indicators; ++ free(algorithm_names); ++ algorithm_names = NULL; ++ break; ++ } ++ } ++ free(algorithm_names); ++ } ++ if (indicator_dispatch == NULL) { ++ fprintf(stderr, "No indicator for algorithm %s.\n", algorithm); ++ // handle error ++ } ++ ++If an appropriate I array is available for the ++given algorithm name, it maps function IDs to their approval status. The last ++entry is indicated by a zero I. I is ++I if the operation is an approved security ++service, or part of an approved security service, or ++I otherwise. Any other value is invalid. ++Function IDs are I constants from I, ++e.g., I or I. ++ ++Assuming I is the function in question, the following code can be ++used to query the approval status: ++ ++ for (; indicator_dispatch->function_id != 0; ++indicator_dispatch) { ++ if (indicator_dispatch->function_id == function_id) { ++ switch (indicator_dispatch->approved) { ++ case OSSL_RH_FIPSINDICATOR_APPROVED: ++ // approved security service ++ break; ++ case OSSL_RH_FIPSINDICATOR_UNAPPROVED: ++ // unapproved security service ++ break; ++ default: ++ // invalid result ++ break; ++ } ++ break; ++ } ++ } ++ ++=head1 SEE ALSO ++ ++L, L ++ ++=head1 COPYRIGHT ++ ++Copyright 2022 Red Hat, Inc. All Rights Reserved. ++ ++Licensed under the Apache License 2.0 (the "License"). You may not use ++this file except in compliance with the License. You can obtain a copy ++in the file LICENSE in the source distribution or at ++L. ++ ++=cut +diff --git a/providers/fips/fipsprov.c b/providers/fips/fipsprov.c +index de391ce067..1cfd71c5cf 100644 +--- a/providers/fips/fipsprov.c ++++ b/providers/fips/fipsprov.c +@@ -23,6 +23,7 @@ + #include "prov/seeding.h" + #include "self_test.h" + #include "internal/core.h" ++#include "indicator.h" + + static const char FIPS_DEFAULT_PROPERTIES[] = "provider=fips,fips=yes"; + static const char FIPS_UNAPPROVED_PROPERTIES[] = "provider=fips,fips=no"; +@@ -425,6 +426,68 @@ static const OSSL_ALGORITHM fips_signature[] = { + { NULL, NULL, NULL } + }; + ++static const OSSL_RH_FIPSINDICATOR_DISPATCH redhat_rsa_signature_indicators[] = { ++ { OSSL_FUNC_SIGNATURE_NEWCTX, OSSL_RH_FIPSINDICATOR_APPROVED }, ++ { OSSL_FUNC_SIGNATURE_SIGN_INIT, OSSL_RH_FIPSINDICATOR_UNAPPROVED }, ++ { OSSL_FUNC_SIGNATURE_SIGN, OSSL_RH_FIPSINDICATOR_UNAPPROVED }, ++ { OSSL_FUNC_SIGNATURE_VERIFY_INIT, OSSL_RH_FIPSINDICATOR_UNAPPROVED }, ++ { OSSL_FUNC_SIGNATURE_VERIFY, OSSL_RH_FIPSINDICATOR_UNAPPROVED }, ++ { OSSL_FUNC_SIGNATURE_VERIFY_RECOVER_INIT, OSSL_RH_FIPSINDICATOR_UNAPPROVED }, ++ { OSSL_FUNC_SIGNATURE_VERIFY_RECOVER, OSSL_RH_FIPSINDICATOR_UNAPPROVED }, ++ { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT, OSSL_RH_FIPSINDICATOR_APPROVED }, ++ { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_UPDATE, OSSL_RH_FIPSINDICATOR_APPROVED }, ++ { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_FINAL, OSSL_RH_FIPSINDICATOR_APPROVED }, ++ { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT, OSSL_RH_FIPSINDICATOR_APPROVED }, ++ { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_UPDATE, OSSL_RH_FIPSINDICATOR_APPROVED }, ++ { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_FINAL, OSSL_RH_FIPSINDICATOR_APPROVED }, ++ { OSSL_FUNC_SIGNATURE_FREECTX, OSSL_RH_FIPSINDICATOR_APPROVED }, ++ { OSSL_FUNC_SIGNATURE_DUPCTX, OSSL_RH_FIPSINDICATOR_APPROVED }, ++ { OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS, OSSL_RH_FIPSINDICATOR_APPROVED }, ++ { OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS, OSSL_RH_FIPSINDICATOR_APPROVED }, ++ { OSSL_FUNC_SIGNATURE_SET_CTX_PARAMS, OSSL_RH_FIPSINDICATOR_APPROVED }, ++ { OSSL_FUNC_SIGNATURE_SETTABLE_CTX_PARAMS, OSSL_RH_FIPSINDICATOR_APPROVED }, ++ { OSSL_FUNC_SIGNATURE_GET_CTX_MD_PARAMS, OSSL_RH_FIPSINDICATOR_APPROVED }, ++ { OSSL_FUNC_SIGNATURE_GETTABLE_CTX_MD_PARAMS, OSSL_RH_FIPSINDICATOR_APPROVED }, ++ { OSSL_FUNC_SIGNATURE_SET_CTX_MD_PARAMS, OSSL_RH_FIPSINDICATOR_APPROVED }, ++ { OSSL_FUNC_SIGNATURE_SETTABLE_CTX_MD_PARAMS, OSSL_RH_FIPSINDICATOR_APPROVED }, ++ { 0, OSSL_RH_FIPSINDICATOR_UNAPPROVED } ++}; ++ ++static const OSSL_RH_FIPSINDICATOR_DISPATCH redhat_ecdsa_signature_indicators[] = { ++ { OSSL_FUNC_SIGNATURE_NEWCTX, OSSL_RH_FIPSINDICATOR_APPROVED }, ++ { OSSL_FUNC_SIGNATURE_SIGN_INIT, OSSL_RH_FIPSINDICATOR_UNAPPROVED }, ++ { OSSL_FUNC_SIGNATURE_SIGN, OSSL_RH_FIPSINDICATOR_UNAPPROVED }, ++ { OSSL_FUNC_SIGNATURE_VERIFY_INIT, OSSL_RH_FIPSINDICATOR_UNAPPROVED }, ++ { OSSL_FUNC_SIGNATURE_VERIFY, OSSL_RH_FIPSINDICATOR_UNAPPROVED }, ++ { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT, OSSL_RH_FIPSINDICATOR_APPROVED }, ++ { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_UPDATE, OSSL_RH_FIPSINDICATOR_APPROVED }, ++ { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_FINAL, OSSL_RH_FIPSINDICATOR_APPROVED }, ++ { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT, OSSL_RH_FIPSINDICATOR_APPROVED }, ++ { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_UPDATE, OSSL_RH_FIPSINDICATOR_APPROVED }, ++ { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_FINAL, OSSL_RH_FIPSINDICATOR_APPROVED }, ++ { OSSL_FUNC_SIGNATURE_FREECTX, OSSL_RH_FIPSINDICATOR_APPROVED }, ++ { OSSL_FUNC_SIGNATURE_DUPCTX, OSSL_RH_FIPSINDICATOR_APPROVED }, ++ { OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS, OSSL_RH_FIPSINDICATOR_APPROVED }, ++ { OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS, OSSL_RH_FIPSINDICATOR_APPROVED }, ++ { OSSL_FUNC_SIGNATURE_SET_CTX_PARAMS, OSSL_RH_FIPSINDICATOR_APPROVED }, ++ { OSSL_FUNC_SIGNATURE_SETTABLE_CTX_PARAMS, OSSL_RH_FIPSINDICATOR_APPROVED }, ++ { OSSL_FUNC_SIGNATURE_GET_CTX_MD_PARAMS, OSSL_RH_FIPSINDICATOR_APPROVED }, ++ { OSSL_FUNC_SIGNATURE_GETTABLE_CTX_MD_PARAMS, OSSL_RH_FIPSINDICATOR_APPROVED }, ++ { OSSL_FUNC_SIGNATURE_SET_CTX_MD_PARAMS, OSSL_RH_FIPSINDICATOR_APPROVED }, ++ { OSSL_FUNC_SIGNATURE_SETTABLE_CTX_MD_PARAMS, OSSL_RH_FIPSINDICATOR_APPROVED }, ++ { 0, OSSL_RH_FIPSINDICATOR_UNAPPROVED } ++}; ++ ++static const OSSL_RH_FIPSINDICATOR_ALGORITHM redhat_indicator_fips_signature[] = { ++ { PROV_NAMES_RSA, FIPS_DEFAULT_PROPERTIES, ++ redhat_rsa_signature_indicators }, ++#ifndef OPENSSL_NO_EC ++ { PROV_NAMES_ECDSA, FIPS_DEFAULT_PROPERTIES, ++ redhat_ecdsa_signature_indicators }, ++#endif ++ { NULL, NULL, NULL } ++}; ++ + static const OSSL_ALGORITHM fips_asym_cipher[] = { + { PROV_NAMES_RSA, FIPS_DEFAULT_PROPERTIES, ossl_rsa_asym_cipher_functions }, + { NULL, NULL, NULL } +@@ -527,6 +590,14 @@ static void fips_deinit_casecmp(void) { + freelocale(loc); + } + ++const OSSL_RH_FIPSINDICATOR_ALGORITHM *redhat_ossl_query_fipsindicator(int operation_id) { ++ switch (operation_id) { ++ case OSSL_OP_SIGNATURE: ++ return redhat_indicator_fips_signature; ++ } ++ return NULL; ++} ++ + static void fips_teardown(void *provctx) + { + OSSL_LIB_CTX_free(PROV_LIBCTX_OF(provctx)); +diff --git a/providers/fips/indicator.h b/providers/fips/indicator.h +new file mode 100644 +index 0000000000..b323efe44c +--- /dev/null ++++ b/providers/fips/indicator.h +@@ -0,0 +1,66 @@ ++/* ++ * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved. ++ * ++ * Licensed under the Apache License 2.0 (the "License"). You may not use ++ * this file except in compliance with the License. You can obtain a copy ++ * in the file LICENSE in the source distribution or at ++ * https://www.openssl.org/source/license.html ++ */ ++ ++#ifndef OPENSSL_FIPS_INDICATOR_H ++# define OPENSSL_FIPS_INDICATOR_H ++# pragma once ++ ++# ifdef __cplusplus ++extern "C" { ++# endif ++ ++# define OSSL_RH_FIPSINDICATOR_UNAPPROVED (0) ++# define OSSL_RH_FIPSINDICATOR_APPROVED (1) ++ ++/* ++ * FIPS indicator dispatch table element. function_id numbers and the ++ * functions are defined in core_dispatch.h, see macros with ++ * 'OSSL_CORE_MAKE_FUNC' in their names. ++ * ++ * An array of these is always terminated by function_id == 0 ++ */ ++typedef struct ossl_rh_fipsindicator_dispatch_st { ++ int function_id; ++ int approved; ++} OSSL_RH_FIPSINDICATOR_DISPATCH; ++ ++/* ++ * Type to tie together algorithm names, property definition string and the ++ * algorithm implementation's FIPS indicator status in the form of a FIPS ++ * indicator dispatch table. ++ * ++ * An array of these is always terminated by algorithm_names == NULL ++ */ ++typedef struct ossl_rh_fipsindicator_algorithm_st { ++ const char *algorithm_names; /* key */ ++ const char *property_definition; /* key */ ++ const OSSL_RH_FIPSINDICATOR_DISPATCH *indicators; ++} OSSL_RH_FIPSINDICATOR_ALGORITHM; ++ ++/** ++ * Query FIPS indicator status for the given operation. Possible values for ++ * 'operation_id' are currently only OSSL_OP_SIGNATURE, as all other algorithms ++ * use implicit indicators. The return value is an array of ++ * OSSL_RH_FIPSINDICATOR_ALGORITHMs, terminated by an entry with ++ * algorithm_names == NULL. 'algorithm_names' is a colon-separated list of ++ * algorithm names, 'property_definition' a comma-separated list of properties, ++ * and 'indicators' is a list of OSSL_RH_FIPSINDICATOR_DISPATCH structs. This ++ * list is terminated by function_id == 0. 'function_id' is one of the ++ * OSSL_FUNC_* constants, e.g., OSSL_FUNC_SIGNATURE_DIGEST_SIGN_FINAL. ++ * ++ * If there is no entry in the returned struct for the given operation_id, ++ * algorithm name, or function_id, the algorithm is unapproved. ++ */ ++const OSSL_RH_FIPSINDICATOR_ALGORITHM *redhat_ossl_query_fipsindicator(int operation_id); ++ ++# ifdef __cplusplus ++} ++# endif ++ ++#endif +diff --git a/util/mkdef.pl b/util/mkdef.pl +index a1c76f7c97..eda39b71ee 100755 +--- a/util/mkdef.pl ++++ b/util/mkdef.pl +@@ -149,7 +149,8 @@ $ordinal_opts{filter} = + return + $item->exists() + && platform_filter($item) +- && feature_filter($item); ++ && feature_filter($item) ++ && fips_filter($item, $name); + }; + my $ordinals = OpenSSL::Ordinals->new(from => $ordinals_file); + +@@ -205,6 +206,28 @@ sub feature_filter { + return $verdict; + } + ++sub fips_filter { ++ my $item = shift; ++ my $name = uc(shift); ++ my @features = ( $item->features() ); ++ ++ # True if no features are defined ++ return 1 if scalar @features == 0; ++ ++ my @matches = grep(/^ONLY_.*$/, @features); ++ if (@matches) { ++ # There is at least one only_* flag on this symbol, check if any of ++ # them match the name ++ for (@matches) { ++ if ($_ eq "ONLY_${name}") { ++ return 1; ++ } ++ } ++ return 0; ++ } ++ return 1; ++} ++ + sub sorter_unix { + my $by_name = OpenSSL::Ordinals::by_name(); + my %weight = ( +diff --git a/util/providers.num b/util/providers.num +index 4e2fa81b98..77879d0e5f 100644 +--- a/util/providers.num ++++ b/util/providers.num +@@ -1 +1,2 @@ + OSSL_provider_init 1 * EXIST::FUNCTION: ++redhat_ossl_query_fipsindicator 1 * EXIST::FUNCTION:ONLY_PROVIDERS/FIPS +-- +2.35.3 + diff --git a/openssl.spec b/openssl.spec index 4792222..2109d0f 100644 --- a/openssl.spec +++ b/openssl.spec @@ -29,7 +29,7 @@ print(string.sub(hash, 0, 16)) Summary: Utilities from the general purpose cryptography library with TLS implementation Name: openssl Version: 3.0.1 -Release: 34%{?dist} +Release: 35%{?dist} Epoch: 1 # We have to remove certain patented algorithms from the openssl source # tarball with the hobble-openssl script which is included below. @@ -118,8 +118,7 @@ Patch58: 0058-FIPS-limit-rsa-encrypt.patch Patch60: 0060-FIPS-KAT-signature-tests.patch # https://bugzilla.redhat.com/show_bug.cgi?id=2087147 Patch61: 0061-Deny-SHA-1-signature-verification-in-FIPS-provider.patch -# Disabled for now because it breaks EVP_SignFinal -#Patch62: 0062-Disable-EVP_PKEY_-sign-verify-in-FIPS-provider.patch +Patch62: 0062-fips-Expose-a-FIPS-indicator.patch # https://github.com/openssl/openssl/pull/18141 Patch63: 0063-CVE-2022-1473.patch # upstream commits 55c80c222293a972587004c185dc5653ae207a0e 2eda98790c5c2741d76d23cc1e74b0dc4f4b391a @@ -459,6 +458,11 @@ install -m644 %{SOURCE9} \ %ldconfig_scriptlets libs %changelog +* Wed Jun 08 2022 Clemens Lang - 1:3.0.1-35 +- Add explicit indicators for signatures in FIPS mode and mark signature + primitives as unapproved. + Resolves: rhbz#2087147 + * Fri Jun 03 2022 Dmitry Belyavskiy - 1:3.0.1-34 - Some OpenSSL test certificates are expired, updating - Resolves: rhbz#2092456