From cf8c04f9e31a757dbdc5e7e241ec4c9cea001264 Mon Sep 17 00:00:00 2001 From: hzero1996 Date: Thu, 23 Mar 2023 20:59:01 +0800 Subject: [PATCH] backport some patches --- ...-documents-for-SM2-cert-verification.patch | 108 ++ ...test-cases-for-SM2-cert-verification.patch | 127 ++ ...x-a-document-description-in-apps-req.patch | 29 + ...ble-free-issue-when-signing-SM2-cert.patch | 121 ++ Backport-Fix-a-memleak-in-apps-verify.patch | 43 + Backport-Fix-no-ec-no-sm2-and-no-sm3.patch | 67 + ...me-SM2-functions-with-OPENSSL_NO_SM2.patch | 44 + ...sm2_id-consistent-with-other-setters.patch | 320 +++++ ...t-number-of-tests-if-SM2-is-disabled.patch | 30 + ...port-Support-SM2-certificate-signing.patch | 1189 +++++++++++++++++ ...Support-SM2-certificate-verification.patch | 579 ++++++++ ...port-parsing-of-SM2-ID-in-hexdecimal.patch | 127 ++ ...pport-raw-input-data-in-apps-pkeyutl.patch | 482 +++++++ ...A-but-both-CAserial-and-CAcreateseri.patch | 187 +++ ...S-support-to-the-large-app-data-test.patch | 76 ++ backport-Add-a-test-for-large-app-data.patch | 166 +++ ...uction-step-to-RSAZ-mod_exp-implemen.patch | 123 ++ ...-Add-test-for-EC_KEY_set_private_key.patch | 71 + ...d_exp_mont_consttime-with-normal-Mon.patch | 406 ++++++ ...ckport-a-missing-bug-fix-from-master.patch | 65 + ...info-in-SSL_CTX_use_serverinfo-to-v2.patch | 376 ++++++ ...rt-Coverity-1508506-misuse-of-time_t.patch | 177 +++ ...ty-1508534-1508540-misuses-of-time_t.patch | 67 + ...r-allocation-allows-for-the-Explicit.patch | 41 + ..._asn1-to-properly-report-some-errors.patch | 41 + backport-Fix-BIO_f_cipher-flushing.patch | 54 + ..._set_private_key-priv_key-regression.patch | 42 + ...rlf_copy-to-properly-report-an-error.patch | 45 + ...ending-and-SSL_has_pending-with-DTLS.patch | 89 ++ ...port-Fix-a-crash-in-v2i_IPAddrBlocks.patch | 76 ++ ...ix-a-logic-flaw-in-test_mod_exp_zero.patch | 33 + ...Fix-a-memory-leak-in-rsa_priv_encode.patch | 31 + ...asc-behavior-on-invalid-Ip-addresses.patch | 45 + ...ertificates-with-different-key-sizes.patch | 131 ++ ...port-Fix-test-case-for-a2i_IPADDRESS.patch | 42 + ...on-how-much-encryption-growth-we-can.patch | 71 + ...ack-in-the-openssl-s_client-s_server.patch | 64 + ...xes-segfault-occurrence-in-PEM_write.patch | 37 + ...dulus-for-bn_mul_mont-and-BN_mod_exp.patch | 208 +++ ...notify-check-after-the-no-time-check.patch | 40 + ...th-engine-using-different-openssl-ru.patch | 44 + backport-Test-case-for-a2i_IPADDRESS.patch | 91 ++ ...ng-the-first-app-data-record-with-Fi.patch | 183 +++ ...Set-modified-flag-when-X509_req_info.patch | 111 ++ ...ensions-Return-empty-stack-if-no-ext.patch | 32 + ...ss_rulestr-don-t-read-outside-rule_s.patch | 40 + openssl.spec | 52 +- 47 files changed, 6622 insertions(+), 1 deletion(-) create mode 100644 Backport-Add-documents-for-SM2-cert-verification.patch create mode 100644 Backport-Add-test-cases-for-SM2-cert-verification.patch create mode 100644 Backport-Fix-a-document-description-in-apps-req.patch create mode 100644 Backport-Fix-a-double-free-issue-when-signing-SM2-cert.patch create mode 100644 Backport-Fix-a-memleak-in-apps-verify.patch create mode 100644 Backport-Fix-no-ec-no-sm2-and-no-sm3.patch create mode 100644 Backport-Guard-some-SM2-functions-with-OPENSSL_NO_SM2.patch create mode 100644 Backport-Make-X509_set_sm2_id-consistent-with-other-setters.patch create mode 100644 Backport-Skip-the-correct-number-of-tests-if-SM2-is-disabled.patch create mode 100644 Backport-Support-SM2-certificate-signing.patch create mode 100644 Backport-Support-SM2-certificate-verification.patch create mode 100644 Backport-Support-parsing-of-SM2-ID-in-hexdecimal.patch create mode 100644 Backport-Support-raw-input-data-in-apps-pkeyutl.patch create mode 100644 backport-APPS-x509-With-CA-but-both-CAserial-and-CAcreateseri.patch create mode 100644 backport-Add-DTLS-support-to-the-large-app-data-test.patch create mode 100644 backport-Add-a-test-for-large-app-data.patch create mode 100644 backport-Add-an-extra-reduction-step-to-RSAZ-mod_exp-implemen.patch create mode 100644 backport-Add-test-for-EC_KEY_set_private_key.patch create mode 100644 backport-Always-end-BN_mod_exp_mont_consttime-with-normal-Mon.patch create mode 100644 backport-Backport-a-missing-bug-fix-from-master.patch create mode 100644 backport-Convert-serverinfo-in-SSL_CTX_use_serverinfo-to-v2.patch create mode 100644 backport-Coverity-1508506-misuse-of-time_t.patch create mode 100644 backport-Coverity-1508534-1508540-misuses-of-time_t.patch create mode 100644 backport-Ensure-our-buffer-allocation-allows-for-the-Explicit.patch create mode 100644 backport-Fix-BIO_f_asn1-to-properly-report-some-errors.patch create mode 100644 backport-Fix-BIO_f_cipher-flushing.patch create mode 100644 backport-Fix-EC_KEY_set_private_key-priv_key-regression.patch create mode 100644 backport-Fix-SMIME_crlf_copy-to-properly-report-an-error.patch create mode 100644 backport-Fix-SSL_pending-and-SSL_has_pending-with-DTLS.patch create mode 100644 backport-Fix-a-crash-in-v2i_IPAddrBlocks.patch create mode 100644 backport-Fix-a-logic-flaw-in-test_mod_exp_zero.patch create mode 100644 backport-Fix-a-memory-leak-in-rsa_priv_encode.patch create mode 100644 backport-Fix-ipv4_from_asc-behavior-on-invalid-Ip-addresses.patch create mode 100644 backport-Fix-re-signing-certificates-with-different-key-sizes.patch create mode 100644 backport-Fix-test-case-for-a2i_IPADDRESS.patch create mode 100644 backport-Fix-the-ceiling-on-how-much-encryption-growth-we-can.patch create mode 100644 backport-Fix-verify_callback-in-the-openssl-s_client-s_server.patch create mode 100644 backport-Fixes-segfault-occurrence-in-PEM_write.patch create mode 100644 backport-Limit-size-of-modulus-for-bn_mul_mont-and-BN_mod_exp.patch create mode 100644 backport-Moving-notify-check-after-the-no-time-check.patch create mode 100644 backport-Prevent-crash-with-engine-using-different-openssl-ru.patch create mode 100644 backport-Test-case-for-a2i_IPADDRESS.patch create mode 100644 backport-Test-that-swapping-the-first-app-data-record-with-Fi.patch create mode 100644 backport-X509-x509_req.c-Set-modified-flag-when-X509_req_info.patch create mode 100644 backport-X509_REQ_get_extensions-Return-empty-stack-if-no-ext.patch create mode 100644 backport-ssl_cipher_process_rulestr-don-t-read-outside-rule_s.patch diff --git a/Backport-Add-documents-for-SM2-cert-verification.patch b/Backport-Add-documents-for-SM2-cert-verification.patch new file mode 100644 index 0000000..4c8acd1 --- /dev/null +++ b/Backport-Add-documents-for-SM2-cert-verification.patch @@ -0,0 +1,108 @@ +From 400e9ffc906d66318e4f9364494809d5a519c718 Mon Sep 17 00:00:00 2001 +From: Paul Yang +Date: Wed, 13 Mar 2019 17:22:31 +0800 +Subject: [PATCH 06/15] Add documents for SM2 cert verification + +This follows #8321 which added the SM2 certificate verification feature. +This commit adds the related docs - the newly added 2 APIs and options +in apps/verify. + +Reviewed-by: Paul Dale +(Merged from https://github.com/openssl/openssl/pull/8465) +--- + doc/man1/verify.pod | 14 ++++++++++++ + doc/man3/X509_get0_sm2_id.pod | 43 +++++++++++++++++++++++++++++++++++ + 2 files changed, 57 insertions(+) + create mode 100644 doc/man3/X509_get0_sm2_id.pod + +diff --git a/doc/man1/verify.pod b/doc/man1/verify.pod +index da2b702..a6b6b2b 100644 +--- a/doc/man1/verify.pod ++++ b/doc/man1/verify.pod +@@ -50,6 +50,8 @@ B B + [B<-verify_name name>] + [B<-x509_strict>] + [B<-show_chain>] ++[B<-sm2-id string>] ++[B<-sm2-hex-id hex-string>] + [B<->] + [certificates] + +@@ -319,6 +321,16 @@ Display information about the certificate chain that has been built (if + successful). Certificates in the chain that came from the untrusted list will be + flagged as "untrusted". + ++=item B<-sm2-id> ++ ++Specify the ID string to use when verifying an SM2 certificate. The ID string is ++required by the SM2 signature algorithm for signing and verification. ++ ++=item B<-sm2-hex-id> ++ ++Specify a binary ID string to use when signing or verifying using an SM2 ++certificate. The argument for this option is string of hexadecimal digits. ++ + =item B<-> + + Indicates the last option. All arguments following this are assumed to be +@@ -774,6 +786,8 @@ The B<-show_chain> option was added in OpenSSL 1.1.0. + The B<-issuer_checks> option is deprecated as of OpenSSL 1.1.0 and + is silently ignored. + ++The B<-sm2-id> and B<-sm2-hex-id> options were added in OpenSSL 3.0.0. ++ + =head1 COPYRIGHT + + Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved. +diff --git a/doc/man3/X509_get0_sm2_id.pod b/doc/man3/X509_get0_sm2_id.pod +new file mode 100644 +index 0000000..84da71e +--- /dev/null ++++ b/doc/man3/X509_get0_sm2_id.pod +@@ -0,0 +1,43 @@ ++=pod ++ ++=head1 NAME ++ ++X509_get0_sm2_id, X509_set_sm2_id - get or set SM2 ID for certificate operations ++ ++=head1 SYNOPSIS ++ ++ #include ++ ++ ASN1_OCTET_STRING *X509_get0_sm2_id(X509 *x); ++ void X509_set_sm2_id(X509 *x, ASN1_OCTET_STRING *sm2_id); ++ ++=head1 DESCRIPTION ++ ++X509_get0_sm2_id() gets the ID value of an SM2 certificate B by returning an ++B object which should not be freed by the caller. ++X509_set_sm2_id() sets the B value to an SM2 certificate B. ++ ++=head1 NOTES ++ ++SM2 signature algorithm requires an ID value when generating and verifying a ++signature. The functions described in this manual provide the user with the ++ability to set and retrieve the SM2 ID value. ++ ++=head1 RETURN VALUES ++ ++X509_set_sm2_id() does not return a value. ++ ++=head1 SEE ALSO ++ ++L, L ++ ++=head1 COPYRIGHT ++ ++Copyright 2019 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 ++L. ++ ++=cut +-- +2.20.1 (Apple Git-117) + diff --git a/Backport-Add-test-cases-for-SM2-cert-verification.patch b/Backport-Add-test-cases-for-SM2-cert-verification.patch new file mode 100644 index 0000000..d1e2c68 --- /dev/null +++ b/Backport-Add-test-cases-for-SM2-cert-verification.patch @@ -0,0 +1,127 @@ +From c08251384c0405c151a90b315b8f333c38c74eb2 Mon Sep 17 00:00:00 2001 +From: Paul Yang +Date: Wed, 13 Mar 2019 16:54:11 +0800 +Subject: [PATCH 05/15] Add test cases for SM2 cert verification + +This follows #8321 which added the SM2 certificate verification feature. +This commit adds some test cases for #8321. + +Reviewed-by: Paul Dale +(Merged from https://github.com/openssl/openssl/pull/8465) +--- + test/certs/sm2-ca-cert.pem | 14 +++++++++++++ + test/certs/{sm2.crt => sm2.pem} | 0 + test/recipes/20-test_pkeyutl.t | 37 +++++++++++++-------------------- + test/recipes/25-test_verify.t | 14 ++++++++++++- + 4 files changed, 42 insertions(+), 23 deletions(-) + create mode 100644 test/certs/sm2-ca-cert.pem + rename test/certs/{sm2.crt => sm2.pem} (100%) + +diff --git a/test/certs/sm2-ca-cert.pem b/test/certs/sm2-ca-cert.pem +new file mode 100644 +index 0000000..5677ac6 +--- /dev/null ++++ b/test/certs/sm2-ca-cert.pem +@@ -0,0 +1,14 @@ ++-----BEGIN CERTIFICATE----- ++MIICJDCCAcqgAwIBAgIJAOlkpDpSrmVbMAoGCCqBHM9VAYN1MGgxCzAJBgNVBAYT ++AkNOMQswCQYDVQQIDAJMTjERMA8GA1UEBwwIU2hlbnlhbmcxETAPBgNVBAoMCFRl ++c3QgT3JnMRAwDgYDVQQLDAdUZXN0IE9VMRQwEgYDVQQDDAtUZXN0IFNNMiBDQTAe ++Fw0xOTAyMTkwNzA1NDhaFw0yMzAzMzAwNzA1NDhaMGgxCzAJBgNVBAYTAkNOMQsw ++CQYDVQQIDAJMTjERMA8GA1UEBwwIU2hlbnlhbmcxETAPBgNVBAoMCFRlc3QgT3Jn ++MRAwDgYDVQQLDAdUZXN0IE9VMRQwEgYDVQQDDAtUZXN0IFNNMiBDQTBZMBMGByqG ++SM49AgEGCCqBHM9VAYItA0IABHRYnqErofBdXPptvvO7+BSVJxcpHuTGnZ+UPrbU ++5kVEUMaUnNOeMJZl/vRGimZCm/AkReJmRfnb15ESHR+ssp6jXTBbMB0GA1UdDgQW ++BBTFjcWu/zJgSZ5SKUlU5Vx4/0W5dDAfBgNVHSMEGDAWgBTFjcWu/zJgSZ5SKUlU ++5Vx4/0W5dDAMBgNVHRMEBTADAQH/MAsGA1UdDwQEAwIBBjAKBggqgRzPVQGDdQNI ++ADBFAiEAs6byi1nSQtFELOw/2tQIv5AEsZFR5MJ/oB2ztXzs2LYCIEfIw4xlUH6X ++YFhs4RnIa0K9Ng1ebsGPrifYkudwBIk3 ++-----END CERTIFICATE----- +diff --git a/test/certs/sm2.crt b/test/certs/sm2.pem +similarity index 100% +rename from test/certs/sm2.crt +rename to test/certs/sm2.pem +diff --git a/test/recipes/20-test_pkeyutl.t b/test/recipes/20-test_pkeyutl.t +index 1457530..a36d41e 100644 +--- a/test/recipes/20-test_pkeyutl.t ++++ b/test/recipes/20-test_pkeyutl.t +@@ -17,32 +17,25 @@ setup("test_pkeyutl"); + + plan tests => 2; + +-sub sign +-{ +- # Utilize the sm2.crt as the TBS file +- return run(app(([ 'openssl', 'pkeyutl', '-sign', +- '-in', srctop_file('test', 'certs', 'sm2.crt'), +- '-inkey', srctop_file('test', 'certs', 'sm2.key'), +- '-out', 'signature.sm2', '-rawin', +- '-digest', 'sm3', '-pkeyopt', 'sm2_id:someid']))); +-} +- +-sub verify +-{ +- # Utilize the sm2.crt as the TBS file +- return run(app(([ 'openssl', 'pkeyutl', '-verify', '-certin', +- '-in', srctop_file('test', 'certs', 'sm2.crt'), +- '-inkey', srctop_file('test', 'certs', 'sm2.crt'), +- '-sigfile', 'signature.sm2', '-rawin', +- '-digest', 'sm3', '-pkeyopt', 'sm2_id:someid']))); +-} ++# For the tests below we use the cert itself as the TBS file + + SKIP: { + skip "Skipping tests that require EC, SM2 or SM3", 2 + if disabled("ec") || disabled("sm2") || disabled("sm3"); + +- ok(sign, "Sign a piece of data using SM2"); +- ok(verify, "Verify an SM2 signature against a piece of data"); ++ # SM2 ++ ok(run(app(([ 'openssl', 'pkeyutl', '-sign', ++ '-in', srctop_file('test', 'certs', 'sm2.pem'), ++ '-inkey', srctop_file('test', 'certs', 'sm2.key'), ++ '-out', 'signature.dat', '-rawin', ++ '-digest', 'sm3', '-pkeyopt', 'sm2_id:someid']))), ++ "Sign a piece of data using SM2"); ++ ok(run(app(([ 'openssl', 'pkeyutl', '-verify', '-certin', ++ '-in', srctop_file('test', 'certs', 'sm2.pem'), ++ '-inkey', srctop_file('test', 'certs', 'sm2.pem'), ++ '-sigfile', 'signature.dat', '-rawin', ++ '-digest', 'sm3', '-pkeyopt', 'sm2_id:someid']))), ++ "Verify an SM2 signature against a piece of data"); + } + +-unlink 'signature.sm2'; ++unlink 'signature.dat'; +diff --git a/test/recipes/25-test_verify.t b/test/recipes/25-test_verify.t +index ffa48ed..b340833 100644 +--- a/test/recipes/25-test_verify.t ++++ b/test/recipes/25-test_verify.t +@@ -27,7 +27,7 @@ sub verify { + run(app([@args])); + } + +-plan tests => 146; ++plan tests => 148; + + # Canonical success + ok(verify("ee-cert", "sslserver", ["root-cert"], ["ca-cert"]), +@@ -409,3 +409,15 @@ SKIP: { + "ED25519 signature"); + + } ++ ++SKIP: { ++ skip "SM2 is not supported by this OpenSSL build", 1 ++ if disabled("sm2"); ++ ++ # Test '-sm2-id' and '-sm2-hex-id' option ++ ok(verify("sm2", "any", ["sm2-ca-cert"], [], "-sm2-id", "1234567812345678"), ++ "SM2 ID test"); ++ ok(verify("sm2", "any", ["sm2-ca-cert"], [], "-sm2-hex-id", ++ "31323334353637383132333435363738"), ++ "SM2 hex ID test"); ++} +-- +2.20.1 (Apple Git-117) + diff --git a/Backport-Fix-a-document-description-in-apps-req.patch b/Backport-Fix-a-document-description-in-apps-req.patch new file mode 100644 index 0000000..421d83b --- /dev/null +++ b/Backport-Fix-a-document-description-in-apps-req.patch @@ -0,0 +1,29 @@ +From 7e64be50900c4aa8cd040c4e3999540883bdeeb6 Mon Sep 17 00:00:00 2001 +From: Paul Yang +Date: Thu, 26 Sep 2019 10:57:23 +0800 +Subject: [PATCH 13/15] Fix a document description in apps/req + +Reviewed-by: Matt Caswell +(Merged from https://github.com/openssl/openssl/pull/9958) +--- + doc/man1/req.pod | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/doc/man1/req.pod b/doc/man1/req.pod +index 7b00bad..e117ec6 100644 +--- a/doc/man1/req.pod ++++ b/doc/man1/req.pod +@@ -348,8 +348,8 @@ string is required by the SM2 signature algorithm for signing and verification. + + =item B<-sm2-hex-id> + +-Specify a binary ID string to use when signing or verifying using an SM2 +-certificate. The argument for this option is string of hexadecimal digits. ++Specify a binary ID string to use when verifying an SM2 certificate request. The ++argument for this option is string of hexadecimal digits. + + =back + +-- +2.20.1 (Apple Git-117) + diff --git a/Backport-Fix-a-double-free-issue-when-signing-SM2-cert.patch b/Backport-Fix-a-double-free-issue-when-signing-SM2-cert.patch new file mode 100644 index 0000000..e7e27cd --- /dev/null +++ b/Backport-Fix-a-double-free-issue-when-signing-SM2-cert.patch @@ -0,0 +1,121 @@ +From a63238684c1d2e15f417f766f44418a8b52ef383 Mon Sep 17 00:00:00 2001 +From: Paul Yang +Date: Sat, 21 Sep 2019 00:32:57 +0800 +Subject: [PATCH 12/15] Fix a double free issue when signing SM2 cert + +If the SM2 ID value has not been passed correctly when signing an SM2 +certificate/certificate request, a double free occurs. For instance: + + openssl req -x509 ... -sm2-id 1234567812345678 + +The '-sm2-id' should not be used in this scenario, while the '-sigopt' is +the correct one to use. Documentation has also been updated to make the +options more clear. + +Reviewed-by: Matt Caswell +(Merged from https://github.com/openssl/openssl/pull/9958) +--- + apps/req.c | 48 ++++++++++++++++++++++++++++++------------------ + doc/man1/req.pod | 4 ++-- + 2 files changed, 32 insertions(+), 20 deletions(-) + +diff --git a/apps/req.c b/apps/req.c +index 96f1edd..95dd0e4 100644 +--- a/apps/req.c ++++ b/apps/req.c +@@ -1756,15 +1756,19 @@ int do_X509_sign(X509 *x, EVP_PKEY *pkey, const EVP_MD *md, + #endif + + rv = do_sign_init(mctx, pkey, md, sigopts); +- if (rv > 0) ++ if (rv > 0) { + rv = X509_sign_ctx(x, mctx); + #ifndef OPENSSL_NO_SM2 +- /* only in SM2 case we need to free the pctx explicitly */ +- if (ec_pkey_is_sm2(pkey)) { +- pctx = EVP_MD_CTX_pkey_ctx(mctx); +- EVP_PKEY_CTX_free(pctx); +- } ++ /* ++ * only in SM2 case we need to free the pctx explicitly ++ * if do_sign_init() fails, pctx is already freed in it ++ */ ++ if (ec_pkey_is_sm2(pkey)) { ++ pctx = EVP_MD_CTX_pkey_ctx(mctx); ++ EVP_PKEY_CTX_free(pctx); ++ } + #endif ++ } + EVP_MD_CTX_free(mctx); + return rv > 0 ? 1 : 0; + } +@@ -1779,15 +1783,19 @@ int do_X509_REQ_sign(X509_REQ *x, EVP_PKEY *pkey, const EVP_MD *md, + #endif + + rv = do_sign_init(mctx, pkey, md, sigopts); +- if (rv > 0) ++ if (rv > 0) { + rv = X509_REQ_sign_ctx(x, mctx); + #ifndef OPENSSL_NO_SM2 +- /* only in SM2 case we need to free the pctx explicitly */ +- if (ec_pkey_is_sm2(pkey)) { +- pctx = EVP_MD_CTX_pkey_ctx(mctx); +- EVP_PKEY_CTX_free(pctx); +- } ++ /* ++ * only in SM2 case we need to free the pctx explicitly ++ * if do_sign_init() fails, pctx is already freed in it ++ */ ++ if (ec_pkey_is_sm2(pkey)) { ++ pctx = EVP_MD_CTX_pkey_ctx(mctx); ++ EVP_PKEY_CTX_free(pctx); ++ } + #endif ++ } + EVP_MD_CTX_free(mctx); + return rv > 0 ? 1 : 0; + } +@@ -1802,15 +1810,19 @@ int do_X509_CRL_sign(X509_CRL *x, EVP_PKEY *pkey, const EVP_MD *md, + #endif + + rv = do_sign_init(mctx, pkey, md, sigopts); +- if (rv > 0) ++ if (rv > 0) { + rv = X509_CRL_sign_ctx(x, mctx); + #ifndef OPENSSL_NO_SM2 +- /* only in SM2 case we need to free the pctx explicitly */ +- if (ec_pkey_is_sm2(pkey)) { +- pctx = EVP_MD_CTX_pkey_ctx(mctx); +- EVP_PKEY_CTX_free(pctx); +- } ++ /* ++ * only in SM2 case we need to free the pctx explicitly ++ * if do_sign_init() fails, no need to double free pctx ++ */ ++ if (ec_pkey_is_sm2(pkey)) { ++ pctx = EVP_MD_CTX_pkey_ctx(mctx); ++ EVP_PKEY_CTX_free(pctx); ++ } + #endif ++ } + EVP_MD_CTX_free(mctx); + return rv > 0 ? 1 : 0; + } +diff --git a/doc/man1/req.pod b/doc/man1/req.pod +index 3b9fcc3..7b00bad 100644 +--- a/doc/man1/req.pod ++++ b/doc/man1/req.pod +@@ -343,8 +343,8 @@ for key generation operations. + + =item B<-sm2-id> + +-Specify the ID string to use when verifying an SM2 certificate. The ID string is +-required by the SM2 signature algorithm for signing and verification. ++Specify the ID string to use when verifying an SM2 certificate request. The ID ++string is required by the SM2 signature algorithm for signing and verification. + + =item B<-sm2-hex-id> + +-- +2.20.1 (Apple Git-117) + diff --git a/Backport-Fix-a-memleak-in-apps-verify.patch b/Backport-Fix-a-memleak-in-apps-verify.patch new file mode 100644 index 0000000..53c2118 --- /dev/null +++ b/Backport-Fix-a-memleak-in-apps-verify.patch @@ -0,0 +1,43 @@ +From 1c243548ef736329b08344ad9191803e5a93ec17 Mon Sep 17 00:00:00 2001 +From: Paul Yang +Date: Wed, 13 Mar 2019 18:04:05 +0800 +Subject: [PATCH 07/15] Fix a memleak in apps/verify + +Reviewed-by: Paul Dale +(Merged from https://github.com/openssl/openssl/pull/8465) +--- + apps/verify.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/apps/verify.c b/apps/verify.c +index 09b31cf..5052d80 100644 +--- a/apps/verify.c ++++ b/apps/verify.c +@@ -80,6 +80,7 @@ int verify_main(int argc, char **argv) + OPTION_CHOICE o; + unsigned char *sm2_id = NULL; + size_t sm2_idlen = 0; ++ int sm2_free = 0; + + if ((vpm = X509_VERIFY_PARAM_new()) == NULL) + goto end; +@@ -174,6 +175,7 @@ int verify_main(int argc, char **argv) + break; + case OPT_SM2HEXID: + /* try to parse the input as hex string first */ ++ sm2_free = 1; + sm2_id = OPENSSL_hexstr2buf(opt_arg(), (long *)&sm2_idlen); + if (sm2_id == NULL) { + BIO_printf(bio_err, "Invalid hex string input\n"); +@@ -216,6 +218,8 @@ int verify_main(int argc, char **argv) + } + + end: ++ if (sm2_free) ++ OPENSSL_free(sm2_id); + X509_VERIFY_PARAM_free(vpm); + X509_STORE_free(store); + sk_X509_pop_free(untrusted, X509_free); +-- +2.20.1 (Apple Git-117) + diff --git a/Backport-Fix-no-ec-no-sm2-and-no-sm3.patch b/Backport-Fix-no-ec-no-sm2-and-no-sm3.patch new file mode 100644 index 0000000..6e1a9f3 --- /dev/null +++ b/Backport-Fix-no-ec-no-sm2-and-no-sm3.patch @@ -0,0 +1,67 @@ +From 380cf570be1ded495141e16ceab7afb7f7c57ab7 Mon Sep 17 00:00:00 2001 +From: Matt Caswell +Date: Thu, 28 Feb 2019 13:47:26 +0000 +Subject: [PATCH 02/15] Fix no-ec, no-sm2 and no-sm3 + +Reviewed-by: Richard Levitte +(Merged from https://github.com/openssl/openssl/pull/8372) +--- + apps/pkeyutl.c | 11 +++++++---- + test/recipes/20-test_pkeyutl.t | 9 +++++++-- + 2 files changed, 14 insertions(+), 6 deletions(-) + +diff --git a/apps/pkeyutl.c b/apps/pkeyutl.c +index bca0464..1d3d57b 100644 +--- a/apps/pkeyutl.c ++++ b/apps/pkeyutl.c +@@ -473,14 +473,16 @@ static EVP_PKEY_CTX *init_ctx(const char *kdfalg, int *pkeysize, + } + ctx = EVP_PKEY_CTX_new_id(kdfnid, impl); + } else { +- EC_KEY *eckey = NULL; +- const EC_GROUP *group = NULL; +- int nid; +- + if (pkey == NULL) + goto end; ++ ++#ifndef OPENSSL_NO_EC + /* SM2 needs a special treatment */ + if (EVP_PKEY_id(pkey) == EVP_PKEY_EC) { ++ EC_KEY *eckey = NULL; ++ const EC_GROUP *group = NULL; ++ int nid; ++ + if ((eckey = EVP_PKEY_get0_EC_KEY(pkey)) == NULL + || (group = EC_KEY_get0_group(eckey)) == NULL + || (nid = EC_GROUP_get_curve_name(group)) == 0) +@@ -488,6 +490,7 @@ static EVP_PKEY_CTX *init_ctx(const char *kdfalg, int *pkeysize, + if (nid == NID_sm2) + EVP_PKEY_set_alias_type(pkey, EVP_PKEY_SM2); + } ++#endif + *pkeysize = EVP_PKEY_size(pkey); + ctx = EVP_PKEY_CTX_new(pkey, impl); + if (ppkey != NULL) +diff --git a/test/recipes/20-test_pkeyutl.t b/test/recipes/20-test_pkeyutl.t +index a051138..1457530 100644 +--- a/test/recipes/20-test_pkeyutl.t ++++ b/test/recipes/20-test_pkeyutl.t +@@ -37,7 +37,12 @@ sub verify + '-digest', 'sm3', '-pkeyopt', 'sm2_id:someid']))); + } + +-ok(sign, "Sign a piece of data using SM2"); +-ok(verify, "Verify an SM2 signature against a piece of data"); ++SKIP: { ++ skip "Skipping tests that require EC, SM2 or SM3", 2 ++ if disabled("ec") || disabled("sm2") || disabled("sm3"); ++ ++ ok(sign, "Sign a piece of data using SM2"); ++ ok(verify, "Verify an SM2 signature against a piece of data"); ++} + + unlink 'signature.sm2'; +-- +2.20.1 (Apple Git-117) + diff --git a/Backport-Guard-some-SM2-functions-with-OPENSSL_NO_SM2.patch b/Backport-Guard-some-SM2-functions-with-OPENSSL_NO_SM2.patch new file mode 100644 index 0000000..87b3bfd --- /dev/null +++ b/Backport-Guard-some-SM2-functions-with-OPENSSL_NO_SM2.patch @@ -0,0 +1,44 @@ +From 908570d02b683195ddfdc8e8c324638bfaa0d2c2 Mon Sep 17 00:00:00 2001 +From: Matt Caswell +Date: Thu, 14 Mar 2019 11:14:38 +0000 +Subject: [PATCH 04/15] Guard some SM2 functions with OPENSSL_NO_SM2 + +Fixes the no-ec build + +Reviewed-by: Richard Levitte +(Merged from https://github.com/openssl/openssl/pull/8481) +--- + include/openssl/x509.h | 2 ++ + util/libcrypto.num | 4 ++-- + 2 files changed, 4 insertions(+), 2 deletions(-) + +diff --git a/include/openssl/x509.h b/include/openssl/x509.h +index 5f17057..5c88251 100644 +--- a/include/openssl/x509.h ++++ b/include/openssl/x509.h +@@ -573,8 +573,10 @@ void X509_get0_signature(const ASN1_BIT_STRING **psig, + const X509_ALGOR **palg, const X509 *x); + int X509_get_signature_nid(const X509 *x); + ++# ifndef OPENSSL_NO_SM2 + void X509_set_sm2_id(X509 *x, ASN1_OCTET_STRING *sm2_id); + ASN1_OCTET_STRING *X509_get0_sm2_id(X509 *x); ++# endif + + int X509_trusted(const X509 *x); + int X509_alias_set1(X509 *x, const unsigned char *name, int len); +diff --git a/util/libcrypto.num b/util/libcrypto.num +index 8635ac4..233d1c7 100644 +--- a/util/libcrypto.num ++++ b/util/libcrypto.num +@@ -4626,5 +4626,5 @@ FIPS_drbg_get_strength 6379 1_1_0g EXIST::FUNCTION: + FIPS_rand_strength 6380 1_1_0g EXIST::FUNCTION: + FIPS_drbg_get_blocklength 6381 1_1_0g EXIST::FUNCTION: + FIPS_drbg_init 6382 1_1_0g EXIST::FUNCTION: +-X509_set_sm2_id 6383 1_1_1m EXIST::FUNCTION: +-X509_get0_sm2_id 6384 1_1_1m EXIST::FUNCTION: ++X509_set_sm2_id 6383 1_1_1m EXIST::FUNCTION:SM2 ++X509_get0_sm2_id 6384 1_1_1m EXIST::FUNCTION:SM2 +-- +2.20.1 (Apple Git-117) + diff --git a/Backport-Make-X509_set_sm2_id-consistent-with-other-setters.patch b/Backport-Make-X509_set_sm2_id-consistent-with-other-setters.patch new file mode 100644 index 0000000..daeeee8 --- /dev/null +++ b/Backport-Make-X509_set_sm2_id-consistent-with-other-setters.patch @@ -0,0 +1,320 @@ +From 0717cc33d72b011cce4f53661c58d628b684275c Mon Sep 17 00:00:00 2001 +From: Paul Yang +Date: Mon, 1 Apr 2019 10:21:53 +0900 +Subject: [PATCH 09/15] Make X509_set_sm2_id consistent with other setters + +This commit makes the X509_set_sm2_id to 'set0' behaviour, which means +the memory management is passed to X509 and user doesn't need to free +the sm2_id parameter later. API name also changes to X509_set0_sm2_id. + +Document and test case are also updated. + +Reviewed-by: Matt Caswell +(Merged from https://github.com/openssl/openssl/pull/8626) +--- + apps/verify.c | 40 +++++++++++++++++++----------- + crypto/x509/x_all.c | 5 +++- + crypto/x509/x_x509.c | 13 +++++++--- + doc/man3/X509_get0_sm2_id.pod | 12 ++++++--- + include/crypto/x509.h | 2 +- + include/openssl/x509.h | 2 +- + test/verify_extra_test.c | 46 +++++++++++++++++++++++++++++++++++ + util/libcrypto.num | 2 +- + 8 files changed, 97 insertions(+), 25 deletions(-) + +diff --git a/apps/verify.c b/apps/verify.c +index 5052d80..9000567 100644 +--- a/apps/verify.c ++++ b/apps/verify.c +@@ -246,27 +246,37 @@ static int check(X509_STORE *ctx, const char *file, + + if (sm2id != NULL) { + #ifndef OPENSSL_NO_SM2 +- ASN1_OCTET_STRING v; ++ ASN1_OCTET_STRING *v; + +- v.data = sm2id; +- v.length = sm2idlen; ++ v = ASN1_OCTET_STRING_new(); ++ if (v == NULL) { ++ BIO_printf(bio_err, "error: SM2 ID allocation failed\n"); ++ goto end; ++ } + +- X509_set_sm2_id(x, &v); ++ if (!ASN1_OCTET_STRING_set(v, sm2id, sm2idlen)) { ++ BIO_printf(bio_err, "error: setting SM2 ID failed\n"); ++ ASN1_OCTET_STRING_free(v); ++ goto end; ++ } ++ ++ X509_set0_sm2_id(x, v); + #endif + } + + csc = X509_STORE_CTX_new(); + if (csc == NULL) { +- printf("error %s: X.509 store context allocation failed\n", +- (file == NULL) ? "stdin" : file); ++ BIO_printf(bio_err, "error %s: X.509 store context allocation failed\n", ++ (file == NULL) ? "stdin" : file); + goto end; + } + + X509_STORE_set_flags(ctx, vflags); + if (!X509_STORE_CTX_init(csc, ctx, x, uchain)) { + X509_STORE_CTX_free(csc); +- printf("error %s: X.509 store context initialization failed\n", +- (file == NULL) ? "stdin" : file); ++ BIO_printf(bio_err, ++ "error %s: X.509 store context initialization failed\n", ++ (file == NULL) ? "stdin" : file); + goto end; + } + if (tchain != NULL) +@@ -275,28 +285,30 @@ static int check(X509_STORE *ctx, const char *file, + X509_STORE_CTX_set0_crls(csc, crls); + i = X509_verify_cert(csc); + if (i > 0 && X509_STORE_CTX_get_error(csc) == X509_V_OK) { +- printf("%s: OK\n", (file == NULL) ? "stdin" : file); ++ BIO_printf(bio_out, "%s: OK\n", (file == NULL) ? "stdin" : file); + ret = 1; + if (show_chain) { + int j; + + chain = X509_STORE_CTX_get1_chain(csc); + num_untrusted = X509_STORE_CTX_get_num_untrusted(csc); +- printf("Chain:\n"); ++ BIO_printf(bio_out, "Chain:\n"); + for (j = 0; j < sk_X509_num(chain); j++) { + X509 *cert = sk_X509_value(chain, j); +- printf("depth=%d: ", j); ++ BIO_printf(bio_out, "depth=%d: ", j); + X509_NAME_print_ex_fp(stdout, + X509_get_subject_name(cert), + 0, get_nameopt()); + if (j < num_untrusted) +- printf(" (untrusted)"); +- printf("\n"); ++ BIO_printf(bio_out, " (untrusted)"); ++ BIO_printf(bio_out, "\n"); + } + sk_X509_pop_free(chain, X509_free); + } + } else { +- printf("error %s: verification failed\n", (file == NULL) ? "stdin" : file); ++ BIO_printf(bio_err, ++ "error %s: verification failed\n", ++ (file == NULL) ? "stdin" : file); + } + X509_STORE_CTX_free(csc); + +diff --git a/crypto/x509/x_all.c b/crypto/x509/x_all.c +index 60a2892..9c8aea5 100644 +--- a/crypto/x509/x_all.c ++++ b/crypto/x509/x_all.c +@@ -72,7 +72,10 @@ static int x509_verify_sm2(X509 *x, EVP_PKEY *pkey, int mdnid, int pknid) + ret = 0; + goto err; + } +- if (EVP_PKEY_CTX_set1_id(pctx, x->sm2_id.data, x->sm2_id.length) != 1) { ++ /* NOTE: we tolerate no actual ID, to provide maximum flexibility */ ++ if (x->sm2_id != NULL ++ && EVP_PKEY_CTX_set1_id(pctx, x->sm2_id->data, ++ x->sm2_id->length) != 1) { + X509err(X509_F_X509_VERIFY_SM2, ERR_R_EVP_LIB); + ret = 0; + goto err; +diff --git a/crypto/x509/x_x509.c b/crypto/x509/x_x509.c +index 1beab78..fb03bb2 100644 +--- a/crypto/x509/x_x509.c ++++ b/crypto/x509/x_x509.c +@@ -72,6 +72,9 @@ static int x509_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, + #ifndef OPENSSL_NO_RFC3779 + ret->rfc3779_addr = NULL; + ret->rfc3779_asid = NULL; ++#endif ++#ifndef OPENSSL_NO_SM2 ++ ret->sm2_id = NULL; + #endif + ret->aux = NULL; + ret->crldp = NULL; +@@ -91,6 +94,9 @@ static int x509_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, + #ifndef OPENSSL_NO_RFC3779 + sk_IPAddressFamily_pop_free(ret->rfc3779_addr, IPAddressFamily_free); + ASIdentifiers_free(ret->rfc3779_asid); ++#endif ++#ifndef OPENSSL_NO_SM2 ++ ASN1_OCTET_STRING_free(ret->sm2_id); + #endif + break; + +@@ -247,13 +253,14 @@ int X509_get_signature_nid(const X509 *x) + } + + #ifndef OPENSSL_NO_SM2 +-void X509_set_sm2_id(X509 *x, ASN1_OCTET_STRING *sm2_id) ++void X509_set0_sm2_id(X509 *x, ASN1_OCTET_STRING *sm2_id) + { +- x->sm2_id = *sm2_id; ++ ASN1_OCTET_STRING_free(x->sm2_id); ++ x->sm2_id = sm2_id; + } + + ASN1_OCTET_STRING *X509_get0_sm2_id(X509 *x) + { +- return &x->sm2_id; ++ return x->sm2_id; + } + #endif +diff --git a/doc/man3/X509_get0_sm2_id.pod b/doc/man3/X509_get0_sm2_id.pod +index 84da71e..9698c86 100644 +--- a/doc/man3/X509_get0_sm2_id.pod ++++ b/doc/man3/X509_get0_sm2_id.pod +@@ -2,20 +2,24 @@ + + =head1 NAME + +-X509_get0_sm2_id, X509_set_sm2_id - get or set SM2 ID for certificate operations ++X509_get0_sm2_id, X509_set0_sm2_id - get or set SM2 ID for certificate operations + + =head1 SYNOPSIS + + #include + + ASN1_OCTET_STRING *X509_get0_sm2_id(X509 *x); +- void X509_set_sm2_id(X509 *x, ASN1_OCTET_STRING *sm2_id); ++ void X509_set0_sm2_id(X509 *x, ASN1_OCTET_STRING *sm2_id); + + =head1 DESCRIPTION + + X509_get0_sm2_id() gets the ID value of an SM2 certificate B by returning an + B object which should not be freed by the caller. +-X509_set_sm2_id() sets the B value to an SM2 certificate B. ++ ++X509_set0_sm2_id() sets the B value to an SM2 certificate B. Calling ++this function transfers the memory management of the value to the X509 object, ++and therefore the value that has been passed in should not be freed by the ++caller after this function has been called. + + =head1 NOTES + +@@ -25,7 +29,7 @@ ability to set and retrieve the SM2 ID value. + + =head1 RETURN VALUES + +-X509_set_sm2_id() does not return a value. ++X509_set0_sm2_id() does not return a value. + + =head1 SEE ALSO + +diff --git a/include/crypto/x509.h b/include/crypto/x509.h +index 418c427..5c314a8 100644 +--- a/include/crypto/x509.h ++++ b/include/crypto/x509.h +@@ -186,7 +186,7 @@ struct x509_st { + CRYPTO_RWLOCK *lock; + volatile int ex_cached; + # ifndef OPENSSL_NO_SM2 +- ASN1_OCTET_STRING sm2_id; ++ ASN1_OCTET_STRING *sm2_id; + # endif + } /* X509 */ ; + +diff --git a/include/openssl/x509.h b/include/openssl/x509.h +index 5c88251..a02cf50 100644 +--- a/include/openssl/x509.h ++++ b/include/openssl/x509.h +@@ -574,7 +574,7 @@ void X509_get0_signature(const ASN1_BIT_STRING **psig, + int X509_get_signature_nid(const X509 *x); + + # ifndef OPENSSL_NO_SM2 +-void X509_set_sm2_id(X509 *x, ASN1_OCTET_STRING *sm2_id); ++void X509_set0_sm2_id(X509 *x, ASN1_OCTET_STRING *sm2_id); + ASN1_OCTET_STRING *X509_get0_sm2_id(X509 *x); + # endif + +diff --git a/test/verify_extra_test.c b/test/verify_extra_test.c +index b9959e0..763ea4f 100644 +--- a/test/verify_extra_test.c ++++ b/test/verify_extra_test.c +@@ -8,6 +8,7 @@ + */ + + #include ++#include + #include + #include + #include +@@ -231,6 +232,48 @@ static int test_self_signed_bad(void) + return test_self_signed(bad_f, 0); + } + ++#ifndef OPENSSL_NO_SM2 ++static int test_sm2_id(void) ++{ ++ /* we only need an X509 structure, no matter if it's a real SM2 cert */ ++ X509 *x = NULL; ++ BIO *bio = NULL; ++ int ret = 0; ++ ASN1_OCTET_STRING *v = NULL, *v2 = NULL; ++ char *sm2id = "this is an ID"; ++ ++ bio = BIO_new_file(bad_f, "r"); ++ if (bio == NULL) ++ goto err; ++ ++ x = PEM_read_bio_X509(bio, NULL, 0, NULL); ++ if (x == NULL) ++ goto err; ++ ++ v = ASN1_OCTET_STRING_new(); ++ if (v == NULL) ++ goto err; ++ ++ if (!ASN1_OCTET_STRING_set(v, (unsigned char *)sm2id, (int)strlen(sm2id))) { ++ ASN1_OCTET_STRING_free(v); ++ goto err; ++ } ++ ++ X509_set0_sm2_id(x, v); ++ ++ v2 = X509_get0_sm2_id(x); ++ if (!TEST_ptr(v2) ++ || !TEST_int_eq(ASN1_OCTET_STRING_cmp(v, v2), 0)) ++ goto err; ++ ++ ret = 1; ++ err: ++ X509_free(x); ++ BIO_free(bio); ++ return ret; ++} ++#endif ++ + int setup_tests(void) + { + if (!TEST_ptr(roots_f = test_get_argument(0)) +@@ -245,5 +288,8 @@ int setup_tests(void) + ADD_TEST(test_store_ctx); + ADD_TEST(test_self_signed_good); + ADD_TEST(test_self_signed_bad); ++#ifndef OPENSSL_NO_SM2 ++ ADD_TEST(test_sm2_id); ++#endif + return 1; + } +diff --git a/util/libcrypto.num b/util/libcrypto.num +index 233d1c7..d7abe91 100644 +--- a/util/libcrypto.num ++++ b/util/libcrypto.num +@@ -4626,5 +4626,5 @@ FIPS_drbg_get_strength 6379 1_1_0g EXIST::FUNCTION: + FIPS_rand_strength 6380 1_1_0g EXIST::FUNCTION: + FIPS_drbg_get_blocklength 6381 1_1_0g EXIST::FUNCTION: + FIPS_drbg_init 6382 1_1_0g EXIST::FUNCTION: +-X509_set_sm2_id 6383 1_1_1m EXIST::FUNCTION:SM2 ++X509_set0_sm2_id 6383 1_1_1m EXIST::FUNCTION:SM2 + X509_get0_sm2_id 6384 1_1_1m EXIST::FUNCTION:SM2 +-- +2.20.1 (Apple Git-117) + diff --git a/Backport-Skip-the-correct-number-of-tests-if-SM2-is-disabled.patch b/Backport-Skip-the-correct-number-of-tests-if-SM2-is-disabled.patch new file mode 100644 index 0000000..b0e5f9d --- /dev/null +++ b/Backport-Skip-the-correct-number-of-tests-if-SM2-is-disabled.patch @@ -0,0 +1,30 @@ +From f0dd65378296590d87250bf2130bad567483ee3d Mon Sep 17 00:00:00 2001 +From: Matt Caswell +Date: Wed, 3 Apr 2019 09:44:41 +0100 +Subject: [PATCH 08/15] Skip the correct number of tests if SM2 is disabled + +Fixes no-sm2 (and also no-sm3 and no-ec) + +Reviewed-by: Richard Levitte +Reviewed-by: Paul Dale +(Merged from https://github.com/openssl/openssl/pull/8650) +--- + test/recipes/25-test_verify.t | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/test/recipes/25-test_verify.t b/test/recipes/25-test_verify.t +index b340833..d254bd8 100644 +--- a/test/recipes/25-test_verify.t ++++ b/test/recipes/25-test_verify.t +@@ -411,7 +411,7 @@ SKIP: { + } + + SKIP: { +- skip "SM2 is not supported by this OpenSSL build", 1 ++ skip "SM2 is not supported by this OpenSSL build", 2 + if disabled("sm2"); + + # Test '-sm2-id' and '-sm2-hex-id' option +-- +2.20.1 (Apple Git-117) + diff --git a/Backport-Support-SM2-certificate-signing.patch b/Backport-Support-SM2-certificate-signing.patch new file mode 100644 index 0000000..11e84cc --- /dev/null +++ b/Backport-Support-SM2-certificate-signing.patch @@ -0,0 +1,1189 @@ +From 0bacd53ecedfef3ca8af4a8884c46ec8e47c83fa Mon Sep 17 00:00:00 2001 +From: Paul Yang +Date: Wed, 5 Jun 2019 14:46:48 +0800 +Subject: [PATCH 10/15] Support SM2 certificate signing + +SM2 certificate signing request can be created and signed by OpenSSL +now, both in library and apps. + +Documentation and test cases are added. + +Reviewed-by: Tim Hudson +Reviewed-by: Shane Lontis +(Merged from https://github.com/openssl/openssl/pull/9085) +--- + CHANGES | 3 + + apps/ca.c | 68 ++++++++++++- + apps/req.c | 149 ++++++++++++++++++++++++++-- + crypto/asn1/a_sign.c | 13 ++- + crypto/ec/ec_pmeth.c | 3 +- + crypto/err/openssl.txt | 3 + + crypto/x509/x509_err.c | 4 + + crypto/x509/x_all.c | 85 ++++++++++++---- + crypto/x509/x_req.c | 38 ++++++- + crypto/x509/x_x509.c | 3 + + doc/man1/ca.pod | 16 +++ + doc/man1/req.pod | 21 ++++ + doc/man3/X509_get0_sm2_id.pod | 12 ++- + include/crypto/x509.h | 3 + + include/openssl/x509.h | 2 + + include/openssl/x509err.h | 3 + + test/certs/sm2-csr.pem | 9 ++ + test/certs/sm2-root.crt | 14 +++ + test/certs/sm2-root.key | 5 + + test/recipes/25-test_req.t | 21 +++- + test/recipes/70-test_verify_extra.t | 3 +- + test/recipes/80-test_ca.t | 20 +++- + test/verify_extra_test.c | 45 ++++++++- + util/libcrypto.num | 2 + + 24 files changed, 501 insertions(+), 44 deletions(-) + create mode 100644 test/certs/sm2-csr.pem + create mode 100644 test/certs/sm2-root.crt + create mode 100644 test/certs/sm2-root.key + +diff --git a/CHANGES b/CHANGES +index 9d58cb0..6ab70fe 100644 +--- a/CHANGES ++++ b/CHANGES +@@ -9,6 +9,9 @@ + + Changes between 1.1.1l and 1.1.1m [14 Dec 2021] + ++ *) Support SM2 signing and verification schemes with X509 certificate. ++ [Paul Yang] ++ + *) Avoid loading of a dynamic engine twice. + + [Bernd Edlinger] +diff --git a/apps/ca.c b/apps/ca.c +index 390ac37..795ee2c 100755 +--- a/apps/ca.c ++++ b/apps/ca.c +@@ -96,7 +96,8 @@ static int certify(X509 **xret, const char *infile, EVP_PKEY *pkey, X509 *x509, + const char *enddate, + long days, int batch, const char *ext_sect, CONF *conf, + int verbose, unsigned long certopt, unsigned long nameopt, +- int default_op, int ext_copy, int selfsign); ++ int default_op, int ext_copy, int selfsign, ++ unsigned char *sm2_id, size_t sm2idlen); + static int certify_cert(X509 **xret, const char *infile, EVP_PKEY *pkey, X509 *x509, + const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts, + STACK_OF(CONF_VALUE) *policy, CA_DB *db, +@@ -147,7 +148,7 @@ typedef enum OPTION_choice { + OPT_INFILES, OPT_SS_CERT, OPT_SPKAC, OPT_REVOKE, OPT_VALID, + OPT_EXTENSIONS, OPT_EXTFILE, OPT_STATUS, OPT_UPDATEDB, OPT_CRLEXTS, + OPT_RAND_SERIAL, +- OPT_R_ENUM, ++ OPT_R_ENUM, OPT_SM2ID, OPT_SM2HEXID, + /* Do not change the order here; see related case statements below */ + OPT_CRL_REASON, OPT_CRL_HOLD, OPT_CRL_COMPROMISE, OPT_CRL_CA_COMPROMISE + } OPTION_CHOICE; +@@ -217,6 +218,12 @@ const OPTIONS ca_options[] = { + OPT_R_OPTIONS, + #ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, ++#endif ++#ifndef OPENSSL_NO_SM2 ++ {"sm2-id", OPT_SM2ID, 's', ++ "Specify an ID string to verify an SM2 certificate request"}, ++ {"sm2-hex-id", OPT_SM2HEXID, 's', ++ "Specify a hex ID string to verify an SM2 certificate request"}, + #endif + {NULL} + }; +@@ -262,6 +269,9 @@ int ca_main(int argc, char **argv) + REVINFO_TYPE rev_type = REV_NONE; + X509_REVOKED *r = NULL; + OPTION_CHOICE o; ++ unsigned char *sm2_id = NULL; ++ size_t sm2_idlen = 0; ++ int sm2_free = 0; + + prog = opt_init(argc, argv, ca_options); + while ((o = opt_next()) != OPT_EOF) { +@@ -425,6 +435,30 @@ opthelp: + case OPT_ENGINE: + e = setup_engine(opt_arg(), 0); + break; ++ case OPT_SM2ID: ++ /* we assume the input is not a hex string */ ++ if (sm2_id != NULL) { ++ BIO_printf(bio_err, ++ "Use one of the options 'sm2-hex-id' or 'sm2-id'\n"); ++ goto end; ++ } ++ sm2_id = (unsigned char *)opt_arg(); ++ sm2_idlen = strlen((const char *)sm2_id); ++ break; ++ case OPT_SM2HEXID: ++ /* try to parse the input as hex string first */ ++ if (sm2_id != NULL) { ++ BIO_printf(bio_err, ++ "Use one of the options 'sm2-hex-id' or 'sm2-id'\n"); ++ goto end; ++ } ++ sm2_free = 1; ++ sm2_id = OPENSSL_hexstr2buf(opt_arg(), (long *)&sm2_idlen); ++ if (sm2_id == NULL) { ++ BIO_printf(bio_err, "Invalid hex string input\n"); ++ goto end; ++ } ++ break; + } + } + end_of_options: +@@ -913,7 +947,8 @@ end_of_options: + j = certify(&x, infile, pkey, x509p, dgst, sigopts, attribs, db, + serial, subj, chtype, multirdn, email_dn, startdate, + enddate, days, batch, extensions, conf, verbose, +- certopt, get_nameopt(), default_op, ext_copy, selfsign); ++ certopt, get_nameopt(), default_op, ext_copy, selfsign, ++ sm2_id, sm2_idlen); + if (j < 0) + goto end; + if (j > 0) { +@@ -932,7 +967,8 @@ end_of_options: + j = certify(&x, argv[i], pkey, x509p, dgst, sigopts, attribs, db, + serial, subj, chtype, multirdn, email_dn, startdate, + enddate, days, batch, extensions, conf, verbose, +- certopt, get_nameopt(), default_op, ext_copy, selfsign); ++ certopt, get_nameopt(), default_op, ext_copy, selfsign, ++ sm2_id, sm2_idlen); + if (j < 0) + goto end; + if (j > 0) { +@@ -1230,6 +1266,8 @@ end_of_options: + ret = 0; + + end: ++ if (sm2_free) ++ OPENSSL_free(sm2_id); + if (ret) + ERR_print_errors(bio_err); + BIO_free_all(Sout); +@@ -1268,7 +1306,8 @@ static int certify(X509 **xret, const char *infile, EVP_PKEY *pkey, X509 *x509, + const char *enddate, + long days, int batch, const char *ext_sect, CONF *lconf, + int verbose, unsigned long certopt, unsigned long nameopt, +- int default_op, int ext_copy, int selfsign) ++ int default_op, int ext_copy, int selfsign, ++ unsigned char *sm2id, size_t sm2idlen) + { + X509_REQ *req = NULL; + BIO *in = NULL; +@@ -1300,6 +1339,25 @@ static int certify(X509 **xret, const char *infile, EVP_PKEY *pkey, X509 *x509, + BIO_printf(bio_err, "error unpacking public key\n"); + goto end; + } ++ if (sm2id != NULL) { ++#ifndef OPENSSL_NO_SM2 ++ ASN1_OCTET_STRING *v; ++ ++ v = ASN1_OCTET_STRING_new(); ++ if (v == NULL) { ++ BIO_printf(bio_err, "error: SM2 ID allocation failed\n"); ++ goto end; ++ } ++ ++ if (!ASN1_OCTET_STRING_set(v, sm2id, sm2idlen)) { ++ BIO_printf(bio_err, "error: setting SM2 ID failed\n"); ++ ASN1_OCTET_STRING_free(v); ++ goto end; ++ } ++ ++ X509_REQ_set0_sm2_id(req, v); ++#endif ++ } + i = X509_REQ_verify(req, pktmp); + pktmp = NULL; + if (i < 0) { +diff --git a/apps/req.c b/apps/req.c +index a603907..96f1edd 100644 +--- a/apps/req.c ++++ b/apps/req.c +@@ -90,7 +90,7 @@ typedef enum OPTION_choice { + OPT_VERIFY, OPT_NODES, OPT_NOOUT, OPT_VERBOSE, OPT_UTF8, + OPT_NAMEOPT, OPT_REQOPT, OPT_SUBJ, OPT_SUBJECT, OPT_TEXT, OPT_X509, + OPT_MULTIVALUE_RDN, OPT_DAYS, OPT_SET_SERIAL, OPT_ADDEXT, OPT_EXTENSIONS, +- OPT_REQEXTS, OPT_PRECERT, OPT_MD, ++ OPT_REQEXTS, OPT_PRECERT, OPT_MD, OPT_SM2ID, OPT_SM2HEXID, + OPT_R_ENUM + } OPTION_CHOICE; + +@@ -145,6 +145,12 @@ const OPTIONS req_options[] = { + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, + {"keygen_engine", OPT_KEYGEN_ENGINE, 's', + "Specify engine to be used for key generation operations"}, ++#endif ++#ifndef OPENSSL_NO_SM2 ++ {"sm2-id", OPT_SM2ID, 's', ++ "Specify an ID string to verify an SM2 certificate request"}, ++ {"sm2-hex-id", OPT_SM2HEXID, 's', ++ "Specify a hex ID string to verify an SM2 certificate request"}, + #endif + {NULL} + }; +@@ -242,6 +248,9 @@ int req_main(int argc, char **argv) + int nodes = 0, newhdr = 0, subject = 0, pubkey = 0, precert = 0; + long newkey = -1; + unsigned long chtype = MBSTRING_ASC, reqflag = 0; ++ unsigned char *sm2_id = NULL; ++ size_t sm2_idlen = 0; ++ int sm2_free = 0; + + #ifndef OPENSSL_NO_DES + cipher = EVP_des_ede3_cbc(); +@@ -417,6 +426,29 @@ int req_main(int argc, char **argv) + goto opthelp; + digest = md_alg; + break; ++ case OPT_SM2ID: ++ if (sm2_id != NULL) { ++ BIO_printf(bio_err, ++ "Use one of the options 'sm2-hex-id' or 'sm2-id'\n"); ++ goto end; ++ } ++ sm2_id = (unsigned char *)opt_arg(); ++ sm2_idlen = strlen((const char *)sm2_id); ++ break; ++ case OPT_SM2HEXID: ++ if (sm2_id != NULL) { ++ BIO_printf(bio_err, ++ "Use one of the options 'sm2-hex-id' or 'sm2-id'\n"); ++ goto end; ++ } ++ /* try to parse the input as hex string first */ ++ sm2_free = 1; ++ sm2_id = OPENSSL_hexstr2buf(opt_arg(), (long *)&sm2_idlen); ++ if (sm2_id == NULL) { ++ BIO_printf(bio_err, "Invalid hex string input\n"); ++ goto end; ++ } ++ break; + } + } + argc = opt_num_rest(); +@@ -849,6 +881,26 @@ int req_main(int argc, char **argv) + goto end; + } + ++ if (sm2_id != NULL) { ++#ifndef OPENSSL_NO_SM2 ++ ASN1_OCTET_STRING *v; ++ ++ v = ASN1_OCTET_STRING_new(); ++ if (v == NULL) { ++ BIO_printf(bio_err, "error: SM2 ID allocation failed\n"); ++ goto end; ++ } ++ ++ if (!ASN1_OCTET_STRING_set(v, sm2_id, sm2_idlen)) { ++ BIO_printf(bio_err, "error: setting SM2 ID failed\n"); ++ ASN1_OCTET_STRING_free(v); ++ goto end; ++ } ++ ++ X509_REQ_set0_sm2_id(req, v); ++#endif ++ } ++ + i = X509_REQ_verify(req, tpubkey); + + if (i < 0) { +@@ -957,6 +1009,8 @@ int req_main(int argc, char **argv) + } + ret = 0; + end: ++ if (sm2_free) ++ OPENSSL_free(sm2_id); + if (ret) { + ERR_print_errors(bio_err); + } +@@ -1611,14 +1665,58 @@ static int genpkey_cb(EVP_PKEY_CTX *ctx) + return 1; + } + ++#ifndef OPENSSL_NO_SM2 ++static int ec_pkey_is_sm2(EVP_PKEY *pkey) ++{ ++ EC_KEY *eckey = NULL; ++ const EC_GROUP *group = NULL; ++ ++ if (EVP_PKEY_id(pkey) == EVP_PKEY_SM2) ++ return 1; ++ if (EVP_PKEY_id(pkey) == EVP_PKEY_EC ++ && (eckey = EVP_PKEY_get0_EC_KEY(pkey)) != NULL ++ && (group = EC_KEY_get0_group(eckey)) != NULL ++ && EC_GROUP_get_curve_name(group) == NID_sm2) ++ return 1; ++ return 0; ++} ++#endif ++ + static int do_sign_init(EVP_MD_CTX *ctx, EVP_PKEY *pkey, + const EVP_MD *md, STACK_OF(OPENSSL_STRING) *sigopts) + { + EVP_PKEY_CTX *pkctx = NULL; +- int i, def_nid; ++#ifndef OPENSSL_NO_SM2 ++ EVP_PKEY_CTX *pctx = NULL; ++#endif ++ int i, def_nid, ret = 0; + + if (ctx == NULL) +- return 0; ++ goto err; ++#ifndef OPENSSL_NO_SM2 ++ if (ec_pkey_is_sm2(pkey)) { ++ /* initialize some SM2-specific code */ ++ if (!EVP_PKEY_set_alias_type(pkey, EVP_PKEY_SM2)) { ++ BIO_printf(bio_err, "Internal error.\n"); ++ goto err; ++ } ++ pctx = EVP_PKEY_CTX_new(pkey, NULL); ++ if (pctx == NULL) { ++ BIO_printf(bio_err, "memory allocation failure.\n"); ++ goto err; ++ } ++ /* set SM2 ID from sig options before calling the real init routine */ ++ for (i = 0; i < sk_OPENSSL_STRING_num(sigopts); i++) { ++ char *sigopt = sk_OPENSSL_STRING_value(sigopts, i); ++ if (pkey_ctrl_string(pctx, sigopt) <= 0) { ++ BIO_printf(bio_err, "parameter error \"%s\"\n", sigopt); ++ ERR_print_errors(bio_err); ++ goto err; ++ } ++ } ++ EVP_MD_CTX_set_pkey_ctx(ctx, pctx); ++ } ++#endif + /* + * EVP_PKEY_get_default_digest_nid() returns 2 if the digest is mandatory + * for this algorithm. +@@ -1629,16 +1727,23 @@ static int do_sign_init(EVP_MD_CTX *ctx, EVP_PKEY *pkey, + md = NULL; + } + if (!EVP_DigestSignInit(ctx, &pkctx, md, NULL, pkey)) +- return 0; ++ goto err; + for (i = 0; i < sk_OPENSSL_STRING_num(sigopts); i++) { + char *sigopt = sk_OPENSSL_STRING_value(sigopts, i); + if (pkey_ctrl_string(pkctx, sigopt) <= 0) { + BIO_printf(bio_err, "parameter error \"%s\"\n", sigopt); + ERR_print_errors(bio_err); +- return 0; ++ goto err; + } + } +- return 1; ++ ++ ret = 1; ++ err: ++#ifndef OPENSSL_NO_SM2 ++ if (!ret) ++ EVP_PKEY_CTX_free(pctx); ++#endif ++ return ret; + } + + int do_X509_sign(X509 *x, EVP_PKEY *pkey, const EVP_MD *md, +@@ -1646,10 +1751,20 @@ int do_X509_sign(X509 *x, EVP_PKEY *pkey, const EVP_MD *md, + { + int rv; + EVP_MD_CTX *mctx = EVP_MD_CTX_new(); ++#ifndef OPENSSL_NO_SM2 ++ EVP_PKEY_CTX *pctx = NULL; ++#endif + + rv = do_sign_init(mctx, pkey, md, sigopts); + if (rv > 0) + rv = X509_sign_ctx(x, mctx); ++#ifndef OPENSSL_NO_SM2 ++ /* only in SM2 case we need to free the pctx explicitly */ ++ if (ec_pkey_is_sm2(pkey)) { ++ pctx = EVP_MD_CTX_pkey_ctx(mctx); ++ EVP_PKEY_CTX_free(pctx); ++ } ++#endif + EVP_MD_CTX_free(mctx); + return rv > 0 ? 1 : 0; + } +@@ -1659,9 +1774,20 @@ int do_X509_REQ_sign(X509_REQ *x, EVP_PKEY *pkey, const EVP_MD *md, + { + int rv; + EVP_MD_CTX *mctx = EVP_MD_CTX_new(); ++#ifndef OPENSSL_NO_SM2 ++ EVP_PKEY_CTX *pctx = NULL; ++#endif ++ + rv = do_sign_init(mctx, pkey, md, sigopts); + if (rv > 0) + rv = X509_REQ_sign_ctx(x, mctx); ++#ifndef OPENSSL_NO_SM2 ++ /* only in SM2 case we need to free the pctx explicitly */ ++ if (ec_pkey_is_sm2(pkey)) { ++ pctx = EVP_MD_CTX_pkey_ctx(mctx); ++ EVP_PKEY_CTX_free(pctx); ++ } ++#endif + EVP_MD_CTX_free(mctx); + return rv > 0 ? 1 : 0; + } +@@ -1671,9 +1797,20 @@ int do_X509_CRL_sign(X509_CRL *x, EVP_PKEY *pkey, const EVP_MD *md, + { + int rv; + EVP_MD_CTX *mctx = EVP_MD_CTX_new(); ++#ifndef OPENSSL_NO_SM2 ++ EVP_PKEY_CTX *pctx = NULL; ++#endif ++ + rv = do_sign_init(mctx, pkey, md, sigopts); + if (rv > 0) + rv = X509_CRL_sign_ctx(x, mctx); ++#ifndef OPENSSL_NO_SM2 ++ /* only in SM2 case we need to free the pctx explicitly */ ++ if (ec_pkey_is_sm2(pkey)) { ++ pctx = EVP_MD_CTX_pkey_ctx(mctx); ++ EVP_PKEY_CTX_free(pctx); ++ } ++#endif + EVP_MD_CTX_free(mctx); + return rv > 0 ? 1 : 0; + } +diff --git a/crypto/asn1/a_sign.c b/crypto/asn1/a_sign.c +index 72381b6..c29080b 100644 +--- a/crypto/asn1/a_sign.c ++++ b/crypto/asn1/a_sign.c +@@ -145,7 +145,7 @@ int ASN1_item_sign_ctx(const ASN1_ITEM *it, + unsigned char *buf_in = NULL, *buf_out = NULL; + size_t inl = 0, outl = 0, outll = 0; + int signid, paramtype, buf_len = 0; +- int rv; ++ int rv, pkey_id; + + type = EVP_MD_CTX_md(ctx); + pkey = EVP_PKEY_CTX_get0_pkey(EVP_MD_CTX_pkey_ctx(ctx)); +@@ -184,9 +184,14 @@ int ASN1_item_sign_ctx(const ASN1_ITEM *it, + ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ASN1_R_CONTEXT_NOT_INITIALISED); + goto err; + } +- if (!OBJ_find_sigid_by_algs(&signid, +- EVP_MD_nid(type), +- pkey->ameth->pkey_id)) { ++ ++ pkey_id = ++#ifndef OPENSSL_NO_SM2 ++ EVP_PKEY_id(pkey) == NID_sm2 ? NID_sm2 : ++#endif ++ pkey->ameth->pkey_id; ++ ++ if (!OBJ_find_sigid_by_algs(&signid, EVP_MD_nid(type), pkey_id)) { + ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, + ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED); + goto err; +diff --git a/crypto/ec/ec_pmeth.c b/crypto/ec/ec_pmeth.c +index 77876a0..591f27a 100644 +--- a/crypto/ec/ec_pmeth.c ++++ b/crypto/ec/ec_pmeth.c +@@ -327,7 +327,8 @@ static int pkey_ec_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) + EVP_MD_type((const EVP_MD *)p2) != NID_sha3_224 && + EVP_MD_type((const EVP_MD *)p2) != NID_sha3_256 && + EVP_MD_type((const EVP_MD *)p2) != NID_sha3_384 && +- EVP_MD_type((const EVP_MD *)p2) != NID_sha3_512) { ++ EVP_MD_type((const EVP_MD *)p2) != NID_sha3_512 && ++ EVP_MD_type((const EVP_MD *)p2) != NID_sm3) { + ECerr(EC_F_PKEY_EC_CTRL, EC_R_INVALID_DIGEST_TYPE); + return 0; + } +diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt +index 5e71e65..b93cace 100644 +--- a/crypto/err/openssl.txt ++++ b/crypto/err/openssl.txt +@@ -1711,6 +1711,7 @@ X509_F_BUILD_CHAIN:106:build_chain + X509_F_BY_FILE_CTRL:101:by_file_ctrl + X509_F_CHECK_NAME_CONSTRAINTS:149:check_name_constraints + X509_F_CHECK_POLICY:145:check_policy ++X509_F_COMMON_VERIFY_SM2:165:common_verify_sm2 + X509_F_DANE_I2D:107:dane_i2d + X509_F_DIR_CTRL:102:dir_ctrl + X509_F_GET_CERT_BY_SUBJECT:103:get_cert_by_subject +@@ -1755,6 +1756,8 @@ X509_F_X509_REQ_CHECK_PRIVATE_KEY:144:X509_REQ_check_private_key + X509_F_X509_REQ_PRINT_EX:121:X509_REQ_print_ex + X509_F_X509_REQ_PRINT_FP:122:X509_REQ_print_fp + X509_F_X509_REQ_TO_X509:123:X509_REQ_to_X509 ++X509_F_X509_REQ_VERIFY:163:X509_REQ_verify ++X509_F_X509_REQ_VERIFY_SM2:164:x509_req_verify_sm2 + X509_F_X509_STORE_ADD_CERT:124:X509_STORE_add_cert + X509_F_X509_STORE_ADD_CRL:125:X509_STORE_add_crl + X509_F_X509_STORE_ADD_LOOKUP:157:X509_STORE_add_lookup +diff --git a/crypto/x509/x509_err.c b/crypto/x509/x509_err.c +index c91ad7c..f02793b 100644 +--- a/crypto/x509/x509_err.c ++++ b/crypto/x509/x509_err.c +@@ -20,6 +20,7 @@ static const ERR_STRING_DATA X509_str_functs[] = { + {ERR_PACK(ERR_LIB_X509, X509_F_CHECK_NAME_CONSTRAINTS, 0), + "check_name_constraints"}, + {ERR_PACK(ERR_LIB_X509, X509_F_CHECK_POLICY, 0), "check_policy"}, ++ {ERR_PACK(ERR_LIB_X509, X509_F_COMMON_VERIFY_SM2, 0), "common_verify_sm2"}, + {ERR_PACK(ERR_LIB_X509, X509_F_DANE_I2D, 0), "dane_i2d"}, + {ERR_PACK(ERR_LIB_X509, X509_F_DIR_CTRL, 0), "dir_ctrl"}, + {ERR_PACK(ERR_LIB_X509, X509_F_GET_CERT_BY_SUBJECT, 0), +@@ -87,6 +88,9 @@ static const ERR_STRING_DATA X509_str_functs[] = { + {ERR_PACK(ERR_LIB_X509, X509_F_X509_REQ_PRINT_EX, 0), "X509_REQ_print_ex"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_REQ_PRINT_FP, 0), "X509_REQ_print_fp"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_REQ_TO_X509, 0), "X509_REQ_to_X509"}, ++ {ERR_PACK(ERR_LIB_X509, X509_F_X509_REQ_VERIFY, 0), "X509_REQ_verify"}, ++ {ERR_PACK(ERR_LIB_X509, X509_F_X509_REQ_VERIFY_SM2, 0), ++ "x509_req_verify_sm2"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_STORE_ADD_CERT, 0), + "X509_STORE_add_cert"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_STORE_ADD_CRL, 0), +diff --git a/crypto/x509/x_all.c b/crypto/x509/x_all.c +index 9c8aea5..5c371f5 100644 +--- a/crypto/x509/x_all.c ++++ b/crypto/x509/x_all.c +@@ -24,86 +24,105 @@ + # include "crypto/asn1.h" + # include "crypto/evp.h" + +-static int x509_verify_sm2(X509 *x, EVP_PKEY *pkey, int mdnid, int pknid) ++static int common_verify_sm2(void *data, EVP_PKEY *pkey, ++ int mdnid, int pknid, int req) + { ++ X509 *x = NULL; ++ X509_REQ *r = NULL; + EVP_MD_CTX *ctx = NULL; + unsigned char *buf_in = NULL; + int ret = -1, inl = 0; + size_t inll = 0; + EVP_PKEY_CTX *pctx = NULL; + const EVP_MD *type = EVP_get_digestbynid(mdnid); ++ ASN1_BIT_STRING *signature = NULL; ++ ASN1_OCTET_STRING *sm2_id = NULL; ++ ASN1_VALUE *tbv = NULL; + + if (type == NULL) { +- X509err(X509_F_X509_VERIFY_SM2, ++ X509err(X509_F_COMMON_VERIFY_SM2, + ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM); + goto err; + } + + if (pkey == NULL) { +- X509err(X509_F_X509_VERIFY_SM2, ERR_R_PASSED_NULL_PARAMETER); ++ X509err(X509_F_COMMON_VERIFY_SM2, ERR_R_PASSED_NULL_PARAMETER); + return -1; + } + +- if (x->signature.type == V_ASN1_BIT_STRING && x->signature.flags & 0x7) { +- X509err(X509_F_X509_VERIFY_SM2, ASN1_R_INVALID_BIT_STRING_BITS_LEFT); ++ if (req == 1) { ++ r = (X509_REQ *)data; ++ signature = r->signature; ++ sm2_id = r->sm2_id; ++ tbv = (ASN1_VALUE *)&r->req_info; ++ } else { ++ x = (X509 *)data; ++ signature = &x->signature; ++ sm2_id = x->sm2_id; ++ tbv = (ASN1_VALUE *)&x->cert_info; ++ } ++ ++ if (signature->type == V_ASN1_BIT_STRING && signature->flags & 0x7) { ++ X509err(X509_F_COMMON_VERIFY_SM2, ASN1_R_INVALID_BIT_STRING_BITS_LEFT); + return -1; + } + + ctx = EVP_MD_CTX_new(); + if (ctx == NULL) { +- X509err(X509_F_X509_VERIFY_SM2, ERR_R_MALLOC_FAILURE); ++ X509err(X509_F_COMMON_VERIFY_SM2, ERR_R_MALLOC_FAILURE); + goto err; + } + + /* Check public key OID matches public key type */ + if (EVP_PKEY_type(pknid) != pkey->ameth->pkey_id) { +- X509err(X509_F_X509_VERIFY_SM2, ASN1_R_WRONG_PUBLIC_KEY_TYPE); ++ X509err(X509_F_COMMON_VERIFY_SM2, ASN1_R_WRONG_PUBLIC_KEY_TYPE); + goto err; + } + + if (!EVP_PKEY_set_alias_type(pkey, EVP_PKEY_SM2)) { +- X509err(X509_F_X509_VERIFY_SM2, ERR_R_EVP_LIB); ++ X509err(X509_F_COMMON_VERIFY_SM2, ERR_R_EVP_LIB); + ret = 0; + goto err; + } + pctx = EVP_PKEY_CTX_new(pkey, NULL); + if (pctx == NULL) { +- X509err(X509_F_X509_VERIFY_SM2, ERR_R_EVP_LIB); ++ X509err(X509_F_COMMON_VERIFY_SM2, ERR_R_EVP_LIB); + ret = 0; + goto err; + } + /* NOTE: we tolerate no actual ID, to provide maximum flexibility */ +- if (x->sm2_id != NULL +- && EVP_PKEY_CTX_set1_id(pctx, x->sm2_id->data, +- x->sm2_id->length) != 1) { +- X509err(X509_F_X509_VERIFY_SM2, ERR_R_EVP_LIB); ++ if (sm2_id != NULL ++ && EVP_PKEY_CTX_set1_id(pctx, sm2_id->data, sm2_id->length) != 1) { ++ X509err(X509_F_COMMON_VERIFY_SM2, ERR_R_EVP_LIB); + ret = 0; + goto err; + } + EVP_MD_CTX_set_pkey_ctx(ctx, pctx); + + if (!EVP_DigestVerifyInit(ctx, NULL, type, NULL, pkey)) { +- X509err(X509_F_X509_VERIFY_SM2, ERR_R_EVP_LIB); ++ X509err(X509_F_COMMON_VERIFY_SM2, ERR_R_EVP_LIB); + ret = 0; + goto err; + } + +- inl = ASN1_item_i2d((ASN1_VALUE *)&x->cert_info, &buf_in, ++ inl = ASN1_item_i2d(tbv, &buf_in, ++ req == 1 ? ++ ASN1_ITEM_rptr(X509_REQ_INFO) : + ASN1_ITEM_rptr(X509_CINF)); + if (inl <= 0) { +- X509err(X509_F_X509_VERIFY_SM2, ERR_R_INTERNAL_ERROR); ++ X509err(X509_F_COMMON_VERIFY_SM2, ERR_R_INTERNAL_ERROR); + goto err; + } + if (buf_in == NULL) { +- X509err(X509_F_X509_VERIFY_SM2, ERR_R_MALLOC_FAILURE); ++ X509err(X509_F_COMMON_VERIFY_SM2, ERR_R_MALLOC_FAILURE); + goto err; + } + inll = inl; + +- ret = EVP_DigestVerify(ctx, x->signature.data, +- (size_t)x->signature.length, buf_in, inl); ++ ret = EVP_DigestVerify(ctx, signature->data, ++ (size_t)signature->length, buf_in, inl); + if (ret <= 0) { +- X509err(X509_F_X509_VERIFY_SM2, ERR_R_EVP_LIB); ++ X509err(X509_F_COMMON_VERIFY_SM2, ERR_R_EVP_LIB); + goto err; + } + ret = 1; +@@ -113,6 +132,18 @@ static int x509_verify_sm2(X509 *x, EVP_PKEY *pkey, int mdnid, int pknid) + EVP_PKEY_CTX_free(pctx); + return ret; + } ++ ++static int x509_verify_sm2(X509 *x, EVP_PKEY *pkey, int mdnid, int pknid) ++{ ++ return common_verify_sm2(x, pkey, mdnid, pknid, 0); ++} ++ ++static int x509_req_verify_sm2(X509_REQ *x, EVP_PKEY *pkey, ++ int mdnid, int pknid) ++{ ++ return common_verify_sm2(x, pkey, mdnid, pknid, 1); ++} ++ + #endif + + int X509_verify(X509 *a, EVP_PKEY *r) +@@ -142,6 +173,20 @@ int X509_verify(X509 *a, EVP_PKEY *r) + + int X509_REQ_verify(X509_REQ *a, EVP_PKEY *r) + { ++#ifndef OPENSSL_NO_SM2 ++ int mdnid, pknid; ++ ++ /* Convert signature OID into digest and public key OIDs */ ++ if (!OBJ_find_sigid_algs(OBJ_obj2nid(a->sig_alg.algorithm), ++ &mdnid, &pknid)) { ++ X509err(X509_F_X509_REQ_VERIFY, ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM); ++ return 0; ++ } ++ ++ if (pknid == NID_sm2) ++ return x509_req_verify_sm2(a, r, mdnid, pknid); ++#endif ++ + return (ASN1_item_verify(ASN1_ITEM_rptr(X509_REQ_INFO), + &a->sig_alg, a->signature, &a->req_info, r)); + } +diff --git a/crypto/x509/x_req.c b/crypto/x509/x_req.c +index d2b02f6..de4ff2c 100644 +--- a/crypto/x509/x_req.c ++++ b/crypto/x509/x_req.c +@@ -45,6 +45,29 @@ static int rinf_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, + return 1; + } + ++static int req_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, ++ void *exarg) ++{ ++#ifndef OPENSSL_NO_SM2 ++ X509_REQ *ret = (X509_REQ *)*pval; ++ ++ switch (operation) { ++ case ASN1_OP_D2I_PRE: ++ ASN1_OCTET_STRING_free(ret->sm2_id); ++ /* fall thru */ ++ case ASN1_OP_NEW_POST: ++ ret->sm2_id = NULL; ++ break; ++ ++ case ASN1_OP_FREE_POST: ++ ASN1_OCTET_STRING_free(ret->sm2_id); ++ break; ++ } ++#endif ++ ++ return 1; ++} ++ + ASN1_SEQUENCE_enc(X509_REQ_INFO, enc, rinf_cb) = { + ASN1_SIMPLE(X509_REQ_INFO, version, ASN1_INTEGER), + ASN1_SIMPLE(X509_REQ_INFO, subject, X509_NAME), +@@ -57,7 +80,7 @@ ASN1_SEQUENCE_enc(X509_REQ_INFO, enc, rinf_cb) = { + + IMPLEMENT_ASN1_FUNCTIONS(X509_REQ_INFO) + +-ASN1_SEQUENCE_ref(X509_REQ, 0) = { ++ASN1_SEQUENCE_ref(X509_REQ, req_cb) = { + ASN1_EMBED(X509_REQ, req_info, X509_REQ_INFO), + ASN1_EMBED(X509_REQ, sig_alg, X509_ALGOR), + ASN1_SIMPLE(X509_REQ, signature, ASN1_BIT_STRING) +@@ -66,3 +89,16 @@ ASN1_SEQUENCE_ref(X509_REQ, 0) = { + IMPLEMENT_ASN1_FUNCTIONS(X509_REQ) + + IMPLEMENT_ASN1_DUP_FUNCTION(X509_REQ) ++ ++#ifndef OPENSSL_NO_SM2 ++void X509_REQ_set0_sm2_id(X509_REQ *x, ASN1_OCTET_STRING *sm2_id) ++{ ++ ASN1_OCTET_STRING_free(x->sm2_id); ++ x->sm2_id = sm2_id; ++} ++ ++ASN1_OCTET_STRING *X509_REQ_get0_sm2_id(X509_REQ *x) ++{ ++ return x->sm2_id; ++} ++#endif +diff --git a/crypto/x509/x_x509.c b/crypto/x509/x_x509.c +index fb03bb2..8c27265 100644 +--- a/crypto/x509/x_x509.c ++++ b/crypto/x509/x_x509.c +@@ -53,6 +53,9 @@ static int x509_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, + sk_IPAddressFamily_pop_free(ret->rfc3779_addr, IPAddressFamily_free); + ASIdentifiers_free(ret->rfc3779_asid); + #endif ++#ifndef OPENSSL_NO_SM2 ++ ASN1_OCTET_STRING_free(ret->sm2_id); ++#endif + + /* fall thru */ + +diff --git a/doc/man1/ca.pod b/doc/man1/ca.pod +index 4380d86..1a6c53e 100644 +--- a/doc/man1/ca.pod ++++ b/doc/man1/ca.pod +@@ -57,6 +57,8 @@ B B + [B<-multivalue-rdn>] + [B<-rand file...>] + [B<-writerand file>] ++[B<-sm2-id string>] ++[B<-sm2-hex-id hex-string>] + + =head1 DESCRIPTION + +@@ -303,6 +305,16 @@ all others. + Writes random data to the specified I upon exit. + This can be used with a subsequent B<-rand> flag. + ++=item B<-sm2-id> ++ ++Specify the ID string to use when verifying an SM2 certificate. The ID string is ++required by the SM2 signature algorithm for signing and verification. ++ ++=item B<-sm2-hex-id> ++ ++Specify a binary ID string to use when signing or verifying using an SM2 ++certificate. The argument for this option is string of hexadecimal digits. ++ + =back + + =head1 CRL OPTIONS +@@ -600,6 +612,10 @@ Sign a certificate request: + + openssl ca -in req.pem -out newcert.pem + ++Sign an SM2 certificate request: ++ ++ openssl ca -in sm2.csr -out sm2.crt -md sm3 -sigopt "sm2_id:1234567812345678" -sm2-id "1234567812345678" ++ + Sign a certificate request, using CA extensions: + + openssl ca -in req.pem -extensions v3_ca -out newcert.pem +diff --git a/doc/man1/req.pod b/doc/man1/req.pod +index 539b843..3b9fcc3 100644 +--- a/doc/man1/req.pod ++++ b/doc/man1/req.pod +@@ -50,6 +50,8 @@ B B + [B<-batch>] + [B<-verbose>] + [B<-engine id>] ++[B<-sm2-id string>] ++[B<-sm2-hex-id hex-string>] + + =head1 DESCRIPTION + +@@ -339,6 +341,16 @@ for all available algorithms. + Specifies an engine (by its unique B string) which would be used + for key generation operations. + ++=item B<-sm2-id> ++ ++Specify the ID string to use when verifying an SM2 certificate. The ID string is ++required by the SM2 signature algorithm for signing and verification. ++ ++=item B<-sm2-hex-id> ++ ++Specify a binary ID string to use when signing or verifying using an SM2 ++certificate. The argument for this option is string of hexadecimal digits. ++ + =back + + =head1 CONFIGURATION FILE FORMAT +@@ -534,6 +546,15 @@ Generate a self signed root certificate: + + openssl req -x509 -newkey rsa:2048 -keyout key.pem -out req.pem + ++Create an SM2 private key and then generate a certificate request from it: ++ ++ openssl ecparam -genkey -name SM2 -out sm2.key ++ openssl req -new -key sm2.key -out sm2.csr -sm3 -sigopt "sm2_id:1234567812345678" ++ ++Examine and verify an SM2 certificate request: ++ ++ openssl req -verify -in sm2.csr -sm3 -sm2-id 1234567812345678 ++ + Example of a file pointed to by the B option: + + 1.2.3.4 shortName A longer Name +diff --git a/doc/man3/X509_get0_sm2_id.pod b/doc/man3/X509_get0_sm2_id.pod +index 9698c86..d8a85d7 100644 +--- a/doc/man3/X509_get0_sm2_id.pod ++++ b/doc/man3/X509_get0_sm2_id.pod +@@ -2,7 +2,9 @@ + + =head1 NAME + +-X509_get0_sm2_id, X509_set0_sm2_id - get or set SM2 ID for certificate operations ++X509_get0_sm2_id, X509_set0_sm2_id, ++X509_REQ_get0_sm2_id, X509_REQ_set0_sm2_id ++- get or set SM2 ID for certificate operations + + =head1 SYNOPSIS + +@@ -10,6 +12,8 @@ X509_get0_sm2_id, X509_set0_sm2_id - get or set SM2 ID for certificate operation + + ASN1_OCTET_STRING *X509_get0_sm2_id(X509 *x); + void X509_set0_sm2_id(X509 *x, ASN1_OCTET_STRING *sm2_id); ++ ASN1_OCTET_STRING *X509_REQ_get0_sm2_id(X509_REQ *x); ++ void X509_REQ_set0_sm2_id(X509_REQ *x, ASN1_OCTET_STRING *sm2_id); + + =head1 DESCRIPTION + +@@ -21,6 +25,10 @@ this function transfers the memory management of the value to the X509 object, + and therefore the value that has been passed in should not be freed by the + caller after this function has been called. + ++X509_REQ_get0_sm2_id() and X509_REQ_set0_sm2_id() have the same functionality ++as X509_get0_sm2_id() and X509_set0_sm2_id() except that they deal with ++B objects instead of B. ++ + =head1 NOTES + + SM2 signature algorithm requires an ID value when generating and verifying a +@@ -29,7 +37,7 @@ ability to set and retrieve the SM2 ID value. + + =head1 RETURN VALUES + +-X509_set0_sm2_id() does not return a value. ++X509_set0_sm2_id() and X509_REQ_set0_sm2_id() do not return a value. + + =head1 SEE ALSO + +diff --git a/include/crypto/x509.h b/include/crypto/x509.h +index 5c314a8..a6e812a 100644 +--- a/include/crypto/x509.h ++++ b/include/crypto/x509.h +@@ -73,6 +73,9 @@ struct X509_req_st { + ASN1_BIT_STRING *signature; /* signature */ + CRYPTO_REF_COUNT references; + CRYPTO_RWLOCK *lock; ++# ifndef OPENSSL_NO_SM2 ++ ASN1_OCTET_STRING *sm2_id; ++# endif + }; + + struct X509_crl_info_st { +diff --git a/include/openssl/x509.h b/include/openssl/x509.h +index a02cf50..42e9eee 100644 +--- a/include/openssl/x509.h ++++ b/include/openssl/x509.h +@@ -576,6 +576,8 @@ int X509_get_signature_nid(const X509 *x); + # ifndef OPENSSL_NO_SM2 + void X509_set0_sm2_id(X509 *x, ASN1_OCTET_STRING *sm2_id); + ASN1_OCTET_STRING *X509_get0_sm2_id(X509 *x); ++void X509_REQ_set0_sm2_id(X509_REQ *x, ASN1_OCTET_STRING *sm2_id); ++ASN1_OCTET_STRING *X509_REQ_get0_sm2_id(X509_REQ *x); + # endif + + int X509_trusted(const X509 *x); +diff --git a/include/openssl/x509err.h b/include/openssl/x509err.h +index 06d75f0..0a84ef0 100644 +--- a/include/openssl/x509err.h ++++ b/include/openssl/x509err.h +@@ -26,6 +26,7 @@ int ERR_load_X509_strings(void); + # define X509_F_BY_FILE_CTRL 101 + # define X509_F_CHECK_NAME_CONSTRAINTS 149 + # define X509_F_CHECK_POLICY 145 ++# define X509_F_COMMON_VERIFY_SM2 165 + # define X509_F_DANE_I2D 107 + # define X509_F_DIR_CTRL 102 + # define X509_F_GET_CERT_BY_SUBJECT 103 +@@ -70,6 +71,8 @@ int ERR_load_X509_strings(void); + # define X509_F_X509_REQ_PRINT_EX 121 + # define X509_F_X509_REQ_PRINT_FP 122 + # define X509_F_X509_REQ_TO_X509 123 ++# define X509_F_X509_REQ_VERIFY 163 ++# define X509_F_X509_REQ_VERIFY_SM2 164 + # define X509_F_X509_STORE_ADD_CERT 124 + # define X509_F_X509_STORE_ADD_CRL 125 + # define X509_F_X509_STORE_ADD_LOOKUP 157 +diff --git a/test/certs/sm2-csr.pem b/test/certs/sm2-csr.pem +new file mode 100644 +index 0000000..a6dcca8 +--- /dev/null ++++ b/test/certs/sm2-csr.pem +@@ -0,0 +1,9 @@ ++-----BEGIN CERTIFICATE REQUEST----- ++MIIBMTCB1wIBADB1MQswCQYDVQQGEwJDTjERMA8GA1UECAwITGlhb25pbmcxETAP ++BgNVBAcMCFNoZW55YW5nMQwwCgYDVQQKDANUZXQxDDAKBgNVBAsMA1RldDELMAkG ++A1UEAwwCb28xFzAVBgkqhkiG9w0BCQEWCG9vQG9vLm9vMFkwEwYHKoZIzj0CAQYI ++KoEcz1UBgi0DQgAE1NjdOpldcjTkuZpdGDNyHAnhK9cB2RZ7jAmFzt7jgEs9OHSg ++rb3crjz+qGZfqyJ5AyZulQ7gdARzb1H55jvw5qAAMAoGCCqBHM9VAYN1A0kAMEYC ++IQCacUXA8kyTTDwEm89Yz9qjsbfd8/N32lnzKxuKCcXJwQIhAIpugCbfeWuPxUQO ++7AvQS3yxBp1yn0FbTT2XVSyYy6To ++-----END CERTIFICATE REQUEST----- +diff --git a/test/certs/sm2-root.crt b/test/certs/sm2-root.crt +new file mode 100644 +index 0000000..5677ac6 +--- /dev/null ++++ b/test/certs/sm2-root.crt +@@ -0,0 +1,14 @@ ++-----BEGIN CERTIFICATE----- ++MIICJDCCAcqgAwIBAgIJAOlkpDpSrmVbMAoGCCqBHM9VAYN1MGgxCzAJBgNVBAYT ++AkNOMQswCQYDVQQIDAJMTjERMA8GA1UEBwwIU2hlbnlhbmcxETAPBgNVBAoMCFRl ++c3QgT3JnMRAwDgYDVQQLDAdUZXN0IE9VMRQwEgYDVQQDDAtUZXN0IFNNMiBDQTAe ++Fw0xOTAyMTkwNzA1NDhaFw0yMzAzMzAwNzA1NDhaMGgxCzAJBgNVBAYTAkNOMQsw ++CQYDVQQIDAJMTjERMA8GA1UEBwwIU2hlbnlhbmcxETAPBgNVBAoMCFRlc3QgT3Jn ++MRAwDgYDVQQLDAdUZXN0IE9VMRQwEgYDVQQDDAtUZXN0IFNNMiBDQTBZMBMGByqG ++SM49AgEGCCqBHM9VAYItA0IABHRYnqErofBdXPptvvO7+BSVJxcpHuTGnZ+UPrbU ++5kVEUMaUnNOeMJZl/vRGimZCm/AkReJmRfnb15ESHR+ssp6jXTBbMB0GA1UdDgQW ++BBTFjcWu/zJgSZ5SKUlU5Vx4/0W5dDAfBgNVHSMEGDAWgBTFjcWu/zJgSZ5SKUlU ++5Vx4/0W5dDAMBgNVHRMEBTADAQH/MAsGA1UdDwQEAwIBBjAKBggqgRzPVQGDdQNI ++ADBFAiEAs6byi1nSQtFELOw/2tQIv5AEsZFR5MJ/oB2ztXzs2LYCIEfIw4xlUH6X ++YFhs4RnIa0K9Ng1ebsGPrifYkudwBIk3 ++-----END CERTIFICATE----- +diff --git a/test/certs/sm2-root.key b/test/certs/sm2-root.key +new file mode 100644 +index 0000000..4bda65b +--- /dev/null ++++ b/test/certs/sm2-root.key +@@ -0,0 +1,5 @@ ++-----BEGIN PRIVATE KEY----- ++MIGHAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBG0wawIBAQQglktdVbLA5tyXMc+9 ++KV4ikyDaFZNnXqfNAzUVqTlqn8GhRANCAAR0WJ6hK6HwXVz6bb7zu/gUlScXKR7k ++xp2flD621OZFRFDGlJzTnjCWZf70RopmQpvwJEXiZkX529eREh0frLKe ++-----END PRIVATE KEY----- +diff --git a/test/recipes/25-test_req.t b/test/recipes/25-test_req.t +index 383120c..8289959 100644 +--- a/test/recipes/25-test_req.t ++++ b/test/recipes/25-test_req.t +@@ -15,7 +15,7 @@ use OpenSSL::Test qw/:DEFAULT srctop_file/; + + setup("test_req"); + +-plan tests => 14; ++plan tests => 15; + + require_ok(srctop_file('test','recipes','tconversion.pl')); + +@@ -181,6 +181,25 @@ subtest "generating certificate requests" => sub { + "Verifying signature on request"); + }; + ++subtest "generating SM2 certificate requests" => sub { ++ plan tests => 2; ++ ++ SKIP: { ++ skip "SM2 is not supported by this OpenSSL build", 2 ++ if disabled("sm2"); ++ ok(run(app(["openssl", "req", "-config", srctop_file("test", "test.cnf"), ++ "-new", "-key", srctop_file("test", "certs", "sm2.key"), ++ "-sigopt", "sm2_id:1234567812345678", ++ "-out", "testreq.pem", "-sm3"])), ++ "Generating SM2 certificate request"); ++ ++ ok(run(app(["openssl", "req", "-config", srctop_file("test", "test.cnf"), ++ "-verify", "-in", "testreq.pem", "-noout", ++ "-sm2-id", "1234567812345678", "-sm3"])), ++ "Verifying signature on SM2 certificate request"); ++ } ++}; ++ + my @openssl_args = ("req", "-config", srctop_file("apps", "openssl.cnf")); + + run_conversion('req conversions', +diff --git a/test/recipes/70-test_verify_extra.t b/test/recipes/70-test_verify_extra.t +index 8c7c957..1571115 100644 +--- a/test/recipes/70-test_verify_extra.t ++++ b/test/recipes/70-test_verify_extra.t +@@ -17,4 +17,5 @@ ok(run(test(["verify_extra_test", + srctop_file("test", "certs", "roots.pem"), + srctop_file("test", "certs", "untrusted.pem"), + srctop_file("test", "certs", "bad.pem"), +- srctop_file("test", "certs", "rootCA.pem")]))); ++ srctop_file("test", "certs", "rootCA.pem"), ++ srctop_file("test", "certs", "sm2-csr.pem")]))); +diff --git a/test/recipes/80-test_ca.t b/test/recipes/80-test_ca.t +index 557777e..92557cf 100644 +--- a/test/recipes/80-test_ca.t ++++ b/test/recipes/80-test_ca.t +@@ -23,7 +23,7 @@ my $std_openssl_cnf = + + rmtree("demoCA", { safe => 0 }); + +-plan tests => 5; ++plan tests => 6; + SKIP: { + $ENV{OPENSSL_CONFIG} = '-config "'.srctop_file("test", "CAss.cnf").'"'; + skip "failed creating CA structure", 4 +@@ -51,9 +51,25 @@ plan tests => 5; + 'creating new pre-certificate'); + } + ++SKIP: { ++ skip "SM2 is not supported by this OpenSSL build", 1 ++ if disabled("sm2"); ++ ++ is(yes(cmdstr(app(["openssl", "ca", "-config", ++ srctop_file("test", "CAss.cnf"), ++ "-in", srctop_file("test", "certs", "sm2-csr.pem"), ++ "-out", "sm2-test.crt", ++ "-sigopt", "sm2_id:1234567812345678", ++ "-sm2-id", "1234567812345678", ++ "-md", "sm3", ++ "-cert", srctop_file("test", "certs", "sm2-root.crt"), ++ "-keyfile", srctop_file("test", "certs", "sm2-root.key")]))), ++ 0, ++ "Signing SM2 certificate request"); ++} + + rmtree("demoCA", { safe => 0 }); +-unlink "newcert.pem", "newreq.pem", "newkey.pem"; ++unlink "newcert.pem", "newreq.pem", "newkey.pem", "sm2-test.crt"; + + + sub yes { +diff --git a/test/verify_extra_test.c b/test/verify_extra_test.c +index 763ea4f..d69653c 100644 +--- a/test/verify_extra_test.c ++++ b/test/verify_extra_test.c +@@ -20,6 +20,7 @@ static const char *roots_f; + static const char *untrusted_f; + static const char *bad_f; + static const char *good_f; ++static const char *req_f; + + static X509 *load_cert_pem(const char *file) + { +@@ -272,6 +273,46 @@ static int test_sm2_id(void) + BIO_free(bio); + return ret; + } ++ ++static int test_req_sm2_id(void) ++{ ++ /* we only need an X509_REQ structure, no matter if it's a real SM2 cert */ ++ X509_REQ *x = NULL; ++ BIO *bio = NULL; ++ int ret = 0; ++ ASN1_OCTET_STRING *v = NULL, *v2 = NULL; ++ char *sm2id = "this is an ID"; ++ ++ bio = BIO_new_file(req_f, "r"); ++ if (bio == NULL) ++ goto err; ++ ++ x = PEM_read_bio_X509_REQ(bio, NULL, 0, NULL); ++ if (x == NULL) ++ goto err; ++ ++ v = ASN1_OCTET_STRING_new(); ++ if (v == NULL) ++ goto err; ++ ++ if (!ASN1_OCTET_STRING_set(v, (unsigned char *)sm2id, (int)strlen(sm2id))) { ++ ASN1_OCTET_STRING_free(v); ++ goto err; ++ } ++ ++ X509_REQ_set0_sm2_id(x, v); ++ ++ v2 = X509_REQ_get0_sm2_id(x); ++ if (!TEST_ptr(v2) ++ || !TEST_int_eq(ASN1_OCTET_STRING_cmp(v, v2), 0)) ++ goto err; ++ ++ ret = 1; ++ err: ++ X509_REQ_free(x); ++ BIO_free(bio); ++ return ret; ++} + #endif + + int setup_tests(void) +@@ -279,7 +320,8 @@ int setup_tests(void) + if (!TEST_ptr(roots_f = test_get_argument(0)) + || !TEST_ptr(untrusted_f = test_get_argument(1)) + || !TEST_ptr(bad_f = test_get_argument(2)) +- || !TEST_ptr(good_f = test_get_argument(3))) { ++ || !TEST_ptr(good_f = test_get_argument(3)) ++ || !TEST_ptr(req_f = test_get_argument(4))) { + TEST_error("usage: verify_extra_test roots.pem untrusted.pem bad.pem good.pem\n"); + return 0; + } +@@ -290,6 +332,7 @@ int setup_tests(void) + ADD_TEST(test_self_signed_bad); + #ifndef OPENSSL_NO_SM2 + ADD_TEST(test_sm2_id); ++ ADD_TEST(test_req_sm2_id); + #endif + return 1; + } +diff --git a/util/libcrypto.num b/util/libcrypto.num +index d7abe91..81a6388 100644 +--- a/util/libcrypto.num ++++ b/util/libcrypto.num +@@ -4628,3 +4628,5 @@ FIPS_drbg_get_blocklength 6381 1_1_0g EXIST::FUNCTION: + FIPS_drbg_init 6382 1_1_0g EXIST::FUNCTION: + X509_set0_sm2_id 6383 1_1_1m EXIST::FUNCTION:SM2 + X509_get0_sm2_id 6384 1_1_1m EXIST::FUNCTION:SM2 ++X509_REQ_get0_sm2_id 6385 1_1_1m EXIST::FUNCTION:SM2 ++X509_REQ_set0_sm2_id 6386 1_1_1m EXIST::FUNCTION:SM2 +-- +2.20.1 (Apple Git-117) + diff --git a/Backport-Support-SM2-certificate-verification.patch b/Backport-Support-SM2-certificate-verification.patch new file mode 100644 index 0000000..87c5ade --- /dev/null +++ b/Backport-Support-SM2-certificate-verification.patch @@ -0,0 +1,579 @@ +From 7d86ccd1282aeff8f6d564c5d37625ffcc048f2d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?=E6=9D=A8=E6=B4=8B?= +Date: Fri, 26 Oct 2018 21:34:08 +0800 +Subject: [PATCH 03/15] Support SM2 certificate verification + +Reviewed-by: Tim Hudson +(Merged from https://github.com/openssl/openssl/pull/8321) +--- + apps/verify.c | 45 +++++++++++++-- + crypto/asn1/a_verify.c | 3 +- + crypto/err/openssl.txt | 2 + + crypto/objects/obj_dat.h | 17 ++++-- + crypto/objects/obj_mac.num | 1 + + crypto/objects/obj_xref.h | 4 +- + crypto/objects/obj_xref.txt | 2 + + crypto/objects/objects.txt | 2 + + crypto/x509/x509_err.c | 2 + + crypto/x509/x_all.c | 110 ++++++++++++++++++++++++++++++++++++ + crypto/x509/x_x509.c | 12 ++++ + fuzz/oids.txt | 1 + + include/crypto/x509.h | 5 +- + include/openssl/obj_mac.h | 7 ++- + include/openssl/x509.h | 3 + + include/openssl/x509err.h | 2 + + util/libcrypto.num | 2 + + 17 files changed, 204 insertions(+), 16 deletions(-) + +diff --git a/apps/verify.c b/apps/verify.c +index 1f93856..09b31cf 100644 +--- a/apps/verify.c ++++ b/apps/verify.c +@@ -21,7 +21,8 @@ + static int cb(int ok, X509_STORE_CTX *ctx); + static int check(X509_STORE *ctx, const char *file, + STACK_OF(X509) *uchain, STACK_OF(X509) *tchain, +- STACK_OF(X509_CRL) *crls, int show_chain); ++ STACK_OF(X509_CRL) *crls, int show_chain, ++ unsigned char *sm2id, size_t sm2idlen); + static int v_verbose = 0, vflags = 0; + + typedef enum OPTION_choice { +@@ -29,7 +30,7 @@ typedef enum OPTION_choice { + OPT_ENGINE, OPT_CAPATH, OPT_CAFILE, OPT_NOCAPATH, OPT_NOCAFILE, + OPT_UNTRUSTED, OPT_TRUSTED, OPT_CRLFILE, OPT_CRL_DOWNLOAD, OPT_SHOW_CHAIN, + OPT_V_ENUM, OPT_NAMEOPT, +- OPT_VERBOSE ++ OPT_VERBOSE, OPT_SM2ID, OPT_SM2HEXID + } OPTION_CHOICE; + + const OPTIONS verify_options[] = { +@@ -56,6 +57,12 @@ const OPTIONS verify_options[] = { + OPT_V_OPTIONS, + #ifndef OPENSSL_NO_ENGINE + {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"}, ++#endif ++#ifndef OPENSSL_NO_SM2 ++ {"sm2-id", OPT_SM2ID, 's', ++ "Specify an ID string to verify an SM2 certificate"}, ++ {"sm2-hex-id", OPT_SM2HEXID, 's', ++ "Specify a hex ID string to verify an SM2 certificate"}, + #endif + {NULL} + }; +@@ -71,6 +78,8 @@ int verify_main(int argc, char **argv) + int noCApath = 0, noCAfile = 0; + int vpmtouched = 0, crl_download = 0, show_chain = 0, i = 0, ret = 1; + OPTION_CHOICE o; ++ unsigned char *sm2_id = NULL; ++ size_t sm2_idlen = 0; + + if ((vpm = X509_VERIFY_PARAM_new()) == NULL) + goto end; +@@ -158,6 +167,19 @@ int verify_main(int argc, char **argv) + case OPT_VERBOSE: + v_verbose = 1; + break; ++ case OPT_SM2ID: ++ /* we assume the input is not a hex string */ ++ sm2_id = (unsigned char *)opt_arg(); ++ sm2_idlen = strlen((const char *)sm2_id); ++ break; ++ case OPT_SM2HEXID: ++ /* try to parse the input as hex string first */ ++ sm2_id = OPENSSL_hexstr2buf(opt_arg(), (long *)&sm2_idlen); ++ if (sm2_id == NULL) { ++ BIO_printf(bio_err, "Invalid hex string input\n"); ++ goto end; ++ } ++ break; + } + } + argc = opt_num_rest(); +@@ -183,12 +205,13 @@ int verify_main(int argc, char **argv) + + ret = 0; + if (argc < 1) { +- if (check(store, NULL, untrusted, trusted, crls, show_chain) != 1) ++ if (check(store, NULL, untrusted, trusted, crls, show_chain, ++ sm2_id, sm2_idlen) != 1) + ret = -1; + } else { + for (i = 0; i < argc; i++) + if (check(store, argv[i], untrusted, trusted, crls, +- show_chain) != 1) ++ show_chain, sm2_id, sm2_idlen) != 1) + ret = -1; + } + +@@ -204,7 +227,8 @@ int verify_main(int argc, char **argv) + + static int check(X509_STORE *ctx, const char *file, + STACK_OF(X509) *uchain, STACK_OF(X509) *tchain, +- STACK_OF(X509_CRL) *crls, int show_chain) ++ STACK_OF(X509_CRL) *crls, int show_chain, ++ unsigned char *sm2id, size_t sm2idlen) + { + X509 *x = NULL; + int i = 0, ret = 0; +@@ -216,6 +240,17 @@ static int check(X509_STORE *ctx, const char *file, + if (x == NULL) + goto end; + ++ if (sm2id != NULL) { ++#ifndef OPENSSL_NO_SM2 ++ ASN1_OCTET_STRING v; ++ ++ v.data = sm2id; ++ v.length = sm2idlen; ++ ++ X509_set_sm2_id(x, &v); ++#endif ++ } ++ + csc = X509_STORE_CTX_new(); + if (csc == NULL) { + printf("error %s: X.509 store context allocation failed\n", +diff --git a/crypto/asn1/a_verify.c b/crypto/asn1/a_verify.c +index 4b5f542..f543aa1 100644 +--- a/crypto/asn1/a_verify.c ++++ b/crypto/asn1/a_verify.c +@@ -94,7 +94,7 @@ int ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *a, + int mdnid, pknid; + size_t inll = 0; + +- if (!pkey) { ++ if (pkey == NULL) { + ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ERR_R_PASSED_NULL_PARAMETER); + return -1; + } +@@ -150,7 +150,6 @@ int ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *a, + ret = 0; + goto err; + } +- + } + + inl = ASN1_item_i2d(asn, &buf_in, it); +diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt +index 902e97b..5e71e65 100644 +--- a/crypto/err/openssl.txt ++++ b/crypto/err/openssl.txt +@@ -1766,8 +1766,10 @@ X509_F_X509_STORE_NEW:158:X509_STORE_new + X509_F_X509_TO_X509_REQ:126:X509_to_X509_REQ + X509_F_X509_TRUST_ADD:133:X509_TRUST_add + X509_F_X509_TRUST_SET:141:X509_TRUST_set ++X509_F_X509_VERIFY:161:X509_verify + X509_F_X509_VERIFY_CERT:127:X509_verify_cert + X509_F_X509_VERIFY_PARAM_NEW:159:X509_VERIFY_PARAM_new ++X509_F_X509_VERIFY_SM2:162:x509_verify_sm2 + + #Reason codes + ASN1_R_ADDING_OBJECT:171:adding object +diff --git a/crypto/objects/obj_dat.h b/crypto/objects/obj_dat.h +index 24b49a2..eb4cce4 100644 +--- a/crypto/objects/obj_dat.h ++++ b/crypto/objects/obj_dat.h +@@ -2,7 +2,7 @@ + * WARNING: do not edit! + * Generated by crypto/objects/obj_dat.pl + * +- * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. ++ * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved. + * Licensed under the OpenSSL license (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 +@@ -10,7 +10,7 @@ + */ + + /* Serialized OID's */ +-static const unsigned char so[7762] = { ++static const unsigned char so[7770] = { + 0x2A,0x86,0x48,0x86,0xF7,0x0D, /* [ 0] OBJ_rsadsi */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01, /* [ 6] OBJ_pkcs */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x02, /* [ 13] OBJ_md2 */ +@@ -1076,9 +1076,10 @@ static const unsigned char so[7762] = { + 0x2A,0x85,0x03,0x07,0x01,0x02,0x01,0x01,0x04, /* [ 7736] OBJ_id_tc26_gost_3410_2012_256_paramSetD */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x0C, /* [ 7745] OBJ_hmacWithSHA512_224 */ + 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x0D, /* [ 7753] OBJ_hmacWithSHA512_256 */ ++ 0x2A,0x81,0x1C,0xCF,0x55,0x01,0x83,0x75, /* [ 7761] OBJ_SM2_with_SM3 */ + }; + +-#define NUM_NID 1195 ++#define NUM_NID 1196 + static const ASN1_OBJECT nid_objs[NUM_NID] = { + {"UNDEF", "undefined", NID_undef}, + {"rsadsi", "RSA Data Security, Inc.", NID_rsadsi, 6, &so[0]}, +@@ -2275,9 +2276,10 @@ static const ASN1_OBJECT nid_objs[NUM_NID] = { + {"magma-mac", "magma-mac", NID_magma_mac}, + {"hmacWithSHA512-224", "hmacWithSHA512-224", NID_hmacWithSHA512_224, 8, &so[7745]}, + {"hmacWithSHA512-256", "hmacWithSHA512-256", NID_hmacWithSHA512_256, 8, &so[7753]}, ++ {"SM2-SM3", "SM2-with-SM3", NID_SM2_with_SM3, 8, &so[7761]}, + }; + +-#define NUM_SN 1186 ++#define NUM_SN 1187 + static const unsigned int sn_objs[NUM_SN] = { + 364, /* "AD_DVCS" */ + 419, /* "AES-128-CBC" */ +@@ -2543,6 +2545,7 @@ static const unsigned int sn_objs[NUM_SN] = { + 1100, /* "SHAKE128" */ + 1101, /* "SHAKE256" */ + 1172, /* "SM2" */ ++ 1195, /* "SM2-SM3" */ + 1143, /* "SM3" */ + 1134, /* "SM4-CBC" */ + 1137, /* "SM4-CFB" */ +@@ -3467,7 +3470,7 @@ static const unsigned int sn_objs[NUM_SN] = { + 1093, /* "x509ExtAdmission" */ + }; + +-#define NUM_LN 1186 ++#define NUM_LN 1187 + static const unsigned int ln_objs[NUM_LN] = { + 363, /* "AD Time Stamping" */ + 405, /* "ANSI X9.62" */ +@@ -3623,6 +3626,7 @@ static const unsigned int ln_objs[NUM_LN] = { + 1119, /* "RSA-SHA3-512" */ + 188, /* "S/MIME" */ + 167, /* "S/MIME Capabilities" */ ++ 1195, /* "SM2-with-SM3" */ + 1006, /* "SNILS" */ + 387, /* "SNMPv2" */ + 1025, /* "SSH Client" */ +@@ -4657,7 +4661,7 @@ static const unsigned int ln_objs[NUM_LN] = { + 125, /* "zlib compression" */ + }; + +-#define NUM_OBJ 1071 ++#define NUM_OBJ 1072 + static const unsigned int obj_objs[NUM_OBJ] = { + 0, /* OBJ_undef 0 */ + 181, /* OBJ_iso 1 */ +@@ -5126,6 +5130,7 @@ static const unsigned int obj_objs[NUM_OBJ] = { + 1139, /* OBJ_sm4_ctr 1 2 156 10197 1 104 7 */ + 1172, /* OBJ_sm2 1 2 156 10197 1 301 */ + 1143, /* OBJ_sm3 1 2 156 10197 1 401 */ ++ 1195, /* OBJ_SM2_with_SM3 1 2 156 10197 1 501 */ + 1144, /* OBJ_sm3WithRSAEncryption 1 2 156 10197 1 504 */ + 776, /* OBJ_seed_ecb 1 2 410 200004 1 3 */ + 777, /* OBJ_seed_cbc 1 2 410 200004 1 4 */ +diff --git a/crypto/objects/obj_mac.num b/crypto/objects/obj_mac.num +index 1b6a9c6..8b797b0 100644 +--- a/crypto/objects/obj_mac.num ++++ b/crypto/objects/obj_mac.num +@@ -1192,3 +1192,4 @@ magma_cfb 1191 + magma_mac 1192 + hmacWithSHA512_224 1193 + hmacWithSHA512_256 1194 ++SM2_with_SM3 1195 +diff --git a/crypto/objects/obj_xref.h b/crypto/objects/obj_xref.h +index 5c3561a..1acfcde 100644 +--- a/crypto/objects/obj_xref.h ++++ b/crypto/objects/obj_xref.h +@@ -2,7 +2,7 @@ + * WARNING: do not edit! + * Generated by objxref.pl + * +- * Copyright 1998-2021 The OpenSSL Project Authors. All Rights Reserved. ++ * Copyright 1998-2022 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy +@@ -79,6 +79,7 @@ static const nid_triple sigoid_srt[] = { + {NID_RSA_SHA3_256, NID_sha3_256, NID_rsaEncryption}, + {NID_RSA_SHA3_384, NID_sha3_384, NID_rsaEncryption}, + {NID_RSA_SHA3_512, NID_sha3_512, NID_rsaEncryption}, ++ {NID_SM2_with_SM3, NID_sm3, NID_sm2}, + }; + + static const nid_triple *const sigoid_srt_xref[] = { +@@ -125,4 +126,5 @@ static const nid_triple *const sigoid_srt_xref[] = { + &sigoid_srt[45], + &sigoid_srt[46], + &sigoid_srt[47], ++ &sigoid_srt[48], + }; +diff --git a/crypto/objects/obj_xref.txt b/crypto/objects/obj_xref.txt +index ca3e744..f3dd8ed 100644 +--- a/crypto/objects/obj_xref.txt ++++ b/crypto/objects/obj_xref.txt +@@ -64,3 +64,5 @@ dhSinglePass_cofactorDH_sha224kdf_scheme sha224 dh_cofactor_kdf + dhSinglePass_cofactorDH_sha256kdf_scheme sha256 dh_cofactor_kdf + dhSinglePass_cofactorDH_sha384kdf_scheme sha384 dh_cofactor_kdf + dhSinglePass_cofactorDH_sha512kdf_scheme sha512 dh_cofactor_kdf ++ ++SM2_with_SM3 sm3 sm2 +diff --git a/crypto/objects/objects.txt b/crypto/objects/objects.txt +index c49d4c5..be9da47 100644 +--- a/crypto/objects/objects.txt ++++ b/crypto/objects/objects.txt +@@ -385,6 +385,8 @@ sm-scheme 301 : SM2 : sm2 + sm-scheme 401 : SM3 : sm3 + sm-scheme 504 : RSA-SM3 : sm3WithRSAEncryption + ++sm-scheme 501 : SM2-SM3 : SM2-with-SM3 ++ + # From RFC4231 + rsadsi 2 8 : : hmacWithSHA224 + rsadsi 2 9 : : hmacWithSHA256 +diff --git a/crypto/x509/x509_err.c b/crypto/x509/x509_err.c +index bdd1e67..c91ad7c 100644 +--- a/crypto/x509/x509_err.c ++++ b/crypto/x509/x509_err.c +@@ -105,9 +105,11 @@ static const ERR_STRING_DATA X509_str_functs[] = { + {ERR_PACK(ERR_LIB_X509, X509_F_X509_TO_X509_REQ, 0), "X509_to_X509_REQ"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_TRUST_ADD, 0), "X509_TRUST_add"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_TRUST_SET, 0), "X509_TRUST_set"}, ++ {ERR_PACK(ERR_LIB_X509, X509_F_X509_VERIFY, 0), "X509_verify"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_VERIFY_CERT, 0), "X509_verify_cert"}, + {ERR_PACK(ERR_LIB_X509, X509_F_X509_VERIFY_PARAM_NEW, 0), + "X509_VERIFY_PARAM_new"}, ++ {ERR_PACK(ERR_LIB_X509, X509_F_X509_VERIFY_SM2, 0), "x509_verify_sm2"}, + {0, NULL} + }; + +diff --git a/crypto/x509/x_all.c b/crypto/x509/x_all.c +index a4e9cda..60a2892 100644 +--- a/crypto/x509/x_all.c ++++ b/crypto/x509/x_all.c +@@ -19,10 +19,120 @@ + #include + #include + ++#ifndef OPENSSL_NO_SM2 ++ ++# include "crypto/asn1.h" ++# include "crypto/evp.h" ++ ++static int x509_verify_sm2(X509 *x, EVP_PKEY *pkey, int mdnid, int pknid) ++{ ++ EVP_MD_CTX *ctx = NULL; ++ unsigned char *buf_in = NULL; ++ int ret = -1, inl = 0; ++ size_t inll = 0; ++ EVP_PKEY_CTX *pctx = NULL; ++ const EVP_MD *type = EVP_get_digestbynid(mdnid); ++ ++ if (type == NULL) { ++ X509err(X509_F_X509_VERIFY_SM2, ++ ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM); ++ goto err; ++ } ++ ++ if (pkey == NULL) { ++ X509err(X509_F_X509_VERIFY_SM2, ERR_R_PASSED_NULL_PARAMETER); ++ return -1; ++ } ++ ++ if (x->signature.type == V_ASN1_BIT_STRING && x->signature.flags & 0x7) { ++ X509err(X509_F_X509_VERIFY_SM2, ASN1_R_INVALID_BIT_STRING_BITS_LEFT); ++ return -1; ++ } ++ ++ ctx = EVP_MD_CTX_new(); ++ if (ctx == NULL) { ++ X509err(X509_F_X509_VERIFY_SM2, ERR_R_MALLOC_FAILURE); ++ goto err; ++ } ++ ++ /* Check public key OID matches public key type */ ++ if (EVP_PKEY_type(pknid) != pkey->ameth->pkey_id) { ++ X509err(X509_F_X509_VERIFY_SM2, ASN1_R_WRONG_PUBLIC_KEY_TYPE); ++ goto err; ++ } ++ ++ if (!EVP_PKEY_set_alias_type(pkey, EVP_PKEY_SM2)) { ++ X509err(X509_F_X509_VERIFY_SM2, ERR_R_EVP_LIB); ++ ret = 0; ++ goto err; ++ } ++ pctx = EVP_PKEY_CTX_new(pkey, NULL); ++ if (pctx == NULL) { ++ X509err(X509_F_X509_VERIFY_SM2, ERR_R_EVP_LIB); ++ ret = 0; ++ goto err; ++ } ++ if (EVP_PKEY_CTX_set1_id(pctx, x->sm2_id.data, x->sm2_id.length) != 1) { ++ X509err(X509_F_X509_VERIFY_SM2, ERR_R_EVP_LIB); ++ ret = 0; ++ goto err; ++ } ++ EVP_MD_CTX_set_pkey_ctx(ctx, pctx); ++ ++ if (!EVP_DigestVerifyInit(ctx, NULL, type, NULL, pkey)) { ++ X509err(X509_F_X509_VERIFY_SM2, ERR_R_EVP_LIB); ++ ret = 0; ++ goto err; ++ } ++ ++ inl = ASN1_item_i2d((ASN1_VALUE *)&x->cert_info, &buf_in, ++ ASN1_ITEM_rptr(X509_CINF)); ++ if (inl <= 0) { ++ X509err(X509_F_X509_VERIFY_SM2, ERR_R_INTERNAL_ERROR); ++ goto err; ++ } ++ if (buf_in == NULL) { ++ X509err(X509_F_X509_VERIFY_SM2, ERR_R_MALLOC_FAILURE); ++ goto err; ++ } ++ inll = inl; ++ ++ ret = EVP_DigestVerify(ctx, x->signature.data, ++ (size_t)x->signature.length, buf_in, inl); ++ if (ret <= 0) { ++ X509err(X509_F_X509_VERIFY_SM2, ERR_R_EVP_LIB); ++ goto err; ++ } ++ ret = 1; ++ err: ++ OPENSSL_clear_free(buf_in, inll); ++ EVP_MD_CTX_free(ctx); ++ EVP_PKEY_CTX_free(pctx); ++ return ret; ++} ++#endif ++ + int X509_verify(X509 *a, EVP_PKEY *r) + { ++#ifndef OPENSSL_NO_SM2 ++ int mdnid, pknid; ++#endif ++ + if (X509_ALGOR_cmp(&a->sig_alg, &a->cert_info.signature)) + return 0; ++ ++#ifndef OPENSSL_NO_SM2 ++ /* Convert signature OID into digest and public key OIDs */ ++ if (!OBJ_find_sigid_algs(OBJ_obj2nid(a->sig_alg.algorithm), ++ &mdnid, &pknid)) { ++ X509err(X509_F_X509_VERIFY, ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM); ++ return 0; ++ } ++ ++ if (pknid == NID_sm2) ++ return x509_verify_sm2(a, r, mdnid, pknid); ++#endif ++ + return (ASN1_item_verify(ASN1_ITEM_rptr(X509_CINF), &a->sig_alg, + &a->signature, &a->cert_info, r)); + } +diff --git a/crypto/x509/x_x509.c b/crypto/x509/x_x509.c +index 7aa8b77..1beab78 100644 +--- a/crypto/x509/x_x509.c ++++ b/crypto/x509/x_x509.c +@@ -245,3 +245,15 @@ int X509_get_signature_nid(const X509 *x) + { + return OBJ_obj2nid(x->sig_alg.algorithm); + } ++ ++#ifndef OPENSSL_NO_SM2 ++void X509_set_sm2_id(X509 *x, ASN1_OCTET_STRING *sm2_id) ++{ ++ x->sm2_id = *sm2_id; ++} ++ ++ASN1_OCTET_STRING *X509_get0_sm2_id(X509 *x) ++{ ++ return &x->sm2_id; ++} ++#endif +diff --git a/fuzz/oids.txt b/fuzz/oids.txt +index eda55e4..8dfdea9 100644 +--- a/fuzz/oids.txt ++++ b/fuzz/oids.txt +@@ -1063,3 +1063,4 @@ OBJ_id_tc26_gost_3410_2012_256_paramSetC="\x2A\x85\x03\x07\x01\x02\x01\x01\x03" + OBJ_id_tc26_gost_3410_2012_256_paramSetD="\x2A\x85\x03\x07\x01\x02\x01\x01\x04" + OBJ_hmacWithSHA512_224="\x2A\x86\x48\x86\xF7\x0D\x02\x0C" + OBJ_hmacWithSHA512_256="\x2A\x86\x48\x86\xF7\x0D\x02\x0D" ++OBJ_SM2_with_SM3="\x2A\x81\x1C\xCF\x55\x01\x83\x75" +diff --git a/include/crypto/x509.h b/include/crypto/x509.h +index 243ea74..418c427 100644 +--- a/include/crypto/x509.h ++++ b/include/crypto/x509.h +@@ -177,7 +177,7 @@ struct x509_st { + STACK_OF(DIST_POINT) *crldp; + STACK_OF(GENERAL_NAME) *altname; + NAME_CONSTRAINTS *nc; +-#ifndef OPENSSL_NO_RFC3779 ++# ifndef OPENSSL_NO_RFC3779 + STACK_OF(IPAddressFamily) *rfc3779_addr; + struct ASIdentifiers_st *rfc3779_asid; + # endif +@@ -185,6 +185,9 @@ struct x509_st { + X509_CERT_AUX *aux; + CRYPTO_RWLOCK *lock; + volatile int ex_cached; ++# ifndef OPENSSL_NO_SM2 ++ ASN1_OCTET_STRING sm2_id; ++# endif + } /* X509 */ ; + + /* +diff --git a/include/openssl/obj_mac.h b/include/openssl/obj_mac.h +index eb812ed..9b125c1 100644 +--- a/include/openssl/obj_mac.h ++++ b/include/openssl/obj_mac.h +@@ -2,7 +2,7 @@ + * WARNING: do not edit! + * Generated by crypto/objects/objects.pl + * +- * Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved. ++ * Copyright 2000-2022 The OpenSSL Project Authors. All Rights Reserved. + * Licensed under the OpenSSL license (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 +@@ -1179,6 +1179,11 @@ + #define NID_sm3WithRSAEncryption 1144 + #define OBJ_sm3WithRSAEncryption OBJ_sm_scheme,504L + ++#define SN_SM2_with_SM3 "SM2-SM3" ++#define LN_SM2_with_SM3 "SM2-with-SM3" ++#define NID_SM2_with_SM3 1195 ++#define OBJ_SM2_with_SM3 OBJ_sm_scheme,501L ++ + #define LN_hmacWithSHA224 "hmacWithSHA224" + #define NID_hmacWithSHA224 798 + #define OBJ_hmacWithSHA224 OBJ_rsadsi,2L,8L +diff --git a/include/openssl/x509.h b/include/openssl/x509.h +index 3ff86ec..5f17057 100644 +--- a/include/openssl/x509.h ++++ b/include/openssl/x509.h +@@ -573,6 +573,9 @@ void X509_get0_signature(const ASN1_BIT_STRING **psig, + const X509_ALGOR **palg, const X509 *x); + int X509_get_signature_nid(const X509 *x); + ++void X509_set_sm2_id(X509 *x, ASN1_OCTET_STRING *sm2_id); ++ASN1_OCTET_STRING *X509_get0_sm2_id(X509 *x); ++ + int X509_trusted(const X509 *x); + int X509_alias_set1(X509 *x, const unsigned char *name, int len); + int X509_keyid_set1(X509 *x, const unsigned char *id, int len); +diff --git a/include/openssl/x509err.h b/include/openssl/x509err.h +index cd08673..06d75f0 100644 +--- a/include/openssl/x509err.h ++++ b/include/openssl/x509err.h +@@ -81,8 +81,10 @@ int ERR_load_X509_strings(void); + # define X509_F_X509_TO_X509_REQ 126 + # define X509_F_X509_TRUST_ADD 133 + # define X509_F_X509_TRUST_SET 141 ++# define X509_F_X509_VERIFY 161 + # define X509_F_X509_VERIFY_CERT 127 + # define X509_F_X509_VERIFY_PARAM_NEW 159 ++# define X509_F_X509_VERIFY_SM2 162 + + /* + * X509 reason codes. +diff --git a/util/libcrypto.num b/util/libcrypto.num +index 1566231..8635ac4 100644 +--- a/util/libcrypto.num ++++ b/util/libcrypto.num +@@ -4626,3 +4626,5 @@ FIPS_drbg_get_strength 6379 1_1_0g EXIST::FUNCTION: + FIPS_rand_strength 6380 1_1_0g EXIST::FUNCTION: + FIPS_drbg_get_blocklength 6381 1_1_0g EXIST::FUNCTION: + FIPS_drbg_init 6382 1_1_0g EXIST::FUNCTION: ++X509_set_sm2_id 6383 1_1_1m EXIST::FUNCTION: ++X509_get0_sm2_id 6384 1_1_1m EXIST::FUNCTION: +-- +2.20.1 (Apple Git-117) + diff --git a/Backport-Support-parsing-of-SM2-ID-in-hexdecimal.patch b/Backport-Support-parsing-of-SM2-ID-in-hexdecimal.patch new file mode 100644 index 0000000..1e0f591 --- /dev/null +++ b/Backport-Support-parsing-of-SM2-ID-in-hexdecimal.patch @@ -0,0 +1,127 @@ +From 1d9e832e41858b13a96899d842afd183f1c66c48 Mon Sep 17 00:00:00 2001 +From: Paul Yang +Date: Tue, 30 Jul 2019 23:05:44 +0800 +Subject: [PATCH 11/15] Support parsing of SM2 ID in hexdecimal + +The current EVP_PEKY_ctrl for SM2 has no capability of parsing an ID +input in hexdecimal. + +The newly added ctrl string is called: sm2_hex_id + +Test cases and documentation are updated. + +Reviewed-by: Tim Hudson +Reviewed-by: Richard Levitte +(Merged from https://github.com/openssl/openssl/pull/9584) +--- + crypto/sm2/sm2_pmeth.c | 19 +++++++++++++++++++ + doc/man1/pkeyutl.pod | 7 +++++++ + include/openssl/ec.h | 1 - + test/recipes/25-test_req.t | 15 +++++++++++++-- + 4 files changed, 39 insertions(+), 3 deletions(-) + +diff --git a/crypto/sm2/sm2_pmeth.c b/crypto/sm2/sm2_pmeth.c +index 837bdc1..9551d70 100644 +--- a/crypto/sm2/sm2_pmeth.c ++++ b/crypto/sm2/sm2_pmeth.c +@@ -232,6 +232,10 @@ static int pkey_sm2_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) + static int pkey_sm2_ctrl_str(EVP_PKEY_CTX *ctx, + const char *type, const char *value) + { ++ uint8_t *hex_id; ++ long hex_len = 0; ++ int ret = 0; ++ + if (strcmp(type, "ec_paramgen_curve") == 0) { + int nid = NID_undef; + +@@ -255,6 +259,21 @@ static int pkey_sm2_ctrl_str(EVP_PKEY_CTX *ctx, + } else if (strcmp(type, "sm2_id") == 0) { + return pkey_sm2_ctrl(ctx, EVP_PKEY_CTRL_SET1_ID, + (int)strlen(value), (void *)value); ++ } else if (strcmp(type, "sm2_hex_id") == 0) { ++ /* ++ * TODO(3.0): reconsider the name "sm2_hex_id", OR change ++ * OSSL_PARAM_construct_from_text() / OSSL_PARAM_allocate_from_text() ++ * to handle infix "_hex_" ++ */ ++ hex_id = OPENSSL_hexstr2buf((const char *)value, &hex_len); ++ if (hex_id == NULL) { ++ SM2err(SM2_F_PKEY_SM2_CTRL_STR, ERR_R_PASSED_INVALID_ARGUMENT); ++ return 0; ++ } ++ ret = pkey_sm2_ctrl(ctx, EVP_PKEY_CTRL_SET1_ID, (int)hex_len, ++ (void *)hex_id); ++ OPENSSL_free(hex_id); ++ return ret; + } + + return -2; +diff --git a/doc/man1/pkeyutl.pod b/doc/man1/pkeyutl.pod +index f0f80af..1a742ab 100644 +--- a/doc/man1/pkeyutl.pod ++++ b/doc/man1/pkeyutl.pod +@@ -329,6 +329,13 @@ This sets the ID string used in SM2 sign or verify operations. While verifying + an SM2 signature, the ID string must be the same one used when signing the data. + Otherwise the verification will fail. + ++=item B ++ ++This sets the ID string used in SM2 sign or verify operations. While verifying ++an SM2 signature, the ID string must be the same one used when signing the data. ++Otherwise the verification will fail. The ID string provided with this option ++should be a valid hexadecimal value. ++ + =back + + =head1 EXAMPLES +diff --git a/include/openssl/ec.h b/include/openssl/ec.h +index 24baf53..e8c8869 100644 +--- a/include/openssl/ec.h ++++ b/include/openssl/ec.h +@@ -1444,7 +1444,6 @@ void EC_KEY_METHOD_get_verify(const EC_KEY_METHOD *meth, + # define EVP_PKEY_CTX_set1_id(ctx, id, id_len) \ + EVP_PKEY_CTX_ctrl(ctx, -1, -1, \ + EVP_PKEY_CTRL_SET1_ID, (int)id_len, (void*)(id)) +- + # define EVP_PKEY_CTX_get1_id(ctx, id) \ + EVP_PKEY_CTX_ctrl(ctx, -1, -1, \ + EVP_PKEY_CTRL_GET1_ID, 0, (void*)(id)) +diff --git a/test/recipes/25-test_req.t b/test/recipes/25-test_req.t +index 8289959..d53e577 100644 +--- a/test/recipes/25-test_req.t ++++ b/test/recipes/25-test_req.t +@@ -182,10 +182,10 @@ subtest "generating certificate requests" => sub { + }; + + subtest "generating SM2 certificate requests" => sub { +- plan tests => 2; ++ plan tests => 4; + + SKIP: { +- skip "SM2 is not supported by this OpenSSL build", 2 ++ skip "SM2 is not supported by this OpenSSL build", 4 + if disabled("sm2"); + ok(run(app(["openssl", "req", "-config", srctop_file("test", "test.cnf"), + "-new", "-key", srctop_file("test", "certs", "sm2.key"), +@@ -197,6 +197,17 @@ subtest "generating SM2 certificate requests" => sub { + "-verify", "-in", "testreq.pem", "-noout", + "-sm2-id", "1234567812345678", "-sm3"])), + "Verifying signature on SM2 certificate request"); ++ ++ ok(run(app(["openssl", "req", "-config", srctop_file("test", "test.cnf"), ++ "-new", "-key", srctop_file("test", "certs", "sm2.key"), ++ "-sigopt", "sm2_hex_id:DEADBEEF", ++ "-out", "testreq.pem", "-sm3"])), ++ "Generating SM2 certificate request with hex id"); ++ ++ ok(run(app(["openssl", "req", "-config", srctop_file("test", "test.cnf"), ++ "-verify", "-in", "testreq.pem", "-noout", ++ "-sm2-hex-id", "DEADBEEF", "-sm3"])), ++ "Verifying signature on SM2 certificate request"); + } + }; + +-- +2.20.1 (Apple Git-117) + diff --git a/Backport-Support-raw-input-data-in-apps-pkeyutl.patch b/Backport-Support-raw-input-data-in-apps-pkeyutl.patch new file mode 100644 index 0000000..cd973db --- /dev/null +++ b/Backport-Support-raw-input-data-in-apps-pkeyutl.patch @@ -0,0 +1,482 @@ +From b14bf717ccb166cce13173a817106effb02f6c2e Mon Sep 17 00:00:00 2001 +From: Paul Yang +Date: Wed, 16 Jan 2019 16:16:28 +0800 +Subject: [PATCH 01/15] Support raw input data in apps/pkeyutl + +Some signature algorithms require special treatment for digesting, such +as SM2. This patch adds the ability of handling raw input data in +apps/pkeyutl other than accepting only pre-hashed input data. + +Beside, SM2 requries an ID string when signing or verifying a piece of data, +this patch also adds the ability for apps/pkeyutil to specify that ID +string. + +Reviewed-by: Matt Caswell +(Merged from https://github.com/openssl/openssl/pull/8186) +--- + apps/pkeyutl.c | 168 +++++++++++++++++++++++++++++---- + crypto/sm2/sm2_pmeth.c | 3 + + doc/man1/pkeyutl.pod | 45 +++++++++ + test/certs/sm2.crt | 13 +++ + test/certs/sm2.key | 5 + + test/recipes/20-test_pkeyutl.t | 43 +++++++++ + 6 files changed, 260 insertions(+), 17 deletions(-) + create mode 100644 test/certs/sm2.crt + create mode 100644 test/certs/sm2.key + create mode 100644 test/recipes/20-test_pkeyutl.t + +diff --git a/apps/pkeyutl.c b/apps/pkeyutl.c +index 831e14d..bca0464 100644 +--- a/apps/pkeyutl.c ++++ b/apps/pkeyutl.c +@@ -22,7 +22,7 @@ + static EVP_PKEY_CTX *init_ctx(const char *kdfalg, int *pkeysize, + const char *keyfile, int keyform, int key_type, + char *passinarg, int pkey_op, ENGINE *e, +- const int impl); ++ const int impl, EVP_PKEY **ppkey); + + static int setup_peer(EVP_PKEY_CTX *ctx, int peerform, const char *file, + ENGINE *e); +@@ -31,6 +31,11 @@ static int do_keyop(EVP_PKEY_CTX *ctx, int pkey_op, + unsigned char *out, size_t *poutlen, + const unsigned char *in, size_t inlen); + ++static int do_raw_keyop(int pkey_op, EVP_PKEY_CTX *ctx, ++ const EVP_MD *md, EVP_PKEY *pkey, BIO *in, ++ unsigned char *sig, int siglen, ++ unsigned char **out, size_t *poutlen); ++ + typedef enum OPTION_choice { + OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_ENGINE, OPT_ENGINE_IMPL, OPT_IN, OPT_OUT, +@@ -38,12 +43,15 @@ typedef enum OPTION_choice { + OPT_VERIFY, OPT_VERIFYRECOVER, OPT_REV, OPT_ENCRYPT, OPT_DECRYPT, + OPT_DERIVE, OPT_SIGFILE, OPT_INKEY, OPT_PEERKEY, OPT_PASSIN, + OPT_PEERFORM, OPT_KEYFORM, OPT_PKEYOPT, OPT_KDF, OPT_KDFLEN, +- OPT_R_ENUM ++ OPT_R_ENUM, OPT_RAWIN, OPT_DIGEST + } OPTION_CHOICE; + + const OPTIONS pkeyutl_options[] = { + {"help", OPT_HELP, '-', "Display this summary"}, + {"in", OPT_IN, '<', "Input file - default stdin"}, ++ {"rawin", OPT_RAWIN, '-', "Indicate the input data is in raw form"}, ++ {"digest", OPT_DIGEST, 's', ++ "Specify the digest algorithm when signing the raw input data"}, + {"out", OPT_OUT, '>', "Output file - default stdout"}, + {"pubin", OPT_PUBIN, '-', "Input is a public key"}, + {"certin", OPT_CERTIN, '-', "Input is a cert with a public key"}, +@@ -80,6 +88,7 @@ int pkeyutl_main(int argc, char **argv) + BIO *in = NULL, *out = NULL; + ENGINE *e = NULL; + EVP_PKEY_CTX *ctx = NULL; ++ EVP_PKEY *pkey = NULL; + char *infile = NULL, *outfile = NULL, *sigfile = NULL, *passinarg = NULL; + char hexdump = 0, asn1parse = 0, rev = 0, *prog; + unsigned char *buf_in = NULL, *buf_out = NULL, *sig = NULL; +@@ -94,6 +103,8 @@ int pkeyutl_main(int argc, char **argv) + const char *kdfalg = NULL; + int kdflen = 0; + STACK_OF(OPENSSL_STRING) *pkeyopts = NULL; ++ int rawin = 0; ++ const EVP_MD *md = NULL; + + prog = opt_init(argc, argv, pkeyutl_options); + while ((o = opt_next()) != OPT_EOF) { +@@ -192,12 +203,39 @@ int pkeyutl_main(int argc, char **argv) + goto end; + } + break; ++ case OPT_RAWIN: ++ rawin = 1; ++ break; ++ case OPT_DIGEST: ++ if (!opt_md(opt_arg(), &md)) ++ goto end; ++ break; + } + } + argc = opt_num_rest(); + if (argc != 0) + goto opthelp; + ++ if (rawin && pkey_op != EVP_PKEY_OP_SIGN && pkey_op != EVP_PKEY_OP_VERIFY) { ++ BIO_printf(bio_err, ++ "%s: -rawin can only be used with -sign or -verify\n", ++ prog); ++ goto opthelp; ++ } ++ ++ if (md != NULL && !rawin) { ++ BIO_printf(bio_err, ++ "%s: -digest can only be used with -rawin\n", ++ prog); ++ goto opthelp; ++ } ++ ++ if (rawin && rev) { ++ BIO_printf(bio_err, "%s: -rev cannot be used with raw input\n", ++ prog); ++ goto opthelp; ++ } ++ + if (kdfalg != NULL) { + if (kdflen == 0) { + BIO_printf(bio_err, +@@ -214,7 +252,7 @@ int pkeyutl_main(int argc, char **argv) + goto opthelp; + } + ctx = init_ctx(kdfalg, &keysize, inkey, keyform, key_type, +- passinarg, pkey_op, e, engine_impl); ++ passinarg, pkey_op, e, engine_impl, &pkey); + if (ctx == NULL) { + BIO_printf(bio_err, "%s: Error initializing context\n", prog); + ERR_print_errors(bio_err); +@@ -277,7 +315,8 @@ int pkeyutl_main(int argc, char **argv) + } + } + +- if (in != NULL) { ++ /* Raw input data is handled elsewhere */ ++ if (in != NULL && !rawin) { + /* Read the input data */ + buf_inlen = bio_to_mem(&buf_in, keysize * 10, in); + if (buf_inlen < 0) { +@@ -296,8 +335,9 @@ int pkeyutl_main(int argc, char **argv) + } + } + +- /* Sanity check the input */ +- if (buf_inlen > EVP_MAX_MD_SIZE ++ /* Sanity check the input if the input is not raw */ ++ if (!rawin ++ && buf_inlen > EVP_MAX_MD_SIZE + && (pkey_op == EVP_PKEY_OP_SIGN + || pkey_op == EVP_PKEY_OP_VERIFY)) { + BIO_printf(bio_err, +@@ -306,8 +346,13 @@ int pkeyutl_main(int argc, char **argv) + } + + if (pkey_op == EVP_PKEY_OP_VERIFY) { +- rv = EVP_PKEY_verify(ctx, sig, (size_t)siglen, +- buf_in, (size_t)buf_inlen); ++ if (rawin) { ++ rv = do_raw_keyop(pkey_op, ctx, md, pkey, in, sig, siglen, ++ NULL, 0); ++ } else { ++ rv = EVP_PKEY_verify(ctx, sig, (size_t)siglen, ++ buf_in, (size_t)buf_inlen); ++ } + if (rv == 1) { + BIO_puts(out, "Signature Verified Successfully\n"); + ret = 0; +@@ -320,14 +365,20 @@ int pkeyutl_main(int argc, char **argv) + buf_outlen = kdflen; + rv = 1; + } else { +- rv = do_keyop(ctx, pkey_op, NULL, (size_t *)&buf_outlen, +- buf_in, (size_t)buf_inlen); +- } +- if (rv > 0 && buf_outlen != 0) { +- buf_out = app_malloc(buf_outlen, "buffer output"); +- rv = do_keyop(ctx, pkey_op, +- buf_out, (size_t *)&buf_outlen, +- buf_in, (size_t)buf_inlen); ++ if (rawin) { ++ /* rawin allocates the buffer in do_raw_keyop() */ ++ rv = do_raw_keyop(pkey_op, ctx, md, pkey, in, NULL, 0, ++ &buf_out, (size_t *)&buf_outlen); ++ } else { ++ rv = do_keyop(ctx, pkey_op, NULL, (size_t *)&buf_outlen, ++ buf_in, (size_t)buf_inlen); ++ if (rv > 0 && buf_outlen != 0) { ++ buf_out = app_malloc(buf_outlen, "buffer output"); ++ rv = do_keyop(ctx, pkey_op, ++ buf_out, (size_t *)&buf_outlen, ++ buf_in, (size_t)buf_inlen); ++ } ++ } + } + if (rv <= 0) { + if (pkey_op != EVP_PKEY_OP_DERIVE) { +@@ -364,7 +415,7 @@ int pkeyutl_main(int argc, char **argv) + static EVP_PKEY_CTX *init_ctx(const char *kdfalg, int *pkeysize, + const char *keyfile, int keyform, int key_type, + char *passinarg, int pkey_op, ENGINE *e, +- const int engine_impl) ++ const int engine_impl, EVP_PKEY **ppkey) + { + EVP_PKEY *pkey = NULL; + EVP_PKEY_CTX *ctx = NULL; +@@ -422,10 +473,25 @@ static EVP_PKEY_CTX *init_ctx(const char *kdfalg, int *pkeysize, + } + ctx = EVP_PKEY_CTX_new_id(kdfnid, impl); + } else { ++ EC_KEY *eckey = NULL; ++ const EC_GROUP *group = NULL; ++ int nid; ++ + if (pkey == NULL) + goto end; ++ /* SM2 needs a special treatment */ ++ if (EVP_PKEY_id(pkey) == EVP_PKEY_EC) { ++ if ((eckey = EVP_PKEY_get0_EC_KEY(pkey)) == NULL ++ || (group = EC_KEY_get0_group(eckey)) == NULL ++ || (nid = EC_GROUP_get_curve_name(group)) == 0) ++ goto end; ++ if (nid == NID_sm2) ++ EVP_PKEY_set_alias_type(pkey, EVP_PKEY_SM2); ++ } + *pkeysize = EVP_PKEY_size(pkey); + ctx = EVP_PKEY_CTX_new(pkey, impl); ++ if (ppkey != NULL) ++ *ppkey = pkey; + EVP_PKEY_free(pkey); + } + +@@ -522,3 +588,71 @@ static int do_keyop(EVP_PKEY_CTX *ctx, int pkey_op, + } + return rv; + } ++ ++#define TBUF_MAXSIZE 2048 ++ ++static int do_raw_keyop(int pkey_op, EVP_PKEY_CTX *ctx, ++ const EVP_MD *md, EVP_PKEY *pkey, BIO *in, ++ unsigned char *sig, int siglen, ++ unsigned char **out, size_t *poutlen) ++{ ++ int rv = 0; ++ EVP_MD_CTX *mctx = NULL; ++ unsigned char tbuf[TBUF_MAXSIZE]; ++ int tbuf_len = 0; ++ ++ if ((mctx = EVP_MD_CTX_new()) == NULL) { ++ BIO_printf(bio_err, "Error: out of memory\n"); ++ return rv; ++ } ++ EVP_MD_CTX_set_pkey_ctx(mctx, ctx); ++ ++ switch(pkey_op) { ++ case EVP_PKEY_OP_VERIFY: ++ if (EVP_DigestVerifyInit(mctx, NULL, md, NULL, pkey) != 1) ++ goto end; ++ for (;;) { ++ tbuf_len = BIO_read(in, tbuf, TBUF_MAXSIZE); ++ if (tbuf_len == 0) ++ break; ++ if (tbuf_len < 0) { ++ BIO_printf(bio_err, "Error reading raw input data\n"); ++ goto end; ++ } ++ rv = EVP_DigestVerifyUpdate(mctx, tbuf, (size_t)tbuf_len); ++ if (rv != 1) { ++ BIO_printf(bio_err, "Error verifying raw input data\n"); ++ goto end; ++ } ++ } ++ rv = EVP_DigestVerifyFinal(mctx, sig, (size_t)siglen); ++ break; ++ case EVP_PKEY_OP_SIGN: ++ if (EVP_DigestSignInit(mctx, NULL, md, NULL, pkey) != 1) ++ goto end; ++ for (;;) { ++ tbuf_len = BIO_read(in, tbuf, TBUF_MAXSIZE); ++ if (tbuf_len == 0) ++ break; ++ if (tbuf_len < 0) { ++ BIO_printf(bio_err, "Error reading raw input data\n"); ++ goto end; ++ } ++ rv = EVP_DigestSignUpdate(mctx, tbuf, (size_t)tbuf_len); ++ if (rv != 1) { ++ BIO_printf(bio_err, "Error signing raw input data\n"); ++ goto end; ++ } ++ } ++ rv = EVP_DigestSignFinal(mctx, NULL, poutlen); ++ if (rv == 1 && out != NULL) { ++ *out = app_malloc(*poutlen, "buffer output"); ++ rv = EVP_DigestSignFinal(mctx, *out, poutlen); ++ } ++ break; ++ } ++ ++ end: ++ EVP_MD_CTX_free(mctx); ++ return rv; ++} +diff --git a/crypto/sm2/sm2_pmeth.c b/crypto/sm2/sm2_pmeth.c +index 0e722b9..837bdc1 100644 +--- a/crypto/sm2/sm2_pmeth.c ++++ b/crypto/sm2/sm2_pmeth.c +@@ -252,6 +252,9 @@ static int pkey_sm2_ctrl_str(EVP_PKEY_CTX *ctx, + else + return -2; + return EVP_PKEY_CTX_set_ec_param_enc(ctx, param_enc); ++ } else if (strcmp(type, "sm2_id") == 0) { ++ return pkey_sm2_ctrl(ctx, EVP_PKEY_CTRL_SET1_ID, ++ (int)strlen(value), (void *)value); + } + + return -2; +diff --git a/doc/man1/pkeyutl.pod b/doc/man1/pkeyutl.pod +index f6fd48d..f0f80af 100644 +--- a/doc/man1/pkeyutl.pod ++++ b/doc/man1/pkeyutl.pod +@@ -10,6 +10,8 @@ pkeyutl - public key algorithm utility + B B + [B<-help>] + [B<-in file>] ++[B<-rawin>] ++[B<-digest algorithm>] + [B<-out file>] + [B<-sigfile file>] + [B<-inkey file>] +@@ -54,6 +56,23 @@ Print out a usage message. + This specifies the input filename to read data from or standard input + if this option is not specified. + ++=item B<-rawin> ++ ++This indicates that the input data is raw data, which is not hashed by any ++message digest algorithm. The user can specify a digest algorithm by using ++the B<-digest> option. This option can only be used with B<-sign> and ++B<-verify>. ++ ++=item B<-digest algorithm> ++ ++This specifies the digest algorithm which is used to hash the input data before ++signing or verifying it with the input key. This option could be omitted if the ++signature algorithm does not require one (for instance, EdDSA). If this option ++is omitted but the signature algorithm requires one, a default value will be ++used. For signature algorithms like RSA, DSA and ECDSA, SHA-256 will be the ++default digest algorithm. For SM2, it will be SM3. If this option is present, ++then the B<-rawin> option must be also specified to B. ++ + =item B<-out filename> + + Specifies the output filename to write to or standard output by +@@ -296,6 +315,22 @@ the B<-pkeyopt> B option. + The X25519 and X448 algorithms support key derivation only. Currently there are + no additional options. + ++=head1 SM2 ++ ++The SM2 algorithm supports sign, verify, encrypt and decrypt operations. For ++the sign and verify operations, SM2 requires an ID string to be passed in. The ++following B value is supported: ++ ++=over 4 ++ ++=item B ++ ++This sets the ID string used in SM2 sign or verify operations. While verifying ++an SM2 signature, the ID string must be the same one used when signing the data. ++Otherwise the verification will fail. ++ ++=back ++ + =head1 EXAMPLES + + Sign some data using a private key: +@@ -329,6 +364,16 @@ Decrypt some data using a private key with OAEP padding using SHA256: + openssl pkeyutl -decrypt -in file -inkey key.pem -out secret \ + -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha256 + ++Sign some data using an L private key and a specific ID: ++ ++ openssl pkeyutl -sign -in file -inkey sm2.key -out sig -rawin -digest sm3 \ ++ -pkeyopt sm2_id:someid ++ ++Verify some data using an L certificate and a specific ID: ++ ++ openssl pkeyutl -verify -certin -in file -inkey sm2.cert -sigfile sig \ ++ -rawin -digest sm3 -pkeyopt sm2_id:someid ++ + =head1 SEE ALSO + + L, L, L +diff --git a/test/certs/sm2.crt b/test/certs/sm2.crt +new file mode 100644 +index 0000000..189abb1 +--- /dev/null ++++ b/test/certs/sm2.crt +@@ -0,0 +1,13 @@ ++-----BEGIN CERTIFICATE----- ++MIIB6DCCAY6gAwIBAgIJAKH2BR6ITHZeMAoGCCqBHM9VAYN1MGgxCzAJBgNVBAYT ++AkNOMQswCQYDVQQIDAJMTjERMA8GA1UEBwwIU2hlbnlhbmcxETAPBgNVBAoMCFRl ++c3QgT3JnMRAwDgYDVQQLDAdUZXN0IE9VMRQwEgYDVQQDDAtUZXN0IFNNMiBDQTAe ++Fw0xOTAyMTkwNzA1NDhaFw0yMzAzMzAwNzA1NDhaMG8xCzAJBgNVBAYTAkNOMQsw ++CQYDVQQIDAJMTjERMA8GA1UEBwwIU2hlbnlhbmcxETAPBgNVBAoMCFRlc3QgT3Jn ++MRAwDgYDVQQLDAdUZXN0IE9VMRswGQYDVQQDDBJUZXN0IFNNMiBTaWduIENlcnQw ++WTATBgcqhkjOPQIBBggqgRzPVQGCLQNCAAQwqeNkWp7fiu1KZnuDkAucpM8piEzE ++TL1ymrcrOBvv8mhNNkeb20asbWgFQI2zOrSM99/sXGn9rM2/usM/MlcaoxowGDAJ ++BgNVHRMEAjAAMAsGA1UdDwQEAwIGwDAKBggqgRzPVQGDdQNIADBFAiEA9edBnAqT ++TNuGIUIvXsj6/nP+AzXA9HGtAIY4nrqW8LkCIHyZzhRTlxYtgfqkDl0OK5QQRCZH ++OZOfmtx613VyzXwc ++-----END CERTIFICATE----- +diff --git a/test/certs/sm2.key b/test/certs/sm2.key +new file mode 100644 +index 0000000..1efd364 +--- /dev/null ++++ b/test/certs/sm2.key +@@ -0,0 +1,5 @@ ++-----BEGIN PRIVATE KEY----- ++MIGHAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBG0wawIBAQQgSKhk+4xGyDI+IS2H ++WVfFPDxh1qv5+wtrddaIsGNXGZihRANCAAQwqeNkWp7fiu1KZnuDkAucpM8piEzE ++TL1ymrcrOBvv8mhNNkeb20asbWgFQI2zOrSM99/sXGn9rM2/usM/Mlca ++-----END PRIVATE KEY----- +diff --git a/test/recipes/20-test_pkeyutl.t b/test/recipes/20-test_pkeyutl.t +new file mode 100644 +index 0000000..a051138 +--- /dev/null ++++ b/test/recipes/20-test_pkeyutl.t +@@ -0,0 +1,43 @@ ++#! /usr/bin/env perl ++# Copyright 2018 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 ++ ++use strict; ++use warnings; ++ ++use File::Spec; ++use OpenSSL::Test qw/:DEFAULT srctop_file/; ++use OpenSSL::Test::Utils; ++ ++setup("test_pkeyutl"); ++ ++plan tests => 2; ++ ++sub sign ++{ ++ # Utilize the sm2.crt as the TBS file ++ return run(app(([ 'openssl', 'pkeyutl', '-sign', ++ '-in', srctop_file('test', 'certs', 'sm2.crt'), ++ '-inkey', srctop_file('test', 'certs', 'sm2.key'), ++ '-out', 'signature.sm2', '-rawin', ++ '-digest', 'sm3', '-pkeyopt', 'sm2_id:someid']))); ++} ++ ++sub verify ++{ ++ # Utilize the sm2.crt as the TBS file ++ return run(app(([ 'openssl', 'pkeyutl', '-verify', '-certin', ++ '-in', srctop_file('test', 'certs', 'sm2.crt'), ++ '-inkey', srctop_file('test', 'certs', 'sm2.crt'), ++ '-sigfile', 'signature.sm2', '-rawin', ++ '-digest', 'sm3', '-pkeyopt', 'sm2_id:someid']))); ++} ++ ++ok(sign, "Sign a piece of data using SM2"); ++ok(verify, "Verify an SM2 signature against a piece of data"); ++ ++unlink 'signature.sm2'; +-- +2.20.1 (Apple Git-117) + diff --git a/backport-APPS-x509-With-CA-but-both-CAserial-and-CAcreateseri.patch b/backport-APPS-x509-With-CA-but-both-CAserial-and-CAcreateseri.patch new file mode 100644 index 0000000..63c03f2 --- /dev/null +++ b/backport-APPS-x509-With-CA-but-both-CAserial-and-CAcreateseri.patch @@ -0,0 +1,187 @@ +From 55eafed6fbefbc1e725bf7b17b2bbca083a457fc Mon Sep 17 00:00:00 2001 +From: "Dr. David von Oheimb" +Date: Mon, 30 May 2022 16:53:05 +0200 +Subject: [PATCH] APPS/x509: With -CA but both -CAserial and -CAcreateserial + not given, use random serial. + +Also improve openssl-x509.pod.in and error handling of load_serial() in apps.c. +Backported from https://github.com/openssl/openssl/pull/18373 + +Reviewed-by: Hugo Landau +Reviewed-by: Tomas Mraz +Reviewed-by: David von Oheimb +(Merged from https://github.com/openssl/openssl/pull/18803) +--- + apps/apps.c | 15 +++++++++++++-- + apps/apps.h | 9 ++++++--- + apps/ca.c | 6 ++++-- + apps/x509.c | 12 ++++++++---- + doc/man1/x509.pod | 12 +++++++----- + 5 files changed, 38 insertions(+), 16 deletions(-) + +diff --git a/apps/apps.c b/apps/apps.c +index db5b48e4cf..f2447fb0be 100644 +--- a/apps/apps.c ++++ b/apps/apps.c +@@ -1376,7 +1376,8 @@ static IMPLEMENT_LHASH_HASH_FN(index_name, OPENSSL_CSTRING) + static IMPLEMENT_LHASH_COMP_FN(index_name, OPENSSL_CSTRING) + #undef BSIZE + #define BSIZE 256 +-BIGNUM *load_serial(const char *serialfile, int create, ASN1_INTEGER **retai) ++BIGNUM *load_serial(const char *serialfile, int *exists, int create, ++ ASN1_INTEGER **retai) + { + BIO *in = NULL; + BIGNUM *ret = NULL; +@@ -1388,6 +1389,8 @@ BIGNUM *load_serial(const char *serialfile, int create, ASN1_INTEGER **retai) + goto err; + + in = BIO_new_file(serialfile, "r"); ++ if (exists != NULL) ++ *exists = in != NULL; + if (in == NULL) { + if (!create) { + perror(serialfile); +@@ -1395,8 +1398,14 @@ BIGNUM *load_serial(const char *serialfile, int create, ASN1_INTEGER **retai) + } + ERR_clear_error(); + ret = BN_new(); +- if (ret == NULL || !rand_serial(ret, ai)) ++ if (ret == NULL) { + BIO_printf(bio_err, "Out of memory\n"); ++ } else if (!rand_serial(ret, ai)) { ++ BIO_printf(bio_err, "Error creating random number to store in %s\n", ++ serialfile); ++ BN_free(ret); ++ ret = NULL; ++ } + } else { + if (!a2i_ASN1_INTEGER(in, ai, buf, 1024)) { + BIO_printf(bio_err, "unable to load number from %s\n", +@@ -1416,6 +1425,8 @@ BIGNUM *load_serial(const char *serialfile, int create, ASN1_INTEGER **retai) + ai = NULL; + } + err: ++ if (ret == NULL) ++ ERR_print_errors(bio_err); + BIO_free(in); + ASN1_INTEGER_free(ai); + return ret; +diff --git a/apps/apps.h b/apps/apps.h +index 34c3fd8633..775342b4f3 100644 +--- a/apps/apps.h ++++ b/apps/apps.h +@@ -527,9 +527,12 @@ typedef struct ca_db_st { + } CA_DB; + + void* app_malloc(int sz, const char *what); +-BIGNUM *load_serial(const char *serialfile, int create, ASN1_INTEGER **retai); +-int save_serial(const char *serialfile, const char *suffix, const BIGNUM *serial, +- ASN1_INTEGER **retai); ++ ++/* load_serial, save_serial, and rotate_serial are also used for CRL numbers */ ++BIGNUM *load_serial(const char *serialfile, int *exists, int create, ++ ASN1_INTEGER **retai); ++int save_serial(const char *serialfile, const char *suffix, ++ const BIGNUM *serial, ASN1_INTEGER **retai); + int rotate_serial(const char *serialfile, const char *new_suffix, + const char *old_suffix); + int rand_serial(BIGNUM *b, ASN1_INTEGER *ai); +diff --git a/apps/ca.c b/apps/ca.c +index 390ac37493..ad01bba55a 100755 +--- a/apps/ca.c ++++ b/apps/ca.c +@@ -842,7 +842,8 @@ end_of_options: + goto end; + } + } else { +- if ((serial = load_serial(serialfile, create_ser, NULL)) == NULL) { ++ serial = load_serial(serialfile, NULL, create_ser, NULL); ++ if (serial == NULL) { + BIO_printf(bio_err, "error while loading serial number\n"); + goto end; + } +@@ -1078,7 +1079,8 @@ end_of_options: + + if ((crlnumberfile = NCONF_get_string(conf, section, ENV_CRLNUMBER)) + != NULL) +- if ((crlnumber = load_serial(crlnumberfile, 0, NULL)) == NULL) { ++ if ((crlnumber = load_serial(crlnumberfile, NULL, 0, NULL)) ++ == NULL) { + BIO_printf(bio_err, "error while loading CRL number\n"); + goto end; + } +diff --git a/apps/x509.c b/apps/x509.c +index 1f53504209..67a70e7fea 100644 +--- a/apps/x509.c ++++ b/apps/x509.c +@@ -400,7 +400,7 @@ int x509_main(int argc, char **argv) + aliasout = ++num; + break; + case OPT_CACREATESERIAL: +- CA_createserial = ++num; ++ CA_createserial = 1; + break; + case OPT_CLREXT: + clrext = 1; +@@ -916,6 +916,7 @@ static ASN1_INTEGER *x509_load_serial(const char *CAfile, + char *buf = NULL; + ASN1_INTEGER *bs = NULL; + BIGNUM *serial = NULL; ++ int defaultfile = 0, file_exists; + + if (serialfile == NULL) { + const char *p = strrchr(CAfile, '.'); +@@ -925,9 +926,10 @@ static ASN1_INTEGER *x509_load_serial(const char *CAfile, + memcpy(buf, CAfile, len); + memcpy(buf + len, POSTFIX, sizeof(POSTFIX)); + serialfile = buf; ++ defaultfile = 1; + } + +- serial = load_serial(serialfile, create, NULL); ++ serial = load_serial(serialfile, &file_exists, create || defaultfile, NULL); + if (serial == NULL) + goto end; + +@@ -936,8 +938,10 @@ static ASN1_INTEGER *x509_load_serial(const char *CAfile, + goto end; + } + +- if (!save_serial(serialfile, NULL, serial, &bs)) +- goto end; ++ if (file_exists || create) ++ save_serial(serialfile, NULL, serial, &bs); ++ else ++ bs = BN_to_ASN1_INTEGER(serial, NULL); + + end: + OPENSSL_free(buf); +diff --git a/doc/man1/x509.pod b/doc/man1/x509.pod +index 3c9b2f2263..67d131389a 100644 +--- a/doc/man1/x509.pod ++++ b/doc/man1/x509.pod +@@ -443,13 +443,15 @@ The default filename consists of the CA certificate file base name with + ".srl" appended. For example if the CA certificate file is called + "mycacert.pem" it expects to find a serial number file called "mycacert.srl". + ++If the B<-CA> option is specified and both the <-CAserial> and <-CAcreateserial> ++options are not given and the default serial number file does not exist, ++a random number is generated; this is the recommended practice. ++ + =item B<-CAcreateserial> + +-With this option the CA serial number file is created if it does not exist: +-it will contain the serial number "02" and the certificate being signed will +-have the 1 as its serial number. If the B<-CA> option is specified +-and the serial number file does not exist a random number is generated; +-this is the recommended practice. ++With this option the CA serial number file is created if it does not exist. ++A random number is generated, used for the certificate, and saved into the ++serial number file in that case. + + =item B<-extfile filename> + +-- +2.17.1 + diff --git a/backport-Add-DTLS-support-to-the-large-app-data-test.patch b/backport-Add-DTLS-support-to-the-large-app-data-test.patch new file mode 100644 index 0000000..9abf862 --- /dev/null +++ b/backport-Add-DTLS-support-to-the-large-app-data-test.patch @@ -0,0 +1,76 @@ +From adc3cfe452daa0fe51b8059929b2dafdc42737e4 Mon Sep 17 00:00:00 2001 +From: Matt Caswell +Date: Fri, 20 Jan 2023 14:08:42 +0000 +Subject: [PATCH] Add DTLS support to the large app data test + +Reviewed-by: Paul Dale +Reviewed-by: Tomas Mraz +Reviewed-by: Hugo Landau +(Merged from https://github.com/openssl/openssl/pull/20087) +--- + test/sslapitest.c | 28 +++++++++++++++++++++++++--- + 1 file changed, 25 insertions(+), 3 deletions(-) + +diff --git a/test/sslapitest.c b/test/sslapitest.c +index 10bbb1eb92..9864daabf1 100644 +--- a/test/sslapitest.c ++++ b/test/sslapitest.c +@@ -809,6 +809,8 @@ static int test_large_app_data(int tst) + int testresult = 0, prot; + unsigned char *msg, *buf = NULL; + size_t written, readbytes; ++ const SSL_METHOD *smeth = TLS_server_method(); ++ const SSL_METHOD *cmeth = TLS_client_method(); + + switch (tst >> 2) { + case 0: +@@ -851,6 +853,26 @@ static int test_large_app_data(int tst) + return 1; + #endif + ++ case 5: ++#ifndef OPENSSL_NO_DTLS1_2 ++ prot = DTLS1_2_VERSION; ++ smeth = DTLS_server_method(); ++ cmeth = DTLS_client_method(); ++ break; ++#else ++ return 1; ++#endif ++ ++ case 6: ++#ifndef OPENSSL_NO_DTLS1 ++ prot = DTLS1_VERSION; ++ smeth = DTLS_server_method(); ++ cmeth = DTLS_client_method(); ++ break; ++#else ++ return 1; ++#endif ++ + default: + /* Shouldn't happen */ + return 0; +@@ -867,8 +889,8 @@ static int test_large_app_data(int tst) + /* Set whole buffer to all bits set */ + memset(buf, 0xff, SSL3_RT_MAX_PLAIN_LENGTH + 1); + +- if (!TEST_true(create_ssl_ctx_pair(TLS_server_method(), TLS_client_method(), +- prot, prot, &sctx, &cctx, cert, privkey))) ++ if (!TEST_true(create_ssl_ctx_pair(smeth, cmeth, prot, prot, &sctx, &cctx, ++ cert, privkey))) + goto end; + + if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, +@@ -7304,7 +7326,7 @@ int setup_tests(void) + #ifndef OPENSSL_NO_DTLS + ADD_TEST(test_large_message_dtls); + #endif +- ADD_ALL_TESTS(test_large_app_data, 20); ++ ADD_ALL_TESTS(test_large_app_data, 28); + #ifndef OPENSSL_NO_OCSP + ADD_TEST(test_tlsext_status_type); + #endif +-- +2.36.1 + diff --git a/backport-Add-a-test-for-large-app-data.patch b/backport-Add-a-test-for-large-app-data.patch new file mode 100644 index 0000000..febf1e5 --- /dev/null +++ b/backport-Add-a-test-for-large-app-data.patch @@ -0,0 +1,166 @@ +From b958ecf27c5cdbcfab6e27777aca8a9fcd82e7af Mon Sep 17 00:00:00 2001 +From: Matt Caswell +Date: Thu, 19 Jan 2023 10:52:45 +0000 +Subject: [PATCH] Add a test for large app data + +Test that sending large app data records works correctly. + +Reviewed-by: Paul Dale +Reviewed-by: Tomas Mraz +Reviewed-by: Hugo Landau +(Merged from https://github.com/openssl/openssl/pull/20087) +--- + test/sslapitest.c | 130 ++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 130 insertions(+) + +diff --git a/test/sslapitest.c b/test/sslapitest.c +index 685c28d934..10bbb1eb92 100644 +--- a/test/sslapitest.c ++++ b/test/sslapitest.c +@@ -794,6 +794,135 @@ static int test_large_message_dtls(void) + } + #endif + ++/* ++ * Test we can successfully send the maximum amount of application data. We ++ * test each protocol version individually, each with and without EtM enabled. ++ * TLSv1.3 doesn't use EtM so technically it is redundant to test both but it is ++ * simpler this way. We also test all combinations with and without the ++ * SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS option which affects the size of the ++ * underlying buffer. ++ */ ++static int test_large_app_data(int tst) ++{ ++ SSL_CTX *cctx = NULL, *sctx = NULL; ++ SSL *clientssl = NULL, *serverssl = NULL; ++ int testresult = 0, prot; ++ unsigned char *msg, *buf = NULL; ++ size_t written, readbytes; ++ ++ switch (tst >> 2) { ++ case 0: ++#ifndef OPENSSL_NO_TLS1_3 ++ prot = TLS1_3_VERSION; ++ break; ++#else ++ return 1; ++#endif ++ ++ case 1: ++#ifndef OPENSSL_NO_TLS1_2 ++ prot = TLS1_2_VERSION; ++ break; ++#else ++ return 1; ++#endif ++ ++ case 2: ++#ifndef OPENSSL_NO_TLS1_1 ++ prot = TLS1_1_VERSION; ++ break; ++#else ++ return 1; ++#endif ++ ++ case 3: ++#ifndef OPENSSL_NO_TLS1 ++ prot = TLS1_VERSION; ++ break; ++#else ++ return 1; ++#endif ++ ++ case 4: ++#ifndef OPENSSL_NO_SSL3 ++ prot = SSL3_VERSION; ++ break; ++#else ++ return 1; ++#endif ++ ++ default: ++ /* Shouldn't happen */ ++ return 0; ++ } ++ ++ /* Maximal sized message of zeros */ ++ msg = OPENSSL_zalloc(SSL3_RT_MAX_PLAIN_LENGTH); ++ if (!TEST_ptr(msg)) ++ goto end; ++ ++ buf = OPENSSL_malloc(SSL3_RT_MAX_PLAIN_LENGTH + 1); ++ if (!TEST_ptr(buf)) ++ goto end; ++ /* Set whole buffer to all bits set */ ++ memset(buf, 0xff, SSL3_RT_MAX_PLAIN_LENGTH + 1); ++ ++ if (!TEST_true(create_ssl_ctx_pair(TLS_server_method(), TLS_client_method(), ++ prot, prot, &sctx, &cctx, cert, privkey))) ++ goto end; ++ ++ if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, ++ &clientssl, NULL, NULL))) ++ goto end; ++ ++ if ((tst & 1) != 0) { ++ /* Setting this option gives us a minimally sized underlying buffer */ ++ if (!TEST_true(SSL_set_options(serverssl, ++ SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS)) ++ || !TEST_true(SSL_set_options(clientssl, ++ SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS))) ++ goto end; ++ } ++ ++ if ((tst & 2) != 0) { ++ /* ++ * Setting this option means the MAC is added before encryption ++ * giving us a larger record for the encryption process ++ */ ++ if (!TEST_true(SSL_set_options(serverssl, SSL_OP_NO_ENCRYPT_THEN_MAC)) ++ || !TEST_true(SSL_set_options(clientssl, ++ SSL_OP_NO_ENCRYPT_THEN_MAC))) ++ goto end; ++ } ++ ++ if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE))) ++ goto end; ++ ++ if (!TEST_true(SSL_write_ex(clientssl, msg, SSL3_RT_MAX_PLAIN_LENGTH, ++ &written)) ++ || !TEST_size_t_eq(written, SSL3_RT_MAX_PLAIN_LENGTH)) ++ goto end; ++ ++ /* We provide a buffer slightly larger than what we are actually expecting */ ++ if (!TEST_true(SSL_read_ex(serverssl, buf, SSL3_RT_MAX_PLAIN_LENGTH + 1, ++ &readbytes))) ++ goto end; ++ ++ if (!TEST_mem_eq(msg, written, buf, readbytes)) ++ goto end; ++ ++ testresult = 1; ++end: ++ OPENSSL_free(msg); ++ OPENSSL_free(buf); ++ SSL_free(serverssl); ++ SSL_free(clientssl); ++ SSL_CTX_free(sctx); ++ SSL_CTX_free(cctx); ++ return testresult; ++} ++ ++ + #ifndef OPENSSL_NO_OCSP + static int ocsp_server_cb(SSL *s, void *arg) + { +@@ -7175,6 +7304,7 @@ int setup_tests(void) + #ifndef OPENSSL_NO_DTLS + ADD_TEST(test_large_message_dtls); + #endif ++ ADD_ALL_TESTS(test_large_app_data, 20); + #ifndef OPENSSL_NO_OCSP + ADD_TEST(test_tlsext_status_type); + #endif +-- +2.36.1 + diff --git a/backport-Add-an-extra-reduction-step-to-RSAZ-mod_exp-implemen.patch b/backport-Add-an-extra-reduction-step-to-RSAZ-mod_exp-implemen.patch new file mode 100644 index 0000000..463429d --- /dev/null +++ b/backport-Add-an-extra-reduction-step-to-RSAZ-mod_exp-implemen.patch @@ -0,0 +1,123 @@ +From 8438d3a7b7309cbea521d3628fddeda7bd6d6e20 Mon Sep 17 00:00:00 2001 +From: Tomas Mraz +Date: Thu, 9 Jun 2022 16:20:05 +0200 +Subject: [PATCH] Add an extra reduction step to RSAZ mod_exp implementations + +Inspired by BoringSSL fix by David Benjamin. + +Reviewed-by: Matt Caswell +Reviewed-by: Paul Dale +(Merged from https://github.com/openssl/openssl/pull/18511) +--- + crypto/bn/rsaz_exp.c | 8 ++++++++ + crypto/bn/rsaz_exp.h | 23 +++++++++++++++++++++++ + test/recipes/10-test_bn_data/bnmod.txt | 10 ++++------ + 3 files changed, 35 insertions(+), 6 deletions(-) + +diff --git a/crypto/bn/rsaz_exp.c b/crypto/bn/rsaz_exp.c +index 22455b8a63..5c5cd4c282 100644 +--- a/crypto/bn/rsaz_exp.c ++++ b/crypto/bn/rsaz_exp.c +@@ -66,6 +66,7 @@ void RSAZ_1024_mod_exp_avx2(BN_ULONG result_norm[16], + unsigned char *R2 = table_s; /* borrow */ + int index; + int wvalue; ++ BN_ULONG tmp[16]; + + if ((((size_t)p_str & 4095) + 320) >> 12) { + result = p_str; +@@ -237,7 +238,10 @@ void RSAZ_1024_mod_exp_avx2(BN_ULONG result_norm[16], + + rsaz_1024_red2norm_avx2(result_norm, result); + ++ bn_reduce_once_in_place(result_norm, /*carry=*/0, m_norm, tmp, 16); ++ + OPENSSL_cleanse(storage, sizeof(storage)); ++ OPENSSL_cleanse(tmp, sizeof(tmp)); + } + + /* +@@ -266,6 +270,7 @@ void RSAZ_512_mod_exp(BN_ULONG result[8], + unsigned char *p_str = (unsigned char *)exponent; + int index; + unsigned int wvalue; ++ BN_ULONG tmp[8]; + + /* table[0] = 1_inv */ + temp[0] = 0 - m[0]; +@@ -309,7 +314,10 @@ void RSAZ_512_mod_exp(BN_ULONG result[8], + /* from Montgomery */ + rsaz_512_mul_by_one(result, temp, m, k0); + ++ bn_reduce_once_in_place(result, /*carry=*/0, m, tmp, 8); ++ + OPENSSL_cleanse(storage, sizeof(storage)); ++ OPENSSL_cleanse(tmp, sizeof(tmp)); + } + + #endif +diff --git a/crypto/bn/rsaz_exp.h b/crypto/bn/rsaz_exp.h +index 88f65a4bae..606496d45a 100644 +--- a/crypto/bn/rsaz_exp.h ++++ b/crypto/bn/rsaz_exp.h +@@ -22,6 +22,8 @@ + # define RSAZ_ENABLED + + # include ++# include "internal/constant_time.h" ++# include "bn_local.h" + + void RSAZ_1024_mod_exp_avx2(BN_ULONG result[16], + const BN_ULONG base_norm[16], +@@ -35,6 +37,27 @@ void RSAZ_512_mod_exp(BN_ULONG result[8], + const BN_ULONG m_norm[8], BN_ULONG k0, + const BN_ULONG RR[8]); + ++static ossl_inline void bn_select_words(BN_ULONG *r, BN_ULONG mask, ++ const BN_ULONG *a, ++ const BN_ULONG *b, size_t num) ++{ ++ size_t i; ++ ++ for (i = 0; i < num; i++) { ++ r[i] = constant_time_select_64(mask, a[i], b[i]); ++ } ++} ++ ++static ossl_inline BN_ULONG bn_reduce_once_in_place(BN_ULONG *r, ++ BN_ULONG carry, ++ const BN_ULONG *m, ++ BN_ULONG *tmp, size_t num) ++{ ++ carry -= bn_sub_words(tmp, r, m, num); ++ bn_select_words(r, carry, r /* tmp < 0 */, tmp /* tmp >= 0 */, num); ++ return carry; ++} ++ + # endif + + #endif +diff --git a/test/recipes/10-test_bn_data/bnmod.txt b/test/recipes/10-test_bn_data/bnmod.txt +index 69f8af43d5..edde03bd62 100644 +--- a/test/recipes/10-test_bn_data/bnmod.txt ++++ b/test/recipes/10-test_bn_data/bnmod.txt +@@ -2493,12 +2493,10 @@ E = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + M = 8f42c9e9e351ba9b32ab0cf69da43f4acf7028d19cff6e5059ea0e3fcc97c97f36a31470044737d4c0c933ac441ecb29e32c81401523afdac7de9c3fd8493c97 + + # 1024-bit +-# TODO(davidben): This test breaks the RSAZ implementation. Fix it and enable +-# this test. +-# ModExp = 00 +-# A = 800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002f +-# E = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +-# M = 9da8dc26fdf4d2e49833b240ee552beb7a6e251caa91bfb5d6cafaf8ed9461877fda8f6ac299036d35806bc1ae7872e54eaac1ec6bee6d02c6621a9cf8883b3abc33c49b3e601203e0e86ef8f0562412cc689ee2670704583909ca6d7774c9f9f9f4d77d37fedef9cb51d207cb629ec02fa03b526fd6594bfa8f2da71238a0b7 ++ModExp = 00 ++A = 800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002f ++E = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ++M = 9da8dc26fdf4d2e49833b240ee552beb7a6e251caa91bfb5d6cafaf8ed9461877fda8f6ac299036d35806bc1ae7872e54eaac1ec6bee6d02c6621a9cf8883b3abc33c49b3e601203e0e86ef8f0562412cc689ee2670704583909ca6d7774c9f9f9f4d77d37fedef9cb51d207cb629ec02fa03b526fd6594bfa8f2da71238a0b7 + + # 1025-bit + ModExp = 00 +-- +2.17.1 + diff --git a/backport-Add-test-for-EC_KEY_set_private_key.patch b/backport-Add-test-for-EC_KEY_set_private_key.patch new file mode 100644 index 0000000..c6def39 --- /dev/null +++ b/backport-Add-test-for-EC_KEY_set_private_key.patch @@ -0,0 +1,71 @@ +From 1c2f52bed3ebee6222cf078278074c72717df4ec Mon Sep 17 00:00:00 2001 +From: Roberto Hueso Gomez +Date: Mon, 1 Aug 2022 02:08:47 +0200 +Subject: [PATCH] Add test for EC_KEY_set_private_key() + +This tests the behavior and API of the EC_KEY_set_private_key function. +It tests compliance with legacy features related to NULL private keys +too. + +Reviewed-by: Nicola Tuveri +Reviewed-by: Matt Caswell +(Merged from https://github.com/openssl/openssl/pull/18874) +--- + test/ec_internal_test.c | 34 ++++++++++++++++++++++++++++++++++ + 1 file changed, 34 insertions(+) + +diff --git a/test/ec_internal_test.c b/test/ec_internal_test.c +index 45a36ab94a..4da842a8a7 100644 +--- a/test/ec_internal_test.c ++++ b/test/ec_internal_test.c +@@ -183,6 +183,39 @@ static int field_tests_default(int n) + return ret; + } + ++/* ++ * Tests behavior of the EC_KEY_set_private_key ++ */ ++static int set_private_key(void) ++{ ++ EC_KEY *key = NULL, *aux_key = NULL; ++ int testresult = 0; ++ ++ key = EC_KEY_new_by_curve_name(NID_secp224r1); ++ aux_key = EC_KEY_new_by_curve_name(NID_secp224r1); ++ if (!TEST_ptr(key) ++ || !TEST_ptr(aux_key) ++ || !TEST_int_eq(EC_KEY_generate_key(key), 1) ++ || !TEST_int_eq(EC_KEY_generate_key(aux_key), 1)) ++ goto err; ++ ++ /* Test setting a valid private key */ ++ if (!TEST_int_eq(EC_KEY_set_private_key(key, aux_key->priv_key), 1)) ++ goto err; ++ ++ /* Test compliance with legacy behavior for NULL private keys */ ++ if (!TEST_int_eq(EC_KEY_set_private_key(key, NULL), 0) ++ || !TEST_ptr_null(key->priv_key)) ++ goto err; ++ ++ testresult = 1; ++ ++ err: ++ EC_KEY_free(key); ++ EC_KEY_free(aux_key); ++ return testresult; ++} ++ + /* + * Tests behavior of the decoded_from_explicit_params flag and API + */ +@@ -337,6 +370,7 @@ int setup_tests(void) + ADD_TEST(field_tests_ec2_simple); + #endif + ADD_ALL_TESTS(field_tests_default, crv_len); ++ ADD_TEST(set_private_key); + ADD_TEST(decoded_flag_test); + ADD_ALL_TESTS(ecpkparams_i2d2i_test, crv_len); + +-- +2.17.1 + diff --git a/backport-Always-end-BN_mod_exp_mont_consttime-with-normal-Mon.patch b/backport-Always-end-BN_mod_exp_mont_consttime-with-normal-Mon.patch new file mode 100644 index 0000000..6084d8c --- /dev/null +++ b/backport-Always-end-BN_mod_exp_mont_consttime-with-normal-Mon.patch @@ -0,0 +1,406 @@ +From 0ed27fb7a8d85685cb671bf0a1e41bcdfc2624dc Mon Sep 17 00:00:00 2001 +From: Tomas Mraz +Date: Thu, 9 Jun 2022 12:34:55 +0200 +Subject: [PATCH] Always end BN_mod_exp_mont_consttime with normal Montgomery + reduction. + +This partially fixes a bug where, on x86_64, BN_mod_exp_mont_consttime +would sometimes return m, the modulus, when it should have returned +zero. Thanks to Guido Vranken for reporting it. It is only a partial fix +because the same bug also exists in the "rsaz" codepath. + +The bug only affects zero outputs (with non-zero inputs), so we believe +it has no security impact on our cryptographic functions. + +The fx is to delete lowercase bn_from_montgomery altogether, and have the +mont5 path use the same BN_from_montgomery ending as the non-mont5 path. +This only impacts the final step of the whole exponentiation and has no +measurable perf impact. + +See the original BoringSSL commit +https://boringssl.googlesource.com/boringssl/+/13c9d5c69d04485a7a8840c12185c832026c8315 +for further analysis. + +Original-author: David Benjamin + +Reviewed-by: Matt Caswell +Reviewed-by: Paul Dale +(Merged from https://github.com/openssl/openssl/pull/18511) +--- + crypto/bn/asm/x86_64-mont5.pl | 196 ------------------------- + crypto/bn/bn_exp.c | 44 +++--- + test/recipes/10-test_bn_data/bnmod.txt | 67 +++++++++ + 3 files changed, 93 insertions(+), 214 deletions(-) + +diff --git a/crypto/bn/asm/x86_64-mont5.pl b/crypto/bn/asm/x86_64-mont5.pl +index 8c37d132e4..cc7b610145 100755 +--- a/crypto/bn/asm/x86_64-mont5.pl ++++ b/crypto/bn/asm/x86_64-mont5.pl +@@ -2101,193 +2101,6 @@ __bn_post4x_internal: + .size __bn_post4x_internal,.-__bn_post4x_internal + ___ + } +-{ +-$code.=<<___; +-.globl bn_from_montgomery +-.type bn_from_montgomery,\@abi-omnipotent +-.align 32 +-bn_from_montgomery: +-.cfi_startproc +- testl \$7,`($win64?"48(%rsp)":"%r9d")` +- jz bn_from_mont8x +- xor %eax,%eax +- ret +-.cfi_endproc +-.size bn_from_montgomery,.-bn_from_montgomery +- +-.type bn_from_mont8x,\@function,6 +-.align 32 +-bn_from_mont8x: +-.cfi_startproc +- .byte 0x67 +- mov %rsp,%rax +-.cfi_def_cfa_register %rax +- push %rbx +-.cfi_push %rbx +- push %rbp +-.cfi_push %rbp +- push %r12 +-.cfi_push %r12 +- push %r13 +-.cfi_push %r13 +- push %r14 +-.cfi_push %r14 +- push %r15 +-.cfi_push %r15 +-.Lfrom_prologue: +- +- shl \$3,${num}d # convert $num to bytes +- lea ($num,$num,2),%r10 # 3*$num in bytes +- neg $num +- mov ($n0),$n0 # *n0 +- +- ############################################################## +- # Ensure that stack frame doesn't alias with $rptr+3*$num +- # modulo 4096, which covers ret[num], am[num] and n[num] +- # (see bn_exp.c). The stack is allocated to aligned with +- # bn_power5's frame, and as bn_from_montgomery happens to be +- # last operation, we use the opportunity to cleanse it. +- # +- lea -320(%rsp,$num,2),%r11 +- mov %rsp,%rbp +- sub $rptr,%r11 +- and \$4095,%r11 +- cmp %r11,%r10 +- jb .Lfrom_sp_alt +- sub %r11,%rbp # align with $aptr +- lea -320(%rbp,$num,2),%rbp # future alloca(frame+2*$num*8+256) +- jmp .Lfrom_sp_done +- +-.align 32 +-.Lfrom_sp_alt: +- lea 4096-320(,$num,2),%r10 +- lea -320(%rbp,$num,2),%rbp # future alloca(frame+2*$num*8+256) +- sub %r10,%r11 +- mov \$0,%r10 +- cmovc %r10,%r11 +- sub %r11,%rbp +-.Lfrom_sp_done: +- and \$-64,%rbp +- mov %rsp,%r11 +- sub %rbp,%r11 +- and \$-4096,%r11 +- lea (%rbp,%r11),%rsp +- mov (%rsp),%r10 +- cmp %rbp,%rsp +- ja .Lfrom_page_walk +- jmp .Lfrom_page_walk_done +- +-.Lfrom_page_walk: +- lea -4096(%rsp),%rsp +- mov (%rsp),%r10 +- cmp %rbp,%rsp +- ja .Lfrom_page_walk +-.Lfrom_page_walk_done: +- +- mov $num,%r10 +- neg $num +- +- ############################################################## +- # Stack layout +- # +- # +0 saved $num, used in reduction section +- # +8 &t[2*$num], used in reduction section +- # +32 saved *n0 +- # +40 saved %rsp +- # +48 t[2*$num] +- # +- mov $n0, 32(%rsp) +- mov %rax, 40(%rsp) # save original %rsp +-.cfi_cfa_expression %rsp+40,deref,+8 +-.Lfrom_body: +- mov $num,%r11 +- lea 48(%rsp),%rax +- pxor %xmm0,%xmm0 +- jmp .Lmul_by_1 +- +-.align 32 +-.Lmul_by_1: +- movdqu ($aptr),%xmm1 +- movdqu 16($aptr),%xmm2 +- movdqu 32($aptr),%xmm3 +- movdqa %xmm0,(%rax,$num) +- movdqu 48($aptr),%xmm4 +- movdqa %xmm0,16(%rax,$num) +- .byte 0x48,0x8d,0xb6,0x40,0x00,0x00,0x00 # lea 64($aptr),$aptr +- movdqa %xmm1,(%rax) +- movdqa %xmm0,32(%rax,$num) +- movdqa %xmm2,16(%rax) +- movdqa %xmm0,48(%rax,$num) +- movdqa %xmm3,32(%rax) +- movdqa %xmm4,48(%rax) +- lea 64(%rax),%rax +- sub \$64,%r11 +- jnz .Lmul_by_1 +- +- movq $rptr,%xmm1 +- movq $nptr,%xmm2 +- .byte 0x67 +- mov $nptr,%rbp +- movq %r10, %xmm3 # -num +-___ +-$code.=<<___ if ($addx); +- mov OPENSSL_ia32cap_P+8(%rip),%r11d +- and \$0x80108,%r11d +- cmp \$0x80108,%r11d # check for AD*X+BMI2+BMI1 +- jne .Lfrom_mont_nox +- +- lea (%rax,$num),$rptr +- call __bn_sqrx8x_reduction +- call __bn_postx4x_internal +- +- pxor %xmm0,%xmm0 +- lea 48(%rsp),%rax +- jmp .Lfrom_mont_zero +- +-.align 32 +-.Lfrom_mont_nox: +-___ +-$code.=<<___; +- call __bn_sqr8x_reduction +- call __bn_post4x_internal +- +- pxor %xmm0,%xmm0 +- lea 48(%rsp),%rax +- jmp .Lfrom_mont_zero +- +-.align 32 +-.Lfrom_mont_zero: +- mov 40(%rsp),%rsi # restore %rsp +-.cfi_def_cfa %rsi,8 +- movdqa %xmm0,16*0(%rax) +- movdqa %xmm0,16*1(%rax) +- movdqa %xmm0,16*2(%rax) +- movdqa %xmm0,16*3(%rax) +- lea 16*4(%rax),%rax +- sub \$32,$num +- jnz .Lfrom_mont_zero +- +- mov \$1,%rax +- mov -48(%rsi),%r15 +-.cfi_restore %r15 +- mov -40(%rsi),%r14 +-.cfi_restore %r14 +- mov -32(%rsi),%r13 +-.cfi_restore %r13 +- mov -24(%rsi),%r12 +-.cfi_restore %r12 +- mov -16(%rsi),%rbp +-.cfi_restore %rbp +- mov -8(%rsi),%rbx +-.cfi_restore %rbx +- lea (%rsi),%rsp +-.cfi_def_cfa_register %rsp +-.Lfrom_epilogue: +- ret +-.cfi_endproc +-.size bn_from_mont8x,.-bn_from_mont8x +-___ +-} + }}} + + if ($addx) {{{ +@@ -3894,10 +3707,6 @@ mul_handler: + .rva .LSEH_begin_bn_power5 + .rva .LSEH_end_bn_power5 + .rva .LSEH_info_bn_power5 +- +- .rva .LSEH_begin_bn_from_mont8x +- .rva .LSEH_end_bn_from_mont8x +- .rva .LSEH_info_bn_from_mont8x + ___ + $code.=<<___ if ($addx); + .rva .LSEH_begin_bn_mulx4x_mont_gather5 +@@ -3929,11 +3738,6 @@ $code.=<<___; + .byte 9,0,0,0 + .rva mul_handler + .rva .Lpower5_prologue,.Lpower5_body,.Lpower5_epilogue # HandlerData[] +-.align 8 +-.LSEH_info_bn_from_mont8x: +- .byte 9,0,0,0 +- .rva mul_handler +- .rva .Lfrom_prologue,.Lfrom_body,.Lfrom_epilogue # HandlerData[] + ___ + $code.=<<___ if ($addx); + .align 8 +diff --git a/crypto/bn/bn_exp.c b/crypto/bn/bn_exp.c +index 8c54ab005c..e21dcff027 100644 +--- a/crypto/bn/bn_exp.c ++++ b/crypto/bn/bn_exp.c +@@ -900,14 +900,21 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, + #if defined(OPENSSL_BN_ASM_MONT5) + if (window == 5 && top > 1) { + /* +- * This optimization uses ideas from http://eprint.iacr.org/2011/239, +- * specifically optimization of cache-timing attack countermeasures +- * and pre-computation optimization. +- */ +- +- /* +- * Dedicated window==4 case improves 512-bit RSA sign by ~15%, but as +- * 512-bit RSA is hardly relevant, we omit it to spare size... ++ * This optimization uses ideas from https://eprint.iacr.org/2011/239, ++ * specifically optimization of cache-timing attack countermeasures, ++ * pre-computation optimization, and Almost Montgomery Multiplication. ++ * ++ * The paper discusses a 4-bit window to optimize 512-bit modular ++ * exponentiation, used in RSA-1024 with CRT, but RSA-1024 is no longer ++ * important. ++ * ++ * |bn_mul_mont_gather5| and |bn_power5| implement the "almost" ++ * reduction variant, so the values here may not be fully reduced. ++ * They are bounded by R (i.e. they fit in |top| words), not |m|. ++ * Additionally, we pass these "almost" reduced inputs into ++ * |bn_mul_mont|, which implements the normal reduction variant. ++ * Given those inputs, |bn_mul_mont| may not give reduced ++ * output, but it will still produce "almost" reduced output. + */ + void bn_mul_mont_gather5(BN_ULONG *rp, const BN_ULONG *ap, + const void *table, const BN_ULONG *np, +@@ -919,9 +926,6 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, + const void *table, const BN_ULONG *np, + const BN_ULONG *n0, int num, int power); + int bn_get_bits5(const BN_ULONG *ap, int off); +- int bn_from_montgomery(BN_ULONG *rp, const BN_ULONG *ap, +- const BN_ULONG *not_used, const BN_ULONG *np, +- const BN_ULONG *n0, int num); + + BN_ULONG *n0 = mont->n0, *np; + +@@ -1010,14 +1014,18 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, + } + } + +- ret = bn_from_montgomery(tmp.d, tmp.d, NULL, np, n0, top); + tmp.top = top; +- bn_correct_top(&tmp); +- if (ret) { +- if (!BN_copy(rr, &tmp)) +- ret = 0; +- goto err; /* non-zero ret means it's not error */ +- } ++ /* ++ * The result is now in |tmp| in Montgomery form, but it may not be ++ * fully reduced. This is within bounds for |BN_from_montgomery| ++ * (tmp < R <= m*R) so it will, when converting from Montgomery form, ++ * produce a fully reduced result. ++ * ++ * This differs from Figure 2 of the paper, which uses AMM(h, 1) to ++ * convert from Montgomery form with unreduced output, followed by an ++ * extra reduction step. In the paper's terminology, we replace ++ * steps 9 and 10 with MM(h, 1). ++ */ + } else + #endif + { +diff --git a/test/recipes/10-test_bn_data/bnmod.txt b/test/recipes/10-test_bn_data/bnmod.txt +index 6c94a0f025..69f8af43d5 100644 +--- a/test/recipes/10-test_bn_data/bnmod.txt ++++ b/test/recipes/10-test_bn_data/bnmod.txt +@@ -2474,6 +2474,73 @@ A = 9025e6183706105e948b1b0edf922f9011b9e11887d70adb00b26f272b9e76a38f3099084d9c + E = d7e6df5d755284929b986cd9b61c9c2c8843f24c711fbdbae1a468edcae159400943725570726cdc92b3ea94f9f206729516fdda83e31d815b0c7720e7598a91d992273e3bd8ac413b441d8f1dfe5aa7c3bf3ef573adc38292676217467731e6cf440a59611b8110af88d3e62f60209b513b01fbb69a097458ad02096b5e38f0 + M = e4e784aa1fa88625a43ba0185a153a929663920be7fe674a4d33c943d3b898cff051482e7050a070cede53be5e89f31515772c7aea637576f99f82708f89d9e244f6ad3a24a02cbe5c0ff7bcf2dad5491f53db7c3f2698a7c41b44f086652f17bb05fe4c5c0a92433c34086b49d7e1825b28bab6c5a9bd0bc95b53d659afa0d7 + ++# The following inputs trigger an edge case between Montgomery reduction and the ++# "almost" reduction variant from https://eprint.iacr.org/2011/239 ++ModExp = 00 ++A = 19c7bc9b97c6083cd7b8d1cd001452c9b67983247169c6532047eb7fc8933014dbf69fee7a358769f1429802c8ea89d4f9ca6ba6f368fbdb1fa5717b4a00 ++E = bbc7e09147408571050e8d0c634682c5863b7e8a573626648902cff12e590c74f5a23ecce39732266bc15b8afbd6c48a48c83fbdc33947515cc0b6e4fb98ae2cd730e58f951fec8be7e2e3c74f4506c7fd7e29bdb28675fe8a59789ab1148e931a2ebd2d36f78bc241682a3d8083d8ff538858cd240c5a693936e5a391dc9d77118062a3f868c058440a4192267faaaba91112f45eee5842060febbf9353a6d3e7f7996573209136a5506062ea23d74067f08c613f3ff74bade25f8c3368e6dba84eae672eac11be1137fc514924fcab8c82e46d092bd047dcbadaa48c67a096ec1a04f392a8511e6acbad9954949b703e71ff837337b594055ae6f3c0fc154447a687c9ac8a2cdfd64a2e680c6ff21254735af7f5eb6b43f0bce86bda55a04143a991711081435ed4f4a89b23fc3a588022b7a8543db4bf5c8ac93603367c750ff2191f59a716340fab49bb7544759c8d846465eec1438e76395f73e7b5e945f31f1b87fefa854a0d208846eaab5fa27144fd039911608bab0eaee80f1d3553dfa2d9ba95268479b97a059613660df5ad79796e0b272244aca90ccc13449ec15c206eeed7b60405a4c5cfdf5da5d136c27fa9385d810ad198dfe794ffce9955e10520efea1e2eb794e379401b9affd863b9566ce941c4726755574a1b1946acf0090bfb93f37dd55f524485bbba7fa84b53addfde01ae1de9c57fe50d4b708dd0fa45d02af398b3d05c6d17f84c11e9aacdbe0b146cad6ddbd877731e26a17f3ebed459560d12ed7a6abc2ea6fe922e69d2622ef11b6b245b9ba8f0940faaa671a4beb727be5393a94dafaeff7221b29183e7418f4c5bb95a6a586c93dbc8ce0236d9dbe26c40513611b4141fed66599adbfb20fc30e09a4815e4159f65a6708f34584a7a77b3843941cd61a6917dcc3d07a3dfb5a2cb108bacea7e782f2111b4d22ecaaeff469ecd0da371df1ac5e9bf6df6ccba2d3a9f393d597499eaca2c206bfb81c3426c5fe45bcf16e38aecd246a319a1f37041c638b75a4839517e43a6d01bee7d85eaeedbce13cd15699d3ee42c7414cfed576590e4fb6ddb6edd3e1957efaf039bfe8b9dc75869b1f93abff15cae8b234161070fa3542303c2ed35ca66083d0ac299b81182317a2a3985269602b1fa1e822fcbda48e686d80b273f06b0a702ca7f42cbbbd2fc2b3601422c8bff6302eda3c61b293049636002649b16f3c1f0be2b6599d66493a4497cd795b10a2ab8220fafad24fa90e1bfcf39ecce337e705695c7a224bf9f445a287d6aab221341659ca4be7861f6ac4c9d33dac811e6 ++M = 519b6e57781d40d897ec0c1b648d195526726b295438c9a70928ac25979563d72db91c8c42298a33b572edecdf40904c68a23337aa5341b56e92b0da5041 ++ ++# To fully exercise BN_mod_exp_mont_consttime codepaths, we generate inputs at ++# different bitwidths. rsaz-avx2.pl only runs at 1024-bit moduli, and ++# x86_64-mont5.pl unrolls 8 64-bit words at a time, so we want to capture both ++# multiples of 512- and non-multiples. Also include moduli that are not quite a ++# full word. ++# 512-bit ++ModExp = 00 ++A = 8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e ++E = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ++M = 8f42c9e9e351ba9b32ab0cf69da43f4acf7028d19cff6e5059ea0e3fcc97c97f36a31470044737d4c0c933ac441ecb29e32c81401523afdac7de9c3fd8493c97 ++ ++# 1024-bit ++# TODO(davidben): This test breaks the RSAZ implementation. Fix it and enable ++# this test. ++# ModExp = 00 ++# A = 800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002f ++# E = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ++# M = 9da8dc26fdf4d2e49833b240ee552beb7a6e251caa91bfb5d6cafaf8ed9461877fda8f6ac299036d35806bc1ae7872e54eaac1ec6bee6d02c6621a9cf8883b3abc33c49b3e601203e0e86ef8f0562412cc689ee2670704583909ca6d7774c9f9f9f4d77d37fedef9cb51d207cb629ec02fa03b526fd6594bfa8f2da71238a0b7 ++ ++# 1025-bit ++ModExp = 00 ++A = 010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011 ++E = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ++M = 010223abfdda02e84e11cec8ee7fc784fa135733935f7b9054bb70f1f06d234d76dcf3beed55c7f39e955dc1fef2b65009240fd02f7a1b27a78fc2867144bf666efb929856db9f671c356c4c67a068a70fe83c52eebda03668872fd270d0794f0771d217fb6b93b12529a944f7f0496a9158757c55b8ee14f803f1d2d887e2f561 ++ ++# 1088-bit ++ModExp = 00 ++A = 8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003d ++E = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ++M = e91f6d748773cb212a23aa348125615123b1800c9ea222c9374c757702ae4140fa333790ed8f6bf60a1d7dda65c2767cc5f33e32e333d19fbfb5a2b85795757c9ca070268763a618e9d33873d28a89bf88acd209efbb15b80cd33b92a6b3a682e1c91782fc24fb86ddff4f809219c977b54b99359094bbcc51dfe17b992ab24b74a17950ad754281 ++ ++# 1472-bit ++ModExp = 00 ++A = 8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001d ++E = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ++M = a8770362f4bfe4fc1ab0e52705c11a9b6ba235d5a5f22197c2d68e27ed18426ede3316af706aa79bcf943dbd51459eb15ae1f9386216b3f3a847f94440a65b97659bc5ba2adb67173714ecaa886c0b926d7a64ea45576f9d2171784ce7e801724d5b0abfd93357d538ea7ad3ad89a74f4660bdb66dfb5f684dcf00402e3cdf0ab58afd867c943c8f47b80268a789456aa7c50a619dd2f9f5e3f74b5d810f0f8dadbf4ad5b917cdcb156c4c132611c8b3b035118a9e03551f ++ ++# 1536-bit ++ModExp = 00 ++A = 800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002 ++E = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ++M = 878cd000778f927b2f1a4b8bac86efd282079a7ac0d25e09ffd2f72fbc282e65e233929d2457c7b1d63c56fb706cdfa04fb87e654c578c98d7cf59c2293dc5641086b68db4867105981daaf147a0ee91f6932ef064deae4142c19e58d50c0686f0eaf778be72450f89a98b4680bbc5ffab942195e44dd20616150fd1deca058068ca31ab2f861e99082588f17a2025bf5e536150142fca3187a259c791fc721430f24d7e338f8dc02e693a7e694d42775e80f7f7c03600b6ae86b4aba2b0e991 ++ ++# 2048-bit ++ModExp = 00 ++A = 8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f ++E = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ++M = 9f40a7535c561208ecb38e17c9336d9bc8484d335901b2cd42759cf03689227f6992f10cb6b586d767fbcdf30e9d82a0eda60d2694ccd0194fa96b50b56e0cdeec1951ea9e58b07e334a7f108841a0ab28256917fecea561388807ed124a17386a7a7b501f9cbf3404247a76948d0561e48137d3f9669e36f175731796aeaf78851f7d866917f661422186a4814aa35c066b5a90b9cfc918af769a9f0bb30c12581027df64ac328a0f07dbd20adb704479f6d0f233a131828c71bab19c3c34795ea4fb68aa632c6f688e5b3b84413c9031d8dc251003a590dec0dd09bfa6109ed4570701439b6f265b84ac2170c317357b5fbe5535e2bbdd93c1aacfdaa28c85 ++ ++# 3072-bit ++ModExp = 00 ++A = 80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001d ++E = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ++M = c23dfd244a58a668d514498a705c8f8f548311b24f0f98b023d2d33632534c2ae948d6641d41fd7a29fbbd594bfc7fdd6e8162cbb3056af3075347b6fc8876458d33a9d0ffdbcdf482de0c73d1310fd8fa8f9f92dd0dbb0e2034e98a30f6c11b482f7476c5b593f673a322b1130daa4314e9074270dce1076436f0d56cf196afcbb235a9a7b3ac85b9062e85fc0e63a12c468c787019f6805f9faab64fc6a0babc80785d88740243f11366bffb40ccbe8b2bb7a99a2c8238a6f656bb0117d7b2602aa400f4d77de5f93c673f13264ca70de949454e3e3f261993c1aa427e8ef4f507af744f71f3b4aaf3c981d44cc1bfb1eb1151168762b242b740573df698e500d99612e17dc760f7b3bf7c235e39e81ad7edbe6c07dbb8b139745bb394d61cb799bcafec5de074932b0b2d74797e779ac8d81f63a2b2e9baa229dfaa7f90f34ffade1d2ad022a3407d35eb2d7477c6ae8ad100f6e95c05b4f947c1fabfb11a17add384e6b4cd3a02fd9b43f46805c6c74e366b74aa3b766be7a5fbbd67fa81 ++ ++# 4096-bit ++ModExp = 00 ++A = 8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ++E = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ++M = 8030411ecbddcb0fe4e76fd6b5bf542e8b015d1610cf96130ded12ba2cda0641bd9692080f218ea8b0d751845b519d95b843542ec8d2a07f1f93afe3189b69a4f35c983011c7f7928c3df458cc3eae85c36e6934a4b1bc0a67c8a521de336642c49e10a7ffa8d0af911aacc19e3900449161940f139220e099a150dcaf0ff96ffff6e726c1ac139969103cf6a828ac3adf0301506aa02787b4f570d5dde53a34acab8fec6fa94760abf16ee99954371ad65a6e899daab87b95811d069404991de9abe064ebbddf886e970f10d260c899dda940191a82d4c8bd36651363aff5493f4f59e700007dcadf37ebea7fcfd7600d16617ffea0d9ae659446d851d93c564e50e558f734c894d735fa273770703dab62844d9f01badf632f3d14a00f739c022c9be95f54e9cea46ec6da7cb11f4602e06962951c48204726b7f120ddbd0eb3566dc8d1e6f195a9196e96db33322d088b43aecffe9b4df182dd016aca0bd14f1c56cd1a18b89165c027029862b09ffd78e92ab614349c4fd67f49cb12cd33d0728930d0538bda57acef1365a73cc8fbac7d463b9e3c3bae0bb6224b080cdb8b5cd47d546d53111fdc22b7ff679bcfe27192920ee163b2be337d8cccc93b4de7d2d31934b9c0e97af291dcc1135b4a473bd37114eec3ba75c411887b57799d3188e7353f33a4d31735ebfc9fcfc044985148dd96da3876a5ab7ea7a404b411 + + # These test vectors satisfy (ModSqrt * ModSqrt) mod P = A mod P with P a prime. + # ModSqrt is in [0, (P-1)/2]. +-- +2.17.1 + diff --git a/backport-Backport-a-missing-bug-fix-from-master.patch b/backport-Backport-a-missing-bug-fix-from-master.patch new file mode 100644 index 0000000..cb2d259 --- /dev/null +++ b/backport-Backport-a-missing-bug-fix-from-master.patch @@ -0,0 +1,65 @@ +From 17519e2595b5ed8211a7763ff6eb2d6cf47c13cb Mon Sep 17 00:00:00 2001 +From: Bernd Edlinger +Date: Thu, 19 May 2022 15:50:28 +0200 +Subject: [PATCH] Backport a missing bug-fix from master + +This is a backport of the following commit from master: + +commit 61b0fead5e6079ca826594df5b9ca00e65883cb0 +Author: Matt Caswell +Date: Thu Nov 19 13:58:21 2020 +0000 + + Don't Overflow when printing Thawte Strong Extranet Version + + When printing human readable info on the Thawte Strong Extranet extension + the version number could overflow if the version number == LONG_MAX. This + is undefined behaviour. + + Issue found by OSSFuzz. + + Reviewed-by: Ben Kaduk + (Merged from https://github.com/openssl/openssl/pull/13452) + +Reviewed-by: Matt Caswell +Reviewed-by: Tomas Mraz +(Merged from https://github.com/openssl/openssl/pull/18347) +--- + crypto/x509v3/v3_sxnet.c | 18 +++++++++++++++--- + 1 files changed, 15 insertions(+), 3 deletions(-) + create mode 100644 fuzz/corpora/crl/4d72381f46c50eb9cabd8aa27f456962bf013b28 + +diff --git a/crypto/x509v3/v3_sxnet.c b/crypto/x509v3/v3_sxnet.c +index 89cda01be2..0648553ae3 100644 +--- a/crypto/x509v3/v3_sxnet.c ++++ b/crypto/x509v3/v3_sxnet.c +@@ -57,12 +57,24 @@ IMPLEMENT_ASN1_FUNCTIONS(SXNET) + static int sxnet_i2r(X509V3_EXT_METHOD *method, SXNET *sx, BIO *out, + int indent) + { +- long v; ++ int64_t v; + char *tmp; + SXNETID *id; + int i; +- v = ASN1_INTEGER_get(sx->version); +- BIO_printf(out, "%*sVersion: %ld (0x%lX)", indent, "", v + 1, v); ++ ++ /* ++ * Since we add 1 to the version number to display it, we don't support ++ * LONG_MAX since that would cause on overflow. ++ */ ++ if (!ASN1_INTEGER_get_int64(&v, sx->version) ++ || v >= LONG_MAX ++ || v < LONG_MIN) { ++ BIO_printf(out, "%*sVersion: ", indent, ""); ++ } else { ++ long vl = (long)v; ++ ++ BIO_printf(out, "%*sVersion: %ld (0x%lX)", indent, "", vl + 1, vl); ++ } + for (i = 0; i < sk_SXNETID_num(sx->ids); i++) { + id = sk_SXNETID_value(sx->ids, i); + tmp = i2s_ASN1_INTEGER(NULL, id->zone); +-- +2.38.1.windows.1 + diff --git a/backport-Convert-serverinfo-in-SSL_CTX_use_serverinfo-to-v2.patch b/backport-Convert-serverinfo-in-SSL_CTX_use_serverinfo-to-v2.patch new file mode 100644 index 0000000..8fd098c --- /dev/null +++ b/backport-Convert-serverinfo-in-SSL_CTX_use_serverinfo-to-v2.patch @@ -0,0 +1,376 @@ +From 6e6aad333f26694ff39aba1e59b358e3f25a9a1d Mon Sep 17 00:00:00 2001 +From: Daniel Fiala +Date: Sun, 28 Aug 2022 11:53:32 +0200 +Subject: [PATCH] Convert serverinfo in SSL_CTX_use_serverinfo() to v2. + +Fixes #18183. + +Reviewed-by: Matt Caswell +Reviewed-by: Paul Dale +Reviewed-by: Hugo Landau +(Merged from https://github.com/openssl/openssl/pull/19081) +--- + ssl/ssl_rsa.c | 81 ++++++++++++++++------ + test/sslapitest.c | 171 +++++++++++++++++++++++++++++++--------------- + 2 files changed, 177 insertions(+), 75 deletions(-) + +diff --git a/ssl/ssl_rsa.c b/ssl/ssl_rsa.c +index 6457c0c0ef..3535c95354 100644 +--- a/ssl/ssl_rsa.c ++++ b/ssl/ssl_rsa.c +@@ -727,6 +727,34 @@ static int serverinfoex_srv_parse_cb(SSL *s, unsigned int ext_type, + return 1; + } + ++static size_t extension_contextoff(unsigned int version) ++{ ++ return version == SSL_SERVERINFOV1 ? 4 : 0; ++} ++ ++static size_t extension_append_length(unsigned int version, size_t extension_length) ++{ ++ return extension_length + extension_contextoff(version); ++} ++ ++static void extension_append(unsigned int version, ++ const unsigned char *extension, ++ const size_t extension_length, ++ unsigned char *serverinfo) ++{ ++ const size_t contextoff = extension_contextoff(version); ++ ++ if (contextoff > 0) { ++ /* We know this only uses the last 2 bytes */ ++ serverinfo[0] = 0; ++ serverinfo[1] = 0; ++ serverinfo[2] = (SYNTHV1CONTEXT >> 8) & 0xff; ++ serverinfo[3] = SYNTHV1CONTEXT & 0xff; ++ } ++ ++ memcpy(serverinfo + contextoff, extension, extension_length); ++} ++ + static int serverinfo_srv_parse_cb(SSL *s, unsigned int ext_type, + const unsigned char *in, + size_t inlen, int *al, void *arg) +@@ -842,12 +870,36 @@ int SSL_CTX_use_serverinfo_ex(SSL_CTX *ctx, unsigned int version, + const unsigned char *serverinfo, + size_t serverinfo_length) + { +- unsigned char *new_serverinfo; ++ unsigned char *new_serverinfo = NULL; + + if (ctx == NULL || serverinfo == NULL || serverinfo_length == 0) { + SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_EX, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } ++ if (version == SSL_SERVERINFOV1) { ++ /* ++ * Convert serverinfo version v1 to v2 and call yourself recursively ++ * over the converted serverinfo. ++ */ ++ const size_t sinfo_length = extension_append_length(SSL_SERVERINFOV1, ++ serverinfo_length); ++ unsigned char *sinfo; ++ int ret; ++ ++ sinfo = OPENSSL_malloc(sinfo_length); ++ if (sinfo == NULL) { ++ SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_EX, ERR_R_MALLOC_FAILURE); ++ return 0; ++ } ++ ++ extension_append(SSL_SERVERINFOV1, serverinfo, serverinfo_length, sinfo); ++ ++ ret = SSL_CTX_use_serverinfo_ex(ctx, SSL_SERVERINFOV2, sinfo, ++ sinfo_length); ++ ++ OPENSSL_free(sinfo); ++ return ret; ++ } + if (!serverinfo_process_buffer(version, serverinfo, serverinfo_length, + NULL)) { + SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_EX, SSL_R_INVALID_SERVERINFO_DATA); +@@ -899,7 +951,7 @@ int SSL_CTX_use_serverinfo_file(SSL_CTX *ctx, const char *file) + char namePrefix2[] = "SERVERINFOV2 FOR "; + int ret = 0; + BIO *bin = NULL; +- size_t num_extensions = 0, contextoff = 0; ++ size_t num_extensions = 0; + + if (ctx == NULL || file == NULL) { + SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_FILE, ERR_R_PASSED_NULL_PARAMETER); +@@ -918,6 +970,7 @@ int SSL_CTX_use_serverinfo_file(SSL_CTX *ctx, const char *file) + + for (num_extensions = 0;; num_extensions++) { + unsigned int version; ++ size_t append_length; + + if (PEM_read_bio(bin, &name, &header, &extension, &extension_length) + == 0) { +@@ -962,11 +1015,6 @@ int SSL_CTX_use_serverinfo_file(SSL_CTX *ctx, const char *file) + SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_FILE, SSL_R_BAD_DATA); + goto end; + } +- /* +- * File does not have a context value so we must take account of +- * this later. +- */ +- contextoff = 4; + } else { + /* 8 byte header: 4 bytes context, 2 bytes type, 2 bytes len */ + if (extension_length < 8 +@@ -977,25 +1025,16 @@ int SSL_CTX_use_serverinfo_file(SSL_CTX *ctx, const char *file) + } + } + /* Append the decoded extension to the serverinfo buffer */ +- tmp = OPENSSL_realloc(serverinfo, serverinfo_length + extension_length +- + contextoff); ++ append_length = extension_append_length(version, extension_length); ++ tmp = OPENSSL_realloc(serverinfo, serverinfo_length + append_length); + if (tmp == NULL) { + SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_FILE, ERR_R_MALLOC_FAILURE); + goto end; + } + serverinfo = tmp; +- if (contextoff > 0) { +- unsigned char *sinfo = serverinfo + serverinfo_length; +- +- /* We know this only uses the last 2 bytes */ +- sinfo[0] = 0; +- sinfo[1] = 0; +- sinfo[2] = (SYNTHV1CONTEXT >> 8) & 0xff; +- sinfo[3] = SYNTHV1CONTEXT & 0xff; +- } +- memcpy(serverinfo + serverinfo_length + contextoff, +- extension, extension_length); +- serverinfo_length += extension_length + contextoff; ++ extension_append(version, extension, extension_length, ++ serverinfo + serverinfo_length); ++ serverinfo_length += append_length; + + OPENSSL_free(name); + name = NULL; +diff --git a/test/sslapitest.c b/test/sslapitest.c +index 7197e15cac..685c28d934 100644 +--- a/test/sslapitest.c ++++ b/test/sslapitest.c +@@ -85,20 +85,6 @@ struct sslapitest_log_counts { + }; + + +-static unsigned char serverinfov1[] = { +- 0xff, 0xff, /* Dummy extension type */ +- 0x00, 0x01, /* Extension length is 1 byte */ +- 0xff /* Dummy extension data */ +-}; +- +-static unsigned char serverinfov2[] = { +- 0x00, 0x00, 0x00, +- (unsigned char)(SSL_EXT_CLIENT_HELLO & 0xff), /* Dummy context - 4 bytes */ +- 0xff, 0xff, /* Dummy extension type */ +- 0x00, 0x01, /* Extension length is 1 byte */ +- 0xff /* Dummy extension data */ +-}; +- + static int hostname_cb(SSL *s, int *al, void *arg) + { + const char *hostname = SSL_get_servername(s, TLSEXT_NAMETYPE_host_name); +@@ -4349,62 +4335,137 @@ end: + return testresult; + } + +-/* +- * Test loading of serverinfo data in various formats. test_sslmessages actually +- * tests to make sure the extensions appear in the handshake +- */ +-static int test_serverinfo(int tst) ++#if !defined(OPENSSL_NO_TLS1_2) && !defined(OPENSSL_NO_TLS1_3) ++ ++#define SYNTHV1CONTEXT (SSL_EXT_TLS1_2_AND_BELOW_ONLY \ ++ | SSL_EXT_CLIENT_HELLO \ ++ | SSL_EXT_TLS1_2_SERVER_HELLO \ ++ | SSL_EXT_IGNORE_ON_RESUMPTION) ++ ++#define TLS13CONTEXT (SSL_EXT_TLS1_3_CERTIFICATE \ ++ | SSL_EXT_TLS1_2_SERVER_HELLO \ ++ | SSL_EXT_CLIENT_HELLO) ++ ++#define SERVERINFO_CUSTOM \ ++ 0x00, (char)TLSEXT_TYPE_signed_certificate_timestamp, \ ++ 0x00, 0x03, \ ++ 0x04, 0x05, 0x06 \ ++ ++static const unsigned char serverinfo_custom_tls13[] = { ++ 0x00, 0x00, (TLS13CONTEXT >> 8) & 0xff, TLS13CONTEXT & 0xff, ++ SERVERINFO_CUSTOM ++}; ++static const unsigned char serverinfo_custom_v2[] = { ++ 0x00, 0x00, (SYNTHV1CONTEXT >> 8) & 0xff, SYNTHV1CONTEXT & 0xff, ++ SERVERINFO_CUSTOM ++}; ++static const unsigned char serverinfo_custom_v1[] = { ++ SERVERINFO_CUSTOM ++}; ++static const size_t serverinfo_custom_tls13_len = sizeof(serverinfo_custom_tls13); ++static const size_t serverinfo_custom_v2_len = sizeof(serverinfo_custom_v2); ++static const size_t serverinfo_custom_v1_len = sizeof(serverinfo_custom_v1); ++ ++static int serverinfo_custom_parse_cb(SSL *s, unsigned int ext_type, ++ unsigned int context, ++ const unsigned char *in, ++ size_t inlen, X509 *x, ++ size_t chainidx, int *al, ++ void *parse_arg) + { +- unsigned int version; +- unsigned char *sibuf; +- size_t sibuflen; +- int ret, expected, testresult = 0; +- SSL_CTX *ctx; ++ const size_t len = serverinfo_custom_v1_len; ++ const unsigned char *si = &serverinfo_custom_v1[len - 3]; ++ int *p_cb_result = (int*)parse_arg; ++ *p_cb_result = TEST_mem_eq(in, inlen, si, 3); ++ return 1; ++} + +- ctx = SSL_CTX_new(TLS_method()); +- if (!TEST_ptr(ctx)) +- goto end; ++static int test_serverinfo_custom(const int idx) ++{ ++ SSL_CTX *sctx = NULL, *cctx = NULL; ++ SSL *clientssl = NULL, *serverssl = NULL; ++ int testresult = 0; ++ int cb_result = 0; + +- if ((tst & 0x01) == 0x01) +- version = SSL_SERVERINFOV2; +- else +- version = SSL_SERVERINFOV1; ++ /* ++ * Following variables are set in the switch statement ++ * according to the test iteration. ++ * Default values do not make much sense: test would fail with them. ++ */ ++ int serverinfo_version = 0; ++ int protocol_version = 0; ++ unsigned int extension_context = 0; ++ const unsigned char *si = NULL; ++ size_t si_len = 0; + +- if ((tst & 0x02) == 0x02) { +- sibuf = serverinfov2; +- sibuflen = sizeof(serverinfov2); +- expected = (version == SSL_SERVERINFOV2); +- } else { +- sibuf = serverinfov1; +- sibuflen = sizeof(serverinfov1); +- expected = (version == SSL_SERVERINFOV1); ++ const int call_use_serverinfo_ex = idx > 0; ++ switch (idx) { ++ case 0: /* FALLTHROUGH */ ++ case 1: ++ serverinfo_version = SSL_SERVERINFOV1; ++ protocol_version = TLS1_2_VERSION; ++ extension_context = SYNTHV1CONTEXT; ++ si = serverinfo_custom_v1; ++ si_len = serverinfo_custom_v1_len; ++ break; ++ case 2: ++ serverinfo_version = SSL_SERVERINFOV2; ++ protocol_version = TLS1_2_VERSION; ++ extension_context = SYNTHV1CONTEXT; ++ si = serverinfo_custom_v2; ++ si_len = serverinfo_custom_v2_len; ++ break; ++ case 3: ++ serverinfo_version = SSL_SERVERINFOV2; ++ protocol_version = TLS1_3_VERSION; ++ extension_context = TLS13CONTEXT; ++ si = serverinfo_custom_tls13; ++ si_len = serverinfo_custom_tls13_len; ++ break; + } + +- if ((tst & 0x04) == 0x04) { +- ret = SSL_CTX_use_serverinfo_ex(ctx, version, sibuf, sibuflen); +- } else { +- ret = SSL_CTX_use_serverinfo(ctx, sibuf, sibuflen); ++ if (!TEST_true(create_ssl_ctx_pair(TLS_method(), ++ TLS_method(), ++ protocol_version, ++ protocol_version, ++ &sctx, &cctx, cert, privkey))) ++ goto end; + +- /* +- * The version variable is irrelevant in this case - it's what is in the +- * buffer that matters +- */ +- if ((tst & 0x02) == 0x02) +- expected = 0; +- else +- expected = 1; ++ if (call_use_serverinfo_ex) { ++ if (!TEST_true(SSL_CTX_use_serverinfo_ex(sctx, serverinfo_version, ++ si, si_len))) ++ goto end; ++ } else { ++ if (!TEST_true(SSL_CTX_use_serverinfo(sctx, si, si_len))) ++ goto end; + } + +- if (!TEST_true(ret == expected)) ++ if (!TEST_true(SSL_CTX_add_custom_ext(cctx, TLSEXT_TYPE_signed_certificate_timestamp, ++ extension_context, ++ NULL, NULL, NULL, ++ serverinfo_custom_parse_cb, ++ &cb_result)) ++ || !TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl, ++ NULL, NULL)) ++ || !TEST_true(create_ssl_connection(serverssl, clientssl, ++ SSL_ERROR_NONE)) ++ || !TEST_int_eq(SSL_do_handshake(clientssl), 1)) ++ goto end; ++ ++ if (!TEST_true(cb_result)) + goto end; + + testresult = 1; + + end: +- SSL_CTX_free(ctx); ++ SSL_free(serverssl); ++ SSL_free(clientssl); ++ SSL_CTX_free(sctx); ++ SSL_CTX_free(cctx); + + return testresult; + } ++#endif + + /* + * Test that SSL_export_keying_material() produces expected results. There are +@@ -7175,7 +7236,6 @@ int setup_tests(void) + #else + ADD_ALL_TESTS(test_custom_exts, 3); + #endif +- ADD_ALL_TESTS(test_serverinfo, 8); + ADD_ALL_TESTS(test_export_key_mat, 6); + #ifndef OPENSSL_NO_TLS1_3 + ADD_ALL_TESTS(test_export_key_mat_early, 3); +@@ -7207,6 +7267,9 @@ int setup_tests(void) + #endif + ADD_TEST(test_set_alpn); + ADD_TEST(test_inherit_verify_param); ++#if !defined(OPENSSL_NO_TLS1_2) && !defined(OPENSSL_NO_TLS1_3) ++ ADD_ALL_TESTS(test_serverinfo_custom, 4); ++#endif + return 1; + } + +-- +2.17.1 + diff --git a/backport-Coverity-1508506-misuse-of-time_t.patch b/backport-Coverity-1508506-misuse-of-time_t.patch new file mode 100644 index 0000000..e95f6fd --- /dev/null +++ b/backport-Coverity-1508506-misuse-of-time_t.patch @@ -0,0 +1,177 @@ +From 07ecb790b02c0e8781ae591e7efb2a4f93177354 Mon Sep 17 00:00:00 2001 +From: Pauli +Date: Tue, 16 Aug 2022 11:05:02 +1000 +Subject: [PATCH] Coverity 1508506: misuse of time_t + +Fixes a bug in the cookie code which would have caused problems for ten +minutes before and after the lower 32 bits of time_t rolled over. + +Reviewed-by: Ben Kaduk +Reviewed-by: Matt Caswell +(Merged from https://github.com/openssl/openssl/pull/19022) +--- + ssl/packet.c | 6 +++--- + ssl/packet_local.h | 37 +++++++++++++++++++++++++++++++++++- + ssl/statem/extensions_srvr.c | 14 +++++++------- + 3 files changed, 46 insertions(+), 11 deletions(-) + +diff --git a/ssl/packet.c b/ssl/packet.c +index 1ddde969f3..691a82b706 100644 +--- a/ssl/packet.c ++++ b/ssl/packet.c +@@ -161,7 +161,7 @@ int WPACKET_set_flags(WPACKET *pkt, unsigned int flags) + } + + /* Store the |value| of length |len| at location |data| */ +-static int put_value(unsigned char *data, size_t value, size_t len) ++static int put_value(unsigned char *data, uint64_t value, size_t len) + { + for (data += len - 1; len > 0; len--) { + *data = (unsigned char)(value & 0xff); +@@ -306,12 +306,12 @@ int WPACKET_start_sub_packet(WPACKET *pkt) + return WPACKET_start_sub_packet_len__(pkt, 0); + } + +-int WPACKET_put_bytes__(WPACKET *pkt, unsigned int val, size_t size) ++int WPACKET_put_bytes__(WPACKET *pkt, uint64_t val, size_t size) + { + unsigned char *data; + + /* Internal API, so should not fail */ +- if (!ossl_assert(size <= sizeof(unsigned int)) ++ if (!ossl_assert(size <= sizeof(uint64_t)) + || !WPACKET_allocate_bytes(pkt, size, &data) + || !put_value(data, val, size)) + return 0; +diff --git a/ssl/packet_local.h b/ssl/packet_local.h +index 1b6c2fb9bc..e93680d8bb 100644 +--- a/ssl/packet_local.h ++++ b/ssl/packet_local.h +@@ -227,6 +227,28 @@ __owur static ossl_inline int PACKET_peek_net_4(const PACKET *pkt, + return 1; + } + ++/* ++ * Peek ahead at 8 bytes in network order from |pkt| and store the value in ++ * |*data| ++ */ ++__owur static ossl_inline int PACKET_peek_net_8(const PACKET *pkt, ++ uint64_t *data) ++{ ++ if (PACKET_remaining(pkt) < 8) ++ return 0; ++ ++ *data = ((uint64_t)(*pkt->curr)) << 56; ++ *data |= ((uint64_t)(*(pkt->curr + 1))) << 48; ++ *data |= ((uint64_t)(*(pkt->curr + 2))) << 40; ++ *data |= ((uint64_t)(*(pkt->curr + 3))) << 32; ++ *data |= ((uint64_t)(*(pkt->curr + 4))) << 24; ++ *data |= ((uint64_t)(*(pkt->curr + 5))) << 16; ++ *data |= ((uint64_t)(*(pkt->curr + 6))) << 8; ++ *data |= *(pkt->curr + 7); ++ ++ return 1; ++} ++ + /* Equivalent of n2l */ + /* Get 4 bytes in network order from |pkt| and store the value in |*data| */ + __owur static ossl_inline int PACKET_get_net_4(PACKET *pkt, unsigned long *data) +@@ -250,6 +272,17 @@ __owur static ossl_inline int PACKET_get_net_4_len(PACKET *pkt, size_t *data) + + return ret; + } ++ ++/* Get 8 bytes in network order from |pkt| and store the value in |*data| */ ++__owur static ossl_inline int PACKET_get_net_8(PACKET *pkt, uint64_t *data) ++{ ++ if (!PACKET_peek_net_8(pkt, data)) ++ return 0; ++ ++ packet_forward(pkt, 8); ++ ++ return 1; ++} + + /* Peek ahead at 1 byte from |pkt| and store the value in |*data| */ + __owur static ossl_inline int PACKET_peek_1(const PACKET *pkt, +@@ -808,7 +841,7 @@ int WPACKET_sub_reserve_bytes__(WPACKET *pkt, size_t len, + * 1 byte will fail. Don't call this directly. Use the convenience macros below + * instead. + */ +-int WPACKET_put_bytes__(WPACKET *pkt, unsigned int val, size_t bytes); ++int WPACKET_put_bytes__(WPACKET *pkt, uint64_t val, size_t bytes); + + /* + * Convenience macros for calling WPACKET_put_bytes with different +@@ -822,6 +855,8 @@ int WPACKET_put_bytes__(WPACKET *pkt, unsigned int val, size_t bytes); + WPACKET_put_bytes__((pkt), (val), 3) + #define WPACKET_put_bytes_u32(pkt, val) \ + WPACKET_put_bytes__((pkt), (val), 4) ++#define WPACKET_put_bytes_u64(pkt, val) \ ++ WPACKET_put_bytes__((pkt), (val), 8) + + /* Set a maximum size that we will not allow the WPACKET to grow beyond */ + int WPACKET_set_max_size(WPACKET *pkt, size_t maxsize); +diff --git a/ssl/statem/extensions_srvr.c b/ssl/statem/extensions_srvr.c +index f110053273..93a9b675e6 100644 +--- a/ssl/statem/extensions_srvr.c ++++ b/ssl/statem/extensions_srvr.c +@@ -12,16 +12,16 @@ + #include "statem_local.h" + #include "internal/cryptlib.h" + +-#define COOKIE_STATE_FORMAT_VERSION 0 ++#define COOKIE_STATE_FORMAT_VERSION 1 + + /* + * 2 bytes for packet length, 2 bytes for format version, 2 bytes for + * protocol version, 2 bytes for group id, 2 bytes for cipher id, 1 byte for +- * key_share present flag, 4 bytes for timestamp, 2 bytes for the hashlen, ++ * key_share present flag, 8 bytes for timestamp, 2 bytes for the hashlen, + * EVP_MAX_MD_SIZE for transcript hash, 1 byte for app cookie length, app cookie + * length bytes, SHA256_DIGEST_LENGTH bytes for the HMAC of the whole thing. + */ +-#define MAX_COOKIE_SIZE (2 + 2 + 2 + 2 + 2 + 1 + 4 + 2 + EVP_MAX_MD_SIZE + 1 \ ++#define MAX_COOKIE_SIZE (2 + 2 + 2 + 2 + 2 + 1 + 8 + 2 + EVP_MAX_MD_SIZE + 1 \ + + SSL_COOKIE_LENGTH + SHA256_DIGEST_LENGTH) + + /* +@@ -741,7 +741,7 @@ int tls_parse_ctos_cookie(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + unsigned char hmac[SHA256_DIGEST_LENGTH]; + unsigned char hrr[MAX_HRR_SIZE]; + size_t rawlen, hmaclen, hrrlen, ciphlen; +- unsigned long tm, now; ++ uint64_t tm, now; + + /* Ignore any cookie if we're not set up to verify it */ + if (s->ctx->verify_stateless_cookie_cb == NULL +@@ -851,7 +851,7 @@ int tls_parse_ctos_cookie(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + } + + if (!PACKET_get_1(&cookie, &key_share) +- || !PACKET_get_net_4(&cookie, &tm) ++ || !PACKET_get_net_8(&cookie, &tm) + || !PACKET_get_length_prefixed_2(&cookie, &chhash) + || !PACKET_get_length_prefixed_1(&cookie, &appcookie) + || PACKET_remaining(&cookie) != SHA256_DIGEST_LENGTH) { +@@ -861,7 +861,7 @@ int tls_parse_ctos_cookie(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + } + + /* We tolerate a cookie age of up to 10 minutes (= 60 * 10 seconds) */ +- now = (unsigned long)time(NULL); ++ now = time(NULL); + if (tm > now || (now - tm) > 600) { + /* Cookie is stale. Ignore it */ + return 1; +@@ -1799,7 +1799,7 @@ EXT_RETURN tls_construct_stoc_cookie(SSL *s, WPACKET *pkt, unsigned int context, + &ciphlen) + /* Is there a key_share extension present in this HRR? */ + || !WPACKET_put_bytes_u8(pkt, s->s3->peer_tmp == NULL) +- || !WPACKET_put_bytes_u32(pkt, (unsigned int)time(NULL)) ++ || !WPACKET_put_bytes_u64(pkt, time(NULL)) + || !WPACKET_start_sub_packet_u16(pkt) + || !WPACKET_reserve_bytes(pkt, EVP_MAX_MD_SIZE, &hashval1)) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_COOKIE, +-- +2.36.1 + diff --git a/backport-Coverity-1508534-1508540-misuses-of-time_t.patch b/backport-Coverity-1508534-1508540-misuses-of-time_t.patch new file mode 100644 index 0000000..22cd21f --- /dev/null +++ b/backport-Coverity-1508534-1508540-misuses-of-time_t.patch @@ -0,0 +1,67 @@ +From 552603edfed18f30466277d29b70939390fea65b Mon Sep 17 00:00:00 2001 +From: Pauli +Date: Tue, 16 Aug 2022 11:05:02 +1000 +Subject: [PATCH] Coverity 1508534 & 1508540: misuses of time_t + +Avoid problems when the lower 32 bits of time_t roll over by delaying +the cast to integer until after the time delta has been computed. + +Reviewed-by: Ben Kaduk +Reviewed-by: Matt Caswell +(Merged from https://github.com/openssl/openssl/pull/19004) + +(cherry picked from commit a6cadcbdc3b4f3fbd0fd228e41177f0661b68264) +--- + ssl/statem/extensions_clnt.c | 5 ++--- + ssl/statem/extensions_srvr.c | 5 ++--- + 2 files changed, 4 insertions(+), 6 deletions(-) + +diff --git a/ssl/statem/extensions_clnt.c b/ssl/statem/extensions_clnt.c +index b6f72d685c..1cbaefa9f1 100644 +--- a/ssl/statem/extensions_clnt.c ++++ b/ssl/statem/extensions_clnt.c +@@ -1002,7 +1002,7 @@ EXT_RETURN tls_construct_ctos_psk(SSL *s, WPACKET *pkt, unsigned int context, + X509 *x, size_t chainidx) + { + #ifndef OPENSSL_NO_TLS1_3 +- uint32_t now, agesec, agems = 0; ++ uint32_t agesec, agems = 0; + size_t reshashsize = 0, pskhashsize = 0, binderoffset, msglen; + unsigned char *resbinder = NULL, *pskbinder = NULL, *msgstart = NULL; + const EVP_MD *handmd = NULL, *mdres = NULL, *mdpsk = NULL; +@@ -1059,8 +1059,7 @@ EXT_RETURN tls_construct_ctos_psk(SSL *s, WPACKET *pkt, unsigned int context, + * this in multiple places in the code, so portability shouldn't be an + * issue. + */ +- now = (uint32_t)time(NULL); +- agesec = now - (uint32_t)s->session->time; ++ agesec = (uint32_t)(time(NULL) - s->session->time); + /* + * We calculate the age in seconds but the server may work in ms. Due to + * rounding errors we could overestimate the age by up to 1s. It is +diff --git a/ssl/statem/extensions_srvr.c b/ssl/statem/extensions_srvr.c +index 04f64f8106..f110053273 100644 +--- a/ssl/statem/extensions_srvr.c ++++ b/ssl/statem/extensions_srvr.c +@@ -1167,7 +1167,7 @@ int tls_parse_ctos_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + s->ext.early_data_ok = 1; + s->ext.ticket_expected = 1; + } else { +- uint32_t ticket_age = 0, now, agesec, agems; ++ uint32_t ticket_age = 0, agesec, agems; + int ret; + + /* +@@ -1209,8 +1209,7 @@ int tls_parse_ctos_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x, + } + + ticket_age = (uint32_t)ticket_agel; +- now = (uint32_t)time(NULL); +- agesec = now - (uint32_t)sess->time; ++ agesec = (uint32_t)(time(NULL) - sess->time); + agems = agesec * (uint32_t)1000; + ticket_age -= sess->ext.tick_age_add; + +-- +2.17.1 + diff --git a/backport-Ensure-our-buffer-allocation-allows-for-the-Explicit.patch b/backport-Ensure-our-buffer-allocation-allows-for-the-Explicit.patch new file mode 100644 index 0000000..69c5c17 --- /dev/null +++ b/backport-Ensure-our-buffer-allocation-allows-for-the-Explicit.patch @@ -0,0 +1,41 @@ +From 4b5ec7c560717ac90b4b05b123e6fe8ab9e20b41 Mon Sep 17 00:00:00 2001 +From: Matt Caswell +Date: Thu, 19 Jan 2023 11:59:44 +0000 +Subject: [PATCH] Ensure our buffer allocation allows for the Explicit IV + +Some ciphers/protocol versions have an explicit IV. We need to make sure we +have sufficient room for it in the underlying buffer. + +Reviewed-by: Paul Dale +Reviewed-by: Tomas Mraz +Reviewed-by: Hugo Landau +(Merged from https://github.com/openssl/openssl/pull/20087) +--- + ssl/record/ssl3_buffer.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/ssl/record/ssl3_buffer.c b/ssl/record/ssl3_buffer.c +index b9ba25e0c3..5f40046f57 100644 +--- a/ssl/record/ssl3_buffer.c ++++ b/ssl/record/ssl3_buffer.c +@@ -97,11 +97,16 @@ int ssl3_setup_write_buffer(SSL *s, size_t numwpipes, size_t len) + #endif + + len = ssl_get_max_send_fragment(s) +- + SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD + headerlen + align; ++ + SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD + headerlen + align ++ + SSL_RT_MAX_CIPHER_BLOCK_SIZE /* Explicit IV allowance */; + #ifndef OPENSSL_NO_COMP + if (ssl_allow_compression(s)) + len += SSL3_RT_MAX_COMPRESSED_OVERHEAD; + #endif ++ /* ++ * We don't need to add an allowance for eivlen here since empty ++ * fragments only occur when we don't have an explicit IV ++ */ + if (!(s->options & SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS)) + len += headerlen + align + SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD; + } +-- +2.36.1 + diff --git a/backport-Fix-BIO_f_asn1-to-properly-report-some-errors.patch b/backport-Fix-BIO_f_asn1-to-properly-report-some-errors.patch new file mode 100644 index 0000000..e0be7d9 --- /dev/null +++ b/backport-Fix-BIO_f_asn1-to-properly-report-some-errors.patch @@ -0,0 +1,41 @@ +From e913b911e04a6b276deb7d7553694ae2c1a563cc Mon Sep 17 00:00:00 2001 +From: Matt Caswell +Date: Tue, 6 Dec 2022 14:35:53 +0000 +Subject: [PATCH] Fix BIO_f_asn1() to properly report some errors + +Some things that may go wrong in asn1_bio_write() are serious errors +that should be reported as -1, rather than 0 (which just means "we wrote +no data"). + +Reviewed-by: Hugo Landau +Reviewed-by: Tomas Mraz +(Merged from https://github.com/openssl/openssl/pull/19920) +--- + crypto/asn1/bio_asn1.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/crypto/asn1/bio_asn1.c b/crypto/asn1/bio_asn1.c +index 914d77c866..17b0d1aa6c 100644 +--- a/crypto/asn1/bio_asn1.c ++++ b/crypto/asn1/bio_asn1.c +@@ -172,7 +172,7 @@ static int asn1_bio_write(BIO *b, const char *in, int inl) + case ASN1_STATE_START: + if (!asn1_bio_setup_ex(b, ctx, ctx->prefix, + ASN1_STATE_PRE_COPY, ASN1_STATE_HEADER)) +- return 0; ++ return -1; + break; + + /* Copy any pre data first */ +@@ -189,7 +189,7 @@ static int asn1_bio_write(BIO *b, const char *in, int inl) + case ASN1_STATE_HEADER: + ctx->buflen = ASN1_object_size(0, inl, ctx->asn1_tag) - inl; + if (!ossl_assert(ctx->buflen <= ctx->bufsize)) +- return 0; ++ return -1; + p = ctx->buf; + ASN1_put_object(&p, 0, inl, ctx->asn1_tag, ctx->asn1_class); + ctx->copylen = inl; +-- +2.36.1 + diff --git a/backport-Fix-BIO_f_cipher-flushing.patch b/backport-Fix-BIO_f_cipher-flushing.patch new file mode 100644 index 0000000..8b83dd2 --- /dev/null +++ b/backport-Fix-BIO_f_cipher-flushing.patch @@ -0,0 +1,54 @@ +From 6446cb444c2a4fd8a12ccafe9329b1b1b268460d Mon Sep 17 00:00:00 2001 +From: Matt Caswell +Date: Tue, 6 Dec 2022 14:18:53 +0000 +Subject: [PATCH] Fix BIO_f_cipher() flushing + +If an error occurs during a flush on a BIO_f_cipher() then in some cases +we could get into an infinite loop. We add a check to make sure we are +making progress during flush and exit if not. + +This issue was reported by Octavio Galland who also demonstrated an +infinite loop in CMS encryption as a result of this bug. + +The security team has assessed this issue as not a CVE. This occurs on +*encryption* only which is typically processing trusted data. We are not +aware of a way to trigger this with untrusted data. + +Reviewed-by: Hugo Landau +Reviewed-by: Tomas Mraz +(Merged from https://github.com/openssl/openssl/pull/19920) +--- + crypto/evp/bio_enc.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/crypto/evp/bio_enc.c b/crypto/evp/bio_enc.c +index 6639061eae..9afce7c084 100644 +--- a/crypto/evp/bio_enc.c ++++ b/crypto/evp/bio_enc.c +@@ -299,6 +299,7 @@ static long enc_ctrl(BIO *b, int cmd, long num, void *ptr) + int i; + EVP_CIPHER_CTX **c_ctx; + BIO *next; ++ int pend; + + ctx = BIO_get_data(b); + next = BIO_next(b); +@@ -334,8 +335,14 @@ static long enc_ctrl(BIO *b, int cmd, long num, void *ptr) + /* do a final write */ + again: + while (ctx->buf_len != ctx->buf_off) { ++ pend = ctx->buf_len - ctx->buf_off; + i = enc_write(b, NULL, 0); +- if (i < 0) ++ /* ++ * i should never be > 0 here because we didn't ask to write any ++ * new data. We stop if we get an error or we failed to make any ++ * progress writing pending data. ++ */ ++ if (i < 0 || (ctx->buf_len - ctx->buf_off) == pend) + return i; + } + +-- +2.36.1 + diff --git a/backport-Fix-EC_KEY_set_private_key-priv_key-regression.patch b/backport-Fix-EC_KEY_set_private_key-priv_key-regression.patch new file mode 100644 index 0000000..a0354a9 --- /dev/null +++ b/backport-Fix-EC_KEY_set_private_key-priv_key-regression.patch @@ -0,0 +1,42 @@ +From 143d7d4c791df8b9051356be51d9f77bc241fe4c Mon Sep 17 00:00:00 2001 +From: Roberto Hueso Gomez +Date: Tue, 26 Jul 2022 20:41:02 +0200 +Subject: [PATCH] Fix EC_KEY_set_private_key() priv_key regression + +This allows to set EC_KEY's private key to NULL and fixes regression +issue following OTC guideline in +https://github.com/openssl/openssl/issues/18744#issuecomment-1195175696 + +Fixes #18744. + +Reviewed-by: Nicola Tuveri +Reviewed-by: Matt Caswell +(Merged from https://github.com/openssl/openssl/pull/18874) +--- + crypto/ec/ec_key.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/crypto/ec/ec_key.c b/crypto/ec/ec_key.c +index 3017f0936c..63799002bc 100644 +--- a/crypto/ec/ec_key.c ++++ b/crypto/ec/ec_key.c +@@ -443,6 +443,16 @@ int EC_KEY_set_private_key(EC_KEY *key, const BIGNUM *priv_key) + && key->meth->set_private(key, priv_key) == 0) + return 0; + ++ /* ++ * Return `0` to comply with legacy behavior for this function, see ++ * https://github.com/openssl/openssl/issues/18744#issuecomment-1195175696 ++ */ ++ if (priv_key == NULL) { ++ BN_clear_free(key->priv_key); ++ key->priv_key = NULL; ++ return 0; /* intentional for legacy compatibility */ ++ } ++ + /* + * We should never leak the bit length of the secret scalar in the key, + * so we always set the `BN_FLG_CONSTTIME` flag on the internal `BIGNUM` +-- +2.17.1 + diff --git a/backport-Fix-SMIME_crlf_copy-to-properly-report-an-error.patch b/backport-Fix-SMIME_crlf_copy-to-properly-report-an-error.patch new file mode 100644 index 0000000..a8a21b4 --- /dev/null +++ b/backport-Fix-SMIME_crlf_copy-to-properly-report-an-error.patch @@ -0,0 +1,45 @@ +From 1354191dac44f9ac04c38fd9fb56287f00039b82 Mon Sep 17 00:00:00 2001 +From: Matt Caswell +Date: Tue, 6 Dec 2022 14:21:23 +0000 +Subject: [PATCH] Fix SMIME_crlf_copy() to properly report an error + +If the BIO unexpectedly fails to flush then SMIME_crlf_copy() was not +correctly reporting the error. We modify it to properly propagate the +error condition. + +Reviewed-by: Hugo Landau +Reviewed-by: Tomas Mraz +(Merged from https://github.com/openssl/openssl/pull/19920) +--- + crypto/asn1/asn_mime.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/crypto/asn1/asn_mime.c b/crypto/asn1/asn_mime.c +index 38735cd86f..36853612b6 100644 +--- a/crypto/asn1/asn_mime.c ++++ b/crypto/asn1/asn_mime.c +@@ -489,6 +489,7 @@ int SMIME_crlf_copy(BIO *in, BIO *out, int flags) + char eol; + int len; + char linebuf[MAX_SMLEN]; ++ int ret; + /* + * Buffer output so we don't write one line at a time. This is useful + * when streaming as we don't end up with one OCTET STRING per line. +@@ -523,9 +524,12 @@ int SMIME_crlf_copy(BIO *in, BIO *out, int flags) + BIO_write(out, "\r\n", 2); + } + } +- (void)BIO_flush(out); ++ ret = BIO_flush(out); + BIO_pop(out); + BIO_free(bf); ++ if (ret <= 0) ++ return 0; ++ + return 1; + } + +-- +2.36.1 + diff --git a/backport-Fix-SSL_pending-and-SSL_has_pending-with-DTLS.patch b/backport-Fix-SSL_pending-and-SSL_has_pending-with-DTLS.patch new file mode 100644 index 0000000..c392704 --- /dev/null +++ b/backport-Fix-SSL_pending-and-SSL_has_pending-with-DTLS.patch @@ -0,0 +1,89 @@ +From 01fc812cb0aafc3cfc271303b6646d1c0a86b020 Mon Sep 17 00:00:00 2001 +From: Matt Caswell +Date: Mon, 25 Jul 2022 15:59:38 +0100 +Subject: [PATCH] Fix SSL_pending() and SSL_has_pending() with DTLS + +If app data is received before a Finished message in DTLS then we buffer +it to return later. The function SSL_pending() is supposed to tell you +how much processed app data we have already buffered, and SSL_has_pending() +is supposed to tell you if we have any data buffered (whether processed or +not, and whether app data or not). + +Neither SSL_pending() or SSL_has_pending() were taking account of this +DTLS specific app data buffer. + +Reviewed-by: Hugo Landau +Reviewed-by: Tomas Mraz +(Merged from https://github.com/openssl/openssl/pull/18976) +--- + ssl/record/rec_layer_s3.c | 14 +++++++++++++- + ssl/ssl_lib.c | 24 +++++++++++++++++++----- + 2 files changed, 32 insertions(+), 6 deletions(-) + +diff --git a/ssl/record/rec_layer_s3.c b/ssl/record/rec_layer_s3.c +index 8249b4ace9..23cd4219e9 100644 +--- a/ssl/record/rec_layer_s3.c ++++ b/ssl/record/rec_layer_s3.c +@@ -115,10 +115,22 @@ size_t ssl3_pending(const SSL *s) + if (s->rlayer.rstate == SSL_ST_READ_BODY) + return 0; + ++ /* Take into account DTLS buffered app data */ ++ if (SSL_IS_DTLS(s)) { ++ DTLS1_RECORD_DATA *rdata; ++ pitem *item, *iter; ++ ++ iter = pqueue_iterator(s->rlayer.d->buffered_app_data.q); ++ while ((item = pqueue_next(&iter)) != NULL) { ++ rdata = item->data; ++ num += rdata->rrec.length; ++ } ++ } ++ + for (i = 0; i < RECORD_LAYER_get_numrpipes(&s->rlayer); i++) { + if (SSL3_RECORD_get_type(&s->rlayer.rrec[i]) + != SSL3_RT_APPLICATION_DATA) +- return 0; ++ return num; + num += SSL3_RECORD_get_length(&s->rlayer.rrec[i]); + } + +diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c +index 25a1a44785..47adc3211c 100644 +--- a/ssl/ssl_lib.c ++++ b/ssl/ssl_lib.c +@@ -1510,12 +1510,26 @@ int SSL_has_pending(const SSL *s) + { + /* + * Similar to SSL_pending() but returns a 1 to indicate that we have +- * unprocessed data available or 0 otherwise (as opposed to the number of +- * bytes available). Unlike SSL_pending() this will take into account +- * read_ahead data. A 1 return simply indicates that we have unprocessed +- * data. That data may not result in any application data, or we may fail +- * to parse the records for some reason. ++ * processed or unprocessed data available or 0 otherwise (as opposed to the ++ * number of bytes available). Unlike SSL_pending() this will take into ++ * account read_ahead data. A 1 return simply indicates that we have data. ++ * That data may not result in any application data, or we may fail to parse ++ * the records for some reason. + */ ++ ++ /* Check buffered app data if any first */ ++ if (SSL_IS_DTLS(s)) { ++ DTLS1_RECORD_DATA *rdata; ++ pitem *item, *iter; ++ ++ iter = pqueue_iterator(s->rlayer.d->buffered_app_data.q); ++ while ((item = pqueue_next(&iter)) != NULL) { ++ rdata = item->data; ++ if (rdata->rrec.length > 0) ++ return 1; ++ } ++ } ++ + if (RECORD_LAYER_processed_read_pending(&s->rlayer)) + return 1; + +-- +2.17.1 + diff --git a/backport-Fix-a-crash-in-v2i_IPAddrBlocks.patch b/backport-Fix-a-crash-in-v2i_IPAddrBlocks.patch new file mode 100644 index 0000000..90f12ea --- /dev/null +++ b/backport-Fix-a-crash-in-v2i_IPAddrBlocks.patch @@ -0,0 +1,76 @@ +From 264a3f453c418dc01f4b74928ed2a76a08a65513 Mon Sep 17 00:00:00 2001 +From: Matt Caswell +Date: Fri, 10 Jun 2022 12:33:45 +0100 +Subject: [PATCH] Fix a crash in v2i_IPAddrBlocks() + +If an IP address prefix value is supplied that is too large then a crash +can result. v2i_IPAddrBlocks() should sanity check the prefix value, as +should X509v3_addr_add_prefix(). + +Reported by Theo Buehler (@botovq) + +Reviewed-by: Tomas Mraz +Reviewed-by: Dmitry Belyavskiy +Reviewed-by: Hugo Landau +(Merged from https://github.com/openssl/openssl/pull/18847) +--- + crypto/x509v3/v3_addr.c | 17 ++++--- + test/v3ext.c | 99 +++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 111 insertions(+), 5 deletions(-) + +diff --git a/crypto/x509v3/v3_addr.c b/crypto/x509v3/v3_addr.c +index ccce34ef2e..f9c368bea4 100644 +--- a/crypto/x509v3/v3_addr.c ++++ b/crypto/x509v3/v3_addr.c +@@ -392,12 +392,14 @@ static int range_should_be_prefix(const unsigned char *min, + /* + * Construct a prefix. + */ +-static int make_addressPrefix(IPAddressOrRange **result, +- unsigned char *addr, const int prefixlen) ++static int make_addressPrefix(IPAddressOrRange **result, unsigned char *addr, ++ const int prefixlen, const int afilen) + { + int bytelen = (prefixlen + 7) / 8, bitlen = prefixlen % 8; + IPAddressOrRange *aor = IPAddressOrRange_new(); + ++ if (prefixlen < 0 || prefixlen > (afilen * 8)) ++ return 0; + if (aor == NULL) + return 0; + aor->type = IPAddressOrRange_addressPrefix; +@@ -437,7 +439,7 @@ static int make_addressRange(IPAddressOrRange **result, + return 0; + + if ((prefixlen = range_should_be_prefix(min, max, length)) >= 0) +- return make_addressPrefix(result, min, prefixlen); ++ return make_addressPrefix(result, min, prefixlen, length); + + if ((aor = IPAddressOrRange_new()) == NULL) + return 0; +@@ -599,7 +601,9 @@ int X509v3_addr_add_prefix(IPAddrBlocks *addr, + { + IPAddressOrRanges *aors = make_prefix_or_range(addr, afi, safi); + IPAddressOrRange *aor; +- if (aors == NULL || !make_addressPrefix(&aor, a, prefixlen)) ++ ++ if (aors == NULL ++ || !make_addressPrefix(&aor, a, prefixlen, length_from_afi(afi))) + return 0; + if (sk_IPAddressOrRange_push(aors, aor)) + return 1; +@@ -996,7 +1000,10 @@ static void *v2i_IPAddrBlocks(const struct v3_ext_method *method, + switch (delim) { + case '/': + prefixlen = (int)strtoul(s + i2, &t, 10); +- if (t == s + i2 || *t != '\0') { ++ if (t == s + i2 ++ || *t != '\0' ++ || prefixlen > (length * 8) ++ || prefixlen < 0) { + X509V3err(X509V3_F_V2I_IPADDRBLOCKS, + X509V3_R_EXTENSION_VALUE_ERROR); + X509V3_conf_err(val); +-- +2.17.1 + diff --git a/backport-Fix-a-logic-flaw-in-test_mod_exp_zero.patch b/backport-Fix-a-logic-flaw-in-test_mod_exp_zero.patch new file mode 100644 index 0000000..910c2ac --- /dev/null +++ b/backport-Fix-a-logic-flaw-in-test_mod_exp_zero.patch @@ -0,0 +1,33 @@ +From ed8af0502167c80ba70522d88e719f874e24ebfd Mon Sep 17 00:00:00 2001 +From: Bernd Edlinger +Date: Fri, 16 Dec 2022 19:30:29 +0100 +Subject: [PATCH] Fix a logic flaw in test_mod_exp_zero + +Due to the logic flaw, possible test failures +in this test case might be ignored. + +Reviewed-by: Shane Lontis +Reviewed-by: Tomas Mraz +(Merged from https://github.com/openssl/openssl/pull/19929) + +(cherry picked from commit 42061268ee8f9ae0555d522870740fc91b744f4f) +--- + test/exptest.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/test/exptest.c b/test/exptest.c +index cde4d6bc45..a327773ec4 100644 +--- a/test/exptest.c ++++ b/test/exptest.c +@@ -49,7 +49,7 @@ static int test_mod_exp_zero(void) + BIGNUM *r = NULL; + BN_ULONG one_word = 1; + BN_CTX *ctx = BN_CTX_new(); +- int ret = 1, failed = 0; ++ int ret = 0, failed = 0; + + if (!TEST_ptr(m = BN_new()) + || !TEST_ptr(a = BN_new()) +-- +2.36.1 + diff --git a/backport-Fix-a-memory-leak-in-rsa_priv_encode.patch b/backport-Fix-a-memory-leak-in-rsa_priv_encode.patch new file mode 100644 index 0000000..6ef9d2e --- /dev/null +++ b/backport-Fix-a-memory-leak-in-rsa_priv_encode.patch @@ -0,0 +1,31 @@ +From 68cec7e9d31fdf05b82a627a82398d8cfb0b915c Mon Sep 17 00:00:00 2001 +From: Bernd Edlinger +Date: Wed, 16 Nov 2022 12:32:06 +0100 +Subject: [PATCH] Fix a memory leak in rsa_priv_encode + +If PKCS8_pkey_set0 fails, the memory in rk need to be clear freed +otherwise it is owned by the PKCS8_PRIV_KEY_INFO. + +Reviewed-by: Hugo Landau +Reviewed-by: Todd Short +Reviewed-by: Paul Dale +(Merged from https://github.com/openssl/openssl/pull/19694) +--- + crypto/rsa/rsa_ameth.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/crypto/rsa/rsa_ameth.c b/crypto/rsa/rsa_ameth.c +index fb045544a8..2c9c46ea53 100644 +--- a/crypto/rsa/rsa_ameth.c ++++ b/crypto/rsa/rsa_ameth.c +@@ -172,6 +172,7 @@ static int rsa_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey) + strtype, str, rk, rklen)) { + RSAerr(RSA_F_RSA_PRIV_ENCODE, ERR_R_MALLOC_FAILURE); + ASN1_STRING_free(str); ++ OPENSSL_clear_free(rk, rklen); + return 0; + } + +-- +2.36.1 + diff --git a/backport-Fix-ipv4_from_asc-behavior-on-invalid-Ip-addresses.patch b/backport-Fix-ipv4_from_asc-behavior-on-invalid-Ip-addresses.patch new file mode 100644 index 0000000..fec3959 --- /dev/null +++ b/backport-Fix-ipv4_from_asc-behavior-on-invalid-Ip-addresses.patch @@ -0,0 +1,45 @@ +From 65e30e7d56f01008d29e65c9ae7a42ce074def2f Mon Sep 17 00:00:00 2001 +From: Amir Mohammadi +Date: Wed, 4 Aug 2021 09:43:49 +0430 +Subject: [PATCH] Fix ipv4_from_asc behavior on invalid Ip addresses + +sscanf() call in ipv4_from_asc does not check that +the string is terminated immediately after the last digit. + +(cherry picked from commit 8b9a13b43ba3d71e441fca47a52e800ce79b3d2b) + +Reviewed-by: Tomas Mraz +Reviewed-by: Dmitry Belyavskiy +Reviewed-by: Hugo Landau +(Merged from https://github.com/openssl/openssl/pull/18847) +--- + crypto/x509v3/v3_utl.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/crypto/x509v3/v3_utl.c b/crypto/x509v3/v3_utl.c +index a7ff4b4fb4..eac78259fc 100644 +--- a/crypto/x509v3/v3_utl.c ++++ b/crypto/x509v3/v3_utl.c +@@ -1087,12 +1087,17 @@ int a2i_ipadd(unsigned char *ipout, const char *ipasc) + + static int ipv4_from_asc(unsigned char *v4, const char *in) + { +- int a0, a1, a2, a3; +- if (sscanf(in, "%d.%d.%d.%d", &a0, &a1, &a2, &a3) != 4) ++ const char *p; ++ int a0, a1, a2, a3, n; ++ ++ if (sscanf(in, "%d.%d.%d.%d%n", &a0, &a1, &a2, &a3, &n) != 4) + return 0; + if ((a0 < 0) || (a0 > 255) || (a1 < 0) || (a1 > 255) + || (a2 < 0) || (a2 > 255) || (a3 < 0) || (a3 > 255)) + return 0; ++ p = in + n; ++ if (!(*p == '\0' || ossl_isspace(*p))) ++ return 0; + v4[0] = a0; + v4[1] = a1; + v4[2] = a2; +-- +2.17.1 + diff --git a/backport-Fix-re-signing-certificates-with-different-key-sizes.patch b/backport-Fix-re-signing-certificates-with-different-key-sizes.patch new file mode 100644 index 0000000..dc15494 --- /dev/null +++ b/backport-Fix-re-signing-certificates-with-different-key-sizes.patch @@ -0,0 +1,131 @@ +From 952fab01bebb15a8408c6ac27b59c28c979f7d49 Mon Sep 17 00:00:00 2001 +From: Todd Short +Date: Wed, 20 Jul 2022 16:42:50 -0400 +Subject: [PATCH] Fix re-signing certificates with different key sizes + +PR #18129 broke the scenario of signing a certificate (not CSR) with +different-sized key. This works in 3.0, so port the fix from 3.0 +(which is to only update the issuer for a request). + +Partially undo #18129, but keep setting the issuer only for a CSR + +Create two certs (a and ca) then sign a with c (into b): +``` +openssl req -x509 -newkey rsa:2048 -keyout a-key.pem -out a-cert.pem -days 365 -nodes -subj /CN=a.example.com +openssl req -x509 -newkey rsa:4096 -keyout ${HERE}/ca-key.pem -out ${HERE}/ca-cert.pem -days 3650 -nodes -subj /CN=ca.example.com +openssl x509 -in a-cert.pem -CA ca-cert.pem -CAkey ca-key.pem -set_serial '1234567890' -preserve_dates -sha256 -out b-cert.pem +``` +The above succeeds in 1.1.1n and 3.0, fails in 1.1.1o (which includes #18129) +The issue in #16080 is also fixed. + +Reviewed-by: Matt Caswell +Reviewed-by: Tomas Mraz +Reviewed-by: Ben Kaduk +(Merged from https://github.com/openssl/openssl/pull/18836) +--- + apps/x509.c | 4 ++- + test/recipes/25-test_x509.t | 61 ++++++++++++++++++++++++++++++++++++- + 2 files changed, 63 insertions(+), 2 deletions(-) + +diff --git a/apps/x509.c b/apps/x509.c +index 67a70e7fea..8d4bf71a03 100644 +--- a/apps/x509.c ++++ b/apps/x509.c +@@ -590,7 +590,7 @@ int x509_main(int argc, char **argv) + xca = load_cert(CAfile, CAformat, "CA Certificate"); + if (xca == NULL) + goto end; +- if (!X509_set_issuer_name(x, X509_get_subject_name(xca))) ++ if (reqfile && !X509_set_issuer_name(x, X509_get_subject_name(xca))) + goto end; + } + +@@ -993,6 +993,8 @@ static int x509_certify(X509_STORE *ctx, const char *CAfile, const EVP_MD *diges + goto end; + } + ++ if (!X509_set_issuer_name(x, X509_get_subject_name(xca))) ++ goto end; + if (!X509_set_serialNumber(x, bs)) + goto end; + +diff --git a/test/recipes/25-test_x509.t b/test/recipes/25-test_x509.t +index f5ef0f9963..73548145c8 100644 +--- a/test/recipes/25-test_x509.t ++++ b/test/recipes/25-test_x509.t +@@ -15,7 +15,11 @@ use OpenSSL::Test qw/:DEFAULT srctop_file/; + + setup("test_x509"); + +-plan tests => 9; ++plan tests => 16; ++ ++# Prevent MSys2 filename munging for arguments that look like file paths but ++# aren't ++$ENV{MSYS2_ARG_CONV_EXCL} = "/CN="; + + require_ok(srctop_file('test','recipes','tconversion.pl')); + +@@ -46,4 +50,59 @@ subtest 'x509 -- second x.509 v3 certificate' => sub { + + subtest 'x509 -- pathlen' => sub { + ok(run(test(["v3ext", srctop_file("test/certs", "pathlen.pem")]))); ++}; ++ ++# extracts issuer from a -text formatted-output ++sub get_issuer { ++ my $f = shift(@_); ++ my $issuer = ""; ++ open my $fh, $f or die; ++ while (my $line = <$fh>) { ++ if ($line =~ /Issuer:/) { ++ $issuer = $line; ++ } ++ } ++ close $fh; ++ return $issuer; + } ++ ++# Tests for signing certs (broken in 1.1.1o) ++my $a_key = "a-key.pem"; ++my $a_cert = "a-cert.pem"; ++my $a2_cert = "a2-cert.pem"; ++my $ca_key = "ca-key.pem"; ++my $ca_cert = "ca-cert.pem"; ++my $cnf = srctop_file('apps', 'openssl.cnf'); ++ ++# Create cert A ++ok(run(app(["openssl", "req", "-x509", "-newkey", "rsa:2048", ++ "-config", $cnf, ++ "-keyout", $a_key, "-out", $a_cert, "-days", "365", ++ "-nodes", "-subj", "/CN=test.example.com"]))); ++# Create cert CA - note key size ++ok(run(app(["openssl", "req", "-x509", "-newkey", "rsa:4096", ++ "-config", $cnf, ++ "-keyout", $ca_key, "-out", $ca_cert, "-days", "3650", ++ "-nodes", "-subj", "/CN=ca.example.com"]))); ++# Sign cert A with CA (errors on 1.1.1o) ++ok(run(app(["openssl", "x509", "-in", $a_cert, "-CA", $ca_cert, ++ "-CAkey", $ca_key, "-set_serial", "1234567890", ++ "-preserve_dates", "-sha256", "-text", "-out", $a2_cert]))); ++# verify issuer is CA ++ok (get_issuer($a2_cert) =~ /CN = ca.example.com/); ++ ++# Tests for issue #16080 (fixed in 1.1.1o) ++my $b_key = "b-key.pem"; ++my $b_csr = "b-cert.csr"; ++my $b_cert = "b-cert.pem"; ++# Create the CSR ++ok(run(app(["openssl", "req", "-new", "-newkey", "rsa:4096", ++ "-keyout", $b_key, "-out", $b_csr, "-nodes", ++ "-config", $cnf, ++ "-subj", "/CN=b.example.com"]))); ++# Sign it - position of "-text" matters! ++ok(run(app(["openssl", "x509", "-req", "-text", "-CAcreateserial", ++ "-CA", $ca_cert, "-CAkey", $ca_key, ++ "-in", $b_csr, "-out", $b_cert]))); ++# Verify issuer is CA ++ok(get_issuer($b_cert) =~ /CN = ca.example.com/); +-- +2.17.1 + diff --git a/backport-Fix-test-case-for-a2i_IPADDRESS.patch b/backport-Fix-test-case-for-a2i_IPADDRESS.patch new file mode 100644 index 0000000..6fb1f30 --- /dev/null +++ b/backport-Fix-test-case-for-a2i_IPADDRESS.patch @@ -0,0 +1,42 @@ +From c3b0279bda7bf4f0f81a3dba952698fa68a51639 Mon Sep 17 00:00:00 2001 +From: Amir Mohammadi +Date: Wed, 4 Aug 2021 09:44:29 +0430 +Subject: [PATCH] Fix test case for a2i_IPADDRESS + +(cherry picked from commit 9b887d5d5a8ef9aa1c3ce6e54a82ddcba25b9415) + +Reviewed-by: Tomas Mraz +Reviewed-by: Dmitry Belyavskiy +Reviewed-by: Hugo Landau +(Merged from https://github.com/openssl/openssl/pull/18847) +--- + test/x509_internal_test.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/test/x509_internal_test.c b/test/x509_internal_test.c +index 3eec970352..63f350f74b 100644 +--- a/test/x509_internal_test.c ++++ b/test/x509_internal_test.c +@@ -61,7 +61,6 @@ typedef struct { + const char *ipasc; + const char *data; + int length; +- ASN1_OCTET_STRING ip; + } IP_TESTDATA; + + static IP_TESTDATA a2i_ipaddress_tests[] = { +@@ -81,8 +80,10 @@ static IP_TESTDATA a2i_ipaddress_tests[] = { + {"example.test", NULL, 0}, + {"", NULL, 0}, + ++ {"1.2.3.4 ", "\x01\x02\x03\x04", 4}, ++ {" 1.2.3.4", "\x01\x02\x03\x04", 4}, ++ {" 1.2.3.4 ", "\x01\x02\x03\x04", 4}, + {"1.2.3.4.example.test", NULL, 0}, +- {"1.2.3.4 ", NULL, 0}, + }; + + +-- +2.17.1 + diff --git a/backport-Fix-the-ceiling-on-how-much-encryption-growth-we-can.patch b/backport-Fix-the-ceiling-on-how-much-encryption-growth-we-can.patch new file mode 100644 index 0000000..77e4c3d --- /dev/null +++ b/backport-Fix-the-ceiling-on-how-much-encryption-growth-we-can.patch @@ -0,0 +1,71 @@ +From 31efcf2c872f8f4d09ad5209ccbf1ada73436775 Mon Sep 17 00:00:00 2001 +From: Matt Caswell +Date: Thu, 27 Oct 2022 14:14:53 +0100 +Subject: [PATCH] Fix the ceiling on how much encryption growth we can have + +Stitched ciphersuites can grow by more during encryption than the code +allowed for. We fix the calculation and add an assert to check we go it +right. + +Also if we are adding the MAC independently of the cipher algorithm then +the encryption growth will not include that MAC so we should remove it +from the amount of bytes that we reserve for that growth. Otherwise we +might exceed our buffer size and the WPACKET_reserve operation will +fail. + +Note that this is not a security issue. Even though we can overflow the +amount of bytes reserved in the WPACKET for the encryption, the underlying +buffer is still big enough. + +Reviewed-by: Tomas Mraz +Reviewed-by: Hugo Landau +(Merged from https://github.com/openssl/openssl/pull/19585) +--- + ssl/record/rec_layer_s3.c | 17 ++++++++++++----- + 1 file changed, 12 insertions(+), 5 deletions(-) + +diff --git a/ssl/record/rec_layer_s3.c b/ssl/record/rec_layer_s3.c +index fe4abd6723..1db1712a09 100644 +--- a/ssl/record/rec_layer_s3.c ++++ b/ssl/record/rec_layer_s3.c +@@ -16,6 +16,7 @@ + #include + #include "record_local.h" + #include "../packet_local.h" ++#include "internal/cryptlib.h" + + #if defined(OPENSSL_SMALL_FOOTPRINT) || \ + !( defined(AESNI_ASM) && ( \ +@@ -983,11 +984,14 @@ int do_ssl3_write(SSL *s, int type, const unsigned char *buf, + } + + /* +- * Reserve some bytes for any growth that may occur during encryption. +- * This will be at most one cipher block or the tag length if using +- * AEAD. SSL_RT_MAX_CIPHER_BLOCK_SIZE covers either case. +- */ +- if (!WPACKET_reserve_bytes(thispkt, SSL_RT_MAX_CIPHER_BLOCK_SIZE, ++ * Reserve some bytes for any growth that may occur during encryption. If ++ * we are adding the MAC independently of the cipher algorithm, then the ++ * max encrypted overhead does not need to include an allocation for that ++ * MAC ++ */ ++ if (!WPACKET_reserve_bytes(thispkt, ++ SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD ++ - mac_size, + NULL) + /* + * We also need next the amount of bytes written to this +@@ -1037,6 +1041,9 @@ int do_ssl3_write(SSL *s, int type, const unsigned char *buf, + + /* Allocate bytes for the encryption overhead */ + if (!WPACKET_get_length(thispkt, &origlen) ++ /* Check we allowed enough room for the encryption growth */ ++ || !ossl_assert(origlen + SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD ++ - mac_size >= thiswr->length) + /* Encryption should never shrink the data! */ + || origlen > thiswr->length + || (thiswr->length > origlen +-- +2.36.1 + diff --git a/backport-Fix-verify_callback-in-the-openssl-s_client-s_server.patch b/backport-Fix-verify_callback-in-the-openssl-s_client-s_server.patch new file mode 100644 index 0000000..f5f70b4 --- /dev/null +++ b/backport-Fix-verify_callback-in-the-openssl-s_client-s_server.patch @@ -0,0 +1,64 @@ +From 86945b10ccd84f685bd6215bbb00d1e700303e49 Mon Sep 17 00:00:00 2001 +From: Dmitry Belyavskiy +Date: Thu, 14 Jul 2022 21:41:48 +0200 +Subject: [PATCH] Fix verify_callback in the openssl s_client/s_server app + +We need to check that error cert is available before printing its data + +Reviewed-by: Tomas Mraz +Reviewed-by: David von Oheimb +Reviewed-by: Viktor Dukhovni +Reviewed-by: Hugo Landau +(Merged from https://github.com/openssl/openssl/pull/18805) + +(cherry picked from commit fad0f80eff188ef938fed614245a56ed56110deb) +--- + apps/s_cb.c | 26 ++++++++++++++++---------- + 1 file changed, 16 insertions(+), 10 deletions(-) + +diff --git a/apps/s_cb.c b/apps/s_cb.c +index d066a423de..a4ff978908 100644 +--- a/apps/s_cb.c ++++ b/apps/s_cb.c +@@ -74,22 +74,28 @@ int verify_callback(int ok, X509_STORE_CTX *ctx) + } + switch (err) { + case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: +- BIO_puts(bio_err, "issuer= "); +- X509_NAME_print_ex(bio_err, X509_get_issuer_name(err_cert), +- 0, get_nameopt()); +- BIO_puts(bio_err, "\n"); ++ if (err_cert != NULL) { ++ BIO_puts(bio_err, "issuer= "); ++ X509_NAME_print_ex(bio_err, X509_get_issuer_name(err_cert), ++ 0, get_nameopt()); ++ BIO_puts(bio_err, "\n"); ++ } + break; + case X509_V_ERR_CERT_NOT_YET_VALID: + case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: +- BIO_printf(bio_err, "notBefore="); +- ASN1_TIME_print(bio_err, X509_get0_notBefore(err_cert)); +- BIO_printf(bio_err, "\n"); ++ if (err_cert != NULL) { ++ BIO_printf(bio_err, "notBefore="); ++ ASN1_TIME_print(bio_err, X509_get0_notBefore(err_cert)); ++ BIO_printf(bio_err, "\n"); ++ } + break; + case X509_V_ERR_CERT_HAS_EXPIRED: + case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: +- BIO_printf(bio_err, "notAfter="); +- ASN1_TIME_print(bio_err, X509_get0_notAfter(err_cert)); +- BIO_printf(bio_err, "\n"); ++ if (err_cert != NULL) { ++ BIO_printf(bio_err, "notAfter="); ++ ASN1_TIME_print(bio_err, X509_get0_notAfter(err_cert)); ++ BIO_printf(bio_err, "\n"); ++ } + break; + case X509_V_ERR_NO_EXPLICIT_POLICY: + if (!verify_args.quiet) +-- +2.17.1 + diff --git a/backport-Fixes-segfault-occurrence-in-PEM_write.patch b/backport-Fixes-segfault-occurrence-in-PEM_write.patch new file mode 100644 index 0000000..4a3888b --- /dev/null +++ b/backport-Fixes-segfault-occurrence-in-PEM_write.patch @@ -0,0 +1,37 @@ +From 3b9082c844913d3a0efada9fac0bd2924ce1a8f2 Mon Sep 17 00:00:00 2001 +From: valdaarhun +Date: Mon, 25 Jul 2022 18:49:19 +0530 +Subject: [PATCH] Fixes segfault occurrence in PEM_write() + +Checks if header is NULL or not before calling strlen(). + +CLA: trivial + +Fixes #18825 + +Reviewed-by: Tomas Mraz +Reviewed-by: Ben Kaduk +Reviewed-by: Paul Dale +(Merged from https://github.com/openssl/openssl/pull/18865) + +(cherry picked from commit 205957405d08ef199e6ab654e333a627bbca9ccc) +--- + crypto/pem/pem_lib.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/crypto/pem/pem_lib.c b/crypto/pem/pem_lib.c +index 2de093595d..c2cf407931 100644 +--- a/crypto/pem/pem_lib.c ++++ b/crypto/pem/pem_lib.c +@@ -621,7 +621,7 @@ int PEM_write_bio(BIO *bp, const char *name, const char *header, + (BIO_write(bp, "-----\n", 6) != 6)) + goto err; + +- i = strlen(header); ++ i = header != NULL ? strlen(header) : 0; + if (i > 0) { + if ((BIO_write(bp, header, i) != i) || (BIO_write(bp, "\n", 1) != 1)) + goto err; +-- +2.17.1 + diff --git a/backport-Limit-size-of-modulus-for-bn_mul_mont-and-BN_mod_exp.patch b/backport-Limit-size-of-modulus-for-bn_mul_mont-and-BN_mod_exp.patch new file mode 100644 index 0000000..0100c5c --- /dev/null +++ b/backport-Limit-size-of-modulus-for-bn_mul_mont-and-BN_mod_exp.patch @@ -0,0 +1,208 @@ +From 5bbd921ff5610bb5cca7475813f7f689f2a670e6 Mon Sep 17 00:00:00 2001 +From: Bernd Edlinger +Date: Tue, 8 Nov 2022 17:43:22 +0100 +Subject: [PATCH] Limit size of modulus for bn_mul_mont and + BN_mod_exp_mont_consttime + +Otherwise the alloca can cause an exception. + +Issue reported by Jiayi Lin. + +Reviewed-by: Tomas Mraz +Reviewed-by: Paul Dale +(Merged from https://github.com/openssl/openssl/pull/19735) +--- + crypto/bn/bn_exp.c | 34 +++++++++++++++++++++++++++------- + crypto/bn/bn_local.h | 20 ++++++++++++++++++++ + crypto/bn/bn_mont.c | 2 +- + test/exptest.c | 29 +++++++++++++++++++++++++++++ + 4 files changed, 77 insertions(+), 8 deletions(-) + +diff --git a/crypto/bn/bn_exp.c b/crypto/bn/bn_exp.c +index e21dcff027..31043c8bc2 100644 +--- a/crypto/bn/bn_exp.c ++++ b/crypto/bn/bn_exp.c +@@ -37,6 +37,15 @@ extern unsigned int OPENSSL_sparcv9cap_P[]; + /* maximum precomputation table size for *variable* sliding windows */ + #define TABLE_SIZE 32 + ++/* ++ * Beyond this limit the constant time code is disabled due to ++ * the possible overflow in the computation of powerbufLen in ++ * BN_mod_exp_mont_consttime. ++ * When this limit is exceeded, the computation will be done using ++ * non-constant time code, but it will take very long. ++ */ ++#define BN_CONSTTIME_SIZE_LIMIT (INT_MAX / BN_BYTES / 256) ++ + /* this one works - simple but works */ + int BN_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx) + { +@@ -305,12 +314,6 @@ int BN_mod_exp_mont(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, + BIGNUM *val[TABLE_SIZE]; + BN_MONT_CTX *mont = NULL; + +- if (BN_get_flags(p, BN_FLG_CONSTTIME) != 0 +- || BN_get_flags(a, BN_FLG_CONSTTIME) != 0 +- || BN_get_flags(m, BN_FLG_CONSTTIME) != 0) { +- return BN_mod_exp_mont_consttime(rr, a, p, m, ctx, in_mont); +- } +- + bn_check_top(a); + bn_check_top(p); + bn_check_top(m); +@@ -319,6 +322,14 @@ int BN_mod_exp_mont(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, + BNerr(BN_F_BN_MOD_EXP_MONT, BN_R_CALLED_WITH_EVEN_MODULUS); + return 0; + } ++ ++ if (m->top <= BN_CONSTTIME_SIZE_LIMIT ++ && (BN_get_flags(p, BN_FLG_CONSTTIME) != 0 ++ || BN_get_flags(a, BN_FLG_CONSTTIME) != 0 ++ || BN_get_flags(m, BN_FLG_CONSTTIME) != 0)) { ++ return BN_mod_exp_mont_consttime(rr, a, p, m, ctx, in_mont); ++ } ++ + bits = BN_num_bits(p); + if (bits == 0) { + /* x**0 mod 1, or x**0 mod -1 is still zero. */ +@@ -618,6 +629,11 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, + + top = m->top; + ++ if (top > BN_CONSTTIME_SIZE_LIMIT) { ++ /* Prevent overflowing the powerbufLen computation below */ ++ return BN_mod_exp_mont(rr, a, p, m, ctx, in_mont); ++ } ++ + /* + * Use all bits stored in |p|, rather than |BN_num_bits|, so we do not leak + * whether the top bits are zero. +@@ -697,7 +713,7 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, + else + #endif + #if defined(OPENSSL_BN_ASM_MONT5) +- if (window >= 5) { ++ if (window >= 5 && top <= BN_SOFT_LIMIT) { + window = 5; /* ~5% improvement for RSA2048 sign, and even + * for RSA4096 */ + /* reserve space for mont->N.d[] copy */ +@@ -758,6 +774,9 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, + if (!bn_to_mont_fixed_top(&am, a, mont, ctx)) + goto err; + ++ if (top > BN_SOFT_LIMIT) ++ goto fallback; ++ + #if defined(SPARC_T4_MONT) + if (t4) { + typedef int (*bn_pwr5_mont_f) (BN_ULONG *tp, const BN_ULONG *np, +@@ -1029,6 +1048,7 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, + } else + #endif + { ++ fallback: + if (!MOD_EXP_CTIME_COPY_TO_PREBUF(&tmp, top, powerbuf, 0, window)) + goto err; + if (!MOD_EXP_CTIME_COPY_TO_PREBUF(&am, top, powerbuf, 1, window)) +diff --git a/crypto/bn/bn_local.h b/crypto/bn/bn_local.h +index 8ad69ccd36..62a969b134 100644 +--- a/crypto/bn/bn_local.h ++++ b/crypto/bn/bn_local.h +@@ -35,6 +35,26 @@ + /* #define BN_DEBUG */ + /* #define BN_DEBUG_RAND */ + ++/* ++ * This should limit the stack usage due to alloca to about 4K. ++ * BN_SOFT_LIMIT is a soft limit equivalent to 2*OPENSSL_RSA_MAX_MODULUS_BITS. ++ * Beyond that size bn_mul_mont is no longer used, and the constant time ++ * assembler code is disabled, due to the blatant alloca and bn_mul_mont usage. ++ * Note that bn_mul_mont does an alloca that is hidden away in assembly. ++ * It is not recommended to do computations with numbers exceeding this limit, ++ * since the result will be highly version dependent: ++ * While the current OpenSSL version will use non-optimized, but safe code, ++ * previous versions will use optimized code, that may crash due to unexpected ++ * stack overflow, and future versions may very well turn this into a hard ++ * limit. ++ * Note however, that it is possible to override the size limit using ++ * "./config -DBN_SOFT_LIMIT=" if necessary, and the O/S specific ++ * stack limit is known and taken into consideration. ++ */ ++# ifndef BN_SOFT_LIMIT ++# define BN_SOFT_LIMIT (4096 / BN_BYTES) ++# endif ++ + # ifndef OPENSSL_SMALL_FOOTPRINT + # define BN_MUL_COMBA + # define BN_SQR_COMBA +diff --git a/crypto/bn/bn_mont.c b/crypto/bn/bn_mont.c +index 1e5045a010..3d4a1bda45 100644 +--- a/crypto/bn/bn_mont.c ++++ b/crypto/bn/bn_mont.c +@@ -42,7 +42,7 @@ int bn_mul_mont_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + int num = mont->N.top; + + #if defined(OPENSSL_BN_ASM_MONT) && defined(MONT_WORD) +- if (num > 1 && a->top == num && b->top == num) { ++ if (num > 1 && num <= BN_SOFT_LIMIT && a->top == num && b->top == num) { + if (bn_wexpand(r, num) == NULL) + return 0; + if (bn_mul_mont(r->d, a->d, b->d, mont->N.d, mont->n0, num)) { +diff --git a/test/exptest.c b/test/exptest.c +index a327773ec4..5cab57c851 100644 +--- a/test/exptest.c ++++ b/test/exptest.c +@@ -50,6 +50,7 @@ static int test_mod_exp_zero(void) + BN_ULONG one_word = 1; + BN_CTX *ctx = BN_CTX_new(); + int ret = 0, failed = 0; ++ BN_MONT_CTX *mont = NULL; + + if (!TEST_ptr(m = BN_new()) + || !TEST_ptr(a = BN_new()) +@@ -94,6 +95,33 @@ static int test_mod_exp_zero(void) + if (!TEST_true(a_is_zero_mod_one("BN_mod_exp_mont_consttime", r, a))) + failed = 1; + ++ if (!TEST_ptr(mont = BN_MONT_CTX_new())) ++ goto err; ++ ++ ERR_set_mark(); ++ /* mont is not set but passed in */ ++ if (!TEST_false(BN_mod_exp_mont_consttime(r, p, a, m, ctx, mont))) ++ goto err; ++ if (!TEST_false(BN_mod_exp_mont(r, p, a, m, ctx, mont))) ++ goto err; ++ ERR_pop_to_mark(); ++ ++ if (!TEST_true(BN_MONT_CTX_set(mont, m, ctx))) ++ goto err; ++ ++ /* we compute 0 ** a mod 1 here, to execute code that uses mont */ ++ if (!TEST_true(BN_mod_exp_mont_consttime(r, p, a, m, ctx, mont))) ++ goto err; ++ ++ if (!TEST_true(a_is_zero_mod_one("BN_mod_exp_mont_consttime", r, a))) ++ failed = 1; ++ ++ if (!TEST_true(BN_mod_exp_mont(r, p, a, m, ctx, mont))) ++ goto err; ++ ++ if (!TEST_true(a_is_zero_mod_one("BN_mod_exp_mont", r, a))) ++ failed = 1; ++ + /* + * A different codepath exists for single word multiplication + * in non-constant-time only. +@@ -114,6 +142,7 @@ static int test_mod_exp_zero(void) + BN_free(a); + BN_free(p); + BN_free(m); ++ BN_MONT_CTX_free(mont); + BN_CTX_free(ctx); + + return ret; +-- +2.36.1 + diff --git a/backport-Moving-notify-check-after-the-no-time-check.patch b/backport-Moving-notify-check-after-the-no-time-check.patch new file mode 100644 index 0000000..1f4dbf5 --- /dev/null +++ b/backport-Moving-notify-check-after-the-no-time-check.patch @@ -0,0 +1,40 @@ +From 9eae491721209f302a9a475bffd271370e8bcb8f Mon Sep 17 00:00:00 2001 +From: Ryan Kelley +Date: Tue, 16 Aug 2022 05:28:50 +0000 +Subject: [PATCH] Moving notify check after the no time check + +CLA: trivial + +Reviewed-by: Tomas Mraz +Reviewed-by: Paul Dale +(Merged from https://github.com/openssl/openssl/pull/19007) + +(cherry picked from commit c92c3dfb99485eb2cfb840e92bd0ece8cdd72d0c) +--- + crypto/x509/x509_vfy.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/crypto/x509/x509_vfy.c b/crypto/x509/x509_vfy.c +index b18489f67f..925fbb5412 100644 +--- a/crypto/x509/x509_vfy.c ++++ b/crypto/x509/x509_vfy.c +@@ -973,14 +973,14 @@ static int check_crl_time(X509_STORE_CTX *ctx, X509_CRL *crl, int notify) + time_t *ptime; + int i; + +- if (notify) +- ctx->current_crl = crl; + if (ctx->param->flags & X509_V_FLAG_USE_CHECK_TIME) + ptime = &ctx->param->check_time; + else if (ctx->param->flags & X509_V_FLAG_NO_CHECK_TIME) + return 1; + else + ptime = NULL; ++ if (notify) ++ ctx->current_crl = crl; + + i = X509_cmp_time(X509_CRL_get0_lastUpdate(crl), ptime); + if (i == 0) { +-- +2.17.1 + diff --git a/backport-Prevent-crash-with-engine-using-different-openssl-ru.patch b/backport-Prevent-crash-with-engine-using-different-openssl-ru.patch new file mode 100644 index 0000000..3a14ffb --- /dev/null +++ b/backport-Prevent-crash-with-engine-using-different-openssl-ru.patch @@ -0,0 +1,44 @@ +From 38ac4415a9cc4cca307c866e5fc548b889fe2bb6 Mon Sep 17 00:00:00 2001 +From: Bernd Edlinger +Date: Mon, 22 Nov 2021 21:50:04 +0100 +Subject: [PATCH] Prevent crash with engine using different openssl runtime + +This problem happens usually because an application +links libcrypto and/or libssl statically which +installs an atexit handler, but later an engine using +a shared instance of libcrypto is installed. +The problem is in simple words that both instances +of libcrypto have an atexit handler installed, +but both are unable to coordinate with each other, +which causes a crash, typically a use-after-free +in the engine's destroy function. + +Work around that by preventing the engine's +libcrypto to install the atexit handler. +This may result in a small memory leak, but that +memory is still reachable. + +Fixes #15898 + +Reviewed-by: Richard Levitte +Reviewed-by: Tomas Mraz +(Merged from https://github.com/openssl/openssl/pull/17541) +--- + include/openssl/engine.h | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/include/openssl/engine.h b/include/openssl/engine.h +index 0780f0fb5f..756751c6d3 100644 +--- a/include/openssl/engine.h ++++ b/include/openssl/engine.h +@@ -722,6 +722,7 @@ typedef int (*dynamic_bind_engine) (ENGINE *e, const char *id, + CRYPTO_set_mem_functions(fns->mem_fns.malloc_fn, \ + fns->mem_fns.realloc_fn, \ + fns->mem_fns.free_fn); \ ++ OPENSSL_init_crypto(OPENSSL_INIT_NO_ATEXIT, NULL); \ + skip_cbs: \ + if (!fn(e, id)) return 0; \ + return 1; } +-- +2.38.1.windows.1 + diff --git a/backport-Test-case-for-a2i_IPADDRESS.patch b/backport-Test-case-for-a2i_IPADDRESS.patch new file mode 100644 index 0000000..e0c1a6a --- /dev/null +++ b/backport-Test-case-for-a2i_IPADDRESS.patch @@ -0,0 +1,91 @@ +From bd41b84bede84c1a5716be4eafddd1dd052faa72 Mon Sep 17 00:00:00 2001 +From: Christian Heimes +Date: Sat, 15 Aug 2020 20:01:49 +0200 +Subject: [PATCH] Test case for a2i_IPADDRESS + +Unit test to show that a2i_IPADDRESS("1.2.3.4.test.example") ignores +trailing data. + +See: https://github.com/openssl/openssl/issues/12649 +See: https://bugs.python.org/issue41556 + +(cherry picked from commit 1a9411a30b09a98498366979a1ea4898f70f6d19) + +Reviewed-by: Tomas Mraz +Reviewed-by: Dmitry Belyavskiy +Reviewed-by: Hugo Landau +(Merged from https://github.com/openssl/openssl/pull/18847) +--- + test/x509_internal_test.c | 54 +++++++++++++++++++++++++++++++++++++++ + 1 file changed, 54 insertions(+) + +diff --git a/test/x509_internal_test.c b/test/x509_internal_test.c +index d2f41d7085..3eec970352 100644 +--- a/test/x509_internal_test.c ++++ b/test/x509_internal_test.c +@@ -57,8 +57,62 @@ static int test_standard_exts(void) + return good; + } + ++typedef struct { ++ const char *ipasc; ++ const char *data; ++ int length; ++ ASN1_OCTET_STRING ip; ++} IP_TESTDATA; ++ ++static IP_TESTDATA a2i_ipaddress_tests[] = { ++ {"127.0.0.1", "\x7f\x00\x00\x01", 4}, ++ {"1.2.3.4", "\x01\x02\x03\x04", 4}, ++ {"1.2.3.255", "\x01\x02\x03\xff", 4}, ++ {"1.2.3", NULL, 0}, ++ {"1.2.3 .4", NULL, 0}, ++ ++ {"::1", "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01", 16}, ++ {"1:1:1:1:1:1:1:1", "\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01", 16}, ++ {"2001:db8::ff00:42:8329", "\x20\x01\x0d\xb8\x00\x00\x00\x00\x00\x00\xff\x00\x00\x42\x83\x29", 16}, ++ {"1:1:1:1:1:1:1:1.test", NULL, 0}, ++ {":::1", NULL, 0}, ++ {"2001::123g", NULL, 0}, ++ ++ {"example.test", NULL, 0}, ++ {"", NULL, 0}, ++ ++ {"1.2.3.4.example.test", NULL, 0}, ++ {"1.2.3.4 ", NULL, 0}, ++}; ++ ++ ++static int test_a2i_ipaddress(int idx) ++{ ++ int good = 1; ++ ASN1_OCTET_STRING *ip; ++ int len = a2i_ipaddress_tests[idx].length; ++ ++ ip = a2i_IPADDRESS(a2i_ipaddress_tests[idx].ipasc); ++ if (len == 0) { ++ if (!TEST_ptr_null(ip)) { ++ good = 0; ++ TEST_note("'%s' should not be parsed as IP address", a2i_ipaddress_tests[idx].ipasc); ++ } ++ } else { ++ if (!TEST_ptr(ip) ++ || !TEST_int_eq(ASN1_STRING_length(ip), len) ++ || !TEST_mem_eq(ASN1_STRING_get0_data(ip), len, ++ a2i_ipaddress_tests[idx].data, len)) { ++ good = 0; ++ } ++ } ++ ASN1_OCTET_STRING_free(ip); ++ return good; ++} ++ + int setup_tests(void) + { + ADD_TEST(test_standard_exts); ++ ADD_ALL_TESTS(test_a2i_ipaddress, OSSL_NELEM(a2i_ipaddress_tests)); + return 1; + } +-- +2.17.1 + diff --git a/backport-Test-that-swapping-the-first-app-data-record-with-Fi.patch b/backport-Test-that-swapping-the-first-app-data-record-with-Fi.patch new file mode 100644 index 0000000..6856681 --- /dev/null +++ b/backport-Test-that-swapping-the-first-app-data-record-with-Fi.patch @@ -0,0 +1,183 @@ +From d87e99df3162b2d56b8d44907fde88b67d7e3900 Mon Sep 17 00:00:00 2001 +From: Matt Caswell +Date: Mon, 25 Jul 2022 12:39:52 +0100 +Subject: [PATCH] Test that swapping the first app data record with Finished + msg works + +If the first app data record arrives before the Finished message we should +be able to buffer it and move on to the Finished message. + +Reviewed-by: Hugo Landau +Reviewed-by: Tomas Mraz +(Merged from https://github.com/openssl/openssl/pull/18976) +--- + test/dtlstest.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++ + test/ssltestlib.c | 33 ++++++++++++++++++ + test/ssltestlib.h | 1 + + 3 files changed, 122 insertions(+) + +diff --git a/test/dtlstest.c b/test/dtlstest.c +index 1d7b105fb6..f5c9dcfcd8 100644 +--- a/test/dtlstest.c ++++ b/test/dtlstest.c +@@ -328,6 +328,93 @@ static int test_dtls_duplicate_records(void) + return testresult; + } + ++/* ++ * Test that swapping an app data record so that it is received before the ++ * Finished message still works. ++ */ ++static int test_swap_app_data(void) ++{ ++ SSL_CTX *sctx = NULL, *cctx = NULL; ++ SSL *sssl = NULL, *cssl = NULL; ++ int testresult = 0; ++ BIO *bio; ++ char msg[] = { 0x00, 0x01, 0x02, 0x03 }; ++ char buf[10]; ++ ++ if (!TEST_true(create_ssl_ctx_pair(DTLS_server_method(), ++ DTLS_client_method(), ++ DTLS1_VERSION, 0, ++ &sctx, &cctx, cert, privkey))) ++ return 0; ++ ++#ifndef OPENSSL_NO_DTLS1_2 ++ if (!TEST_true(SSL_CTX_set_cipher_list(cctx, "AES128-SHA"))) ++ goto end; ++#else ++ /* Default sigalgs are SHA1 based in pkts); ++ ++ /* We need at least 2 packets to be able to swap them */ ++ if (numpkts <= 1) ++ return 0; ++ ++ /* Get the penultimate packet */ ++ thispkt = sk_MEMPACKET_value(ctx->pkts, numpkts - 2); ++ if (thispkt == NULL) ++ return 0; ++ ++ if (sk_MEMPACKET_delete(ctx->pkts, numpkts - 2) != thispkt) ++ return 0; ++ ++ /* Re-add it to the end of the list */ ++ thispkt->num++; ++ if (sk_MEMPACKET_insert(ctx->pkts, thispkt, numpkts - 1) <= 0) ++ return 0; ++ ++ /* We also have to adjust the packet number of the other packet */ ++ thispkt = sk_MEMPACKET_value(ctx->pkts, numpkts - 2); ++ if (thispkt == NULL) ++ return 0; ++ thispkt->num--; ++ ++ return 1; ++} ++ + int mempacket_test_inject(BIO *bio, const char *in, int inl, int pktnum, + int type) + { +diff --git a/test/ssltestlib.h b/test/ssltestlib.h +index 17b278219a..b47004f62e 100644 +--- a/test/ssltestlib.h ++++ b/test/ssltestlib.h +@@ -46,6 +46,7 @@ void bio_s_always_retry_free(void); + #define MEMPACKET_CTRL_GET_DROP_REC (3 << 15) + #define MEMPACKET_CTRL_SET_DUPLICATE_REC (4 << 15) + ++int mempacket_swap_recent(BIO *bio); + int mempacket_test_inject(BIO *bio, const char *in, int inl, int pktnum, + int type); + +-- +2.17.1 + diff --git a/backport-X509-x509_req.c-Set-modified-flag-when-X509_req_info.patch b/backport-X509-x509_req.c-Set-modified-flag-when-X509_req_info.patch new file mode 100644 index 0000000..ac2e0f1 --- /dev/null +++ b/backport-X509-x509_req.c-Set-modified-flag-when-X509_req_info.patch @@ -0,0 +1,111 @@ +From 002cf9a68e20700388326c92b0c9ec8630b5c5d2 Mon Sep 17 00:00:00 2001 +From: Gibeom Gwon +Date: Sat, 27 Aug 2022 22:04:38 +0900 +Subject: [PATCH] X509 x509_req.c: Set 'modified' flag when X509_req_info_st + member data updated + +We need to reencode X509_req_info_st if member data updated. + +Reviewed-by: Tomas Mraz +Reviewed-by: David von Oheimb +(Merged from https://github.com/openssl/openssl/pull/18879) +--- + crypto/x509/x509_req.c | 40 ++++++++++++++++++++++++---------------- + crypto/x509/x_all.c | 2 ++ + 2 files changed, 26 insertions(+), 16 deletions(-) + +diff --git a/crypto/x509/x509_req.c b/crypto/x509/x509_req.c +index a69f9a723d..1be47174ac 100644 +--- a/crypto/x509/x509_req.c ++++ b/crypto/x509/x509_req.c +@@ -229,44 +229,52 @@ X509_ATTRIBUTE *X509_REQ_get_attr(const X509_REQ *req, int loc) + + X509_ATTRIBUTE *X509_REQ_delete_attr(X509_REQ *req, int loc) + { +- return X509at_delete_attr(req->req_info.attributes, loc); ++ X509_ATTRIBUTE *attr = X509at_delete_attr(req->req_info.attributes, loc); ++ ++ if (attr != NULL) ++ req->req_info.enc.modified = 1; ++ return attr; + } + + int X509_REQ_add1_attr(X509_REQ *req, X509_ATTRIBUTE *attr) + { +- if (X509at_add1_attr(&req->req_info.attributes, attr)) +- return 1; +- return 0; ++ if (!X509at_add1_attr(&req->req_info.attributes, attr)) ++ return 0; ++ req->req_info.enc.modified = 1; ++ return 1; + } + + int X509_REQ_add1_attr_by_OBJ(X509_REQ *req, + const ASN1_OBJECT *obj, int type, + const unsigned char *bytes, int len) + { +- if (X509at_add1_attr_by_OBJ(&req->req_info.attributes, obj, +- type, bytes, len)) +- return 1; +- return 0; ++ if (!X509at_add1_attr_by_OBJ(&req->req_info.attributes, obj, ++ type, bytes, len)) ++ return 0; ++ req->req_info.enc.modified = 1; ++ return 1; + } + + int X509_REQ_add1_attr_by_NID(X509_REQ *req, + int nid, int type, + const unsigned char *bytes, int len) + { +- if (X509at_add1_attr_by_NID(&req->req_info.attributes, nid, +- type, bytes, len)) +- return 1; +- return 0; ++ if (!X509at_add1_attr_by_NID(&req->req_info.attributes, nid, ++ type, bytes, len)) ++ return 0; ++ req->req_info.enc.modified = 1; ++ return 1; + } + + int X509_REQ_add1_attr_by_txt(X509_REQ *req, + const char *attrname, int type, + const unsigned char *bytes, int len) + { +- if (X509at_add1_attr_by_txt(&req->req_info.attributes, attrname, +- type, bytes, len)) +- return 1; +- return 0; ++ if (!X509at_add1_attr_by_txt(&req->req_info.attributes, attrname, ++ type, bytes, len)) ++ return 0; ++ req->req_info.enc.modified = 1; ++ return 1; + } + + long X509_REQ_get_version(const X509_REQ *req) +diff --git a/crypto/x509/x_all.c b/crypto/x509/x_all.c +index a4e9cdaee8..ae061f234c 100644 +--- a/crypto/x509/x_all.c ++++ b/crypto/x509/x_all.c +@@ -65,12 +65,14 @@ int X509_http_nbio(OCSP_REQ_CTX *rctx, X509 **pcert) + + int X509_REQ_sign(X509_REQ *x, EVP_PKEY *pkey, const EVP_MD *md) + { ++ x->req_info.enc.modified = 1; + return (ASN1_item_sign(ASN1_ITEM_rptr(X509_REQ_INFO), &x->sig_alg, NULL, + x->signature, &x->req_info, pkey, md)); + } + + int X509_REQ_sign_ctx(X509_REQ *x, EVP_MD_CTX *ctx) + { ++ x->req_info.enc.modified = 1; + return ASN1_item_sign_ctx(ASN1_ITEM_rptr(X509_REQ_INFO), + &x->sig_alg, NULL, x->signature, &x->req_info, + ctx); +-- +2.17.1 + diff --git a/backport-X509_REQ_get_extensions-Return-empty-stack-if-no-ext.patch b/backport-X509_REQ_get_extensions-Return-empty-stack-if-no-ext.patch new file mode 100644 index 0000000..1bc0efd --- /dev/null +++ b/backport-X509_REQ_get_extensions-Return-empty-stack-if-no-ext.patch @@ -0,0 +1,32 @@ +From 0b755cdfb52ff51830aa004799e1f78548423c00 Mon Sep 17 00:00:00 2001 +From: "Dr. David von Oheimb" +Date: Fri, 8 Jan 2021 08:27:17 +0100 +Subject: [PATCH] X509_REQ_get_extensions(): Return empty stack if no + extensions found + +Reviewed-by: Tomas Mraz +Reviewed-by: Todd Short +Reviewed-by: David von Oheimb +(Merged from https://github.com/openssl/openssl/pull/18926) +--- + crypto/x509/x509_req.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/crypto/x509/x509_req.c b/crypto/x509/x509_req.c +index dd674926dd..a69f9a723d 100644 +--- a/crypto/x509/x509_req.c ++++ b/crypto/x509/x509_req.c +@@ -167,7 +167,9 @@ STACK_OF(X509_EXTENSION) *X509_REQ_get_extensions(X509_REQ *req) + ext = X509_ATTRIBUTE_get0_type(attr, 0); + break; + } +- if (!ext || (ext->type != V_ASN1_SEQUENCE)) ++ if (ext == NULL) /* no extensions is not an error */ ++ return sk_X509_EXTENSION_new_null(); ++ if (ext->type != V_ASN1_SEQUENCE) + return NULL; + p = ext->value.sequence->data; + return (STACK_OF(X509_EXTENSION) *) +-- +2.17.1 + diff --git a/backport-ssl_cipher_process_rulestr-don-t-read-outside-rule_s.patch b/backport-ssl_cipher_process_rulestr-don-t-read-outside-rule_s.patch new file mode 100644 index 0000000..7cfa6ef --- /dev/null +++ b/backport-ssl_cipher_process_rulestr-don-t-read-outside-rule_s.patch @@ -0,0 +1,40 @@ +From 9b3219ba544db82cdad3058b9872058739559944 Mon Sep 17 00:00:00 2001 +From: "Todd C. Miller" +Date: Mon, 24 Oct 2022 08:00:48 -0600 +Subject: [PATCH] ssl_cipher_process_rulestr: don't read outside rule_str + buffer + +If rule_str ended in a "-", "l" was incremented one byte past the +end of the buffer. This resulted in an out-of-bounds read when "l" +is dereferenced at the end of the loop. It is safest to just return +early in this case since the condition occurs inside a nested loop. + +CLA: trivial + +Reviewed-by: Paul Dale +Reviewed-by: Tomas Mraz +(Merged from https://github.com/openssl/openssl/pull/19166) + +(cherry picked from commit 428511ca66670e169a0e1b12e7540714b0be4cf8) +--- + ssl/ssl_ciph.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/ssl/ssl_ciph.c b/ssl/ssl_ciph.c +index 55f919fcd5..62d0a58b22 100644 +--- a/ssl/ssl_ciph.c ++++ b/ssl/ssl_ciph.c +@@ -1026,9 +1026,7 @@ static int ssl_cipher_process_rulestr(const char *rule_str, + * alphanumeric, so we call this an error. + */ + SSLerr(SSL_F_SSL_CIPHER_PROCESS_RULESTR, SSL_R_INVALID_COMMAND); +- retval = found = 0; +- l++; +- break; ++ return 0; + } + + if (rule == CIPHER_SPECIAL) { +-- +2.17.1 + diff --git a/openssl.spec b/openssl.spec index b99d165..949497f 100644 --- a/openssl.spec +++ b/openssl.spec @@ -2,7 +2,7 @@ Name: openssl Epoch: 1 Version: 1.1.1m -Release: 18 +Release: 19 Summary: Cryptography and SSL/TLS Toolkit License: OpenSSL and SSLeay URL: https://www.openssl.org/ @@ -64,6 +64,53 @@ Patch53: backport-CVE-2022-4450-Avoid-dangling-ptrs-in-header-and-data-param Patch54: backport-CVE-2023-0215-Check-CMS-failure-during-BIO-setup-with-stream-is-ha.patch Patch55: backport-CVE-2023-0215-Fix-a-UAF-resulting-from-a-bug-in-BIO_new_NDEF.patch Patch56: backport-CVE-2023-0286-Fix-GENERAL_NAME_cmp-for-x400Address-1.patch +Patch57: Backport-Support-raw-input-data-in-apps-pkeyutl.patch +Patch58: Backport-Fix-no-ec-no-sm2-and-no-sm3.patch +Patch59: Backport-Support-SM2-certificate-verification.patch +Patch60: Backport-Guard-some-SM2-functions-with-OPENSSL_NO_SM2.patch +Patch61: Backport-Add-test-cases-for-SM2-cert-verification.patch +Patch62: Backport-Add-documents-for-SM2-cert-verification.patch +Patch63: Backport-Fix-a-memleak-in-apps-verify.patch +Patch64: Backport-Skip-the-correct-number-of-tests-if-SM2-is-disabled.patch +Patch65: Backport-Make-X509_set_sm2_id-consistent-with-other-setters.patch +Patch66: Backport-Support-SM2-certificate-signing.patch +Patch67: Backport-Support-parsing-of-SM2-ID-in-hexdecimal.patch +Patch68: Backport-Fix-a-double-free-issue-when-signing-SM2-cert.patch +Patch69: Backport-Fix-a-document-description-in-apps-req.patch +Patch70: backport-Backport-a-missing-bug-fix-from-master.patch +Patch71: backport-Prevent-crash-with-engine-using-different-openssl-ru.patch +Patch72: backport-APPS-x509-With-CA-but-both-CAserial-and-CAcreateseri.patch +Patch73: backport-Fix-verify_callback-in-the-openssl-s_client-s_server.patch +Patch74: backport-Fix-re-signing-certificates-with-different-key-sizes.patch +Patch75: backport-Fix-ipv4_from_asc-behavior-on-invalid-Ip-addresses.patch +Patch76: backport-Test-case-for-a2i_IPADDRESS.patch +Patch77: backport-Fix-test-case-for-a2i_IPADDRESS.patch +Patch78: backport-Fix-a-crash-in-v2i_IPAddrBlocks.patch +Patch79: backport-Fixes-segfault-occurrence-in-PEM_write.patch +Patch80: backport-X509_REQ_get_extensions-Return-empty-stack-if-no-ext.patch +Patch81: backport-Fix-EC_KEY_set_private_key-priv_key-regression.patch +Patch82: backport-Add-test-for-EC_KEY_set_private_key.patch +Patch83: backport-Fix-SSL_pending-and-SSL_has_pending-with-DTLS.patch +Patch84: backport-Test-that-swapping-the-first-app-data-record-with-Fi.patch +Patch85: backport-Always-end-BN_mod_exp_mont_consttime-with-normal-Mon.patch +Patch86: backport-Add-an-extra-reduction-step-to-RSAZ-mod_exp-implemen.patch +Patch87: backport-Coverity-1508534-1508540-misuses-of-time_t.patch +Patch88: backport-Moving-notify-check-after-the-no-time-check.patch +Patch89: backport-Convert-serverinfo-in-SSL_CTX_use_serverinfo-to-v2.patch +Patch90: backport-X509-x509_req.c-Set-modified-flag-when-X509_req_info.patch +Patch91: backport-ssl_cipher_process_rulestr-don-t-read-outside-rule_s.patch +Patch92: backport-Fix-BIO_f_asn1-to-properly-report-some-errors.patch +Patch93: backport-Fix-BIO_f_cipher-flushing.patch +Patch94: backport-Fix-SMIME_crlf_copy-to-properly-report-an-error.patch +Patch95: backport-Fix-a-memory-leak-in-rsa_priv_encode.patch +Patch96: backport-Fix-the-ceiling-on-how-much-encryption-growth-we-can.patch +Patch97: backport-Ensure-our-buffer-allocation-allows-for-the-Explicit.patch +Patch98: backport-Add-a-test-for-large-app-data.patch +Patch99: backport-Add-DTLS-support-to-the-large-app-data-test.patch +Patch100: backport-Fix-a-logic-flaw-in-test_mod_exp_zero.patch +Patch101: backport-Coverity-1508506-misuse-of-time_t.patch +Patch102: backport-Limit-size-of-modulus-for-bn_mul_mont-and-BN_mod_exp.patch + BuildRequires: gcc perl make lksctp-tools-devel coreutils util-linux zlib-devel Requires: coreutils %{name}-libs%{?_isa} = %{epoch}:%{version}-%{release} @@ -272,6 +319,9 @@ make test || : %ldconfig_scriptlets libs %changelog +* Thu Mar 23 2023 wangcheng - 1:1.1.1m-19 +- backport some patches + * Thu Feb 9 2023 ExtinctFire - 1:1.1.1m-18 - fix some CVE -- Gitee