From cc4397a1cb887c9f5100d879e3cf32556ca479b1 Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Mon, 11 Dec 2023 15:19:47 +0100 Subject: [PATCH 01/92] Fix provider compatibility check crash in evp_test EVP_MAC_CTX_get_mac_size() cannot be called on older unfixed versions before EVP_MAC_init(). Reviewed-by: Neil Horman Reviewed-by: Shane Lontis (Merged from https://github.com/openssl/openssl/pull/23006) Signed-off-by: lanming1120 --- test/evp_test.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/evp_test.c b/test/evp_test.c index cef7b1b9e8..ecc7f7fe20 100644 --- a/test/evp_test.c +++ b/test/evp_test.c @@ -1514,7 +1514,7 @@ static int mac_test_run_mac(EVP_TEST *t) EVP_MAC_CTX *ctx = NULL; unsigned char *got = NULL; size_t got_len = 0, size = 0; - size_t size_before_init, size_after_init, size_val = 0; + size_t size_before_init = 0, size_after_init, size_val = 0; int i, block_size = -1, output_size = -1; OSSL_PARAM params[21], sizes[3], *psizes = sizes; size_t params_n = 0; @@ -1622,7 +1622,8 @@ static int mac_test_run_mac(EVP_TEST *t) t->err = "MAC_CREATE_ERROR"; goto err; } - size_before_init = EVP_MAC_CTX_get_mac_size(ctx); + if (fips_provider_version_gt(libctx, 3, 2, 0)) + size_before_init = EVP_MAC_CTX_get_mac_size(ctx); if (!EVP_MAC_init(ctx, expected->key, expected->key_len, params)) { t->err = "MAC_INIT_ERROR"; goto err; -- Gitee From f34dc7196f161e0455b524b320f7ed55b0c59c71 Mon Sep 17 00:00:00 2001 From: Dmitry Kobets <89153909+dmitrykobets-msft@users.noreply.github.com> Date: Thu, 14 Dec 2023 20:12:43 -0800 Subject: [PATCH 02/92] Fix instructions for running tests on Windows In the command `nmake TEST='foo' test`, on Windows the runner will look for test `'foo'` and complain about the test not being found (due to the extraneous single quotes), whereas with `nmake TEST="foo" test`, the test `foo` will be correctly found. CLA: trivial Reviewed-by: Tom Cosgrove Reviewed-by: Matthias St. Pierre Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/23059) Signed-off-by: lanming1120 --- test/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/README.md b/test/README.md index fe25bd8b4e..746a0156ce 100644 --- a/test/README.md +++ b/test/README.md @@ -42,7 +42,7 @@ the make variable TESTS to specify them, like this: $ make TESTS='test_rsa test_dsa' test # Unix $ mms/macro="TESTS=test_rsa test_dsa" test ! OpenVMS - $ nmake TESTS='test_rsa test_dsa' test # Windows + $ nmake TESTS="test_rsa test_dsa" test # Windows And of course, you can combine (Unix examples shown): -- Gitee From 139e849237c731508ed96e205cfdfc97aa786f98 Mon Sep 17 00:00:00 2001 From: Frederik Wedel-Heinen Date: Fri, 8 Dec 2023 21:00:43 +0100 Subject: [PATCH 03/92] Handle tls and dtls server version selection similarly Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/22989) Signed-off-by: lanming1120 --- ssl/statem/statem_srvr.c | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/ssl/statem/statem_srvr.c b/ssl/statem/statem_srvr.c index 853af8c0aa..b0f700dda4 100644 --- a/ssl/statem/statem_srvr.c +++ b/ssl/statem/statem_srvr.c @@ -1735,16 +1735,14 @@ static int tls_early_post_process_client_hello(SSL_CONNECTION *s) s->client_version = clienthello->legacy_version; } /* - * Do SSL/TLS version negotiation if applicable. For DTLS we just check - * versions are potentially compatible. Version negotiation comes later. + * Do SSL/TLS version negotiation if applicable. */ - if (!SSL_CONNECTION_IS_DTLS(s)) { - protverr = ssl_choose_server_version(s, clienthello, &dgrd); - } else if (ssl->method->version != DTLS_ANY_VERSION && - DTLS_VERSION_LT((int)clienthello->legacy_version, s->version)) { + if (SSL_CONNECTION_IS_DTLS(s) + && ssl->method->version != DTLS_ANY_VERSION + && DTLS_VERSION_LT((int)clienthello->legacy_version, s->version)) { protverr = SSL_R_VERSION_TOO_LOW; } else { - protverr = 0; + protverr = ssl_choose_server_version(s, clienthello, &dgrd); } if (protverr) { @@ -1783,14 +1781,6 @@ static int tls_early_post_process_client_hello(SSL_CONNECTION *s) } s->d1->cookie_verified = 1; } - if (ssl->method->version == DTLS_ANY_VERSION) { - protverr = ssl_choose_server_version(s, clienthello, &dgrd); - if (protverr != 0) { - s->version = s->client_version; - SSLfatal(s, SSL_AD_PROTOCOL_VERSION, protverr); - goto err; - } - } } s->hit = 0; -- Gitee From 60ba40d7b2cba37d948413b1197f1683967a8858 Mon Sep 17 00:00:00 2001 From: Frederik Wedel-Heinen Date: Tue, 12 Dec 2023 12:58:01 +0100 Subject: [PATCH 04/92] Remove redundant logic for DTLS server version selection Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/22989) Signed-off-by: lanming1120 --- ssl/statem/statem_srvr.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/ssl/statem/statem_srvr.c b/ssl/statem/statem_srvr.c index b0f700dda4..da77c16e6b 100644 --- a/ssl/statem/statem_srvr.c +++ b/ssl/statem/statem_srvr.c @@ -1734,16 +1734,9 @@ static int tls_early_post_process_client_hello(SSL_CONNECTION *s) /* SSLv3/TLS */ s->client_version = clienthello->legacy_version; } - /* - * Do SSL/TLS version negotiation if applicable. - */ - if (SSL_CONNECTION_IS_DTLS(s) - && ssl->method->version != DTLS_ANY_VERSION - && DTLS_VERSION_LT((int)clienthello->legacy_version, s->version)) { - protverr = SSL_R_VERSION_TOO_LOW; - } else { - protverr = ssl_choose_server_version(s, clienthello, &dgrd); - } + + /* Choose the server SSL/TLS/DTLS version. */ + protverr = ssl_choose_server_version(s, clienthello, &dgrd); if (protverr) { if (SSL_IS_FIRST_HANDSHAKE(s)) { -- Gitee From 0ae67c4e32024cb0f1b70df200103df92c09aae6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Dec 2023 09:58:53 +0000 Subject: [PATCH 05/92] Bump actions/upload-artifact from 3 to 4 Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 3 to 4. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] CLA: trivial Reviewed-by: Kurt Roeckx Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/23053) Signed-off-by: lanming1120 --- .github/workflows/fips-checksums.yml | 4 ++-- .github/workflows/main.yml | 2 +- .github/workflows/provider-compatibility.yml | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/fips-checksums.yml b/.github/workflows/fips-checksums.yml index 9b0bec2a78..bbf135fd77 100644 --- a/.github/workflows/fips-checksums.yml +++ b/.github/workflows/fips-checksums.yml @@ -69,7 +69,7 @@ jobs: - name: save PR number run: echo ${{ github.event.number }} > ./artifact/pr_num - name: save artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: fips_checksum path: artifact/ @@ -113,7 +113,7 @@ jobs: - name: save PR number run: echo ${{ github.event.number }} > ./artifact/pr_num - name: save artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: abidiff path: artifact/ diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 8ff02cee27..e167416be5 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -26,7 +26,7 @@ jobs: fuzz-seconds: 600 dry-run: false - name: Upload Crash - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: failure() with: name: artifacts diff --git a/.github/workflows/provider-compatibility.yml b/.github/workflows/provider-compatibility.yml index 8fc125cbd8..803e6608f1 100644 --- a/.github/workflows/provider-compatibility.yml +++ b/.github/workflows/provider-compatibility.yml @@ -93,7 +93,7 @@ jobs: -providers working-directory: ${{ matrix.release.dir }} - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v4 with: name: ${{ matrix.release.tgz }} path: ${{ matrix.release.tgz }} @@ -169,7 +169,7 @@ jobs: run: make test HARNESS_JOBS=${HARNESS_JOBS:-4} working-directory: ${{ matrix.branch.dir }} - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v4 with: name: ${{ matrix.branch.tgz }} path: ${{ matrix.branch.tgz }} -- Gitee From a1867de8d8242879a288da9b86c463de557c3fc6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Dec 2023 10:05:05 +0000 Subject: [PATCH 06/92] Bump actions/download-artifact from 3 to 4 Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 3 to 4. - [Release notes](https://github.com/actions/download-artifact/releases) - [Commits](https://github.com/actions/download-artifact/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/download-artifact dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] CLA: trivial Reviewed-by: Kurt Roeckx Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/23052) Signed-off-by: lanming1120 --- .github/workflows/provider-compatibility.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/provider-compatibility.yml b/.github/workflows/provider-compatibility.yml index 803e6608f1..afb2782690 100644 --- a/.github/workflows/provider-compatibility.yml +++ b/.github/workflows/provider-compatibility.yml @@ -201,7 +201,7 @@ jobs: fi continue-on-error: true - - uses: actions/download-artifact@v3 + - uses: actions/download-artifact@v4 if: steps.early_exit.outcome == 'success' with: name: ${{ matrix.tree_a }}.tar.gz @@ -209,7 +209,7 @@ jobs: if: steps.early_exit.outcome == 'success' run: tar xzf "${{ matrix.tree_a }}.tar.gz" - - uses: actions/download-artifact@v3 + - uses: actions/download-artifact@v4 if: steps.early_exit.outcome == 'success' with: name: ${{ matrix.tree_b }}.tar.gz -- Gitee From 53c2a56256d1f836da1ccb74fdeee66746ef7bce Mon Sep 17 00:00:00 2001 From: Xi Ruoyao Date: Wed, 13 Dec 2023 03:36:48 +0800 Subject: [PATCH 07/92] Define L_ENDIAN for linux64-loongarch64 In commit d7c0fc5b1a7b5cb2219f8d89a861f3879582fc16 we removed L_ENDIAN definition for guessed linux64-loongarch64 as it had caused an inconsistency between configurations with and without explicit specifying linux64-loongarch64. Now add it back to the proper location. Unlike MIPS or RISC-V, LoongArch is always little-endian [1]. By the way, change "LOONGARCH" to "LoongArch" in a comment as LOONGARCH should only appear in the identifiers of macros, constants, etc. [1]:https://loongson.github.io/LoongArch-Documentation/LoongArch-Vol1-EN.html#endian Reviewed-by: Shane Lontis Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/23064) Signed-off-by: lanming1120 --- Configurations/10-main.conf | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Configurations/10-main.conf b/Configurations/10-main.conf index d1a15a1152..7fb0fda866 100644 --- a/Configurations/10-main.conf +++ b/Configurations/10-main.conf @@ -821,12 +821,13 @@ my %targets = ( asm_arch => 'riscv32', }, - # loongarch64 below refers to contemporary LOONGARCH Architecture + # loongarch64 below refers to contemporary LoongArch Architecture # specifications, "linux64-loongarch64" => { inherit_from => [ "linux-generic64"], perlasm_scheme => "linux64", asm_arch => 'loongarch64', + lib_cppflags => add("-DL_ENDIAN"), }, #### IA-32 targets... -- Gitee From 960edd2bf2feb63863c271f7cc05be3d0534ec02 Mon Sep 17 00:00:00 2001 From: James Muir Date: Thu, 14 Dec 2023 14:14:37 -0500 Subject: [PATCH 08/92] cms: avoid intermittent test failure If you decrypt a random input using RSAES-PKCS-v1_5, then there is a non-negligible chance that the result will look like a valid plaintext (that is why RSAES-PKCS-v1_5 shouldn't be used anymore). This was the cause of an intermittent failure in a test that did a cms-encrypt operation targetting multiple recipients. The failure happened during key-only decrypt. The recipient decrypts every RSA ciphertext -- only one is supposed to decrypt successfully, which would reveal the right content-key. Occassionally, more than one decrypted successfully. Update the test by specifying the recipient cert in the decrypt op (this avoids looping over all RSA ciphertexts). Add a new test to get coverage for key-only decrypt, but use RSA-OAEP during the encrypt op. Fixes https://github.com/openssl/project/issues/380 Testing: $ make TESTS='test_cms' test Reviewed-by: Neil Horman Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/23055) Signed-off-by: lanming1120 --- test/recipes/80-test_cms.t | 58 ++++++++++++++++++++++++++++--- test/smime-certs/mksmime-certs.sh | 3 ++ test/smime-certs/smrsa3-cert.pem | 21 +++++++++++ test/smime-certs/smrsa3-key.pem | 28 +++++++++++++++ 4 files changed, 106 insertions(+), 4 deletions(-) create mode 100644 test/smime-certs/smrsa3-cert.pem create mode 100644 test/smime-certs/smrsa3-key.pem diff --git a/test/recipes/80-test_cms.t b/test/recipes/80-test_cms.t index 0e1ebc50cd..3af1a0ce55 100644 --- a/test/recipes/80-test_cms.t +++ b/test/recipes/80-test_cms.t @@ -50,7 +50,7 @@ my ($no_des, $no_dh, $no_dsa, $no_ec, $no_ec2m, $no_rc2, $no_zlib) $no_rc2 = 1 if disabled("legacy"); -plan tests => 22; +plan tests => 23; ok(run(test(["pkcs7_test"])), "test pkcs7"); @@ -222,13 +222,15 @@ my @smime_pkcs7_tests = ( \&final_compare ], - [ "enveloped content test streaming S/MIME format, DES, 3 recipients, key only used", + [ "enveloped content test streaming S/MIME format, DES, 3 recipients, cert and key files used", [ "{cmd1}", @defaultprov, "-encrypt", "-in", $smcont, "-stream", "-out", "{output}.cms", $smrsa1, catfile($smdir, "smrsa2.pem"), - catfile($smdir, "smrsa3.pem") ], - [ "{cmd2}", @defaultprov, "-decrypt", "-inkey", catfile($smdir, "smrsa3.pem"), + catfile($smdir, "smrsa3-cert.pem") ], + [ "{cmd2}", @defaultprov, "-decrypt", + "-recip", catfile($smdir, "smrsa3-cert.pem"), + "-inkey", catfile($smdir, "smrsa3-key.pem"), "-in", "{output}.cms", "-out", "{output}.txt" ], \&final_compare ], @@ -1165,3 +1167,51 @@ with({ exit_checker => sub { return shift == 3; } }, ])), "Check for failure when cipher does not have an assigned OID (issue#22225)"); }); + +# Test encrypt to three recipients, and decrypt using key-only; +# i.e. do not follow the recommended practice of providing the +# recipient cert in the decrypt op. +# +# Use RSAES-OAEP for key-transport, not RSAES-PKCS-v1_5. +# +# Because the cert is not provided during decrypt, all RSA ciphertexts +# are decrypted in turn, and when/if there is a valid decryption, it +# is assumed the correct content-key has been recovered. +# +# That process may fail with RSAES-PKCS-v1_5 b/c there is a +# non-negligible chance that decrypting a random input using +# RSAES-PKCS-v1_5 can result in a valid plaintext (so two content-keys +# could be recovered and the wrong one might be used). +# +# See https://github.com/openssl/project/issues/380 +subtest "encrypt to three recipients with RSA-OAEP, key only decrypt" => sub { + plan tests => 3; + + my $pt = srctop_file("test", "smcont.txt"); + my $ct = "smtst.cms"; + my $ptpt = "smtst.txt"; + + ok(run(app(['openssl', 'cms', + @defaultprov, + '-encrypt', + '-in', $pt, + '-out', $ct, + '-stream', + '-recip', catfile($smdir, "smrsa1.pem"), + '-keyopt', 'rsa_padding_mode:oaep', + '-recip', catfile($smdir, "smrsa2.pem"), + '-keyopt', 'rsa_padding_mode:oaep', + '-recip', catfile($smdir, "smrsa3-cert.pem"), + '-keyopt', 'rsa_padding_mode:oaep', + ])), + "encrypt to three recipients with RSA-OAEP (avoid openssl/project issue#380)"); + ok(run(app(['openssl', 'cms', + @defaultprov, + '-decrypt', + '-in', $ct, + '-out', $ptpt, + '-inkey', catfile($smdir, "smrsa3-key.pem"), + ])), + "decrypt with key only"); + is(compare($pt, $ptpt), 0, "compare original message with decrypted ciphertext"); +}; diff --git a/test/smime-certs/mksmime-certs.sh b/test/smime-certs/mksmime-certs.sh index ab7e22a136..0edf1d789e 100644 --- a/test/smime-certs/mksmime-certs.sh +++ b/test/smime-certs/mksmime-certs.sh @@ -30,6 +30,9 @@ gen smrsa2.pem "/CN=Test SMIME EE RSA #2" usr_rsa_cert >>smrsa2.pem cp ../certs/ee-key-4096.pem smrsa3.pem gen smrsa3.pem "/CN=Test SMIME EE RSA #3" usr_rsa_cert >>smrsa3.pem +$OPENSSL x509 -in smrsa3.pem > smrsa3-cert.pem +$OPENSSL pkey -in smrsa3.pem > smrsa3-key.pem + # Create DSA certificates with respective extensions cp ../certs/server-dsa-key.pem smdsa1.pem diff --git a/test/smime-certs/smrsa3-cert.pem b/test/smime-certs/smrsa3-cert.pem new file mode 100644 index 0000000000..70004acb86 --- /dev/null +++ b/test/smime-certs/smrsa3-cert.pem @@ -0,0 +1,21 @@ +-----BEGIN CERTIFICATE----- +MIIDeTCCAmGgAwIBAgIUIDyc//j/LoNDesZTGbPBoVarv4EwDQYJKoZIhvcNAQEL +BQAwRDELMAkGA1UEBhMCVUsxFjAUBgNVBAoMDU9wZW5TU0wgR3JvdXAxHTAbBgNV +BAMMFFRlc3QgUy9NSU1FIFJTQSBSb290MCAXDTIyMDYwMjE1MzMxM1oYDzIxMjIw +NTA5MTUzMzEzWjBFMQswCQYDVQQGEwJVSzEWMBQGA1UECgwNT3BlblNTTCBHcm91 +cDEeMBwGA1UEAwwVVGVzdCBTL01JTUUgRUUgUlNBICMzMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEA+QP7d56K4/9eu7aChtWILYNxvqWeDcJeWvX5Z5vC +XUjFuUxBD9U0rw1SBLgFYu8aqAJ+oXsqaGjJARifgKEqPUe7pnYYatr55lhTbHR+ +qA88p1V4sclEaPNWKzd7J/V3eeYr04kqWV5XYhAq9k9AWLzsNIePe2z7OoGPS6oK +wRzWFRd5RYXTpmFr/tqknbYvtYFd7duKb9QqytgHV+RKXXeY0fnjZ7frLmaqDwtI +U3DY7MyS3Hw2BVx72vQXBNA364HGEpqEgVOdzI7et0wpSumaFXDye714xUR53L7N +f3fp3PQXS/RbBiNXs7KUsHCR6nsdsIKO+sg66gxOLNt6zwIDAQABo2AwXjAMBgNV +HRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIF4DAdBgNVHQ4EFgQUN9pGq/UFS3o50rTi +V+AYgAk+3R4wHwYDVR0jBBgwFoAUFcETIWviVV+nah1XINbP86lzZFkwDQYJKoZI +hvcNAQELBQADggEBAGcOh380/6aJqMpYBssuf2CB3DX/hGKdvEF7fF8iNSfl5HHq +112kHl3MhbL9Th/safJq9sLDJqjXRNdVCUJJbU4YI2P2gsi04paC0qxWxMLtzQLd +CE7ki2xH94Fuu/dThbpzZBABROO1RrdI24GDGt9t4Gf0WVkobmT/zNlwGppKTIB2 +iV/Ug30iKr/C49UzwUIa+XXXujkjPTmGSnrKwVQNxQh81rb+iTL7GEnNuqDsatHW +ZyLS2SaVdG5tMqDkITPMDGjehUzJcAbVc8Bv4m8Ukuov3uDj2Doc6MxlvrVkV0AE +BcSCb/bWQJJ/X4LQZlx9cMk4NINxV9UeFPZOefg= +-----END CERTIFICATE----- diff --git a/test/smime-certs/smrsa3-key.pem b/test/smime-certs/smrsa3-key.pem new file mode 100644 index 0000000000..216d70b61b --- /dev/null +++ b/test/smime-certs/smrsa3-key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQD5A/t3norj/167 +toKG1Ygtg3G+pZ4Nwl5a9flnm8JdSMW5TEEP1TSvDVIEuAVi7xqoAn6heypoaMkB +GJ+AoSo9R7umdhhq2vnmWFNsdH6oDzynVXixyURo81YrN3sn9Xd55ivTiSpZXldi +ECr2T0BYvOw0h497bPs6gY9LqgrBHNYVF3lFhdOmYWv+2qSdti+1gV3t24pv1CrK +2AdX5Epdd5jR+eNnt+suZqoPC0hTcNjszJLcfDYFXHva9BcE0DfrgcYSmoSBU53M +jt63TClK6ZoVcPJ7vXjFRHncvs1/d+nc9BdL9FsGI1ezspSwcJHqex2wgo76yDrq +DE4s23rPAgMBAAECggEAEDi+VWD5VUpjD5zWOoPQiRDGBJBhtMAKkl6okxEmXvWb +Xz3STFnjHgA1JFHW3bRU9BHI9k8vSHmnlnkfKb3V/ZX5IHNcKCHb/x9NBak+QLVQ +0zLtfE9vxiTC0B/oac+MPaiD4hYFQ81pFwK6VS0Poi8ZCBJtOkRqfUvsyV8zZrgh +/6cs4mwOVyZPFRgF9eWXYv7PJz8pNRizhII0iv9H/r2I3DzsZLPCg7c29mP+I/SG +A7Pl82UXjtOc0KurGY2M5VheZjxJT/k/FLMkWY2GS5n6dfcyzsVSKb25HoeuvQsI +vs1mKs+Onbobdc17hCcKVJzbi3DwXs5XDhrEzfHccQKBgQD88uBxVCRV31PsCN6I +pKxQDGgz+1BqPqe7KMRiZI7HgDUK0eCM3/oG089/jsBtJcSxnScLSVNBjQ+xGiFi +YCD4icQoJSzpqJyR6gDq5lTHASAe+9LWRW771MrtyACQWNXowYEyu8AjekrZkCUS +wIKVpw57oWykzIoS7ixZsJ8gxwKBgQD8BPWqJEsLiQvOlS5E/g88eV1KTpxm9Xs+ +BbwsDXZ7m4Iw5lYaUu5CwBB/2jkGGRl8Q/EfAdUT7gXv3t6x5b1qMXaIczmRGYto +NuI3AH2MPxAa7lg5TgBgie1r7PKwyPMfG3CtDx6n8W5sexgJpbIy5u7E+U6d8s1o +c7EcsefduQKBgCkHJAx9v18GWFBip+W2ABUDzisQSlzRSNd8p03mTZpiWzgkDq4K +7j0JQhDIkMGjbKH6gYi9Hfn17WOmf1+7g92MSvrP/NbxeGPadsejEIEu14zu/6Wt +oXDLdRbYZ+8B2cBlEpWuCl42yck8Lic6fnPTou++oSah3otvglYR5d2lAoGACd8L +3FE1m0sP6lSPjmZBJIZAcDOqDqJY5HIHD9arKGZL8CxlfPx4lqa9PrTGfQWoqORk +YmmI9hHhq6aYJHGyPKGZWfjhbVyJyFg1/h+Hy2GA+P0S+ZOjkiR050BNtTz5wOMr +Q6wO8FcVkywzIdWaqEHBYne9a5RiFVBKxKv3QAkCgYBxmCBKajFkMVb4Uc55WqJs +Add0mctGgmZ1l5vq81eWe3wjM8wgfJgaD3Q3gwx2ABUX/R+OsVWSh4o5ZR86sYoz +TviknBHF8GeDLjpT49+04fEaz336J2JOptF9zIpz7ZK1nrOEjzaZGtumReVjUP7X +fNcb5iDYqZRzD8ixBbLxUw== +-----END PRIVATE KEY----- -- Gitee From e6c3e11b0ac62ccc6d0d6999e202411c1bccb106 Mon Sep 17 00:00:00 2001 From: Dmitry Misharov Date: Thu, 14 Dec 2023 11:09:15 +0100 Subject: [PATCH 09/92] run Cross Compiles workflow on self-hosted runner Reviewed-by: Hugo Landau Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/23042) Signed-off-by: lanming1120 --- .github/workflows/cross-compiles.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cross-compiles.yml b/.github/workflows/cross-compiles.yml index 21683b731d..c3dd90cab9 100644 --- a/.github/workflows/cross-compiles.yml +++ b/.github/workflows/cross-compiles.yml @@ -148,7 +148,7 @@ jobs: tests: none } ] - runs-on: ubuntu-latest + runs-on: ${{ github.server_url == 'https://github.com' && 'ubuntu-latest' || 'ubuntu-22.04-self-hosted' }} steps: - name: install package repository if: matrix.platform.ppa != '' -- Gitee From 82daf1d7c4e73e87c3a307f34c4bf10fd1bc3381 Mon Sep 17 00:00:00 2001 From: Dmitry Misharov Date: Thu, 14 Dec 2023 12:29:23 +0100 Subject: [PATCH 10/92] run GitHub CI workflow on self-hosted runners Reviewed-by: Hugo Landau Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/23042) Signed-off-by: lanming1120 --- .github/workflows/ci.yml | 114 ++++++++++++++++++++++++++++----------- 1 file changed, 83 insertions(+), 31 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 165f435c69..ae9ad6a269 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,7 +23,7 @@ permissions: jobs: check_update: - runs-on: ubuntu-latest + runs-on: ${{ github.server_url == 'https://github.com' && 'ubuntu-latest' || 'ubuntu-22.04-self-hosted' }} steps: - name: install unifdef run: | @@ -42,7 +42,7 @@ jobs: run: git diff --exit-code check_docs: - runs-on: ubuntu-latest + runs-on: ${{ github.server_url == 'https://github.com' && 'ubuntu-latest' || 'ubuntu-22.04-self-hosted' }} steps: - uses: actions/checkout@v4 - name: config @@ -62,7 +62,7 @@ jobs: # We are not as strict with libraries, but rather adapt to what's # expected to be available in a certain version of each platform. check-ansi: - runs-on: ubuntu-latest + runs-on: ${{ github.server_url == 'https://github.com' && 'ubuntu-latest' || 'ubuntu-22.04-self-hosted' }} steps: - uses: actions/checkout@v4 - name: config @@ -71,7 +71,7 @@ jobs: run: make -s -j4 basic_gcc: - runs-on: ubuntu-latest + runs-on: ${{ github.server_url == 'https://github.com' && 'ubuntu-latest' || 'ubuntu-22.04-self-hosted' }} steps: - uses: actions/checkout@v4 - name: checkout fuzz/corpora submodule @@ -91,7 +91,7 @@ jobs: run: make test HARNESS_JOBS=${HARNESS_JOBS:-4} basic_clang: - runs-on: ubuntu-latest + runs-on: ${{ github.server_url == 'https://github.com' && 'ubuntu-latest' || 'ubuntu-22.04-self-hosted' }} steps: - uses: actions/checkout@v4 - name: checkout fuzz/corpora submodule @@ -127,7 +127,7 @@ jobs: run: make test HARNESS_JOBS=${HARNESS_JOBS:-4} minimal: - runs-on: ubuntu-latest + runs-on: ${{ github.server_url == 'https://github.com' && 'ubuntu-latest' || 'ubuntu-22.04-self-hosted' }} steps: - uses: actions/checkout@v4 - name: checkout fuzz/corpora submodule @@ -144,7 +144,7 @@ jobs: run: make test HARNESS_JOBS=${HARNESS_JOBS:-4} no-deprecated: - runs-on: ubuntu-latest + runs-on: ${{ github.server_url == 'https://github.com' && 'ubuntu-latest' || 'ubuntu-22.04-self-hosted' }} steps: - uses: actions/checkout@v4 - name: checkout fuzz/corpora submodule @@ -160,11 +160,8 @@ jobs: - name: make test run: make test HARNESS_JOBS=${HARNESS_JOBS:-4} - no-shared: - strategy: - matrix: - os: [ ubuntu-latest, macos-latest ] - runs-on: ${{matrix.os}} + no-shared-ubuntu: + runs-on: ${{ github.server_url == 'https://github.com' && 'ubuntu-latest' || 'ubuntu-22.04-self-hosted' }} steps: - uses: actions/checkout@v4 - name: checkout fuzz/corpora submodule @@ -174,12 +171,32 @@ jobs: - name: make run: make -s -j4 - name: get cpu info - run: ./util/opensslwrap.sh version -c + run: | + cat /proc/cpuinfo + ./util/opensslwrap.sh version -c + - name: make test + run: make test HARNESS_JOBS=${HARNESS_JOBS:-4} + + no-shared-macos: + runs-on: macos-latest + if: github.server_url == 'https://github.com' + steps: + - uses: actions/checkout@v4 + - name: checkout fuzz/corpora submodule + run: git submodule update --init --depth 1 fuzz/corpora + - name: config + run: ./config --banner=Configured --strict-warnings no-shared no-fips && perl configdata.pm --dump + - name: make + run: make -s -j4 + - name: get cpu info + run: | + sysctl machdep.cpu + ./util/opensslwrap.sh version -c - name: make test run: make test HARNESS_JOBS=${HARNESS_JOBS:-4} non-caching: - runs-on: ubuntu-latest + runs-on: ${{ github.server_url == 'https://github.com' && 'ubuntu-latest' || 'ubuntu-22.04-self-hosted' }} steps: - uses: actions/checkout@v4 - name: checkout fuzz/corpora submodule @@ -196,7 +213,7 @@ jobs: run: make test HARNESS_JOBS=${HARNESS_JOBS:-4} OPENSSL_TEST_RAND_ORDER=0 TESTS="-test_fuzz* -test_ssl_* -test_sslapi -test_evp -test_cmp_http -test_verify -test_cms -test_store -test_enc -[01][0-9]" address_ub_sanitizer: - runs-on: ubuntu-latest + runs-on: ${{ github.server_url == 'https://github.com' && 'ubuntu-latest' || 'ubuntu-22.04-self-hosted' }} steps: - uses: actions/checkout@v4 - name: checkout fuzz/corpora submodule @@ -213,7 +230,7 @@ jobs: run: make test HARNESS_JOBS=${HARNESS_JOBS:-4} OPENSSL_TEST_RAND_ORDER=0 fuzz_tests: - runs-on: ubuntu-latest + runs-on: ${{ github.server_url == 'https://github.com' && 'ubuntu-latest' || 'ubuntu-22.04-self-hosted' }} steps: - uses: actions/checkout@v4 - name: checkout fuzz/corpora submodule @@ -230,7 +247,7 @@ jobs: run: make test HARNESS_JOBS=${HARNESS_JOBS:-4} OPENSSL_TEST_RAND_ORDER=0 TESTS="test_fuzz*" memory_sanitizer: - runs-on: ubuntu-latest + runs-on: ${{ github.server_url == 'https://github.com' && 'ubuntu-latest' || 'ubuntu-22.04-self-hosted' }} steps: - uses: actions/checkout@v4 - name: checkout fuzz/corpora submodule @@ -248,7 +265,7 @@ jobs: run: make test HARNESS_JOBS=${HARNESS_JOBS:-4} OPENSSL_TEST_RAND_ORDER=0 threads_sanitizer: - runs-on: ubuntu-latest + runs-on: ${{ github.server_url == 'https://github.com' && 'ubuntu-latest' || 'ubuntu-22.04-self-hosted' }} steps: - uses: actions/checkout@v4 - name: checkout fuzz/corpora submodule @@ -265,7 +282,7 @@ jobs: run: make V=1 TESTS="test_threads test_internal_provider test_provfetch test_provider test_pbe test_evp_kdf test_pkcs12 test_store test_evp test_quic*" test HARNESS_JOBS=${HARNESS_JOBS:-4} enable_non-default_options: - runs-on: ubuntu-latest + runs-on: ${{ github.server_url == 'https://github.com' && 'ubuntu-latest' || 'ubuntu-22.04-self-hosted' }} steps: - uses: actions/checkout@v4 - name: checkout fuzz/corpora submodule @@ -284,7 +301,7 @@ jobs: run: make test HARNESS_JOBS=${HARNESS_JOBS:-4} full_featured: - runs-on: ubuntu-latest + runs-on: ${{ github.server_url == 'https://github.com' && 'ubuntu-latest' || 'ubuntu-22.04-self-hosted' }} steps: - uses: actions/checkout@v4 - name: checkout fuzz/corpora submodule @@ -309,7 +326,7 @@ jobs: run: make test HARNESS_JOBS=${HARNESS_JOBS:-4} no-legacy: - runs-on: ubuntu-latest + runs-on: ${{ github.server_url == 'https://github.com' && 'ubuntu-latest' || 'ubuntu-22.04-self-hosted' }} steps: - uses: actions/checkout@v4 - name: checkout fuzz/corpora submodule @@ -326,7 +343,7 @@ jobs: run: make test HARNESS_JOBS=${HARNESS_JOBS:-4} legacy: - runs-on: ubuntu-latest + runs-on: ${{ github.server_url == 'https://github.com' && 'ubuntu-latest' || 'ubuntu-22.04-self-hosted' }} steps: - uses: actions/checkout@v4 - name: checkout fuzz/corpora submodule @@ -347,11 +364,8 @@ jobs: # build tree # - That building, testing and installing works with a read-only source # tree - out-of-readonly-source-and-install: - strategy: - matrix: - os: [ubuntu-latest, macos-latest ] - runs-on: ${{matrix.os}} + out-of-readonly-source-and-install-ubuntu: + runs-on: ${{ github.server_url == 'https://github.com' && 'ubuntu-latest' || 'ubuntu-22.04-self-hosted' }} steps: - uses: actions/checkout@v4 with: @@ -374,7 +388,45 @@ jobs: run: make -s -j4 working-directory: ./build - name: get cpu info - run: ./util/opensslwrap.sh version -c + run: | + cat /proc/cpuinfo + ./util/opensslwrap.sh version -c + working-directory: ./build + - name: make test + run: make test HARNESS_JOBS=${HARNESS_JOBS:-4} + working-directory: ./build + - name: make install + run: make install + working-directory: ./build + + out-of-readonly-source-and-install-macos: + runs-on: macos-latest + if: github.server_url == 'https://github.com' + steps: + - uses: actions/checkout@v4 + with: + path: ./source + - name: checkout fuzz/corpora submodule + run: git submodule update --init --depth 1 fuzz/corpora + working-directory: ./source + - name: make source read-only + run: chmod -R a-w ./source + - name: create build and install directories + run: | + mkdir ./build + mkdir ./install + - name: config + run: | + ../source/config --banner=Configured enable-fips enable-quic enable-acvp-tests --strict-warnings --prefix=$(cd ../install; pwd) + perl configdata.pm --dump + working-directory: ./build + - name: make + run: make -s -j4 + working-directory: ./build + - name: get cpu info + run: | + sysctl machdep.cpu + ./util/opensslwrap.sh version -c working-directory: ./build - name: make test run: make test HARNESS_JOBS=${HARNESS_JOBS:-4} @@ -384,7 +436,7 @@ jobs: working-directory: ./build external-tests: - runs-on: ubuntu-latest + runs-on: ${{ github.server_url == 'https://github.com' && 'ubuntu-latest' || 'ubuntu-22.04-self-hosted' }} steps: - uses: actions/checkout@v4 with: @@ -417,7 +469,7 @@ jobs: run: make test TESTS="test_external_oqsprovider" external-test-pyca: - runs-on: ubuntu-latest + runs-on: ${{ github.server_url == 'https://github.com' && 'ubuntu-latest' || 'ubuntu-22.04-self-hosted' }} strategy: matrix: RUST: @@ -450,7 +502,7 @@ jobs: run: make test TESTS="test_external_pyca" VERBOSE=1 external-test-cf-quiche: - runs-on: ubuntu-latest + runs-on: ${{ github.server_url == 'https://github.com' && 'ubuntu-latest' || 'ubuntu-22.04-self-hosted' }} steps: - uses: actions/checkout@v4 with: -- Gitee From 5b14a51c746f48ed1a2e182097204a19f01cae78 Mon Sep 17 00:00:00 2001 From: Dmitry Misharov Date: Thu, 14 Dec 2023 13:36:04 +0100 Subject: [PATCH 11/92] run Windows GitHub CI workflow on self-hosted runners Reviewed-by: Hugo Landau Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/23042) Signed-off-by: lanming1120 --- .github/workflows/windows.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 0d0f24c299..792190bb08 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -25,7 +25,7 @@ jobs: config: enable-fips - arch: win32 config: --strict-warnings no-fips - runs-on: ${{matrix.os}} + runs-on: ${{ github.server_url == 'https://github.com' && matrix.os || format('{0}-self-hosted', matrix.os) }} steps: - uses: actions/checkout@v4 - name: checkout fuzz/corpora submodule @@ -77,7 +77,7 @@ jobs: os: - windows-2019 - windows-2022 - runs-on: ${{matrix.os}} + runs-on: ${{ github.server_url == 'https://github.com' && matrix.os || format('{0}-self-hosted', matrix.os) }} steps: - uses: actions/checkout@v4 - name: checkout fuzz/corpora submodule @@ -114,7 +114,7 @@ jobs: os: - windows-2019 - windows-2022 - runs-on: ${{matrix.os}} + runs-on: ${{ github.server_url == 'https://github.com' && matrix.os || format('{0}-self-hosted', matrix.os) }} steps: - uses: actions/checkout@v4 - name: checkout fuzz/corpora submodule @@ -159,7 +159,7 @@ jobs: # are we really learning sth new from win32? So let's save some CO2 for now disabling this # - arch: win32 # config: -DCMAKE_C_COMPILER=gcc --strict-warnings no-fips - runs-on: ${{matrix.os}} + runs-on: ${{ github.server_url == 'https://github.com' && matrix.os || format('{0}-self-hosted', matrix.os) }} env: CYGWIN_NOWINPATH: 1 SHELLOPTS: igncr -- Gitee From de67d1a5d08bfbf65a21d5d7ee23d9c64bfe544c Mon Sep 17 00:00:00 2001 From: Matt Caswell Date: Tue, 12 Dec 2023 13:17:51 +0000 Subject: [PATCH 12/92] Ensure the default length calculation includes the content type byte TLSv1.3 includes an extra byte after the payload for the content type. We should incorporate that in the calculation of the default buffer length. Fixes #23015 Reviewed-by: Tomas Mraz Reviewed-by: Hugo Landau (Merged from https://github.com/openssl/openssl/pull/23021) Signed-off-by: lanming1120 --- ssl/record/methods/tls_common.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/ssl/record/methods/tls_common.c b/ssl/record/methods/tls_common.c index 423777c18d..7da423e243 100644 --- a/ssl/record/methods/tls_common.c +++ b/ssl/record/methods/tls_common.c @@ -147,6 +147,7 @@ int tls_setup_write_buffer(OSSL_RECORD_LAYER *rl, size_t numwpipes, TLS_BUFFER *wb; size_t currpipe; size_t defltlen = 0; + size_t contenttypelen = 0; if (firstlen == 0 || (numwpipes > 1 && nextlen == 0)) { if (rl->isdtls) @@ -154,21 +155,26 @@ int tls_setup_write_buffer(OSSL_RECORD_LAYER *rl, size_t numwpipes, else headerlen = SSL3_RT_HEADER_LENGTH; + /* TLSv1.3 adds an extra content type byte after payload data */ + if (rl->version == TLS1_3_VERSION) + contenttypelen = 1; + #if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD != 0 align = SSL3_ALIGN_PAYLOAD - 1; #endif - defltlen = rl->max_frag_len + SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD - + headerlen + align + rl->eivlen; + defltlen = align + headerlen + rl->eivlen + rl->max_frag_len + + contenttypelen + SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD; #ifndef OPENSSL_NO_COMP if (tls_allow_compression(rl)) defltlen += SSL3_RT_MAX_COMPRESSED_OVERHEAD; #endif /* * We don't need to add eivlen here since empty fragments only occur - * when we don't have an explicit IV + * when we don't have an explicit IV. The contenttype byte will also + * always be 0 in these protocol versions */ - if (!(rl->options & SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS)) + if ((rl->options & SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS) == 0) defltlen += headerlen + align + SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD; } -- Gitee From 9c776732b48370243cbca8ec615254324b5693e4 Mon Sep 17 00:00:00 2001 From: Matt Caswell Date: Tue, 12 Dec 2023 13:47:11 +0000 Subject: [PATCH 13/92] Add a daily test for an alternative value for SSL3_ALIGN_PAYLOAD Reviewed-by: Tomas Mraz Reviewed-by: Hugo Landau (Merged from https://github.com/openssl/openssl/pull/23021) Signed-off-by: lanming1120 --- .github/workflows/run-checker-daily.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/run-checker-daily.yml b/.github/workflows/run-checker-daily.yml index 157746f39f..eda5005f68 100644 --- a/.github/workflows/run-checker-daily.yml +++ b/.github/workflows/run-checker-daily.yml @@ -130,7 +130,8 @@ jobs: no-zlib, enable-zlib-dynamic, no-zlib-dynamic, - -DOPENSSL_NO_BUILTIN_OVERFLOW_CHECKING + -DOPENSSL_NO_BUILTIN_OVERFLOW_CHECKING, + -DSSL3_ALIGN_PAYLOAD=4 ] runs-on: ubuntu-latest steps: -- Gitee From 676e49f43d252c43be15f68a03a9d525cd58f581 Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Thu, 14 Dec 2023 16:26:21 +0100 Subject: [PATCH 14/92] Always apply all configuration settings from the ssl section Even if some configuration entry is incorrect, do not skip the remaining ones. Fixes #20789 Reviewed-by: Neil Horman Reviewed-by: Dmitry Belyavskiy (Merged from https://github.com/openssl/openssl/pull/23048) Signed-off-by: lanming1120 --- ssl/ssl_mcnf.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/ssl/ssl_mcnf.c b/ssl/ssl_mcnf.c index c2366e41e3..d7ec22c0e8 100644 --- a/ssl/ssl_mcnf.c +++ b/ssl/ssl_mcnf.c @@ -24,7 +24,7 @@ static int ssl_do_config(SSL *s, SSL_CTX *ctx, const char *name, int system) { SSL_CONF_CTX *cctx = NULL; size_t i, idx, cmd_count; - int rv = 0; + int err = 1; unsigned int flags; const SSL_METHOD *meth; const SSL_CONF_CMD *cmds; @@ -66,8 +66,10 @@ static int ssl_do_config(SSL *s, SSL_CTX *ctx, const char *name, int system) flags |= SSL_CONF_FLAG_CLIENT; SSL_CONF_CTX_set_flags(cctx, flags); prev_libctx = OSSL_LIB_CTX_set0_default(libctx); + err = 0; for (i = 0; i < cmd_count; i++) { char *cmdstr, *arg; + int rv; conf_ssl_get_cmd(cmds, i, &cmdstr, &arg); rv = SSL_CONF_cmd(cctx, cmdstr, arg); @@ -76,14 +78,15 @@ static int ssl_do_config(SSL *s, SSL_CTX *ctx, const char *name, int system) ERR_raise_data(ERR_LIB_SSL, errcode, "section=%s, cmd=%s, arg=%s", name, cmdstr, arg); - goto err; + ++err; } } - rv = SSL_CONF_CTX_finish(cctx); + if (!SSL_CONF_CTX_finish(cctx)) + ++err; err: OSSL_LIB_CTX_set0_default(prev_libctx); SSL_CONF_CTX_free(cctx); - return rv <= 0 ? 0 : 1; + return err == 0; } int SSL_config(SSL *s, const char *name) -- Gitee From 84af1001679db73912e78423819eee2ed20a5048 Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Thu, 14 Dec 2023 16:37:58 +0100 Subject: [PATCH 15/92] Test that incorrect entry in the ssl section is not fatal The following entries should be still applied. Reviewed-by: Neil Horman Reviewed-by: Dmitry Belyavskiy (Merged from https://github.com/openssl/openssl/pull/23048) Signed-off-by: lanming1120 --- test/sysdefault.cnf | 1 + 1 file changed, 1 insertion(+) diff --git a/test/sysdefault.cnf b/test/sysdefault.cnf index 20712b5bda..1c8915074a 100644 --- a/test/sysdefault.cnf +++ b/test/sysdefault.cnf @@ -18,5 +18,6 @@ new-sig-oid = 1.1.1.1.1.1.1.1.1.1.1.1.1.1 system_default = ssl_default_sect [ssl_default_sect] +SignatureAlgorithms = RSA+SHA256:nonex MaxProtocol = TLSv1.2 MinProtocol = TLSv1.2 -- Gitee From 45faadf97f588957a60c8d50736e20cdefe079ce Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Thu, 14 Dec 2023 18:33:57 +0100 Subject: [PATCH 16/92] Consolidate raising errors in SSL_CONF_cmd() Reviewed-by: Neil Horman Reviewed-by: Dmitry Belyavskiy (Merged from https://github.com/openssl/openssl/pull/23048) Signed-off-by: lanming1120 --- ssl/ssl_conf.c | 24 ++++++++++++++++-------- ssl/ssl_mcnf.c | 7 +------ 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/ssl/ssl_conf.c b/ssl/ssl_conf.c index b361719a5a..49e6822479 100644 --- a/ssl/ssl_conf.c +++ b/ssl/ssl_conf.c @@ -902,9 +902,12 @@ static int ctrl_switch_option(SSL_CONF_CTX *cctx, const ssl_conf_cmd_tbl *cmd) /* Find index of command in table */ size_t idx = cmd - ssl_conf_cmds; const ssl_switch_tbl *scmd; + /* Sanity check index */ - if (idx >= OSSL_NELEM(ssl_cmd_switches)) + if (idx >= OSSL_NELEM(ssl_cmd_switches)) { + ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR); return 0; + } /* Obtain switches entry with same index */ scmd = ssl_cmd_switches + idx; ssl_set_option(cctx, scmd->name_flags, scmd->option_value, 1); @@ -920,28 +923,33 @@ int SSL_CONF_cmd(SSL_CONF_CTX *cctx, const char *cmd, const char *value) } if (!ssl_conf_cmd_skip_prefix(cctx, &cmd)) - return -2; + goto unknown_cmd; runcmd = ssl_conf_cmd_lookup(cctx, cmd); if (runcmd) { - int rv; + int rv = -3; + if (runcmd->value_type == SSL_CONF_TYPE_NONE) { return ctrl_switch_option(cctx, runcmd); } if (value == NULL) - return -3; + goto bad_value; rv = runcmd->cmd(cctx, value); if (rv > 0) return 2; - if (rv == -2) - return -2; + if (rv != -2) + rv = 0; + + bad_value: if (cctx->flags & SSL_CONF_FLAG_SHOW_ERRORS) ERR_raise_data(ERR_LIB_SSL, SSL_R_BAD_VALUE, - "cmd=%s, value=%s", cmd, value); - return 0; + "cmd=%s, value=%s", cmd, + value != NULL ? value : ""); + return rv; } + unknown_cmd: if (cctx->flags & SSL_CONF_FLAG_SHOW_ERRORS) ERR_raise_data(ERR_LIB_SSL, SSL_R_UNKNOWN_CMD_NAME, "cmd=%s", cmd); diff --git a/ssl/ssl_mcnf.c b/ssl/ssl_mcnf.c index d7ec22c0e8..8bccce84d4 100644 --- a/ssl/ssl_mcnf.c +++ b/ssl/ssl_mcnf.c @@ -73,13 +73,8 @@ static int ssl_do_config(SSL *s, SSL_CTX *ctx, const char *name, int system) conf_ssl_get_cmd(cmds, i, &cmdstr, &arg); rv = SSL_CONF_cmd(cctx, cmdstr, arg); - if (rv <= 0) { - int errcode = rv == -2 ? SSL_R_UNKNOWN_COMMAND : SSL_R_BAD_VALUE; - - ERR_raise_data(ERR_LIB_SSL, errcode, - "section=%s, cmd=%s, arg=%s", name, cmdstr, arg); + if (rv <= 0) ++err; - } } if (!SSL_CONF_CTX_finish(cctx)) ++err; -- Gitee From 9f5e85c804bbf1ce125cb979447b4c5c24831a3b Mon Sep 17 00:00:00 2001 From: "Dr. David von Oheimb" Date: Tue, 13 Jun 2023 21:56:57 +0200 Subject: [PATCH 17/92] CMP lib and app: add optional certProfile request message header and respective -profile option Also add missing getter functionss OSSL_CMP_{CTX,HDR}_get0_geninfo_ITAVs() to CMP API. Reviewed-by: Tomas Mraz Reviewed-by: Shane Lontis Reviewed-by: David von Oheimb (Merged from https://github.com/openssl/openssl/pull/21281) Signed-off-by: lanming1120 --- CHANGES.md | 5 ++ apps/cmp.c | 44 ++++++++++++++- apps/lib/cmp_mock_srv.c | 36 +++++++++++++ crypto/cmp/cmp_asn.c | 54 ++++++++++++------- crypto/cmp/cmp_ctx.c | 2 + crypto/cmp/cmp_err.c | 2 + crypto/cmp/cmp_hdr.c | 10 ++++ crypto/cmp/cmp_local.h | 2 + crypto/err/openssl.txt | 1 + doc/man1/openssl-cmp.pod.in | 10 +++- doc/man3/OSSL_CMP_CTX_new.pod | 13 ++++- doc/man3/OSSL_CMP_HDR_get0_transactionID.pod | 10 +++- doc/man3/OSSL_CMP_ITAV_set0.pod | 35 ++++++++++-- include/openssl/cmp.h.in | 8 +++ include/openssl/cmperr.h | 1 + .../80-test_cmp_http_data/test_commands.csv | 5 ++ util/libcrypto.num | 4 ++ 17 files changed, 213 insertions(+), 29 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 93365619fa..f1c8bce1b3 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -33,6 +33,11 @@ OpenSSL 3.3 *James Muir* + * Added several new features of CMPv3 defined in RFC 9480 and RFC 9483: + - `certProfile` request message header and respective `-profile` CLI option + + *David von Oheimb* + * The build of exporters (such as `.pc` files for pkg-config) cleaned up to be less hard coded in the build file templates, and to allow easier addition of more exporters. With that, an exporter for CMake is also diff --git a/apps/cmp.c b/apps/cmp.c index dd5a69af7c..67f281e0aa 100644 --- a/apps/cmp.c +++ b/apps/cmp.c @@ -112,6 +112,7 @@ static int opt_cmd = -1; static char *opt_geninfo = NULL; static char *opt_infotype_s = NULL; static int opt_infotype = NID_undef; +static char *opt_profile = NULL; /* certificate enrollment */ static char *opt_newkey = NULL; @@ -210,7 +211,7 @@ typedef enum OPTION_choice { OPT_COMMON, OPT_CONFIG, OPT_SECTION, OPT_VERBOSITY, - OPT_CMD, OPT_INFOTYPE, OPT_GENINFO, + OPT_CMD, OPT_INFOTYPE, OPT_PROFILE, OPT_GENINFO, OPT_NEWKEY, OPT_NEWKEYPASS, OPT_SUBJECT, OPT_DAYS, OPT_REQEXTS, @@ -291,6 +292,8 @@ const OPTIONS cmp_options[] = { "InfoType name for requesting specific info in genm, with specific support"}, {OPT_MORE_STR, 0, 0, "for 'caCerts' and 'rootCaCert'"}, + {"profile", OPT_PROFILE, 's', + "Certificate profile name to place in generalInfo field of request PKIHeader"}, {"geninfo", OPT_GENINFO, 's', "generalInfo integer values to place in request PKIHeader with given OID"}, {OPT_MORE_STR, 0, 0, @@ -587,7 +590,7 @@ typedef union { static varref cmp_vars[] = { /* must be in same order as enumerated above! */ {&opt_config}, {&opt_section}, {(char **)&opt_verbosity}, - {&opt_cmd_s}, {&opt_infotype_s}, {&opt_geninfo}, + {&opt_cmd_s}, {&opt_infotype_s}, {&opt_profile}, {&opt_geninfo}, {&opt_newkey}, {&opt_newkeypass}, {&opt_subject}, {(char **)&opt_days}, {&opt_reqexts}, @@ -1837,6 +1840,37 @@ static int setup_request_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine) return 0; } +static int add_certProfile(OSSL_CMP_CTX *ctx, const char *name) +{ + OSSL_CMP_ITAV *itav = NULL; + STACK_OF(ASN1_UTF8STRING) *sk; + ASN1_UTF8STRING *utf8string; + + if (ctx == NULL || name == NULL) + return 0; + + if ((sk = sk_ASN1_UTF8STRING_new_reserve(NULL, 1)) == NULL) + return 0; + if ((utf8string = ASN1_UTF8STRING_new()) == NULL) + goto err; + if (!ASN1_STRING_set(utf8string, name, (int)strlen(name))) { + ASN1_STRING_free(utf8string); + goto err; + } + /* Due to sk_ASN1_UTF8STRING_new_reserve(NULL, 1), this surely succeeds: */ + (void)sk_ASN1_UTF8STRING_push(sk, utf8string); + if ((itav = OSSL_CMP_ITAV_new0_certProfile(sk)) == NULL) + goto err; + if (OSSL_CMP_CTX_push0_geninfo_ITAV(ctx, itav)) + return 1; + OSSL_CMP_ITAV_free(itav); + return 0; + + err: + sk_ASN1_UTF8STRING_pop_free(sk, ASN1_UTF8STRING_free); + return 0; +} + static int handle_opt_geninfo(OSSL_CMP_CTX *ctx) { long value; @@ -2078,6 +2112,8 @@ static int setup_client_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine) if (opt_geninfo != NULL && !handle_opt_geninfo(ctx)) goto err; + if (opt_profile != NULL && !add_certProfile(ctx, opt_profile)) + goto err; /* not printing earlier, to minimize confusion in case setup fails before */ if (opt_rspin != NULL) @@ -2603,6 +2639,9 @@ static int get_opts(int argc, char **argv) case OPT_INFOTYPE: opt_infotype_s = opt_str(); break; + case OPT_PROFILE: + opt_profile = opt_str(); + break; case OPT_GENINFO: opt_geninfo = opt_str(); break; @@ -3131,6 +3170,7 @@ int cmp_main(int argc, char **argv) cmp_ctx = OSSL_CMP_CTX_new(app_get0_libctx(), app_get0_propq()); if (cmp_ctx == NULL) goto err; + OSSL_CMP_CTX_set_log_verbosity(cmp_ctx, opt_verbosity); if (!OSSL_CMP_CTX_set_log_cb(cmp_ctx, print_to_bio_out)) { CMP_err1("cannot set up error reporting and logging for %s", prog); diff --git a/apps/lib/cmp_mock_srv.c b/apps/lib/cmp_mock_srv.c index a0450446c1..d58937ea78 100644 --- a/apps/lib/cmp_mock_srv.c +++ b/apps/lib/cmp_mock_srv.c @@ -241,6 +241,42 @@ static OSSL_CMP_PKISI *process_cert_request(OSSL_CMP_SRV_CTX *srv_ctx, /* give final response after polling */ ctx->curr_pollCount = 0; + /* accept cert profile for cr messages only with the configured name */ + if (OSSL_CMP_MSG_get_bodytype(cert_req) == OSSL_CMP_CR) { + STACK_OF(OSSL_CMP_ITAV) *itavs = + OSSL_CMP_HDR_get0_geninfo_ITAVs(OSSL_CMP_MSG_get0_header(cert_req)); + int i; + + for (i = 0; i < sk_OSSL_CMP_ITAV_num(itavs); i++) { + OSSL_CMP_ITAV *itav = sk_OSSL_CMP_ITAV_value(itavs, i); + ASN1_OBJECT *obj = OSSL_CMP_ITAV_get0_type(itav); + STACK_OF(ASN1_UTF8STRING) *strs; + ASN1_UTF8STRING *str; + const char *data; + + if (OBJ_obj2nid(obj) == NID_id_it_certProfile) { + if (!OSSL_CMP_ITAV_get0_certProfile(itav, &strs)) + return NULL; + if (sk_ASN1_UTF8STRING_num(strs) < 1) { + ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_CERTPROFILE); + return NULL; + } + str = sk_ASN1_UTF8STRING_value(strs, 0); + if (str == NULL + || (data = + (const char *)ASN1_STRING_get0_data(str)) == NULL) { + ERR_raise(ERR_LIB_CMP, ERR_R_PASSED_INVALID_ARGUMENT); + return NULL; + } + if (strcmp(data, "profile1") != 0) { + ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_CERTPROFILE); + return NULL; + } + break; + } + } + } + /* accept cert update request only for the reference cert, if given */ if (bodytype == OSSL_CMP_KUR && crm != NULL /* thus not p10cr */ && ctx->refCert != NULL) { diff --git a/crypto/cmp/cmp_asn.c b/crypto/cmp/cmp_asn.c index 0133dc5f80..3049d4f080 100644 --- a/crypto/cmp/cmp_asn.c +++ b/crypto/cmp/cmp_asn.c @@ -58,11 +58,7 @@ IMPLEMENT_ASN1_FUNCTIONS(OSSL_CMP_CAKEYUPDANNCONTENT) ASN1_SEQUENCE(OSSL_CMP_ERRORMSGCONTENT) = { ASN1_SIMPLE(OSSL_CMP_ERRORMSGCONTENT, pKIStatusInfo, OSSL_CMP_PKISI), ASN1_OPT(OSSL_CMP_ERRORMSGCONTENT, errorCode, ASN1_INTEGER), - /* - * OSSL_CMP_PKIFREETEXT is effectively a sequence of ASN1_UTF8STRING - * so it is used directly - * - */ + /* OSSL_CMP_PKIFREETEXT is a ASN1_UTF8STRING sequence, so used directly */ ASN1_SEQUENCE_OF_OPT(OSSL_CMP_ERRORMSGCONTENT, errorDetails, ASN1_UTF8STRING) } ASN1_SEQUENCE_END(OSSL_CMP_ERRORMSGCONTENT) @@ -121,6 +117,9 @@ ASN1_ADB(OSSL_CMP_ITAV) = { ADB_ENTRY(NID_id_it_rootCaKeyUpdate, ASN1_OPT(OSSL_CMP_ITAV, infoValue.rootCaKeyUpdate, OSSL_CMP_ROOTCAKEYUPDATE)), + ADB_ENTRY(NID_id_it_certProfile, + ASN1_SEQUENCE_OF_OPT(OSSL_CMP_ITAV, infoValue.certProfile, + ASN1_UTF8STRING)), } ASN1_ADB_END(OSSL_CMP_ITAV, 0, infoType, 0, &infotypeandvalue_default_tt, NULL); @@ -190,13 +189,40 @@ int OSSL_CMP_ITAV_push0_stack_item(STACK_OF(OSSL_CMP_ITAV) **itav_sk_p, return 1; err: - if (created != 0) { + if (created) { sk_OSSL_CMP_ITAV_free(*itav_sk_p); *itav_sk_p = NULL; } return 0; } +OSSL_CMP_ITAV +*OSSL_CMP_ITAV_new0_certProfile(STACK_OF(ASN1_UTF8STRING) *certProfile) +{ + OSSL_CMP_ITAV *itav; + + if ((itav = OSSL_CMP_ITAV_new()) == NULL) + return NULL; + itav->infoType = OBJ_nid2obj(NID_id_it_certProfile); + itav->infoValue.certProfile = certProfile; + return itav; +} + +int OSSL_CMP_ITAV_get0_certProfile(const OSSL_CMP_ITAV *itav, + STACK_OF(ASN1_UTF8STRING) **out) +{ + if (itav == NULL || out == NULL) { + ERR_raise(ERR_LIB_CMP, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + if (OBJ_obj2nid(itav->infoType) != NID_id_it_certProfile) { + ERR_raise(ERR_LIB_CMP, ERR_R_PASSED_INVALID_ARGUMENT); + return 0; + } + *out = itav->infoValue.certProfile; + return 1; +} + OSSL_CMP_ITAV *OSSL_CMP_ITAV_new_caCerts(const STACK_OF(X509) *caCerts) { OSSL_CMP_ITAV *itav = OSSL_CMP_ITAV_new(); @@ -327,7 +353,7 @@ int ossl_cmp_asn1_get_int(const ASN1_INTEGER *a) } static int ossl_cmp_msg_cb(int operation, ASN1_VALUE **pval, - const ASN1_ITEM *it, void *exarg) + ossl_unused const ASN1_ITEM *it, void *exarg) { OSSL_CMP_MSG *msg = (OSSL_CMP_MSG *)*pval; @@ -417,14 +443,9 @@ ASN1_ITEM_TEMPLATE_END(OSSL_CMP_PKISTATUS) ASN1_SEQUENCE(OSSL_CMP_PKISI) = { ASN1_SIMPLE(OSSL_CMP_PKISI, status, OSSL_CMP_PKISTATUS), - /* - * CMP_PKIFREETEXT is effectively a sequence of ASN1_UTF8STRING - * so it is used directly - */ + /* OSSL_CMP_PKIFREETEXT is a ASN1_UTF8STRING sequence, so used directly */ ASN1_SEQUENCE_OF_OPT(OSSL_CMP_PKISI, statusString, ASN1_UTF8STRING), - /* - * OSSL_CMP_PKIFAILUREINFO is effectively ASN1_BIT_STRING so used directly - */ + /* OSSL_CMP_PKIFAILUREINFO is effectively ASN1_BIT_STRING, used directly */ ASN1_OPT(OSSL_CMP_PKISI, failInfo, ASN1_BIT_STRING) } ASN1_SEQUENCE_END(OSSL_CMP_PKISI) IMPLEMENT_ASN1_FUNCTIONS(OSSL_CMP_PKISI) @@ -541,10 +562,7 @@ ASN1_SEQUENCE(OSSL_CMP_PKIHEADER) = { ASN1_EXP_OPT(OSSL_CMP_PKIHEADER, transactionID, ASN1_OCTET_STRING, 4), ASN1_EXP_OPT(OSSL_CMP_PKIHEADER, senderNonce, ASN1_OCTET_STRING, 5), ASN1_EXP_OPT(OSSL_CMP_PKIHEADER, recipNonce, ASN1_OCTET_STRING, 6), - /* - * OSSL_CMP_PKIFREETEXT is effectively a sequence of ASN1_UTF8STRING - * so it is used directly - */ + /* OSSL_CMP_PKIFREETEXT is a ASN1_UTF8STRING sequence, so used directly */ ASN1_EXP_SEQUENCE_OF_OPT(OSSL_CMP_PKIHEADER, freeText, ASN1_UTF8STRING, 7), ASN1_EXP_SEQUENCE_OF_OPT(OSSL_CMP_PKIHEADER, generalInfo, OSSL_CMP_ITAV, 8) diff --git a/crypto/cmp/cmp_ctx.c b/crypto/cmp/cmp_ctx.c index 947d2ceb8f..5e542200e9 100644 --- a/crypto/cmp/cmp_ctx.c +++ b/crypto/cmp/cmp_ctx.c @@ -534,6 +534,8 @@ int OSSL_CMP_CTX_reset_geninfo_ITAVs(OSSL_CMP_CTX *ctx) return 1; } +DEFINE_OSSL_CMP_CTX_get0(geninfo_ITAVs, STACK_OF(OSSL_CMP_ITAV)) + /* Add an itav for the body of outgoing general messages */ int OSSL_CMP_CTX_push0_genm_ITAV(OSSL_CMP_CTX *ctx, OSSL_CMP_ITAV *itav) { diff --git a/crypto/cmp/cmp_err.c b/crypto/cmp/cmp_err.c index 3853e52605..c4d5c97f9e 100644 --- a/crypto/cmp/cmp_err.c +++ b/crypto/cmp/cmp_err.c @@ -144,6 +144,8 @@ static const ERR_STRING_DATA CMP_str_reasons[] = { "transactionid unmatched"}, {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_TRANSFER_ERROR), "transfer error"}, {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNCLEAN_CTX), "unclean ctx"}, + {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNEXPECTED_CERTPROFILE), + "unexpected certprofile"}, {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNEXPECTED_PKIBODY), "unexpected pkibody"}, {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNEXPECTED_PKISTATUS), "unexpected pkistatus"}, diff --git a/crypto/cmp/cmp_hdr.c b/crypto/cmp/cmp_hdr.c index 5fabf1aa33..4358b38873 100644 --- a/crypto/cmp/cmp_hdr.c +++ b/crypto/cmp/cmp_hdr.c @@ -72,6 +72,16 @@ ASN1_OCTET_STRING *OSSL_CMP_HDR_get0_recipNonce(const OSSL_CMP_PKIHEADER *hdr) return hdr->recipNonce; } +STACK_OF(OSSL_CMP_ITAV) + *OSSL_CMP_HDR_get0_geninfo_ITAVs(const OSSL_CMP_PKIHEADER *hdr) +{ + if (hdr == NULL) { + ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); + return NULL; + } + return hdr->generalInfo; +} + /* a NULL-DN as an empty sequence of RDNs */ int ossl_cmp_general_name_is_NULL_DN(GENERAL_NAME *name) { diff --git a/crypto/cmp/cmp_local.h b/crypto/cmp/cmp_local.h index 29aa84cd2a..b8da48ac43 100644 --- a/crypto/cmp/cmp_local.h +++ b/crypto/cmp/cmp_local.h @@ -254,6 +254,8 @@ struct ossl_cmp_itav_st { OSSL_CMP_MSGS *origPKIMessage; /* NID_id_it_suppLangTags - Supported Language Tags */ STACK_OF(ASN1_UTF8STRING) *suppLangTagsValue; + /* NID_id_it_certProfile - Certificate Profile */ + STACK_OF(ASN1_UTF8STRING) *certProfile; /* NID_id_it_caCerts - CA Certificates */ STACK_OF(X509) *caCerts; /* NID_id_it_rootCaCert - Root CA Certificate */ diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt index 5f60bd52d2..8e6d9ddcae 100644 --- a/crypto/err/openssl.txt +++ b/crypto/err/openssl.txt @@ -272,6 +272,7 @@ CMP_R_TOTAL_TIMEOUT:184:total timeout CMP_R_TRANSACTIONID_UNMATCHED:152:transactionid unmatched CMP_R_TRANSFER_ERROR:159:transfer error CMP_R_UNCLEAN_CTX:191:unclean ctx +CMP_R_UNEXPECTED_CERTPROFILE:196:unexpected certprofile CMP_R_UNEXPECTED_PKIBODY:133:unexpected pkibody CMP_R_UNEXPECTED_PKISTATUS:185:unexpected pkistatus CMP_R_UNEXPECTED_PVNO:153:unexpected pvno diff --git a/doc/man1/openssl-cmp.pod.in b/doc/man1/openssl-cmp.pod.in index 051c749d08..ee54697c9c 100644 --- a/doc/man1/openssl-cmp.pod.in +++ b/doc/man1/openssl-cmp.pod.in @@ -17,6 +17,7 @@ Generic message options: [B<-cmd> I] [B<-infotype> I] +[B<-profile> I] [B<-geninfo> I] Certificate enrollment options: @@ -246,6 +247,11 @@ Set InfoType name to use for requesting specific info in B, e.g., C. So far, there is specific support for C and C. +=item B<-profile> I + +Name of a certificate profile to place in +the PKIHeader generalInfo field of request messages. + =item B<-geninfo> I generalInfo integer values to place in request PKIHeader with given OID, @@ -1390,7 +1396,9 @@ L, L, L The B application was added in OpenSSL 3.0. -The B<-engine option> was deprecated in OpenSSL 3.0. +The B<-engine> option was deprecated in OpenSSL 3.0. + +The B<-profile> option was added in OpenSSL 3.3. =head1 COPYRIGHT diff --git a/doc/man3/OSSL_CMP_CTX_new.pod b/doc/man3/OSSL_CMP_CTX_new.pod index 8109970171..d038f2f61c 100644 --- a/doc/man3/OSSL_CMP_CTX_new.pod +++ b/doc/man3/OSSL_CMP_CTX_new.pod @@ -39,6 +39,7 @@ OSSL_CMP_CTX_set1_secretValue, OSSL_CMP_CTX_set1_recipient, OSSL_CMP_CTX_push0_geninfo_ITAV, OSSL_CMP_CTX_reset_geninfo_ITAVs, +OSSL_CMP_CTX_get0_geninfo_ITAVs, OSSL_CMP_CTX_set1_extraCertsOut, OSSL_CMP_CTX_set0_newPkey, OSSL_CMP_CTX_get0_newPkey, @@ -127,6 +128,8 @@ OSSL_CMP_CTX_set1_senderNonce int OSSL_CMP_CTX_set1_recipient(OSSL_CMP_CTX *ctx, const X509_NAME *name); int OSSL_CMP_CTX_push0_geninfo_ITAV(OSSL_CMP_CTX *ctx, OSSL_CMP_ITAV *itav); int OSSL_CMP_CTX_reset_geninfo_ITAVs(OSSL_CMP_CTX *ctx); + STACK_OF(OSSL_CMP_ITAV) + *OSSL_CMP_CTX_get0_geninfo_ITAVs(const OSSL_CMP_CTX *ctx); int OSSL_CMP_CTX_set1_extraCertsOut(OSSL_CMP_CTX *ctx, STACK_OF(X509) *extraCertsOut); @@ -540,12 +543,16 @@ the issuer of the CMP signer certificate, as far as any of those is present, else the NULL-DN as last resort. OSSL_CMP_CTX_push0_geninfo_ITAV() adds I to the stack in the I to be -added to the GeneralInfo field of the CMP PKIMessage header of a request +added to the generalInfo field of the CMP PKIMessage header of a request message sent with this context. OSSL_CMP_CTX_reset_geninfo_ITAVs() clears any ITAVs that were added by OSSL_CMP_CTX_push0_geninfo_ITAV(). +OSSL_CMP_CTX_get0_geninfo_ITAVs() returns the list of ITAVs set in I +for inclusion in the generalInfo field of the CMP PKIMessage header of requests +or NULL if not set. + OSSL_CMP_CTX_set1_extraCertsOut() sets the stack of extraCerts that will be sent to remote. @@ -737,6 +744,7 @@ OSSL_CMP_CTX_get_http_cb_arg(), OSSL_CMP_CTX_get_transfer_cb_arg(), OSSL_CMP_CTX_get0_trusted(), OSSL_CMP_CTX_get0_untrusted(), +OSSL_CMP_CTX_get0_geninfo_ITAVs(), OSSL_CMP_CTX_get0_newPkey(), OSSL_CMP_CTX_get_certConf_cb_arg(), OSSL_CMP_CTX_get0_statusString(), @@ -841,10 +849,11 @@ in OpenSSL 3.2. OSSL_CMP_CTX_reset_geninfo_ITAVs() was added in OpenSSL 3.0.8. +OSSL_CMP_CTX_set1_serialNumber(), OSSL_CMP_CTX_get0_libctx(), OSSL_CMP_CTX_get0_propq(), and OSSL_CMP_CTX_get0_validatedSrvCert() were added in OpenSSL 3.2. -OSSL_CMP_CTX_set1_serialNumber() was added in OpenSSL 3.2. +OSSL_CMP_CTX_get0_geninfo_ITAVs() was added in OpenSSL 3.3. =head1 COPYRIGHT diff --git a/doc/man3/OSSL_CMP_HDR_get0_transactionID.pod b/doc/man3/OSSL_CMP_HDR_get0_transactionID.pod index 36bdf1917f..6e79e9a0e3 100644 --- a/doc/man3/OSSL_CMP_HDR_get0_transactionID.pod +++ b/doc/man3/OSSL_CMP_HDR_get0_transactionID.pod @@ -3,7 +3,8 @@ =head1 NAME OSSL_CMP_HDR_get0_transactionID, -OSSL_CMP_HDR_get0_recipNonce +OSSL_CMP_HDR_get0_recipNonce, +OSSL_CMP_HDR_get0_geninfo_ITAVs - functions manipulating CMP message headers =head1 SYNOPSIS @@ -14,6 +15,8 @@ OSSL_CMP_HDR_get0_recipNonce OSSL_CMP_PKIHEADER *hdr); ASN1_OCTET_STRING *OSSL_CMP_HDR_get0_recipNonce(const OSSL_CMP_PKIHEADER *hdr); + STACK_OF(OSSL_CMP_ITAV) + *OSSL_CMP_HDR_get0_geninfo_ITAVs(const OSSL_CMP_PKIHEADER *hdr); =head1 DESCRIPTION @@ -22,6 +25,9 @@ PKIHeader. OSSL_CMP_HDR_get0_recipNonce returns the recipient nonce of the given PKIHeader. +OSSL_CMP_HDR_get0_geninfo_ITAVs() returns the list of ITAVs +in the generalInfo field of the given PKIHeader. + =head1 NOTES CMP is defined in RFC 4210. @@ -35,6 +41,8 @@ or NULL if the respective entry does not exist and on error. The OpenSSL CMP support was added in OpenSSL 3.0. +OSSL_CMP_HDR_get0_geninfo_ITAVs() was added in OpenSSL 3.3. + =head1 COPYRIGHT Copyright 2007-2019 The OpenSSL Project Authors. All Rights Reserved. diff --git a/doc/man3/OSSL_CMP_ITAV_set0.pod b/doc/man3/OSSL_CMP_ITAV_set0.pod index 5dd9bcb266..13d7868a6d 100644 --- a/doc/man3/OSSL_CMP_ITAV_set0.pod +++ b/doc/man3/OSSL_CMP_ITAV_set0.pod @@ -6,7 +6,9 @@ OSSL_CMP_ITAV_create, OSSL_CMP_ITAV_set0, OSSL_CMP_ITAV_get0_type, OSSL_CMP_ITAV_get0_value, -OSSL_CMP_ITAV_push0_stack_item +OSSL_CMP_ITAV_push0_stack_item, +OSSL_CMP_ITAV_new0_certProfile, +OSSL_CMP_ITAV_get0_certProfile - OSSL_CMP_ITAV utility functions =head1 SYNOPSIS @@ -20,6 +22,10 @@ OSSL_CMP_ITAV_push0_stack_item ASN1_TYPE *OSSL_CMP_ITAV_get0_value(const OSSL_CMP_ITAV *itav); int OSSL_CMP_ITAV_push0_stack_item(STACK_OF(OSSL_CMP_ITAV) **itav_sk_p, OSSL_CMP_ITAV *itav); + OSSL_CMP_ITAV + *OSSL_CMP_ITAV_new0_certProfile(STACK_OF(ASN1_UTF8STRING) *certProfile); + int OSSL_CMP_ITAV_get0_certProfile(const OSSL_CMP_ITAV *itav, + STACK_OF(ASN1_UTF8STRING) **out); =head1 DESCRIPTION @@ -43,21 +49,37 @@ the I as generic B pointer. OSSL_CMP_ITAV_push0_stack_item() pushes I to the stack pointed to by I<*itav_sk_p>. It creates a new stack if I<*itav_sk_p> points to NULL. +OSSL_CMP_ITAV_new0_certProfile() creates a new B structure +of type B that includes the optionally given list of profile names. +On success, ownership of the list is with the new B structure. + +OSSL_CMP_ITAV_get0_certProfile() on success assigns to I<*out> +an internal pointer to the +list of certificate profile names contained in the infoValue field of I. +The pointer may be NULL if no profile name is included. +It is an error if the infoType of I is not B. + =head1 NOTES -CMP is defined in RFC 4210 (and CRMF in RFC 4211). +CMP is defined in RFC 4210 and RFC 9480 (and CRMF in RFC 4211). + +OIDs to use as types in B can be found at +L. +The respective OpenSSL NIDs, such as B, +are defined in the F<< >> header file. =head1 RETURN VALUES -OSSL_CMP_ITAV_create() returns a pointer to the ITAV structure on success, -or NULL on error. +OSSL_CMP_ITAV_create() and OSSL_CMP_ITAV_new0_certProfile() +return a pointer to an ITAV structure on success, or NULL on error. OSSL_CMP_ITAV_set0() does not return a value. OSSL_CMP_ITAV_get0_type() and OSSL_CMP_ITAV_get0_value() return the respective pointer or NULL if their input is NULL. -OSSL_CMP_ITAV_push0_stack_item() returns 1 on success, 0 on error. +OSSL_CMP_ITAV_push0_stack_item() and OSSL_CMP_ITAV_get0_certProfile() +return 1 on success, 0 on error. =head1 EXAMPLES @@ -96,6 +118,9 @@ L, L, L The OpenSSL CMP support was added in OpenSSL 3.0. +OSSL_CMP_ITAV_new0_certProfile() and OSSL_CMP_ITAV_get0_certProfile() +were added in OpenSSL 3.3. + =head1 COPYRIGHT Copyright 2007-2021 The OpenSSL Project Authors. All Rights Reserved. diff --git a/include/openssl/cmp.h.in b/include/openssl/cmp.h.in index 5bd8beb57a..fa4fe000ba 100644 --- a/include/openssl/cmp.h.in +++ b/include/openssl/cmp.h.in @@ -261,6 +261,10 @@ int OSSL_CMP_ITAV_push0_stack_item(STACK_OF(OSSL_CMP_ITAV) **itav_sk_p, OSSL_CMP_ITAV *itav); void OSSL_CMP_ITAV_free(OSSL_CMP_ITAV *itav); +OSSL_CMP_ITAV *OSSL_CMP_ITAV_new0_certProfile(STACK_OF(ASN1_UTF8STRING) + *certProfile); +int OSSL_CMP_ITAV_get0_certProfile(const OSSL_CMP_ITAV *itav, + STACK_OF(ASN1_UTF8STRING) **out); OSSL_CMP_ITAV *OSSL_CMP_ITAV_new_caCerts(const STACK_OF(X509) *caCerts); int OSSL_CMP_ITAV_get0_caCerts(const OSSL_CMP_ITAV *itav, STACK_OF(X509) **out); @@ -351,6 +355,8 @@ int OSSL_CMP_CTX_set1_secretValue(OSSL_CMP_CTX *ctx, int OSSL_CMP_CTX_set1_recipient(OSSL_CMP_CTX *ctx, const X509_NAME *name); int OSSL_CMP_CTX_push0_geninfo_ITAV(OSSL_CMP_CTX *ctx, OSSL_CMP_ITAV *itav); int OSSL_CMP_CTX_reset_geninfo_ITAVs(OSSL_CMP_CTX *ctx); +STACK_OF(OSSL_CMP_ITAV) + *OSSL_CMP_CTX_get0_geninfo_ITAVs(const OSSL_CMP_CTX *ctx); int OSSL_CMP_CTX_set1_extraCertsOut(OSSL_CMP_CTX *ctx, STACK_OF(X509) *extraCertsOut); /* certificate template: */ @@ -403,6 +409,8 @@ OSSL_CMP_STATUSINFO_new(int status, int fail_info, const char *text); ASN1_OCTET_STRING *OSSL_CMP_HDR_get0_transactionID(const OSSL_CMP_PKIHEADER *hdr); ASN1_OCTET_STRING *OSSL_CMP_HDR_get0_recipNonce(const OSSL_CMP_PKIHEADER *hdr); +STACK_OF(OSSL_CMP_ITAV) + *OSSL_CMP_HDR_get0_geninfo_ITAVs(const OSSL_CMP_PKIHEADER *hdr); /* from cmp_msg.c */ OSSL_CMP_PKIHEADER *OSSL_CMP_MSG_get0_header(const OSSL_CMP_MSG *msg); diff --git a/include/openssl/cmperr.h b/include/openssl/cmperr.h index 57a6effbe3..dec9e0be45 100644 --- a/include/openssl/cmperr.h +++ b/include/openssl/cmperr.h @@ -98,6 +98,7 @@ # define CMP_R_TRANSACTIONID_UNMATCHED 152 # define CMP_R_TRANSFER_ERROR 159 # define CMP_R_UNCLEAN_CTX 191 +# define CMP_R_UNEXPECTED_CERTPROFILE 196 # define CMP_R_UNEXPECTED_PKIBODY 133 # define CMP_R_UNEXPECTED_PKISTATUS 185 # define CMP_R_UNEXPECTED_PVNO 153 diff --git a/test/recipes/80-test_cmp_http_data/test_commands.csv b/test/recipes/80-test_cmp_http_data/test_commands.csv index 5ab2ca3fd7..869bab7c99 100644 --- a/test/recipes/80-test_cmp_http_data/test_commands.csv +++ b/test/recipes/80-test_cmp_http_data/test_commands.csv @@ -77,6 +77,11 @@ expected,description, -section,val, -cmd,val,val2, -cacertsout,val,val2, -infoty 0,genm rootCaCert newwithold missig arg , -section,, -cmd,genm,, BLANK,,, -infotype,rootCaCert,, -oldwithold, oldWithOld.pem, -newwithnew, _RESULT_DIR/test.newwithnew.pem, -oldwithnew, _RESULT_DIR/test.oldwithnew.pem, -newwithold,, 1,genm rootCaCert newwithnew newwithold , -section,, -cmd,genm,, BLANK,,, -infotype,rootCaCert,, -oldwithold, oldWithOld.pem, -newwithnew, _RESULT_DIR/test.newwithnew3.pem, -newwithold, _RESULT_DIR/test.newwithold2.pem ,,,,,,,,,,,,,,,,,,,,,, +1,profile, -section,, -cmd,cr,, -cert,signer.crt, -key,signer.p12, -keypass,pass:12345,BLANK,, -profile,profile1,BLANK,,BLANK, +0,profile wrong value, -section,, -cmd,cr,, -cert,signer.crt, -key,signer.p12, -keypass,pass:12345,BLANK,, -profile,profile2,BLANK,,BLANK, +0,profile missing argument, -section,, -cmd,cr,, -cert,signer.crt, -key,signer.p12, -keypass,pass:12345,BLANK,, -profile,,,,, +0,profile extra argument, -section,, -cmd,cr,, -cert,signer.crt, -key,signer.p12, -keypass,pass:12345,BLANK,, -profile,profile1,profile2,,, +,,,,,,,,,,,,,,,,,,, 1,geninfo, -section,, -cmd,cr,, -cert,signer.crt, -key,signer.p12, -keypass,pass:12345,BLANK,, -geninfo,1.2.3:int:987,BLANK,,BLANK, 0,geninfo missing argument, -section,, -cmd,cr,, -cert,signer.crt, -key,signer.p12, -keypass,pass:12345,BLANK,, -geninfo,,,,, 0,geninfo bad syntax: leading '.', -section,, -cmd,cr,, -cert,signer.crt, -key,signer.p12, -keypass,pass:12345,BLANK,, -geninfo,.1.2.3:int:987,BLANK,,BLANK, diff --git a/util/libcrypto.num b/util/libcrypto.num index c9941a383b..60f320c33a 100644 --- a/util/libcrypto.num +++ b/util/libcrypto.num @@ -5536,4 +5536,8 @@ X509_STORE_CTX_set_get_crl 5663 3_2_0 EXIST::FUNCTION: X509_STORE_CTX_set_current_reasons 5664 3_2_0 EXIST::FUNCTION: OSSL_STORE_delete 5665 3_2_0 EXIST::FUNCTION: BIO_ADDR_copy 5666 3_2_0 EXIST::FUNCTION:SOCK +OSSL_CMP_CTX_get0_geninfo_ITAVs ? 3_3_0 EXIST::FUNCTION:CMP +OSSL_CMP_HDR_get0_geninfo_ITAVs ? 3_3_0 EXIST::FUNCTION:CMP +OSSL_CMP_ITAV_new0_certProfile ? 3_3_0 EXIST::FUNCTION:CMP +OSSL_CMP_ITAV_get0_certProfile ? 3_3_0 EXIST::FUNCTION:CMP EVP_DigestSqueeze ? 3_3_0 EXIST::FUNCTION: -- Gitee From 126a302d4fb84640030c55690e888b0e691bda5d Mon Sep 17 00:00:00 2001 From: "Dr. David von Oheimb" Date: Wed, 21 Jun 2023 13:01:09 +0200 Subject: [PATCH 18/92] CMP app: make -geninfo option accept multiple ITAVs and support string values besides integers Reviewed-by: Tomas Mraz Reviewed-by: Shane Lontis Reviewed-by: David von Oheimb (Merged from https://github.com/openssl/openssl/pull/21281) Signed-off-by: lanming1120 --- apps/cmp.c | 138 +++++++++++------- doc/man1/openssl-cmp.pod.in | 11 +- .../80-test_cmp_http_data/test_commands.csv | 18 ++- 3 files changed, 106 insertions(+), 61 deletions(-) diff --git a/apps/cmp.c b/apps/cmp.c index 67f281e0aa..e0b03c3cb5 100644 --- a/apps/cmp.c +++ b/apps/cmp.c @@ -295,9 +295,9 @@ const OPTIONS cmp_options[] = { {"profile", OPT_PROFILE, 's', "Certificate profile name to place in generalInfo field of request PKIHeader"}, {"geninfo", OPT_GENINFO, 's', - "generalInfo integer values to place in request PKIHeader with given OID"}, + "Comma-separated list of OID and value to place in generalInfo PKIHeader"}, {OPT_MORE_STR, 0, 0, - "specified in the form :int:, e.g. \"1.2.3.4:int:56789\""}, + "of form :int: or :str:, e.g. \'1.2.3.4:int:56789, id-kp:str:name'"}, OPT_SECTION("Certificate enrollment"), {"newkey", OPT_NEWKEY, 's', @@ -1794,9 +1794,11 @@ static int setup_request_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine) char *next = next_item(opt_policy_oids); if ((policy = OBJ_txt2obj(opt_policy_oids, 1)) == 0) { - CMP_err1("unknown policy OID '%s'", opt_policy_oids); + CMP_err1("Invalid -policy_oids arg '%s'", opt_policy_oids); return 0; } + if (OBJ_obj2nid(policy) == NID_undef) + CMP_warn1("Unknown -policy_oids arg: %.40s", opt_policy_oids); if ((pinfo = POLICYINFO_new()) == NULL) { ASN1_OBJECT_free(policy); @@ -1873,62 +1875,94 @@ static int add_certProfile(OSSL_CMP_CTX *ctx, const char *name) static int handle_opt_geninfo(OSSL_CMP_CTX *ctx) { + ASN1_OBJECT *obj = NULL; + ASN1_TYPE *type = NULL; long value; - ASN1_OBJECT *type; - ASN1_INTEGER *aint; - ASN1_TYPE *val; + ASN1_INTEGER *aint = NULL; + ASN1_UTF8STRING *text = NULL; OSSL_CMP_ITAV *itav; - char *endstr; - char *valptr = strchr(opt_geninfo, ':'); - - if (valptr == NULL) { - CMP_err("missing ':' in -geninfo option"); - return 0; - } - valptr[0] = '\0'; - valptr++; - - if (!CHECK_AND_SKIP_CASE_PREFIX(valptr, "int:")) { - CMP_err("missing 'int:' in -geninfo option"); - return 0; - } + char *ptr = opt_geninfo, *oid, *end; + + do { + while (isspace(_UC(*ptr))) + ptr++; + oid = ptr; + if ((ptr = strchr(oid, ':')) == NULL) { + CMP_err1("Missing ':' in -geninfo arg %.40s", oid); + return 0; + } + *ptr++ = '\0'; + if ((obj = OBJ_txt2obj(oid, 0)) == NULL) { + CMP_err1("Invalid OID in -geninfo arg %.40s", oid); + return 0; + } + if (OBJ_obj2nid(obj) == NID_undef) + CMP_warn1("Unknown OID in -geninfo arg: %.40s", oid); + if ((type = ASN1_TYPE_new()) == NULL) + goto oom; - value = strtol(valptr, &endstr, 10); - if (endstr == valptr || *endstr != '\0') { - CMP_err("cannot parse int in -geninfo option"); - return 0; - } + if (CHECK_AND_SKIP_CASE_PREFIX(ptr, "int:")) { + value = strtol(ptr, &end, 10); + if (end == ptr) { + CMP_err1("Cannot parse int in -geninfo arg %.40s", ptr); + goto err; + } + ptr = end; + if (*ptr != '\0') { + if (*ptr != ',') { + CMP_err1("Missing ',' or end of -geninfo arg after int at %.40s", + ptr); + goto err; + } + ptr++; + } - type = OBJ_txt2obj(opt_geninfo, 1); - if (type == NULL) { - CMP_err("cannot parse OID in -geninfo option"); - return 0; - } + if ((aint = ASN1_INTEGER_new()) == NULL + || !ASN1_INTEGER_set(aint, value)) + goto oom; + ASN1_TYPE_set(type, V_ASN1_INTEGER, aint); + aint = NULL; + + } else if (CHECK_AND_SKIP_CASE_PREFIX(ptr, "str:")) { + end = strchr(ptr, ','); + if (end == NULL) + end = ptr + strlen(ptr); + else + *end++ = '\0'; + if ((text = ASN1_UTF8STRING_new()) == NULL + || !ASN1_STRING_set(text, ptr, -1)) + goto oom; + ptr = end; + ASN1_TYPE_set(type, V_ASN1_UTF8STRING, text); + text = NULL; - if ((aint = ASN1_INTEGER_new()) == NULL) - goto oom; + } else { + CMP_err1("Missing 'int:' or 'str:' in -geninfo arg %.40s", ptr); + goto err; + } - val = ASN1_TYPE_new(); - if (!ASN1_INTEGER_set(aint, value) || val == NULL) { - ASN1_INTEGER_free(aint); - goto oom; - } - ASN1_TYPE_set(val, V_ASN1_INTEGER, aint); - itav = OSSL_CMP_ITAV_create(type, val); - if (itav == NULL) { - ASN1_TYPE_free(val); - goto oom; - } + if ((itav = OSSL_CMP_ITAV_create(obj, type)) == NULL) { + CMP_err("Unable to create 'OSSL_CMP_ITAV' structure"); + goto err; + } + obj = NULL; + type = NULL; - if (!OSSL_CMP_CTX_push0_geninfo_ITAV(ctx, itav)) { - OSSL_CMP_ITAV_free(itav); - return 0; - } + if (!OSSL_CMP_CTX_push0_geninfo_ITAV(ctx, itav)) { + CMP_err("Failed to add ITAV for geninfo of the PKI message header"); + OSSL_CMP_ITAV_free(itav); + return 0; + } + } while (*ptr != '\0'); return 1; oom: - ASN1_OBJECT_free(type); CMP_err("out of memory"); + err: + ASN1_OBJECT_free(obj); + ASN1_TYPE_free(type); + ASN1_INTEGER_free(aint); + ASN1_UTF8STRING_free(text); return 0; } @@ -3147,6 +3181,10 @@ int cmp_main(int argc, char **argv) } (void)BIO_flush(bio_err); /* prevent interference with opt_help() */ + cmp_ctx = OSSL_CMP_CTX_new(app_get0_libctx(), app_get0_propq()); + if (cmp_ctx == NULL) + goto err; + ret = get_opts(argc, argv); if (ret <= 0) goto err; @@ -3167,10 +3205,6 @@ int cmp_main(int argc, char **argv) } } - cmp_ctx = OSSL_CMP_CTX_new(app_get0_libctx(), app_get0_propq()); - if (cmp_ctx == NULL) - goto err; - OSSL_CMP_CTX_set_log_verbosity(cmp_ctx, opt_verbosity); if (!OSSL_CMP_CTX_set_log_cb(cmp_ctx, print_to_bio_out)) { CMP_err1("cannot set up error reporting and logging for %s", prog); diff --git a/doc/man1/openssl-cmp.pod.in b/doc/man1/openssl-cmp.pod.in index ee54697c9c..911b63e155 100644 --- a/doc/man1/openssl-cmp.pod.in +++ b/doc/man1/openssl-cmp.pod.in @@ -18,7 +18,7 @@ Generic message options: [B<-cmd> I] [B<-infotype> I] [B<-profile> I] -[B<-geninfo> I] +[B<-geninfo> I] Certificate enrollment options: @@ -252,10 +252,13 @@ So far, there is specific support for C and C. Name of a certificate profile to place in the PKIHeader generalInfo field of request messages. -=item B<-geninfo> I +=item B<-geninfo> I -generalInfo integer values to place in request PKIHeader with given OID, -e.g., C<1.2.3.4:int:56789>. +A comma-separated list of InfoTypeAndValue to place in +the generalInfo field of the PKIHeader of requests messages. +Each InfoTypeAndValue gives an OID and an integer or string value +of the form I:int:I or I:str:I, +e.g., C<'1.2.3.4:int:56789, id-kp:str:name'>. =back diff --git a/test/recipes/80-test_cmp_http_data/test_commands.csv b/test/recipes/80-test_cmp_http_data/test_commands.csv index 869bab7c99..425385fe69 100644 --- a/test/recipes/80-test_cmp_http_data/test_commands.csv +++ b/test/recipes/80-test_cmp_http_data/test_commands.csv @@ -82,12 +82,20 @@ expected,description, -section,val, -cmd,val,val2, -cacertsout,val,val2, -infoty 0,profile missing argument, -section,, -cmd,cr,, -cert,signer.crt, -key,signer.p12, -keypass,pass:12345,BLANK,, -profile,,,,, 0,profile extra argument, -section,, -cmd,cr,, -cert,signer.crt, -key,signer.p12, -keypass,pass:12345,BLANK,, -profile,profile1,profile2,,, ,,,,,,,,,,,,,,,,,,, -1,geninfo, -section,, -cmd,cr,, -cert,signer.crt, -key,signer.p12, -keypass,pass:12345,BLANK,, -geninfo,1.2.3:int:987,BLANK,,BLANK, -0,geninfo missing argument, -section,, -cmd,cr,, -cert,signer.crt, -key,signer.p12, -keypass,pass:12345,BLANK,, -geninfo,,,,, -0,geninfo bad syntax: leading '.', -section,, -cmd,cr,, -cert,signer.crt, -key,signer.p12, -keypass,pass:12345,BLANK,, -geninfo,.1.2.3:int:987,BLANK,,BLANK, -0,geninfo bad syntax: missing ':', -section,, -cmd,cr,, -cert,signer.crt, -key,signer.p12, -keypass,pass:12345,BLANK,, -geninfo,1.2.3:int987,,,, -0,geninfo bad syntax: double ':', -section,, -cmd,cr,, -cert,signer.crt, -key,signer.p12, -keypass,pass:12345,BLANK,, -geninfo,1.2.3:int::987,,,, +1,geninfo int, -section,, -cmd,cr,, -cert,signer.crt, -key,signer.p12, -keypass,pass:12345,BLANK,, -geninfo,1.3:int:987 +1,geninfo str, -section,, -cmd,cr,, -cert,signer.crt, -key,signer.p12, -keypass,pass:12345,BLANK,, -geninfo,id-kp:str:name +1,geninfo empty str, -section,, -cmd,cr,, -cert,signer.crt, -key,signer.p12, -keypass,pass:12345,BLANK,, -geninfo,id-kp:str: +1,geninfo str and int, -section,, -cmd,cr,, -cert,signer.crt, -key,signer.p12, -keypass,pass:12345,BLANK,, -geninfo, 'id-kp:str:name, 1.3:int:987' +0,geninfo missing argument, -section,, -cmd,cr,, -cert,signer.crt, -key,signer.p12, -keypass,pass:12345,BLANK,, -geninfo,,,,, +0,geninfo bad OID num syntax, -section,, -cmd,cr,, -cert,signer.crt, -key,signer.p12, -keypass,pass:12345,BLANK,, -geninfo,.1.2.3:int:987 +0,geninfo invalid OID number string, -section,, -cmd,cr,, -cert,signer.crt, -key,signer.p12, -keypass,pass:12345,BLANK,, -geninfo,1.333:int:987 +1,geninfo unknown OID number string, -section,, -cmd,cr,, -cert,signer.crt, -key,signer.p12, -keypass,pass:12345,BLANK,, -geninfo,1.33:int:987 +0,geninfo bad OID name: trailing '_', -section,, -cmd,cr,, -cert,signer.crt, -key,signer.p12, -keypass,pass:12345,BLANK,, -geninfo,id-kp_:int:987 0,geninfo bad syntax: missing ':int', -section,, -cmd,cr,, -cert,signer.crt, -key,signer.p12, -keypass,pass:12345,BLANK,, -geninfo,1.2.3,,,, +0,geninfo bad type tag, -section,, -cmd,cr,, -cert,signer.crt, -key,signer.p12, -keypass,pass:12345,BLANK,, -geninfo,1.2.3:xyz:987,,,, +0,geninfo bad syntax: missing ':', -section,, -cmd,cr,, -cert,signer.crt, -key,signer.p12, -keypass,pass:12345,BLANK,, -geninfo,1.2.3:int987,,,, +0,geninfo bad int syntax: double ':', -section,, -cmd,cr,, -cert,signer.crt, -key,signer.p12, -keypass,pass:12345,BLANK,, -geninfo,1.2.3:int::987,,,, +0,geninfo bad int syntax: extra char, -section,, -cmd,cr,, -cert,signer.crt, -key,signer.p12, -keypass,pass:12345,BLANK,, -geninfo,1.2.3:int:987@,,,, ,,,,,,,,,,,,,,,,,,, 1,reqout ir+certConf rspout ip+pkiConf, -section,, -cmd,ir,,-reqout,_RESULT_DIR/ir.der _RESULT_DIR/certConf.der,,-rspout,_RESULT_DIR/ip.der _RESULT_DIR/pkiConf.der,,BLANK,,BLANK, 1,reqout cr rspout cp, -section,, -cmd,cr,,-reqout,_RESULT_DIR/cr.der,,-rspout,_RESULT_DIR/cp.der,,BLANK,,BLANK, -- Gitee From d8111d32091437d3d94df8ded54f5b179e7acf96 Mon Sep 17 00:00:00 2001 From: "Dr. David von Oheimb" Date: Fri, 15 Sep 2023 13:42:19 +0200 Subject: [PATCH 19/92] openssl-cmp.pod.in: fix grammar glitch Reviewed-by: Tomas Mraz Reviewed-by: Shane Lontis (Merged from https://github.com/openssl/openssl/pull/21281) Signed-off-by: lanming1120 --- doc/man1/openssl-cmp.pod.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/man1/openssl-cmp.pod.in b/doc/man1/openssl-cmp.pod.in index 911b63e155..21e4bd95b7 100644 --- a/doc/man1/openssl-cmp.pod.in +++ b/doc/man1/openssl-cmp.pod.in @@ -1281,7 +1281,7 @@ In order to update the enrolled certificate one may call openssl cmp -section insta,kur -using with MAC-based protection with PBM or +using MAC-based protection with PBM or openssl cmp -section insta,kur,signature -- Gitee From 267e8e7316610a03008176aac3dc231c05534d11 Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Mon, 11 Dec 2023 15:40:19 +0100 Subject: [PATCH 20/92] test_export_key_mat(): Long context support works with new fips provider only Reviewed-by: Shane Lontis Reviewed-by: Hugo Landau (Merged from https://github.com/openssl/openssl/pull/23007) Signed-off-by: lanming1120 --- test/sslapitest.c | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/test/sslapitest.c b/test/sslapitest.c index efea1a6495..e2c4563fd3 100644 --- a/test/sslapitest.c +++ b/test/sslapitest.c @@ -6335,6 +6335,7 @@ static int test_export_key_mat(int tst) const unsigned char context[] = "context"; const unsigned char *emptycontext = NULL; unsigned char longcontext[1280]; + int test_longcontext = fips_provider_version_ge(libctx, 3, 3, 0); unsigned char ckeymat1[80], ckeymat2[80], ckeymat3[80], ckeymat4[80]; unsigned char skeymat1[80], skeymat2[80], skeymat3[80], skeymat4[80]; size_t labellen; @@ -6429,12 +6430,14 @@ static int test_export_key_mat(int tst) sizeof(ckeymat3), label, labellen, NULL, 0, 0), 1) - || !TEST_int_eq(SSL_export_keying_material(clientssl, ckeymat4, - sizeof(ckeymat4), label, - labellen, - longcontext, - sizeof(longcontext), 1), - 1) + || (test_longcontext + && !TEST_int_eq(SSL_export_keying_material(clientssl, + ckeymat4, + sizeof(ckeymat4), label, + labellen, + longcontext, + sizeof(longcontext), 1), + 1)) || !TEST_int_eq(SSL_export_keying_material(serverssl, skeymat1, sizeof(skeymat1), label, labellen, @@ -6450,12 +6453,13 @@ static int test_export_key_mat(int tst) sizeof(skeymat3), label, labellen, NULL, 0, 0), 1) - || !TEST_int_eq(SSL_export_keying_material(serverssl, skeymat4, - sizeof(skeymat4), label, - labellen, - longcontext, - sizeof(longcontext), 1), - 1) + || (test_longcontext + && !TEST_int_eq(SSL_export_keying_material(serverssl, skeymat4, + sizeof(skeymat4), label, + labellen, + longcontext, + sizeof(longcontext), 1), + 1)) /* * Check that both sides created the same key material with the * same context. @@ -6478,8 +6482,9 @@ static int test_export_key_mat(int tst) * Check that both sides created the same key material with a * long context. */ - || !TEST_mem_eq(ckeymat4, sizeof(ckeymat4), skeymat4, - sizeof(skeymat4)) + || (test_longcontext + && !TEST_mem_eq(ckeymat4, sizeof(ckeymat4), skeymat4, + sizeof(skeymat4))) /* Different contexts should produce different results */ || !TEST_mem_ne(ckeymat1, sizeof(ckeymat1), ckeymat2, sizeof(ckeymat2))) -- Gitee From 703f7f54b1828336e7e7695827bab8970ebf1112 Mon Sep 17 00:00:00 2001 From: Bernd Edlinger Date: Mon, 18 Dec 2023 21:38:22 +0100 Subject: [PATCH 21/92] Fix no-des failure in test_cms The newly introduced test case do not work when configured with no-des, fix that by choosing -aes128 as cipher. Fixes ffed597882ba ("cms: avoid intermittent test failure") Reviewed-by: Hugo Landau Reviewed-by: Matt Caswell Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/23086) Signed-off-by: lanming1120 --- test/recipes/80-test_cms.t | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/recipes/80-test_cms.t b/test/recipes/80-test_cms.t index 3af1a0ce55..6a9792128b 100644 --- a/test/recipes/80-test_cms.t +++ b/test/recipes/80-test_cms.t @@ -1193,7 +1193,7 @@ subtest "encrypt to three recipients with RSA-OAEP, key only decrypt" => sub { ok(run(app(['openssl', 'cms', @defaultprov, - '-encrypt', + '-encrypt', '-aes128', '-in', $pt, '-out', $ct, '-stream', @@ -1207,7 +1207,7 @@ subtest "encrypt to three recipients with RSA-OAEP, key only decrypt" => sub { "encrypt to three recipients with RSA-OAEP (avoid openssl/project issue#380)"); ok(run(app(['openssl', 'cms', @defaultprov, - '-decrypt', + '-decrypt', '-aes128', '-in', $ct, '-out', $ptpt, '-inkey', catfile($smdir, "smrsa3-key.pem"), -- Gitee From 8f27ed0de88c0bfe81bfa3c619d14d4a7f62adfe Mon Sep 17 00:00:00 2001 From: Kai Pastor Date: Sun, 17 Dec 2023 11:26:50 +0100 Subject: [PATCH 22/92] Fix comment syntax Reviewed-by: Hugo Landau Reviewed-by: Tom Cosgrove (Merged from https://github.com/openssl/openssl/pull/23072) Signed-off-by: lanming1120 --- crypto/ec/asm/ecp_sm2p256-armv8.pl | 316 ++++++++++++++--------------- 1 file changed, 158 insertions(+), 158 deletions(-) diff --git a/crypto/ec/asm/ecp_sm2p256-armv8.pl b/crypto/ec/asm/ecp_sm2p256-armv8.pl index 50950865e4..62fadc0454 100644 --- a/crypto/ec/asm/ecp_sm2p256-armv8.pl +++ b/crypto/ec/asm/ecp_sm2p256-armv8.pl @@ -28,44 +28,44 @@ my ($t4,$t5,$t6,$t7,$t8)=map("x$_",(15..19)); sub bn_mod_add() { my $mod = shift; $code.=<<___; - # Load inputs + // Load inputs ldp $s0,$s1,[x1] ldp $s2,$s3,[x1,#16] ldp $s4,$s5,[x2] ldp $s6,$s7,[x2,#16] - # Addition + // Addition adds $s0,$s0,$s4 adcs $s1,$s1,$s5 adcs $s2,$s2,$s6 adcs $s3,$s3,$s7 adc $t4,xzr,xzr - # Load polynomial + // Load polynomial adr x2,$mod ldp $s4,$s5,[x2] ldp $s6,$s7,[x2,#16] - # Backup Addition + // Backup Addition mov $t0,$s0 mov $t1,$s1 mov $t2,$s2 mov $t3,$s3 - # Sub polynomial + // Sub polynomial subs $t0,$t0,$s4 sbcs $t1,$t1,$s5 sbcs $t2,$t2,$s6 sbcs $t3,$t3,$s7 sbcs $t4,$t4,xzr - # Select based on carry + // Select based on carry csel $s0,$s0,$t0,cc csel $s1,$s1,$t1,cc csel $s2,$s2,$t2,cc csel $s3,$s3,$t3,cc - # Store results + // Store results stp $s0,$s1,[x0] stp $s2,$s3,[x0,#16] ___ @@ -74,44 +74,44 @@ ___ sub bn_mod_sub() { my $mod = shift; $code.=<<___; - # Load inputs + // Load inputs ldp $s0,$s1,[x1] ldp $s2,$s3,[x1,#16] ldp $s4,$s5,[x2] ldp $s6,$s7,[x2,#16] - # Subtraction + // Subtraction subs $s0,$s0,$s4 sbcs $s1,$s1,$s5 sbcs $s2,$s2,$s6 sbcs $s3,$s3,$s7 sbc $t4,xzr,xzr - # Load polynomial + // Load polynomial adr x2,$mod ldp $s4,$s5,[x2] ldp $s6,$s7,[x2,#16] - # Backup subtraction + // Backup subtraction mov $t0,$s0 mov $t1,$s1 mov $t2,$s2 mov $t3,$s3 - # Add polynomial + // Add polynomial adds $t0,$t0,$s4 adcs $t1,$t1,$s5 adcs $t2,$t2,$s6 adcs $t3,$t3,$s7 tst $t4,$t4 - # Select based on carry + // Select based on carry csel $s0,$s0,$t0,eq csel $s1,$s1,$t1,eq csel $s2,$s2,$t2,eq csel $s3,$s3,$t3,eq - # Store results + // Store results stp $s0,$s1,[x0] stp $s2,$s3,[x0,#16] ___ @@ -120,38 +120,38 @@ ___ sub bn_mod_div_by_2() { my $mod = shift; $code.=<<___; - # Load inputs + // Load inputs ldp $s0,$s1,[x1] ldp $s2,$s3,[x1,#16] - # Save the least significant bit + // Save the least significant bit mov $t0,$s0 - # Right shift 1 + // Right shift 1 extr $s0,$s1,$s0,#1 extr $s1,$s2,$s1,#1 extr $s2,$s3,$s2,#1 lsr $s3,$s3,#1 - # Load mod + // Load mod adr x2,$mod ldp $s4,$s5,[x2] ldp $s6,$s7,[x2,#16] - # Parity check + // Parity check tst $t0,#1 csel $s4,xzr,$s4,eq csel $s5,xzr,$s5,eq csel $s6,xzr,$s6,eq csel $s7,xzr,$s7,eq - # Add + // Add adds $s0,$s0,$s4 adcs $s1,$s1,$s5 adcs $s2,$s2,$s6 adc $s3,$s3,$s7 - # Store results + // Store results stp $s0,$s1,[x0] stp $s2,$s3,[x0,#16] ___ @@ -183,17 +183,17 @@ $code.=<<___; .align 5 bn_rshift1: AARCH64_VALID_CALL_TARGET - # Load inputs + // Load inputs ldp $s0,$s1,[x0] ldp $s2,$s3,[x0,#16] - # Right shift + // Right shift extr $s0,$s1,$s0,#1 extr $s1,$s2,$s1,#1 extr $s2,$s3,$s2,#1 lsr $s3,$s3,#1 - # Store results + // Store results stp $s0,$s1,[x0] stp $s2,$s3,[x0,#16] @@ -206,19 +206,19 @@ bn_rshift1: .align 5 bn_sub: AARCH64_VALID_CALL_TARGET - # Load inputs + // Load inputs ldp $s0,$s1,[x1] ldp $s2,$s3,[x1,#16] ldp $s4,$s5,[x2] ldp $s6,$s7,[x2,#16] - # Subtraction + // Subtraction subs $s0,$s0,$s4 sbcs $s1,$s1,$s5 sbcs $s2,$s2,$s6 sbc $s3,$s3,$s7 - # Store results + // Store results stp $s0,$s1,[x0] stp $s2,$s3,[x0,#16] @@ -255,11 +255,11 @@ $code.=<<___; .align 5 ecp_sm2p256_mul_by_3: AARCH64_VALID_CALL_TARGET - # Load inputs + // Load inputs ldp $s0,$s1,[x1] ldp $s2,$s3,[x1,#16] - # 2*a + // 2*a adds $s0,$s0,$s0 adcs $s1,$s1,$s1 adcs $s2,$s2,$s2 @@ -271,7 +271,7 @@ ecp_sm2p256_mul_by_3: mov $t2,$s2 mov $t3,$s3 - # Sub polynomial + // Sub polynomial adr x2,.Lpoly ldp $s4,$s5,[x2] ldp $s6,$s7,[x2,#16] @@ -287,7 +287,7 @@ ecp_sm2p256_mul_by_3: csel $s3,$s3,$t3,cs eor $t4,$t4,$t4 - # 3*a + // 3*a ldp $s4,$s5,[x1] ldp $s6,$s7,[x1,#16] adds $s0,$s0,$s4 @@ -301,7 +301,7 @@ ecp_sm2p256_mul_by_3: mov $t2,$s2 mov $t3,$s3 - # Sub polynomial + // Sub polynomial adr x2,.Lpoly ldp $s4,$s5,[x2] ldp $s6,$s7,[x2,#16] @@ -316,7 +316,7 @@ ecp_sm2p256_mul_by_3: csel $s2,$s2,$t2,cs csel $s3,$s3,$t3,cs - # Store results + // Store results stp $s0,$s1,[x0] stp $s2,$s3,[x0,#16] @@ -360,45 +360,45 @@ $code.=<<___; .size ecp_sm2p256_sub_mod_ord,.-ecp_sm2p256_sub_mod_ord .macro RDC - # a = | s7 | ... | s0 |, where si are 64-bit quantities - # = |a15|a14| ... |a1|a0|, where ai are 32-bit quantities - # | s7 | s6 | s5 | s4 | - # | a15 | a14 | a13 | a12 | a11 | a10 | a9 | a8 | - # | s3 | s2 | s1 | s0 | - # | a7 | a6 | a5 | a4 | a3 | a2 | a1 | a0 | - # ================================================= - # | a8 | a11 | a10 | a9 | a8 | 0 | s4 | (+) - # | a9 | a15 | s6 | a11 | 0 | a10 | a9 | (+) - # | a10 | 0 | a14 | a13 | a12 | 0 | s5 | (+) - # | a11 | 0 | s7 | a13 | 0 | a12 | a11 | (+) - # | a12 | 0 | s7 | a13 | 0 | s6 | (+) - # | a12 | 0 | 0 | a15 | a14 | 0 | a14 | a13 | (+) - # | a13 | 0 | 0 | 0 | a15 | 0 | a14 | a13 | (+) - # | a13 | 0 | 0 | 0 | 0 | 0 | s7 | (+) - # | a14 | 0 | 0 | 0 | 0 | 0 | s7 | (+) - # | a14 | 0 | 0 | 0 | 0 | 0 | 0 | a15 | (+) - # | a15 | 0 | 0 | 0 | 0 | 0 | 0 | a15 | (+) - # | a15 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | (+) - # | s7 | 0 | 0 | 0 | 0 | 0 | 0 | (+) - # | 0 | 0 | 0 | 0 | 0 | a8 | 0 | 0 | (-) - # | 0 | 0 | 0 | 0 | 0 | a9 | 0 | 0 | (-) - # | 0 | 0 | 0 | 0 | 0 | a13 | 0 | 0 | (-) - # | 0 | 0 | 0 | 0 | 0 | a14 | 0 | 0 | (-) - # | U[7]| U[6]| U[5]| U[4]| U[3]| U[2]| U[1]| U[0]| - # | V[3] | V[2] | V[1] | V[0] | - - # 1. 64-bit addition - # t2=s6+s7+s7 + // a = | s7 | ... | s0 |, where si are 64-bit quantities + // = |a15|a14| ... |a1|a0|, where ai are 32-bit quantities + // | s7 | s6 | s5 | s4 | + // | a15 | a14 | a13 | a12 | a11 | a10 | a9 | a8 | + // | s3 | s2 | s1 | s0 | + // | a7 | a6 | a5 | a4 | a3 | a2 | a1 | a0 | + // ================================================= + // | a8 | a11 | a10 | a9 | a8 | 0 | s4 | (+) + // | a9 | a15 | s6 | a11 | 0 | a10 | a9 | (+) + // | a10 | 0 | a14 | a13 | a12 | 0 | s5 | (+) + // | a11 | 0 | s7 | a13 | 0 | a12 | a11 | (+) + // | a12 | 0 | s7 | a13 | 0 | s6 | (+) + // | a12 | 0 | 0 | a15 | a14 | 0 | a14 | a13 | (+) + // | a13 | 0 | 0 | 0 | a15 | 0 | a14 | a13 | (+) + // | a13 | 0 | 0 | 0 | 0 | 0 | s7 | (+) + // | a14 | 0 | 0 | 0 | 0 | 0 | s7 | (+) + // | a14 | 0 | 0 | 0 | 0 | 0 | 0 | a15 | (+) + // | a15 | 0 | 0 | 0 | 0 | 0 | 0 | a15 | (+) + // | a15 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | (+) + // | s7 | 0 | 0 | 0 | 0 | 0 | 0 | (+) + // | 0 | 0 | 0 | 0 | 0 | a8 | 0 | 0 | (-) + // | 0 | 0 | 0 | 0 | 0 | a9 | 0 | 0 | (-) + // | 0 | 0 | 0 | 0 | 0 | a13 | 0 | 0 | (-) + // | 0 | 0 | 0 | 0 | 0 | a14 | 0 | 0 | (-) + // | U[7]| U[6]| U[5]| U[4]| U[3]| U[2]| U[1]| U[0]| + // | V[3] | V[2] | V[1] | V[0] | + + // 1. 64-bit addition + // t2=s6+s7+s7 adds $t2,$s6,$s7 adcs $t1,xzr,xzr adds $t2,$t2,$s7 adcs $t1,$t1,xzr - # t3=s4+s5+t2 + // t3=s4+s5+t2 adds $t3,$s4,$t2 adcs $t4,$t1,xzr adds $t3,$t3,$s5 adcs $t4,$t4,xzr - # sum + // sum adds $s0,$s0,$t3 adcs $s1,$s1,$t4 adcs $s2,$s2,$t2 @@ -410,7 +410,7 @@ $code.=<<___; stp $s0,$s1,[sp,#32] stp $s2,$s3,[sp,#48] - # 2. 64-bit to 32-bit spread + // 2. 64-bit to 32-bit spread mov $t1,#0xffffffff mov $s0,$s4 mov $s1,$s5 @@ -425,7 +425,7 @@ $code.=<<___; lsr $s6,$s6,#32 // a13 lsr $s7,$s7,#32 // a15 - # 3. 32-bit addition + // 3. 32-bit addition add $t1,$a14,$a12 // t1 <- a12 + a14 add $t2,$a15,$a13 // t2 <- a13 + a15 add $t3,$a8,$a9 // t3 <- a8 + a9 @@ -446,53 +446,53 @@ $code.=<<___; add $a11,$a11,$t2 // a11 <- a9 + a11 + 2*(a13 + a15) add $t1,$t1,$t4 // t1 <- a10 + a12 + 2*a14 - # U[0] s5 a9 + a11 + 2*(a13 + a15) - # U[1] t1 a10 + a12 + 2*a14 - # U[2] -t3 a8 + a9 + a13 + a14 - # U[3] s2 a8 + a11 + a12 + 2*a13 + a14 + a15 - # U[4] s4 a9 + a13 + a15 - # U[5] t4 a10 + a14 - # U[6] s7 a11 + a15 - # U[7] s1 a8 + a9 + a10 + a11 + 2*(a12 + a13 + a14 + a15) + // U[0] s5 a9 + a11 + 2*(a13 + a15) + // U[1] t1 a10 + a12 + 2*a14 + // U[2] -t3 a8 + a9 + a13 + a14 + // U[3] s2 a8 + a11 + a12 + 2*a13 + a14 + a15 + // U[4] s4 a9 + a13 + a15 + // U[5] t4 a10 + a14 + // U[6] s7 a11 + a15 + // U[7] s1 a8 + a9 + a10 + a11 + 2*(a12 + a13 + a14 + a15) - # 4. 32-bit to 64-bit + // 4. 32-bit to 64-bit lsl $s0,$t1,#32 extr $t1,$s2,$t1,#32 extr $s2,$t4,$s2,#32 extr $t4,$s1,$t4,#32 lsr $s1,$s1,#32 - # 5. 64-bit addition + // 5. 64-bit addition adds $s5,$s5,$s0 adcs $t1,$t1,xzr adcs $s4,$s4,$s2 adcs $s7,$s7,$t4 adcs $t0,$t0,$s1 - # V[0] s5 - # V[1] t1 - # V[2] s4 - # V[3] s7 - # carry t0 - # sub t3 + // V[0] s5 + // V[1] t1 + // V[2] s4 + // V[3] s7 + // carry t0 + // sub t3 - # 5. Process s0-s3 + // 5. Process s0-s3 ldp $s0,$s1,[sp,#32] ldp $s2,$s3,[sp,#48] - # add with V0-V3 + // add with V0-V3 adds $s0,$s0,$s5 adcs $s1,$s1,$t1 adcs $s2,$s2,$s4 adcs $s3,$s3,$s7 adcs $t0,$t0,xzr - # sub with t3 + // sub with t3 subs $s1,$s1,$t3 sbcs $s2,$s2,xzr sbcs $s3,$s3,xzr sbcs $t0,$t0,xzr - # 6. MOD - # First Mod + // 6. MOD + // First Mod lsl $t1,$t0,#32 subs $t2,$t1,$t0 @@ -501,8 +501,8 @@ $code.=<<___; adcs $s2,$s2,xzr adcs $s3,$s3,$t1 - # Last Mod - # return y - p if y > p else y + // Last Mod + // return y - p if y > p else y mov $s4,$s0 mov $s5,$s1 mov $s6,$s2 @@ -533,44 +533,44 @@ $code.=<<___; .align 5 ecp_sm2p256_mul: AARCH64_SIGN_LINK_REGISTER - # Store scalar registers + // Store scalar registers stp x29,x30,[sp,#-80]! add x29,sp,#0 stp x16,x17,[sp,#16] stp x18,x19,[sp,#64] - # Load inputs + // Load inputs ldp $s0,$s1,[x1] ldp $s2,$s3,[x1,#16] ldp $s4,$s5,[x2] ldp $s6,$s7,[x2,#16] -### multiplication ### - # ======================== - # s3 s2 s1 s0 - # * s7 s6 s5 s4 - # ------------------------ - # + s0 s0 s0 s0 - # * * * * - # s7 s6 s5 s4 - # s1 s1 s1 s1 - # * * * * - # s7 s6 s5 s4 - # s2 s2 s2 s2 - # * * * * - # s7 s6 s5 s4 - # s3 s3 s3 s3 - # * * * * - # s7 s6 s5 s4 - # ------------------------ - # s7 s6 s5 s4 s3 s2 s1 s0 - # ======================== - -### s0*s4 ### +// ### multiplication ### + // ======================== + // s3 s2 s1 s0 + // * s7 s6 s5 s4 + // ------------------------ + // + s0 s0 s0 s0 + // * * * * + // s7 s6 s5 s4 + // s1 s1 s1 s1 + // * * * * + // s7 s6 s5 s4 + // s2 s2 s2 s2 + // * * * * + // s7 s6 s5 s4 + // s3 s3 s3 s3 + // * * * * + // s7 s6 s5 s4 + // ------------------------ + // s7 s6 s5 s4 s3 s2 s1 s0 + // ======================== + +// ### s0*s4 ### mul $t5,$s0,$s4 umulh $t2,$s0,$s4 -### s1*s4 + s0*s5 ### +// ### s1*s4 + s0*s5 ### mul $t0,$s1,$s4 umulh $t1,$s1,$s4 adds $t2,$t2,$t0 @@ -582,7 +582,7 @@ ecp_sm2p256_mul: adcs $t3,$t3,$t1 adcs $t4,xzr,xzr -### s2*s4 + s1*s5 + s0*s6 ### +// ### s2*s4 + s1*s5 + s0*s6 ### mul $t0,$s2,$s4 umulh $t1,$s2,$s4 adds $t3,$t3,$t0 @@ -600,7 +600,7 @@ ecp_sm2p256_mul: adcs $t4,$t4,$t1 adcs $t6,$t6,xzr -### s3*s4 + s2*s5 + s1*s6 + s0*s7 ### +// ### s3*s4 + s2*s5 + s1*s6 + s0*s7 ### mul $t0,$s3,$s4 umulh $t1,$s3,$s4 adds $t4,$t4,$t0 @@ -625,7 +625,7 @@ ecp_sm2p256_mul: adcs $t6,$t6,$t1 adcs $t7,$t7,xzr -### s3*s5 + s2*s6 + s1*s7 ### +// ### s3*s5 + s2*s6 + s1*s7 ### mul $t0,$s3,$s5 umulh $t1,$s3,$s5 adds $t6,$t6,$t0 @@ -644,7 +644,7 @@ ecp_sm2p256_mul: adcs $t7,$t7,$t1 adcs $t8,$t8,xzr -### s3*s6 + s2*s7 ### +// ### s3*s6 + s2*s7 ### mul $t0,$s3,$s6 umulh $t1,$s3,$s6 adds $t7,$t7,$t0 @@ -657,7 +657,7 @@ ecp_sm2p256_mul: adcs $t8,$t8,$t1 adcs $t6,$t6,xzr -### s3*s7 ### +// ### s3*s7 ### mul $t0,$s3,$s7 umulh $t1,$s3,$s7 adds $s6,$t8,$t0 @@ -668,15 +668,15 @@ ecp_sm2p256_mul: mov $s2,$t3 mov $s3,$t4 - # result of mul: s7 s6 s5 s4 s3 s2 s1 s0 + // result of mul: s7 s6 s5 s4 s3 s2 s1 s0 -### Reduction ### +// ### Reduction ### RDC stp $s0,$s1,[x0] stp $s2,$s3,[x0,#16] - # Restore scalar registers + // Restore scalar registers ldp x16,x17,[sp,#16] ldp x18,x19,[sp,#64] ldp x29,x30,[sp],#80 @@ -692,48 +692,48 @@ ecp_sm2p256_mul: ecp_sm2p256_sqr: AARCH64_SIGN_LINK_REGISTER - # Store scalar registers + // Store scalar registers stp x29,x30,[sp,#-80]! add x29,sp,#0 stp x16,x17,[sp,#16] stp x18,x19,[sp,#64] - # Load inputs + // Load inputs ldp $s4,$s5,[x1] ldp $s6,$s7,[x1,#16] -### square ### - # ======================== - # s7 s6 s5 s4 - # * s7 s6 s5 s4 - # ------------------------ - # + s4 s4 s4 s4 - # * * * * - # s7 s6 s5 s4 - # s5 s5 s5 s5 - # * * * * - # s7 s6 s5 s4 - # s6 s6 s6 s6 - # * * * * - # s7 s6 s5 s4 - # s7 s7 s7 s7 - # * * * * - # s7 s6 s5 s4 - # ------------------------ - # s7 s6 s5 s4 s3 s2 s1 s0 - # ======================== - -### s4*s5 ### +// ### square ### + // ======================== + // s7 s6 s5 s4 + // * s7 s6 s5 s4 + // ------------------------ + // + s4 s4 s4 s4 + // * * * * + // s7 s6 s5 s4 + // s5 s5 s5 s5 + // * * * * + // s7 s6 s5 s4 + // s6 s6 s6 s6 + // * * * * + // s7 s6 s5 s4 + // s7 s7 s7 s7 + // * * * * + // s7 s6 s5 s4 + // ------------------------ + // s7 s6 s5 s4 s3 s2 s1 s0 + // ======================== + +// ### s4*s5 ### mul $s1,$s4,$s5 umulh $s2,$s4,$s5 -### s4*s6 ### +// ### s4*s6 ### mul $t0,$s6,$s4 umulh $s3,$s6,$s4 adds $s2,$s2,$t0 adcs $s3,$s3,xzr -### s4*s7 + s5*s6 ### +// ### s4*s7 + s5*s6 ### mul $t0,$s7,$s4 umulh $t1,$s7,$s4 adds $s3,$s3,$t0 @@ -745,19 +745,19 @@ ecp_sm2p256_sqr: adcs $s0,$s0,$t1 adcs $t2,xzr,xzr -### s5*s7 ### +// ### s5*s7 ### mul $t0,$s7,$s5 umulh $t1,$s7,$s5 adds $s0,$s0,$t0 adcs $t2,$t2,$t1 -### s6*s7 ### +// ### s6*s7 ### mul $t0,$s7,$s6 umulh $t1,$s7,$s6 adds $t2,$t2,$t0 adcs $t3,$t1,xzr -### 2*(t3,t2,s0,s3,s2,s1) ### +// ### 2*(t3,t2,s0,s3,s2,s1) ### adds $s1,$s1,$s1 adcs $s2,$s2,$s2 adcs $s3,$s3,$s3 @@ -766,19 +766,19 @@ ecp_sm2p256_sqr: adcs $t3,$t3,$t3 adcs $t4,xzr,xzr -### s4*s4 ### +// ### s4*s4 ### mul $t5,$s4,$s4 umulh $t6,$s4,$s4 -### s5*s5 ### +// ### s5*s5 ### mul $s4,$s5,$s5 umulh $s5,$s5,$s5 -### s6*s6 ### +// ### s6*s6 ### mul $t0,$s6,$s6 umulh $t1,$s6,$s6 -### s7*s7 ### +// ### s7*s7 ### mul $t7,$s7,$s7 umulh $t8,$s7,$s7 @@ -796,15 +796,15 @@ ecp_sm2p256_sqr: mov $s6,$t3 mov $s7,$t4 - # result of mul: s7 s6 s5 s4 s3 s2 s1 s0 + // result of mul: s7 s6 s5 s4 s3 s2 s1 s0 -### Reduction ### +// ### Reduction ### RDC stp $s0,$s1,[x0] stp $s2,$s3,[x0,#16] - # Restore scalar registers + // Restore scalar registers ldp x16,x17,[sp,#16] ldp x18,x19,[sp,#64] ldp x29,x30,[sp],#80 -- Gitee From 4437aa35a8e61ae570474bcc9d049299920427d5 Mon Sep 17 00:00:00 2001 From: Kai Pastor Date: Sun, 17 Dec 2023 11:27:19 +0100 Subject: [PATCH 23/92] Fix declspec align syntax Reviewed-by: Hugo Landau Reviewed-by: Tom Cosgrove (Merged from https://github.com/openssl/openssl/pull/23072) Signed-off-by: lanming1120 --- crypto/ec/ecp_sm2p256.c | 76 ++++++++++++++++++++--------------------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/crypto/ec/ecp_sm2p256.c b/crypto/ec/ecp_sm2p256.c index 6ec4245529..7668b61378 100644 --- a/crypto/ec/ecp_sm2p256.c +++ b/crypto/ec/ecp_sm2p256.c @@ -40,28 +40,28 @@ typedef struct { #if !defined(OPENSSL_NO_SM2_PRECOMP) /* Coordinates of G, for which we have precomputed tables */ -static const BN_ULONG def_xG[P256_LIMBS] ALIGN32 = { +ALIGN32 static const BN_ULONG def_xG[P256_LIMBS] = { 0x715a4589334c74c7, 0x8fe30bbff2660be1, 0x5f9904466a39c994, 0x32c4ae2c1f198119 }; -static const BN_ULONG def_yG[P256_LIMBS] ALIGN32 = { +ALIGN32 static const BN_ULONG def_yG[P256_LIMBS] = { 0x02df32e52139f0a0, 0xd0a9877cc62a4740, 0x59bdcee36b692153, 0xbc3736a2f4f6779c, }; #endif /* p and order for SM2 according to GB/T 32918.5-2017 */ -static const BN_ULONG def_p[P256_LIMBS] ALIGN32 = { +ALIGN32 static const BN_ULONG def_p[P256_LIMBS] = { 0xffffffffffffffff, 0xffffffff00000000, 0xffffffffffffffff, 0xfffffffeffffffff }; -static const BN_ULONG def_ord[P256_LIMBS] ALIGN32 = { +ALIGN32 static const BN_ULONG def_ord[P256_LIMBS] = { 0x53bbf40939d54123, 0x7203df6b21c6052b, 0xffffffffffffffff, 0xfffffffeffffffff }; -static const BN_ULONG ONE[P256_LIMBS] ALIGN32 = {1, 0, 0, 0}; +ALIGN32 static const BN_ULONG ONE[P256_LIMBS] = {1, 0, 0, 0}; /* Functions implemented in assembly */ /* @@ -139,10 +139,10 @@ static ossl_inline int is_greater(const BN_ULONG *a, const BN_ULONG *b) /* Binary algorithm for inversion in Fp */ #define BN_MOD_INV(out, in, mod_div, mod_sub, mod) \ do { \ - BN_ULONG u[4] ALIGN32; \ - BN_ULONG v[4] ALIGN32; \ - BN_ULONG x1[4] ALIGN32 = {1, 0, 0, 0}; \ - BN_ULONG x2[4] ALIGN32 = {0}; \ + ALIGN32 BN_ULONG u[4]; \ + ALIGN32 BN_ULONG v[4]; \ + ALIGN32 BN_ULONG x1[4] = {1, 0, 0, 0}; \ + ALIGN32 BN_ULONG x2[4] = {0}; \ \ if (is_zeros(in)) \ return; \ @@ -188,9 +188,9 @@ static ossl_inline void ecp_sm2p256_mod_ord_inverse(BN_ULONG* out, static void ecp_sm2p256_point_double(P256_POINT *R, const P256_POINT *P) { unsigned int i; - BN_ULONG tmp0[P256_LIMBS] ALIGN32; - BN_ULONG tmp1[P256_LIMBS] ALIGN32; - BN_ULONG tmp2[P256_LIMBS] ALIGN32; + ALIGN32 BN_ULONG tmp0[P256_LIMBS]; + ALIGN32 BN_ULONG tmp1[P256_LIMBS]; + ALIGN32 BN_ULONG tmp2[P256_LIMBS]; /* zero-check P->Z */ if (is_zeros(P->Z)) { @@ -225,10 +225,10 @@ static void ecp_sm2p256_point_add_affine(P256_POINT *R, const P256_POINT *P, const P256_POINT_AFFINE *Q) { unsigned int i; - BN_ULONG tmp0[P256_LIMBS] ALIGN32 = {0}; - BN_ULONG tmp1[P256_LIMBS] ALIGN32 = {0}; - BN_ULONG tmp2[P256_LIMBS] ALIGN32 = {0}; - BN_ULONG tmp3[P256_LIMBS] ALIGN32 = {0}; + ALIGN32 BN_ULONG tmp0[P256_LIMBS] = {0}; + ALIGN32 BN_ULONG tmp1[P256_LIMBS] = {0}; + ALIGN32 BN_ULONG tmp2[P256_LIMBS] = {0}; + ALIGN32 BN_ULONG tmp3[P256_LIMBS] = {0}; /* zero-check P->Z */ if (is_zeros(P->Z)) { @@ -288,9 +288,9 @@ static void ecp_sm2p256_point_add(P256_POINT *R, const P256_POINT *P, const P256_POINT *Q) { unsigned int i; - BN_ULONG tmp0[P256_LIMBS] ALIGN32 = {0}; - BN_ULONG tmp1[P256_LIMBS] ALIGN32 = {0}; - BN_ULONG tmp2[P256_LIMBS] ALIGN32 = {0}; + ALIGN32 BN_ULONG tmp0[P256_LIMBS] = {0}; + ALIGN32 BN_ULONG tmp1[P256_LIMBS] = {0}; + ALIGN32 BN_ULONG tmp2[P256_LIMBS] = {0}; /* zero-check P | Q ->Z */ if (is_zeros(P->Z)) { @@ -382,7 +382,7 @@ static void ecp_sm2p256_point_P_mul_by_scalar(P256_POINT *R, const BN_ULONG *k, { int i, init = 0; unsigned int index, mask = 0x0f; - P256_POINT precomputed[16] ALIGN64; + ALIGN64 P256_POINT precomputed[16]; memset(R, 0, sizeof(P256_POINT)); @@ -427,8 +427,8 @@ static void ecp_sm2p256_point_P_mul_by_scalar(P256_POINT *R, const BN_ULONG *k, static void ecp_sm2p256_point_get_affine(P256_POINT_AFFINE *R, const P256_POINT *P) { - BN_ULONG z_inv3[P256_LIMBS] ALIGN32 = {0}; - BN_ULONG z_inv2[P256_LIMBS] ALIGN32 = {0}; + ALIGN32 BN_ULONG z_inv3[P256_LIMBS] = {0}; + ALIGN32 BN_ULONG z_inv2[P256_LIMBS] = {0}; if (is_one(P->Z)) { memcpy(R->X, P->X, 32); @@ -461,13 +461,13 @@ static int ecp_sm2p256_get_affine(const EC_GROUP *group, const EC_POINT *point, BIGNUM *x, BIGNUM *y, BN_CTX *ctx) { - BN_ULONG z_inv2[P256_LIMBS] ALIGN32 = {0}; - BN_ULONG z_inv3[P256_LIMBS] ALIGN32 = {0}; - BN_ULONG x_aff[P256_LIMBS] ALIGN32 = {0}; - BN_ULONG y_aff[P256_LIMBS] ALIGN32 = {0}; - BN_ULONG point_x[P256_LIMBS] ALIGN32 = {0}; - BN_ULONG point_y[P256_LIMBS] ALIGN32 = {0}; - BN_ULONG point_z[P256_LIMBS] ALIGN32 = {0}; + ALIGN32 BN_ULONG z_inv2[P256_LIMBS] = {0}; + ALIGN32 BN_ULONG z_inv3[P256_LIMBS] = {0}; + ALIGN32 BN_ULONG x_aff[P256_LIMBS] = {0}; + ALIGN32 BN_ULONG y_aff[P256_LIMBS] = {0}; + ALIGN32 BN_ULONG point_x[P256_LIMBS] = {0}; + ALIGN32 BN_ULONG point_y[P256_LIMBS] = {0}; + ALIGN32 BN_ULONG point_z[P256_LIMBS] = {0}; if (EC_POINT_is_at_infinity(group, point)) { ECerr(ERR_LIB_EC, EC_R_POINT_AT_INFINITY); @@ -510,7 +510,7 @@ static int ecp_sm2p256_windowed_mul(const EC_GROUP *group, unsigned int i; int ret = 0; const BIGNUM **scalars = NULL; - BN_ULONG k[P256_LIMBS] ALIGN32 = {0}; + ALIGN32 BN_ULONG k[P256_LIMBS] = {0}; P256_POINT kP; ALIGN32 union { P256_POINT p; @@ -572,7 +572,7 @@ static int ecp_sm2p256_points_mul(const EC_GROUP *group, { int ret = 0, p_is_infinity = 0; const EC_POINT *generator = NULL; - BN_ULONG k[P256_LIMBS] ALIGN32 = {0}; + ALIGN32 BN_ULONG k[P256_LIMBS] = {0}; ALIGN32 union { P256_POINT p; P256_POINT_AFFINE a; @@ -646,9 +646,9 @@ err: static int ecp_sm2p256_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) { - BN_ULONG a_fe[P256_LIMBS] ALIGN32 = {0}; - BN_ULONG b_fe[P256_LIMBS] ALIGN32 = {0}; - BN_ULONG r_fe[P256_LIMBS] ALIGN32 = {0}; + ALIGN32 BN_ULONG a_fe[P256_LIMBS] = {0}; + ALIGN32 BN_ULONG b_fe[P256_LIMBS] = {0}; + ALIGN32 BN_ULONG r_fe[P256_LIMBS] = {0}; if (a == NULL || b == NULL || r == NULL) return 0; @@ -670,8 +670,8 @@ static int ecp_sm2p256_field_mul(const EC_GROUP *group, BIGNUM *r, static int ecp_sm2p256_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, BN_CTX *ctx) { - BN_ULONG a_fe[P256_LIMBS] ALIGN32 = {0}; - BN_ULONG r_fe[P256_LIMBS] ALIGN32 = {0}; + ALIGN32 BN_ULONG a_fe[P256_LIMBS] = {0}; + ALIGN32 BN_ULONG r_fe[P256_LIMBS] = {0}; if (a == NULL || r == NULL) return 0; @@ -693,8 +693,8 @@ static int ecp_sm2p256_inv_mod_ord(const EC_GROUP *group, BIGNUM *r, const BIGNUM *x, BN_CTX *ctx) { int ret = 0; - BN_ULONG t[P256_LIMBS] ALIGN32 = {0}; - BN_ULONG out[P256_LIMBS] ALIGN32 = {0}; + ALIGN32 BN_ULONG t[P256_LIMBS] = {0}; + ALIGN32 BN_ULONG out[P256_LIMBS] = {0}; if (bn_wexpand(r, P256_LIMBS) == NULL) { ECerr(ERR_LIB_EC, ERR_R_BN_LIB); -- Gitee From d4113cab2114203f5e0c40dfd311df109b3bba3d Mon Sep 17 00:00:00 2001 From: Xi Ruoyao Date: Sat, 25 Nov 2023 17:53:57 +0800 Subject: [PATCH 24/92] LoongArch64 assembly pack: Fix ChaCha20 ABI breakage The [LP64D ABI][1] requires the floating-point registers f24-f31 (aka fs0-fs7) callee-saved. The low 64 bits of a LSX/LASX vector register aliases with the corresponding FPR, so we must save and restore the callee-saved FPR when we writes into the corresponding vector register. This ABI breakage can be easily demonstrated by injecting the use of a saved FPR into the test in bio_enc_test.c: static int test_bio_enc_chacha20(int idx) { register double fs7 asm("f31") = 114.514; asm("#optimize barrier":"+f"(fs7)); return do_test_bio_cipher(EVP_chacha20(), idx) && fs7 == 114.514; } So fix it. To make the logic simpler, jump into the scalar implementation earlier when LSX and LASX are not enumerated in AT_HWCAP, or the input is too short. [1]: https://github.com/loongson/la-abi-specs/blob/v2.20/lapcs.adoc#floating-point-registers Reviewed-by: Neil Horman Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/22817) Signed-off-by: lanming1120 --- crypto/chacha/asm/chacha-loongarch64.pl | 46 +++++++++++++++++++------ 1 file changed, 36 insertions(+), 10 deletions(-) diff --git a/crypto/chacha/asm/chacha-loongarch64.pl b/crypto/chacha/asm/chacha-loongarch64.pl index ea9cc7ecce..9eed5860de 100644 --- a/crypto/chacha/asm/chacha-loongarch64.pl +++ b/crypto/chacha/asm/chacha-loongarch64.pl @@ -17,6 +17,14 @@ my ($a0,$a1,$a2,$a3,$a4,$a5,$a6,$a7)=map("\$r$_",(4..11)); my ($t0,$t1,$t2,$t3,$t4,$t5,$t6,$t7,$t8,$x)=map("\$r$_",(12..21)); my ($s0,$s1,$s2,$s3,$s4,$s5,$s6,$s7,$s8)=map("\$r$_",(23..31)); +# The saved floating-point registers in the LP64D ABI. In LoongArch +# with vector extension, the low 64 bits of a vector register alias with +# the corresponding FPR. So we must save and restore the corresponding +# FPR if we'll write into a vector register. The ABI only requires +# saving and restoring the FPR (i.e. 64 bits of the corresponding vector +# register), not the entire vector register. +my ($fs0,$fs1,$fs2,$fs3,$fs4,$fs5,$fs6,$fs7)=map("\$f$_",(24..31)); + # Here is the 128-bit vector register layout for LSX extension. my ($vr0,$vr1,$vr2,$vr3,$vr4,$vr5,$vr6,$vr7,$vr8,$vr9,$vr10, $vr11,$vr12,$vr13,$vr14,$vr15,$vr16,$vr17,$vr18,$vr19, @@ -66,13 +74,25 @@ ChaCha20_ctr32: la.pcrel $t0,OPENSSL_loongarch_hwcap_P ld.w $t0,$t0,0 + bleu $len,$t3,.LChaCha20_1x # goto 1x when len <= 64 + + andi $t0,$t0,LOONGARCH_HWCAP_LASX | LOONGARCH_HWCAP_LSX + beqz $t0,.LChaCha20_1x + + addi.d $sp,$sp,-64 + fst.d $fs0,$sp,0 + fst.d $fs1,$sp,8 + fst.d $fs2,$sp,16 + fst.d $fs3,$sp,24 + fst.d $fs4,$sp,32 + fst.d $fs5,$sp,40 + fst.d $fs6,$sp,48 + fst.d $fs7,$sp,56 + andi $t1,$t0,LOONGARCH_HWCAP_LASX bnez $t1,.LChaCha20_8x - andi $t2,$t0,LOONGARCH_HWCAP_LSX - bnez $t2,.LChaCha20_4x - - b .LChaCha20_1x + b .LChaCha20_4x EOF @@ -442,8 +462,6 @@ $code .= < Date: Mon, 18 Dec 2023 18:58:25 +0530 Subject: [PATCH 25/92] Update IPAddressOrRange_cmp function to handle switch case As there is no default case for a->type or b->type in the switch() statements, if the type does not fall into any defined cases then memcmp() will be done on garbage data. Adding default cases in both switches. CLA: trivial Reviewed-by: Tom Cosgrove Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/23082) Signed-off-by: lanming1120 --- crypto/x509/v3_addr.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/crypto/x509/v3_addr.c b/crypto/x509/v3_addr.c index b990d54048..da9604cf96 100644 --- a/crypto/x509/v3_addr.c +++ b/crypto/x509/v3_addr.c @@ -300,6 +300,8 @@ static int IPAddressOrRange_cmp(const IPAddressOrRange *a, return -1; prefixlen_a = length * 8; break; + default: + return -1; } switch (b->type) { @@ -313,6 +315,8 @@ static int IPAddressOrRange_cmp(const IPAddressOrRange *a, return -1; prefixlen_b = length * 8; break; + default: + return -1; } if ((r = memcmp(addr_a, addr_b, length)) != 0) -- Gitee From 843bdb5531dd3c9842fa5a3eef85ea4fce825fab Mon Sep 17 00:00:00 2001 From: Xi Ruoyao Date: Sun, 26 Nov 2023 19:49:48 +0800 Subject: [PATCH 26/92] LoongArch64 assembly pack: Really implement OPENSSL_rdtsc LoongArch [rdtimel.w][1] instruction reads the low 32 bits of the 64-bit stable counter, implement OPENSSL_rdtsc with it instead of always returning 0. [1]:https://loongson.github.io/LoongArch-Documentation/LoongArch-Vol1-EN.html#_rdtimelh_w_rdtime_d Reviewed-by: Hugo Landau Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/22823) Signed-off-by: lanming1120 --- crypto/loongarch64cpuid.pl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crypto/loongarch64cpuid.pl b/crypto/loongarch64cpuid.pl index d16a8e98f2..8a84caca92 100644 --- a/crypto/loongarch64cpuid.pl +++ b/crypto/loongarch64cpuid.pl @@ -101,8 +101,8 @@ $code.=<<___; .globl OPENSSL_rdtsc .type OPENSSL_rdtsc,\@function OPENSSL_rdtsc: - move $a0,$zero - jr $ra + rdtimel.w $a0,$zero + jr $ra ___ } -- Gitee From 6bb6a8517761ad433f841d3faa9e33763f61c696 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 19 Dec 2023 18:00:12 +0000 Subject: [PATCH 27/92] Bump actions/setup-python from 4.7.1 to 5.0.0 Bumps [actions/setup-python](https://github.com/actions/setup-python) from 4.7.1 to 5.0.0. - [Release notes](https://github.com/actions/setup-python/releases) - [Commits](https://github.com/actions/setup-python/compare/v4.7.1...v5.0.0) --- updated-dependencies: - dependency-name: actions/setup-python dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] CLA: trivial Reviewed-by: Kurt Roeckx Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/22963) Signed-off-by: lanming1120 --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ae9ad6a269..c125b0684f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -485,7 +485,7 @@ jobs: - name: make run: make -s -j4 - name: Setup Python - uses: actions/setup-python@v4.7.1 + uses: actions/setup-python@v5.0.0 with: python-version: ${{ matrix.PYTHON }} - uses: actions-rs/toolchain@v1 -- Gitee From 5fb0489d50812c8d98d045ef9d3cafb02229c373 Mon Sep 17 00:00:00 2001 From: lan1120 Date: Tue, 19 Dec 2023 17:15:58 +0800 Subject: [PATCH 28/92] Make SSL_clear_options pass new options to record layer Signed-off-by: lan1120 Reviewed-by: Hugo Landau Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/23045) Signed-off-by: lanming1120 --- ssl/ssl_lib.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c index 0150589fea..cf59d2dfa5 100644 --- a/ssl/ssl_lib.c +++ b/ssl/ssl_lib.c @@ -6023,6 +6023,7 @@ uint64_t SSL_set_options(SSL *s, uint64_t op) /* Ignore return value */ sc->rlayer.rrlmethod->set_options(sc->rlayer.rrl, options); + sc->rlayer.wrlmethod->set_options(sc->rlayer.wrl, options); return sc->options; } @@ -6035,6 +6036,7 @@ uint64_t SSL_CTX_clear_options(SSL_CTX *ctx, uint64_t op) uint64_t SSL_clear_options(SSL *s, uint64_t op) { SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL(s); + OSSL_PARAM options[2], *opts = options; #ifndef OPENSSL_NO_QUIC if (IS_QUIC(s)) @@ -6044,7 +6046,17 @@ uint64_t SSL_clear_options(SSL *s, uint64_t op) if (sc == NULL) return 0; - return sc->options &= ~op; + sc->options &= ~op; + + *opts++ = OSSL_PARAM_construct_uint64(OSSL_LIBSSL_RECORD_LAYER_PARAM_OPTIONS, + &sc->options); + *opts = OSSL_PARAM_construct_end(); + + /* Ignore return value */ + sc->rlayer.rrlmethod->set_options(sc->rlayer.rrl, options); + sc->rlayer.wrlmethod->set_options(sc->rlayer.wrl, options); + + return sc->options; } STACK_OF(X509) *SSL_get0_verified_chain(const SSL *s) -- Gitee From edac6efe2abac58caa4eff8deaf418a8665bf3aa Mon Sep 17 00:00:00 2001 From: Hugo Landau Date: Thu, 9 Nov 2023 10:27:13 +0000 Subject: [PATCH 29/92] list.h: Allow separation of declarations and function definitions Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/22674) Signed-off-by: lanming1120 --- include/internal/list.h | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/include/internal/list.h b/include/internal/list.h index fdd356c407..de2a102cd4 100644 --- a/include/internal/list.h +++ b/include/internal/list.h @@ -30,12 +30,14 @@ OSSL_LIST_DBG(struct ossl_list_st_ ## name *list) \ } ossl_list_ ## name -# define DEFINE_LIST_OF(name, type) \ +# define DECLARE_LIST_OF(name, type) \ typedef struct ossl_list_st_ ## name OSSL_LIST(name); \ struct ossl_list_st_ ## name { \ type *alpha, *omega; \ size_t num_elems; \ - }; \ + } \ + +# define DEFINE_LIST_OF_IMPL(name, type) \ static ossl_unused ossl_inline void \ ossl_list_##name##_init(OSSL_LIST(name) *list) \ { \ @@ -166,4 +168,8 @@ } \ struct ossl_list_st_ ## name +# define DEFINE_LIST_OF(name, type) \ + DECLARE_LIST_OF(name, type); \ + DEFINE_LIST_OF_IMPL(name, type) + #endif -- Gitee From 7f3e5454fd628ce2c0455402fd4831cf86b2d4ce Mon Sep 17 00:00:00 2001 From: Hugo Landau Date: Thu, 9 Nov 2023 10:27:13 +0000 Subject: [PATCH 30/92] list.h: Add iterator macros Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/22674) Signed-off-by: lanming1120 --- include/internal/list.h | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/include/internal/list.h b/include/internal/list.h index de2a102cd4..902047641f 100644 --- a/include/internal/list.h +++ b/include/internal/list.h @@ -20,6 +20,34 @@ # define OSSL_LIST_DBG(x) x; # endif +# define LIST_FOREACH_FROM(p, name, init) \ + for ((p) = (init); \ + (p) != NULL; \ + (p) = ossl_list_##name##_next(p)) +# define LIST_FOREACH(p, name, l) \ + LIST_FOREACH_FROM(p, name, ossl_list_##name##_head(l)) + +# define LIST_FOREACH_REV_FROM(p, name, init) \ + for ((p) = (init); \ + (p) != NULL; \ + (p) = ossl_list_##name##_prev(p)) +# define LIST_FOREACH_REV(p, name, l) \ + LIST_FOREACH_FROM(p, name, ossl_list_##name##_tail(l)) + +# define LIST_FOREACH_DELSAFE_FROM(p, pn, name, init) \ + for ((p) = (init); \ + (p) != NULL && (((pn) = ossl_list_##name##_next(p)), 1); \ + (p) = (pn)) +#define LIST_FOREACH_DELSAFE(p, pn, name, l) \ + LIST_FOREACH_DELSAFE_FROM(p, pn, name, ossl_list_##name##_head(l)) + +# define LIST_FOREACH_REV_DELSAFE_FROM(p, pn, name, init) \ + for ((p) = (init); \ + (p) != NULL && (((pn) = ossl_list_##name##_prev(p)), 1); \ + (p) = (pn)) +# define LIST_FOREACH_REV_DELSAFE(p, pn, name, l) \ + LIST_FOREACH_REV_DELSAFE_FROM(p, pn, name, ossl_list_##name##_tail(l)) + /* Define a list structure */ # define OSSL_LIST(name) OSSL_LIST_ ## name -- Gitee From c26380b76456a7875684ffe377fc479ce7a9246c Mon Sep 17 00:00:00 2001 From: Hugo Landau Date: Thu, 9 Nov 2023 10:27:13 +0000 Subject: [PATCH 31/92] QUIC REACTOR: Add utility function for merging tick results Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/22674) Signed-off-by: lanming1120 --- include/internal/quic_reactor.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/include/internal/quic_reactor.h b/include/internal/quic_reactor.h index 57bb551e27..bffbf50d8b 100644 --- a/include/internal/quic_reactor.h +++ b/include/internal/quic_reactor.h @@ -73,6 +73,15 @@ typedef struct quic_tick_result_st { OSSL_TIME tick_deadline; } QUIC_TICK_RESULT; +static ossl_inline ossl_unused void +ossl_quic_tick_result_merge_into(QUIC_TICK_RESULT *r, + const QUIC_TICK_RESULT *src) +{ + r->net_read_desired = r->net_read_desired || src->net_read_desired; + r->net_write_desired = r->net_write_desired || src->net_write_desired; + r->tick_deadline = ossl_time_min(r->tick_deadline, src->tick_deadline); +} + typedef struct quic_reactor_st { /* * BIO poll descriptors which can be polled. poll_r is a poll descriptor -- Gitee From 4b5ddf91c7b6d611a41c49cae13bde9ab9ab413d Mon Sep 17 00:00:00 2001 From: Hugo Landau Date: Thu, 9 Nov 2023 10:27:13 +0000 Subject: [PATCH 32/92] QUIC CHANNEL: Consolidate forward object declarations in a single header Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/22674) Signed-off-by: lanming1120 --- include/internal/quic_channel.h | 6 ++--- include/internal/quic_predef.h | 41 +++++++++++++++++++++++++++++++++ ssl/quic/quic_channel_local.h | 6 ++--- test/quic_multistream_test.c | 1 + util/quicserver.c | 1 + 5 files changed, 49 insertions(+), 6 deletions(-) create mode 100644 include/internal/quic_predef.h diff --git a/include/internal/quic_channel.h b/include/internal/quic_channel.h index f46db0637e..6f883faf76 100644 --- a/include/internal/quic_channel.h +++ b/include/internal/quic_channel.h @@ -12,9 +12,9 @@ # include # include "internal/quic_types.h" -# include "internal/quic_stream_map.h" -# include "internal/quic_reactor.h" -# include "internal/quic_statm.h" +# include "internal/quic_record_tx.h" +# include "internal/quic_wire.h" +# include "internal/quic_predef.h" # include "internal/time.h" # include "internal/thread.h" diff --git a/include/internal/quic_predef.h b/include/internal/quic_predef.h new file mode 100644 index 0000000000..2512810afa --- /dev/null +++ b/include/internal/quic_predef.h @@ -0,0 +1,41 @@ +/* + * Copyright 2023 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef OSSL_QUIC_PREDEF_H +# define OSSL_QUIC_PREDEF_H + +# ifndef OPENSSL_NO_QUIC + +typedef struct quic_port_st QUIC_PORT; +typedef struct quic_channel_st QUIC_CHANNEL; +typedef struct quic_tls_st QUIC_TLS; +typedef struct quic_txpim_st QUIC_TXPIM; +typedef struct quic_cfq_st QUIC_CFQ; +typedef struct ossl_quic_tx_packetiser_st OSSL_QUIC_TX_PACKETISER; +typedef struct ossl_ackm_st OSSL_ACKM; +typedef struct quic_srt_elem_st QUIC_SRT_ELEM; +typedef struct ossl_cc_data_st OSSL_CC_DATA; +typedef struct ossl_cc_method_st OSSL_CC_METHOD; +typedef struct quic_stream_map_st QUIC_STREAM_MAP; +typedef struct quic_stream_st QUIC_STREAM; +typedef struct quic_sstream_st QUIC_SSTREAM; +typedef struct quic_rstream_st QUIC_RSTREAM; +typedef struct quic_reactor_st QUIC_REACTOR; +typedef struct ossl_statm_st OSSL_STATM; +typedef struct quic_demux_st QUIC_DEMUX; +typedef struct ossl_qrx_pkt_st OSSL_QRX_PKT; +typedef struct ossl_qtx_pkt_st OSSL_QTX_PKT; +typedef struct quic_tick_result_st QUIC_TICK_RESULT; +typedef struct quic_srtm_st QUIC_SRTM; +typedef struct quic_lcidm_st QUIC_LCIDM; +typedef struct quic_urxe_st QUIC_URXE; + +# endif + +#endif diff --git a/ssl/quic/quic_channel_local.h b/ssl/quic/quic_channel_local.h index f0ac742420..f4a02559c6 100644 --- a/ssl/quic/quic_channel_local.h +++ b/ssl/quic/quic_channel_local.h @@ -7,9 +7,9 @@ # include # include "internal/list.h" - - -typedef struct quic_srt_elem_st QUIC_SRT_ELEM; +# include "internal/quic_predef.h" +# include "internal/quic_fc.h" +# include "internal/quic_stream_map.h" struct quic_srt_elem_st { OSSL_LIST_MEMBER(stateless_reset_tokens, QUIC_SRT_ELEM); diff --git a/test/quic_multistream_test.c b/test/quic_multistream_test.c index 22a753ad67..d0560bb041 100644 --- a/test/quic_multistream_test.c +++ b/test/quic_multistream_test.c @@ -13,6 +13,7 @@ #include "internal/quic_tserver.h" #include "internal/quic_ssl.h" #include "internal/quic_error.h" +#include "internal/quic_stream_map.h" #include "testutil.h" #include "helpers/quictestlib.h" #if defined(OPENSSL_THREADS) diff --git a/util/quicserver.c b/util/quicserver.c index b5c15806a3..d752340882 100644 --- a/util/quicserver.c +++ b/util/quicserver.c @@ -19,6 +19,7 @@ #include "internal/e_os.h" #include "internal/sockets.h" #include "internal/quic_tserver.h" +#include "internal/quic_stream_map.h" #include "internal/time.h" static BIO *bio_err = NULL; -- Gitee From 27b5935d8b789d4173b5b4ac84667cddcd1df687 Mon Sep 17 00:00:00 2001 From: Hugo Landau Date: Thu, 9 Nov 2023 10:27:13 +0000 Subject: [PATCH 33/92] QUIC PORT: Add basic unwired QUIC_PORT object Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/22674) Signed-off-by: lanming1120 --- include/internal/quic_port.h | 81 +++++++++++++ ssl/quic/build.info | 2 +- ssl/quic/quic_port.c | 219 +++++++++++++++++++++++++++++++++++ ssl/quic/quic_port_local.h | 41 +++++++ 4 files changed, 342 insertions(+), 1 deletion(-) create mode 100644 include/internal/quic_port.h create mode 100644 ssl/quic/quic_port.c create mode 100644 ssl/quic/quic_port_local.h diff --git a/include/internal/quic_port.h b/include/internal/quic_port.h new file mode 100644 index 0000000000..f8d774c153 --- /dev/null +++ b/include/internal/quic_port.h @@ -0,0 +1,81 @@ +/* + * Copyright 2023 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ +#ifndef OSSL_QUIC_PORT_H +# define OSSL_QUIC_PORT_H + +# include +# include "internal/quic_types.h" +# include "internal/quic_reactor.h" +# include "internal/quic_demux.h" +# include "internal/thread_arch.h" + +# ifndef OPENSSL_NO_QUIC + +/* + * QUIC Port + * ========= + * + * A QUIC Port (QUIC_PORT) represents a single UDP network socket and contains + * zero or more subsidiary QUIC_CHANNEL instances, each of which represents a + * single QUIC connection. All QUIC_CHANNEL instances must belong to a + * QUIC_PORT. + */ +typedef struct quic_port_args_st { + /* All channels in a QUIC event domain share the same (libctx, propq). */ + OSSL_LIB_CTX *libctx; + const char *propq; + + /* + * This must be a mutex the lifetime of which will exceed that of the port + * and all channels. The instantiator of the port is responsible for + * providing a mutex as this makes it easier to handle instantiation and + * teardown of channels in situations potentially requiring locking. + * + * Note that this is a MUTEX not a RWLOCK as it needs to be an OS mutex for + * compatibility with an OS's condition variable wait API, whereas RWLOCK + * may, depending on the build configuration, be implemented using an OS's + * mutex primitive or using its RW mutex primitive. + */ + CRYPTO_MUTEX *mutex; + + OSSL_TIME (*now_cb)(void *arg); + void *now_cb_arg; +} QUIC_PORT_ARGS; + +typedef struct quic_port_st QUIC_PORT; + +QUIC_PORT *ossl_quic_port_new(const QUIC_PORT_ARGS *args); + +void ossl_quic_port_free(QUIC_PORT *port); + +/* + * Queries and Accessors + * ===================== + */ + +/* Gets/sets the underlying network read and write BIO. */ +BIO *ossl_quic_port_get_net_rbio(QUIC_PORT *port); +BIO *ossl_quic_port_get_net_wbio(QUIC_PORT *port); +int ossl_quic_port_set_net_rbio(QUIC_PORT *port, BIO *net_rbio); +int ossl_quic_port_set_net_wbio(QUIC_PORT *port, BIO *net_wbio); + +int ossl_quic_port_update_poll_descriptors(QUIC_PORT *port); + +/* Gets the reactor which can be used to tick/poll on the port. */ +QUIC_REACTOR *ossl_quic_port_get0_reactor(QUIC_PORT *port); + +/* Gets the demuxer belonging to the port. */ +QUIC_DEMUX *ossl_quic_port_get0_demux(QUIC_PORT *port); + +/* Gets the mutex used by the port. */ +CRYPTO_MUTEX *ossl_quic_port_get0_mutex(QUIC_PORT *port); + +# endif + +#endif diff --git a/ssl/quic/build.info b/ssl/quic/build.info index e8016dae91..d837fc764b 100644 --- a/ssl/quic/build.info +++ b/ssl/quic/build.info @@ -9,7 +9,7 @@ SOURCE[$LIBSSL]=quic_cfq.c quic_txpim.c quic_fifd.c quic_txp.c SOURCE[$LIBSSL]=quic_stream_map.c SOURCE[$LIBSSL]=quic_sf_list.c quic_rstream.c quic_sstream.c SOURCE[$LIBSSL]=quic_reactor.c -SOURCE[$LIBSSL]=quic_channel.c +SOURCE[$LIBSSL]=quic_channel.c quic_port.c SOURCE[$LIBSSL]=quic_tserver.c SOURCE[$LIBSSL]=quic_tls.c SOURCE[$LIBSSL]=quic_thread_assist.c diff --git a/ssl/quic/quic_port.c b/ssl/quic/quic_port.c new file mode 100644 index 0000000000..a5858d009a --- /dev/null +++ b/ssl/quic/quic_port.c @@ -0,0 +1,219 @@ +/* + * Copyright 2023 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 + */ + +#include "internal/quic_port.h" +#include "internal/quic_channel.h" +#include "quic_port_local.h" +#include "quic_channel_local.h" +#include "../ssl_local.h" + +/* + * QUIC Port Structure + * =================== + */ +static int port_init(QUIC_PORT *port); +static void port_cleanup(QUIC_PORT *port); +static OSSL_TIME get_time(void *arg); +static void port_tick(QUIC_TICK_RESULT *res, void *arg, uint32_t flags); +//static void port_default_packet_handler(QUIC_URXE *e, void *arg); + +QUIC_PORT *ossl_quic_port_new(const QUIC_PORT_ARGS *args) +{ + QUIC_PORT *port; + + if ((port = OPENSSL_zalloc(sizeof(QUIC_PORT))) == NULL) + return NULL; + + port->libctx = args->libctx; + port->propq = args->propq; + port->mutex = args->mutex; + port->now_cb = args->now_cb; + port->now_cb_arg = args->now_cb_arg; + + if (!port_init(port)) { + OPENSSL_free(port); + return NULL; + } + + return port; +} + +void ossl_quic_port_free(QUIC_PORT *port) +{ + if (port == NULL) + return; + + port_cleanup(port); + OPENSSL_free(port); +} + +static int port_init(QUIC_PORT *port) +{ + size_t rx_short_cid_len = 8; + + if ((port->demux = ossl_quic_demux_new(/*BIO=*/NULL, + /*Short CID Len=*/rx_short_cid_len, + get_time, port)) == NULL) + goto err; + + /* + * If we are a server, setup our handler for packets not corresponding to + * any known DCID on our end. This is for handling clients establishing new + * connections. + */ + // if (is_server) + //ossl_quic_demux_set_default_handler(port->demux, + // port_default_packet_handler, + // port); + + ossl_quic_reactor_init(&port->rtor, port_tick, port, ossl_time_zero()); + return 1; + +err: + port_cleanup(port); + return 0; +} + +static void port_cleanup(QUIC_PORT *port) +{ + ossl_quic_demux_free(port->demux); + port->demux = NULL; +} + +QUIC_REACTOR *ossl_quic_port_get0_reactor(QUIC_PORT *port) +{ + return &port->rtor; +} + +QUIC_DEMUX *ossl_quic_port_get0_demux(QUIC_PORT *port) +{ + return port->demux; +} + +CRYPTO_MUTEX *ossl_quic_port_get0_mutex(QUIC_PORT *port) +{ + return port->mutex; +} + +static OSSL_TIME get_time(void *arg) +{ + QUIC_PORT *port = arg; + + if (port->now_cb == NULL) + return ossl_time_now(); + + return port->now_cb(port->now_cb_arg); +} + +/* + * QUIC Port: Network BIO Configuration + * ==================================== + */ + +/* Determines whether we can support a given poll descriptor. */ +static int validate_poll_descriptor(const BIO_POLL_DESCRIPTOR *d) +{ + if (d->type == BIO_POLL_DESCRIPTOR_TYPE_SOCK_FD && d->value.fd < 0) { + ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_INVALID_ARGUMENT); + return 0; + } + + return 1; +} + +BIO *ossl_quic_port_get_net_rbio(QUIC_PORT *port) +{ + return port->net_rbio; +} + +BIO *ossl_quic_port_get_net_wbio(QUIC_PORT *port) +{ + return port->net_wbio; +} + +static int port_update_poll_desc(QUIC_PORT *port, BIO *net_bio, int for_write) +{ + BIO_POLL_DESCRIPTOR d = {0}; + + if (net_bio == NULL + || (!for_write && !BIO_get_rpoll_descriptor(net_bio, &d)) + || (for_write && !BIO_get_wpoll_descriptor(net_bio, &d))) + /* Non-pollable BIO */ + d.type = BIO_POLL_DESCRIPTOR_TYPE_NONE; + + if (!validate_poll_descriptor(&d)) + return 0; + + if (for_write) + ossl_quic_reactor_set_poll_w(&port->rtor, &d); + else + ossl_quic_reactor_set_poll_r(&port->rtor, &d); + + return 1; +} + +int ossl_quic_port_update_poll_descriptors(QUIC_PORT *port) +{ + int ok = 1; + + if (!port_update_poll_desc(port, port->net_rbio, /*for_write=*/0)) + ok = 0; + + if (!port_update_poll_desc(port, port->net_wbio, /*for_write=*/1)) + ok = 0; + + return ok; +} + +/* + * QUIC_PORT does not ref any BIO it is provided with, nor is any ref + * transferred to it. The caller (e.g., QUIC_CONNECTION) is responsible for + * ensuring the BIO lasts until the channel is freed or the BIO is switched out + * for another BIO by a subsequent successful call to this function. + */ +int ossl_quic_port_set_net_rbio(QUIC_PORT *port, BIO *net_rbio) +{ + if (port->net_rbio == net_rbio) + return 1; + + if (!port_update_poll_desc(port, net_rbio, /*for_write=*/0)) + return 0; + + ossl_quic_demux_set_bio(port->demux, net_rbio); + port->net_rbio = net_rbio; + return 1; +} + +int ossl_quic_port_set_net_wbio(QUIC_PORT *port, BIO *net_wbio) +{ + if (port->net_wbio == net_wbio) + return 1; + + if (!port_update_poll_desc(port, net_wbio, /*for_write=*/1)) + return 0; + + //ossl_qtx_set_bio(port->qtx, net_wbio); + port->net_wbio = net_wbio; + return 1; +} + +/* + * QUIC Port: Ticker-Mutator + * ========================= + */ + +/* + * The central ticker function called by the reactor. This does everything, or + * at least everything network I/O related. Best effort - not allowed to fail + * "loudly". + */ +static void port_tick(QUIC_TICK_RESULT *res, void *arg, uint32_t flags) +{ + /* TODO */ +} diff --git a/ssl/quic/quic_port_local.h b/ssl/quic/quic_port_local.h new file mode 100644 index 0000000000..0336cd7d04 --- /dev/null +++ b/ssl/quic/quic_port_local.h @@ -0,0 +1,41 @@ +#ifndef OSSL_QUIC_PORT_LOCAL_H +# define OSSL_QUIC_PORT_LOCAL_H + +# include "internal/quic_port.h" +# include "internal/quic_reactor.h" + +# ifndef OPENSSL_NO_QUIC + +/* + * QUIC Port Structure + * =================== + * + * QUIC port internals. It is intended that only the QUIC_PORT and QUIC_CHANNEL + * implementation be allowed to access this structure directly. + * + * Other components should not include this header. + */ +struct quic_port_st { + OSSL_LIB_CTX *libctx; + const char *propq; + + /* Mutex for the entire QUIC event domain. */ + CRYPTO_MUTEX *mutex; + + /* Callback used to get the current time. */ + OSSL_TIME (*now_cb)(void *arg); + void *now_cb_arg; + + /* Asynchronous I/O reactor. */ + QUIC_REACTOR rtor; + + /* Network-side read and write BIOs. */ + BIO *net_rbio, *net_wbio; + + /* RX demuxer. We register incoming DCIDs with this. */ + QUIC_DEMUX *demux; +}; + +# endif + +#endif -- Gitee From 9aba36759df643388efba9a83b86f70eece99256 Mon Sep 17 00:00:00 2001 From: Hugo Landau Date: Thu, 9 Nov 2023 10:27:13 +0000 Subject: [PATCH 34/92] QUIC CHANNEL: Keep a reference to a QUIC_PORT Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/22674) Signed-off-by: lanming1120 --- include/internal/quic_channel.h | 3 +++ ssl/quic/quic_channel.c | 6 ++++++ ssl/quic/quic_channel_local.h | 2 ++ 3 files changed, 11 insertions(+) diff --git a/include/internal/quic_channel.h b/include/internal/quic_channel.h index 6f883faf76..d4f3018cc4 100644 --- a/include/internal/quic_channel.h +++ b/include/internal/quic_channel.h @@ -106,6 +106,8 @@ # define QUIC_CHANNEL_STATE_TERMINATED 4 typedef struct quic_channel_args_st { + QUIC_PORT *port; + OSSL_LIB_CTX *libctx; const char *propq; int is_server; @@ -326,6 +328,7 @@ int ossl_quic_channel_is_active(const QUIC_CHANNEL *ch); int ossl_quic_channel_is_handshake_complete(const QUIC_CHANNEL *ch); int ossl_quic_channel_is_handshake_confirmed(const QUIC_CHANNEL *ch); +QUIC_PORT *ossl_quic_channel_get0_port(QUIC_CHANNEL *ch); QUIC_DEMUX *ossl_quic_channel_get0_demux(QUIC_CHANNEL *ch); SSL *ossl_quic_channel_get0_ssl(QUIC_CHANNEL *ch); diff --git a/ssl/quic/quic_channel.c b/ssl/quic/quic_channel.c index d3b7947fb4..22a1b158d2 100644 --- a/ssl/quic/quic_channel.c +++ b/ssl/quic/quic_channel.c @@ -548,6 +548,7 @@ QUIC_CHANNEL *ossl_quic_channel_new(const QUIC_CHANNEL_ARGS *args) if ((ch = OPENSSL_zalloc(sizeof(*ch))) == NULL) return NULL; + ch->port = args->port; ch->libctx = args->libctx; ch->propq = args->propq; ch->is_server = args->is_server; @@ -685,6 +686,11 @@ QUIC_DEMUX *ossl_quic_channel_get0_demux(QUIC_CHANNEL *ch) return ch->demux; } +QUIC_PORT *ossl_quic_channel_get0_port(QUIC_CHANNEL *ch) +{ + return ch->port; +} + CRYPTO_MUTEX *ossl_quic_channel_get_mutex(QUIC_CHANNEL *ch) { return ch->mutex; diff --git a/ssl/quic/quic_channel_local.h b/ssl/quic/quic_channel_local.h index f4a02559c6..67e648b42f 100644 --- a/ssl/quic/quic_channel_local.h +++ b/ssl/quic/quic_channel_local.h @@ -36,6 +36,8 @@ DEFINE_LIST_OF(stateless_reset_tokens, QUIC_SRT_ELEM); * Other components should not include this header. */ struct quic_channel_st { + QUIC_PORT *port; + OSSL_LIB_CTX *libctx; const char *propq; -- Gitee From 0b02aad62f3da0c5e1ab058283a5a5c94a95449d Mon Sep 17 00:00:00 2001 From: Hugo Landau Date: Thu, 9 Nov 2023 10:27:13 +0000 Subject: [PATCH 35/92] QUIC APL: Provide the QUIC_CHANNEL with a currently unused QUIC_PORT Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/22674) Signed-off-by: lanming1120 --- ssl/quic/quic_impl.c | 35 ++++++++++++++++++++++++++--------- ssl/quic/quic_local.h | 3 +++ 2 files changed, 29 insertions(+), 9 deletions(-) diff --git a/ssl/quic/quic_impl.c b/ssl/quic/quic_impl.c index 399d1d2afd..adc954cafe 100644 --- a/ssl/quic/quic_impl.c +++ b/ssl/quic/quic_impl.c @@ -15,6 +15,7 @@ #include "internal/quic_tls.h" #include "internal/quic_rx_depack.h" #include "internal/quic_error.h" +#include "internal/quic_port.h" #include "internal/time.h" typedef struct qctx_st QCTX; @@ -543,6 +544,7 @@ void ossl_quic_free(SSL *s) #endif ossl_quic_channel_free(ctx.qc->ch); + ossl_quic_port_free(ctx.qc->port); BIO_free_all(ctx.qc->net_rbio); BIO_free_all(ctx.qc->net_wbio); @@ -1487,19 +1489,34 @@ static int configure_channel(QUIC_CONNECTION *qc) QUIC_NEEDS_LOCK static int create_channel(QUIC_CONNECTION *qc) { - QUIC_CHANNEL_ARGS args = {0}; + QUIC_PORT_ARGS port_args = {0}; + QUIC_CHANNEL_ARGS ch_args = {0}; - args.libctx = qc->ssl.ctx->libctx; - args.propq = qc->ssl.ctx->propq; - args.is_server = qc->as_server; - args.tls = qc->tls; - args.mutex = qc->mutex; - args.now_cb = get_time_cb; - args.now_cb_arg = qc; + port_args.libctx = qc->ssl.ctx->libctx; + port_args.propq = qc->ssl.ctx->propq; + port_args.mutex = qc->mutex; + port_args.now_cb = get_time_cb; + port_args.now_cb_arg = qc; - qc->ch = ossl_quic_channel_new(&args); + qc->port = ossl_quic_port_new(&port_args); + if (qc->port == NULL) { + QUIC_RAISE_NON_NORMAL_ERROR(NULL, ERR_R_INTERNAL_ERROR, NULL); + return 0; + } + + ch_args.port = qc->port; + ch_args.libctx = qc->ssl.ctx->libctx; + ch_args.propq = qc->ssl.ctx->propq; + ch_args.is_server = qc->as_server; + ch_args.tls = qc->tls; + ch_args.mutex = qc->mutex; + ch_args.now_cb = get_time_cb; + ch_args.now_cb_arg = qc; + + qc->ch = ossl_quic_channel_new(&ch_args); if (qc->ch == NULL) { QUIC_RAISE_NON_NORMAL_ERROR(NULL, ERR_R_INTERNAL_ERROR, NULL); + ossl_quic_port_free(qc->port); return 0; } diff --git a/ssl/quic/quic_local.h b/ssl/quic/quic_local.h index 928ae4c6bf..ef074daf71 100644 --- a/ssl/quic/quic_local.h +++ b/ssl/quic/quic_local.h @@ -118,6 +118,9 @@ struct quic_conn_st { SSL *tls; + /* The QUIC port representing the QUIC listener and socket. */ + QUIC_PORT *port; + /* * The QUIC channel providing the core QUIC connection implementation. Note * that this is not instantiated until we actually start trying to do the -- Gitee From 9b9785bb1f37441ee48f15954a00f9809c79b209 Mon Sep 17 00:00:00 2001 From: Hugo Landau Date: Thu, 9 Nov 2023 10:27:13 +0000 Subject: [PATCH 36/92] QUIC TSERVER: Provide a TSERVER's QUIC_CHANNEL with a currently unused QUIC_PORT Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/22674) Signed-off-by: lanming1120 --- include/internal/quic_channel.h | 4 ++++ ssl/quic/quic_tserver.c | 18 +++++++++++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/include/internal/quic_channel.h b/include/internal/quic_channel.h index d4f3018cc4..f4bee6bf46 100644 --- a/include/internal/quic_channel.h +++ b/include/internal/quic_channel.h @@ -106,6 +106,10 @@ # define QUIC_CHANNEL_STATE_TERMINATED 4 typedef struct quic_channel_args_st { + /* + * The QUIC_PORT which the channel is to belong to. The lifetime of the + * QUIC_PORT must exceed that of the created channel. + */ QUIC_PORT *port; OSSL_LIB_CTX *libctx; diff --git a/ssl/quic/quic_tserver.c b/ssl/quic/quic_tserver.c index 130733821c..e5cc31ba82 100644 --- a/ssl/quic/quic_tserver.c +++ b/ssl/quic/quic_tserver.c @@ -10,6 +10,7 @@ #include "internal/quic_tserver.h" #include "internal/quic_channel.h" #include "internal/quic_statm.h" +#include "internal/quic_port.h" #include "internal/common.h" #include "internal/time.h" #include "quic_local.h" @@ -25,8 +26,10 @@ struct quic_tserver_st { SSL *ssl; /* - * The QUIC channel providing the core QUIC connection implementation. + * The QUIC port and channel providing the core QUIC connection + * implementation. */ + QUIC_PORT *port; QUIC_CHANNEL *ch; /* The mutex we give to the QUIC channel. */ @@ -75,6 +78,7 @@ QUIC_TSERVER *ossl_quic_tserver_new(const QUIC_TSERVER_ARGS *args, const char *certfile, const char *keyfile) { QUIC_TSERVER *srv = NULL; + QUIC_PORT_ARGS port_args = {0}; QUIC_CHANNEL_ARGS ch_args = {0}; QUIC_CONNECTION *qc = NULL; @@ -113,6 +117,16 @@ QUIC_TSERVER *ossl_quic_tserver_new(const QUIC_TSERVER_ARGS *args, if (srv->tls == NULL) goto err; + port_args.libctx = srv->args.libctx; + port_args.propq = srv->args.propq; + port_args.mutex = srv->mutex; + port_args.now_cb = srv->args.now_cb; + port_args.now_cb_arg = srv->args.now_cb_arg; + + if ((srv->port = ossl_quic_port_new(&port_args)) == NULL) + goto err; + + ch_args.port = srv->port; ch_args.libctx = srv->args.libctx; ch_args.propq = srv->args.propq; ch_args.tls = srv->tls; @@ -143,6 +157,7 @@ err: SSL_CTX_free(srv->ctx); SSL_free(srv->tls); ossl_quic_channel_free(srv->ch); + ossl_quic_port_free(srv->port); #if defined(OPENSSL_THREADS) ossl_crypto_mutex_free(&srv->mutex); #endif @@ -159,6 +174,7 @@ void ossl_quic_tserver_free(QUIC_TSERVER *srv) return; ossl_quic_channel_free(srv->ch); + ossl_quic_port_free(srv->port); BIO_free_all(srv->args.net_rbio); BIO_free_all(srv->args.net_wbio); OPENSSL_free(srv->ssl); -- Gitee From b6862374333c42b84863f2a6576046308d65ac40 Mon Sep 17 00:00:00 2001 From: Hugo Landau Date: Thu, 9 Nov 2023 10:27:13 +0000 Subject: [PATCH 37/92] QUIC CHANNEL: Make a QUIC_PORT mandatory Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/22674) Signed-off-by: lanming1120 --- ssl/quic/quic_channel.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ssl/quic/quic_channel.c b/ssl/quic/quic_channel.c index 22a1b158d2..8a7ddb9f39 100644 --- a/ssl/quic/quic_channel.c +++ b/ssl/quic/quic_channel.c @@ -274,6 +274,9 @@ static int ch_init(QUIC_CHANNEL *ch) uint32_t pn_space; size_t rx_short_cid_len = ch->is_server ? INIT_DCID_LEN : 0; + if (ch->port == NULL) + goto err; + ossl_list_stateless_reset_tokens_init(&ch->srt_list_seq); ch->srt_hash_tok = lh_QUIC_SRT_ELEM_new(&chan_reset_token_hash, &chan_reset_token_cmp); -- Gitee From 50b74f71738a96c592000a49f7cca8b811273d50 Mon Sep 17 00:00:00 2001 From: Hugo Landau Date: Thu, 9 Nov 2023 10:27:13 +0000 Subject: [PATCH 38/92] MARKER: End of Phase 1: Unused QUIC_PORT Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/22674) Signed-off-by: lanming1120 -- Gitee From 2fe3f784104c97509b30044116ea9c5494224661 Mon Sep 17 00:00:00 2001 From: Hugo Landau Date: Thu, 9 Nov 2023 10:27:13 +0000 Subject: [PATCH 39/92] QUIC CHANNEL, TSERVER: Move to using libctx/propq/mutex/now_cb via QUIC_PORT Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/22674) Signed-off-by: lanming1120 --- include/internal/quic_channel.h | 22 -------------------- include/internal/quic_port.h | 4 ++++ ssl/quic/quic_channel.c | 36 +++++++++++++++------------------ ssl/quic/quic_channel_local.h | 17 ---------------- ssl/quic/quic_impl.c | 5 ----- ssl/quic/quic_port_local.h | 7 ++++++- ssl/quic/quic_tserver.c | 5 ----- 7 files changed, 26 insertions(+), 70 deletions(-) diff --git a/include/internal/quic_channel.h b/include/internal/quic_channel.h index f4bee6bf46..9a434fbb7f 100644 --- a/include/internal/quic_channel.h +++ b/include/internal/quic_channel.h @@ -112,30 +112,8 @@ typedef struct quic_channel_args_st { */ QUIC_PORT *port; - OSSL_LIB_CTX *libctx; - const char *propq; int is_server; SSL *tls; - - /* - * This must be a mutex the lifetime of which will exceed that of the - * channel. The instantiator of the channel is responsible for providing a - * mutex as this makes it easier to handle instantiation and teardown of - * channels in situations potentially requiring locking. - * - * Note that this is a MUTEX not a RWLOCK as it needs to be an OS mutex for - * compatibility with an OS's condition variable wait API, whereas RWLOCK - * may, depending on the build configuration, be implemented using an OS's - * mutex primitive or using its RW mutex primitive. - */ - CRYPTO_MUTEX *mutex; - - /* - * Optional function pointer to use to retrieve the current time. If NULL, - * ossl_time_now() is used. - */ - OSSL_TIME (*now_cb)(void *arg); - void *now_cb_arg; } QUIC_CHANNEL_ARGS; typedef struct quic_channel_st QUIC_CHANNEL; diff --git a/include/internal/quic_port.h b/include/internal/quic_port.h index f8d774c153..a42d2138f5 100644 --- a/include/internal/quic_port.h +++ b/include/internal/quic_port.h @@ -44,6 +44,10 @@ typedef struct quic_port_args_st { */ CRYPTO_MUTEX *mutex; + /* + * Optional function pointer to use to retrieve the current time. If NULL, + * ossl_time_now() is used. + */ OSSL_TIME (*now_cb)(void *arg); void *now_cb_arg; } QUIC_PORT_ARGS; diff --git a/ssl/quic/quic_channel.c b/ssl/quic/quic_channel.c index 8a7ddb9f39..e266a552e3 100644 --- a/ssl/quic/quic_channel.c +++ b/ssl/quic/quic_channel.c @@ -14,6 +14,7 @@ #include "internal/quic_rx_depack.h" #include "../ssl_local.h" #include "quic_channel_local.h" +#include "quic_port_local.h" /* * NOTE: While this channel implementation currently has basic server support, @@ -285,11 +286,11 @@ static int ch_init(QUIC_CHANNEL *ch) /* For clients, generate our initial DCID. */ if (!ch->is_server - && !gen_rand_conn_id(ch->libctx, INIT_DCID_LEN, &ch->init_dcid)) + && !gen_rand_conn_id(ch->port->libctx, INIT_DCID_LEN, &ch->init_dcid)) goto err; /* We plug in a network write BIO to the QTX later when we get one. */ - qtx_args.libctx = ch->libctx; + qtx_args.libctx = ch->port->libctx; qtx_args.mdpl = QUIC_MIN_INITIAL_DGRAM_LEN; ch->rx_max_udp_payload_size = qtx_args.mdpl; @@ -414,7 +415,7 @@ static int ch_init(QUIC_CHANNEL *ch) ch_default_packet_handler, ch); - qrx_args.libctx = ch->libctx; + qrx_args.libctx = ch->port->libctx; qrx_args.demux = ch->demux; qrx_args.short_conn_id_len = rx_short_cid_len; qrx_args.max_deferred = 32; @@ -552,13 +553,8 @@ QUIC_CHANNEL *ossl_quic_channel_new(const QUIC_CHANNEL_ARGS *args) return NULL; ch->port = args->port; - ch->libctx = args->libctx; - ch->propq = args->propq; ch->is_server = args->is_server; ch->tls = args->tls; - ch->mutex = args->mutex; - ch->now_cb = args->now_cb; - ch->now_cb_arg = args->now_cb_arg; if (!ch_init(ch)) { OPENSSL_free(ch); @@ -696,7 +692,7 @@ QUIC_PORT *ossl_quic_channel_get0_port(QUIC_CHANNEL *ch) CRYPTO_MUTEX *ossl_quic_channel_get_mutex(QUIC_CHANNEL *ch) { - return ch->mutex; + return ch->port->mutex; } int ossl_quic_channel_has_pending(const QUIC_CHANNEL *ch) @@ -715,10 +711,10 @@ static OSSL_TIME get_time(void *arg) { QUIC_CHANNEL *ch = arg; - if (ch->now_cb == NULL) + if (ch->port->now_cb == NULL) return ossl_time_now(); - return ch->now_cb(ch->now_cb_arg); + return ch->port->now_cb(ch->port->now_cb_arg); } /* Used by QSM. */ @@ -2279,8 +2275,8 @@ static void ch_rx_handle_packet(QUIC_CHANNEL *ch, int channel_only) * than allow the QRX to emit a potentially malformed packet to the * upper layers. However, special casing this will do for now. */ - if (!ossl_quic_validate_retry_integrity_tag(ch->libctx, - ch->propq, + if (!ossl_quic_validate_retry_integrity_tag(ch->port->libctx, + ch->port->propq, ch->qrx_pkt->hdr, &ch->init_dcid)) /* Malformed retry packet, ignore. */ @@ -2780,8 +2776,8 @@ int ossl_quic_channel_start(QUIC_CHANNEL *ch) return 0; /* Plug in secrets for the Initial EL. */ - if (!ossl_quic_provide_initial_secret(ch->libctx, - ch->propq, + if (!ossl_quic_provide_initial_secret(ch->port->libctx, + ch->port->propq, &ch->init_dcid, ch->is_server, ch->qrx, ch->qtx)) @@ -2880,8 +2876,8 @@ static int ch_retry(QUIC_CHANNEL *ch, * Plug in new secrets for the Initial EL. This is the only time we change * the secrets for an EL after we already provisioned it. */ - if (!ossl_quic_provide_initial_secret(ch->libctx, - ch->propq, + if (!ossl_quic_provide_initial_secret(ch->port->libctx, + ch->port->propq, &ch->retry_scid, /*is_server=*/0, ch->qrx, ch->qtx)) @@ -3504,7 +3500,7 @@ static int ch_server_on_new_conn(QUIC_CHANNEL *ch, const BIO_ADDR *peer, return 0; /* Generate a SCID we will use for the connection. */ - if (!gen_rand_conn_id(ch->libctx, INIT_DCID_LEN, + if (!gen_rand_conn_id(ch->port->libctx, INIT_DCID_LEN, &ch->cur_local_cid)) return 0; @@ -3525,8 +3521,8 @@ static int ch_server_on_new_conn(QUIC_CHANNEL *ch, const BIO_ADDR *peer, return 0; /* Plug in secrets for the Initial EL. */ - if (!ossl_quic_provide_initial_secret(ch->libctx, - ch->propq, + if (!ossl_quic_provide_initial_secret(ch->port->libctx, + ch->port->propq, &ch->init_dcid, /*is_server=*/1, ch->qrx, ch->qtx)) diff --git a/ssl/quic/quic_channel_local.h b/ssl/quic/quic_channel_local.h index 67e648b42f..af35a6326b 100644 --- a/ssl/quic/quic_channel_local.h +++ b/ssl/quic/quic_channel_local.h @@ -38,23 +38,6 @@ DEFINE_LIST_OF(stateless_reset_tokens, QUIC_SRT_ELEM); struct quic_channel_st { QUIC_PORT *port; - OSSL_LIB_CTX *libctx; - const char *propq; - - /* - * Master synchronisation mutex used for thread assisted mode - * synchronisation. We don't own this; the instantiator of the channel - * passes it to us and is responsible for freeing it after channel - * destruction. - */ - CRYPTO_MUTEX *mutex; - - /* - * Callback used to get the current time. - */ - OSSL_TIME (*now_cb)(void *arg); - void *now_cb_arg; - /* * The associated TLS 1.3 connection data. Used to provide the handshake * layer; its 'network' side is plugged into the crypto stream for each EL diff --git a/ssl/quic/quic_impl.c b/ssl/quic/quic_impl.c index adc954cafe..618b4f4ac4 100644 --- a/ssl/quic/quic_impl.c +++ b/ssl/quic/quic_impl.c @@ -1505,13 +1505,8 @@ static int create_channel(QUIC_CONNECTION *qc) } ch_args.port = qc->port; - ch_args.libctx = qc->ssl.ctx->libctx; - ch_args.propq = qc->ssl.ctx->propq; ch_args.is_server = qc->as_server; ch_args.tls = qc->tls; - ch_args.mutex = qc->mutex; - ch_args.now_cb = get_time_cb; - ch_args.now_cb_arg = qc; qc->ch = ossl_quic_channel_new(&ch_args); if (qc->ch == NULL) { diff --git a/ssl/quic/quic_port_local.h b/ssl/quic/quic_port_local.h index 0336cd7d04..60216bb1b5 100644 --- a/ssl/quic/quic_port_local.h +++ b/ssl/quic/quic_port_local.h @@ -19,7 +19,12 @@ struct quic_port_st { OSSL_LIB_CTX *libctx; const char *propq; - /* Mutex for the entire QUIC event domain. */ + /* + * Master synchronisation mutex for the entire QUIC event domain. Used for + * thread assisted mode synchronisation. We don't own this; the instantiator + * of the port passes it to us and is responsible for freeing it after port + * destruction. + */ CRYPTO_MUTEX *mutex; /* Callback used to get the current time. */ diff --git a/ssl/quic/quic_tserver.c b/ssl/quic/quic_tserver.c index e5cc31ba82..b5ba3eeb85 100644 --- a/ssl/quic/quic_tserver.c +++ b/ssl/quic/quic_tserver.c @@ -127,13 +127,8 @@ QUIC_TSERVER *ossl_quic_tserver_new(const QUIC_TSERVER_ARGS *args, goto err; ch_args.port = srv->port; - ch_args.libctx = srv->args.libctx; - ch_args.propq = srv->args.propq; ch_args.tls = srv->tls; - ch_args.mutex = srv->mutex; ch_args.is_server = 1; - ch_args.now_cb = srv->args.now_cb; - ch_args.now_cb_arg = srv->args.now_cb_arg; if ((srv->ch = ossl_quic_channel_new(&ch_args)) == NULL) goto err; -- Gitee From c1a64745204b670ff0498f9e5237bbecc7fe1424 Mon Sep 17 00:00:00 2001 From: Hugo Landau Date: Thu, 9 Nov 2023 10:27:13 +0000 Subject: [PATCH 40/92] QUIC CHANNEL, PORT: Abstract time retrieval Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/22674) Signed-off-by: lanming1120 --- include/internal/quic_port.h | 3 +++ ssl/quic/quic_channel.c | 7 ++----- ssl/quic/quic_port.c | 10 +++++++--- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/include/internal/quic_port.h b/include/internal/quic_port.h index a42d2138f5..86614d607c 100644 --- a/include/internal/quic_port.h +++ b/include/internal/quic_port.h @@ -80,6 +80,9 @@ QUIC_DEMUX *ossl_quic_port_get0_demux(QUIC_PORT *port); /* Gets the mutex used by the port. */ CRYPTO_MUTEX *ossl_quic_port_get0_mutex(QUIC_PORT *port); +/* Gets the current time. */ +OSSL_TIME ossl_quic_port_get_time(QUIC_PORT *port); + # endif #endif diff --git a/ssl/quic/quic_channel.c b/ssl/quic/quic_channel.c index e266a552e3..02ef845496 100644 --- a/ssl/quic/quic_channel.c +++ b/ssl/quic/quic_channel.c @@ -692,7 +692,7 @@ QUIC_PORT *ossl_quic_channel_get0_port(QUIC_CHANNEL *ch) CRYPTO_MUTEX *ossl_quic_channel_get_mutex(QUIC_CHANNEL *ch) { - return ch->port->mutex; + return ossl_quic_port_get0_mutex(ch->port); } int ossl_quic_channel_has_pending(const QUIC_CHANNEL *ch) @@ -711,10 +711,7 @@ static OSSL_TIME get_time(void *arg) { QUIC_CHANNEL *ch = arg; - if (ch->port->now_cb == NULL) - return ossl_time_now(); - - return ch->port->now_cb(ch->port->now_cb_arg); + return ossl_quic_port_get_time(ch->port); } /* Used by QSM. */ diff --git a/ssl/quic/quic_port.c b/ssl/quic/quic_port.c index a5858d009a..0beb69835b 100644 --- a/ssl/quic/quic_port.c +++ b/ssl/quic/quic_port.c @@ -101,16 +101,20 @@ CRYPTO_MUTEX *ossl_quic_port_get0_mutex(QUIC_PORT *port) return port->mutex; } -static OSSL_TIME get_time(void *arg) +OSSL_TIME ossl_quic_port_get_time(QUIC_PORT *port) { - QUIC_PORT *port = arg; - if (port->now_cb == NULL) return ossl_time_now(); return port->now_cb(port->now_cb_arg); } +static OSSL_TIME get_time(void *port) +{ + return ossl_quic_port_get_time(port); +} + + /* * QUIC Port: Network BIO Configuration * ==================================== -- Gitee From afa0d8d2cad39f9f76fa6bc25d140ac0cfb55f7d Mon Sep 17 00:00:00 2001 From: Hugo Landau Date: Thu, 9 Nov 2023 10:27:13 +0000 Subject: [PATCH 41/92] QUIC PORT: Keep a list of all child channels Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/22674) Signed-off-by: lanming1120 --- ssl/quic/quic_channel.c | 8 ++++++++ ssl/quic/quic_channel_local.h | 9 +++++++++ ssl/quic/quic_port.c | 3 +++ ssl/quic/quic_port_local.h | 6 ++++++ 4 files changed, 26 insertions(+) diff --git a/ssl/quic/quic_channel.c b/ssl/quic/quic_channel.c index 02ef845496..1ea69584c5 100644 --- a/ssl/quic/quic_channel.c +++ b/ssl/quic/quic_channel.c @@ -46,6 +46,8 @@ */ #define DEFAULT_MAX_ACK_DELAY QUIC_DEFAULT_MAX_ACK_DELAY +DEFINE_LIST_OF_IMPL(ch, QUIC_CHANNEL); + static void ch_save_err_state(QUIC_CHANNEL *ch); static void ch_rx_pre(QUIC_CHANNEL *ch); static int ch_rx(QUIC_CHANNEL *ch, int channel_only); @@ -486,6 +488,8 @@ static int ch_init(QUIC_CHANNEL *ch) ch_update_idle(ch); ossl_quic_reactor_init(&ch->rtor, ch_tick, ch, ch_determine_next_tick_deadline(ch)); + ossl_list_ch_insert_tail(&ch->port->channel_list, ch); + ch->on_port_list = 1; return 1; err: @@ -543,6 +547,10 @@ static void ch_cleanup(QUIC_CHANNEL *ch) OPENSSL_free(srte); } lh_QUIC_SRT_ELEM_free(ch->srt_hash_tok); + if (ch->on_port_list) { + ossl_list_ch_remove(&ch->port->channel_list, ch); + ch->on_port_list = 0; + } } QUIC_CHANNEL *ossl_quic_channel_new(const QUIC_CHANNEL_ARGS *args) diff --git a/ssl/quic/quic_channel_local.h b/ssl/quic/quic_channel_local.h index af35a6326b..37cf73c67a 100644 --- a/ssl/quic/quic_channel_local.h +++ b/ssl/quic/quic_channel_local.h @@ -38,6 +38,12 @@ DEFINE_LIST_OF(stateless_reset_tokens, QUIC_SRT_ELEM); struct quic_channel_st { QUIC_PORT *port; + /* + * QUIC_PORT keeps the channels which belong to it on a list for bookkeeping + * purposes. + */ + OSSL_LIST_MEMBER(ch, struct quic_channel_st); + /* * The associated TLS 1.3 connection data. Used to provide the handshake * layer; its 'network' side is plugged into the crypto stream for each EL @@ -449,6 +455,9 @@ struct quic_channel_st { /* Are we using addressed mode? */ unsigned int addressed_mode : 1; + /* Are we on the QUIC_PORT linked list of channels? */ + unsigned int on_port_list : 1; + /* Saved error stack in case permanent error was encountered */ ERR_STATE *err_state; diff --git a/ssl/quic/quic_port.c b/ssl/quic/quic_port.c index 0beb69835b..8b727d2f12 100644 --- a/ssl/quic/quic_port.c +++ b/ssl/quic/quic_port.c @@ -23,6 +23,8 @@ static OSSL_TIME get_time(void *arg); static void port_tick(QUIC_TICK_RESULT *res, void *arg, uint32_t flags); //static void port_default_packet_handler(QUIC_URXE *e, void *arg); +DEFINE_LIST_OF_IMPL(ch, QUIC_CHANNEL); + QUIC_PORT *ossl_quic_port_new(const QUIC_PORT_ARGS *args) { QUIC_PORT *port; @@ -82,6 +84,7 @@ err: static void port_cleanup(QUIC_PORT *port) { + assert(ossl_list_ch_num(&port->channel_list) == 0); ossl_quic_demux_free(port->demux); port->demux = NULL; } diff --git a/ssl/quic/quic_port_local.h b/ssl/quic/quic_port_local.h index 60216bb1b5..7aaf4d6a42 100644 --- a/ssl/quic/quic_port_local.h +++ b/ssl/quic/quic_port_local.h @@ -3,6 +3,7 @@ # include "internal/quic_port.h" # include "internal/quic_reactor.h" +# include "internal/list.h" # ifndef OPENSSL_NO_QUIC @@ -15,6 +16,8 @@ * * Other components should not include this header. */ +DECLARE_LIST_OF(ch, QUIC_CHANNEL); + struct quic_port_st { OSSL_LIB_CTX *libctx; const char *propq; @@ -39,6 +42,9 @@ struct quic_port_st { /* RX demuxer. We register incoming DCIDs with this. */ QUIC_DEMUX *demux; + + /* List of all child channels. */ + OSSL_LIST(ch) channel_list; }; # endif -- Gitee From e29509121708774fc355a8d0300718f6d0901613 Mon Sep 17 00:00:00 2001 From: Hugo Landau Date: Thu, 9 Nov 2023 10:27:13 +0000 Subject: [PATCH 42/92] QUIC PORT: Record a SSL_CTX for use when creating handshake layer objects Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/22674) Signed-off-by: lanming1120 --- include/internal/quic_port.h | 7 +++++++ ssl/quic/quic_impl.c | 1 + ssl/quic/quic_port.c | 4 ++++ ssl/quic/quic_port_local.h | 3 +++ ssl/quic/quic_tserver.c | 1 + 5 files changed, 16 insertions(+) diff --git a/include/internal/quic_port.h b/include/internal/quic_port.h index 86614d607c..cb277c1971 100644 --- a/include/internal/quic_port.h +++ b/include/internal/quic_port.h @@ -13,6 +13,7 @@ # include "internal/quic_types.h" # include "internal/quic_reactor.h" # include "internal/quic_demux.h" +# include "internal/quic_predef.h" # include "internal/thread_arch.h" # ifndef OPENSSL_NO_QUIC @@ -50,6 +51,12 @@ typedef struct quic_port_args_st { */ OSSL_TIME (*now_cb)(void *arg); void *now_cb_arg; + + /* + * This SSL_CTX will be used when constructing the handshake layer object + * inside newly created channels. + */ + SSL_CTX *channel_ctx; } QUIC_PORT_ARGS; typedef struct quic_port_st QUIC_PORT; diff --git a/ssl/quic/quic_impl.c b/ssl/quic/quic_impl.c index 618b4f4ac4..45666190cf 100644 --- a/ssl/quic/quic_impl.c +++ b/ssl/quic/quic_impl.c @@ -1495,6 +1495,7 @@ static int create_channel(QUIC_CONNECTION *qc) port_args.libctx = qc->ssl.ctx->libctx; port_args.propq = qc->ssl.ctx->propq; port_args.mutex = qc->mutex; + port_args.channel_ctx = qc->ssl.ctx; port_args.now_cb = get_time_cb; port_args.now_cb_arg = qc; diff --git a/ssl/quic/quic_port.c b/ssl/quic/quic_port.c index 8b727d2f12..661b6c6cb8 100644 --- a/ssl/quic/quic_port.c +++ b/ssl/quic/quic_port.c @@ -37,6 +37,7 @@ QUIC_PORT *ossl_quic_port_new(const QUIC_PORT_ARGS *args) port->mutex = args->mutex; port->now_cb = args->now_cb; port->now_cb_arg = args->now_cb_arg; + port->channel_ctx = args->channel_ctx; if (!port_init(port)) { OPENSSL_free(port); @@ -59,6 +60,9 @@ static int port_init(QUIC_PORT *port) { size_t rx_short_cid_len = 8; + if (port->channel_ctx == NULL) + goto err; + if ((port->demux = ossl_quic_demux_new(/*BIO=*/NULL, /*Short CID Len=*/rx_short_cid_len, get_time, port)) == NULL) diff --git a/ssl/quic/quic_port_local.h b/ssl/quic/quic_port_local.h index 7aaf4d6a42..fc0521d02b 100644 --- a/ssl/quic/quic_port_local.h +++ b/ssl/quic/quic_port_local.h @@ -34,6 +34,9 @@ struct quic_port_st { OSSL_TIME (*now_cb)(void *arg); void *now_cb_arg; + /* Used to create handshake layer objects inside newly created channels. */ + SSL_CTX *channel_ctx; + /* Asynchronous I/O reactor. */ QUIC_REACTOR rtor; diff --git a/ssl/quic/quic_tserver.c b/ssl/quic/quic_tserver.c index b5ba3eeb85..7882cca700 100644 --- a/ssl/quic/quic_tserver.c +++ b/ssl/quic/quic_tserver.c @@ -120,6 +120,7 @@ QUIC_TSERVER *ossl_quic_tserver_new(const QUIC_TSERVER_ARGS *args, port_args.libctx = srv->args.libctx; port_args.propq = srv->args.propq; port_args.mutex = srv->mutex; + port_args.channel_ctx = srv->ctx; port_args.now_cb = srv->args.now_cb; port_args.now_cb_arg = srv->args.now_cb_arg; -- Gitee From 95476f04146ca1f00c89aca05205cc5798a0749c Mon Sep 17 00:00:00 2001 From: Hugo Landau Date: Thu, 9 Nov 2023 10:27:13 +0000 Subject: [PATCH 43/92] QUIC PORT: Make QUIC_PORT responsible for creation of all channels Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/22674) Signed-off-by: lanming1120 --- include/internal/quic_channel.h | 2 ++ include/internal/quic_port.h | 14 +++++++++ ssl/quic/quic_impl.c | 7 +---- ssl/quic/quic_port.c | 55 +++++++++++++++++++++++++++++++++ ssl/quic/quic_tserver.c | 7 +---- 5 files changed, 73 insertions(+), 12 deletions(-) diff --git a/include/internal/quic_channel.h b/include/internal/quic_channel.h index 9a434fbb7f..59caf58b30 100644 --- a/include/internal/quic_channel.h +++ b/include/internal/quic_channel.h @@ -164,6 +164,8 @@ typedef struct quic_terminate_cause_st { /* * Create a new QUIC channel using the given arguments. The argument structure * does not need to remain allocated. Returns NULL on failure. + * + * Only QUIC_PORT should use this function. */ QUIC_CHANNEL *ossl_quic_channel_new(const QUIC_CHANNEL_ARGS *args); diff --git a/include/internal/quic_port.h b/include/internal/quic_port.h index cb277c1971..08740f5afa 100644 --- a/include/internal/quic_port.h +++ b/include/internal/quic_port.h @@ -65,6 +65,20 @@ QUIC_PORT *ossl_quic_port_new(const QUIC_PORT_ARGS *args); void ossl_quic_port_free(QUIC_PORT *port); +/* + * Operations + * ========== + */ + +/* Create an outgoing channel using this port. */ +QUIC_CHANNEL *ossl_quic_port_create_outgoing(QUIC_PORT *port, SSL *tls); + +/* + * Create an incoming channel using this port. XXX for temporary TSERVER use + * only - will be removed. + */ +QUIC_CHANNEL *ossl_quic_port_create_incoming(QUIC_PORT *port, SSL *tls); + /* * Queries and Accessors * ===================== diff --git a/ssl/quic/quic_impl.c b/ssl/quic/quic_impl.c index 45666190cf..d1138f89f5 100644 --- a/ssl/quic/quic_impl.c +++ b/ssl/quic/quic_impl.c @@ -1490,7 +1490,6 @@ QUIC_NEEDS_LOCK static int create_channel(QUIC_CONNECTION *qc) { QUIC_PORT_ARGS port_args = {0}; - QUIC_CHANNEL_ARGS ch_args = {0}; port_args.libctx = qc->ssl.ctx->libctx; port_args.propq = qc->ssl.ctx->propq; @@ -1505,11 +1504,7 @@ static int create_channel(QUIC_CONNECTION *qc) return 0; } - ch_args.port = qc->port; - ch_args.is_server = qc->as_server; - ch_args.tls = qc->tls; - - qc->ch = ossl_quic_channel_new(&ch_args); + qc->ch = ossl_quic_port_create_outgoing(qc->port, qc->tls); if (qc->ch == NULL) { QUIC_RAISE_NON_NORMAL_ERROR(NULL, ERR_R_INTERNAL_ERROR, NULL); ossl_quic_port_free(qc->port); diff --git a/ssl/quic/quic_port.c b/ssl/quic/quic_port.c index 661b6c6cb8..66e0d3b0d5 100644 --- a/ssl/quic/quic_port.c +++ b/ssl/quic/quic_port.c @@ -214,6 +214,61 @@ int ossl_quic_port_set_net_wbio(QUIC_PORT *port, BIO *net_wbio) return 1; } +/* + * QUIC Port: Channel Lifecycle + * ============================ + */ + +static SSL *port_new_handshake_layer(QUIC_PORT *port) +{ + SSL *tls = NULL; + SSL_CONNECTION *tls_conn = NULL; + + tls = ossl_ssl_connection_new_int(port->channel_ctx, TLS_method()); + if (tls == NULL || (tls_conn = SSL_CONNECTION_FROM_SSL(tls)) == NULL) + return NULL; + + /* Override the user_ssl of the inner connection. */ + tls_conn->s3.flags |= TLS1_FLAGS_QUIC; + + /* Restrict options derived from the SSL_CTX. */ + tls_conn->options &= OSSL_QUIC_PERMITTED_OPTIONS_CONN; + tls_conn->pha_enabled = 0; + return tls; +} + +static QUIC_CHANNEL *port_make_channel(QUIC_PORT *port, SSL *tls, int is_server) +{ + QUIC_CHANNEL_ARGS args = {0}; + QUIC_CHANNEL *ch; + + args.port = port; + args.is_server = is_server; + args.tls = (tls != NULL ? tls : port_new_handshake_layer(port)); + if (args.tls == NULL) + return NULL; + + ch = ossl_quic_channel_new(&args); + if (ch == NULL) { + if (tls == NULL) + SSL_free(args.tls); + + return NULL; + } + + return ch; +} + +QUIC_CHANNEL *ossl_quic_port_create_outgoing(QUIC_PORT *port, SSL *tls) +{ + return port_make_channel(port, tls, /*is_server=*/0); +} + +QUIC_CHANNEL *ossl_quic_port_create_incoming(QUIC_PORT *port, SSL *tls) +{ + return port_make_channel(port, tls, /*is_server=*/1); +} + /* * QUIC Port: Ticker-Mutator * ========================= diff --git a/ssl/quic/quic_tserver.c b/ssl/quic/quic_tserver.c index 7882cca700..7246963253 100644 --- a/ssl/quic/quic_tserver.c +++ b/ssl/quic/quic_tserver.c @@ -79,7 +79,6 @@ QUIC_TSERVER *ossl_quic_tserver_new(const QUIC_TSERVER_ARGS *args, { QUIC_TSERVER *srv = NULL; QUIC_PORT_ARGS port_args = {0}; - QUIC_CHANNEL_ARGS ch_args = {0}; QUIC_CONNECTION *qc = NULL; if (args->net_rbio == NULL || args->net_wbio == NULL) @@ -127,11 +126,7 @@ QUIC_TSERVER *ossl_quic_tserver_new(const QUIC_TSERVER_ARGS *args, if ((srv->port = ossl_quic_port_new(&port_args)) == NULL) goto err; - ch_args.port = srv->port; - ch_args.tls = srv->tls; - ch_args.is_server = 1; - - if ((srv->ch = ossl_quic_channel_new(&ch_args)) == NULL) + if ((srv->ch = ossl_quic_port_create_incoming(srv->port, srv->tls)) == NULL) goto err; if (!ossl_quic_channel_set_net_rbio(srv->ch, srv->args.net_rbio) -- Gitee From d38a8236d77ec17dcc08680a8c52ce8f88d548f2 Mon Sep 17 00:00:00 2001 From: Hugo Landau Date: Thu, 9 Nov 2023 10:27:13 +0000 Subject: [PATCH 44/92] QUIC PORT, CHANNEL: Move DEMUX and default packet handling out of CHANNEL Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/22674) Signed-off-by: lanming1120 --- include/internal/quic_channel.h | 5 ++ include/internal/quic_port.h | 10 +++ ssl/quic/quic_channel.c | 137 +++++-------------------------- ssl/quic/quic_channel_local.h | 9 +-- ssl/quic/quic_port.c | 138 +++++++++++++++++++++++++++++--- ssl/quic/quic_port_local.h | 11 +++ ssl/quic/quic_tserver.c | 1 + 7 files changed, 172 insertions(+), 139 deletions(-) diff --git a/include/internal/quic_channel.h b/include/internal/quic_channel.h index 59caf58b30..b8d3edf23f 100644 --- a/include/internal/quic_channel.h +++ b/include/internal/quic_channel.h @@ -262,6 +262,11 @@ void ossl_quic_channel_on_remote_conn_close(QUIC_CHANNEL *ch, void ossl_quic_channel_on_new_conn_id(QUIC_CHANNEL *ch, OSSL_QUIC_FRAME_NEW_CONN_ID *f); +/* Temporarily exposed during QUIC_PORT transition. */ +int ossl_quic_channel_on_new_conn(QUIC_CHANNEL *ch, const BIO_ADDR *peer, + const QUIC_CONN_ID *peer_scid, + const QUIC_CONN_ID *peer_dcid); + /* * Queries and Accessors * ===================== diff --git a/include/internal/quic_port.h b/include/internal/quic_port.h index 08740f5afa..75fcaad87f 100644 --- a/include/internal/quic_port.h +++ b/include/internal/quic_port.h @@ -57,6 +57,13 @@ typedef struct quic_port_args_st { * inside newly created channels. */ SSL_CTX *channel_ctx; + + /* + * If 1, this port is to be used for multiple connections, so + * non-zero-length CIDs should be used. If 0, this port will only be used + * for a single connection, so a zero-length local CID can be used. + */ + int is_multi_conn; } QUIC_PORT_ARGS; typedef struct quic_port_st QUIC_PORT; @@ -104,6 +111,9 @@ CRYPTO_MUTEX *ossl_quic_port_get0_mutex(QUIC_PORT *port); /* Gets the current time. */ OSSL_TIME ossl_quic_port_get_time(QUIC_PORT *port); +int ossl_quic_port_get_rx_short_dcid_len(const QUIC_PORT *port); +int ossl_quic_port_get_tx_init_dcid_len(const QUIC_PORT *port); + # endif #endif diff --git a/ssl/quic/quic_channel.c b/ssl/quic/quic_channel.c index 1ea69584c5..2d7784ff04 100644 --- a/ssl/quic/quic_channel.c +++ b/ssl/quic/quic_channel.c @@ -26,7 +26,6 @@ * TODO(QUIC SERVER): Implement retry logic */ -#define INIT_DCID_LEN 8 #define INIT_CRYPTO_RECV_BUF_LEN 16384 #define INIT_CRYPTO_SEND_BUF_LEN 16384 #define INIT_APP_BUF_LEN 8192 @@ -99,10 +98,6 @@ static void ch_start_terminating(QUIC_CHANNEL *ch, const QUIC_TERMINATE_CAUSE *tcause, int force_immediate); static int ch_stateless_reset_token_handler(const unsigned char *data, size_t datalen, void *arg); -static void ch_default_packet_handler(QUIC_URXE *e, void *arg); -static int ch_server_on_new_conn(QUIC_CHANNEL *ch, const BIO_ADDR *peer, - const QUIC_CONN_ID *peer_scid, - const QUIC_CONN_ID *peer_dcid); static void ch_on_txp_ack_tx(const OSSL_QUIC_FRAME_ACK *ack, uint32_t pn_space, void *arg); static void ch_rx_handle_version_neg(QUIC_CHANNEL *ch, OSSL_QRX_PKT *pkt); @@ -220,7 +215,7 @@ static void chan_remove_reset_token(QUIC_CHANNEL *ch, uint64_t seq_num) * * TODO(QUIC FUTURE): optimise this to only be called for unparsable packets */ -static int ch_stateless_reset_token_handler(const unsigned char *data, +static int ossl_unused ch_stateless_reset_token_handler(const unsigned char *data, size_t datalen, void *arg) { QUIC_SRT_ELEM srte; @@ -275,7 +270,8 @@ static int ch_init(QUIC_CHANNEL *ch) OSSL_QRX_ARGS qrx_args = {0}; QUIC_TLS_ARGS tls_args = {0}; uint32_t pn_space; - size_t rx_short_cid_len = ch->is_server ? INIT_DCID_LEN : 0; + size_t rx_short_dcid_len = ossl_quic_port_get_rx_short_dcid_len(ch->port); + size_t tx_init_dcid_len = ossl_quic_port_get_tx_init_dcid_len(ch->port); if (ch->port == NULL) goto err; @@ -288,7 +284,7 @@ static int ch_init(QUIC_CHANNEL *ch) /* For clients, generate our initial DCID. */ if (!ch->is_server - && !gen_rand_conn_id(ch->port->libctx, INIT_DCID_LEN, &ch->init_dcid)) + && !gen_rand_conn_id(ch->port->libctx, tx_init_dcid_len, &ch->init_dcid)) goto err; /* We plug in a network write BIO to the QTX later when we get one. */ @@ -395,31 +391,16 @@ static int ch_init(QUIC_CHANNEL *ch) ossl_quic_tx_packetiser_set_ack_tx_cb(ch->txp, ch_on_txp_ack_tx, ch); - if ((ch->demux = ossl_quic_demux_new(/*BIO=*/NULL, - /*Short CID Len=*/rx_short_cid_len, - get_time, ch)) == NULL) - goto err; - /* * Setup a handler to detect stateless reset tokens. */ - ossl_quic_demux_set_stateless_reset_handler(ch->demux, - &ch_stateless_reset_token_handler, - ch); - - /* - * If we are a server, setup our handler for packets not corresponding to - * any known DCID on our end. This is for handling clients establishing new - * connections. - */ - if (ch->is_server) - ossl_quic_demux_set_default_handler(ch->demux, - ch_default_packet_handler, - ch); + //ossl_quic_demux_set_stateless_reset_handler(ch->demux, + // &ch_stateless_reset_token_handler, + // ch); qrx_args.libctx = ch->port->libctx; - qrx_args.demux = ch->demux; - qrx_args.short_conn_id_len = rx_short_cid_len; + qrx_args.demux = ch->port->demux; + qrx_args.short_conn_id_len = rx_short_dcid_len; qrx_args.max_deferred = 32; if ((ch->qrx = ossl_qrx_new(&qrx_args)) == NULL) @@ -531,7 +512,6 @@ static void ch_cleanup(QUIC_CHANNEL *ch) ossl_quic_tls_free(ch->qtls); ossl_qrx_free(ch->qrx); - ossl_quic_demux_free(ch->demux); OPENSSL_free(ch->local_transport_params); OPENSSL_free((char *)ch->terminate_cause.reason); OSSL_ERR_STATE_free(ch->err_state); @@ -690,7 +670,7 @@ int ossl_quic_channel_is_handshake_confirmed(const QUIC_CHANNEL *ch) QUIC_DEMUX *ossl_quic_channel_get0_demux(QUIC_CHANNEL *ch) { - return ch->demux; + return ch->port->demux; } QUIC_PORT *ossl_quic_channel_get0_port(QUIC_CHANNEL *ch) @@ -705,7 +685,7 @@ CRYPTO_MUTEX *ossl_quic_channel_get_mutex(QUIC_CHANNEL *ch) int ossl_quic_channel_has_pending(const QUIC_CHANNEL *ch) { - return ossl_quic_demux_has_pending(ch->demux) + return ossl_quic_demux_has_pending(ch->port->demux) || ossl_qrx_processed_read_pending(ch->qrx); } @@ -2032,7 +2012,7 @@ static void ch_rx_pre(QUIC_CHANNEL *ch) * Get DEMUX to BIO_recvmmsg from the network and queue incoming datagrams * to the appropriate QRX instance. */ - ret = ossl_quic_demux_pump(ch->demux); + ret = ossl_quic_demux_pump(ch->port->demux); if (ret == QUIC_DEMUX_PUMP_RES_STATELESS_RESET) ch_stateless_reset(ch); else if (ret == QUIC_DEMUX_PUMP_RES_PERMANENT_FAIL) @@ -2423,87 +2403,6 @@ static void ch_raise_version_neg_failure(QUIC_CHANNEL *ch) ch_start_terminating(ch, &tcause, 1); } -/* - * This is called by the demux when we get a packet not destined for any known - * DCID. - */ -static void ch_default_packet_handler(QUIC_URXE *e, void *arg) -{ - QUIC_CHANNEL *ch = arg; - PACKET pkt; - QUIC_PKT_HDR hdr; - - if (!ossl_assert(ch->is_server)) - goto undesirable; - - /* - * We only support one connection to our server currently, so if we already - * started one, ignore any new connection attempts. - */ - if (ch->state != QUIC_CHANNEL_STATE_IDLE) - goto undesirable; - - /* - * We have got a packet for an unknown DCID. This might be an attempt to - * open a new connection. - */ - if (e->data_len < QUIC_MIN_INITIAL_DGRAM_LEN) - goto undesirable; - - if (!PACKET_buf_init(&pkt, ossl_quic_urxe_data(e), e->data_len)) - goto err; - - /* - * We set short_conn_id_len to SIZE_MAX here which will cause the decode - * operation to fail if we get a 1-RTT packet. This is fine since we only - * care about Initial packets. - */ - if (!ossl_quic_wire_decode_pkt_hdr(&pkt, SIZE_MAX, 1, 0, &hdr, NULL)) - goto undesirable; - - switch (hdr.version) { - case QUIC_VERSION_1: - break; - - case QUIC_VERSION_NONE: - default: - /* Unknown version or proactive version negotiation request, bail. */ - /* TODO(QUIC SERVER): Handle version negotiation on server side */ - goto undesirable; - } - - /* - * We only care about Initial packets which might be trying to establish a - * connection. - */ - if (hdr.type != QUIC_PKT_TYPE_INITIAL) - goto undesirable; - - /* - * Assume this is a valid attempt to initiate a connection. - * - * We do not register the DCID in the initial packet we received and that - * DCID is not actually used again, thus after provisioning the correct - * Initial keys derived from it (which is done in the call below) we pass - * the received packet directly to the QRX so that it can process it as a - * one-time thing, instead of going through the usual DEMUX DCID-based - * routing. - */ - if (!ch_server_on_new_conn(ch, &e->peer, - &hdr.src_conn_id, - &hdr.dst_conn_id)) - goto err; - - ossl_qrx_inject_urxe(ch->qrx, e); - return; - -err: - ossl_quic_channel_raise_protocol_error(ch, QUIC_ERR_INTERNAL_ERROR, 0, - "internal error"); -undesirable: - ossl_quic_demux_release_urxe(ch->demux, e); -} - /* Try to generate packets and if possible, flush them to the network. */ static int ch_tx(QUIC_CHANNEL *ch) { @@ -2741,7 +2640,7 @@ int ossl_quic_channel_set_net_rbio(QUIC_CHANNEL *ch, BIO *net_rbio) if (!ch_update_poll_desc(ch, net_rbio, /*for_write=*/0)) return 0; - ossl_quic_demux_set_bio(ch->demux, net_rbio); + ossl_quic_demux_set_bio(ch->port->demux, net_rbio); ch->net_rbio = net_rbio; return 1; } @@ -3497,15 +3396,17 @@ static void ch_on_idle_timeout(QUIC_CHANNEL *ch) } /* Called when we, as a server, get a new incoming connection. */ -static int ch_server_on_new_conn(QUIC_CHANNEL *ch, const BIO_ADDR *peer, - const QUIC_CONN_ID *peer_scid, - const QUIC_CONN_ID *peer_dcid) +int ossl_quic_channel_on_new_conn(QUIC_CHANNEL *ch, const BIO_ADDR *peer, + const QUIC_CONN_ID *peer_scid, + const QUIC_CONN_ID *peer_dcid) { if (!ossl_assert(ch->state == QUIC_CHANNEL_STATE_IDLE && ch->is_server)) return 0; + /* Generate a SCID we will use for the connection. */ - if (!gen_rand_conn_id(ch->port->libctx, INIT_DCID_LEN, + if (!gen_rand_conn_id(ch->port->libctx, + ossl_quic_port_get_tx_init_dcid_len(ch->port), &ch->cur_local_cid)) return 0; diff --git a/ssl/quic/quic_channel_local.h b/ssl/quic/quic_channel_local.h index 37cf73c67a..e2aea16f68 100644 --- a/ssl/quic/quic_channel_local.h +++ b/ssl/quic/quic_channel_local.h @@ -87,14 +87,7 @@ struct quic_channel_st { const OSSL_CC_METHOD *cc_method; OSSL_ACKM *ackm; - /* - * RX demuxer. We register incoming DCIDs with this. Since we currently only - * support client operation and use one L4 port per connection, we own the - * demuxer and register a single zero-length DCID with it. - */ - QUIC_DEMUX *demux; - - /* Record layers in the TX and RX directions, plus the RX demuxer. */ + /* Record layers in the TX and RX directions. */ OSSL_QTX *qtx; OSSL_QRX *qrx; diff --git a/ssl/quic/quic_port.c b/ssl/quic/quic_port.c index 66e0d3b0d5..5c5cde8ecd 100644 --- a/ssl/quic/quic_port.c +++ b/ssl/quic/quic_port.c @@ -17,11 +17,13 @@ * QUIC Port Structure * =================== */ +#define INIT_DCID_LEN 8 + static int port_init(QUIC_PORT *port); static void port_cleanup(QUIC_PORT *port); static OSSL_TIME get_time(void *arg); static void port_tick(QUIC_TICK_RESULT *res, void *arg, uint32_t flags); -//static void port_default_packet_handler(QUIC_URXE *e, void *arg); +static void port_default_packet_handler(QUIC_URXE *e, void *arg); DEFINE_LIST_OF_IMPL(ch, QUIC_CHANNEL); @@ -32,12 +34,13 @@ QUIC_PORT *ossl_quic_port_new(const QUIC_PORT_ARGS *args) if ((port = OPENSSL_zalloc(sizeof(QUIC_PORT))) == NULL) return NULL; - port->libctx = args->libctx; - port->propq = args->propq; - port->mutex = args->mutex; - port->now_cb = args->now_cb; - port->now_cb_arg = args->now_cb_arg; - port->channel_ctx = args->channel_ctx; + port->libctx = args->libctx; + port->propq = args->propq; + port->mutex = args->mutex; + port->now_cb = args->now_cb; + port->now_cb_arg = args->now_cb_arg; + port->channel_ctx = args->channel_ctx; + port->is_multi_conn = args->is_multi_conn; if (!port_init(port)) { OPENSSL_free(port); @@ -58,13 +61,13 @@ void ossl_quic_port_free(QUIC_PORT *port) static int port_init(QUIC_PORT *port) { - size_t rx_short_cid_len = 8; + size_t rx_short_dcid_len = (port->is_multi_conn ? INIT_DCID_LEN : 0); if (port->channel_ctx == NULL) goto err; if ((port->demux = ossl_quic_demux_new(/*BIO=*/NULL, - /*Short CID Len=*/rx_short_cid_len, + /*Short CID Len=*/rx_short_dcid_len, get_time, port)) == NULL) goto err; @@ -74,11 +77,13 @@ static int port_init(QUIC_PORT *port) * connections. */ // if (is_server) - //ossl_quic_demux_set_default_handler(port->demux, - // port_default_packet_handler, - // port); + ossl_quic_demux_set_default_handler(port->demux, + port_default_packet_handler, + port); ossl_quic_reactor_init(&port->rtor, port_tick, port, ossl_time_zero()); + port->rx_short_dcid_len = (unsigned char)rx_short_dcid_len; + port->tx_init_dcid_len = INIT_DCID_LEN; return 1; err: @@ -121,6 +126,15 @@ static OSSL_TIME get_time(void *port) return ossl_quic_port_get_time(port); } +int ossl_quic_port_get_rx_short_dcid_len(const QUIC_PORT *port) +{ + return port->rx_short_dcid_len; +} + +int ossl_quic_port_get_tx_init_dcid_len(const QUIC_PORT *port) +{ + return port->tx_init_dcid_len; +} /* * QUIC Port: Network BIO Configuration @@ -266,7 +280,13 @@ QUIC_CHANNEL *ossl_quic_port_create_outgoing(QUIC_PORT *port, SSL *tls) QUIC_CHANNEL *ossl_quic_port_create_incoming(QUIC_PORT *port, SSL *tls) { - return port_make_channel(port, tls, /*is_server=*/1); + QUIC_CHANNEL *ch; + + assert(port->tserver_ch == NULL); + + ch = port_make_channel(port, tls, /*is_server=*/1); + port->tserver_ch = ch; + return ch; } /* @@ -283,3 +303,95 @@ static void port_tick(QUIC_TICK_RESULT *res, void *arg, uint32_t flags) { /* TODO */ } + +/* + * Handles an incoming connection request and potentially decides to make a + * connection from it. If a new connection is made, the new channel is written + * to *new_ch. + */ +static void port_on_new_conn(QUIC_PORT *port, const BIO_ADDR *peer, + const QUIC_CONN_ID *scid, + const QUIC_CONN_ID *dcid, + QUIC_CHANNEL **new_ch) +{ + if (port->tserver_ch != NULL) { + /* Specially assign to existing channel */ + if (!ossl_quic_channel_on_new_conn(port->tserver_ch, peer, scid, dcid)) + return; + + *new_ch = port->tserver_ch; + port->tserver_ch = NULL; + return; + } +} + +/* + * This is called by the demux when we get a packet not destined for any known + * DCID. + */ +static void port_default_packet_handler(QUIC_URXE *e, void *arg) +{ + QUIC_PORT *port = arg; + PACKET pkt; + QUIC_PKT_HDR hdr; + QUIC_CHANNEL *new_ch = NULL; + + if (port->tserver_ch == NULL) + goto undesirable; + + /* + * We have got a packet for an unknown DCID. This might be an attempt to + * open a new connection. + */ + if (e->data_len < QUIC_MIN_INITIAL_DGRAM_LEN) + goto undesirable; + + if (!PACKET_buf_init(&pkt, ossl_quic_urxe_data(e), e->data_len)) + goto undesirable; + + /* + * We set short_conn_id_len to SIZE_MAX here which will cause the decode + * operation to fail if we get a 1-RTT packet. This is fine since we only + * care about Initial packets. + */ + if (!ossl_quic_wire_decode_pkt_hdr(&pkt, SIZE_MAX, 1, 0, &hdr, NULL)) + goto undesirable; + + switch (hdr.version) { + case QUIC_VERSION_1: + break; + + case QUIC_VERSION_NONE: + default: + /* Unknown version or proactive version negotiation request, bail. */ + /* TODO(QUIC SERVER): Handle version negotiation on server side */ + goto undesirable; + } + + /* + * We only care about Initial packets which might be trying to establish a + * connection. + */ + if (hdr.type != QUIC_PKT_TYPE_INITIAL) + goto undesirable; + + /* + * Try to process this as a valid attempt to initiate a connection. + * + * We do not register the DCID in the Initial packet we received as + * that DCID is not actually used again, thus after provisioning + * the new connection and associated Initial keys, we inject the + * received packet directly to the new channel's QRX so that it can + * process it as a one-time thing, instead of going through the usual + * DEMUX DCID-based routing. + */ + port_on_new_conn(port, &e->peer, &hdr.src_conn_id, &hdr.dst_conn_id, + &new_ch); + if (new_ch != NULL) + ossl_qrx_inject_urxe(new_ch->qrx, e); + + return; + +undesirable: + ossl_quic_demux_release_urxe(port->demux, e); +} diff --git a/ssl/quic/quic_port_local.h b/ssl/quic/quic_port_local.h index fc0521d02b..ff109365aa 100644 --- a/ssl/quic/quic_port_local.h +++ b/ssl/quic/quic_port_local.h @@ -48,6 +48,17 @@ struct quic_port_st { /* List of all child channels. */ OSSL_LIST(ch) channel_list; + + /* Special TSERVER channel. To be removed in the future. */ + QUIC_CHANNEL *tserver_ch; + + /* DCID length used for incoming short header packets. */ + unsigned char rx_short_dcid_len; + /* For clients, CID length used for outgoing Initial packets. */ + unsigned char tx_init_dcid_len; + + /* Is this port created to support multiple connections? */ + unsigned int is_multi_conn : 1; }; # endif diff --git a/ssl/quic/quic_tserver.c b/ssl/quic/quic_tserver.c index 7246963253..bc6668ef90 100644 --- a/ssl/quic/quic_tserver.c +++ b/ssl/quic/quic_tserver.c @@ -122,6 +122,7 @@ QUIC_TSERVER *ossl_quic_tserver_new(const QUIC_TSERVER_ARGS *args, port_args.channel_ctx = srv->ctx; port_args.now_cb = srv->args.now_cb; port_args.now_cb_arg = srv->args.now_cb_arg; + port_args.is_multi_conn = 1; if ((srv->port = ossl_quic_port_new(&port_args)) == NULL) goto err; -- Gitee From cf26d2cfc617de4643db2efecf5f20cce672a961 Mon Sep 17 00:00:00 2001 From: Hugo Landau Date: Thu, 9 Nov 2023 10:27:13 +0000 Subject: [PATCH 45/92] QUIC PORT, CHANNEL: Move ticking code into QUIC_PORT Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/22674) Signed-off-by: lanming1120 --- include/internal/quic_channel.h | 16 ++-- include/internal/quic_port.h | 18 ++++ ssl/quic/quic_channel.c | 161 +++++--------------------------- ssl/quic/quic_channel_local.h | 9 -- ssl/quic/quic_impl.c | 4 +- ssl/quic/quic_port.c | 74 ++++++++++++++- ssl/quic/quic_port_local.h | 3 + test/quic_multistream_test.c | 6 +- 8 files changed, 128 insertions(+), 163 deletions(-) diff --git a/include/internal/quic_channel.h b/include/internal/quic_channel.h index b8d3edf23f..d0046d07d1 100644 --- a/include/internal/quic_channel.h +++ b/include/internal/quic_channel.h @@ -267,6 +267,13 @@ int ossl_quic_channel_on_new_conn(QUIC_CHANNEL *ch, const BIO_ADDR *peer, const QUIC_CONN_ID *peer_scid, const QUIC_CONN_ID *peer_dcid); +/* For use by QUIC_PORT. You should not need to call this directly. */ +void ossl_quic_channel_subtick(QUIC_CHANNEL *ch, QUIC_TICK_RESULT *r, + uint32_t flags); + +/* For use by QUIC_PORT only. */ +void ossl_quic_channel_raise_net_error(QUIC_CHANNEL *ch); + /* * Queries and Accessors * ===================== @@ -294,12 +301,6 @@ BIO *ossl_quic_channel_get_net_wbio(QUIC_CHANNEL *ch); int ossl_quic_channel_set_net_rbio(QUIC_CHANNEL *ch, BIO *net_rbio); int ossl_quic_channel_set_net_wbio(QUIC_CHANNEL *ch, BIO *net_wbio); -/* - * Re-poll the network BIOs already set to determine if their support - * for polling has changed. - */ -int ossl_quic_channel_update_poll_descriptors(QUIC_CHANNEL *ch); - /* * Returns an existing stream by stream ID. Returns NULL if the stream does not * exist. @@ -396,9 +397,6 @@ int ossl_quic_channel_has_pending(const QUIC_CHANNEL *ch); /* Force transmission of an ACK-eliciting packet. */ int ossl_quic_channel_ping(QUIC_CHANNEL *ch); -/* For testing use. While enabled, ticking is not performed. */ -void ossl_quic_channel_set_inhibit_tick(QUIC_CHANNEL *ch, int inhibit); - /* * These queries exist for diagnostic purposes only. They may roll over. * Do not rely on them for non-testing purposes. diff --git a/include/internal/quic_port.h b/include/internal/quic_port.h index 75fcaad87f..3d9e5b0211 100644 --- a/include/internal/quic_port.h +++ b/include/internal/quic_port.h @@ -97,6 +97,10 @@ BIO *ossl_quic_port_get_net_wbio(QUIC_PORT *port); int ossl_quic_port_set_net_rbio(QUIC_PORT *port, BIO *net_rbio); int ossl_quic_port_set_net_wbio(QUIC_PORT *port, BIO *net_wbio); +/* + * Re-poll the network BIOs already set to determine if their support + * for polling has changed. + */ int ossl_quic_port_update_poll_descriptors(QUIC_PORT *port); /* Gets the reactor which can be used to tick/poll on the port. */ @@ -114,6 +118,20 @@ OSSL_TIME ossl_quic_port_get_time(QUIC_PORT *port); int ossl_quic_port_get_rx_short_dcid_len(const QUIC_PORT *port); int ossl_quic_port_get_tx_init_dcid_len(const QUIC_PORT *port); +/* For testing use. While enabled, ticking is not performed. */ +void ossl_quic_port_set_inhibit_tick(QUIC_PORT *port, int inhibit); + +/* + * Events + * ====== + */ + +/* + * Called if a permanent network error occurs. Terminates all channels + * immediately. + */ +void ossl_quic_port_raise_net_error(QUIC_PORT *port); + # endif #endif diff --git a/ssl/quic/quic_channel.c b/ssl/quic/quic_channel.c index 2d7784ff04..24f428a3f8 100644 --- a/ssl/quic/quic_channel.c +++ b/ssl/quic/quic_channel.c @@ -48,10 +48,8 @@ DEFINE_LIST_OF_IMPL(ch, QUIC_CHANNEL); static void ch_save_err_state(QUIC_CHANNEL *ch); -static void ch_rx_pre(QUIC_CHANNEL *ch); static int ch_rx(QUIC_CHANNEL *ch, int channel_only); static int ch_tx(QUIC_CHANNEL *ch); -static void ch_tick(QUIC_TICK_RESULT *res, void *arg, uint32_t flags); static int ch_tick_tls(QUIC_CHANNEL *ch, int channel_only); static void ch_rx_handle_packet(QUIC_CHANNEL *ch, int channel_only); static OSSL_TIME ch_determine_next_tick_deadline(QUIC_CHANNEL *ch); @@ -92,7 +90,6 @@ static void ch_on_idle_timeout(QUIC_CHANNEL *ch); static void ch_update_idle(QUIC_CHANNEL *ch); static void ch_update_ping_deadline(QUIC_CHANNEL *ch); static void ch_stateless_reset(QUIC_CHANNEL *ch); -static void ch_raise_net_error(QUIC_CHANNEL *ch); static void ch_on_terminating_timeout(QUIC_CHANNEL *ch); static void ch_start_terminating(QUIC_CHANNEL *ch, const QUIC_TERMINATE_CAUSE *tcause, @@ -467,8 +464,6 @@ static int ch_init(QUIC_CHANNEL *ch) goto err; ch_update_idle(ch); - ossl_quic_reactor_init(&ch->rtor, ch_tick, ch, - ch_determine_next_tick_deadline(ch)); ossl_list_ch_insert_tail(&ch->port->channel_list, ch); ch->on_port_list = 1; return 1; @@ -601,7 +596,7 @@ int ossl_quic_channel_set_peer_addr(QUIC_CHANNEL *ch, const BIO_ADDR *peer_addr) QUIC_REACTOR *ossl_quic_channel_get_reactor(QUIC_CHANNEL *ch) { - return &ch->rtor; + return ossl_quic_port_get0_reactor(ch->port); } QUIC_STREAM_MAP *ossl_quic_channel_get_qsm(QUIC_CHANNEL *ch) @@ -1839,20 +1834,20 @@ err: * at least everything network I/O related. Best effort - not allowed to fail * "loudly". */ -static void ch_tick(QUIC_TICK_RESULT *res, void *arg, uint32_t flags) +void ossl_quic_channel_subtick(QUIC_CHANNEL *ch, QUIC_TICK_RESULT *res, + uint32_t flags) { OSSL_TIME now, deadline; - QUIC_CHANNEL *ch = arg; int channel_only = (flags & QUIC_REACTOR_TICK_FLAG_CHANNEL_ONLY) != 0; /* * When we tick the QUIC connection, we do everything we need to do - * periodically. In order, we: + * periodically. Network I/O handling will already have been performed + * as necessary by the QUIC port. Thus, in order, we: * - * - handle any incoming data from the network; - * - handle any timer events which are due to fire (ACKM, etc.) - * - write any data to the network due to be sent, to the extent - * possible; + * - handle any packets the DEMUX has queued up for us; + * - handle any timer events which are due to fire (ACKM, etc.); + * - generate any packets which need to be sent; * - determine the time at which we should next be ticked. */ @@ -1880,13 +1875,10 @@ static void ch_tick(QUIC_TICK_RESULT *res, void *arg, uint32_t flags) } } - if (!ch->inhibit_tick) { + if (!ch->port->inhibit_tick) { /* Handle RXKU timeouts. */ ch_rxku_tick(ch); - /* Handle any incoming data from network. */ - ch_rx_pre(ch); - do { /* Process queued incoming packets. */ ch->did_tls_tick = 0; @@ -1923,7 +1915,7 @@ static void ch_tick(QUIC_TICK_RESULT *res, void *arg, uint32_t flags) * Idle timeout differs from normal protocol violation because we do * not send a CONN_CLOSE frame; go straight to TERMINATED. */ - if (!ch->inhibit_tick) + if (!ch->port->inhibit_tick) ch_on_idle_timeout(ch); res->net_read_desired = 0; @@ -1932,7 +1924,7 @@ static void ch_tick(QUIC_TICK_RESULT *res, void *arg, uint32_t flags) return; } - if (!ch->inhibit_tick) { + if (!ch->port->inhibit_tick) { deadline = ossl_ackm_get_loss_detection_deadline(ch->ackm); if (!ossl_time_is_zero(deadline) && ossl_time_compare(now, deadline) >= 0) @@ -1954,7 +1946,7 @@ static void ch_tick(QUIC_TICK_RESULT *res, void *arg, uint32_t flags) ch_update_ping_deadline(ch); } - /* Write any data to the network due to be sent. */ + /* Queue any data to be sent for transmission. */ ch_tx(ch); /* Do stream GC. */ @@ -1965,14 +1957,13 @@ static void ch_tick(QUIC_TICK_RESULT *res, void *arg, uint32_t flags) res->tick_deadline = ch_determine_next_tick_deadline(ch); /* - * Always process network input unless we are now terminated. - * Although we had not terminated at the beginning of this tick, network - * errors in ch_rx_pre() or ch_tx() may have caused us to transition to the - * Terminated state. + * Always process network input unless we are now terminated. Although we + * had not terminated at the beginning of this tick, network errors in + * ch_tx() may have caused us to transition to the Terminated state. */ res->net_read_desired = !ossl_quic_channel_is_terminated(ch); - /* We want to write to the network if we have any in our queue. */ + /* We want to write to the network if we have any data in our TX queue. */ res->net_write_desired = (!ossl_quic_channel_is_terminated(ch) && ossl_qtx_get_queue_len_datagrams(ch->qtx) > 0); @@ -2000,32 +1991,6 @@ static int ch_tick_tls(QUIC_CHANNEL *ch, int channel_only) return 1; } -/* Process incoming datagrams, if any. */ -static void ch_rx_pre(QUIC_CHANNEL *ch) -{ - int ret; - - if (!ch->is_server && !ch->have_sent_any_pkt) - return; - - /* - * Get DEMUX to BIO_recvmmsg from the network and queue incoming datagrams - * to the appropriate QRX instance. - */ - ret = ossl_quic_demux_pump(ch->port->demux); - if (ret == QUIC_DEMUX_PUMP_RES_STATELESS_RESET) - ch_stateless_reset(ch); - else if (ret == QUIC_DEMUX_PUMP_RES_PERMANENT_FAIL) - /* - * We don't care about transient failure, but permanent failure means we - * should tear down the connection as though a protocol violation - * occurred. Skip straight to the Terminating state as there is no point - * trying to send CONNECTION_CLOSE frames if the network BIO is not - * operating correctly. - */ - ch_raise_net_error(ch); -} - /* Check incoming forged packet limit and terminate connection if needed. */ static void ch_rx_check_forged_pkt_limit(QUIC_CHANNEL *ch) { @@ -2508,7 +2473,7 @@ static int ch_tx(QUIC_CHANNEL *ch) case QTX_FLUSH_NET_RES_PERMANENT_FAIL: default: /* Permanent underlying network BIO, start terminating. */ - ch_raise_net_error(ch); + ossl_quic_port_raise_net_error(ch->port); break; } @@ -2571,91 +2536,14 @@ static OSSL_TIME ch_determine_next_tick_deadline(QUIC_CHANNEL *ch) * ======================================= */ -/* Determines whether we can support a given poll descriptor. */ -static int validate_poll_descriptor(const BIO_POLL_DESCRIPTOR *d) -{ - if (d->type == BIO_POLL_DESCRIPTOR_TYPE_SOCK_FD && d->value.fd < 0) { - ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_INVALID_ARGUMENT); - return 0; - } - - return 1; -} - -BIO *ossl_quic_channel_get_net_rbio(QUIC_CHANNEL *ch) -{ - return ch->net_rbio; -} - -BIO *ossl_quic_channel_get_net_wbio(QUIC_CHANNEL *ch) -{ - return ch->net_wbio; -} - -static int ch_update_poll_desc(QUIC_CHANNEL *ch, BIO *net_bio, int for_write) -{ - BIO_POLL_DESCRIPTOR d = {0}; - - if (net_bio == NULL - || (!for_write && !BIO_get_rpoll_descriptor(net_bio, &d)) - || (for_write && !BIO_get_wpoll_descriptor(net_bio, &d))) - /* Non-pollable BIO */ - d.type = BIO_POLL_DESCRIPTOR_TYPE_NONE; - - if (!validate_poll_descriptor(&d)) - return 0; - - if (for_write) - ossl_quic_reactor_set_poll_w(&ch->rtor, &d); - else - ossl_quic_reactor_set_poll_r(&ch->rtor, &d); - - return 1; -} - -int ossl_quic_channel_update_poll_descriptors(QUIC_CHANNEL *ch) -{ - int ok = 1; - - if (!ch_update_poll_desc(ch, ch->net_rbio, /*for_write=*/0)) - ok = 0; - - if (!ch_update_poll_desc(ch, ch->net_wbio, /*for_write=*/1)) - ok = 0; - - return ok; -} - -/* - * QUIC_CHANNEL does not ref any BIO it is provided with, nor is any ref - * transferred to it. The caller (i.e., QUIC_CONNECTION) is responsible for - * ensuring the BIO lasts until the channel is freed or the BIO is switched out - * for another BIO by a subsequent successful call to this function. - */ int ossl_quic_channel_set_net_rbio(QUIC_CHANNEL *ch, BIO *net_rbio) { - if (ch->net_rbio == net_rbio) - return 1; - - if (!ch_update_poll_desc(ch, net_rbio, /*for_write=*/0)) - return 0; - - ossl_quic_demux_set_bio(ch->port->demux, net_rbio); - ch->net_rbio = net_rbio; - return 1; + return ossl_quic_port_set_net_rbio(ch->port, net_rbio); } int ossl_quic_channel_set_net_wbio(QUIC_CHANNEL *ch, BIO *net_wbio) { - if (ch->net_wbio == net_wbio) - return 1; - - if (!ch_update_poll_desc(ch, net_wbio, /*for_write=*/1)) - return 0; - - ossl_qtx_set_bio(ch->qtx, net_wbio); - ch->net_wbio = net_wbio; - return 1; + return ossl_quic_port_set_net_wbio(ch->port, net_wbio); } /* @@ -2695,7 +2583,7 @@ int ossl_quic_channel_start(QUIC_CHANNEL *ch) if (!ch_tick_tls(ch, /*channel_only=*/0)) return 0; - ossl_quic_reactor_tick(&ch->rtor, 0); /* best effort */ + ossl_quic_reactor_tick(ossl_quic_port_get0_reactor(ch->port), 0); /* best effort */ return 1; } @@ -3199,7 +3087,7 @@ static void ch_save_err_state(QUIC_CHANNEL *ch) OSSL_ERR_STATE_save(ch->err_state); } -static void ch_stateless_reset(QUIC_CHANNEL *ch) +static void ossl_unused ch_stateless_reset(QUIC_CHANNEL *ch) { QUIC_TERMINATE_CAUSE tcause = {0}; @@ -3207,7 +3095,7 @@ static void ch_stateless_reset(QUIC_CHANNEL *ch) ch_start_terminating(ch, &tcause, 1); } -static void ch_raise_net_error(QUIC_CHANNEL *ch) +void ossl_quic_channel_raise_net_error(QUIC_CHANNEL *ch) { QUIC_TERMINATE_CAUSE tcause = {0}; @@ -3698,11 +3586,6 @@ int ossl_quic_channel_ping(QUIC_CHANNEL *ch) return 1; } -void ossl_quic_channel_set_inhibit_tick(QUIC_CHANNEL *ch, int inhibit) -{ - ch->inhibit_tick = (inhibit != 0); -} - uint16_t ossl_quic_channel_get_diag_num_rx_ack(QUIC_CHANNEL *ch) { return ch->diag_num_rx_ack; diff --git a/ssl/quic/quic_channel_local.h b/ssl/quic/quic_channel_local.h index e2aea16f68..dafe03fe8a 100644 --- a/ssl/quic/quic_channel_local.h +++ b/ssl/quic/quic_channel_local.h @@ -58,15 +58,9 @@ struct quic_channel_st { */ unsigned char *local_transport_params; - /* Asynchronous I/O reactor. */ - QUIC_REACTOR rtor; - /* Our current L4 peer address, if any. */ BIO_ADDR cur_peer_addr; - /* Network-side read and write BIOs. */ - BIO *net_rbio, *net_wbio; - /* * Subcomponents of the connection. All of these components are instantiated * and owned by us. @@ -442,9 +436,6 @@ struct quic_channel_st { */ unsigned int protocol_error : 1; - /* Inhibit tick for testing purposes? */ - unsigned int inhibit_tick : 1; - /* Are we using addressed mode? */ unsigned int addressed_mode : 1; diff --git a/ssl/quic/quic_impl.c b/ssl/quic/quic_impl.c index d1138f89f5..751d5b846a 100644 --- a/ssl/quic/quic_impl.c +++ b/ssl/quic/quic_impl.c @@ -64,7 +64,7 @@ static int block_until_pred(QUIC_CONNECTION *qc, * Any attempt to block auto-disables tick inhibition as otherwise we will * hang around forever. */ - ossl_quic_channel_set_inhibit_tick(qc->ch, 0); + ossl_quic_port_set_inhibit_tick(qc->port, 0); rtor = ossl_quic_channel_get_reactor(qc->ch); return ossl_quic_reactor_block_until_pred(rtor, pred, pred_arg, flags, @@ -856,7 +856,7 @@ static int qc_can_support_blocking_cached(QUIC_CONNECTION *qc) static void qc_update_can_support_blocking(QUIC_CONNECTION *qc) { - ossl_quic_channel_update_poll_descriptors(qc->ch); /* best effort */ + ossl_quic_port_update_poll_descriptors(qc->port); /* best effort */ } static void qc_update_blocking_mode(QUIC_CONNECTION *qc) diff --git a/ssl/quic/quic_port.c b/ssl/quic/quic_port.c index 5c5cde8ecd..ee4b2900e0 100644 --- a/ssl/quic/quic_port.c +++ b/ssl/quic/quic_port.c @@ -24,6 +24,7 @@ static void port_cleanup(QUIC_PORT *port); static OSSL_TIME get_time(void *arg); static void port_tick(QUIC_TICK_RESULT *res, void *arg, uint32_t flags); static void port_default_packet_handler(QUIC_URXE *e, void *arg); +static void port_rx_pre(QUIC_PORT *port); DEFINE_LIST_OF_IMPL(ch, QUIC_CHANNEL); @@ -217,13 +218,17 @@ int ossl_quic_port_set_net_rbio(QUIC_PORT *port, BIO *net_rbio) int ossl_quic_port_set_net_wbio(QUIC_PORT *port, BIO *net_wbio) { + QUIC_CHANNEL *ch; + if (port->net_wbio == net_wbio) return 1; if (!port_update_poll_desc(port, net_wbio, /*for_write=*/1)) return 0; - //ossl_qtx_set_bio(port->qtx, net_wbio); + LIST_FOREACH(ch, ch, &port->channel_list) + ossl_qtx_set_bio(ch->qtx, net_wbio); + port->net_wbio = net_wbio; return 1; } @@ -301,7 +306,49 @@ QUIC_CHANNEL *ossl_quic_port_create_incoming(QUIC_PORT *port, SSL *tls) */ static void port_tick(QUIC_TICK_RESULT *res, void *arg, uint32_t flags) { - /* TODO */ + QUIC_PORT *port = arg; + QUIC_CHANNEL *ch; + + res->net_read_desired = 0; + res->net_write_desired = 0; + res->tick_deadline = ossl_time_infinite(); + + if (!port->inhibit_tick) { + /* Handle any incoming data from network. */ + port_rx_pre(port); + + /* Iterate through all channels and service them. */ + LIST_FOREACH(ch, ch, &port->channel_list) { + QUIC_TICK_RESULT subr = {0}; + + ossl_quic_channel_subtick(ch, &subr, flags); + ossl_quic_tick_result_merge_into(res, &subr); + } + } +} + +/* Process incoming datagrams, if any. */ +static void port_rx_pre(QUIC_PORT *port) +{ + int ret; + + // TODO !have_sent_any_pkt + + /* + * Get DEMUX to BIO_recvmmsg from the network and queue incoming datagrams + * to the appropriate QRX instances. + */ + ret = ossl_quic_demux_pump(port->demux); + // TODO: handle ret, stateless reset + + if (ret == QUIC_DEMUX_PUMP_RES_PERMANENT_FAIL) + /* + * We don't care about transient failure, but permanent failure means we + * should tear down the port. All connections skip straight to the + * Terminated state as there is no point trying to send CONNECTION_CLOSE + * frames if the network BIO is not operating correctly. + */ + ossl_quic_port_raise_net_error(port); } /* @@ -336,9 +383,17 @@ static void port_default_packet_handler(QUIC_URXE *e, void *arg) QUIC_PKT_HDR hdr; QUIC_CHANNEL *new_ch = NULL; + // TODO review this if (port->tserver_ch == NULL) goto undesirable; + // TODO allow_incoming + //if (!ossl_assert(ch->is_server)) + // goto undesirable; + + //TODO if (ch->state != QUIC_CHANNEL_STATE_IDLE) + // goto undesirable; + /* * We have got a packet for an unknown DCID. This might be an attempt to * open a new connection. @@ -395,3 +450,18 @@ static void port_default_packet_handler(QUIC_URXE *e, void *arg) undesirable: ossl_quic_demux_release_urxe(port->demux, e); } + +void ossl_quic_port_set_inhibit_tick(QUIC_PORT *port, int inhibit) +{ + port->inhibit_tick = (inhibit != 0); +} + +void ossl_quic_port_raise_net_error(QUIC_PORT *port) +{ + QUIC_CHANNEL *ch; + + // TODO fsm + + LIST_FOREACH(ch, ch, &port->channel_list) + ossl_quic_channel_raise_net_error(ch); +} diff --git a/ssl/quic/quic_port_local.h b/ssl/quic/quic_port_local.h index ff109365aa..ad6638eb2f 100644 --- a/ssl/quic/quic_port_local.h +++ b/ssl/quic/quic_port_local.h @@ -59,6 +59,9 @@ struct quic_port_st { /* Is this port created to support multiple connections? */ unsigned int is_multi_conn : 1; + + /* Inhibit tick for testing purposes? */ + unsigned int inhibit_tick : 1; }; # endif diff --git a/test/quic_multistream_test.c b/test/quic_multistream_test.c index d0560bb041..604c2f986b 100644 --- a/test/quic_multistream_test.c +++ b/test/quic_multistream_test.c @@ -14,6 +14,7 @@ #include "internal/quic_ssl.h" #include "internal/quic_error.h" #include "internal/quic_stream_map.h" +#include "internal/quic_port.h" #include "testutil.h" #include "helpers/quictestlib.h" #if defined(OPENSSL_THREADS) @@ -1594,7 +1595,7 @@ static int run_script_worker(struct helper *h, const struct script_op *script, QUIC_CHANNEL *ch = ossl_quic_conn_get_channel(h->c_conn); SSL_SHUTDOWN_EX_ARGS args = {0}; - ossl_quic_channel_set_inhibit_tick(ch, 0); + ossl_quic_port_set_inhibit_tick(ossl_quic_channel_get0_port(ch), 0); if (!TEST_ptr(c_tgt)) goto out; @@ -1918,7 +1919,8 @@ static int run_script_worker(struct helper *h, const struct script_op *script, { QUIC_CHANNEL *ch = ossl_quic_conn_get_channel(h->c_conn); - ossl_quic_channel_set_inhibit_tick(ch, op->arg1); + ossl_quic_port_set_inhibit_tick(ossl_quic_channel_get0_port(ch), + op->arg1); } break; -- Gitee From 5e523cf9c537aa8a7ea98d15fdae5f3140011c8d Mon Sep 17 00:00:00 2001 From: Hugo Landau Date: Thu, 9 Nov 2023 10:27:13 +0000 Subject: [PATCH 46/92] MARKER: End of Phase 2: Transfer of Responsibilities Done, Legacy Compat Retained Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/22674) Signed-off-by: lanming1120 -- Gitee From 3e6d4a78d690cfb501f21f132b580780a68e5a43 Mon Sep 17 00:00:00 2001 From: Hugo Landau Date: Thu, 9 Nov 2023 10:27:13 +0000 Subject: [PATCH 47/92] QUIC CHANNEL: Remove legacy calls for functionality moved to QUIC_PORT Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/22674) Signed-off-by: lanming1120 --- include/internal/quic_channel.h | 7 ------- include/internal/quic_port.h | 9 +++++++++ ssl/quic/quic_channel.c | 15 --------------- ssl/quic/quic_impl.c | 8 ++++---- ssl/quic/quic_tserver.c | 4 ++-- 5 files changed, 15 insertions(+), 28 deletions(-) diff --git a/include/internal/quic_channel.h b/include/internal/quic_channel.h index d0046d07d1..c696f93324 100644 --- a/include/internal/quic_channel.h +++ b/include/internal/quic_channel.h @@ -160,7 +160,6 @@ typedef struct quic_terminate_cause_st { unsigned int remote : 1; } QUIC_TERMINATE_CAUSE; - /* * Create a new QUIC channel using the given arguments. The argument structure * does not need to remain allocated. Returns NULL on failure. @@ -295,12 +294,6 @@ OSSL_STATM *ossl_quic_channel_get_statm(QUIC_CHANNEL *ch); int ossl_quic_channel_get_peer_addr(QUIC_CHANNEL *ch, BIO_ADDR *peer_addr); int ossl_quic_channel_set_peer_addr(QUIC_CHANNEL *ch, const BIO_ADDR *peer_addr); -/* Gets/sets the underlying network read and write BIOs. */ -BIO *ossl_quic_channel_get_net_rbio(QUIC_CHANNEL *ch); -BIO *ossl_quic_channel_get_net_wbio(QUIC_CHANNEL *ch); -int ossl_quic_channel_set_net_rbio(QUIC_CHANNEL *ch, BIO *net_rbio); -int ossl_quic_channel_set_net_wbio(QUIC_CHANNEL *ch, BIO *net_wbio); - /* * Returns an existing stream by stream ID. Returns NULL if the stream does not * exist. diff --git a/include/internal/quic_port.h b/include/internal/quic_port.h index 3d9e5b0211..0b24338c2f 100644 --- a/include/internal/quic_port.h +++ b/include/internal/quic_port.h @@ -26,6 +26,15 @@ * zero or more subsidiary QUIC_CHANNEL instances, each of which represents a * single QUIC connection. All QUIC_CHANNEL instances must belong to a * QUIC_PORT. + * + * A QUIC port is responsible for managing a set of channels which all use the + * same UDP socket, and (in future) for automatically creating new channels when + * incoming connections are received. + * + * In order to retain compatibility with QUIC_TSERVER, it also supports a point + * of legacy compatibility where a caller can create an incoming (server role) + * channel and that channel will be automatically be bound to the next incoming + * connection. In the future this will go away once QUIC_TSERVER is removed. */ typedef struct quic_port_args_st { /* All channels in a QUIC event domain share the same (libctx, propq). */ diff --git a/ssl/quic/quic_channel.c b/ssl/quic/quic_channel.c index 24f428a3f8..aa5ea0971e 100644 --- a/ssl/quic/quic_channel.c +++ b/ssl/quic/quic_channel.c @@ -2531,21 +2531,6 @@ static OSSL_TIME ch_determine_next_tick_deadline(QUIC_CHANNEL *ch) return deadline; } -/* - * QUIC Channel: Network BIO Configuration - * ======================================= - */ - -int ossl_quic_channel_set_net_rbio(QUIC_CHANNEL *ch, BIO *net_rbio) -{ - return ossl_quic_port_set_net_rbio(ch->port, net_rbio); -} - -int ossl_quic_channel_set_net_wbio(QUIC_CHANNEL *ch, BIO *net_wbio) -{ - return ossl_quic_port_set_net_wbio(ch->port, net_wbio); -} - /* * QUIC Channel: Lifecycle Events * ============================== diff --git a/ssl/quic/quic_impl.c b/ssl/quic/quic_impl.c index 751d5b846a..7279c37c17 100644 --- a/ssl/quic/quic_impl.c +++ b/ssl/quic/quic_impl.c @@ -874,7 +874,7 @@ void ossl_quic_conn_set0_net_rbio(SSL *s, BIO *net_rbio) if (ctx.qc->net_rbio == net_rbio) return; - if (!ossl_quic_channel_set_net_rbio(ctx.qc->ch, net_rbio)) + if (!ossl_quic_port_set_net_rbio(ctx.qc->port, net_rbio)) return; BIO_free_all(ctx.qc->net_rbio); @@ -901,7 +901,7 @@ void ossl_quic_conn_set0_net_wbio(SSL *s, BIO *net_wbio) if (ctx.qc->net_wbio == net_wbio) return; - if (!ossl_quic_channel_set_net_wbio(ctx.qc->ch, net_wbio)) + if (!ossl_quic_port_set_net_wbio(ctx.qc->port, net_wbio)) return; BIO_free_all(ctx.qc->net_wbio); @@ -1478,8 +1478,8 @@ static int configure_channel(QUIC_CONNECTION *qc) { assert(qc->ch != NULL); - if (!ossl_quic_channel_set_net_rbio(qc->ch, qc->net_rbio) - || !ossl_quic_channel_set_net_wbio(qc->ch, qc->net_wbio) + if (!ossl_quic_port_set_net_rbio(qc->port, qc->net_rbio) + || !ossl_quic_port_set_net_wbio(qc->port, qc->net_wbio) || !ossl_quic_channel_set_peer_addr(qc->ch, &qc->init_peer_addr)) return 0; diff --git a/ssl/quic/quic_tserver.c b/ssl/quic/quic_tserver.c index bc6668ef90..885f4d5242 100644 --- a/ssl/quic/quic_tserver.c +++ b/ssl/quic/quic_tserver.c @@ -130,8 +130,8 @@ QUIC_TSERVER *ossl_quic_tserver_new(const QUIC_TSERVER_ARGS *args, if ((srv->ch = ossl_quic_port_create_incoming(srv->port, srv->tls)) == NULL) goto err; - if (!ossl_quic_channel_set_net_rbio(srv->ch, srv->args.net_rbio) - || !ossl_quic_channel_set_net_wbio(srv->ch, srv->args.net_wbio)) + if (!ossl_quic_port_set_net_rbio(srv->port, srv->args.net_rbio) + || !ossl_quic_port_set_net_wbio(srv->port, srv->args.net_wbio)) goto err; qc = OPENSSL_zalloc(sizeof(*qc)); -- Gitee From 3d4eb7a3de83404ce7a79027d53bb1be73cd2c6d Mon Sep 17 00:00:00 2001 From: Hugo Landau Date: Thu, 9 Nov 2023 10:27:13 +0000 Subject: [PATCH 48/92] QUIC PORT: Add SRTM wiring Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/22674) Signed-off-by: lanming1120 --- ssl/quic/quic_port.c | 9 +++++++++ ssl/quic/quic_port_local.h | 6 ++++++ 2 files changed, 15 insertions(+) diff --git a/ssl/quic/quic_port.c b/ssl/quic/quic_port.c index ee4b2900e0..b128477c0a 100644 --- a/ssl/quic/quic_port.c +++ b/ssl/quic/quic_port.c @@ -9,6 +9,8 @@ #include "internal/quic_port.h" #include "internal/quic_channel.h" +#include "internal/quic_lcidm.h" +#include "internal/quic_srtm.h" #include "quic_port_local.h" #include "quic_channel_local.h" #include "../ssl_local.h" @@ -82,6 +84,9 @@ static int port_init(QUIC_PORT *port) port_default_packet_handler, port); + if ((port->srtm = ossl_quic_srtm_new(port->libctx, port->propq)) == NULL) + goto err; + ossl_quic_reactor_init(&port->rtor, port_tick, port, ossl_time_zero()); port->rx_short_dcid_len = (unsigned char)rx_short_dcid_len; port->tx_init_dcid_len = INIT_DCID_LEN; @@ -95,8 +100,12 @@ err: static void port_cleanup(QUIC_PORT *port) { assert(ossl_list_ch_num(&port->channel_list) == 0); + ossl_quic_demux_free(port->demux); port->demux = NULL; + + ossl_quic_srtm_free(port->srtm); + port->srtm = NULL; } QUIC_REACTOR *ossl_quic_port_get0_reactor(QUIC_PORT *port) diff --git a/ssl/quic/quic_port_local.h b/ssl/quic/quic_port_local.h index ad6638eb2f..bfcc5896e1 100644 --- a/ssl/quic/quic_port_local.h +++ b/ssl/quic/quic_port_local.h @@ -52,6 +52,12 @@ struct quic_port_st { /* Special TSERVER channel. To be removed in the future. */ QUIC_CHANNEL *tserver_ch; + /* LCIDM used for incoming packet routing by DCID. */ + QUIC_LCIDM *lcidm; + + /* SRTM used for incoming packet routing by SRT. */ + QUIC_SRTM *srtm; + /* DCID length used for incoming short header packets. */ unsigned char rx_short_dcid_len; /* For clients, CID length used for outgoing Initial packets. */ -- Gitee From df5826b4eedd2d3d0ebdef388ee033a4e8161fc9 Mon Sep 17 00:00:00 2001 From: Hugo Landau Date: Thu, 9 Nov 2023 10:27:13 +0000 Subject: [PATCH 49/92] QUIC PORT: Partially move stateless reset handling to port Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/22674) Signed-off-by: lanming1120 --- include/internal/quic_channel.h | 3 ++ ssl/quic/quic_channel.c | 50 +++------------------------------ ssl/quic/quic_port.c | 49 ++++++++++++++++++++++++++++++++ 3 files changed, 56 insertions(+), 46 deletions(-) diff --git a/include/internal/quic_channel.h b/include/internal/quic_channel.h index c696f93324..bdc48e5084 100644 --- a/include/internal/quic_channel.h +++ b/include/internal/quic_channel.h @@ -273,6 +273,9 @@ void ossl_quic_channel_subtick(QUIC_CHANNEL *ch, QUIC_TICK_RESULT *r, /* For use by QUIC_PORT only. */ void ossl_quic_channel_raise_net_error(QUIC_CHANNEL *ch); +/* For use by QUIC_PORT only. */ +void ossl_quic_channel_on_stateless_reset(QUIC_CHANNEL *ch); + /* * Queries and Accessors * ===================== diff --git a/ssl/quic/quic_channel.c b/ssl/quic/quic_channel.c index aa5ea0971e..c363b3bdde 100644 --- a/ssl/quic/quic_channel.c +++ b/ssl/quic/quic_channel.c @@ -89,12 +89,10 @@ static int ch_discard_el(QUIC_CHANNEL *ch, static void ch_on_idle_timeout(QUIC_CHANNEL *ch); static void ch_update_idle(QUIC_CHANNEL *ch); static void ch_update_ping_deadline(QUIC_CHANNEL *ch); -static void ch_stateless_reset(QUIC_CHANNEL *ch); static void ch_on_terminating_timeout(QUIC_CHANNEL *ch); static void ch_start_terminating(QUIC_CHANNEL *ch, const QUIC_TERMINATE_CAUSE *tcause, int force_immediate); -static int ch_stateless_reset_token_handler(const unsigned char *data, size_t datalen, void *arg); static void ch_on_txp_ack_tx(const OSSL_QUIC_FRAME_ACK *ack, uint32_t pn_space, void *arg); static void ch_rx_handle_version_neg(QUIC_CHANNEL *ch, OSSL_QRX_PKT *pkt); @@ -207,47 +205,6 @@ static void chan_remove_reset_token(QUIC_CHANNEL *ch, uint64_t seq_num) } } -/* - * This is called by the demux whenever a new datagram arrives - * - * TODO(QUIC FUTURE): optimise this to only be called for unparsable packets - */ -static int ossl_unused ch_stateless_reset_token_handler(const unsigned char *data, - size_t datalen, void *arg) -{ - QUIC_SRT_ELEM srte; - QUIC_CHANNEL *ch = (QUIC_CHANNEL *)arg; - - /* - * Perform some fast and cheap checks for a packet not being a stateless - * reset token. RFC 9000 s. 10.3 specifies this layout for stateless - * reset packets: - * - * Stateless Reset { - * Fixed Bits (2) = 1, - * Unpredictable Bits (38..), - * Stateless Reset Token (128), - * } - * - * It also specifies: - * However, endpoints MUST treat any packet ending in a valid - * stateless reset token as a Stateless Reset, as other QUIC - * versions might allow the use of a long header. - * - * We can rapidly check for the minimum length and that the first pair - * of bits in the first byte are 01 or 11. - * - * The function returns 1 if it is a stateless reset packet, 0 if it isn't - * and -1 if an error was encountered. - */ - if (datalen < QUIC_STATELESS_RESET_TOKEN_LEN + 5 || (0100 & *data) != 0100) - return 0; - memset(&srte, 0, sizeof(srte)); - if (!reset_token_obfuscate(&srte, data + datalen - sizeof(srte.token))) - return -1; - return lh_QUIC_SRT_ELEM_retrieve(ch->srt_hash_tok, &srte) != NULL; -} - /* * QUIC Channel Initialization and Teardown * ======================================== @@ -3072,12 +3029,13 @@ static void ch_save_err_state(QUIC_CHANNEL *ch) OSSL_ERR_STATE_save(ch->err_state); } -static void ossl_unused ch_stateless_reset(QUIC_CHANNEL *ch) +void ossl_quic_channel_on_stateless_reset(QUIC_CHANNEL *ch) { QUIC_TERMINATE_CAUSE tcause = {0}; - tcause.error_code = QUIC_ERR_NO_ERROR; - ch_start_terminating(ch, &tcause, 1); + tcause.error_code = QUIC_ERR_NO_ERROR; + tcause.remote = 1; + ch_start_terminating(ch, &tcause, 0); } void ossl_quic_channel_raise_net_error(QUIC_CHANNEL *ch) diff --git a/ssl/quic/quic_port.c b/ssl/quic/quic_port.c index b128477c0a..bf351e923c 100644 --- a/ssl/quic/quic_port.c +++ b/ssl/quic/quic_port.c @@ -381,6 +381,52 @@ static void port_on_new_conn(QUIC_PORT *port, const BIO_ADDR *peer, } } +static int port_try_handle_stateless_reset(QUIC_PORT *port, const QUIC_URXE *e) +{ + size_t i; + const unsigned char *data = ossl_quic_urxe_data(e); + void *opaque = NULL; + + /* + * Perform some fast and cheap checks for a packet not being a stateless + * reset token. RFC 9000 s. 10.3 specifies this layout for stateless + * reset packets: + * + * Stateless Reset { + * Fixed Bits (2) = 1, + * Unpredictable Bits (38..), + * Stateless Reset Token (128), + * } + * + * It also specifies: + * However, endpoints MUST treat any packet ending in a valid + * stateless reset token as a Stateless Reset, as other QUIC + * versions might allow the use of a long header. + * + * We can rapidly check for the minimum length and that the first pair + * of bits in the first byte are 01 or 11. + * + * The function returns 1 if it is a stateless reset packet, 0 if it isn't + * and -1 if an error was encountered. + */ + if (e->data_len < QUIC_STATELESS_RESET_TOKEN_LEN + 5 + || (0100 & *data) != 0100) + return 0; + + for (i = 0;; ++i) { + if (!ossl_quic_srtm_lookup(port->srtm, + (QUIC_STATELESS_RESET_TOKEN *)(data + e->data_len + - sizeof(QUIC_STATELESS_RESET_TOKEN)), + i, &opaque, NULL)) + break; + + assert(opaque != NULL); + ossl_quic_channel_on_stateless_reset((QUIC_CHANNEL *)opaque); + } + + return i > 0; +} + /* * This is called by the demux when we get a packet not destined for any known * DCID. @@ -392,6 +438,9 @@ static void port_default_packet_handler(QUIC_URXE *e, void *arg) QUIC_PKT_HDR hdr; QUIC_CHANNEL *new_ch = NULL; + if (port_try_handle_stateless_reset(port, e)) + goto undesirable; + // TODO review this if (port->tserver_ch == NULL) goto undesirable; -- Gitee From 56f7ec2ecddc634e80e24c7b2338b2ee7767fe56 Mon Sep 17 00:00:00 2001 From: Hugo Landau Date: Thu, 9 Nov 2023 10:27:13 +0000 Subject: [PATCH 50/92] QUIC PORT: Create a LCIDM Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/22674) Signed-off-by: lanming1120 --- ssl/quic/quic_port.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ssl/quic/quic_port.c b/ssl/quic/quic_port.c index bf351e923c..64cee54c8b 100644 --- a/ssl/quic/quic_port.c +++ b/ssl/quic/quic_port.c @@ -87,6 +87,9 @@ static int port_init(QUIC_PORT *port) if ((port->srtm = ossl_quic_srtm_new(port->libctx, port->propq)) == NULL) goto err; + if ((port->lcidm = ossl_quic_lcidm_new(port->libctx, rx_short_dcid_len)) == NULL) + goto err; + ossl_quic_reactor_init(&port->rtor, port_tick, port, ossl_time_zero()); port->rx_short_dcid_len = (unsigned char)rx_short_dcid_len; port->tx_init_dcid_len = INIT_DCID_LEN; @@ -106,6 +109,9 @@ static void port_cleanup(QUIC_PORT *port) ossl_quic_srtm_free(port->srtm); port->srtm = NULL; + + ossl_quic_lcidm_free(port->lcidm); + port->lcidm = NULL; } QUIC_REACTOR *ossl_quic_port_get0_reactor(QUIC_PORT *port) -- Gitee From bdfbf90e7f73395ca878eab683cacd0140b4f5d7 Mon Sep 17 00:00:00 2001 From: Hugo Landau Date: Thu, 9 Nov 2023 10:27:13 +0000 Subject: [PATCH 51/92] QUIC DEMUX: Allow parsed DCID to be learnt in default packet handler Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/22674) Signed-off-by: lanming1120 --- include/internal/quic_demux.h | 6 +++++- ssl/quic/quic_demux.c | 21 ++++++++++++--------- ssl/quic/quic_port.c | 6 ++++-- ssl/quic/quic_record_rx.c | 4 ++-- 4 files changed, 23 insertions(+), 14 deletions(-) diff --git a/include/internal/quic_demux.h b/include/internal/quic_demux.h index 444249e728..354d408c85 100644 --- a/include/internal/quic_demux.h +++ b/include/internal/quic_demux.h @@ -169,6 +169,9 @@ typedef struct quic_demux_st QUIC_DEMUX; * to mutate this buffer; once the demuxer calls this callback, it will never * read the buffer again. * + * If a DCID was identified for the datagram, dcid is non-NULL; otherwise + * it is NULL. + * * The callee must arrange for ossl_quic_demux_release_urxe or * ossl_quic_demux_reinject_urxe to be called on the URXE at some point in the * future (this need not be before the callback returns). @@ -176,7 +179,8 @@ typedef struct quic_demux_st QUIC_DEMUX; * At the time the callback is made, the URXE will not be in any queue, * therefore the callee can use the prev and next fields as it wishes. */ -typedef void (ossl_quic_demux_cb_fn)(QUIC_URXE *e, void *arg); +typedef void (ossl_quic_demux_cb_fn)(QUIC_URXE *e, void *arg, + const QUIC_CONN_ID *dcid); /* * Called when a datagram is received. diff --git a/ssl/quic/quic_demux.c b/ssl/quic/quic_demux.c index 88135fe5b9..376c088811 100644 --- a/ssl/quic/quic_demux.c +++ b/ssl/quic/quic_demux.c @@ -481,18 +481,19 @@ static int demux_identify_conn_id(QUIC_DEMUX *demux, } /* Identify the connection structure corresponding to a given URXE. */ -static QUIC_DEMUX_CONN *demux_identify_conn(QUIC_DEMUX *demux, QUIC_URXE *e) +static QUIC_DEMUX_CONN *demux_identify_conn(QUIC_DEMUX *demux, QUIC_URXE *e, + QUIC_CONN_ID *dst_conn_id, + int *dst_conn_id_ok) { - QUIC_CONN_ID dst_conn_id; - - if (!demux_identify_conn_id(demux, e, &dst_conn_id)) + if (!demux_identify_conn_id(demux, e, dst_conn_id)) /* * Datagram is so badly malformed we can't get the DCID from the first * packet in it, so just give up. */ return NULL; - return demux_get_by_conn_id(demux, &dst_conn_id); + *dst_conn_id_ok = 1; + return demux_get_by_conn_id(demux, dst_conn_id); } /* @@ -502,7 +503,8 @@ static QUIC_DEMUX_CONN *demux_identify_conn(QUIC_DEMUX *demux, QUIC_URXE *e) static int demux_process_pending_urxe(QUIC_DEMUX *demux, QUIC_URXE *e) { QUIC_DEMUX_CONN *conn; - int r; + QUIC_CONN_ID dst_conn_id; + int r, dst_conn_id_ok = 0; /* The next URXE we process should be at the head of the pending list. */ if (!ossl_assert(e == ossl_list_urxe_head(&demux->urx_pending))) @@ -533,7 +535,7 @@ static int demux_process_pending_urxe(QUIC_DEMUX *demux, QUIC_URXE *e) return 0; } - conn = demux_identify_conn(demux, e); + conn = demux_identify_conn(demux, e, &dst_conn_id, &dst_conn_id_ok); if (conn == NULL) { /* * We could not identify a connection. If we have a default packet @@ -544,7 +546,8 @@ static int demux_process_pending_urxe(QUIC_DEMUX *demux, QUIC_URXE *e) if (demux->default_cb != NULL) { /* Pass to default handler. */ e->demux_state = URXE_DEMUX_STATE_ISSUED; - demux->default_cb(e, demux->default_cb_arg); + demux->default_cb(e, demux->default_cb_arg, + dst_conn_id_ok ? &dst_conn_id : NULL); } else { /* Discard. */ ossl_list_urxe_insert_tail(&demux->urx_free, e); @@ -559,7 +562,7 @@ static int demux_process_pending_urxe(QUIC_DEMUX *demux, QUIC_URXE *e) */ ossl_list_urxe_remove(&demux->urx_pending, e); e->demux_state = URXE_DEMUX_STATE_ISSUED; - conn->cb(e, conn->cb_arg); + conn->cb(e, conn->cb_arg, dst_conn_id_ok ? &dst_conn_id : NULL); return 1; } diff --git a/ssl/quic/quic_port.c b/ssl/quic/quic_port.c index 64cee54c8b..91240c3c0e 100644 --- a/ssl/quic/quic_port.c +++ b/ssl/quic/quic_port.c @@ -25,7 +25,8 @@ static int port_init(QUIC_PORT *port); static void port_cleanup(QUIC_PORT *port); static OSSL_TIME get_time(void *arg); static void port_tick(QUIC_TICK_RESULT *res, void *arg, uint32_t flags); -static void port_default_packet_handler(QUIC_URXE *e, void *arg); +static void port_default_packet_handler(QUIC_URXE *e, void *arg, + const QUIC_CONN_ID *dcid); static void port_rx_pre(QUIC_PORT *port); DEFINE_LIST_OF_IMPL(ch, QUIC_CHANNEL); @@ -437,7 +438,8 @@ static int port_try_handle_stateless_reset(QUIC_PORT *port, const QUIC_URXE *e) * This is called by the demux when we get a packet not destined for any known * DCID. */ -static void port_default_packet_handler(QUIC_URXE *e, void *arg) +static void port_default_packet_handler(QUIC_URXE *e, void *arg, + const QUIC_CONN_ID *dcid) { QUIC_PORT *port = arg; PACKET pkt; diff --git a/ssl/quic/quic_record_rx.c b/ssl/quic/quic_record_rx.c index 4d0493baff..d35264e7a2 100644 --- a/ssl/quic/quic_record_rx.c +++ b/ssl/quic/quic_record_rx.c @@ -167,7 +167,7 @@ struct ossl_qrx_st { SSL *msg_callback_ssl; }; -static void qrx_on_rx(QUIC_URXE *urxe, void *arg); +static void qrx_on_rx(QUIC_URXE *urxe, void *arg, const QUIC_CONN_ID *dcid); OSSL_QRX *ossl_qrx_new(const OSSL_QRX_ARGS *args) { @@ -252,7 +252,7 @@ void ossl_qrx_inject_urxe(OSSL_QRX *qrx, QUIC_URXE *urxe) qrx->msg_callback_arg); } -static void qrx_on_rx(QUIC_URXE *urxe, void *arg) +static void qrx_on_rx(QUIC_URXE *urxe, void *arg, const QUIC_CONN_ID *dcid) { OSSL_QRX *qrx = arg; -- Gitee From 8b5ca18b6ca44e23e5910ccfb42fa14d862fb154 Mon Sep 17 00:00:00 2001 From: Hugo Landau Date: Thu, 9 Nov 2023 10:27:14 +0000 Subject: [PATCH 52/92] QUIC PORT: Enable injection of incoming URXEs into a channel via default handler rather than DEMUX routing Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/22674) Signed-off-by: lanming1120 --- include/internal/quic_channel.h | 2 ++ ssl/quic/quic_channel.c | 5 +++++ ssl/quic/quic_port.c | 10 +++++++++- 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/include/internal/quic_channel.h b/include/internal/quic_channel.h index bdc48e5084..91366ec7cc 100644 --- a/include/internal/quic_channel.h +++ b/include/internal/quic_channel.h @@ -276,6 +276,8 @@ void ossl_quic_channel_raise_net_error(QUIC_CHANNEL *ch); /* For use by QUIC_PORT only. */ void ossl_quic_channel_on_stateless_reset(QUIC_CHANNEL *ch); +void ossl_quic_channel_inject(QUIC_CHANNEL *ch, QUIC_URXE *e); + /* * Queries and Accessors * ===================== diff --git a/ssl/quic/quic_channel.c b/ssl/quic/quic_channel.c index c363b3bdde..ebbc3e86a1 100644 --- a/ssl/quic/quic_channel.c +++ b/ssl/quic/quic_channel.c @@ -3029,6 +3029,11 @@ static void ch_save_err_state(QUIC_CHANNEL *ch) OSSL_ERR_STATE_save(ch->err_state); } +void ossl_quic_channel_inject(QUIC_CHANNEL *ch, QUIC_URXE *e) +{ + ossl_qrx_inject_urxe(ch->qrx, e); +} + void ossl_quic_channel_on_stateless_reset(QUIC_CHANNEL *ch) { QUIC_TERMINATE_CAUSE tcause = {0}; diff --git a/ssl/quic/quic_port.c b/ssl/quic/quic_port.c index 91240c3c0e..b99089e42b 100644 --- a/ssl/quic/quic_port.c +++ b/ssl/quic/quic_port.c @@ -444,7 +444,15 @@ static void port_default_packet_handler(QUIC_URXE *e, void *arg, QUIC_PORT *port = arg; PACKET pkt; QUIC_PKT_HDR hdr; - QUIC_CHANNEL *new_ch = NULL; + QUIC_CHANNEL *ch = NULL, *new_ch = NULL; + + if (dcid != NULL + && ossl_quic_lcidm_lookup(port->lcidm, dcid, NULL, + (void **)&ch)) { + assert(ch != NULL); + ossl_quic_channel_inject(ch, e); + return; + } if (port_try_handle_stateless_reset(port, e)) goto undesirable; -- Gitee From a057e8e08a721b07fa6394e9f07b4a5ac40b9044 Mon Sep 17 00:00:00 2001 From: Hugo Landau Date: Thu, 9 Nov 2023 10:27:14 +0000 Subject: [PATCH 53/92] QUIC CHANNEL: Keep a reference to our LCIDM Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/22674) Signed-off-by: lanming1120 --- include/internal/quic_channel.h | 2 ++ ssl/quic/quic_channel.c | 5 ++++- ssl/quic/quic_channel_local.h | 3 +++ ssl/quic/quic_port.c | 1 + 4 files changed, 10 insertions(+), 1 deletion(-) diff --git a/include/internal/quic_channel.h b/include/internal/quic_channel.h index 91366ec7cc..61683aff6c 100644 --- a/include/internal/quic_channel.h +++ b/include/internal/quic_channel.h @@ -111,6 +111,8 @@ typedef struct quic_channel_args_st { * QUIC_PORT must exceed that of the created channel. */ QUIC_PORT *port; + /* LCIDM to register LCIDs with. */ + QUIC_LCIDM *lcidm; int is_server; SSL *tls; diff --git a/ssl/quic/quic_channel.c b/ssl/quic/quic_channel.c index ebbc3e86a1..c366a087b7 100644 --- a/ssl/quic/quic_channel.c +++ b/ssl/quic/quic_channel.c @@ -12,6 +12,7 @@ #include "internal/quic_channel.h" #include "internal/quic_error.h" #include "internal/quic_rx_depack.h" +#include "internal/quic_lcidm.h" #include "../ssl_local.h" #include "quic_channel_local.h" #include "quic_port_local.h" @@ -227,7 +228,7 @@ static int ch_init(QUIC_CHANNEL *ch) size_t rx_short_dcid_len = ossl_quic_port_get_rx_short_dcid_len(ch->port); size_t tx_init_dcid_len = ossl_quic_port_get_tx_init_dcid_len(ch->port); - if (ch->port == NULL) + if (ch->port == NULL || ch->lcidm == NULL) goto err; ossl_list_stateless_reset_tokens_init(&ch->srt_list_seq); @@ -441,6 +442,7 @@ static void ch_cleanup(QUIC_CHANNEL *ch) ++pn_space) ossl_ackm_on_pkt_space_discarded(ch->ackm, pn_space); + ossl_quic_lcidm_cull(ch->lcidm, ch); ossl_quic_tx_packetiser_free(ch->txp); ossl_quic_txpim_free(ch->txpim); ossl_quic_cfq_free(ch->cfq); @@ -495,6 +497,7 @@ QUIC_CHANNEL *ossl_quic_channel_new(const QUIC_CHANNEL_ARGS *args) ch->port = args->port; ch->is_server = args->is_server; ch->tls = args->tls; + ch->lcidm = args->lcidm; if (!ch_init(ch)) { OPENSSL_free(ch); diff --git a/ssl/quic/quic_channel_local.h b/ssl/quic/quic_channel_local.h index dafe03fe8a..8c8688aac2 100644 --- a/ssl/quic/quic_channel_local.h +++ b/ssl/quic/quic_channel_local.h @@ -52,6 +52,9 @@ struct quic_channel_st { QUIC_TLS *qtls; SSL *tls; + /* Port LCIDM we use to register LCIDs. */ + QUIC_LCIDM *lcidm; + /* * The transport parameter block we will send or have sent. * Freed after sending or when connection is freed. diff --git a/ssl/quic/quic_port.c b/ssl/quic/quic_port.c index b99089e42b..9be20c3f7b 100644 --- a/ssl/quic/quic_port.c +++ b/ssl/quic/quic_port.c @@ -280,6 +280,7 @@ static QUIC_CHANNEL *port_make_channel(QUIC_PORT *port, SSL *tls, int is_server) args.port = port; args.is_server = is_server; args.tls = (tls != NULL ? tls : port_new_handshake_layer(port)); + args.lcidm = port->lcidm; if (args.tls == NULL) return NULL; -- Gitee From 8bea2ec50c0304d1bd716bfb31fde5c2cc1c694f Mon Sep 17 00:00:00 2001 From: Hugo Landau Date: Thu, 9 Nov 2023 10:27:14 +0000 Subject: [PATCH 54/92] QUIC CHANNEL: Phase out use of QRX-DEMUX routing in favour of PORT-LCIDM routing Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/22674) Signed-off-by: lanming1120 --- ssl/quic/quic_channel.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/ssl/quic/quic_channel.c b/ssl/quic/quic_channel.c index c366a087b7..0d7493daa5 100644 --- a/ssl/quic/quic_channel.c +++ b/ssl/quic/quic_channel.c @@ -371,7 +371,9 @@ static int ch_init(QUIC_CHANNEL *ch) ch)) goto err; - if (!ch->is_server && !ossl_qrx_add_dst_conn_id(ch->qrx, &txp_args.cur_scid)) + /* TODO plug this correctly */ + if (!ch->is_server + && !ossl_quic_lcidm_generate_initial(ch->lcidm, ch, &txp_args.cur_scid)) goto err; for (pn_space = QUIC_PN_SPACE_INITIAL; pn_space < QUIC_PN_SPACE_NUM; ++pn_space) { @@ -3242,11 +3244,8 @@ int ossl_quic_channel_on_new_conn(QUIC_CHANNEL *ch, const BIO_ADDR *peer, if (!ossl_assert(ch->state == QUIC_CHANNEL_STATE_IDLE && ch->is_server)) return 0; - - /* Generate a SCID we will use for the connection. */ - if (!gen_rand_conn_id(ch->port->libctx, - ossl_quic_port_get_tx_init_dcid_len(ch->port), - &ch->cur_local_cid)) + /* Generate an Initial LCID we will use for the connection. */ + if (!ossl_quic_lcidm_generate_initial(ch->lcidm, ch, &ch->cur_local_cid)) return 0; /* Note our newly learnt peer address and CIDs. */ @@ -3273,8 +3272,8 @@ int ossl_quic_channel_on_new_conn(QUIC_CHANNEL *ch, const BIO_ADDR *peer, ch->qrx, ch->qtx)) return 0; - /* Register our local CID in the DEMUX. */ - if (!ossl_qrx_add_dst_conn_id(ch->qrx, &ch->cur_local_cid)) + /* Register the peer ODCID in the LCIDM. */ + if (!ossl_quic_lcidm_enrol_odcid(ch->lcidm, ch, &ch->init_dcid)) return 0; /* Change state. */ @@ -3468,15 +3467,16 @@ void ossl_quic_channel_reject_stream(QUIC_CHANNEL *ch, QUIC_STREAM *qs) int ossl_quic_channel_replace_local_cid(QUIC_CHANNEL *ch, const QUIC_CONN_ID *conn_id) { - /* Remove the current local CID from the DEMUX. */ - if (!ossl_qrx_remove_dst_conn_id(ch->qrx, &ch->cur_local_cid)) + /* Remove the current LCID from the LCIDM. */ + if (!ossl_quic_lcidm_debug_remove(ch->lcidm, &ch->cur_local_cid)) return 0; ch->cur_local_cid = *conn_id; /* Set in the TXP, used only for long header packets. */ if (!ossl_quic_tx_packetiser_set_cur_scid(ch->txp, &ch->cur_local_cid)) return 0; - /* Register our new local CID in the DEMUX. */ - if (!ossl_qrx_add_dst_conn_id(ch->qrx, &ch->cur_local_cid)) + /* Add the new LCID to the LCIDM. */ + if (!ossl_quic_lcidm_debug_add(ch->lcidm, ch, &ch->cur_local_cid, + 100)) return 0; return 1; } -- Gitee From e3560bad06138e999e56cd1480ce039194926318 Mon Sep 17 00:00:00 2001 From: Hugo Landau Date: Thu, 9 Nov 2023 10:27:14 +0000 Subject: [PATCH 55/92] QUIC DEMUX, QRX: Add deprecation notices for future handling Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/22674) Signed-off-by: lanming1120 --- include/internal/quic_demux.h | 14 ++++++++++++++ include/internal/quic_record_rx.h | 6 ++++++ 2 files changed, 20 insertions(+) diff --git a/include/internal/quic_demux.h b/include/internal/quic_demux.h index 354d408c85..0749fe90b7 100644 --- a/include/internal/quic_demux.h +++ b/include/internal/quic_demux.h @@ -243,6 +243,9 @@ int ossl_quic_demux_set_mtu(QUIC_DEMUX *demux, unsigned int mtu); * Only one handler can be set for a given connection ID. If a handler is * already set for the given connection ID, returns 0. * + * TODO(QUIC SERVER): DEPRECATED in favour of explicit routing by QUIC_PORT with + * reference to QUIC_LCIDM. To be removed. + * * Returns 1 on success or 0 on failure. */ int ossl_quic_demux_register(QUIC_DEMUX *demux, @@ -254,6 +257,9 @@ int ossl_quic_demux_register(QUIC_DEMUX *demux, * Unregisters any datagram handler callback set for the given connection ID. * Fails if no handler is registered for the given connection ID. * + * TODO(QUIC SERVER): DEPRECATED in favour of explicit routing by QUIC_PORT with + * reference to QUIC_LCIDM. To be removed. + * * Returns 1 on success or 0 on failure. */ int ossl_quic_demux_unregister(QUIC_DEMUX *demux, @@ -263,6 +269,9 @@ int ossl_quic_demux_unregister(QUIC_DEMUX *demux, * Unregisters any datagram handler callback from all connection IDs it is used * for. cb and cb_arg must both match the values passed to * ossl_quic_demux_register. + * + * TODO(QUIC SERVER): DEPRECATED in favour of explicit routing by QUIC_PORT with + * reference to QUIC_LCIDM. To be removed. */ void ossl_quic_demux_unregister_by_cb(QUIC_DEMUX *demux, ossl_quic_demux_cb_fn *cb, @@ -277,6 +286,11 @@ void ossl_quic_demux_unregister_by_cb(QUIC_DEMUX *demux, * The handler is responsible for ensuring that ossl_quic_demux_reinject_urxe or * ossl_quic_demux_release_urxe is called on the passed packet at some point in * the future, which may or may not be before the handler returns. + * + * TODO(QUIC SERVER): In the future all RX handling will go via this function + * and the QUIC_PORT will be responsible for routing. DEMUX will then handle + * URXE memory management and datagram DCID parsing only. The MVP LCID routing + * functionality of the DEMUX will be removed in favour of LCIDM. */ void ossl_quic_demux_set_default_handler(QUIC_DEMUX *demux, ossl_quic_demux_cb_fn *cb, diff --git a/include/internal/quic_record_rx.h b/include/internal/quic_record_rx.h index e26fd35600..c4ed5a71d3 100644 --- a/include/internal/quic_record_rx.h +++ b/include/internal/quic_record_rx.h @@ -79,6 +79,9 @@ void ossl_qrx_set_msg_callback_arg(OSSL_QRX *qrx, * input to this function. This function fails if the DCID is already * registered. * + * TODO(QUIC SERVER): DEPRECATED in favour of explicit routing by QUIC_PORT with + * reference to QUIC_LCIDM. To be removed. + * * Returns 1 on success or 0 on error. */ int ossl_qrx_add_dst_conn_id(OSSL_QRX *qrx, @@ -89,6 +92,9 @@ int ossl_qrx_add_dst_conn_id(OSSL_QRX *qrx, * is unregistered from the demuxer. Fails if the DCID is not registered with * the demuxer. * + * TODO(QUIC SERVER): DEPRECATED in favour of explicit routing by QUIC_PORT with + * reference to QUIC_LCIDM. To be removed. + * * Returns 1 on success or 0 on error. */ int ossl_qrx_remove_dst_conn_id(OSSL_QRX *qrx, -- Gitee From 7db19fb89e71b34ece07e1074294ad9484a970b6 Mon Sep 17 00:00:00 2001 From: Hugo Landau Date: Thu, 9 Nov 2023 10:27:14 +0000 Subject: [PATCH 56/92] QUIC TXP TEST: Remove dependency on legacy DEMUX-QRX routing Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/22674) Signed-off-by: lanming1120 --- test/quic_txp_test.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/test/quic_txp_test.c b/test/quic_txp_test.c index 423d28ddcb..f234fb683a 100644 --- a/test/quic_txp_test.c +++ b/test/quic_txp_test.c @@ -108,6 +108,17 @@ static void helper_cleanup(struct helper *h) BIO_free(h->bio2); } +static void demux_default_handler(QUIC_URXE *e, void *arg, + const QUIC_CONN_ID *dcid) +{ + struct helper *h = arg; + + if (dcid == NULL || !ossl_quic_conn_id_eq(dcid, &dcid_1)) + return; + + ossl_qrx_inject_urxe(h->qrx, e); +} + static int helper_init(struct helper *h) { int rc = 0; @@ -204,6 +215,8 @@ static int helper_init(struct helper *h) fake_now, NULL))) goto err; + ossl_quic_demux_set_default_handler(h->demux, demux_default_handler, h); + h->qrx_args.demux = h->demux; h->qrx_args.short_conn_id_len = 8; h->qrx_args.max_deferred = 32; @@ -211,9 +224,6 @@ static int helper_init(struct helper *h) if (!TEST_ptr(h->qrx = ossl_qrx_new(&h->qrx_args))) goto err; - if (!TEST_true(ossl_qrx_add_dst_conn_id(h->qrx, &dcid_1))) - goto err; - ossl_qrx_allow_1rtt_processing(h->qrx); rc = 1; -- Gitee From 2bcb1a2c969c85bea7141375929cbe6c85ff5c26 Mon Sep 17 00:00:00 2001 From: Hugo Landau Date: Thu, 9 Nov 2023 10:27:14 +0000 Subject: [PATCH 57/92] QUIC QRL TEST: Remove dependency on legacy DEMUX-QRX routing Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/22674) Signed-off-by: lanming1120 --- test/quic_record_test.c | 50 ++++++++++++++++++++++++++--------------- 1 file changed, 32 insertions(+), 18 deletions(-) diff --git a/test/quic_record_test.c b/test/quic_record_test.c index 5966b93730..3c6eb19f82 100644 --- a/test/quic_record_test.c +++ b/test/quic_record_test.c @@ -21,7 +21,7 @@ static const QUIC_CONN_ID empty_conn_id = {0, {0}}; #define RX_TEST_OP_END 0 /* end of script */ #define RX_TEST_OP_SET_SCID_LEN 1 /* change SCID length */ #define RX_TEST_OP_SET_INIT_LARGEST_PN 2 /* set initial largest PN */ -#define RX_TEST_OP_ADD_RX_DCID 3 /* register an RX DCID */ +#define RX_TEST_OP_SET_RX_DCID 3 /* register an RX DCID */ #define RX_TEST_OP_INJECT 4 /* inject a datagram into demux */ #define RX_TEST_OP_PROVIDE_SECRET 5 /* provide RX secret */ #define RX_TEST_OP_PROVIDE_SECRET_INITIAL 6 /* provide RX secret for initial */ @@ -54,8 +54,8 @@ struct rx_test_op { { RX_TEST_OP_SET_SCID_LEN, 0, NULL, 0, NULL, (scid_len), 0, 0, NULL, NULL }, #define RX_OP_SET_INIT_LARGEST_PN(largest_pn) \ { RX_TEST_OP_SET_INIT_LARGEST_PN, 0, NULL, 0, NULL, 0, 0, (largest_pn), NULL, NULL }, -#define RX_OP_ADD_RX_DCID(dcid) \ - { RX_TEST_OP_ADD_RX_DCID, 0, NULL, 0, NULL, 0, 0, 0, &(dcid), NULL }, +#define RX_OP_SET_RX_DCID(dcid) \ + { RX_TEST_OP_SET_RX_DCID, 0, NULL, 0, NULL, 0, 0, 0, &(dcid), NULL }, #define RX_OP_INJECT(dgram) \ { RX_TEST_OP_INJECT, 0, (dgram), sizeof(dgram), NULL, 0, 0, 0, NULL }, #define RX_OP_PROVIDE_SECRET(el, suite, key) \ @@ -138,7 +138,7 @@ static const QUIC_PKT_HDR rx_script_1_expect_hdr = { static const struct rx_test_op rx_script_1[] = { RX_OP_SET_SCID_LEN(2) RX_OP_SET_INIT_LARGEST_PN(0) - RX_OP_ADD_RX_DCID(empty_conn_id) + RX_OP_SET_RX_DCID(empty_conn_id) RX_OP_PROVIDE_SECRET_INITIAL(rx_script_1_dcid) RX_OP_INJECT_CHECK(1) RX_OP_CHECK_NO_PKT() @@ -173,7 +173,7 @@ static const QUIC_PKT_HDR rx_script_2_expect_hdr = { static const struct rx_test_op rx_script_2[] = { RX_OP_ALLOW_1RTT() RX_OP_SET_INIT_LARGEST_PN(654360560) - RX_OP_ADD_RX_DCID(empty_conn_id) + RX_OP_SET_RX_DCID(empty_conn_id) RX_OP_PROVIDE_SECRET(QUIC_ENC_LEVEL_1RTT, QRL_SUITE_CHACHA20POLY1305, rx_script_2_secret) RX_OP_INJECT_CHECK(2) @@ -218,7 +218,7 @@ static const unsigned char rx_script_3_body[] = { }; static const struct rx_test_op rx_script_3[] = { - RX_OP_ADD_RX_DCID(empty_conn_id) + RX_OP_SET_RX_DCID(empty_conn_id) /* * This is a version negotiation packet, so doesn't have any frames. * However, the depacketizer still handles this sort of packet, so @@ -279,7 +279,7 @@ static const unsigned char rx_script_4_body[] = { }; static const struct rx_test_op rx_script_4[] = { - RX_OP_ADD_RX_DCID(empty_conn_id) + RX_OP_SET_RX_DCID(empty_conn_id) RX_OP_INJECT_CHECK(4) RX_OP_CHECK_NO_PKT() RX_OP_END @@ -592,7 +592,7 @@ static const unsigned char rx_script_5c_body[] = { static const struct rx_test_op rx_script_5[] = { RX_OP_ALLOW_1RTT() - RX_OP_ADD_RX_DCID(empty_conn_id) + RX_OP_SET_RX_DCID(empty_conn_id) RX_OP_PROVIDE_SECRET_INITIAL(rx_script_5_c2s_init_dcid) RX_OP_INJECT_N(5) RX_OP_CHECK_PKT_N(5a) @@ -629,7 +629,7 @@ static const struct rx_test_op rx_script_5[] = { /* Recreate QRL, test reading packets received before key */ RX_OP_SET_SCID_LEN(0) - RX_OP_ADD_RX_DCID(empty_conn_id) + RX_OP_SET_RX_DCID(empty_conn_id) RX_OP_INJECT_N(5) RX_OP_CHECK_NO_PKT() RX_OP_PROVIDE_SECRET_INITIAL(rx_script_5_c2s_init_dcid) @@ -961,7 +961,7 @@ static const unsigned char rx_script_6c_body[] = { static const struct rx_test_op rx_script_6[] = { RX_OP_ALLOW_1RTT() - RX_OP_ADD_RX_DCID(empty_conn_id) + RX_OP_SET_RX_DCID(empty_conn_id) RX_OP_PROVIDE_SECRET_INITIAL(rx_script_6_c2s_init_dcid) RX_OP_INJECT_N(6) RX_OP_CHECK_PKT_N(6a) @@ -998,7 +998,7 @@ static const struct rx_test_op rx_script_6[] = { /* Recreate QRL, test reading packets received before key */ RX_OP_SET_SCID_LEN(0) - RX_OP_ADD_RX_DCID(empty_conn_id) + RX_OP_SET_RX_DCID(empty_conn_id) RX_OP_INJECT_N(6) RX_OP_CHECK_NO_PKT() RX_OP_PROVIDE_SECRET_INITIAL(rx_script_6_c2s_init_dcid) @@ -1324,7 +1324,7 @@ static const unsigned char rx_script_7c_body[] = { static const struct rx_test_op rx_script_7[] = { RX_OP_ALLOW_1RTT() - RX_OP_ADD_RX_DCID(empty_conn_id) + RX_OP_SET_RX_DCID(empty_conn_id) RX_OP_PROVIDE_SECRET_INITIAL(rx_script_7_c2s_init_dcid) RX_OP_INJECT_N(7) RX_OP_CHECK_PKT_N(7a) @@ -1361,7 +1361,7 @@ static const struct rx_test_op rx_script_7[] = { /* Recreate QRL, test reading packets received before key */ RX_OP_SET_SCID_LEN(0) - RX_OP_ADD_RX_DCID(empty_conn_id) + RX_OP_SET_RX_DCID(empty_conn_id) RX_OP_INJECT_N(7) RX_OP_CHECK_NO_PKT() RX_OP_PROVIDE_SECRET_INITIAL(rx_script_7_c2s_init_dcid) @@ -1583,7 +1583,7 @@ static const unsigned char rx_script_8f_body[] = { static const struct rx_test_op rx_script_8[] = { RX_OP_ALLOW_1RTT() - RX_OP_ADD_RX_DCID(empty_conn_id) + RX_OP_SET_RX_DCID(empty_conn_id) /* Inject before we get the keys */ RX_OP_INJECT_N(8a) /* Nothing yet */ @@ -1676,7 +1676,7 @@ static const struct rx_test_op rx_script_8[] = { /* 9. 1-RTT Deferral Test */ static const struct rx_test_op rx_script_9[] = { - RX_OP_ADD_RX_DCID(empty_conn_id) + RX_OP_SET_RX_DCID(empty_conn_id) RX_OP_PROVIDE_SECRET_INITIAL(rx_script_5_c2s_init_dcid) RX_OP_INJECT_N(5) @@ -1723,6 +1723,8 @@ struct rx_state { SSL_CTX *quic_ssl_ctx; QUIC_CONNECTION *quic_conn; + QUIC_CONN_ID rx_dcid; + int allow_1rtt; }; @@ -1760,6 +1762,17 @@ static OSSL_TIME fake_time(void *arg) return expected_time(++time_counter); } +static void demux_default_handler(QUIC_URXE *e, void *arg, + const QUIC_CONN_ID *dcid) +{ + struct rx_state *s = arg; + + if (dcid == NULL || !ossl_quic_conn_id_eq(dcid, &s->rx_dcid)) + return; + + ossl_qrx_inject_urxe(s->qrx, e); +} + static int rx_state_ensure(struct rx_state *s) { if (s->demux == NULL @@ -1777,6 +1790,8 @@ static int rx_state_ensure(struct rx_state *s) && !TEST_ptr(s->qrx = ossl_qrx_new(&s->args))) return 0; + ossl_quic_demux_set_default_handler(s->demux, demux_default_handler, s); + if (s->allow_1rtt) ossl_qrx_allow_1rtt_processing(s->qrx); @@ -1803,11 +1818,10 @@ static int rx_run_script(const struct rx_test_op *script) for (i = 0; i < QUIC_PN_SPACE_NUM; ++i) s.args.init_largest_pn[i] = op->largest_pn; break; - case RX_TEST_OP_ADD_RX_DCID: + case RX_TEST_OP_SET_RX_DCID: if (!TEST_true(rx_state_ensure(&s))) goto err; - if (!TEST_true(ossl_qrx_add_dst_conn_id(s.qrx, op->dcid))) - goto err; + s.rx_dcid = *op->dcid; break; case RX_TEST_OP_PROVIDE_SECRET: if (!TEST_true(rx_state_ensure(&s))) -- Gitee From ea1160f2ce1a609e72faa53634852274cbd88b9b Mon Sep 17 00:00:00 2001 From: Hugo Landau Date: Thu, 9 Nov 2023 10:27:14 +0000 Subject: [PATCH 58/92] QUIC QRX: Remove legacy DEMUX-QRX routing code Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/22674) Signed-off-by: lanming1120 --- include/internal/quic_record_rx.h | 36 +------------------------------ ssl/quic/quic_record_rx.c | 27 ----------------------- 2 files changed, 1 insertion(+), 62 deletions(-) diff --git a/include/internal/quic_record_rx.h b/include/internal/quic_record_rx.h index c4ed5a71d3..cc2d6e94d8 100644 --- a/include/internal/quic_record_rx.h +++ b/include/internal/quic_record_rx.h @@ -28,7 +28,7 @@ typedef struct ossl_qrx_args_st { OSSL_LIB_CTX *libctx; const char *propq; - /* Demux to receive datagrams from. */ + /* Demux which owns the URXEs passed to us. */ QUIC_DEMUX *demux; /* Length of connection IDs used in short-header packets in bytes. */ @@ -66,40 +66,6 @@ void ossl_qrx_set_msg_callback(OSSL_QRX *qrx, ossl_msg_cb msg_callback, void ossl_qrx_set_msg_callback_arg(OSSL_QRX *qrx, void *msg_callback_arg); -/* - * DCID Management - * =============== - */ - -/* - * Adds a given DCID to the QRX. The QRX will register the DCID with the demuxer - * so that incoming packets with that DCID are passed to the given QRX. Multiple - * DCIDs may be associated with a QRX at any one time. You will need to add at - * least one DCID after instantiating the QRX. A zero-length DCID is a valid - * input to this function. This function fails if the DCID is already - * registered. - * - * TODO(QUIC SERVER): DEPRECATED in favour of explicit routing by QUIC_PORT with - * reference to QUIC_LCIDM. To be removed. - * - * Returns 1 on success or 0 on error. - */ -int ossl_qrx_add_dst_conn_id(OSSL_QRX *qrx, - const QUIC_CONN_ID *dst_conn_id); - -/* - * Remove a DCID previously registered with ossl_qrx_add_dst_conn_id. The DCID - * is unregistered from the demuxer. Fails if the DCID is not registered with - * the demuxer. - * - * TODO(QUIC SERVER): DEPRECATED in favour of explicit routing by QUIC_PORT with - * reference to QUIC_LCIDM. To be removed. - * - * Returns 1 on success or 0 on error. - */ -int ossl_qrx_remove_dst_conn_id(OSSL_QRX *qrx, - const QUIC_CONN_ID *dst_conn_id); - /* * Secret Management * ================= diff --git a/ssl/quic/quic_record_rx.c b/ssl/quic/quic_record_rx.c index d35264e7a2..393007df50 100644 --- a/ssl/quic/quic_record_rx.c +++ b/ssl/quic/quic_record_rx.c @@ -167,8 +167,6 @@ struct ossl_qrx_st { SSL *msg_callback_ssl; }; -static void qrx_on_rx(QUIC_URXE *urxe, void *arg, const QUIC_CONN_ID *dcid); - OSSL_QRX *ossl_qrx_new(const OSSL_QRX_ARGS *args) { OSSL_QRX *qrx; @@ -222,9 +220,6 @@ void ossl_qrx_free(OSSL_QRX *qrx) if (qrx == NULL) return; - /* Unregister from the RX DEMUX. */ - ossl_quic_demux_unregister_by_cb(qrx->demux, qrx_on_rx, qrx); - /* Free RXE queue data. */ qrx_cleanup_rxl(&qrx->rx_free); qrx_cleanup_rxl(&qrx->rx_pending); @@ -252,28 +247,6 @@ void ossl_qrx_inject_urxe(OSSL_QRX *qrx, QUIC_URXE *urxe) qrx->msg_callback_arg); } -static void qrx_on_rx(QUIC_URXE *urxe, void *arg, const QUIC_CONN_ID *dcid) -{ - OSSL_QRX *qrx = arg; - - ossl_qrx_inject_urxe(qrx, urxe); -} - -int ossl_qrx_add_dst_conn_id(OSSL_QRX *qrx, - const QUIC_CONN_ID *dst_conn_id) -{ - return ossl_quic_demux_register(qrx->demux, - dst_conn_id, - qrx_on_rx, - qrx); -} - -int ossl_qrx_remove_dst_conn_id(OSSL_QRX *qrx, - const QUIC_CONN_ID *dst_conn_id) -{ - return ossl_quic_demux_unregister(qrx->demux, dst_conn_id); -} - static void qrx_requeue_deferred(OSSL_QRX *qrx) { QUIC_URXE *e; -- Gitee From e9b71ea3db1793c8643560702abca8d704b88d3b Mon Sep 17 00:00:00 2001 From: Hugo Landau Date: Thu, 9 Nov 2023 10:27:14 +0000 Subject: [PATCH 59/92] QUIC DEMUX: Remove legacy routing code Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/22674) Signed-off-by: lanming1120 --- include/internal/quic_demux.h | 85 +++----------- ssl/quic/quic_demux.c | 205 +++------------------------------- 2 files changed, 28 insertions(+), 262 deletions(-) diff --git a/include/internal/quic_demux.h b/include/internal/quic_demux.h index 0749fe90b7..bca483a9a9 100644 --- a/include/internal/quic_demux.h +++ b/include/internal/quic_demux.h @@ -23,20 +23,19 @@ * ============ * * The QUIC connection demuxer is the entity responsible for receiving datagrams - * from the network via a datagram BIO. It parses packet headers to determine - * each packet's destination connection ID (DCID) and hands off processing of - * the packet to the correct QUIC Record Layer (QRL)'s RX side (known as the - * QRX). - * - * A QRX is instantiated per QUIC connection and contains the cryptographic - * resources needed to decrypt QUIC packets for that connection. Received - * datagrams are passed from the demuxer to the QRX via a callback registered - * for a specific DCID by the QRX; thus the demuxer has no specific knowledge of - * the QRX and is not coupled to it. - * - * A connection may have multiple connection IDs associated with it; a QRX - * handles this simply by registering multiple connection IDs with the demuxer - * via multiple register calls. + * from the network via a datagram BIO. It parses the headers of the first + * packet in the datagram to determine that packet's DCID and hands off + * processing of the entire datagram to a single callback function which can + * decide how to handle and route the datagram, for example by looking up + * a QRX instance and injecting the URXE into that QRX. + * + * A QRX will typically be instantiated per QUIC connection and contains the + * cryptographic resources needed to decrypt QUIC packets for that connection. + * However, it is up to the callback function to handle routing, for example by + * consulting a LCIDM instance. Thus the demuxer has no specific knowledge of + * any QRX and is not coupled to it. All CID knowledge is also externalised into + * a LCIDM or other CID state tracking object, without the DEMUX being coupled + * to any particular DCID resolution mechanism. * * URX Queue * --------- @@ -224,59 +223,6 @@ void ossl_quic_demux_set_bio(QUIC_DEMUX *demux, BIO *net_bio); */ int ossl_quic_demux_set_mtu(QUIC_DEMUX *demux, unsigned int mtu); -/* - * Register a datagram handler callback for a connection ID. - * - * ossl_quic_demux_pump will call the specified function if it receives a datagram - * the first packet of which has the specified destination connection ID. - * - * It is assumed all packets in a datagram have the same destination connection - * ID (as QUIC mandates this), but it is the user's responsibility to check for - * this and reject subsequent packets in a datagram that violate this rule. - * - * dst_conn_id is a destination connection ID; it is copied and need not remain - * valid after this function returns. - * - * cb_arg is passed to cb when it is called. For information on the callback, - * see its typedef above. - * - * Only one handler can be set for a given connection ID. If a handler is - * already set for the given connection ID, returns 0. - * - * TODO(QUIC SERVER): DEPRECATED in favour of explicit routing by QUIC_PORT with - * reference to QUIC_LCIDM. To be removed. - * - * Returns 1 on success or 0 on failure. - */ -int ossl_quic_demux_register(QUIC_DEMUX *demux, - const QUIC_CONN_ID *dst_conn_id, - ossl_quic_demux_cb_fn *cb, - void *cb_arg); - -/* - * Unregisters any datagram handler callback set for the given connection ID. - * Fails if no handler is registered for the given connection ID. - * - * TODO(QUIC SERVER): DEPRECATED in favour of explicit routing by QUIC_PORT with - * reference to QUIC_LCIDM. To be removed. - * - * Returns 1 on success or 0 on failure. - */ -int ossl_quic_demux_unregister(QUIC_DEMUX *demux, - const QUIC_CONN_ID *dst_conn_id); - -/* - * Unregisters any datagram handler callback from all connection IDs it is used - * for. cb and cb_arg must both match the values passed to - * ossl_quic_demux_register. - * - * TODO(QUIC SERVER): DEPRECATED in favour of explicit routing by QUIC_PORT with - * reference to QUIC_LCIDM. To be removed. - */ -void ossl_quic_demux_unregister_by_cb(QUIC_DEMUX *demux, - ossl_quic_demux_cb_fn *cb, - void *cb_arg); - /* * Set the default packet handler. This is used for incoming packets which don't * match a registered DCID. This is only needed for servers. If a default packet @@ -286,11 +232,6 @@ void ossl_quic_demux_unregister_by_cb(QUIC_DEMUX *demux, * The handler is responsible for ensuring that ossl_quic_demux_reinject_urxe or * ossl_quic_demux_release_urxe is called on the passed packet at some point in * the future, which may or may not be before the handler returns. - * - * TODO(QUIC SERVER): In the future all RX handling will go via this function - * and the QUIC_PORT will be responsible for routing. DEMUX will then handle - * URXE memory management and datagram DCID parsing only. The MVP LCID routing - * functionality of the DEMUX will be removed in favour of LCIDM. */ void ossl_quic_demux_set_default_handler(QUIC_DEMUX *demux, ossl_quic_demux_cb_fn *cb, diff --git a/ssl/quic/quic_demux.c b/ssl/quic/quic_demux.c index 376c088811..34d53b9f5c 100644 --- a/ssl/quic/quic_demux.c +++ b/ssl/quic/quic_demux.c @@ -21,37 +21,6 @@ #define DEMUX_DEFAULT_MTU 1500 -/* Structure used to track a given connection ID. */ -typedef struct quic_demux_conn_st QUIC_DEMUX_CONN; - -struct quic_demux_conn_st { - QUIC_DEMUX_CONN *next; /* used when unregistering only */ - QUIC_CONN_ID dst_conn_id; - ossl_quic_demux_cb_fn *cb; - void *cb_arg; -}; - -DEFINE_LHASH_OF_EX(QUIC_DEMUX_CONN); - -static unsigned long demux_conn_hash(const QUIC_DEMUX_CONN *conn) -{ - size_t i; - unsigned long v = 0; - - assert(conn->dst_conn_id.id_len <= QUIC_MAX_CONN_ID_LEN); - - for (i = 0; i < conn->dst_conn_id.id_len; ++i) - v ^= ((unsigned long)conn->dst_conn_id.id[i]) - << ((i * 8) % (sizeof(unsigned long) * 8)); - - return v; -} - -static int demux_conn_cmp(const QUIC_DEMUX_CONN *a, const QUIC_DEMUX_CONN *b) -{ - return !ossl_quic_conn_id_eq(&a->dst_conn_id, &b->dst_conn_id); -} - struct quic_demux_st { /* The underlying transport BIO with datagram semantics. */ BIO *net_bio; @@ -73,9 +42,6 @@ struct quic_demux_st { OSSL_TIME (*now)(void *arg); void *now_arg; - /* Hashtable mapping connection IDs to QUIC_DEMUX_CONN structures. */ - LHASH_OF(QUIC_DEMUX_CONN) *conns_by_id; - /* The default packet handler, if any. */ ossl_quic_demux_cb_fn *default_cb; void *default_cb_arg; @@ -121,13 +87,6 @@ QUIC_DEMUX *ossl_quic_demux_new(BIO *net_bio, demux->now = now; demux->now_arg = now_arg; - demux->conns_by_id - = lh_QUIC_DEMUX_CONN_new(demux_conn_hash, demux_conn_cmp); - if (demux->conns_by_id == NULL) { - OPENSSL_free(demux); - return NULL; - } - if (net_bio != NULL && BIO_dgram_get_local_addr_cap(net_bio) && BIO_dgram_set_local_addr_enable(net_bio, 1)) @@ -136,11 +95,6 @@ QUIC_DEMUX *ossl_quic_demux_new(BIO *net_bio, return demux; } -static void demux_free_conn_it(QUIC_DEMUX_CONN *conn, void *arg) -{ - OPENSSL_free(conn); -} - static void demux_free_urxl(QUIC_URXE_LIST *l) { QUIC_URXE *e, *enext; @@ -157,10 +111,6 @@ void ossl_quic_demux_free(QUIC_DEMUX *demux) if (demux == NULL) return; - /* Free all connection structures. */ - lh_QUIC_DEMUX_CONN_doall_arg(demux->conns_by_id, demux_free_conn_it, NULL); - lh_QUIC_DEMUX_CONN_free(demux->conns_by_id); - /* Free all URXEs we are holding. */ demux_free_urxl(&demux->urx_free); demux_free_urxl(&demux->urx_pending); @@ -195,104 +145,6 @@ int ossl_quic_demux_set_mtu(QUIC_DEMUX *demux, unsigned int mtu) return 1; } -static QUIC_DEMUX_CONN *demux_get_by_conn_id(QUIC_DEMUX *demux, - const QUIC_CONN_ID *dst_conn_id) -{ - QUIC_DEMUX_CONN key; - - if (dst_conn_id->id_len > QUIC_MAX_CONN_ID_LEN) - return NULL; - - key.dst_conn_id = *dst_conn_id; - return lh_QUIC_DEMUX_CONN_retrieve(demux->conns_by_id, &key); -} - -int ossl_quic_demux_register(QUIC_DEMUX *demux, - const QUIC_CONN_ID *dst_conn_id, - ossl_quic_demux_cb_fn *cb, void *cb_arg) -{ - QUIC_DEMUX_CONN *conn; - - if (dst_conn_id == NULL - || dst_conn_id->id_len > QUIC_MAX_CONN_ID_LEN - || cb == NULL) - return 0; - - /* Ensure not already registered. */ - if (demux_get_by_conn_id(demux, dst_conn_id) != NULL) - /* Handler already registered with this connection ID. */ - return 0; - - conn = OPENSSL_zalloc(sizeof(QUIC_DEMUX_CONN)); - if (conn == NULL) - return 0; - - conn->dst_conn_id = *dst_conn_id; - conn->cb = cb; - conn->cb_arg = cb_arg; - - lh_QUIC_DEMUX_CONN_insert(demux->conns_by_id, conn); - return 1; -} - -static void demux_unregister(QUIC_DEMUX *demux, - QUIC_DEMUX_CONN *conn) -{ - lh_QUIC_DEMUX_CONN_delete(demux->conns_by_id, conn); - OPENSSL_free(conn); -} - -int ossl_quic_demux_unregister(QUIC_DEMUX *demux, - const QUIC_CONN_ID *dst_conn_id) -{ - QUIC_DEMUX_CONN *conn; - - if (dst_conn_id == NULL - || dst_conn_id->id_len > QUIC_MAX_CONN_ID_LEN) - return 0; - - conn = demux_get_by_conn_id(demux, dst_conn_id); - if (conn == NULL) - return 0; - - demux_unregister(demux, conn); - return 1; -} - -struct unreg_arg { - ossl_quic_demux_cb_fn *cb; - void *cb_arg; - QUIC_DEMUX_CONN *head; -}; - -static void demux_unregister_by_cb(QUIC_DEMUX_CONN *conn, void *arg_) -{ - struct unreg_arg *arg = arg_; - - if (conn->cb == arg->cb && conn->cb_arg == arg->cb_arg) { - conn->next = arg->head; - arg->head = conn; - } -} - -void ossl_quic_demux_unregister_by_cb(QUIC_DEMUX *demux, - ossl_quic_demux_cb_fn *cb, - void *cb_arg) -{ - QUIC_DEMUX_CONN *conn, *cnext; - struct unreg_arg arg = {0}; - arg.cb = cb; - arg.cb_arg = cb_arg; - - lh_QUIC_DEMUX_CONN_doall_arg(demux->conns_by_id, - demux_unregister_by_cb, &arg); - - for (conn = arg.head; conn != NULL; conn = cnext) { - cnext = conn->next; - demux_unregister(demux, conn); - } -} - void ossl_quic_demux_set_default_handler(QUIC_DEMUX *demux, ossl_quic_demux_cb_fn *cb, void *cb_arg) @@ -480,29 +332,12 @@ static int demux_identify_conn_id(QUIC_DEMUX *demux, dst_conn_id); } -/* Identify the connection structure corresponding to a given URXE. */ -static QUIC_DEMUX_CONN *demux_identify_conn(QUIC_DEMUX *demux, QUIC_URXE *e, - QUIC_CONN_ID *dst_conn_id, - int *dst_conn_id_ok) -{ - if (!demux_identify_conn_id(demux, e, dst_conn_id)) - /* - * Datagram is so badly malformed we can't get the DCID from the first - * packet in it, so just give up. - */ - return NULL; - - *dst_conn_id_ok = 1; - return demux_get_by_conn_id(demux, dst_conn_id); -} - /* * Process a single pending URXE. * Returning 1 on success, 0 on failure and -1 on stateless reset. */ static int demux_process_pending_urxe(QUIC_DEMUX *demux, QUIC_URXE *e) { - QUIC_DEMUX_CONN *conn; QUIC_CONN_ID dst_conn_id; int r, dst_conn_id_ok = 0; @@ -535,35 +370,25 @@ static int demux_process_pending_urxe(QUIC_DEMUX *demux, QUIC_URXE *e) return 0; } - conn = demux_identify_conn(demux, e, &dst_conn_id, &dst_conn_id_ok); - if (conn == NULL) { + /* Determine the DCID of the first packet in the datagram. */ + dst_conn_id_ok = demux_identify_conn_id(demux, e, &dst_conn_id); + + ossl_list_urxe_remove(&demux->urx_pending, e); + if (demux->default_cb != NULL) { /* - * We could not identify a connection. If we have a default packet - * handler, pass it to the handler. Otherwise, we will never be able to - * process this datagram, so get rid of it. + * Pass to default handler for routing. The URXE now belongs to the + * callback. */ - ossl_list_urxe_remove(&demux->urx_pending, e); - if (demux->default_cb != NULL) { - /* Pass to default handler. */ - e->demux_state = URXE_DEMUX_STATE_ISSUED; - demux->default_cb(e, demux->default_cb_arg, - dst_conn_id_ok ? &dst_conn_id : NULL); - } else { - /* Discard. */ - ossl_list_urxe_insert_tail(&demux->urx_free, e); - e->demux_state = URXE_DEMUX_STATE_FREE; - } - return 1; /* keep processing pending URXEs */ + e->demux_state = URXE_DEMUX_STATE_ISSUED; + demux->default_cb(e, demux->default_cb_arg, + dst_conn_id_ok ? &dst_conn_id : NULL); + } else { + /* Discard. */ + ossl_list_urxe_insert_tail(&demux->urx_free, e); + e->demux_state = URXE_DEMUX_STATE_FREE; } - /* - * Remove from list and invoke callback. The URXE now belongs to the - * callback. (QUIC_DEMUX_CONN never has non-NULL cb.) - */ - ossl_list_urxe_remove(&demux->urx_pending, e); - e->demux_state = URXE_DEMUX_STATE_ISSUED; - conn->cb(e, conn->cb_arg, dst_conn_id_ok ? &dst_conn_id : NULL); - return 1; + return 1; /* keep processing pending URXEs */ } /* Process pending URXEs to generate callbacks. */ -- Gitee From 1b51afe5c7de58f0da56170e6a0201bcc2bb610e Mon Sep 17 00:00:00 2001 From: Hugo Landau Date: Thu, 9 Nov 2023 10:27:14 +0000 Subject: [PATCH 60/92] MARKER: End of Phase 3: Legacy Cleanup Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/22674) Signed-off-by: lanming1120 -- Gitee From a0694b66e6353d907f9c854a83bac3cfee0f366f Mon Sep 17 00:00:00 2001 From: Hugo Landau Date: Thu, 9 Nov 2023 10:27:14 +0000 Subject: [PATCH 61/92] QUIC CHANNEL: Finish moving SRT handling to SRTM Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/22674) Signed-off-by: lanming1120 --- include/internal/quic_channel.h | 2 + ssl/quic/quic_channel.c | 127 +++----------------------------- ssl/quic/quic_channel_local.h | 16 +--- ssl/quic/quic_port.c | 1 + 4 files changed, 14 insertions(+), 132 deletions(-) diff --git a/include/internal/quic_channel.h b/include/internal/quic_channel.h index 61683aff6c..0103b96eab 100644 --- a/include/internal/quic_channel.h +++ b/include/internal/quic_channel.h @@ -113,6 +113,8 @@ typedef struct quic_channel_args_st { QUIC_PORT *port; /* LCIDM to register LCIDs with. */ QUIC_LCIDM *lcidm; + /* SRTM to register SRTs with. */ + QUIC_SRTM *srtm; int is_server; SSL *tls; diff --git a/ssl/quic/quic_channel.c b/ssl/quic/quic_channel.c index 0d7493daa5..7d2517cef4 100644 --- a/ssl/quic/quic_channel.c +++ b/ssl/quic/quic_channel.c @@ -13,6 +13,7 @@ #include "internal/quic_error.h" #include "internal/quic_rx_depack.h" #include "internal/quic_lcidm.h" +#include "internal/quic_srtm.h" #include "../ssl_local.h" #include "quic_channel_local.h" #include "quic_port_local.h" @@ -117,95 +118,6 @@ static int gen_rand_conn_id(OSSL_LIB_CTX *libctx, size_t len, QUIC_CONN_ID *cid) return 1; } -static unsigned long chan_reset_token_hash(const QUIC_SRT_ELEM *a) -{ - unsigned long h; - - assert(sizeof(h) <= sizeof(a->token)); - memcpy(&h, &a->token, sizeof(h)); - return h; -} - -static int chan_reset_token_cmp(const QUIC_SRT_ELEM *a, const QUIC_SRT_ELEM *b) -{ - /* RFC 9000 s. 10.3.1: - * When comparing a datagram to stateless reset token values, - * endpoints MUST perform the comparison without leaking - * information about the value of the token. For example, - * performing this comparison in constant time protects the - * value of individual stateless reset tokens from information - * leakage through timing side channels. - * - * TODO(QUIC FUTURE): make this a memcmp when obfuscation is done and update - * comment above. - */ - return CRYPTO_memcmp(&a->token, &b->token, sizeof(a->token)); -} - -static int reset_token_obfuscate(QUIC_SRT_ELEM *out, const unsigned char *in) -{ - /* - * TODO(QUIC FUTURE): update this to AES encrypt the token in ECB mode with a - * random (per channel) key. - */ - memcpy(&out->token, in, sizeof(out->token)); - return 1; -} - -/* - * Add a stateless reset token to the channel - */ -static int chan_add_reset_token(QUIC_CHANNEL *ch, const unsigned char *new, - uint64_t seq_num) -{ - QUIC_SRT_ELEM *srte; - int err; - - /* Add to list by sequence number (always the tail) */ - if ((srte = OPENSSL_malloc(sizeof(*srte))) == NULL) - return 0; - - ossl_list_stateless_reset_tokens_init_elem(srte); - ossl_list_stateless_reset_tokens_insert_tail(&ch->srt_list_seq, srte); - reset_token_obfuscate(srte, new); - srte->seq_num = seq_num; - - lh_QUIC_SRT_ELEM_insert(ch->srt_hash_tok, srte); - err = lh_QUIC_SRT_ELEM_error(ch->srt_hash_tok); - if (err > 0) { - ossl_list_stateless_reset_tokens_remove(&ch->srt_list_seq, srte); - OPENSSL_free(srte); - return 0; - } - return 1; -} - -/* - * Remove a stateless reset token from the channel - * If the token isn't known, we just ignore the remove request which is safe. - */ -static void chan_remove_reset_token(QUIC_CHANNEL *ch, uint64_t seq_num) -{ - QUIC_SRT_ELEM *srte; - - /* - * Because the list is ordered and we only ever remove CIDs in order, - * this loop should never iterate, but safer to provide the option. - */ - for (srte = ossl_list_stateless_reset_tokens_head(&ch->srt_list_seq); - srte != NULL; - srte = ossl_list_stateless_reset_tokens_next(srte)) { - if (srte->seq_num > seq_num) - return; - if (srte->seq_num == seq_num) { - ossl_list_stateless_reset_tokens_remove(&ch->srt_list_seq, srte); - (void)lh_QUIC_SRT_ELEM_delete(ch->srt_hash_tok, srte); - OPENSSL_free(srte); - return; - } - } -} - /* * QUIC Channel Initialization and Teardown * ======================================== @@ -228,13 +140,7 @@ static int ch_init(QUIC_CHANNEL *ch) size_t rx_short_dcid_len = ossl_quic_port_get_rx_short_dcid_len(ch->port); size_t tx_init_dcid_len = ossl_quic_port_get_tx_init_dcid_len(ch->port); - if (ch->port == NULL || ch->lcidm == NULL) - goto err; - - ossl_list_stateless_reset_tokens_init(&ch->srt_list_seq); - ch->srt_hash_tok = lh_QUIC_SRT_ELEM_new(&chan_reset_token_hash, - &chan_reset_token_cmp); - if (ch->srt_hash_tok == NULL) + if (ch->port == NULL || ch->lcidm == NULL || ch->srtm == NULL) goto err; /* For clients, generate our initial DCID. */ @@ -346,13 +252,6 @@ static int ch_init(QUIC_CHANNEL *ch) ossl_quic_tx_packetiser_set_ack_tx_cb(ch->txp, ch_on_txp_ack_tx, ch); - /* - * Setup a handler to detect stateless reset tokens. - */ - //ossl_quic_demux_set_stateless_reset_handler(ch->demux, - // &ch_stateless_reset_token_handler, - // ch); - qrx_args.libctx = ch->port->libctx; qrx_args.demux = ch->port->demux; qrx_args.short_conn_id_len = rx_short_dcid_len; @@ -435,7 +334,6 @@ err: static void ch_cleanup(QUIC_CHANNEL *ch) { - QUIC_SRT_ELEM *srte, *srte_next; uint32_t pn_space; if (ch->ackm != NULL) @@ -445,6 +343,7 @@ static void ch_cleanup(QUIC_CHANNEL *ch) ossl_ackm_on_pkt_space_discarded(ch->ackm, pn_space); ossl_quic_lcidm_cull(ch->lcidm, ch); + ossl_quic_srtm_cull(ch->srtm, ch); ossl_quic_tx_packetiser_free(ch->txp); ossl_quic_txpim_free(ch->txpim); ossl_quic_cfq_free(ch->cfq); @@ -473,16 +372,6 @@ static void ch_cleanup(QUIC_CHANNEL *ch) OSSL_ERR_STATE_free(ch->err_state); OPENSSL_free(ch->ack_range_scratch); - /* Free the stateless reset tokens */ - for (srte = ossl_list_stateless_reset_tokens_head(&ch->srt_list_seq); - srte != NULL; - srte = srte_next) { - srte_next = ossl_list_stateless_reset_tokens_next(srte); - ossl_list_stateless_reset_tokens_remove(&ch->srt_list_seq, srte); - (void)lh_QUIC_SRT_ELEM_delete(ch->srt_hash_tok, srte); - OPENSSL_free(srte); - } - lh_QUIC_SRT_ELEM_free(ch->srt_hash_tok); if (ch->on_port_list) { ossl_list_ch_remove(&ch->port->channel_list, ch); ch->on_port_list = 0; @@ -500,6 +389,7 @@ QUIC_CHANNEL *ossl_quic_channel_new(const QUIC_CHANNEL_ARGS *args) ch->is_server = args->is_server; ch->tls = args->tls; ch->lcidm = args->lcidm; + ch->srtm = args->srtm; if (!ch_init(ch)) { OPENSSL_free(ch); @@ -1550,7 +1440,8 @@ static int ch_on_transport_params(const unsigned char *params, reason = TP_REASON_MALFORMED("STATELESS_RESET_TOKEN"); goto malformed; } - if (!chan_add_reset_token(ch, body, ch->cur_remote_seq_num)) { + if (!ossl_quic_srtm_add(ch->srtm, ch, ch->cur_remote_seq_num, + (const QUIC_STATELESS_RESET_TOKEN *)body)) { reason = TP_REASON_INTERNAL_ERROR("STATELESS_RESET_TOKEN"); goto malformed; } @@ -2877,7 +2768,7 @@ static int ch_enqueue_retire_conn_id(QUIC_CHANNEL *ch, uint64_t seq_num) WPACKET wpkt; size_t l; - chan_remove_reset_token(ch, seq_num); + ossl_quic_srtm_remove(ch->srtm, ch, seq_num); if ((buf_mem = BUF_MEM_new()) == NULL) goto err; @@ -2982,8 +2873,8 @@ void ossl_quic_channel_on_new_conn_id(QUIC_CHANNEL *ch, if (new_remote_seq_num > ch->cur_remote_seq_num) { /* Add new stateless reset token */ - if (!chan_add_reset_token(ch, f->stateless_reset.token, - new_remote_seq_num)) { + if (!ossl_quic_srtm_add(ch->srtm, ch, new_remote_seq_num, + &f->stateless_reset)) { ossl_quic_channel_raise_protocol_error( ch, QUIC_ERR_CONNECTION_ID_LIMIT_ERROR, OSSL_QUIC_FRAME_TYPE_NEW_CONN_ID, diff --git a/ssl/quic/quic_channel_local.h b/ssl/quic/quic_channel_local.h index 8c8688aac2..2338f6b262 100644 --- a/ssl/quic/quic_channel_local.h +++ b/ssl/quic/quic_channel_local.h @@ -54,6 +54,8 @@ struct quic_channel_st { /* Port LCIDM we use to register LCIDs. */ QUIC_LCIDM *lcidm; + /* SRTM we register SRTs with. */ + QUIC_SRTM *srtm; /* * The transport parameter block we will send or have sent. @@ -124,14 +126,6 @@ struct quic_channel_st { /* * The DCID we currently use to talk to the peer and its sequence num. - * - * TODO(QUIC FUTURE) consider removing the second two, both are contained in - * srt_list_seq (defined below). - * - * cur_remote_seq_num is same as the sequence number in the last element. - * cur_retire_prior_to corresponds to the sequence number in first element. - * - * Leaving them here avoids null checking etc */ QUIC_CONN_ID cur_remote_dcid; uint64_t cur_remote_seq_num; @@ -140,12 +134,6 @@ struct quic_channel_st { /* Server only: The DCID we currently expect the peer to use to talk to us. */ QUIC_CONN_ID cur_local_cid; - /* Hash of stateless reset tokens keyed on the token */ - LHASH_OF(QUIC_SRT_ELEM) *srt_hash_tok; - - /* List of the stateless reset tokens ordered by sequence number */ - OSSL_LIST(stateless_reset_tokens) srt_list_seq; - /* Transport parameter values we send to our peer. */ uint64_t tx_init_max_stream_data_bidi_local; uint64_t tx_init_max_stream_data_bidi_remote; diff --git a/ssl/quic/quic_port.c b/ssl/quic/quic_port.c index 9be20c3f7b..036c30f1f3 100644 --- a/ssl/quic/quic_port.c +++ b/ssl/quic/quic_port.c @@ -281,6 +281,7 @@ static QUIC_CHANNEL *port_make_channel(QUIC_PORT *port, SSL *tls, int is_server) args.is_server = is_server; args.tls = (tls != NULL ? tls : port_new_handshake_layer(port)); args.lcidm = port->lcidm; + args.srtm = port->srtm; if (args.tls == NULL) return NULL; -- Gitee From 4ecb3cff56f0add860d2a80f49e791387293924e Mon Sep 17 00:00:00 2001 From: Hugo Landau Date: Thu, 9 Nov 2023 10:27:14 +0000 Subject: [PATCH 62/92] QUIC CHANNEL: Finish cleanup of LCIDM integration Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/22674) Signed-off-by: lanming1120 --- ssl/quic/quic_channel.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/ssl/quic/quic_channel.c b/ssl/quic/quic_channel.c index 7d2517cef4..0b1eea2bab 100644 --- a/ssl/quic/quic_channel.c +++ b/ssl/quic/quic_channel.c @@ -221,6 +221,10 @@ static int ch_init(QUIC_CHANNEL *ch) ch->have_qsm = 1; + if (!ch->is_server + && !ossl_quic_lcidm_generate_initial(ch->lcidm, ch, &txp_args.cur_scid)) + goto err; + /* We use a zero-length SCID. */ txp_args.cur_dcid = ch->init_dcid; txp_args.ack_delay_exponent = 3; @@ -270,11 +274,6 @@ static int ch_init(QUIC_CHANNEL *ch) ch)) goto err; - /* TODO plug this correctly */ - if (!ch->is_server - && !ossl_quic_lcidm_generate_initial(ch->lcidm, ch, &txp_args.cur_scid)) - goto err; - for (pn_space = QUIC_PN_SPACE_INITIAL; pn_space < QUIC_PN_SPACE_NUM; ++pn_space) { ch->crypto_recv[pn_space] = ossl_quic_rstream_new(NULL, NULL, 0); if (ch->crypto_recv[pn_space] == NULL) -- Gitee From bd1eb7dc3d5423cea75fbfc8c4416c2efa33ba1a Mon Sep 17 00:00:00 2001 From: Hugo Landau Date: Thu, 9 Nov 2023 10:27:14 +0000 Subject: [PATCH 63/92] QUIC CHANNEL, LCIDM: Factor duplicate CID generation function Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/22674) Signed-off-by: lanming1120 --- include/internal/quic_types.h | 7 +++++++ ssl/quic/quic_channel.c | 19 ++----------------- ssl/quic/quic_lcidm.c | 22 +--------------------- ssl/quic/quic_wire.c | 18 ++++++++++++++++++ 4 files changed, 28 insertions(+), 38 deletions(-) diff --git a/include/internal/quic_types.h b/include/internal/quic_types.h index 1d3816a209..fa1ac81ca1 100644 --- a/include/internal/quic_types.h +++ b/include/internal/quic_types.h @@ -87,6 +87,13 @@ static ossl_unused ossl_inline int ossl_quic_conn_id_eq(const QUIC_CONN_ID *a, return memcmp(a->id, b->id, a->id_len) == 0; } +/* + * Generates a random CID of the given length. libctx may be NULL. + * Returns 1 on success or 0 on failure. + */ +int ossl_quic_gen_rand_conn_id(OSSL_LIB_CTX *libctx, size_t len, + QUIC_CONN_ID *cid); + # define QUIC_MIN_INITIAL_DGRAM_LEN 1200 # define QUIC_DEFAULT_ACK_DELAY_EXP 3 diff --git a/ssl/quic/quic_channel.c b/ssl/quic/quic_channel.c index 0b1eea2bab..aed911ad9f 100644 --- a/ssl/quic/quic_channel.c +++ b/ssl/quic/quic_channel.c @@ -102,22 +102,6 @@ static void ch_raise_version_neg_failure(QUIC_CHANNEL *ch); DEFINE_LHASH_OF_EX(QUIC_SRT_ELEM); -static int gen_rand_conn_id(OSSL_LIB_CTX *libctx, size_t len, QUIC_CONN_ID *cid) -{ - if (len > QUIC_MAX_CONN_ID_LEN) - return 0; - - cid->id_len = (unsigned char)len; - - if (RAND_bytes_ex(libctx, cid->id, len, len * 8) != 1) { - ERR_raise(ERR_LIB_SSL, ERR_R_RAND_LIB); - cid->id_len = 0; - return 0; - } - - return 1; -} - /* * QUIC Channel Initialization and Teardown * ======================================== @@ -145,7 +129,8 @@ static int ch_init(QUIC_CHANNEL *ch) /* For clients, generate our initial DCID. */ if (!ch->is_server - && !gen_rand_conn_id(ch->port->libctx, tx_init_dcid_len, &ch->init_dcid)) + && !ossl_quic_gen_rand_conn_id(ch->port->libctx, tx_init_dcid_len, + &ch->init_dcid)) goto err; /* We plug in a network write BIO to the QTX later when we get one. */ diff --git a/ssl/quic/quic_lcidm.c b/ssl/quic/quic_lcidm.c index a3315164c7..e5948b95e9 100644 --- a/ssl/quic/quic_lcidm.c +++ b/ssl/quic/quic_lcidm.c @@ -287,26 +287,6 @@ size_t ossl_quic_lcidm_get_num_active_lcid(const QUIC_LCIDM *lcidm, return conn->num_active_lcid; } -#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION - -static int gen_rand_conn_id(OSSL_LIB_CTX *libctx, size_t len, QUIC_CONN_ID *cid) -{ - if (len > QUIC_MAX_CONN_ID_LEN) - return 0; - - cid->id_len = (unsigned char)len; - - if (RAND_bytes_ex(libctx, cid->id, len, len * 8) != 1) { - ERR_raise(ERR_LIB_SSL, ERR_R_RAND_LIB); - cid->id_len = 0; - return 0; - } - - return 1; -} - -#endif - static int lcidm_generate_cid(QUIC_LCIDM *lcidm, QUIC_CONN_ID *cid) { @@ -322,7 +302,7 @@ static int lcidm_generate_cid(QUIC_LCIDM *lcidm, return 1; #else - return gen_rand_conn_id(lcidm->libctx, lcidm->lcid_len, cid); + return ossl_quic_gen_rand_conn_id(lcidm->libctx, lcidm->lcid_len, cid); #endif } diff --git a/ssl/quic/quic_wire.c b/ssl/quic/quic_wire.c index 425e7efc2e..faf80cfd07 100644 --- a/ssl/quic/quic_wire.c +++ b/ssl/quic/quic_wire.c @@ -9,6 +9,7 @@ #include #include +#include #include "internal/quic_ssl.h" #include "internal/quic_vlint.h" #include "internal/quic_wire.h" @@ -1076,3 +1077,20 @@ const char *ossl_quic_err_to_string(uint64_t error_code) return NULL; } } + +int ossl_quic_gen_rand_conn_id(OSSL_LIB_CTX *libctx, size_t len, + QUIC_CONN_ID *cid) +{ + if (len > QUIC_MAX_CONN_ID_LEN) + return 0; + + cid->id_len = (unsigned char)len; + + if (RAND_bytes_ex(libctx, cid->id, len, len * 8) != 1) { + ERR_raise(ERR_LIB_SSL, ERR_R_RAND_LIB); + cid->id_len = 0; + return 0; + } + + return 1; +} -- Gitee From 4cba1f3801a8ccceca6741d842661f57111f5f70 Mon Sep 17 00:00:00 2001 From: Hugo Landau Date: Thu, 9 Nov 2023 10:27:14 +0000 Subject: [PATCH 64/92] QUIC DEMUX: Remove obsolete SRT handling code Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/22674) Signed-off-by: lanming1120 --- include/internal/quic_demux.h | 21 ------------------ ssl/quic/quic_demux.c | 42 +++-------------------------------- ssl/quic/quic_port.c | 8 ------- 3 files changed, 3 insertions(+), 68 deletions(-) diff --git a/include/internal/quic_demux.h b/include/internal/quic_demux.h index bca483a9a9..40a1bc412f 100644 --- a/include/internal/quic_demux.h +++ b/include/internal/quic_demux.h @@ -181,14 +181,6 @@ typedef struct quic_demux_st QUIC_DEMUX; typedef void (ossl_quic_demux_cb_fn)(QUIC_URXE *e, void *arg, const QUIC_CONN_ID *dcid); -/* - * Called when a datagram is received. - * Returns 1 if the datagram ends with a stateless reset token and - * 0 if not. - */ -typedef int (ossl_quic_stateless_reset_cb_fn)(const unsigned char *data, - size_t data_len, void *arg); - /* * Creates a new demuxer. The given BIO is used to receive datagrams from the * network using BIO_recvmmsg. short_conn_id_len is the length of destination @@ -237,18 +229,6 @@ void ossl_quic_demux_set_default_handler(QUIC_DEMUX *demux, ossl_quic_demux_cb_fn *cb, void *cb_arg); -/* - * Sets a callback for stateless reset processing. - * - * If set, this callback is called for datagrams for which we cannot identify - * a CID. This function should return 1 if there is a stateless reset token - * present and 0 if not. If there is a token present, the connection should - * also be reset. - */ -void ossl_quic_demux_set_stateless_reset_handler( - QUIC_DEMUX *demux, - ossl_quic_stateless_reset_cb_fn *cb, void *cb_arg); - /* * Releases a URXE back to the demuxer. No reference must be made to the URXE or * its buffer after calling this function. The URXE must not be in any queue; @@ -294,7 +274,6 @@ void ossl_quic_demux_reinject_urxe(QUIC_DEMUX *demux, #define QUIC_DEMUX_PUMP_RES_OK 1 #define QUIC_DEMUX_PUMP_RES_TRANSIENT_FAIL (-1) #define QUIC_DEMUX_PUMP_RES_PERMANENT_FAIL (-2) -#define QUIC_DEMUX_PUMP_RES_STATELESS_RESET (-3) int ossl_quic_demux_pump(QUIC_DEMUX *demux); diff --git a/ssl/quic/quic_demux.c b/ssl/quic/quic_demux.c index 34d53b9f5c..b3e03a0bca 100644 --- a/ssl/quic/quic_demux.c +++ b/ssl/quic/quic_demux.c @@ -46,10 +46,6 @@ struct quic_demux_st { ossl_quic_demux_cb_fn *default_cb; void *default_cb_arg; - /* The stateless reset token checker handler, if any. */ - ossl_quic_stateless_reset_cb_fn *reset_token_cb; - void *reset_token_cb_arg; - /* * List of URXEs which are not currently in use (i.e., not filled with * unconsumed data). These are moved to the pending list as they are filled. @@ -153,14 +149,6 @@ void ossl_quic_demux_set_default_handler(QUIC_DEMUX *demux, demux->default_cb_arg = cb_arg; } -void ossl_quic_demux_set_stateless_reset_handler( - QUIC_DEMUX *demux, - ossl_quic_stateless_reset_cb_fn *cb, void *cb_arg) -{ - demux->reset_token_cb = cb; - demux->reset_token_cb_arg = cb_arg; -} - static QUIC_URXE *demux_alloc_urxe(size_t alloc_len) { QUIC_URXE *e; @@ -334,12 +322,12 @@ static int demux_identify_conn_id(QUIC_DEMUX *demux, /* * Process a single pending URXE. - * Returning 1 on success, 0 on failure and -1 on stateless reset. + * Returning 1 on success, 0 on failure. */ static int demux_process_pending_urxe(QUIC_DEMUX *demux, QUIC_URXE *e) { QUIC_CONN_ID dst_conn_id; - int r, dst_conn_id_ok = 0; + int dst_conn_id_ok = 0; /* The next URXE we process should be at the head of the pending list. */ if (!ossl_assert(e == ossl_list_urxe_head(&demux->urx_pending))) @@ -347,29 +335,6 @@ static int demux_process_pending_urxe(QUIC_DEMUX *demux, QUIC_URXE *e) assert(e->demux_state == URXE_DEMUX_STATE_PENDING); - /* - * Check if the packet ends with a stateless reset token and if it does - * skip it after dropping the connection. - * - * RFC 9000 s. 10.3.1 Detecting a Stateless Reset - * If the last 16 bytes of the datagram are identical in value to - * a stateless reset token, the endpoint MUST enter the draining - * period and not send any further packets on this connection. - * - * Returning a failure here causes the connection to enter the terminating - * state which achieves the desired outcome. - * - * TODO(QUIC FUTURE): only try to match unparsable packets - */ - if (demux->reset_token_cb != NULL) { - r = demux->reset_token_cb(ossl_quic_urxe_data(e), e->data_len, - demux->reset_token_cb_arg); - if (r > 0) /* Received a stateless reset */ - return -1; - if (r < 0) /* Error during stateless reset detection */ - return 0; - } - /* Determine the DCID of the first packet in the datagram. */ dst_conn_id_ok = demux_identify_conn_id(demux, e, &dst_conn_id); @@ -428,8 +393,7 @@ int ossl_quic_demux_pump(QUIC_DEMUX *demux) } if ((ret = demux_process_pending_urxl(demux)) <= 0) - return ret == 0 ? QUIC_DEMUX_PUMP_RES_PERMANENT_FAIL - : QUIC_DEMUX_PUMP_RES_STATELESS_RESET; + return QUIC_DEMUX_PUMP_RES_PERMANENT_FAIL; return QUIC_DEMUX_PUMP_RES_OK; } diff --git a/ssl/quic/quic_port.c b/ssl/quic/quic_port.c index 036c30f1f3..482f696e11 100644 --- a/ssl/quic/quic_port.c +++ b/ssl/quic/quic_port.c @@ -75,12 +75,6 @@ static int port_init(QUIC_PORT *port) get_time, port)) == NULL) goto err; - /* - * If we are a server, setup our handler for packets not corresponding to - * any known DCID on our end. This is for handling clients establishing new - * connections. - */ - // if (is_server) ossl_quic_demux_set_default_handler(port->demux, port_default_packet_handler, port); @@ -357,8 +351,6 @@ static void port_rx_pre(QUIC_PORT *port) * to the appropriate QRX instances. */ ret = ossl_quic_demux_pump(port->demux); - // TODO: handle ret, stateless reset - if (ret == QUIC_DEMUX_PUMP_RES_PERMANENT_FAIL) /* * We don't care about transient failure, but permanent failure means we -- Gitee From f019ddbc4e2b5883907835f95415b0bb35da51be Mon Sep 17 00:00:00 2001 From: Hugo Landau Date: Thu, 9 Nov 2023 10:27:14 +0000 Subject: [PATCH 65/92] QUIC PORT: Resolve TODOs Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/22674) Signed-off-by: lanming1120 --- ssl/quic/quic_port.c | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/ssl/quic/quic_port.c b/ssl/quic/quic_port.c index 482f696e11..2b1e518c68 100644 --- a/ssl/quic/quic_port.c +++ b/ssl/quic/quic_port.c @@ -344,8 +344,6 @@ static void port_rx_pre(QUIC_PORT *port) { int ret; - // TODO !have_sent_any_pkt - /* * Get DEMUX to BIO_recvmmsg from the network and queue incoming datagrams * to the appropriate QRX instances. @@ -451,16 +449,19 @@ static void port_default_packet_handler(QUIC_URXE *e, void *arg, if (port_try_handle_stateless_reset(port, e)) goto undesirable; - // TODO review this + /* + * If we have an incoming packet which doesn't match any existing connection + * we assume this is an attempt to make a new connection. Currently we + * require our caller to have precreated a latent 'incoming' channel via + * TSERVER which then gets turned into the new connection. + * + * TODO(QUIC SERVER): In the future we will construct channels dynamically + * in this case. + */ if (port->tserver_ch == NULL) goto undesirable; - // TODO allow_incoming - //if (!ossl_assert(ch->is_server)) - // goto undesirable; - - //TODO if (ch->state != QUIC_CHANNEL_STATE_IDLE) - // goto undesirable; + // TODO fsm /* * We have got a packet for an unknown DCID. This might be an attempt to @@ -501,12 +502,9 @@ static void port_default_packet_handler(QUIC_URXE *e, void *arg, /* * Try to process this as a valid attempt to initiate a connection. * - * We do not register the DCID in the Initial packet we received as - * that DCID is not actually used again, thus after provisioning - * the new connection and associated Initial keys, we inject the - * received packet directly to the new channel's QRX so that it can - * process it as a one-time thing, instead of going through the usual - * DEMUX DCID-based routing. + * The channel will do all the LCID registration needed, but as an + * optimization inject this packet directly into the channel's QRX for + * processing without going through the DEMUX again. */ port_on_new_conn(port, &e->peer, &hdr.src_conn_id, &hdr.dst_conn_id, &new_ch); -- Gitee From ba76486d2793ed25571c95ae292268f869868489 Mon Sep 17 00:00:00 2001 From: Hugo Landau Date: Thu, 9 Nov 2023 10:27:14 +0000 Subject: [PATCH 66/92] QUIC PORT: Formalise states of a port Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/22674) Signed-off-by: lanming1120 --- include/internal/quic_port.h | 3 +++ ssl/quic/quic_port.c | 22 +++++++++++++++++++--- ssl/quic/quic_port_local.h | 16 ++++++++++++++++ 3 files changed, 38 insertions(+), 3 deletions(-) diff --git a/include/internal/quic_port.h b/include/internal/quic_port.h index 0b24338c2f..ea97b93392 100644 --- a/include/internal/quic_port.h +++ b/include/internal/quic_port.h @@ -130,6 +130,9 @@ int ossl_quic_port_get_tx_init_dcid_len(const QUIC_PORT *port); /* For testing use. While enabled, ticking is not performed. */ void ossl_quic_port_set_inhibit_tick(QUIC_PORT *port, int inhibit); +/* Returns 1 if the port is running/healthy, 0 if it has failed. */ +int ossl_quic_port_is_running(const QUIC_PORT *port); + /* * Events * ====== diff --git a/ssl/quic/quic_port.c b/ssl/quic/quic_port.c index 2b1e518c68..db1a352adf 100644 --- a/ssl/quic/quic_port.c +++ b/ssl/quic/quic_port.c @@ -88,6 +88,7 @@ static int port_init(QUIC_PORT *port) ossl_quic_reactor_init(&port->rtor, port_tick, port, ossl_time_zero()); port->rx_short_dcid_len = (unsigned char)rx_short_dcid_len; port->tx_init_dcid_len = INIT_DCID_LEN; + port->state = QUIC_PORT_STATE_RUNNING; return 1; err: @@ -109,6 +110,19 @@ static void port_cleanup(QUIC_PORT *port) port->lcidm = NULL; } +static void port_transition_failed(QUIC_PORT *port) +{ + if (port->state == QUIC_PORT_STATE_FAILED) + return; + + port->state = QUIC_PORT_STATE_FAILED; +} + +int ossl_quic_port_is_running(const QUIC_PORT *port) +{ + return port->state == QUIC_PORT_STATE_RUNNING; +} + QUIC_REACTOR *ossl_quic_port_get0_reactor(QUIC_PORT *port) { return &port->rtor; @@ -438,6 +452,10 @@ static void port_default_packet_handler(QUIC_URXE *e, void *arg, QUIC_PKT_HDR hdr; QUIC_CHANNEL *ch = NULL, *new_ch = NULL; + /* Don't handle anything if we are no longer running. */ + if (!ossl_quic_port_is_running(port)) + goto undesirable; + if (dcid != NULL && ossl_quic_lcidm_lookup(port->lcidm, dcid, NULL, (void **)&ch)) { @@ -461,8 +479,6 @@ static void port_default_packet_handler(QUIC_URXE *e, void *arg, if (port->tserver_ch == NULL) goto undesirable; - // TODO fsm - /* * We have got a packet for an unknown DCID. This might be an attempt to * open a new connection. @@ -526,7 +542,7 @@ void ossl_quic_port_raise_net_error(QUIC_PORT *port) { QUIC_CHANNEL *ch; - // TODO fsm + port_transition_failed(port); LIST_FOREACH(ch, ch, &port->channel_list) ossl_quic_channel_raise_net_error(ch); diff --git a/ssl/quic/quic_port_local.h b/ssl/quic/quic_port_local.h index bfcc5896e1..a2937beeaf 100644 --- a/ssl/quic/quic_port_local.h +++ b/ssl/quic/quic_port_local.h @@ -18,6 +18,19 @@ */ DECLARE_LIST_OF(ch, QUIC_CHANNEL); +/* A port is always in one of the following states: */ +enum { + /* Initial and steady state. */ + QUIC_PORT_STATE_RUNNING, + + /* + * Terminal state indicating port is no longer functioning. There are no + * transitions out of this state. May be triggered by e.g. a permanent + * network BIO error. + */ + QUIC_PORT_STATE_FAILED +}; + struct quic_port_st { OSSL_LIB_CTX *libctx; const char *propq; @@ -63,6 +76,9 @@ struct quic_port_st { /* For clients, CID length used for outgoing Initial packets. */ unsigned char tx_init_dcid_len; + /* Port state (QUIC_PORT_STATE_*). */ + unsigned int state : 1; + /* Is this port created to support multiple connections? */ unsigned int is_multi_conn : 1; -- Gitee From 974654681aae0e1225668cbe024557eab5149926 Mon Sep 17 00:00:00 2001 From: Hugo Landau Date: Thu, 9 Nov 2023 10:27:14 +0000 Subject: [PATCH 67/92] ERR: Add ERR_pop() Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/22674) Signed-off-by: lanming1120 --- crypto/err/err_mark.c | 13 +++++++++++++ doc/man3/ERR_set_mark.pod | 14 ++++++++++++-- include/openssl/err.h.in | 1 + util/libcrypto.num | 1 + 4 files changed, 27 insertions(+), 2 deletions(-) diff --git a/crypto/err/err_mark.c b/crypto/err/err_mark.c index 82dc4764c4..cb01a1f4f6 100644 --- a/crypto/err/err_mark.c +++ b/crypto/err/err_mark.c @@ -26,6 +26,19 @@ int ERR_set_mark(void) return 1; } +int ERR_pop(void) +{ + ERR_STATE *es; + + es = ossl_err_get_state_int(); + if (es == NULL || es->bottom == es->top) + return 0; + + err_clear(es, es->top, 0); + es->top = es->top > 0 ? es->top - 1 : ERR_NUM_ERRORS - 1; + return 1; +} + int ERR_pop_to_mark(void) { ERR_STATE *es; diff --git a/doc/man3/ERR_set_mark.pod b/doc/man3/ERR_set_mark.pod index b2c0f7de0a..d6d715e2f6 100644 --- a/doc/man3/ERR_set_mark.pod +++ b/doc/man3/ERR_set_mark.pod @@ -2,8 +2,8 @@ =head1 NAME -ERR_set_mark, ERR_clear_last_mark, ERR_pop_to_mark, ERR_count_to_mark - set -mark, clear mark and pop errors until mark +ERR_set_mark, ERR_clear_last_mark, ERR_pop_to_mark, ERR_count_to_mark, ERR_pop - +set mark, clear mark and pop errors until mark =head1 SYNOPSIS @@ -13,6 +13,7 @@ mark, clear mark and pop errors until mark int ERR_pop_to_mark(void); int ERR_clear_last_mark(void); int ERR_count_to_mark(void); + int ERR_pop(void); =head1 DESCRIPTION @@ -28,6 +29,9 @@ ERR_count_to_mark() returns the number of entries on the error stack above the most recently marked entry, not including that entry. If there is no mark in the error stack, the number of entries in the error stack is returned. +ERR_pop() unconditionally pops a single error entry from the top of the error +stack (which is the entry obtainable via L). + =head1 RETURN VALUES ERR_set_mark() returns 0 if the error stack is empty, otherwise 1. @@ -38,6 +42,12 @@ error stack, which implies that the stack became empty, otherwise 1. ERR_count_to_mark() returns the number of error stack entries found above the most recent mark, if any, or the total number of error stack entries. +ERR_pop() returns 1 if an error was popped or 0 if the error stack was empty. + +=head1 HISTORY + +ERR_pop() was added in OpenSSL 3.3. + =head1 COPYRIGHT Copyright 2003-2023 The OpenSSL Project Authors. All Rights Reserved. diff --git a/include/openssl/err.h.in b/include/openssl/err.h.in index 1ef09de02e..9143704c09 100644 --- a/include/openssl/err.h.in +++ b/include/openssl/err.h.in @@ -486,6 +486,7 @@ int ERR_set_mark(void); int ERR_pop_to_mark(void); int ERR_clear_last_mark(void); int ERR_count_to_mark(void); +int ERR_pop(void); ERR_STATE *OSSL_ERR_STATE_new(void); void OSSL_ERR_STATE_save(ERR_STATE *es); diff --git a/util/libcrypto.num b/util/libcrypto.num index 60f320c33a..0b72559f86 100644 --- a/util/libcrypto.num +++ b/util/libcrypto.num @@ -5541,3 +5541,4 @@ OSSL_CMP_HDR_get0_geninfo_ITAVs ? 3_3_0 EXIST::FUNCTION:CMP OSSL_CMP_ITAV_new0_certProfile ? 3_3_0 EXIST::FUNCTION:CMP OSSL_CMP_ITAV_get0_certProfile ? 3_3_0 EXIST::FUNCTION:CMP EVP_DigestSqueeze ? 3_3_0 EXIST::FUNCTION: +ERR_pop ? 3_3_0 EXIST::FUNCTION: -- Gitee From aa04d377f332b8826b8f6bb8bc71c1b3def55cf4 Mon Sep 17 00:00:00 2001 From: Hugo Landau Date: Thu, 9 Nov 2023 10:27:14 +0000 Subject: [PATCH 68/92] QUIC MULTISTREAM TEST: add OP_POP_ERR Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/22674) Signed-off-by: lanming1120 --- test/quic_multistream_test.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/quic_multistream_test.c b/test/quic_multistream_test.c index 604c2f986b..3782e65286 100644 --- a/test/quic_multistream_test.c +++ b/test/quic_multistream_test.c @@ -182,6 +182,7 @@ struct script_op { #define OPK_C_SKIP_IF_UNBOUND 48 #define OPK_S_SET_INJECT_DATAGRAM 49 #define OPK_S_SHUTDOWN 50 +#define OPK_POP_ERR 51 #define EXPECT_CONN_CLOSE_APP (1U << 0) #define EXPECT_CONN_CLOSE_REMOTE (1U << 1) @@ -320,6 +321,8 @@ struct script_op { {OPK_S_SET_INJECT_DATAGRAM, NULL, 0, NULL, NULL, 0, NULL, NULL, (f)}, #define OP_S_SHUTDOWN(error_code) \ {OPK_S_SHUTDOWN, NULL, (error_code)}, +#define OP_POP_ERR() \ + {OPK_POP_ERR}, static OSSL_TIME get_time(void *arg) { @@ -1110,6 +1113,7 @@ static int run_script_worker(struct helper *h, const struct script_op *script, case OPK_C_EXPECT_SSL_ERR: case OPK_EXPECT_ERR_REASON: case OPK_EXPECT_ERR_LIB: + case OPK_POP_ERR: case OPK_SLEEP: break; @@ -1866,6 +1870,10 @@ static int run_script_worker(struct helper *h, const struct script_op *script, } break; + case OPK_POP_ERR: + ERR_pop(); + break; + case OPK_SLEEP: { OSSL_sleep(op->arg2); -- Gitee From 166d50852c759761941a4b9f1d126f7142ccf952 Mon Sep 17 00:00:00 2001 From: Hugo Landau Date: Thu, 9 Nov 2023 10:27:14 +0000 Subject: [PATCH 69/92] QUIC MULTISTREAM TEST: Make error tests non-mutating and restore error code test Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/22674) Signed-off-by: lanming1120 --- test/quic_multistream_test.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/test/quic_multistream_test.c b/test/quic_multistream_test.c index 3782e65286..2fe44cd26f 100644 --- a/test/quic_multistream_test.c +++ b/test/quic_multistream_test.c @@ -1858,14 +1858,14 @@ static int run_script_worker(struct helper *h, const struct script_op *script, case OPK_EXPECT_ERR_REASON: { - if (!TEST_size_t_eq((size_t)ERR_GET_REASON(ERR_get_error()), op->arg1)) + if (!TEST_size_t_eq((size_t)ERR_GET_REASON(ERR_peek_last_error()), op->arg1)) goto out; } break; case OPK_EXPECT_ERR_LIB: { - if (!TEST_size_t_eq((size_t)ERR_GET_LIB(ERR_get_error()), op->arg1)) + if (!TEST_size_t_eq((size_t)ERR_GET_LIB(ERR_peek_last_error()), op->arg1)) goto out; } break; @@ -2723,8 +2723,14 @@ static const struct script_op script_20_child[] = { OP_C_READ_FAIL_WAIT (a) OP_C_EXPECT_SSL_ERR (a, SSL_ERROR_SYSCALL) - OP_EXPECT_ERR_LIB (ERR_LIB_SYS) + + OP_EXPECT_ERR_LIB (ERR_LIB_SSL) + OP_EXPECT_ERR_REASON (SSL_R_PROTOCOL_IS_SHUTDOWN) + + OP_POP_ERR () + OP_EXPECT_ERR_LIB (ERR_LIB_SSL) OP_EXPECT_ERR_REASON (SSL_R_QUIC_NETWORK_ERROR) + OP_C_FREE_STREAM (a) OP_END -- Gitee From 003bb8bd63f14ea78a006aa8b497fbf83a2754d3 Mon Sep 17 00:00:00 2001 From: Hugo Landau Date: Thu, 9 Nov 2023 10:27:14 +0000 Subject: [PATCH 70/92] QUIC PORT: Allow errors to be tracked at port level Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/22674) Signed-off-by: lanming1120 --- include/internal/quic_port.h | 12 ++++++++++-- ssl/quic/quic_channel.c | 16 +++++++++------ ssl/quic/quic_port.c | 38 ++++++++++++++++++++++++++++++++---- ssl/quic/quic_port_local.h | 3 +++ 4 files changed, 57 insertions(+), 12 deletions(-) diff --git a/include/internal/quic_port.h b/include/internal/quic_port.h index ea97b93392..be08e213ee 100644 --- a/include/internal/quic_port.h +++ b/include/internal/quic_port.h @@ -133,6 +133,12 @@ void ossl_quic_port_set_inhibit_tick(QUIC_PORT *port, int inhibit); /* Returns 1 if the port is running/healthy, 0 if it has failed. */ int ossl_quic_port_is_running(const QUIC_PORT *port); +/* + * Restores port-level error to the error stack. To be called only if + * the port is no longer running. + */ +void ossl_quic_port_restore_err_state(const QUIC_PORT *port); + /* * Events * ====== @@ -140,9 +146,11 @@ int ossl_quic_port_is_running(const QUIC_PORT *port); /* * Called if a permanent network error occurs. Terminates all channels - * immediately. + * immediately. triggering_ch is an optional argument designating + * a channel which encountered the network error. */ -void ossl_quic_port_raise_net_error(QUIC_PORT *port); +void ossl_quic_port_raise_net_error(QUIC_PORT *port, + QUIC_CHANNEL *triggering_ch); # endif diff --git a/ssl/quic/quic_channel.c b/ssl/quic/quic_channel.c index aed911ad9f..5bcd66c9e4 100644 --- a/ssl/quic/quic_channel.c +++ b/ssl/quic/quic_channel.c @@ -2310,7 +2310,7 @@ static int ch_tx(QUIC_CHANNEL *ch) case QTX_FLUSH_NET_RES_PERMANENT_FAIL: default: /* Permanent underlying network BIO, start terminating. */ - ossl_quic_port_raise_net_error(ch->port); + ossl_quic_port_raise_net_error(ch->port, ch); break; } @@ -2927,13 +2927,14 @@ void ossl_quic_channel_raise_net_error(QUIC_CHANNEL *ch) { QUIC_TERMINATE_CAUSE tcause = {0}; - ch->net_error = 1; + if (ch->net_error) + return; - ERR_raise_data(ERR_LIB_SSL, SSL_R_QUIC_NETWORK_ERROR, - "connection terminated due to network error"); - ch_save_err_state(ch); + ch->net_error = 1; tcause.error_code = QUIC_ERR_INTERNAL_ERROR; + tcause.reason = "network BIO I/O error"; + tcause.reason_len = strlen(tcause.reason); /* * Skip Terminating state and go directly to Terminated, no point trying to @@ -2952,7 +2953,10 @@ void ossl_quic_channel_restore_err_state(QUIC_CHANNEL *ch) if (ch == NULL) return; - OSSL_ERR_STATE_restore(ch->err_state); + if (!ossl_quic_port_is_running(ch->port)) + ossl_quic_port_restore_err_state(ch->port); + else + OSSL_ERR_STATE_restore(ch->err_state); } void ossl_quic_channel_raise_protocol_error_loc(QUIC_CHANNEL *ch, diff --git a/ssl/quic/quic_port.c b/ssl/quic/quic_port.c index db1a352adf..e6dba46bf4 100644 --- a/ssl/quic/quic_port.c +++ b/ssl/quic/quic_port.c @@ -70,6 +70,9 @@ static int port_init(QUIC_PORT *port) if (port->channel_ctx == NULL) goto err; + if ((port->err_state = OSSL_ERR_STATE_new()) == NULL) + goto err; + if ((port->demux = ossl_quic_demux_new(/*BIO=*/NULL, /*Short CID Len=*/rx_short_dcid_len, get_time, port)) == NULL) @@ -108,6 +111,9 @@ static void port_cleanup(QUIC_PORT *port) ossl_quic_lcidm_free(port->lcidm); port->lcidm = NULL; + + OSSL_ERR_STATE_free(port->err_state); + port->err_state = NULL; } static void port_transition_failed(QUIC_PORT *port) @@ -341,7 +347,8 @@ static void port_tick(QUIC_TICK_RESULT *res, void *arg, uint32_t flags) if (!port->inhibit_tick) { /* Handle any incoming data from network. */ - port_rx_pre(port); + if (ossl_quic_port_is_running(port)) + port_rx_pre(port); /* Iterate through all channels and service them. */ LIST_FOREACH(ch, ch, &port->channel_list) { @@ -370,7 +377,7 @@ static void port_rx_pre(QUIC_PORT *port) * Terminated state as there is no point trying to send CONNECTION_CLOSE * frames if the network BIO is not operating correctly. */ - ossl_quic_port_raise_net_error(port); + ossl_quic_port_raise_net_error(port, NULL); } /* @@ -538,12 +545,35 @@ void ossl_quic_port_set_inhibit_tick(QUIC_PORT *port, int inhibit) port->inhibit_tick = (inhibit != 0); } -void ossl_quic_port_raise_net_error(QUIC_PORT *port) +void ossl_quic_port_raise_net_error(QUIC_PORT *port, + QUIC_CHANNEL *triggering_ch) { QUIC_CHANNEL *ch; + if (!ossl_quic_port_is_running(port)) + return; + + /* + * Immediately capture any triggering error on the error stack, with a + * cover error. + */ + ERR_raise_data(ERR_LIB_SSL, SSL_R_QUIC_NETWORK_ERROR, + "port failed due to network BIO I/O error"); + OSSL_ERR_STATE_save(port->err_state); + port_transition_failed(port); + /* Give the triggering channel (if any) the first notification. */ + if (triggering_ch != NULL) + ossl_quic_channel_raise_net_error(triggering_ch); + LIST_FOREACH(ch, ch, &port->channel_list) - ossl_quic_channel_raise_net_error(ch); + if (ch != triggering_ch) + ossl_quic_channel_raise_net_error(ch); +} + +void ossl_quic_port_restore_err_state(const QUIC_PORT *port) +{ + ERR_clear_error(); + OSSL_ERR_STATE_restore(port->err_state); } diff --git a/ssl/quic/quic_port_local.h b/ssl/quic/quic_port_local.h index a2937beeaf..38bb0193d8 100644 --- a/ssl/quic/quic_port_local.h +++ b/ssl/quic/quic_port_local.h @@ -71,6 +71,9 @@ struct quic_port_st { /* SRTM used for incoming packet routing by SRT. */ QUIC_SRTM *srtm; + /* Port-level permanent errors (causing failure state) are stored here. */ + ERR_STATE *err_state; + /* DCID length used for incoming short header packets. */ unsigned char rx_short_dcid_len; /* For clients, CID length used for outgoing Initial packets. */ -- Gitee From 67ed0ca1773d82374258061e2495038b55fa3615 Mon Sep 17 00:00:00 2001 From: Hugo Landau Date: Thu, 9 Nov 2023 10:27:14 +0000 Subject: [PATCH 71/92] MARKER: End of Phase 4: Finalization & SRT Handling Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/22674) Signed-off-by: lanming1120 -- Gitee From 340b544ebdbca800d87d5a6fef737a4724fc714d Mon Sep 17 00:00:00 2001 From: Hugo Landau Date: Thu, 9 Nov 2023 11:04:50 +0000 Subject: [PATCH 72/92] QUIC Refactor: Fix ANSI - struct definition duplications Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/22674) Signed-off-by: lanming1120 --- include/internal/quic_ackm.h | 3 +-- include/internal/quic_cc.h | 7 +++---- include/internal/quic_cfq.h | 2 +- include/internal/quic_channel.h | 2 -- include/internal/quic_demux.h | 6 +----- include/internal/quic_lcidm.h | 2 +- include/internal/quic_port.h | 2 -- include/internal/quic_predef.h | 1 + include/internal/quic_reactor.h | 9 +++++---- include/internal/quic_record_rx.h | 5 +++-- include/internal/quic_record_tx.h | 5 +++-- include/internal/quic_srtm.h | 2 +- include/internal/quic_statm.h | 5 +++-- include/internal/quic_stream.h | 3 +-- include/internal/quic_stream_map.h | 6 +++--- include/internal/quic_tls.h | 6 ++++-- include/internal/quic_txp.h | 3 +-- include/internal/quic_txpim.h | 3 +-- 18 files changed, 33 insertions(+), 39 deletions(-) diff --git a/include/internal/quic_ackm.h b/include/internal/quic_ackm.h index 03fc608867..69b862d9c5 100644 --- a/include/internal/quic_ackm.h +++ b/include/internal/quic_ackm.h @@ -13,13 +13,12 @@ # include "internal/quic_cc.h" # include "internal/quic_types.h" # include "internal/quic_wire.h" +# include "internal/quic_predef.h" # include "internal/time.h" # include "internal/list.h" # ifndef OPENSSL_NO_QUIC -typedef struct ossl_ackm_st OSSL_ACKM; - OSSL_ACKM *ossl_ackm_new(OSSL_TIME (*now)(void *arg), void *now_arg, OSSL_STATM *statm, diff --git a/include/internal/quic_cc.h b/include/internal/quic_cc.h index 60c710b0bd..dbd439dd0c 100644 --- a/include/internal/quic_cc.h +++ b/include/internal/quic_cc.h @@ -11,11 +11,10 @@ #include "openssl/params.h" #include "internal/time.h" +#include "internal/quic_predef.h" # ifndef OPENSSL_NO_QUIC -typedef struct ossl_cc_data_st OSSL_CC_DATA; - typedef struct ossl_cc_ack_info_st { /* The time the packet being acknowledged was originally sent. */ OSSL_TIME tx_time; @@ -80,7 +79,7 @@ typedef struct ossl_cc_ecn_info_st { */ #define OSSL_CC_LOST_FLAG_PERSISTENT_CONGESTION (1U << 0) -typedef struct ossl_cc_method_st { +struct ossl_cc_method_st { /* * Instantiation. */ @@ -209,7 +208,7 @@ typedef struct ossl_cc_method_st { */ int (*on_ecn)(OSSL_CC_DATA *ccdata, const OSSL_CC_ECN_INFO *info); -} OSSL_CC_METHOD; +}; extern const OSSL_CC_METHOD ossl_cc_dummy_method; extern const OSSL_CC_METHOD ossl_cc_newreno_method; diff --git a/include/internal/quic_cfq.h b/include/internal/quic_cfq.h index 22c436dc07..56ebcb930e 100644 --- a/include/internal/quic_cfq.h +++ b/include/internal/quic_cfq.h @@ -12,6 +12,7 @@ # include # include "internal/quic_types.h" +# include "internal/quic_predef.h" # ifndef OPENSSL_NO_QUIC @@ -63,7 +64,6 @@ int ossl_quic_cfq_item_is_unreliable(const QUIC_CFQ_ITEM *item); * QUIC Control Frame Queue * ======================== */ -typedef struct quic_cfq_st QUIC_CFQ; QUIC_CFQ *ossl_quic_cfq_new(void); void ossl_quic_cfq_free(QUIC_CFQ *cfq); diff --git a/include/internal/quic_channel.h b/include/internal/quic_channel.h index 0103b96eab..a745baedb6 100644 --- a/include/internal/quic_channel.h +++ b/include/internal/quic_channel.h @@ -120,8 +120,6 @@ typedef struct quic_channel_args_st { SSL *tls; } QUIC_CHANNEL_ARGS; -typedef struct quic_channel_st QUIC_CHANNEL; - /* Represents the cause for a connection's termination. */ typedef struct quic_terminate_cause_st { /* diff --git a/include/internal/quic_demux.h b/include/internal/quic_demux.h index 40a1bc412f..bc0ad95636 100644 --- a/include/internal/quic_demux.h +++ b/include/internal/quic_demux.h @@ -12,6 +12,7 @@ # include # include "internal/quic_types.h" +# include "internal/quic_predef.h" # include "internal/bio_addr.h" # include "internal/time.h" # include "internal/list.h" @@ -82,8 +83,6 @@ * same allocation. */ -typedef struct quic_urxe_st QUIC_URXE; - /* Maximum number of packets we allow to exist in one datagram. */ #define QUIC_MAX_PKT_PER_URXE (sizeof(uint64_t) * 8) @@ -158,9 +157,6 @@ void ossl_quic_urxe_remove(QUIC_URXE_LIST *l, QUIC_URXE *e); void ossl_quic_urxe_insert_head(QUIC_URXE_LIST *l, QUIC_URXE *e); void ossl_quic_urxe_insert_tail(QUIC_URXE_LIST *l, QUIC_URXE *e); -/* Opaque type representing a demuxer. */ -typedef struct quic_demux_st QUIC_DEMUX; - /* * Called when a datagram is received for a given connection ID. * diff --git a/include/internal/quic_lcidm.h b/include/internal/quic_lcidm.h index 9b11429814..4911e04230 100644 --- a/include/internal/quic_lcidm.h +++ b/include/internal/quic_lcidm.h @@ -15,6 +15,7 @@ # include "internal/time.h" # include "internal/quic_types.h" # include "internal/quic_wire.h" +# include "internal/quic_predef.h" # ifndef OPENSSL_NO_QUIC @@ -95,7 +96,6 @@ * An ODCID has no sequence number associated with it. It is the only CID to * lack one. */ -typedef struct quic_lcidm_st QUIC_LCIDM; /* * Creates a new LCIDM. lcid_len is the length to use for LCIDs in bytes, which diff --git a/include/internal/quic_port.h b/include/internal/quic_port.h index be08e213ee..9e52a1e77c 100644 --- a/include/internal/quic_port.h +++ b/include/internal/quic_port.h @@ -75,8 +75,6 @@ typedef struct quic_port_args_st { int is_multi_conn; } QUIC_PORT_ARGS; -typedef struct quic_port_st QUIC_PORT; - QUIC_PORT *ossl_quic_port_new(const QUIC_PORT_ARGS *args); void ossl_quic_port_free(QUIC_PORT *port); diff --git a/include/internal/quic_predef.h b/include/internal/quic_predef.h index 2512810afa..6f8f8e5c93 100644 --- a/include/internal/quic_predef.h +++ b/include/internal/quic_predef.h @@ -16,6 +16,7 @@ typedef struct quic_port_st QUIC_PORT; typedef struct quic_channel_st QUIC_CHANNEL; typedef struct quic_tls_st QUIC_TLS; typedef struct quic_txpim_st QUIC_TXPIM; +typedef struct quic_fifd_st QUIC_FIFD; typedef struct quic_cfq_st QUIC_CFQ; typedef struct ossl_quic_tx_packetiser_st OSSL_QUIC_TX_PACKETISER; typedef struct ossl_ackm_st OSSL_ACKM; diff --git a/include/internal/quic_reactor.h b/include/internal/quic_reactor.h index bffbf50d8b..10d54ee156 100644 --- a/include/internal/quic_reactor.h +++ b/include/internal/quic_reactor.h @@ -11,6 +11,7 @@ # include "internal/time.h" # include "internal/sockets.h" +# include "internal/quic_predef.h" # include # ifndef OPENSSL_NO_QUIC @@ -67,11 +68,11 @@ * adaptation layer on top of our internal asynchronous I/O API as exposed by * the reactor interface. */ -typedef struct quic_tick_result_st { +struct quic_tick_result_st { char net_read_desired; char net_write_desired; OSSL_TIME tick_deadline; -} QUIC_TICK_RESULT; +}; static ossl_inline ossl_unused void ossl_quic_tick_result_merge_into(QUIC_TICK_RESULT *r, @@ -82,7 +83,7 @@ ossl_quic_tick_result_merge_into(QUIC_TICK_RESULT *r, r->tick_deadline = ossl_time_min(r->tick_deadline, src->tick_deadline); } -typedef struct quic_reactor_st { +struct quic_reactor_st { /* * BIO poll descriptors which can be polled. poll_r is a poll descriptor * which becomes readable when the QUIC state machine can potentially do @@ -110,7 +111,7 @@ typedef struct quic_reactor_st { */ unsigned int can_poll_r : 1; unsigned int can_poll_w : 1; -} QUIC_REACTOR; +}; void ossl_quic_reactor_init(QUIC_REACTOR *rtor, void (*tick_cb)(QUIC_TICK_RESULT *res, void *arg, diff --git a/include/internal/quic_record_rx.h b/include/internal/quic_record_rx.h index cc2d6e94d8..24c2bbc8ae 100644 --- a/include/internal/quic_record_rx.h +++ b/include/internal/quic_record_rx.h @@ -13,6 +13,7 @@ # include # include "internal/quic_wire_pkt.h" # include "internal/quic_types.h" +# include "internal/quic_predef.h" # include "internal/quic_record_util.h" # include "internal/quic_demux.h" @@ -178,7 +179,7 @@ int ossl_qrx_discard_enc_level(OSSL_QRX *qrx, uint32_t enc_level); */ /* Information about a received packet. */ -typedef struct ossl_qrx_pkt_st { +struct ossl_qrx_pkt_st { /* * Points to a logical representation of the decoded QUIC packet header. The * data and len fields point to the decrypted QUIC payload (i.e., to a @@ -224,7 +225,7 @@ typedef struct ossl_qrx_pkt_st { * packets. */ uint64_t key_epoch; -} OSSL_QRX_PKT; +}; /* * Tries to read a new decrypted packet from the QRX. diff --git a/include/internal/quic_record_tx.h b/include/internal/quic_record_tx.h index f3b798fea0..0688998326 100644 --- a/include/internal/quic_record_tx.h +++ b/include/internal/quic_record_tx.h @@ -13,6 +13,7 @@ # include # include "internal/quic_wire_pkt.h" # include "internal/quic_types.h" +# include "internal/quic_predef.h" # include "internal/quic_record_util.h" # ifndef OPENSSL_NO_QUIC @@ -148,7 +149,7 @@ uint32_t ossl_qrl_get_suite_cipher_tag_len(uint32_t suite_id); * ------------------- */ -typedef struct ossl_qtx_pkt_st { +struct ossl_qtx_pkt_st { /* Logical packet header to be serialized. */ QUIC_PKT_HDR *hdr; @@ -176,7 +177,7 @@ typedef struct ossl_qtx_pkt_st { /* Packet flags. Zero or more OSSL_QTX_PKT_FLAG_* values. */ uint32_t flags; -} OSSL_QTX_PKT; +}; /* * More packets will be written which should be coalesced into a single diff --git a/include/internal/quic_srtm.h b/include/internal/quic_srtm.h index 9a2c18fdf3..830c399275 100644 --- a/include/internal/quic_srtm.h +++ b/include/internal/quic_srtm.h @@ -15,6 +15,7 @@ # include "internal/time.h" # include "internal/quic_types.h" # include "internal/quic_wire.h" +# include "internal/quic_predef.h" # ifndef OPENSSL_NO_QUIC @@ -53,7 +54,6 @@ * The opaque pointer may be used for any purpose but is intended to represent a * connection identity and must therefore be consistent (usefully comparable). */ -typedef struct quic_srtm_st QUIC_SRTM; /* Creates a new empty SRTM instance. */ QUIC_SRTM *ossl_quic_srtm_new(OSSL_LIB_CTX *libctx, const char *propq); diff --git a/include/internal/quic_statm.h b/include/internal/quic_statm.h index 5b33551b06..2fca69b0d1 100644 --- a/include/internal/quic_statm.h +++ b/include/internal/quic_statm.h @@ -12,13 +12,14 @@ # include # include "internal/time.h" +# include "internal/quic_predef.h" # ifndef OPENSSL_NO_QUIC -typedef struct ossl_statm_st { +struct ossl_statm_st { OSSL_TIME smoothed_rtt, latest_rtt, min_rtt, rtt_variance; char have_first_sample; -} OSSL_STATM; +}; typedef struct ossl_rtt_info_st { /* As defined in RFC 9002. */ diff --git a/include/internal/quic_stream.h b/include/internal/quic_stream.h index 0da8febd5a..d446dadc50 100644 --- a/include/internal/quic_stream.h +++ b/include/internal/quic_stream.h @@ -14,6 +14,7 @@ #include "internal/e_os.h" #include "internal/time.h" #include "internal/quic_types.h" +#include "internal/quic_predef.h" #include "internal/quic_wire.h" #include "internal/quic_record_tx.h" #include "internal/quic_record_rx.h" @@ -51,7 +52,6 @@ * datagrams. The terms 'send' and 'receive' are used when referring to the * stream abstraction. Applications send; we transmit. */ -typedef struct quic_sstream_st QUIC_SSTREAM; /* * Instantiates a new QUIC_SSTREAM. init_buf_size specifies the initial size of @@ -312,7 +312,6 @@ void ossl_quic_sstream_set_cleanse(QUIC_SSTREAM *qss, int cleanse); * (i.e., for a unidirectional receiving stream or for the receiving component * of a bidirectional stream). */ -typedef struct quic_rstream_st QUIC_RSTREAM; /* * Create a new instance of QUIC_RSTREAM with pointers to the flow diff --git a/include/internal/quic_stream_map.h b/include/internal/quic_stream_map.h index ae7490619b..9d860f6d1f 100644 --- a/include/internal/quic_stream_map.h +++ b/include/internal/quic_stream_map.h @@ -15,6 +15,7 @@ # include "internal/time.h" # include "internal/common.h" # include "internal/quic_types.h" +# include "internal/quic_predef.h" # include "internal/quic_stream.h" # include "internal/quic_fc.h" # include @@ -27,7 +28,6 @@ * * Logical QUIC stream composing all relevant send and receive components. */ -typedef struct quic_stream_st QUIC_STREAM; typedef struct quic_stream_list_node_st QUIC_STREAM_LIST_NODE; @@ -514,7 +514,7 @@ static ossl_inline ossl_unused int ossl_quic_stream_recv_get_final_size(const QU * - allows iteration over the active streams only. * */ -typedef struct quic_stream_map_st { +struct quic_stream_map_st { LHASH_OF(QUIC_STREAM) *map; QUIC_STREAM_LIST_NODE active_list; QUIC_STREAM_LIST_NODE accept_list; @@ -527,7 +527,7 @@ typedef struct quic_stream_map_st { QUIC_RXFC *max_streams_bidi_rxfc; QUIC_RXFC *max_streams_uni_rxfc; int is_server; -} QUIC_STREAM_MAP; +}; /* * get_stream_limit is a callback which is called to retrieve the current stream diff --git a/include/internal/quic_tls.h b/include/internal/quic_tls.h index 0e4a9d339b..f9f007a76c 100644 --- a/include/internal/quic_tls.h +++ b/include/internal/quic_tls.h @@ -12,9 +12,9 @@ # include # include "internal/quic_stream.h" +# include "internal/quic_predef.h" - -typedef struct quic_tls_st QUIC_TLS; +# ifndef OPENSSL_NO_QUIC typedef struct quic_tls_args_st { /* @@ -103,4 +103,6 @@ int ossl_quic_tls_get_error(QUIC_TLS *qtls, int ossl_quic_tls_is_cert_request(QUIC_TLS *qtls); int ossl_quic_tls_has_bad_max_early_data(QUIC_TLS *qtls); +# endif + #endif diff --git a/include/internal/quic_txp.h b/include/internal/quic_txp.h index ae508f2393..7c00c41419 100644 --- a/include/internal/quic_txp.h +++ b/include/internal/quic_txp.h @@ -12,6 +12,7 @@ # include # include "internal/quic_types.h" +# include "internal/quic_predef.h" # include "internal/quic_record_tx.h" # include "internal/quic_cfq.h" # include "internal/quic_txpim.h" @@ -59,8 +60,6 @@ typedef struct ossl_quic_tx_packetiser_args_st { } OSSL_QUIC_TX_PACKETISER_ARGS; -typedef struct ossl_quic_tx_packetiser_st OSSL_QUIC_TX_PACKETISER; - OSSL_QUIC_TX_PACKETISER *ossl_quic_tx_packetiser_new(const OSSL_QUIC_TX_PACKETISER_ARGS *args); typedef void (ossl_quic_initial_token_free_fn)(const unsigned char *buf, diff --git a/include/internal/quic_txpim.h b/include/internal/quic_txpim.h index ed6e3875c4..efe1ca6302 100644 --- a/include/internal/quic_txpim.h +++ b/include/internal/quic_txpim.h @@ -12,6 +12,7 @@ # include # include "internal/quic_types.h" +# include "internal/quic_predef.h" # include "internal/quic_cfq.h" # include "internal/quic_ackm.h" @@ -21,8 +22,6 @@ * QUIC Transmitted Packet Information Manager * =========================================== */ -typedef struct quic_txpim_st QUIC_TXPIM; -typedef struct quic_fifd_st QUIC_FIFD; typedef struct quic_txpim_pkt_st { /* ACKM-specific data. Caller should fill this. */ -- Gitee From d7e8be975a74793e24bd5b164b2266212173a0b3 Mon Sep 17 00:00:00 2001 From: Hugo Landau Date: Thu, 9 Nov 2023 15:30:15 +0000 Subject: [PATCH 73/92] QUIC PORT: Fix BIO_dgram usage under Winsock due to bind requirement Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/22674) Signed-off-by: lanming1120 --- ssl/quic/quic_channel.c | 1 + ssl/quic/quic_port.c | 20 ++++++++++++++++++++ ssl/quic/quic_port_local.h | 6 ++++++ 3 files changed, 27 insertions(+) diff --git a/ssl/quic/quic_channel.c b/ssl/quic/quic_channel.c index 5bcd66c9e4..60bcc88f84 100644 --- a/ssl/quic/quic_channel.c +++ b/ssl/quic/quic_channel.c @@ -2255,6 +2255,7 @@ static int ch_tx(QUIC_CHANNEL *ch) res = ossl_quic_tx_packetiser_generate(ch->txp, &status); if (status.sent_pkt > 0) { ch->have_sent_any_pkt = 1; /* Packet(s) were sent */ + ch->port->have_sent_any_pkt = 1; /* * RFC 9000 s. 10.1. 'An endpoint also restarts its idle timer when diff --git a/ssl/quic/quic_port.c b/ssl/quic/quic_port.c index e6dba46bf4..46f4b34f9b 100644 --- a/ssl/quic/quic_port.c +++ b/ssl/quic/quic_port.c @@ -323,6 +323,7 @@ QUIC_CHANNEL *ossl_quic_port_create_incoming(QUIC_PORT *port, SSL *tls) ch = port_make_channel(port, tls, /*is_server=*/1); port->tserver_ch = ch; + port->is_server = 1; return ch; } @@ -365,6 +366,25 @@ static void port_rx_pre(QUIC_PORT *port) { int ret; + /* + * Originally, this check (don't RX before we have sent anything if we are + * not a server, because there can't be anything) was just intended as a + * minor optimisation. However, it is actually required on Windows, and + * removing this check will cause Windows to break. + * + * The reason is that under Win32, recvfrom() does not work on a UDP socket + * which has not had bind() called (???). However, calling sendto() will + * automatically bind an unbound UDP socket. Therefore, if we call a Winsock + * recv-type function before calling a Winsock send-type function, that call + * will fail with WSAEINVAL, which we will regard as a permanent network + * error. + * + * Therefore, this check is essential as we do not require our API users to + * bind a socket first when using the API in client mode. + */ + if (!port->is_server && !port->have_sent_any_pkt) + return; + /* * Get DEMUX to BIO_recvmmsg from the network and queue incoming datagrams * to the appropriate QRX instances. diff --git a/ssl/quic/quic_port_local.h b/ssl/quic/quic_port_local.h index 38bb0193d8..968a48ac42 100644 --- a/ssl/quic/quic_port_local.h +++ b/ssl/quic/quic_port_local.h @@ -87,6 +87,12 @@ struct quic_port_st { /* Inhibit tick for testing purposes? */ unsigned int inhibit_tick : 1; + + /* Has this port sent any packet of any kind yet? */ + unsigned int have_sent_any_pkt : 1; + + /* Does this port allow incoming connections? */ + unsigned int is_server : 1; }; # endif -- Gitee From af20d4b400b940b5f3bf116cb5c5f43a9e03efeb Mon Sep 17 00:00:00 2001 From: Hugo Landau Date: Fri, 10 Nov 2023 10:33:13 +0000 Subject: [PATCH 74/92] Update fuzz corpora Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/22674) Signed-off-by: lanming1120 -- Gitee From a704416faa4f488da0e9741c263db54d3997c2c5 Mon Sep 17 00:00:00 2001 From: Hugo Landau Date: Fri, 10 Nov 2023 12:34:56 +0000 Subject: [PATCH 75/92] QUIC PORT: Add missing copyright header Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/22674) Signed-off-by: lanming1120 --- ssl/quic/quic_port_local.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/ssl/quic/quic_port_local.h b/ssl/quic/quic_port_local.h index 968a48ac42..8df3c4ca94 100644 --- a/ssl/quic/quic_port_local.h +++ b/ssl/quic/quic_port_local.h @@ -1,3 +1,12 @@ +/* + * Copyright 2023 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + #ifndef OSSL_QUIC_PORT_LOCAL_H # define OSSL_QUIC_PORT_LOCAL_H -- Gitee From 4f780b62f35afbe9a20d3fd054baaee1b6bcc69c Mon Sep 17 00:00:00 2001 From: Hugo Landau Date: Fri, 10 Nov 2023 12:40:12 +0000 Subject: [PATCH 76/92] QUIC CHANNEL: Remove obsolete SRT definitions Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/22674) Signed-off-by: lanming1120 --- ssl/quic/quic_channel_local.h | 8 -------- 1 file changed, 8 deletions(-) diff --git a/ssl/quic/quic_channel_local.h b/ssl/quic/quic_channel_local.h index 2338f6b262..cd9fe276a5 100644 --- a/ssl/quic/quic_channel_local.h +++ b/ssl/quic/quic_channel_local.h @@ -11,14 +11,6 @@ # include "internal/quic_fc.h" # include "internal/quic_stream_map.h" -struct quic_srt_elem_st { - OSSL_LIST_MEMBER(stateless_reset_tokens, QUIC_SRT_ELEM); - QUIC_STATELESS_RESET_TOKEN token; - uint64_t seq_num; -}; - -DEFINE_LIST_OF(stateless_reset_tokens, QUIC_SRT_ELEM); - /* * QUIC Channel Structure * ====================== -- Gitee From 1e8d3c55f2db3fa860485be2e96751c86b34b678 Mon Sep 17 00:00:00 2001 From: Hugo Landau Date: Fri, 10 Nov 2023 12:53:39 +0000 Subject: [PATCH 77/92] QUIC ENGINE: Add unused QUIC_ENGINE object Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/22674) Signed-off-by: lanming1120 --- include/internal/quic_engine.h | 80 +++++++++++++++++++ include/internal/quic_port.h | 13 ++++ include/internal/quic_predef.h | 1 + ssl/quic/build.info | 2 +- ssl/quic/quic_engine.c | 137 +++++++++++++++++++++++++++++++++ ssl/quic/quic_engine_local.h | 58 ++++++++++++++ ssl/quic/quic_port.c | 37 +++++++-- ssl/quic/quic_port_local.h | 12 +++ 8 files changed, 332 insertions(+), 8 deletions(-) create mode 100644 include/internal/quic_engine.h create mode 100644 ssl/quic/quic_engine.c create mode 100644 ssl/quic/quic_engine_local.h diff --git a/include/internal/quic_engine.h b/include/internal/quic_engine.h new file mode 100644 index 0000000000..a08f76e53f --- /dev/null +++ b/include/internal/quic_engine.h @@ -0,0 +1,80 @@ +/* + * Copyright 2023 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ +#ifndef OSSL_QUIC_ENGINE_H +# define OSSL_QUIC_ENGINE_H + +# include + +# include "internal/quic_predef.h" +# include "internal/quic_port.h" +# include "internal/thread_arch.h" + +# ifndef OPENSSL_NO_QUIC + +/* + * QUIC Engine + * =========== + * + * A QUIC Engine (QUIC_ENGINE) represents an event processing domain for the + * purposes of QUIC and contains zero or more subsidiary QUIC_PORT instances + * (each of which currently represents a UDP socket), each of which in turn + * contains zero or more subsidiary QUIC_CHANNEL instances, each of which + * represents a single QUIC connection. All QUIC_PORT instances must belong + * to a QUIC_ENGINE. + * + * A QUIC engine is the root engine in a QUIC event domain, and is responsible + * for managing event processing for all QUIC ports and channels (e.g. timeouts, + * clock management, the QUIC_REACTOR instance, etc.). + */ +typedef struct quic_engine_args_st { + OSSL_LIB_CTX *libctx; + const char *propq; + + /* + * This must be a mutex the lifetime of which will exceed that of the port + * and all channels. The instantiator of the port is responsible for + * providing a mutex as this makes it easier to handle instantiation and + * teardown of channels in situations potentially requiring locking. + * + * Note that this is a MUTEX not a RWLOCK as it needs to be an OS mutex for + * compatibility with an OS's condition variable wait API, whereas RWLOCK + * may, depending on the build configuration, be implemented using an OS's + * mutex primitive or using its RW mutex primitive. + */ + CRYPTO_MUTEX *mutex; + + OSSL_TIME (*now_cb)(void *arg); + void *now_cb_arg; +} QUIC_ENGINE_ARGS; + +QUIC_ENGINE *ossl_quic_engine_new(const QUIC_ENGINE_ARGS *args); + +void ossl_quic_engine_free(QUIC_ENGINE *qeng); + +/* + * Create a port which is a child of the engine. args->engine shall be NULL. + */ +QUIC_PORT *ossl_quic_engine_create_port(QUIC_ENGINE *qeng, + const QUIC_PORT_ARGS *args); + +/* Gets the mutex used by the engine. */ +CRYPTO_MUTEX *ossl_quic_engine_get0_mutex(QUIC_ENGINE *qeng); + +/* Gets the current time. */ +OSSL_TIME ossl_quic_engine_get_time(QUIC_ENGINE *qeng); + +/* For testing use. While enabled, ticking is not performed. */ +void ossl_quic_engine_set_inhibit_tick(QUIC_ENGINE *qeng, int inhibit); + +/* Gets the reactor which can be used to tick/poll on the port. */ +QUIC_REACTOR *ossl_quic_engine_get0_reactor(QUIC_ENGINE *qeng); + +# endif + +#endif diff --git a/include/internal/quic_port.h b/include/internal/quic_port.h index 9e52a1e77c..74578e9267 100644 --- a/include/internal/quic_port.h +++ b/include/internal/quic_port.h @@ -35,8 +35,13 @@ * of legacy compatibility where a caller can create an incoming (server role) * channel and that channel will be automatically be bound to the next incoming * connection. In the future this will go away once QUIC_TSERVER is removed. + * + * All QUIC_PORT instances are created by a QUIC_ENGINE. */ typedef struct quic_port_args_st { + /* The engine which the QUIC port is to be a child of. */ + QUIC_ENGINE *engine; + /* All channels in a QUIC event domain share the same (libctx, propq). */ OSSL_LIB_CTX *libctx; const char *propq; @@ -75,6 +80,7 @@ typedef struct quic_port_args_st { int is_multi_conn; } QUIC_PORT_ARGS; +/* Only QUIC_ENGINE should use this function. */ QUIC_PORT *ossl_quic_port_new(const QUIC_PORT_ARGS *args); void ossl_quic_port_free(QUIC_PORT *port); @@ -110,6 +116,9 @@ int ossl_quic_port_set_net_wbio(QUIC_PORT *port, BIO *net_wbio); */ int ossl_quic_port_update_poll_descriptors(QUIC_PORT *port); +/* Gets the engine which this port is a child of. */ +QUIC_ENGINE *ossl_quic_port_get0_engine(QUIC_PORT *port); + /* Gets the reactor which can be used to tick/poll on the port. */ QUIC_REACTOR *ossl_quic_port_get0_reactor(QUIC_PORT *port); @@ -137,6 +146,10 @@ int ossl_quic_port_is_running(const QUIC_PORT *port); */ void ossl_quic_port_restore_err_state(const QUIC_PORT *port); +/* For use by QUIC_ENGINE. You should not need to call this directly. */ +void ossl_quic_port_subtick(QUIC_PORT *port, QUIC_TICK_RESULT *r, + uint32_t flags); + /* * Events * ====== diff --git a/include/internal/quic_predef.h b/include/internal/quic_predef.h index 6f8f8e5c93..7c7567b9c5 100644 --- a/include/internal/quic_predef.h +++ b/include/internal/quic_predef.h @@ -36,6 +36,7 @@ typedef struct quic_tick_result_st QUIC_TICK_RESULT; typedef struct quic_srtm_st QUIC_SRTM; typedef struct quic_lcidm_st QUIC_LCIDM; typedef struct quic_urxe_st QUIC_URXE; +typedef struct quic_engine_st QUIC_ENGINE; # endif diff --git a/ssl/quic/build.info b/ssl/quic/build.info index d837fc764b..bb6739b18b 100644 --- a/ssl/quic/build.info +++ b/ssl/quic/build.info @@ -9,7 +9,7 @@ SOURCE[$LIBSSL]=quic_cfq.c quic_txpim.c quic_fifd.c quic_txp.c SOURCE[$LIBSSL]=quic_stream_map.c SOURCE[$LIBSSL]=quic_sf_list.c quic_rstream.c quic_sstream.c SOURCE[$LIBSSL]=quic_reactor.c -SOURCE[$LIBSSL]=quic_channel.c quic_port.c +SOURCE[$LIBSSL]=quic_channel.c quic_port.c quic_engine.c SOURCE[$LIBSSL]=quic_tserver.c SOURCE[$LIBSSL]=quic_tls.c SOURCE[$LIBSSL]=quic_thread_assist.c diff --git a/ssl/quic/quic_engine.c b/ssl/quic/quic_engine.c new file mode 100644 index 0000000000..26c859e595 --- /dev/null +++ b/ssl/quic/quic_engine.c @@ -0,0 +1,137 @@ +/* + * Copyright 2023 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 + */ + +#include "internal/quic_engine.h" +#include "internal/quic_port.h" +#include "quic_engine_local.h" +#include "quic_port_local.h" +#include "../ssl_local.h" + +/* + * QUIC Engine + * =========== + */ +static int qeng_init(QUIC_ENGINE *qeng); +static void qeng_cleanup(QUIC_ENGINE *qeng); +static void qeng_tick(QUIC_TICK_RESULT *res, void *arg, uint32_t flags); + +DEFINE_LIST_OF_IMPL(port, QUIC_PORT); + +QUIC_ENGINE *ossl_quic_engine_new(const QUIC_ENGINE_ARGS *args) +{ + QUIC_ENGINE *qeng; + + if ((qeng = OPENSSL_zalloc(sizeof(QUIC_ENGINE))) == NULL) + return NULL; + + qeng->libctx = args->libctx; + qeng->propq = args->propq; + qeng->mutex = args->mutex; + qeng->now_cb = args->now_cb; + qeng->now_cb_arg = args->now_cb_arg; + + if (!qeng_init(qeng)) { + OPENSSL_free(qeng); + return NULL; + } + + return qeng; +} + +void ossl_quic_engine_free(QUIC_ENGINE *qeng) +{ + if (qeng == NULL) + return; + + qeng_cleanup(qeng); + OPENSSL_free(qeng); +} + +static int qeng_init(QUIC_ENGINE *qeng) +{ + ossl_quic_reactor_init(&qeng->rtor, qeng_tick, qeng, ossl_time_zero()); + return 1; +} + +static void qeng_cleanup(QUIC_ENGINE *qeng) +{ + assert(ossl_list_port_num(&qeng->port_list) == 0); +} + +QUIC_REACTOR *ossl_quic_engine_get0_reactor(QUIC_ENGINE *qeng) + +{ + return &qeng->rtor; +} + +CRYPTO_MUTEX *ossl_quic_engine_get0_mutex(QUIC_ENGINE *qeng) +{ + return qeng->mutex; +} + +OSSL_TIME ossl_quic_engine_get_time(QUIC_ENGINE *qeng) +{ + if (qeng->now_cb == NULL) + return ossl_time_now(); + + return qeng->now_cb(qeng->now_cb_arg); +} + +void ossl_quic_engine_set_inhibit_tick(QUIC_ENGINE *qeng, int inhibit) +{ + qeng->inhibit_tick = (inhibit != 0); +} + +/* + * QUIC Engine: Child Object Lifecycle Management + * ============================================== + */ + +QUIC_PORT *ossl_quic_engine_create_port(QUIC_ENGINE *qeng, + const QUIC_PORT_ARGS *args) +{ + QUIC_PORT_ARGS largs = *args; + + if (largs.engine != NULL) + return NULL; + + largs.engine = qeng; + return ossl_quic_port_new(&largs); +} + +/* + * QUIC Engine: Ticker-Mutator + * ========================== + */ + +/* + * The central ticker function called by the reactor. This does everything, or + * at least everything network I/O related. Best effort - not allowed to fail + * "loudly". + */ +static void qeng_tick(QUIC_TICK_RESULT *res, void *arg, uint32_t flags) +{ + QUIC_ENGINE *qeng = arg; + QUIC_PORT *port; + + res->net_read_desired = 0; + res->net_write_desired = 0; + res->tick_deadline = ossl_time_infinite(); + + if (qeng->inhibit_tick) + return; + + /* Iterate through all ports and service them. */ + LIST_FOREACH(port, port, &qeng->port_list) { + QUIC_TICK_RESULT subr = {0}; + + ossl_quic_port_subtick(port, &subr, flags); + ossl_quic_tick_result_merge_into(res, &subr); + } +} diff --git a/ssl/quic/quic_engine_local.h b/ssl/quic/quic_engine_local.h new file mode 100644 index 0000000000..6896e30d85 --- /dev/null +++ b/ssl/quic/quic_engine_local.h @@ -0,0 +1,58 @@ +/* + * Copyright 2023 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#ifndef OSSL_QUIC_ENGINE_LOCAL_H +# define OSSL_QUIC_ENGINE_LOCAL_H + +# include "internal/quic_engine.h" +# include "internal/quic_reactor.h" + +# ifndef OPENSSL_NO_QUIC + +/* + * QUIC Engine Structure + * ===================== + * + * QUIC engine internals. It is intended that only the QUIC_ENGINE, QUIC_PORT + * and QUIC_CHANNEL implementations be allowed to access this structure + * directly. + * + * Other components should not include this header. + */ +DECLARE_LIST_OF(port, QUIC_PORT); + +struct quic_engine_st { + OSSL_LIB_CTX *libctx; + const char *propq; + + /* + * Master synchronisation mutex for the entire QUIC event domain. Used for + * thread assisted mode synchronisation. We don't own this; the instantiator + * of the port passes it to us and is responsible for freeing it after port + * destruction. + */ + CRYPTO_MUTEX *mutex; + + /* Callback used to get the current time. */ + OSSL_TIME (*now_cb)(void *arg); + void *now_cb_arg; + + /* Asynchronous I/O reactor. */ + QUIC_REACTOR rtor; + + /* List of all child ports. */ + OSSL_LIST(port) port_list; + + /* Inhibit tick for testing purposes? */ + unsigned int inhibit_tick : 1; +}; + +# endif + +#endif diff --git a/ssl/quic/quic_port.c b/ssl/quic/quic_port.c index 46f4b34f9b..897edc4a79 100644 --- a/ssl/quic/quic_port.c +++ b/ssl/quic/quic_port.c @@ -13,6 +13,7 @@ #include "internal/quic_srtm.h" #include "quic_port_local.h" #include "quic_channel_local.h" +#include "quic_engine_local.h" #include "../ssl_local.h" /* @@ -24,12 +25,13 @@ static int port_init(QUIC_PORT *port); static void port_cleanup(QUIC_PORT *port); static OSSL_TIME get_time(void *arg); -static void port_tick(QUIC_TICK_RESULT *res, void *arg, uint32_t flags); static void port_default_packet_handler(QUIC_URXE *e, void *arg, const QUIC_CONN_ID *dcid); static void port_rx_pre(QUIC_PORT *port); +static void port_tick(QUIC_TICK_RESULT *res, void *arg, uint32_t flags); DEFINE_LIST_OF_IMPL(ch, QUIC_CHANNEL); +DEFINE_LIST_OF_IMPL(port, QUIC_PORT); QUIC_PORT *ossl_quic_port_new(const QUIC_PORT_ARGS *args) { @@ -38,6 +40,7 @@ QUIC_PORT *ossl_quic_port_new(const QUIC_PORT_ARGS *args) if ((port = OPENSSL_zalloc(sizeof(QUIC_PORT))) == NULL) return NULL; + port->engine = args->engine; port->libctx = args->libctx; port->propq = args->propq; port->mutex = args->mutex; @@ -88,10 +91,16 @@ static int port_init(QUIC_PORT *port) if ((port->lcidm = ossl_quic_lcidm_new(port->libctx, rx_short_dcid_len)) == NULL) goto err; - ossl_quic_reactor_init(&port->rtor, port_tick, port, ossl_time_zero()); + if (port->engine == NULL) + ossl_quic_reactor_init(&port->rtor, port_tick, port, ossl_time_zero()); + port->rx_short_dcid_len = (unsigned char)rx_short_dcid_len; port->tx_init_dcid_len = INIT_DCID_LEN; port->state = QUIC_PORT_STATE_RUNNING; + if (port->engine != NULL) { + ossl_list_port_insert_tail(&port->engine->port_list, port); + port->on_engine_list = 1; + } return 1; err: @@ -114,6 +123,11 @@ static void port_cleanup(QUIC_PORT *port) OSSL_ERR_STATE_free(port->err_state); port->err_state = NULL; + + if (port->on_engine_list) { + ossl_list_port_remove(&port->engine->port_list, port); + port->on_engine_list = 0; + } } static void port_transition_failed(QUIC_PORT *port) @@ -129,9 +143,14 @@ int ossl_quic_port_is_running(const QUIC_PORT *port) return port->state == QUIC_PORT_STATE_RUNNING; } +QUIC_ENGINE *ossl_quic_port_get0_engine(QUIC_PORT *port) +{ + return port->engine; +} + QUIC_REACTOR *ossl_quic_port_get0_reactor(QUIC_PORT *port) { - return &port->rtor; + return port->engine != NULL ? &port->engine->rtor : &port->rtor; } QUIC_DEMUX *ossl_quic_port_get0_demux(QUIC_PORT *port) @@ -333,13 +352,17 @@ QUIC_CHANNEL *ossl_quic_port_create_incoming(QUIC_PORT *port, SSL *tls) */ /* - * The central ticker function called by the reactor. This does everything, or - * at least everything network I/O related. Best effort - not allowed to fail - * "loudly". + * Tick function for this port. This does everything related to network I/O for + * this port's network BIOs, and services child channels. */ static void port_tick(QUIC_TICK_RESULT *res, void *arg, uint32_t flags) { - QUIC_PORT *port = arg; + ossl_quic_port_subtick(arg, res, flags); +} + +void ossl_quic_port_subtick(QUIC_PORT *port, QUIC_TICK_RESULT *res, + uint32_t flags) +{ QUIC_CHANNEL *ch; res->net_read_desired = 0; diff --git a/ssl/quic/quic_port_local.h b/ssl/quic/quic_port_local.h index 8df3c4ca94..ec12872b72 100644 --- a/ssl/quic/quic_port_local.h +++ b/ssl/quic/quic_port_local.h @@ -41,6 +41,15 @@ enum { }; struct quic_port_st { + /* The engine which this port is a child of. */ + QUIC_ENGINE *engine; + + /* + * QUIC_ENGINE keeps the channels which belong to it on a list for + * bookkeeping purposes. + */ + OSSL_LIST_MEMBER(port, QUIC_PORT); + OSSL_LIB_CTX *libctx; const char *propq; @@ -102,6 +111,9 @@ struct quic_port_st { /* Does this port allow incoming connections? */ unsigned int is_server : 1; + + /* Are we on the QUIC_ENGINE linked list of ports? */ + unsigned int on_engine_list : 1; }; # endif -- Gitee From dbdd279561c83033c25e75036ecc330c630761ce Mon Sep 17 00:00:00 2001 From: Hugo Landau Date: Fri, 10 Nov 2023 13:36:29 +0000 Subject: [PATCH 78/92] QUIC APL, TSERVER: Start using a QUIC_ENGINE object Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/22674) Signed-off-by: lanming1120 --- include/internal/quic_channel.h | 1 + include/internal/quic_port.h | 27 ----------------- ssl/quic/quic_channel.c | 34 +++++++++++++--------- ssl/quic/quic_engine.c | 4 +++ ssl/quic/quic_engine_local.h | 1 + ssl/quic/quic_impl.c | 26 +++++++++++------ ssl/quic/quic_local.h | 3 ++ ssl/quic/quic_port.c | 51 +++++++++++++-------------------- ssl/quic/quic_port_local.h | 21 -------------- ssl/quic/quic_tserver.c | 27 +++++++++++------ test/quic_multistream_test.c | 8 +++--- 11 files changed, 89 insertions(+), 114 deletions(-) diff --git a/include/internal/quic_channel.h b/include/internal/quic_channel.h index a745baedb6..b6b3e28352 100644 --- a/include/internal/quic_channel.h +++ b/include/internal/quic_channel.h @@ -319,6 +319,7 @@ int ossl_quic_channel_is_handshake_complete(const QUIC_CHANNEL *ch); int ossl_quic_channel_is_handshake_confirmed(const QUIC_CHANNEL *ch); QUIC_PORT *ossl_quic_channel_get0_port(QUIC_CHANNEL *ch); +QUIC_ENGINE *ossl_quic_channel_get0_engine(QUIC_CHANNEL *ch); QUIC_DEMUX *ossl_quic_channel_get0_demux(QUIC_CHANNEL *ch); SSL *ossl_quic_channel_get0_ssl(QUIC_CHANNEL *ch); diff --git a/include/internal/quic_port.h b/include/internal/quic_port.h index 74578e9267..81811b0110 100644 --- a/include/internal/quic_port.h +++ b/include/internal/quic_port.h @@ -42,30 +42,6 @@ typedef struct quic_port_args_st { /* The engine which the QUIC port is to be a child of. */ QUIC_ENGINE *engine; - /* All channels in a QUIC event domain share the same (libctx, propq). */ - OSSL_LIB_CTX *libctx; - const char *propq; - - /* - * This must be a mutex the lifetime of which will exceed that of the port - * and all channels. The instantiator of the port is responsible for - * providing a mutex as this makes it easier to handle instantiation and - * teardown of channels in situations potentially requiring locking. - * - * Note that this is a MUTEX not a RWLOCK as it needs to be an OS mutex for - * compatibility with an OS's condition variable wait API, whereas RWLOCK - * may, depending on the build configuration, be implemented using an OS's - * mutex primitive or using its RW mutex primitive. - */ - CRYPTO_MUTEX *mutex; - - /* - * Optional function pointer to use to retrieve the current time. If NULL, - * ossl_time_now() is used. - */ - OSSL_TIME (*now_cb)(void *arg); - void *now_cb_arg; - /* * This SSL_CTX will be used when constructing the handshake layer object * inside newly created channels. @@ -134,9 +110,6 @@ OSSL_TIME ossl_quic_port_get_time(QUIC_PORT *port); int ossl_quic_port_get_rx_short_dcid_len(const QUIC_PORT *port); int ossl_quic_port_get_tx_init_dcid_len(const QUIC_PORT *port); -/* For testing use. While enabled, ticking is not performed. */ -void ossl_quic_port_set_inhibit_tick(QUIC_PORT *port, int inhibit); - /* Returns 1 if the port is running/healthy, 0 if it has failed. */ int ossl_quic_port_is_running(const QUIC_PORT *port); diff --git a/ssl/quic/quic_channel.c b/ssl/quic/quic_channel.c index 60bcc88f84..6a87588e90 100644 --- a/ssl/quic/quic_channel.c +++ b/ssl/quic/quic_channel.c @@ -17,6 +17,7 @@ #include "../ssl_local.h" #include "quic_channel_local.h" #include "quic_port_local.h" +#include "quic_engine_local.h" /* * NOTE: While this channel implementation currently has basic server support, @@ -129,12 +130,12 @@ static int ch_init(QUIC_CHANNEL *ch) /* For clients, generate our initial DCID. */ if (!ch->is_server - && !ossl_quic_gen_rand_conn_id(ch->port->libctx, tx_init_dcid_len, + && !ossl_quic_gen_rand_conn_id(ch->port->engine->libctx, tx_init_dcid_len, &ch->init_dcid)) goto err; /* We plug in a network write BIO to the QTX later when we get one. */ - qtx_args.libctx = ch->port->libctx; + qtx_args.libctx = ch->port->engine->libctx; qtx_args.mdpl = QUIC_MIN_INITIAL_DGRAM_LEN; ch->rx_max_udp_payload_size = qtx_args.mdpl; @@ -241,7 +242,7 @@ static int ch_init(QUIC_CHANNEL *ch) ossl_quic_tx_packetiser_set_ack_tx_cb(ch->txp, ch_on_txp_ack_tx, ch); - qrx_args.libctx = ch->port->libctx; + qrx_args.libctx = ch->port->engine->libctx; qrx_args.demux = ch->port->demux; qrx_args.short_conn_id_len = rx_short_dcid_len; qrx_args.max_deferred = 32; @@ -509,6 +510,11 @@ QUIC_PORT *ossl_quic_channel_get0_port(QUIC_CHANNEL *ch) return ch->port; } +QUIC_ENGINE *ossl_quic_channel_get0_engine(QUIC_CHANNEL *ch) +{ + return ossl_quic_port_get0_engine(ch->port); +} + CRYPTO_MUTEX *ossl_quic_channel_get_mutex(QUIC_CHANNEL *ch) { return ossl_quic_port_get0_mutex(ch->port); @@ -1712,7 +1718,7 @@ void ossl_quic_channel_subtick(QUIC_CHANNEL *ch, QUIC_TICK_RESULT *res, } } - if (!ch->port->inhibit_tick) { + if (!ch->port->engine->inhibit_tick) { /* Handle RXKU timeouts. */ ch_rxku_tick(ch); @@ -1752,7 +1758,7 @@ void ossl_quic_channel_subtick(QUIC_CHANNEL *ch, QUIC_TICK_RESULT *res, * Idle timeout differs from normal protocol violation because we do * not send a CONN_CLOSE frame; go straight to TERMINATED. */ - if (!ch->port->inhibit_tick) + if (!ch->port->engine->inhibit_tick) ch_on_idle_timeout(ch); res->net_read_desired = 0; @@ -1761,7 +1767,7 @@ void ossl_quic_channel_subtick(QUIC_CHANNEL *ch, QUIC_TICK_RESULT *res, return; } - if (!ch->port->inhibit_tick) { + if (!ch->port->engine->inhibit_tick) { deadline = ossl_ackm_get_loss_detection_deadline(ch->ackm); if (!ossl_time_is_zero(deadline) && ossl_time_compare(now, deadline) >= 0) @@ -2062,8 +2068,8 @@ static void ch_rx_handle_packet(QUIC_CHANNEL *ch, int channel_only) * than allow the QRX to emit a potentially malformed packet to the * upper layers. However, special casing this will do for now. */ - if (!ossl_quic_validate_retry_integrity_tag(ch->port->libctx, - ch->port->propq, + if (!ossl_quic_validate_retry_integrity_tag(ch->port->engine->libctx, + ch->port->engine->propq, ch->qrx_pkt->hdr, &ch->init_dcid)) /* Malformed retry packet, ignore. */ @@ -2391,8 +2397,8 @@ int ossl_quic_channel_start(QUIC_CHANNEL *ch) return 0; /* Plug in secrets for the Initial EL. */ - if (!ossl_quic_provide_initial_secret(ch->port->libctx, - ch->port->propq, + if (!ossl_quic_provide_initial_secret(ch->port->engine->libctx, + ch->port->engine->propq, &ch->init_dcid, ch->is_server, ch->qrx, ch->qtx)) @@ -2491,8 +2497,8 @@ static int ch_retry(QUIC_CHANNEL *ch, * Plug in new secrets for the Initial EL. This is the only time we change * the secrets for an EL after we already provisioned it. */ - if (!ossl_quic_provide_initial_secret(ch->port->libctx, - ch->port->propq, + if (!ossl_quic_provide_initial_secret(ch->port->engine->libctx, + ch->port->engine->propq, &ch->retry_scid, /*is_server=*/0, ch->qrx, ch->qtx)) @@ -3145,8 +3151,8 @@ int ossl_quic_channel_on_new_conn(QUIC_CHANNEL *ch, const BIO_ADDR *peer, return 0; /* Plug in secrets for the Initial EL. */ - if (!ossl_quic_provide_initial_secret(ch->port->libctx, - ch->port->propq, + if (!ossl_quic_provide_initial_secret(ch->port->engine->libctx, + ch->port->engine->propq, &ch->init_dcid, /*is_server=*/1, ch->qrx, ch->qtx)) diff --git a/ssl/quic/quic_engine.c b/ssl/quic/quic_engine.c index 26c859e595..9f881b3cc4 100644 --- a/ssl/quic/quic_engine.c +++ b/ssl/quic/quic_engine.c @@ -98,6 +98,10 @@ QUIC_PORT *ossl_quic_engine_create_port(QUIC_ENGINE *qeng, { QUIC_PORT_ARGS largs = *args; + if (ossl_list_port_num(&qeng->port_list) > 0) + /* TODO(QUIC MULTIPORT): We currently support only one port. */ + return NULL; + if (largs.engine != NULL) return NULL; diff --git a/ssl/quic/quic_engine_local.h b/ssl/quic/quic_engine_local.h index 6896e30d85..214cc5e5fe 100644 --- a/ssl/quic/quic_engine_local.h +++ b/ssl/quic/quic_engine_local.h @@ -28,6 +28,7 @@ DECLARE_LIST_OF(port, QUIC_PORT); struct quic_engine_st { + /* All objects in a QUIC event domain share the same (libctx, propq). */ OSSL_LIB_CTX *libctx; const char *propq; diff --git a/ssl/quic/quic_impl.c b/ssl/quic/quic_impl.c index 7279c37c17..5306d6bd40 100644 --- a/ssl/quic/quic_impl.c +++ b/ssl/quic/quic_impl.c @@ -15,6 +15,7 @@ #include "internal/quic_tls.h" #include "internal/quic_rx_depack.h" #include "internal/quic_error.h" +#include "internal/quic_engine.h" #include "internal/quic_port.h" #include "internal/time.h" @@ -64,7 +65,7 @@ static int block_until_pred(QUIC_CONNECTION *qc, * Any attempt to block auto-disables tick inhibition as otherwise we will * hang around forever. */ - ossl_quic_port_set_inhibit_tick(qc->port, 0); + ossl_quic_engine_set_inhibit_tick(qc->engine, 0); rtor = ossl_quic_channel_get_reactor(qc->ch); return ossl_quic_reactor_block_until_pred(rtor, pred, pred_arg, flags, @@ -545,6 +546,7 @@ void ossl_quic_free(SSL *s) ossl_quic_channel_free(ctx.qc->ch); ossl_quic_port_free(ctx.qc->port); + ossl_quic_engine_free(ctx.qc->engine); BIO_free_all(ctx.qc->net_rbio); BIO_free_all(ctx.qc->net_wbio); @@ -1489,18 +1491,25 @@ static int configure_channel(QUIC_CONNECTION *qc) QUIC_NEEDS_LOCK static int create_channel(QUIC_CONNECTION *qc) { + QUIC_ENGINE_ARGS engine_args = {0}; QUIC_PORT_ARGS port_args = {0}; - port_args.libctx = qc->ssl.ctx->libctx; - port_args.propq = qc->ssl.ctx->propq; - port_args.mutex = qc->mutex; - port_args.channel_ctx = qc->ssl.ctx; - port_args.now_cb = get_time_cb; - port_args.now_cb_arg = qc; + engine_args.libctx = qc->ssl.ctx->libctx; + engine_args.propq = qc->ssl.ctx->propq; + engine_args.mutex = qc->mutex; + engine_args.now_cb = get_time_cb; + engine_args.now_cb_arg = qc; + qc->engine = ossl_quic_engine_new(&engine_args); + if (qc->engine == NULL) { + QUIC_RAISE_NON_NORMAL_ERROR(NULL, ERR_R_INTERNAL_ERROR, NULL); + return 0; + } - qc->port = ossl_quic_port_new(&port_args); + port_args.channel_ctx = qc->ssl.ctx; + qc->port = ossl_quic_engine_create_port(qc->engine, &port_args); if (qc->port == NULL) { QUIC_RAISE_NON_NORMAL_ERROR(NULL, ERR_R_INTERNAL_ERROR, NULL); + ossl_quic_engine_free(qc->engine); return 0; } @@ -1508,6 +1517,7 @@ static int create_channel(QUIC_CONNECTION *qc) if (qc->ch == NULL) { QUIC_RAISE_NON_NORMAL_ERROR(NULL, ERR_R_INTERNAL_ERROR, NULL); ossl_quic_port_free(qc->port); + ossl_quic_engine_free(qc->engine); return 0; } diff --git a/ssl/quic/quic_local.h b/ssl/quic/quic_local.h index ef074daf71..ca95f46f52 100644 --- a/ssl/quic/quic_local.h +++ b/ssl/quic/quic_local.h @@ -118,6 +118,9 @@ struct quic_conn_st { SSL *tls; + /* The QUIC engine representing the QUIC event domain. */ + QUIC_ENGINE *engine; + /* The QUIC port representing the QUIC listener and socket. */ QUIC_PORT *port; diff --git a/ssl/quic/quic_port.c b/ssl/quic/quic_port.c index 897edc4a79..3dbcd10957 100644 --- a/ssl/quic/quic_port.c +++ b/ssl/quic/quic_port.c @@ -28,7 +28,6 @@ static OSSL_TIME get_time(void *arg); static void port_default_packet_handler(QUIC_URXE *e, void *arg, const QUIC_CONN_ID *dcid); static void port_rx_pre(QUIC_PORT *port); -static void port_tick(QUIC_TICK_RESULT *res, void *arg, uint32_t flags); DEFINE_LIST_OF_IMPL(ch, QUIC_CHANNEL); DEFINE_LIST_OF_IMPL(port, QUIC_PORT); @@ -41,11 +40,6 @@ QUIC_PORT *ossl_quic_port_new(const QUIC_PORT_ARGS *args) return NULL; port->engine = args->engine; - port->libctx = args->libctx; - port->propq = args->propq; - port->mutex = args->mutex; - port->now_cb = args->now_cb; - port->now_cb_arg = args->now_cb_arg; port->channel_ctx = args->channel_ctx; port->is_multi_conn = args->is_multi_conn; @@ -70,7 +64,7 @@ static int port_init(QUIC_PORT *port) { size_t rx_short_dcid_len = (port->is_multi_conn ? INIT_DCID_LEN : 0); - if (port->channel_ctx == NULL) + if (port->engine == NULL || port->channel_ctx == NULL) goto err; if ((port->err_state = OSSL_ERR_STATE_new()) == NULL) @@ -85,15 +79,14 @@ static int port_init(QUIC_PORT *port) port_default_packet_handler, port); - if ((port->srtm = ossl_quic_srtm_new(port->libctx, port->propq)) == NULL) + if ((port->srtm = ossl_quic_srtm_new(port->engine->libctx, + port->engine->propq)) == NULL) goto err; - if ((port->lcidm = ossl_quic_lcidm_new(port->libctx, rx_short_dcid_len)) == NULL) + if ((port->lcidm = ossl_quic_lcidm_new(port->engine->libctx, + rx_short_dcid_len)) == NULL) goto err; - if (port->engine == NULL) - ossl_quic_reactor_init(&port->rtor, port_tick, port, ossl_time_zero()); - port->rx_short_dcid_len = (unsigned char)rx_short_dcid_len; port->tx_init_dcid_len = INIT_DCID_LEN; port->state = QUIC_PORT_STATE_RUNNING; @@ -150,7 +143,7 @@ QUIC_ENGINE *ossl_quic_port_get0_engine(QUIC_PORT *port) QUIC_REACTOR *ossl_quic_port_get0_reactor(QUIC_PORT *port) { - return port->engine != NULL ? &port->engine->rtor : &port->rtor; + return ossl_quic_engine_get0_reactor(port->engine); } QUIC_DEMUX *ossl_quic_port_get0_demux(QUIC_PORT *port) @@ -160,15 +153,12 @@ QUIC_DEMUX *ossl_quic_port_get0_demux(QUIC_PORT *port) CRYPTO_MUTEX *ossl_quic_port_get0_mutex(QUIC_PORT *port) { - return port->mutex; + return ossl_quic_engine_get0_mutex(port->engine); } OSSL_TIME ossl_quic_port_get_time(QUIC_PORT *port) { - if (port->now_cb == NULL) - return ossl_time_now(); - - return port->now_cb(port->now_cb_arg); + return ossl_quic_engine_get_time(port->engine); } static OSSL_TIME get_time(void *port) @@ -225,10 +215,19 @@ static int port_update_poll_desc(QUIC_PORT *port, BIO *net_bio, int for_write) if (!validate_poll_descriptor(&d)) return 0; + /* + * TODO(QUIC MULTIPORT): We currently only support one port per + * engine/domain. This is necessitated because QUIC_REACTOR only supports a + * single pollable currently. In the future, once complete polling + * infrastructure has been implemented, this limitation can be removed. + * + * For now, just update the descriptor on the the engine's reactor as we are + * guaranteed to be the only port under it. + */ if (for_write) - ossl_quic_reactor_set_poll_w(&port->rtor, &d); + ossl_quic_reactor_set_poll_w(&port->engine->rtor, &d); else - ossl_quic_reactor_set_poll_r(&port->rtor, &d); + ossl_quic_reactor_set_poll_r(&port->engine->rtor, &d); return 1; } @@ -355,11 +354,6 @@ QUIC_CHANNEL *ossl_quic_port_create_incoming(QUIC_PORT *port, SSL *tls) * Tick function for this port. This does everything related to network I/O for * this port's network BIOs, and services child channels. */ -static void port_tick(QUIC_TICK_RESULT *res, void *arg, uint32_t flags) -{ - ossl_quic_port_subtick(arg, res, flags); -} - void ossl_quic_port_subtick(QUIC_PORT *port, QUIC_TICK_RESULT *res, uint32_t flags) { @@ -369,7 +363,7 @@ void ossl_quic_port_subtick(QUIC_PORT *port, QUIC_TICK_RESULT *res, res->net_write_desired = 0; res->tick_deadline = ossl_time_infinite(); - if (!port->inhibit_tick) { + if (!port->engine->inhibit_tick) { /* Handle any incoming data from network. */ if (ossl_quic_port_is_running(port)) port_rx_pre(port); @@ -583,11 +577,6 @@ undesirable: ossl_quic_demux_release_urxe(port->demux, e); } -void ossl_quic_port_set_inhibit_tick(QUIC_PORT *port, int inhibit) -{ - port->inhibit_tick = (inhibit != 0); -} - void ossl_quic_port_raise_net_error(QUIC_PORT *port, QUIC_CHANNEL *triggering_ch) { diff --git a/ssl/quic/quic_port_local.h b/ssl/quic/quic_port_local.h index ec12872b72..f44352a893 100644 --- a/ssl/quic/quic_port_local.h +++ b/ssl/quic/quic_port_local.h @@ -50,27 +50,9 @@ struct quic_port_st { */ OSSL_LIST_MEMBER(port, QUIC_PORT); - OSSL_LIB_CTX *libctx; - const char *propq; - - /* - * Master synchronisation mutex for the entire QUIC event domain. Used for - * thread assisted mode synchronisation. We don't own this; the instantiator - * of the port passes it to us and is responsible for freeing it after port - * destruction. - */ - CRYPTO_MUTEX *mutex; - - /* Callback used to get the current time. */ - OSSL_TIME (*now_cb)(void *arg); - void *now_cb_arg; - /* Used to create handshake layer objects inside newly created channels. */ SSL_CTX *channel_ctx; - /* Asynchronous I/O reactor. */ - QUIC_REACTOR rtor; - /* Network-side read and write BIOs. */ BIO *net_rbio, *net_wbio; @@ -103,9 +85,6 @@ struct quic_port_st { /* Is this port created to support multiple connections? */ unsigned int is_multi_conn : 1; - /* Inhibit tick for testing purposes? */ - unsigned int inhibit_tick : 1; - /* Has this port sent any packet of any kind yet? */ unsigned int have_sent_any_pkt : 1; diff --git a/ssl/quic/quic_tserver.c b/ssl/quic/quic_tserver.c index 885f4d5242..159669ef8f 100644 --- a/ssl/quic/quic_tserver.c +++ b/ssl/quic/quic_tserver.c @@ -11,6 +11,7 @@ #include "internal/quic_channel.h" #include "internal/quic_statm.h" #include "internal/quic_port.h" +#include "internal/quic_engine.h" #include "internal/common.h" #include "internal/time.h" #include "quic_local.h" @@ -26,9 +27,10 @@ struct quic_tserver_st { SSL *ssl; /* - * The QUIC port and channel providing the core QUIC connection + * The QUIC engine, port and channel providing the core QUIC connection * implementation. */ + QUIC_ENGINE *engine; QUIC_PORT *port; QUIC_CHANNEL *ch; @@ -78,6 +80,7 @@ QUIC_TSERVER *ossl_quic_tserver_new(const QUIC_TSERVER_ARGS *args, const char *certfile, const char *keyfile) { QUIC_TSERVER *srv = NULL; + QUIC_ENGINE_ARGS engine_args = {0}; QUIC_PORT_ARGS port_args = {0}; QUIC_CONNECTION *qc = NULL; @@ -116,15 +119,19 @@ QUIC_TSERVER *ossl_quic_tserver_new(const QUIC_TSERVER_ARGS *args, if (srv->tls == NULL) goto err; - port_args.libctx = srv->args.libctx; - port_args.propq = srv->args.propq; - port_args.mutex = srv->mutex; - port_args.channel_ctx = srv->ctx; - port_args.now_cb = srv->args.now_cb; - port_args.now_cb_arg = srv->args.now_cb_arg; - port_args.is_multi_conn = 1; + engine_args.libctx = srv->args.libctx; + engine_args.propq = srv->args.propq; + engine_args.mutex = srv->mutex; + engine_args.now_cb = srv->args.now_cb; + engine_args.now_cb_arg = srv->args.now_cb_arg; - if ((srv->port = ossl_quic_port_new(&port_args)) == NULL) + if ((srv->engine = ossl_quic_engine_new(&engine_args)) == NULL) + goto err; + + port_args.channel_ctx = srv->ctx; + port_args.is_multi_conn = 1; + + if ((srv->port = ossl_quic_engine_create_port(srv->engine, &port_args)) == NULL) goto err; if ((srv->ch = ossl_quic_port_create_incoming(srv->port, srv->tls)) == NULL) @@ -150,6 +157,7 @@ err: SSL_free(srv->tls); ossl_quic_channel_free(srv->ch); ossl_quic_port_free(srv->port); + ossl_quic_engine_free(srv->engine); #if defined(OPENSSL_THREADS) ossl_crypto_mutex_free(&srv->mutex); #endif @@ -167,6 +175,7 @@ void ossl_quic_tserver_free(QUIC_TSERVER *srv) ossl_quic_channel_free(srv->ch); ossl_quic_port_free(srv->port); + ossl_quic_engine_free(srv->engine); BIO_free_all(srv->args.net_rbio); BIO_free_all(srv->args.net_wbio); OPENSSL_free(srv->ssl); diff --git a/test/quic_multistream_test.c b/test/quic_multistream_test.c index 2fe44cd26f..9e53d147a6 100644 --- a/test/quic_multistream_test.c +++ b/test/quic_multistream_test.c @@ -14,7 +14,7 @@ #include "internal/quic_ssl.h" #include "internal/quic_error.h" #include "internal/quic_stream_map.h" -#include "internal/quic_port.h" +#include "internal/quic_engine.h" #include "testutil.h" #include "helpers/quictestlib.h" #if defined(OPENSSL_THREADS) @@ -1599,7 +1599,7 @@ static int run_script_worker(struct helper *h, const struct script_op *script, QUIC_CHANNEL *ch = ossl_quic_conn_get_channel(h->c_conn); SSL_SHUTDOWN_EX_ARGS args = {0}; - ossl_quic_port_set_inhibit_tick(ossl_quic_channel_get0_port(ch), 0); + ossl_quic_engine_set_inhibit_tick(ossl_quic_channel_get0_engine(ch), 0); if (!TEST_ptr(c_tgt)) goto out; @@ -1927,8 +1927,8 @@ static int run_script_worker(struct helper *h, const struct script_op *script, { QUIC_CHANNEL *ch = ossl_quic_conn_get_channel(h->c_conn); - ossl_quic_port_set_inhibit_tick(ossl_quic_channel_get0_port(ch), - op->arg1); + ossl_quic_engine_set_inhibit_tick(ossl_quic_channel_get0_engine(ch), + op->arg1); } break; -- Gitee From f72f79aa72b208fc8086b7d7850815d7c2116e7a Mon Sep 17 00:00:00 2001 From: Hugo Landau Date: Fri, 8 Dec 2023 07:51:16 +0000 Subject: [PATCH 79/92] Minor updates Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/22674) Signed-off-by: lanming1120 --- doc/man3/ERR_set_mark.pod | 2 +- ssl/quic/quic_channel.c | 7 +++++-- ssl/quic/quic_port.c | 2 +- ssl/quic/quic_record_rx.c | 4 ++-- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/doc/man3/ERR_set_mark.pod b/doc/man3/ERR_set_mark.pod index d6d715e2f6..070a7f6e29 100644 --- a/doc/man3/ERR_set_mark.pod +++ b/doc/man3/ERR_set_mark.pod @@ -3,7 +3,7 @@ =head1 NAME ERR_set_mark, ERR_clear_last_mark, ERR_pop_to_mark, ERR_count_to_mark, ERR_pop - -set mark, clear mark and pop errors until mark +set mark, clear mark, pop errors until mark and pop last error =head1 SYNOPSIS diff --git a/ssl/quic/quic_channel.c b/ssl/quic/quic_channel.c index 6a87588e90..b5f019f40e 100644 --- a/ssl/quic/quic_channel.c +++ b/ssl/quic/quic_channel.c @@ -122,12 +122,15 @@ static int ch_init(QUIC_CHANNEL *ch) OSSL_QRX_ARGS qrx_args = {0}; QUIC_TLS_ARGS tls_args = {0}; uint32_t pn_space; - size_t rx_short_dcid_len = ossl_quic_port_get_rx_short_dcid_len(ch->port); - size_t tx_init_dcid_len = ossl_quic_port_get_tx_init_dcid_len(ch->port); + size_t rx_short_dcid_len; + size_t tx_init_dcid_len; if (ch->port == NULL || ch->lcidm == NULL || ch->srtm == NULL) goto err; + rx_short_dcid_len = ossl_quic_port_get_rx_short_dcid_len(ch->port); + tx_init_dcid_len = ossl_quic_port_get_tx_init_dcid_len(ch->port); + /* For clients, generate our initial DCID. */ if (!ch->is_server && !ossl_quic_gen_rand_conn_id(ch->port->engine->libctx, tx_init_dcid_len, diff --git a/ssl/quic/quic_port.c b/ssl/quic/quic_port.c index 3dbcd10957..b4e2deeb84 100644 --- a/ssl/quic/quic_port.c +++ b/ssl/quic/quic_port.c @@ -473,7 +473,7 @@ static int port_try_handle_stateless_reset(QUIC_PORT *port, const QUIC_URXE *e) for (i = 0;; ++i) { if (!ossl_quic_srtm_lookup(port->srtm, (QUIC_STATELESS_RESET_TOKEN *)(data + e->data_len - - sizeof(QUIC_STATELESS_RESET_TOKEN)), + - sizeof(QUIC_STATELESS_RESET_TOKEN)), i, &opaque, NULL)) break; diff --git a/ssl/quic/quic_record_rx.c b/ssl/quic/quic_record_rx.c index 393007df50..97dadd3dbe 100644 --- a/ssl/quic/quic_record_rx.c +++ b/ssl/quic/quic_record_rx.c @@ -173,11 +173,11 @@ OSSL_QRX *ossl_qrx_new(const OSSL_QRX_ARGS *args) size_t i; if (args->demux == NULL || args->max_deferred == 0) - return 0; + return NULL; qrx = OPENSSL_zalloc(sizeof(OSSL_QRX)); if (qrx == NULL) - return 0; + return NULL; for (i = 0; i < OSSL_NELEM(qrx->largest_pn); ++i) qrx->largest_pn[i] = args->init_largest_pn[i]; -- Gitee From f97fff1fd2a1f953c1d211b31d7a7683072d4404 Mon Sep 17 00:00:00 2001 From: Hugo Landau Date: Mon, 18 Dec 2023 07:30:02 +0000 Subject: [PATCH 80/92] Minor fixes Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/22674) Signed-off-by: lanming1120 --- include/internal/quic_port.h | 5 +++-- ssl/quic/quic_port.c | 7 +++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/internal/quic_port.h b/include/internal/quic_port.h index 81811b0110..bcb578c3f8 100644 --- a/include/internal/quic_port.h +++ b/include/internal/quic_port.h @@ -70,8 +70,9 @@ void ossl_quic_port_free(QUIC_PORT *port); QUIC_CHANNEL *ossl_quic_port_create_outgoing(QUIC_PORT *port, SSL *tls); /* - * Create an incoming channel using this port. XXX for temporary TSERVER use - * only - will be removed. + * Create an incoming channel using this port. + * + * TODO(QUIC SERVER): temporary TSERVER use only - will be removed. */ QUIC_CHANNEL *ossl_quic_port_create_incoming(QUIC_PORT *port, SSL *tls); diff --git a/ssl/quic/quic_port.c b/ssl/quic/quic_port.c index b4e2deeb84..9976862138 100644 --- a/ssl/quic/quic_port.c +++ b/ssl/quic/quic_port.c @@ -90,10 +90,9 @@ static int port_init(QUIC_PORT *port) port->rx_short_dcid_len = (unsigned char)rx_short_dcid_len; port->tx_init_dcid_len = INIT_DCID_LEN; port->state = QUIC_PORT_STATE_RUNNING; - if (port->engine != NULL) { - ossl_list_port_insert_tail(&port->engine->port_list, port); - port->on_engine_list = 1; - } + + ossl_list_port_insert_tail(&port->engine->port_list, port); + port->on_engine_list = 1; return 1; err: -- Gitee From ebe195faf69020d10afc5f890568bf6c02312625 Mon Sep 17 00:00:00 2001 From: Hugo Landau Date: Tue, 19 Dec 2023 07:33:24 +0000 Subject: [PATCH 81/92] QUIC: Add more glossary entries Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/22674) Signed-off-by: lanming1120 --- doc/designs/quic-design/glossary.md | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/doc/designs/quic-design/glossary.md b/doc/designs/quic-design/glossary.md index a70cfd1ade..3993c6f845 100644 --- a/doc/designs/quic-design/glossary.md +++ b/doc/designs/quic-design/glossary.md @@ -25,8 +25,7 @@ limits on transmissions accordingly. the CFQ strategy for frame in flight management. For details, see FIFM design document. -**Channel:** Core QUIC connection handling object and connection state machine -implementation. This is fused tightly with the RXDP. +**Channel:** See `QUIC_CHANNEL`. **CID:** Connection ID. @@ -55,6 +54,8 @@ dispatches calls to libssl public APIs to the APL. **EL:** Encryption level. See RFC 9000. +**Engine:** See `QUIC_ENGINE`. + **FC:** Flow control. Comprises TXFC and RXFC. **FIFD:** Frame-in-flight dispatcher. Ties together the CFQ and TXPIM to handle @@ -134,6 +135,8 @@ Initial packets. It is only used temporarily. **PN:** Packet number. Most QUIC packet types have a packet number (PN); see RFC 9000. +**Port:** See `QUIC_PORT`. + **PTO:** Probe timeout. See RFC 9000. **QC:** See `QUIC_CONNECTION`. @@ -167,8 +170,24 @@ wrapping libssl TLS code to implement the QUIC-specific aspects of QUIC TLS. **QTX:** QUIC Record Layer TX. Encrypts and sends packets in datagrams. +**QUIC_CHANNEL:** Internal object in the QUIC core implementation corresponding +to a QUIC connection. Ties together other components and provides connection +handling and state machine implementation. Belongs to a `QUIC_PORT` representing +a UDP socket/BIO, which in turn belongs to a `QUIC_ENGINE`. Owns some number of +`QUIC_STREAM` instances. The `QUIC_CHANNEL` code is fused tightly with the RXDP. + **QUIC_CONNECTION:** QUIC connection. This is the object representing a QUIC -connection in the APL. +connection in the APL. It internally corresponds to a `QUIC_CHANNEL` object in +the QUIC core implementation. + +**QUIC_ENGINE:** Internal object in the QUIC core implementation constituting +the top-level object of a QUIC event and I/O processing domain. Owns zero or +more `QUIC_PORT` instances, each of which owns zero or more `QUIC_CHANNEL` +objects representing QUIC connections. + +**QUIC_PORT:** Internal object in the QUIC core implementation corresponding to +a listening port/network BIO. Has zero or more child `QUIC_CHANNEL` objects +associated with it and belongs to a `QUIC_ENGINE`. **QUIC_STREAM**: Internal object tracking a QUIC stream. Unlike an XSO this is not part of the APL. An XSO wraps a QUIC_STREAM once that stream is exposed as -- Gitee From 557b9fb8b795300b79d8062c6a8c822bfb8c33f7 Mon Sep 17 00:00:00 2001 From: Hugo Landau Date: Tue, 19 Dec 2023 07:34:59 +0000 Subject: [PATCH 82/92] QUIC PORT: Add explicit cast to get_time wrapper Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/22674) Signed-off-by: lanming1120 --- ssl/quic/quic_port.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ssl/quic/quic_port.c b/ssl/quic/quic_port.c index 9976862138..46ca22cc3b 100644 --- a/ssl/quic/quic_port.c +++ b/ssl/quic/quic_port.c @@ -162,7 +162,7 @@ OSSL_TIME ossl_quic_port_get_time(QUIC_PORT *port) static OSSL_TIME get_time(void *port) { - return ossl_quic_port_get_time(port); + return ossl_quic_port_get_time((QUIC_PORT *)port); } int ossl_quic_port_get_rx_short_dcid_len(const QUIC_PORT *port) -- Gitee From 1526062aef021618becebdafa2bbb92e5627a0b9 Mon Sep 17 00:00:00 2001 From: Hugo Landau Date: Tue, 19 Dec 2023 15:10:43 +0000 Subject: [PATCH 83/92] Minor updates Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/22674) Signed-off-by: lanming1120 --- include/internal/quic_engine.h | 12 ++++++++---- ssl/quic/quic_engine.c | 1 - ssl/quic/quic_engine_local.h | 4 ++-- ssl/quic/quic_port_local.h | 4 ++-- 4 files changed, 12 insertions(+), 9 deletions(-) diff --git a/include/internal/quic_engine.h b/include/internal/quic_engine.h index a08f76e53f..5d06d076b9 100644 --- a/include/internal/quic_engine.h +++ b/include/internal/quic_engine.h @@ -28,7 +28,11 @@ * represents a single QUIC connection. All QUIC_PORT instances must belong * to a QUIC_ENGINE. * - * A QUIC engine is the root engine in a QUIC event domain, and is responsible + * TODO(QUIC SERVER): Currently a QUIC_PORT belongs to a single QUIC_CHANNEL. + * This will cease to be the case once connection migration and/or multipath is + * implemented, so in future a channel might be associated with multiple ports. + * + * A QUIC engine is the root object in a QUIC event domain, and is responsible * for managing event processing for all QUIC ports and channels (e.g. timeouts, * clock management, the QUIC_REACTOR instance, etc.). */ @@ -37,9 +41,9 @@ typedef struct quic_engine_args_st { const char *propq; /* - * This must be a mutex the lifetime of which will exceed that of the port - * and all channels. The instantiator of the port is responsible for - * providing a mutex as this makes it easier to handle instantiation and + * This must be a mutex the lifetime of which will exceed that of the engine + * and all ports and channels. The instantiator of the engine is responsible + * for providing a mutex as this makes it easier to handle instantiation and * teardown of channels in situations potentially requiring locking. * * Note that this is a MUTEX not a RWLOCK as it needs to be an OS mutex for diff --git a/ssl/quic/quic_engine.c b/ssl/quic/quic_engine.c index 9f881b3cc4..3bcb5d6810 100644 --- a/ssl/quic/quic_engine.c +++ b/ssl/quic/quic_engine.c @@ -65,7 +65,6 @@ static void qeng_cleanup(QUIC_ENGINE *qeng) } QUIC_REACTOR *ossl_quic_engine_get0_reactor(QUIC_ENGINE *qeng) - { return &qeng->rtor; } diff --git a/ssl/quic/quic_engine_local.h b/ssl/quic/quic_engine_local.h index 214cc5e5fe..280fd31dd7 100644 --- a/ssl/quic/quic_engine_local.h +++ b/ssl/quic/quic_engine_local.h @@ -35,8 +35,8 @@ struct quic_engine_st { /* * Master synchronisation mutex for the entire QUIC event domain. Used for * thread assisted mode synchronisation. We don't own this; the instantiator - * of the port passes it to us and is responsible for freeing it after port - * destruction. + * of the engine passes it to us and is responsible for freeing it after + * engine destruction. */ CRYPTO_MUTEX *mutex; diff --git a/ssl/quic/quic_port_local.h b/ssl/quic/quic_port_local.h index f44352a893..b5e1206368 100644 --- a/ssl/quic/quic_port_local.h +++ b/ssl/quic/quic_port_local.h @@ -45,8 +45,8 @@ struct quic_port_st { QUIC_ENGINE *engine; /* - * QUIC_ENGINE keeps the channels which belong to it on a list for - * bookkeeping purposes. + * QUIC_ENGINE keeps the ports which belong to it on a list for bookkeeping + * purposes. */ OSSL_LIST_MEMBER(port, QUIC_PORT); -- Gitee From 47adc77e98a07c75d48fe04b8b6b4719f5883c41 Mon Sep 17 00:00:00 2001 From: Hugo Landau Date: Tue, 19 Dec 2023 16:09:04 +0000 Subject: [PATCH 84/92] QUIC: Move CID generation to quic_types.c Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/22674) Signed-off-by: lanming1120 --- ssl/quic/build.info | 1 + ssl/quic/quic_types.c | 29 +++++++++++++++++++++++++++++ ssl/quic/quic_wire.c | 18 ------------------ 3 files changed, 30 insertions(+), 18 deletions(-) create mode 100644 ssl/quic/quic_types.c diff --git a/ssl/quic/build.info b/ssl/quic/build.info index bb6739b18b..9927d344d8 100644 --- a/ssl/quic/build.info +++ b/ssl/quic/build.info @@ -16,3 +16,4 @@ SOURCE[$LIBSSL]=quic_thread_assist.c SOURCE[$LIBSSL]=quic_trace.c SOURCE[$LIBSSL]=quic_srtm.c quic_srt_gen.c SOURCE[$LIBSSL]=quic_lcidm.c +SOURCE[$LIBSSL]=quic_types.c diff --git a/ssl/quic/quic_types.c b/ssl/quic/quic_types.c new file mode 100644 index 0000000000..4ff3ae6580 --- /dev/null +++ b/ssl/quic/quic_types.c @@ -0,0 +1,29 @@ +/* + * Copyright 2023 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 + */ + +#include "internal/quic_types.h" +#include +#include + +int ossl_quic_gen_rand_conn_id(OSSL_LIB_CTX *libctx, size_t len, + QUIC_CONN_ID *cid) +{ + if (len > QUIC_MAX_CONN_ID_LEN) + return 0; + + cid->id_len = (unsigned char)len; + + if (RAND_bytes_ex(libctx, cid->id, len, len * 8) != 1) { + ERR_raise(ERR_LIB_SSL, ERR_R_RAND_LIB); + cid->id_len = 0; + return 0; + } + + return 1; +} diff --git a/ssl/quic/quic_wire.c b/ssl/quic/quic_wire.c index faf80cfd07..425e7efc2e 100644 --- a/ssl/quic/quic_wire.c +++ b/ssl/quic/quic_wire.c @@ -9,7 +9,6 @@ #include #include -#include #include "internal/quic_ssl.h" #include "internal/quic_vlint.h" #include "internal/quic_wire.h" @@ -1077,20 +1076,3 @@ const char *ossl_quic_err_to_string(uint64_t error_code) return NULL; } } - -int ossl_quic_gen_rand_conn_id(OSSL_LIB_CTX *libctx, size_t len, - QUIC_CONN_ID *cid) -{ - if (len > QUIC_MAX_CONN_ID_LEN) - return 0; - - cid->id_len = (unsigned char)len; - - if (RAND_bytes_ex(libctx, cid->id, len, len * 8) != 1) { - ERR_raise(ERR_LIB_SSL, ERR_R_RAND_LIB); - cid->id_len = 0; - return 0; - } - - return 1; -} -- Gitee From 8c7b98a1b491421a64e21ef3e97994156fdb11f9 Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Thu, 9 Nov 2023 09:12:51 -0500 Subject: [PATCH 85/92] augment test/run_tests.pl to filter indirect leaks When verbosity isn't set to 1 or higher, suppress indirect leaks (i.e. only print direct leaks) to make output more human-readable. Setting V=1 on make test produces all leaks (direct and indirect) Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/22678) Signed-off-by: lanming1120 --- test/run_tests.pl | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/test/run_tests.pl b/test/run_tests.pl index 90fba194b1..1f4406a49f 100644 --- a/test/run_tests.pl +++ b/test/run_tests.pl @@ -175,6 +175,7 @@ $eres = eval { my $failure_verbosity = $openssl_args{failure_verbosity}; my @plans = (); # initial level, no plan yet my $output_buffer = ""; + my $in_indirect = 0; # We rely heavily on perl closures to make failure verbosity work # We need to do so, because there's no way to safely pass extra @@ -211,7 +212,21 @@ $eres = eval { $output_buffer = ""; # ignore comments etc. until plan } elsif ($is_test) { # result of a test pop @plans if @plans && --($plans[-1]) <= 0; - print $output_buffer if !$is_ok; + if ($output_buffer =~ /.*Indirect leak of.*/ == 1) { + my @asan_array = split("\n", $output_buffer); + foreach (@asan_array) { + if ($_ =~ /.*Indirect leak of.*/ == 1) { + $in_indirect = 1; + } else { + if ($_ =~ /^ #.*/ == 0) { + $in_indirect = 0; + } + } + print "$_\n" if !$in_indirect; + } + } else { + print $output_buffer if !$is_ok; + } print "\n".$self->as_string if !$is_ok || $failure_verbosity == 2; print "\n# ------------------------------------------------------------------------------" if !$is_ok; -- Gitee From 2f4609cb89164f3f62a38beebcc5073b907cbaed Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Tue, 19 Dec 2023 06:36:02 -0500 Subject: [PATCH 86/92] Use GH action commands to group/collapse filtered output Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/22678) Signed-off-by: lanming1120 --- test/run_tests.pl | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/test/run_tests.pl b/test/run_tests.pl index 1f4406a49f..89d7fafb72 100644 --- a/test/run_tests.pl +++ b/test/run_tests.pl @@ -216,13 +216,20 @@ $eres = eval { my @asan_array = split("\n", $output_buffer); foreach (@asan_array) { if ($_ =~ /.*Indirect leak of.*/ == 1) { + if ($in_indirect != 1) { + print "::group::Indirect Leaks\n"; + } $in_indirect = 1; - } else { + } + print "$_\n"; + if ($_ =~ /.*Indirect leak of.*/ != 1) { if ($_ =~ /^ #.*/ == 0) { + if ($in_indirect != 0) { + print "\n::endgroup::\n"; + } $in_indirect = 0; } } - print "$_\n" if !$in_indirect; } } else { print $output_buffer if !$is_ok; -- Gitee From 83b6cc93177e6f84f02daf86f26b592fd40276db Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Fri, 1 Dec 2023 14:02:09 -0500 Subject: [PATCH 87/92] Make the activate setting more intuitive Currently, a provider is activated from our config file using the activate parameter. However, the presence of the config parameter is sufficient to trigger activation, leading to a counterintuitive situation in which setting "activate = 0" still activates the provider Make activation more intuitive by requiring that activate be set to one of yes|true|1 to trigger activation. Any other value, as well as omitting the parameter entirely, prevents activation (and also maintains backward compatibility. It seems a bit heavyweight to create a test specifically to validate the plurality of these settings. Instead, modify the exiting openssl config files in the test directory to use variants of these settings, and augment the default.cnf file to include a provider section that is explicitly disabled Reviewed-by: Tomas Mraz Reviewed-by: Matthias St. Pierre Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/22906) Signed-off-by: lanming1120 --- CHANGES.md | 8 ++++++++ crypto/provider_conf.c | 38 +++++++++++++++++++++++++++++++++----- doc/man5/config.pod | 7 +++++-- test/default-and-fips.cnf | 2 +- test/default.cnf | 6 +++++- test/evp_fetch_prov_test.c | 22 ++++++++++++++++++++++ 6 files changed, 74 insertions(+), 9 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index f1c8bce1b3..0f8db22dce 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -28,6 +28,14 @@ OpenSSL 3.3 ### Changes between 3.2 and 3.3 [xx XXX xxxx] + * The activate configuration setting for providers in openssl.cnf has been + updated to require a value of [1|yes|true|on] (in lower or UPPER case) to + activate the provider. Conversely a setting [0|no|false|off] will prevent + provider activation. All other values, or the omission of a value for this + setting will result in an error. + + *Neil Horman* + * In `openssl speed`, changed the default hash function used with `hmac` from `md5` to `sha256`. diff --git a/crypto/provider_conf.c b/crypto/provider_conf.c index 288ade6b4d..d8454b7941 100644 --- a/crypto/provider_conf.c +++ b/crypto/provider_conf.c @@ -236,15 +236,43 @@ static int provider_conf_load(OSSL_LIB_CTX *libctx, const char *name, /* First handle some special pseudo confs */ /* Override provider name to use */ - if (strcmp(confname, "identity") == 0) + if (strcmp(confname, "identity") == 0) { name = confvalue; - else if (strcmp(confname, "soft_load") == 0) + } else if (strcmp(confname, "soft_load") == 0) { soft = 1; /* Load a dynamic PROVIDER */ - else if (strcmp(confname, "module") == 0) + } else if (strcmp(confname, "module") == 0) { path = confvalue; - else if (strcmp(confname, "activate") == 0) - activate = 1; + } else if (strcmp(confname, "activate") == 0) { + if (confvalue == NULL) { + ERR_raise_data(ERR_LIB_CRYPTO, CRYPTO_R_PROVIDER_SECTION_ERROR, + "section=%s activate set to unrecognized value", + value); + return 0; + } + if ((strcmp(confvalue, "1") == 0) + || (strcmp(confvalue, "yes") == 0) + || (strcmp(confvalue, "YES") == 0) + || (strcmp(confvalue, "true") == 0) + || (strcmp(confvalue, "TRUE") == 0) + || (strcmp(confvalue, "on") == 0) + || (strcmp(confvalue, "ON") == 0)) { + activate = 1; + } else if ((strcmp(confvalue, "0") == 0) + || (strcmp(confvalue, "no") == 0) + || (strcmp(confvalue, "NO") == 0) + || (strcmp(confvalue, "false") == 0) + || (strcmp(confvalue, "FALSE") == 0) + || (strcmp(confvalue, "off") == 0) + || (strcmp(confvalue, "OFF") == 0)) { + activate = 0; + } else { + ERR_raise_data(ERR_LIB_CRYPTO, CRYPTO_R_PROVIDER_SECTION_ERROR, + "section=%s activate set to unrecognized value", + value); + return 0; + } + } } if (activate) { diff --git a/doc/man5/config.pod b/doc/man5/config.pod index 8d312c661f..96eaa6ffd3 100644 --- a/doc/man5/config.pod +++ b/doc/man5/config.pod @@ -265,8 +265,11 @@ Specifies the pathname of the module (typically a shared library) to load. =item B -If present, the module is activated. The value assigned to this name is not -significant. +If present and set to one of the values yes, on, true or 1, then the associated +provider will be activated. Conversely, setting this value to no, off, false, or +0 will prevent the provider from being activated. Settings can be given in lower +or uppercase. Setting activate to any other setting, or omitting a setting +value will result in an error. =back diff --git a/test/default-and-fips.cnf b/test/default-and-fips.cnf index 2ca6487fd2..71af0a385a 100644 --- a/test/default-and-fips.cnf +++ b/test/default-and-fips.cnf @@ -13,4 +13,4 @@ default = default_sect fips = fips_sect [default_sect] -activate = 1 +activate = yes diff --git a/test/default.cnf b/test/default.cnf index f29d0e92ba..21c7e070a9 100644 --- a/test/default.cnf +++ b/test/default.cnf @@ -8,6 +8,10 @@ providers = provider_sect [provider_sect] default = default_sect +legacy = legacy_sect [default_sect] -activate = 1 +activate = true + +[legacy_sect] +activate = false diff --git a/test/evp_fetch_prov_test.c b/test/evp_fetch_prov_test.c index 19e780d856..876d6ccc0a 100644 --- a/test/evp_fetch_prov_test.c +++ b/test/evp_fetch_prov_test.c @@ -121,6 +121,27 @@ static void unload_providers(OSSL_LIB_CTX **libctx, OSSL_PROVIDER *prov[]) } } +static int test_legacy_provider_unloaded(void) +{ + OSSL_LIB_CTX *ctx = NULL; + int rc = 0; + + ctx = OSSL_LIB_CTX_new(); + if (!TEST_ptr(ctx)) + goto err; + + if (!TEST_true(OSSL_LIB_CTX_load_config(ctx, config_file))) + goto err; + + if (!TEST_int_eq(OSSL_PROVIDER_available(ctx, "legacy"), 0)) + goto err; + + rc = 1; +err: + OSSL_LIB_CTX_free(ctx); + return rc; +} + static X509_ALGOR *make_algor(int nid) { X509_ALGOR *algor; @@ -379,6 +400,7 @@ int setup_tests(void) return 0; } } + ADD_TEST(test_legacy_provider_unloaded); if (strcmp(alg, "digest") == 0) { ADD_TEST(test_implicit_EVP_MD_fetch); ADD_TEST(test_explicit_EVP_MD_fetch_by_name); -- Gitee From 523c81e46a5b6c76d265948b503f7d9577ef6811 Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Thu, 30 Nov 2023 14:28:09 -0500 Subject: [PATCH 88/92] Detect and prevent recursive config parsing If a malformed config file is provided such as the following: openssl_conf = openssl_init [openssl_init] providers = provider_sect [provider_sect] = provider_sect The config parsing library will crash overflowing the stack, as it recursively parses the same provider_sect ad nauseum. Prevent this by maintaing a list of visited nodes as we recurse through referenced sections, and erroring out in the event we visit any given section node more than once. Note, adding the test for this revealed that our diagnostic code inadvertently pops recorded errors off the error stack because provider_conf_load returns success even in the event that a configuration parse failed. The call path to provider_conf_load has been updated in this commit to address that shortcoming, allowing recorded errors to be visibile to calling applications. Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/22898) Signed-off-by: lanming1120 --- crypto/conf/conf_err.c | 4 +- crypto/err/openssl.txt | 1 + crypto/provider_conf.c | 118 +++++++++++++++++++++++------ include/crypto/conferr.h | 2 +- include/openssl/conferr.h | 3 +- test/build.info | 8 +- test/prov_config_test.c | 30 ++++++++ test/recipes/30-test_prov_config.t | 7 +- test/recursive.cnf | 8 ++ 9 files changed, 150 insertions(+), 31 deletions(-) create mode 100644 test/recursive.cnf diff --git a/crypto/conf/conf_err.c b/crypto/conf/conf_err.c index 68ee90b970..9f1309c507 100644 --- a/crypto/conf/conf_err.c +++ b/crypto/conf/conf_err.c @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2023 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 @@ -41,6 +41,8 @@ static const ERR_STRING_DATA CONF_str_reasons[] = { "openssl conf references missing section"}, {ERR_PACK(ERR_LIB_CONF, 0, CONF_R_RECURSIVE_DIRECTORY_INCLUDE), "recursive directory include"}, + {ERR_PACK(ERR_LIB_CONF, 0, CONF_R_RECURSIVE_SECTION_REFERENCE), + "recursive section reference"}, {ERR_PACK(ERR_LIB_CONF, 0, CONF_R_RELATIVE_PATH), "relative path"}, {ERR_PACK(ERR_LIB_CONF, 0, CONF_R_SSL_COMMAND_SECTION_EMPTY), "ssl command section empty"}, diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt index 8e6d9ddcae..eaa568bfa8 100644 --- a/crypto/err/openssl.txt +++ b/crypto/err/openssl.txt @@ -425,6 +425,7 @@ CONF_R_NUMBER_TOO_LARGE:121:number too large CONF_R_OPENSSL_CONF_REFERENCES_MISSING_SECTION:124:\ openssl conf references missing section CONF_R_RECURSIVE_DIRECTORY_INCLUDE:111:recursive directory include +CONF_R_RECURSIVE_SECTION_REFERENCE:126:recursive section reference CONF_R_RELATIVE_PATH:125:relative path CONF_R_SSL_COMMAND_SECTION_EMPTY:117:ssl command section empty CONF_R_SSL_COMMAND_SECTION_NOT_FOUND:118:ssl command section not found diff --git a/crypto/provider_conf.c b/crypto/provider_conf.c index d8454b7941..a4a5c5122b 100644 --- a/crypto/provider_conf.c +++ b/crypto/provider_conf.c @@ -64,13 +64,22 @@ static const char *skip_dot(const char *name) return name; } -static int provider_conf_params(OSSL_PROVIDER *prov, - OSSL_PROVIDER_INFO *provinfo, - const char *name, const char *value, - const CONF *cnf) +/* + * Parse the provider params section + * Returns: + * 1 for success + * 0 for non-fatal errors + * < 0 for fatal errors + */ +static int provider_conf_params_internal(OSSL_PROVIDER *prov, + OSSL_PROVIDER_INFO *provinfo, + const char *name, const char *value, + const CONF *cnf, + STACK_OF(OPENSSL_CSTRING) *visited) { STACK_OF(CONF_VALUE) *sect; int ok = 1; + int rc = 0; sect = NCONF_get_section(cnf, value); if (sect != NULL) { @@ -80,6 +89,25 @@ static int provider_conf_params(OSSL_PROVIDER *prov, OSSL_TRACE1(CONF, "Provider params: start section %s\n", value); + /* + * Check to see if the provided section value has already + * been visited. If it has, then we have a recursive lookup + * in the configuration which isn't valid. As such we should error + * out + */ + for (i = 0; i < sk_OPENSSL_CSTRING_num(visited); i++) { + if (sk_OPENSSL_CSTRING_value(visited, i) == value) { + ERR_raise(ERR_LIB_CONF, CONF_R_RECURSIVE_SECTION_REFERENCE); + return -1; + } + } + + /* + * We've not visited this node yet, so record it on the stack + */ + if (!sk_OPENSSL_CSTRING_push(visited, value)) + return -1; + if (name != NULL) { OPENSSL_strlcpy(buffer, name, sizeof(buffer)); OPENSSL_strlcat(buffer, ".", sizeof(buffer)); @@ -89,14 +117,20 @@ static int provider_conf_params(OSSL_PROVIDER *prov, for (i = 0; i < sk_CONF_VALUE_num(sect); i++) { CONF_VALUE *sectconf = sk_CONF_VALUE_value(sect, i); - if (buffer_len + strlen(sectconf->name) >= sizeof(buffer)) - return 0; + if (buffer_len + strlen(sectconf->name) >= sizeof(buffer)) { + sk_OPENSSL_CSTRING_pop(visited); + return -1; + } buffer[buffer_len] = '\0'; OPENSSL_strlcat(buffer, sectconf->name, sizeof(buffer)); - if (!provider_conf_params(prov, provinfo, buffer, sectconf->value, - cnf)) - return 0; + rc = provider_conf_params_internal(prov, provinfo, buffer, + sectconf->value, cnf, visited); + if (rc < 0) { + sk_OPENSSL_CSTRING_pop(visited); + return rc; + } } + sk_OPENSSL_CSTRING_pop(visited); OSSL_TRACE1(CONF, "Provider params: finish section %s\n", value); } else { @@ -110,6 +144,33 @@ static int provider_conf_params(OSSL_PROVIDER *prov, return ok; } +/* + * recursively parse the provider configuration section + * of the config file. + * Returns + * 1 on success + * 0 on non-fatal error + * < 0 on fatal errors + */ +static int provider_conf_params(OSSL_PROVIDER *prov, + OSSL_PROVIDER_INFO *provinfo, + const char *name, const char *value, + const CONF *cnf) +{ + int rc; + STACK_OF(OPENSSL_CSTRING) *visited = sk_OPENSSL_CSTRING_new_null(); + + if (visited == NULL) + return -1; + + rc = provider_conf_params_internal(prov, provinfo, name, + value, cnf, visited); + + sk_OPENSSL_CSTRING_free(visited); + + return rc; +} + static int prov_already_activated(const char *name, STACK_OF(OSSL_PROVIDER) *activated) { @@ -130,6 +191,13 @@ static int prov_already_activated(const char *name, return 0; } +/* + * Attempt to activate a provider + * Returns: + * 1 on successful activation + * 0 on failed activation for non-fatal error + * < 0 on failed activation for fatal errors + */ static int provider_conf_activate(OSSL_LIB_CTX *libctx, const char *name, const char *value, const char *path, int soft, const CONF *cnf) @@ -141,7 +209,7 @@ static int provider_conf_activate(OSSL_LIB_CTX *libctx, const char *name, if (pcgbl == NULL || !CRYPTO_THREAD_write_lock(pcgbl->lock)) { ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR); - return 0; + return -1; } if (!prov_already_activated(name, pcgbl->activated_providers)) { /* @@ -154,7 +222,7 @@ static int provider_conf_activate(OSSL_LIB_CTX *libctx, const char *name, if (!ossl_provider_disable_fallback_loading(libctx)) { CRYPTO_THREAD_unlock(pcgbl->lock); ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR); - return 0; + return -1; } prov = ossl_provider_find(libctx, name, 1); if (prov == NULL) @@ -163,7 +231,7 @@ static int provider_conf_activate(OSSL_LIB_CTX *libctx, const char *name, CRYPTO_THREAD_unlock(pcgbl->lock); if (soft) ERR_clear_error(); - return 0; + return (soft == 0) ? -1 : 0; } if (path != NULL) @@ -171,7 +239,7 @@ static int provider_conf_activate(OSSL_LIB_CTX *libctx, const char *name, ok = provider_conf_params(prov, NULL, NULL, value, cnf); - if (ok) { + if (ok == 1) { if (!ossl_provider_activate(prov, 1, 0)) { ok = 0; } else if (!ossl_provider_add_to_store(prov, &actual, 0)) { @@ -195,7 +263,8 @@ static int provider_conf_activate(OSSL_LIB_CTX *libctx, const char *name, } } } - if (!ok) + + if (ok <= 0) ossl_provider_free(prov); } CRYPTO_THREAD_unlock(pcgbl->lock); @@ -212,6 +281,7 @@ static int provider_conf_load(OSSL_LIB_CTX *libctx, const char *name, const char *path = NULL; long activate = 0; int ok = 0; + int added = 0; name = skip_dot(name); OSSL_TRACE1(CONF, "Configuring provider %s\n", name); @@ -294,19 +364,23 @@ static int provider_conf_load(OSSL_LIB_CTX *libctx, const char *name, } if (ok) ok = provider_conf_params(NULL, &entry, NULL, value, cnf); - if (ok && (entry.path != NULL || entry.parameters != NULL)) + if (ok >= 1 && (entry.path != NULL || entry.parameters != NULL)) { ok = ossl_provider_info_add_to_store(libctx, &entry); - if (!ok || (entry.path == NULL && entry.parameters == NULL)) { - ossl_provider_info_clear(&entry); + added = 1; } - + if (added == 0) + ossl_provider_info_clear(&entry); } /* - * Even if ok is 0, we still return success. Failure to load a provider is - * not fatal. We want to continue to load the rest of the config file. + * Provider activation returns a tristate: + * 1 for successful activation + * 0 for non-fatal activation failure + * < 0 for fatal activation failure + * We return success (1) for activation, (1) for non-fatal activation + * failure, and (0) for fatal activation failure */ - return 1; + return ok >= 0; } static int provider_conf_init(CONF_IMODULE *md, const CONF *cnf) @@ -329,7 +403,7 @@ static int provider_conf_init(CONF_IMODULE *md, const CONF *cnf) for (i = 0; i < sk_CONF_VALUE_num(elist); i++) { cval = sk_CONF_VALUE_value(elist, i); if (!provider_conf_load(NCONF_get0_libctx((CONF *)cnf), - cval->name, cval->value, cnf)) + cval->name, cval->value, cnf)) return 0; } diff --git a/include/crypto/conferr.h b/include/crypto/conferr.h index cb367e4f32..fc9645127d 100644 --- a/include/crypto/conferr.h +++ b/include/crypto/conferr.h @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2020-2023 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 diff --git a/include/openssl/conferr.h b/include/openssl/conferr.h index 496e2e1efd..a8798e7924 100644 --- a/include/openssl/conferr.h +++ b/include/openssl/conferr.h @@ -1,6 +1,6 @@ /* * Generated by util/mkerr.pl DO NOT EDIT - * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2023 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 @@ -38,6 +38,7 @@ # define CONF_R_NUMBER_TOO_LARGE 121 # define CONF_R_OPENSSL_CONF_REFERENCES_MISSING_SECTION 124 # define CONF_R_RECURSIVE_DIRECTORY_INCLUDE 111 +# define CONF_R_RECURSIVE_SECTION_REFERENCE 126 # define CONF_R_RELATIVE_PATH 125 # define CONF_R_SSL_COMMAND_SECTION_EMPTY 117 # define CONF_R_SSL_COMMAND_SECTION_NOT_FOUND 118 diff --git a/test/build.info b/test/build.info index af43407611..88620b86b3 100644 --- a/test/build.info +++ b/test/build.info @@ -60,10 +60,10 @@ IF[{- !$disabled{tests} -}] context_internal_test aesgcmtest params_test evp_pkey_dparams_test \ keymgmt_internal_test hexstr_test provider_status_test defltfips_test \ bio_readbuffer_test user_property_test pkcs7_test upcallstest \ - provfetchtest prov_config_test rand_test ca_internals_test \ - bio_tfo_test membio_test bio_dgram_test list_test fips_version_test \ - x509_test hpke_test pairwise_fail_test nodefltctxtest \ - evp_xof_test x509_load_cert_file_test + provfetchtest prov_config_test rand_test \ + ca_internals_test bio_tfo_test membio_test bio_dgram_test list_test \ + fips_version_test x509_test hpke_test pairwise_fail_test \ + nodefltctxtest evp_xof_test x509_load_cert_file_test IF[{- !$disabled{'rpk'} -}] PROGRAMS{noinst}=rpktest diff --git a/test/prov_config_test.c b/test/prov_config_test.c index 4b04211fa4..b44ec78d8d 100644 --- a/test/prov_config_test.c +++ b/test/prov_config_test.c @@ -8,9 +8,11 @@ */ #include +#include #include "testutil.h" static char *configfile = NULL; +static char *recurseconfigfile = NULL; /* * Test to make sure there are no leaks or failures from loading the config @@ -44,6 +46,30 @@ static int test_double_config(void) return testresult; } +static int test_recursive_config(void) +{ + OSSL_LIB_CTX *ctx = OSSL_LIB_CTX_new(); + int testresult = 0; + unsigned long err; + + if (!TEST_ptr(recurseconfigfile)) + goto err; + + if (!TEST_ptr(ctx)) + goto err; + + if (!TEST_false(OSSL_LIB_CTX_load_config(ctx, recurseconfigfile))) + goto err; + + err = ERR_peek_error(); + /* We expect to get a recursion error here */ + if (ERR_GET_REASON(err) == CONF_R_RECURSIVE_SECTION_REFERENCE) + testresult = 1; + err: + OSSL_LIB_CTX_free(ctx); + return testresult; +} + OPT_TEST_DECLARE_USAGE("configfile\n") int setup_tests(void) @@ -56,6 +82,10 @@ int setup_tests(void) if (!TEST_ptr(configfile = test_get_argument(0))) return 0; + if (!TEST_ptr(recurseconfigfile = test_get_argument(1))) + return 0; + + ADD_TEST(test_recursive_config); ADD_TEST(test_double_config); return 1; } diff --git a/test/recipes/30-test_prov_config.t b/test/recipes/30-test_prov_config.t index f97a26dbe9..7f6350fd84 100644 --- a/test/recipes/30-test_prov_config.t +++ b/test/recipes/30-test_prov_config.t @@ -22,11 +22,14 @@ my $no_fips = disabled('fips') || ($ENV{NO_FIPS} // 0); plan tests => 2; -ok(run(test(["prov_config_test", srctop_file("test", "default.cnf")])), +ok(run(test(["prov_config_test", srctop_file("test", "default.cnf"), + srctop_file("test", "recursive.cnf")])), "running prov_config_test default.cnf"); + SKIP: { skip "Skipping FIPS test in this build", 1 if $no_fips; - ok(run(test(["prov_config_test", srctop_file("test", "fips.cnf")])), + ok(run(test(["prov_config_test", srctop_file("test", "fips.cnf"), + srctop_file("test", "recursive.cnf")])), "running prov_config_test fips.cnf"); } diff --git a/test/recursive.cnf b/test/recursive.cnf new file mode 100644 index 0000000000..505733ae45 --- /dev/null +++ b/test/recursive.cnf @@ -0,0 +1,8 @@ +openssl_conf = openssl_init +config_diagnostics = yes + +[openssl_init] +providers = provider_sect + +[provider_sect] + = provider_sect -- Gitee From e51b845b147753e2e4e3082191e85869a5a90b36 Mon Sep 17 00:00:00 2001 From: Rajeev Ranjan Date: Mon, 13 Mar 2023 09:16:57 +0100 Subject: [PATCH 89/92] crypto/cmp/,apps/lib/cmp_mock_srv.c: add delayed delivery for all types of responses Reviewed-by: Shane Lontis Reviewed-by: Tomas Mraz Reviewed-by: David von Oheimb (Merged from https://github.com/openssl/openssl/pull/20727) Signed-off-by: lanming1120 --- apps/lib/cmp_mock_srv.c | 83 +++++++++++-- crypto/cmp/cmp_client.c | 191 +++++++++++++++++++++++++----- crypto/cmp/cmp_ctx.c | 5 + crypto/cmp/cmp_local.h | 6 + crypto/cmp/cmp_msg.c | 10 ++ crypto/cmp/cmp_server.c | 164 ++++++++++++++++++------- crypto/cmp/cmp_vfy.c | 21 +++- doc/man3/OSSL_CMP_SRV_CTX_new.pod | 12 ++ fuzz/cmp.c | 15 ++- include/openssl/cmp.h.in | 8 ++ test/cmp_client_test.c | 68 ++++++++--- test/cmp_server_test.c | 1 + util/libcrypto.num | 1 + util/other.syms | 2 + 14 files changed, 477 insertions(+), 110 deletions(-) diff --git a/apps/lib/cmp_mock_srv.c b/apps/lib/cmp_mock_srv.c index d58937ea78..edfb1d0c75 100644 --- a/apps/lib/cmp_mock_srv.c +++ b/apps/lib/cmp_mock_srv.c @@ -27,7 +27,7 @@ typedef struct X509 *oldWithNew; /* to return in oldWithNew of rootKeyUpdate */ OSSL_CMP_PKISI *statusOut; /* status for ip/cp/kup/rp msg unless polling */ int sendError; /* send error response on given request type */ - OSSL_CMP_MSG *certReq; /* ir/cr/p10cr/kur remembered while polling */ + OSSL_CMP_MSG *req; /* original request message during polling */ int pollCount; /* number of polls before actual cert response */ int curr_pollCount; /* number of polls so far for current request */ int checkAfterTime; /* time the client should wait between polling */ @@ -43,7 +43,7 @@ static void mock_srv_ctx_free(mock_srv_ctx *ctx) X509_free(ctx->certOut); OSSL_STACK_OF_X509_free(ctx->chainOut); OSSL_STACK_OF_X509_free(ctx->caPubsOut); - OSSL_CMP_MSG_free(ctx->certReq); + OSSL_CMP_MSG_free(ctx->req); OPENSSL_free(ctx); } @@ -183,6 +183,44 @@ int ossl_cmp_mock_srv_set_checkAfterTime(OSSL_CMP_SRV_CTX *srv_ctx, int sec) return 1; } +static int delayed_delivery(OSSL_CMP_SRV_CTX *srv_ctx, + const OSSL_CMP_MSG *req) +{ + mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx); + int req_type = OSSL_CMP_MSG_get_bodytype(req); + + if (ctx == NULL || req == NULL) { + ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); + return 0; + } + + /* + * For ir/cr/p10cr/kur delayed delivery is handled separately in + * process_cert_request + */ + if (req_type == OSSL_CMP_IR + || req_type == OSSL_CMP_CR + || req_type == OSSL_CMP_P10CR + || req_type == OSSL_CMP_KUR + /* Client may use error to abort the ongoing polling */ + || req_type == OSSL_CMP_ERROR) + return 0; + + if (ctx->pollCount > 0 && ctx->curr_pollCount == 0) { + /* start polling */ + if (ctx->req != NULL) { /* TODO: move this check to cmp_server.c */ + /* already in polling mode */ + ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY); + return 0; + } + if ((ctx->req = OSSL_CMP_MSG_dup(req)) == NULL) + return -1; + + return 1; + } + return 0; +} + /* check for matching reference cert components, as far as given */ static int refcert_cmp(const X509 *refcert, const X509_NAME *issuer, const ASN1_INTEGER *serial) @@ -198,6 +236,23 @@ static int refcert_cmp(const X509 *refcert, && (ref_serial == NULL || ASN1_INTEGER_cmp(serial, ref_serial) == 0); } +/* Reset dynamic variable in case of incomplete tansaction */ +static int reset_transaction(OSSL_CMP_SRV_CTX *srv_ctx) +{ + mock_srv_ctx *ctx = NULL; + + if (srv_ctx == NULL) { + ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); + return 0; + } + + ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx); + ctx->curr_pollCount = 0; + OSSL_CMP_MSG_free(ctx->req); + ctx->req = NULL; + return 1; +} + static OSSL_CMP_PKISI *process_cert_request(OSSL_CMP_SRV_CTX *srv_ctx, const OSSL_CMP_MSG *cert_req, ossl_unused int certReqId, @@ -228,12 +283,12 @@ static OSSL_CMP_PKISI *process_cert_request(OSSL_CMP_SRV_CTX *srv_ctx, if (ctx->pollCount > 0 && ctx->curr_pollCount == 0) { /* start polling */ - if (ctx->certReq != NULL) { + if (ctx->req != NULL) { /* already in polling mode */ ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY); return NULL; } - if ((ctx->certReq = OSSL_CMP_MSG_dup(cert_req)) == NULL) + if ((ctx->req = OSSL_CMP_MSG_dup(cert_req)) == NULL) return NULL; return OSSL_CMP_STATUSINFO_new(OSSL_CMP_PKISTATUS_waiting, 0, NULL); } @@ -481,35 +536,35 @@ static int process_certConf(OSSL_CMP_SRV_CTX *srv_ctx, static int process_pollReq(OSSL_CMP_SRV_CTX *srv_ctx, const OSSL_CMP_MSG *pollReq, ossl_unused int certReqId, - OSSL_CMP_MSG **certReq, int64_t *check_after) + OSSL_CMP_MSG **req, int64_t *check_after) { mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx); if (ctx == NULL || pollReq == NULL - || certReq == NULL || check_after == NULL) { + || req == NULL || check_after == NULL) { ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); return 0; } if (ctx->sendError == 1 || ctx->sendError == OSSL_CMP_MSG_get_bodytype(pollReq)) { - *certReq = NULL; + *req = NULL; ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_PROCESSING_MESSAGE); return 0; } - if (ctx->certReq == NULL) { + if (ctx->req == NULL) { /* TODO: move this check to cmp_server.c */ /* not currently in polling mode */ - *certReq = NULL; + *req = NULL; ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY); return 0; } if (++ctx->curr_pollCount >= ctx->pollCount) { /* end polling */ - *certReq = ctx->certReq; - ctx->certReq = NULL; + *req = ctx->req; + ctx->req = NULL; *check_after = 0; } else { - *certReq = NULL; + *req = NULL; *check_after = ctx->checkAfterTime; } return 1; @@ -523,7 +578,9 @@ OSSL_CMP_SRV_CTX *ossl_cmp_mock_srv_new(OSSL_LIB_CTX *libctx, const char *propq) if (srv_ctx != NULL && ctx != NULL && OSSL_CMP_SRV_CTX_init(srv_ctx, ctx, process_cert_request, process_rr, process_genm, process_error, - process_certConf, process_pollReq)) + process_certConf, process_pollReq) + && OSSL_CMP_SRV_CTX_setup_polling(srv_ctx, reset_transaction, + delayed_delivery)) return srv_ctx; mock_srv_ctx_free(ctx); diff --git a/crypto/cmp/cmp_client.c b/crypto/cmp/cmp_client.c index b5b0557b0d..cf352c9d71 100644 --- a/crypto/cmp/cmp_client.c +++ b/crypto/cmp/cmp_client.c @@ -113,6 +113,23 @@ static int save_statusInfo(OSSL_CMP_CTX *ctx, OSSL_CMP_PKISI *si) return 1; } +static int is_crep_with_waiting(OSSL_CMP_MSG *resp, int rid) +{ + OSSL_CMP_CERTREPMESSAGE *crepmsg; + OSSL_CMP_CERTRESPONSE *crep; + int bt = OSSL_CMP_MSG_get_bodytype(resp); + + if (!IS_CREP(bt)) + return 0; + + crepmsg = resp->body->value.ip; /* same for cp and kup */ + crep = ossl_cmp_certrepmessage_get0_certresponse(crepmsg, rid); + + return (crep != NULL + && ossl_cmp_pkisi_get_status(crep->status) + == OSSL_CMP_PKISTATUS_waiting); +} + /*- * Perform the generic aspects of sending a request and receiving a response. * Returns 1 on success and provides the received PKIMESSAGE in *rep. @@ -180,7 +197,8 @@ static int send_receive_check(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *req, * Still we use this preliminary value already for a progress report because * the following msg verification may also produce log entries and may fail. */ - ossl_cmp_log1(INFO, ctx, "received %s", ossl_cmp_bodytype_to_string(bt)); + ossl_cmp_log2(INFO, ctx, "received %s%s", ossl_cmp_bodytype_to_string(bt), + ossl_cmp_is_error_with_waiting(*rep) ? " (waiting)" : ""); /* copy received extraCerts to ctx->extraCertsIn so they can be retrieved */ if (bt != OSSL_CMP_PKIBODY_POLLREP && bt != OSSL_CMP_PKIBODY_PKICONF @@ -191,9 +209,17 @@ static int send_receive_check(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *req, expected_type)) return 0; + /* + * 'rep' can have the expected response type, which during polling is + * pollRep. When polling, also any other non-error response (the final + * response) is fine here. When not yet polling, delayed delivery may + * be started by an error with 'waiting' status (while it may also be + * started by an expected response type ip/cp/kup). + */ if (bt == expected_type - /* as an answer to polling, there could be IP/CP/KUP: */ - || (IS_CREP(bt) && expected_type == OSSL_CMP_PKIBODY_POLLREP)) + || (expected_type == OSSL_CMP_PKIBODY_POLLREP + ? bt != OSSL_CMP_PKIBODY_ERROR + : ossl_cmp_is_error_with_waiting(*rep))) return 1; /* received message type is not one of the expected ones (e.g., error) */ @@ -235,7 +261,7 @@ static int send_receive_check(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *req, /*- * When a 'waiting' PKIStatus has been received, this function is used to - * poll, which should yield a pollRep or finally a CertRepMessage in ip/cp/kup. + * poll, which should yield a pollRep or the final response. * On receiving a pollRep, which includes a checkAfter value, it return this * value if sleep == 0, else it sleeps as long as indicated and retries. * @@ -246,7 +272,8 @@ static int send_receive_check(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *req, * Returns -1 on receiving pollRep if sleep == 0, setting the checkAfter value. * Returns 1 on success and provides the received PKIMESSAGE in *rep. * In this case the caller is responsible for freeing *rep. - * Returns 0 on error (which includes the case that timeout has been reached). + * Returns 0 on error (which includes the case that timeout has been reached or + * received response with waiting status). */ static int poll_for_response(OSSL_CMP_CTX *ctx, int sleep, int rid, OSSL_CMP_MSG **rep, int *checkAfter) @@ -312,7 +339,7 @@ static int poll_for_response(OSSL_CMP_CTX *ctx, int sleep, int rid, str, check_after); if (ctx->total_timeout != 0) { /* timeout is not infinite */ - const int exp = 5; /* expected max time per msg round trip */ + const int exp = OSSL_CMP_EXPECTED_RESP_TIME; int64_t time_left = (int64_t)(ctx->end_time - exp - time(NULL)); if (time_left <= 0) { @@ -335,9 +362,19 @@ static int poll_for_response(OSSL_CMP_CTX *ctx, int sleep, int rid, *checkAfter = (int)check_after; return -1; /* exits the loop */ } + } else if (is_crep_with_waiting(prep, rid) + || ossl_cmp_is_error_with_waiting(prep)) { + /* status cannot be 'waiting' at this point */ + (void)ossl_cmp_exchange_error(ctx, OSSL_CMP_PKISTATUS_rejection, + OSSL_CMP_CTX_FAILINFO_badRequest, + "polling already started", + 0 /* errorCode */, NULL); + ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKISTATUS); + goto err; } else { - ossl_cmp_info(ctx, "received ip/cp/kup after polling"); - /* any other body type has been rejected by send_receive_check() */ + ossl_cmp_info(ctx, "received final response after polling"); + if (!ossl_cmp_ctx_set1_first_senderNonce(ctx, NULL)) + return 0; break; } } @@ -349,11 +386,66 @@ static int poll_for_response(OSSL_CMP_CTX *ctx, int sleep, int rid, return 1; err: + (void)ossl_cmp_ctx_set1_first_senderNonce(ctx, NULL); OSSL_CMP_MSG_free(preq); OSSL_CMP_MSG_free(prep); return 0; } +static int save_senderNonce_if_waiting(OSSL_CMP_CTX *ctx, + OSSL_CMP_MSG *rep, int rid) +{ + /* + * LWCMP section 4.4 states: the senderNonce of the preceding request + * message because this value will be needed for checking the recipNonce + * of the final response to be received after polling. + */ + if ((is_crep_with_waiting(rep, rid) + || ossl_cmp_is_error_with_waiting(rep)) + && !ossl_cmp_ctx_set1_first_senderNonce(ctx, ctx->senderNonce)) + return 0; + + return 1; +} + +/* + * send request and get response possibly with polling initiated by error msg. + * Polling for ip/cp/kup/ with 'waiting' status is handled elsewhere. + */ +static int send_receive_also_delayed(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *req, + OSSL_CMP_MSG **rep, int expected_type) +{ + + if (!send_receive_check(ctx, req, rep, expected_type)) + return 0; + + if (ossl_cmp_is_error_with_waiting(*rep)) { + if (!save_senderNonce_if_waiting(ctx, *rep, -1 /* rid */)) + return 0; + /* + * not modifying ctx->status during the certConf & error exchange, + * because these additional exchanges should not change the status. + */ + if (expected_type != OSSL_CMP_PKIBODY_PKICONF + && !save_statusInfo(ctx, (*rep)->body->value.error->pKIStatusInfo)) + return 0; + + OSSL_CMP_MSG_free(*rep); + *rep = NULL; + + if (poll_for_response(ctx, 1 /* can sleep */, -1 /* rid */, + rep, NULL /* checkAfter */) <= 0) { + ERR_raise(ERR_LIB_CMP, CMP_R_POLLING_FAILED); + return 0; + } + } + if (OSSL_CMP_MSG_get_bodytype(*rep) != expected_type) { + ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY); + return 0; + } + + return 1; +} /* * Send certConf for IR, CR or KUR sequences and check response, * not modifying ctx->status during the certConf exchange @@ -370,7 +462,8 @@ int ossl_cmp_exchange_certConf(OSSL_CMP_CTX *ctx, int certReqId, if (certConf == NULL) goto err; - res = send_receive_check(ctx, certConf, &PKIconf, OSSL_CMP_PKIBODY_PKICONF); + res = send_receive_also_delayed(ctx, certConf, + &PKIconf, OSSL_CMP_PKIBODY_PKICONF); err: OSSL_CMP_MSG_free(certConf); @@ -394,7 +487,8 @@ int ossl_cmp_exchange_error(OSSL_CMP_CTX *ctx, int status, int fail_info, if ((error = ossl_cmp_error_new(ctx, si, errorCode, details, 0)) == NULL) goto err; - res = send_receive_check(ctx, error, &PKIconf, OSSL_CMP_PKIBODY_PKICONF); + res = send_receive_also_delayed(ctx, error, + &PKIconf, OSSL_CMP_PKIBODY_PKICONF); err: OSSL_CMP_MSG_free(error); @@ -515,7 +609,7 @@ int OSSL_CMP_certConf_cb(OSSL_CMP_CTX *ctx, X509 *cert, int fail_info, if (X509_verify_cert(csc) <= 0) goto err; - if (!ossl_x509_add_certs_new(&chain, X509_STORE_CTX_get0_chain(csc), + if (!ossl_x509_add_certs_new(&chain, X509_STORE_CTX_get0_chain(csc), X509_ADD_FLAG_UP_REF | X509_ADD_FLAG_NO_DUP | X509_ADD_FLAG_NO_SS)) { sk_X509_free(chain); @@ -564,48 +658,74 @@ static int cert_response(OSSL_CMP_CTX *ctx, int sleep, int rid, EVP_PKEY *rkey = ossl_cmp_ctx_get0_newPubkey(ctx); int fail_info = 0; /* no failure */ const char *txt = NULL; - OSSL_CMP_CERTREPMESSAGE *crepmsg; - OSSL_CMP_CERTRESPONSE *crep; + OSSL_CMP_CERTREPMESSAGE *crepmsg = NULL; + OSSL_CMP_CERTRESPONSE *crep = NULL; OSSL_CMP_certConf_cb_t cb; X509 *cert; char *subj = NULL; int ret = 1; + int rcvd_type; + OSSL_CMP_PKISI *si; if (!ossl_assert(ctx != NULL)) return 0; retry: - crepmsg = (*resp)->body->value.ip; /* same for cp and kup */ - if (sk_OSSL_CMP_CERTRESPONSE_num(crepmsg->response) > 1) { - ERR_raise(ERR_LIB_CMP, CMP_R_MULTIPLE_RESPONSES_NOT_SUPPORTED); - return 0; - } - crep = ossl_cmp_certrepmessage_get0_certresponse(crepmsg, rid); - if (crep == NULL) - return 0; - if (!save_statusInfo(ctx, crep->status)) - return 0; - if (rid == OSSL_CMP_CERTREQID_NONE) { /* used for OSSL_CMP_PKIBODY_P10CR */ - rid = ossl_cmp_asn1_get_int(crep->certReqId); - if (rid < OSSL_CMP_CERTREQID_NONE) { - ERR_raise(ERR_LIB_CMP, CMP_R_BAD_REQUEST_ID); + rcvd_type = OSSL_CMP_MSG_get_bodytype(*resp); + if (IS_CREP(rcvd_type)) { + crepmsg = (*resp)->body->value.ip; /* same for cp and kup */ + if (sk_OSSL_CMP_CERTRESPONSE_num(crepmsg->response) > 1) { + ERR_raise(ERR_LIB_CMP, CMP_R_MULTIPLE_RESPONSES_NOT_SUPPORTED); return 0; } + crep = ossl_cmp_certrepmessage_get0_certresponse(crepmsg, rid); + if (crep == NULL) + return 0; + si = crep->status; + + if (rid == OSSL_CMP_CERTREQID_NONE) { + /* for OSSL_CMP_PKIBODY_P10CR learn CertReqId from response */ + rid = ossl_cmp_asn1_get_int(crep->certReqId); + if (rid == OSSL_CMP_CERTREQID_NONE) { + ERR_raise(ERR_LIB_CMP, CMP_R_BAD_REQUEST_ID); + return 0; + } + } + } else if (rcvd_type == OSSL_CMP_PKIBODY_ERROR) { + si = (*resp)->body->value.error->pKIStatusInfo; + } else { + ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY); + return 0; } - if (ossl_cmp_pkisi_get_status(crep->status) == OSSL_CMP_PKISTATUS_waiting) { + if (!save_statusInfo(ctx, si)) + return 0; + + if (ossl_cmp_pkisi_get_status(si) == OSSL_CMP_PKISTATUS_waiting) { + /* here we allow different flavor of ip/cp/kup & error with waiting */ OSSL_CMP_MSG_free(*resp); *resp = NULL; if ((ret = poll_for_response(ctx, sleep, rid, resp, checkAfter)) != 0) { if (ret == -1) /* at this point implies sleep == 0 */ return ret; /* waiting */ - goto retry; /* got ip/cp/kup, which may still indicate 'waiting' */ + goto retry; /* got some response other than pollRep */ } else { ERR_raise(ERR_LIB_CMP, CMP_R_POLLING_FAILED); return 0; } } + /* at this point, ip/cp/kup or error without waiting */ + if (rcvd_type == OSSL_CMP_PKIBODY_ERROR) { + ERR_raise(ERR_LIB_CMP, CMP_R_RECEIVED_ERROR); + return 0; + } + /* here we are strict on the flavor of ip/cp/kup */ + if (rcvd_type != expected_type) { + ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY); + return 0; + } + cert = get1_cert_status(ctx, (*resp)->body->type, crep); if (cert == NULL) { ERR_add_error_data(1, "; cannot extract certificate from response"); @@ -618,7 +738,8 @@ static int cert_response(OSSL_CMP_CTX *ctx, int sleep, int rid, * if the CMP server returned certificates in the caPubs field, copy them * to the context so that they can be retrieved if necessary */ - if (crepmsg->caPubs != NULL + if (crepmsg != NULL + && crepmsg->caPubs != NULL && !ossl_cmp_ctx_set1_caPubs(ctx, crepmsg->caPubs)) return 0; @@ -709,6 +830,9 @@ int OSSL_CMP_try_certreq(OSSL_CMP_CTX *ctx, int req_type, if (ctx->status != OSSL_CMP_PKISTATUS_waiting) { /* not polling already */ if (!initial_certreq(ctx, req_type, crm, &rep, rep_type)) goto err; + + if (!save_senderNonce_if_waiting(ctx, rep, rid)) + return 0; } else { if (req_type < 0) return ossl_cmp_exchange_error(ctx, OSSL_CMP_PKISTATUS_rejection, @@ -750,6 +874,9 @@ X509 *OSSL_CMP_exec_certreq(OSSL_CMP_CTX *ctx, int req_type, if (!initial_certreq(ctx, req_type, crm, &rep, rep_type)) goto err; + if (!save_senderNonce_if_waiting(ctx, rep, rid)) + return 0; + if (cert_response(ctx, 1 /* sleep */, rid, &rep, NULL, req_type, rep_type) <= 0) goto err; @@ -787,7 +914,7 @@ int OSSL_CMP_exec_RR_ses(OSSL_CMP_CTX *ctx) goto end; ctx->status = OSSL_CMP_PKISTATUS_trans; - if (!send_receive_check(ctx, rr, &rp, OSSL_CMP_PKIBODY_RP)) + if (!send_receive_also_delayed(ctx, rr, &rp, OSSL_CMP_PKIBODY_RP)) goto end; rrep = rp->body->value.rp; @@ -908,7 +1035,7 @@ STACK_OF(OSSL_CMP_ITAV) *OSSL_CMP_exec_GENM_ses(OSSL_CMP_CTX *ctx) goto err; ctx->status = OSSL_CMP_PKISTATUS_trans; - if (!send_receive_check(ctx, genm, &genp, OSSL_CMP_PKIBODY_GENP)) + if (!send_receive_also_delayed(ctx, genm, &genp, OSSL_CMP_PKIBODY_GENP)) goto err; ctx->status = OSSL_CMP_PKISTATUS_accepted; diff --git a/crypto/cmp/cmp_ctx.c b/crypto/cmp/cmp_ctx.c index 5e542200e9..cc62ae4e4e 100644 --- a/crypto/cmp/cmp_ctx.c +++ b/crypto/cmp/cmp_ctx.c @@ -183,6 +183,7 @@ int OSSL_CMP_CTX_reinit(OSSL_CMP_CTX *ctx) && ossl_cmp_ctx_set1_caPubs(ctx, NULL) && ossl_cmp_ctx_set1_extraCertsIn(ctx, NULL) && ossl_cmp_ctx_set1_validatedSrvCert(ctx, NULL) + && ossl_cmp_ctx_set1_first_senderNonce(ctx, NULL) && OSSL_CMP_CTX_set1_transactionID(ctx, NULL) && OSSL_CMP_CTX_set1_senderNonce(ctx, NULL) && ossl_cmp_ctx_set1_recipNonce(ctx, NULL); @@ -226,6 +227,7 @@ void OSSL_CMP_CTX_free(OSSL_CMP_CTX *ctx) ASN1_OCTET_STRING_free(ctx->transactionID); ASN1_OCTET_STRING_free(ctx->senderNonce); ASN1_OCTET_STRING_free(ctx->recipNonce); + ASN1_OCTET_STRING_free(ctx->first_senderNonce); OSSL_CMP_ITAVs_free(ctx->geninfo_ITAVs); OSSL_STACK_OF_X509_free(ctx->extraCertsOut); @@ -814,6 +816,9 @@ DEFINE_set1_ASN1_OCTET_STRING(ossl_cmp_ctx, recipNonce) /* Stores the given nonce as the last senderNonce sent out */ DEFINE_set1_ASN1_OCTET_STRING(OSSL_CMP_CTX, senderNonce) +/* store the first req sender nonce for verifying delayed delivery */ +DEFINE_set1_ASN1_OCTET_STRING(ossl_cmp_ctx, first_senderNonce) + /* Set the proxy server to use for HTTP(S) connections */ DEFINE_OSSL_CMP_CTX_set1(proxy, char) diff --git a/crypto/cmp/cmp_local.h b/crypto/cmp/cmp_local.h index b8da48ac43..175cc2575c 100644 --- a/crypto/cmp/cmp_local.h +++ b/crypto/cmp/cmp_local.h @@ -95,6 +95,7 @@ struct ossl_cmp_ctx_st { ASN1_OCTET_STRING *transactionID; /* the current transaction ID */ ASN1_OCTET_STRING *senderNonce; /* last nonce sent */ ASN1_OCTET_STRING *recipNonce; /* last nonce received */ + ASN1_OCTET_STRING *first_senderNonce; /* sender nonce when starting to poll */ ASN1_UTF8STRING *freeText; /* optional string to include each msg */ STACK_OF(OSSL_CMP_ITAV) *geninfo_ITAVs; int implicitConfirm; /* set implicitConfirm in IR/KUR/CR messages */ @@ -823,6 +824,8 @@ int ossl_cmp_ctx_set1_extraCertsIn(OSSL_CMP_CTX *ctx, int ossl_cmp_ctx_set1_recipNonce(OSSL_CMP_CTX *ctx, const ASN1_OCTET_STRING *nonce); EVP_PKEY *ossl_cmp_ctx_get0_newPubkey(const OSSL_CMP_CTX *ctx); +int ossl_cmp_ctx_set1_first_senderNonce(OSSL_CMP_CTX *ctx, + const ASN1_OCTET_STRING *nonce); /* from cmp_status.c */ int ossl_cmp_pkisi_get_status(const OSSL_CMP_PKISI *si); @@ -939,6 +942,7 @@ ossl_cmp_certrepmessage_get0_certresponse(const OSSL_CMP_CERTREPMESSAGE *crm, X509 *ossl_cmp_certresponse_get1_cert(const OSSL_CMP_CTX *ctx, const OSSL_CMP_CERTRESPONSE *crep); OSSL_CMP_MSG *ossl_cmp_msg_load(const char *file); +int ossl_cmp_is_error_with_waiting(const OSSL_CMP_MSG *msg); /* from cmp_protect.c */ int ossl_cmp_msg_add_extraCerts(OSSL_CMP_CTX *ctx, OSSL_CMP_MSG *msg); @@ -958,6 +962,8 @@ int ossl_cmp_verify_popo(const OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg, int accept_RAVerified); /* from cmp_client.c */ +/* expected max time per msg round trip, used for last try during polling: */ +# define OSSL_CMP_EXPECTED_RESP_TIME 2 int ossl_cmp_exchange_certConf(OSSL_CMP_CTX *ctx, int certReqId, int fail_info, const char *txt); int ossl_cmp_exchange_error(OSSL_CMP_CTX *ctx, int status, int fail_info, diff --git a/crypto/cmp/cmp_msg.c b/crypto/cmp/cmp_msg.c index e00afc809e..1b9e275d7a 100644 --- a/crypto/cmp/cmp_msg.c +++ b/crypto/cmp/cmp_msg.c @@ -1200,3 +1200,13 @@ int i2d_OSSL_CMP_MSG_bio(BIO *bio, const OSSL_CMP_MSG *msg) { return ASN1_i2d_bio_of(OSSL_CMP_MSG, i2d_OSSL_CMP_MSG, bio, msg); } + +int ossl_cmp_is_error_with_waiting(const OSSL_CMP_MSG *msg) +{ + if (!ossl_assert(msg != NULL)) + return 0; + + return (OSSL_CMP_MSG_get_bodytype(msg) == OSSL_CMP_PKIBODY_ERROR + && ossl_cmp_pkisi_get_status(msg->body->value.error->pKIStatusInfo) + == OSSL_CMP_PKISTATUS_waiting); +} diff --git a/crypto/cmp/cmp_server.c b/crypto/cmp/cmp_server.c index 06ef8fbb61..1e3ca15e89 100644 --- a/crypto/cmp/cmp_server.c +++ b/crypto/cmp/cmp_server.c @@ -32,6 +32,8 @@ struct ossl_cmp_srv_ctx_st OSSL_CMP_SRV_error_cb_t process_error; OSSL_CMP_SRV_certConf_cb_t process_certConf; OSSL_CMP_SRV_pollReq_cb_t process_pollReq; + OSSL_CMP_SRV_reset_transaction_cb_t reset_transaction; + OSSL_CMP_SRV_delayed_delivery_cb_t delayed_delivery; int sendUnprotectedErrors; /* Send error and rejection msgs unprotected */ int acceptUnprotected; /* Accept requests with no/invalid prot. */ @@ -89,6 +91,19 @@ int OSSL_CMP_SRV_CTX_init(OSSL_CMP_SRV_CTX *srv_ctx, void *custom_ctx, return 1; } +int OSSL_CMP_SRV_CTX_setup_polling(OSSL_CMP_SRV_CTX *srv_ctx, + OSSL_CMP_SRV_reset_transaction_cb_t reset_transaction, + OSSL_CMP_SRV_delayed_delivery_cb_t delayed_delivery) +{ + if (srv_ctx == NULL) { + ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); + return 0; + } + srv_ctx->reset_transaction = reset_transaction; + srv_ctx->delayed_delivery = delayed_delivery; + return 1; +} + OSSL_CMP_CTX *OSSL_CMP_SRV_CTX_get0_cmp_ctx(const OSSL_CMP_SRV_CTX *srv_ctx) { if (srv_ctx == NULL) { @@ -149,6 +164,32 @@ int OSSL_CMP_SRV_CTX_set_grant_implicit_confirm(OSSL_CMP_SRV_CTX *srv_ctx, return 1; } +/* Return error msg with waiting status if polling is initiated, else NULL. */ +static OSSL_CMP_MSG *delayed_delivery(OSSL_CMP_SRV_CTX *srv_ctx, + const OSSL_CMP_MSG *req) +{ + OSSL_CMP_MSG *msg = NULL; + OSSL_CMP_PKISI *si = NULL; + int ret; + + if (!ossl_assert(srv_ctx != NULL && srv_ctx->ctx != NULL && req != NULL + && srv_ctx->delayed_delivery != NULL)) + return NULL; + + ret = srv_ctx->delayed_delivery(srv_ctx, req); + if (ret == 0 || !ossl_assert(ret != -1)) + return NULL; + + if ((si = OSSL_CMP_STATUSINFO_new(OSSL_CMP_PKISTATUS_waiting, 0, NULL)) + == NULL) + return NULL; + + msg = ossl_cmp_error_new(srv_ctx->ctx, si, 0, + NULL, srv_ctx->sendUnprotectedErrors); + OSSL_CMP_PKISI_free(si); + return msg; +} + /* * Processes an ir/cr/p10cr/kur and returns a certification response. * Only handles the first certification request contained in req @@ -387,13 +428,66 @@ static OSSL_CMP_MSG *process_certConf(OSSL_CMP_SRV_CTX *srv_ctx, return msg; } +/* pollreq should be handled separately, to avoid recursive call */ +static OSSL_CMP_MSG *process_non_polling_request(OSSL_CMP_SRV_CTX *srv_ctx, + const OSSL_CMP_MSG *req) +{ + OSSL_CMP_MSG *rsp = NULL; + + if (!ossl_assert(srv_ctx != NULL && srv_ctx->ctx != NULL && req != NULL + && req->body != NULL)) + return NULL; + + switch (OSSL_CMP_MSG_get_bodytype(req)) { + case OSSL_CMP_PKIBODY_IR: + case OSSL_CMP_PKIBODY_CR: + case OSSL_CMP_PKIBODY_P10CR: + case OSSL_CMP_PKIBODY_KUR: + if (srv_ctx->process_cert_request == NULL) + ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY); + else + rsp = process_cert_request(srv_ctx, req); + break; + case OSSL_CMP_PKIBODY_RR: + if (srv_ctx->process_rr == NULL) + ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY); + else + rsp = process_rr(srv_ctx, req); + break; + case OSSL_CMP_PKIBODY_GENM: + if (srv_ctx->process_genm == NULL) + ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY); + else + rsp = process_genm(srv_ctx, req); + break; + case OSSL_CMP_PKIBODY_ERROR: + if (srv_ctx->process_error == NULL) + ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY); + else + rsp = process_error(srv_ctx, req); + break; + case OSSL_CMP_PKIBODY_CERTCONF: + if (srv_ctx->process_certConf == NULL) + ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY); + else + rsp = process_certConf(srv_ctx, req); + break; + default: + /* Other request message types are not supported */ + ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY); + break; + } + + return rsp; +} + static OSSL_CMP_MSG *process_pollReq(OSSL_CMP_SRV_CTX *srv_ctx, const OSSL_CMP_MSG *req) { OSSL_CMP_POLLREQCONTENT *prc; OSSL_CMP_POLLREQ *pr; int certReqId; - OSSL_CMP_MSG *certReq; + OSSL_CMP_MSG *orig_req; int64_t check_after = 0; OSSL_CMP_MSG *msg = NULL; @@ -413,12 +507,12 @@ static OSSL_CMP_MSG *process_pollReq(OSSL_CMP_SRV_CTX *srv_ctx, return NULL; } if (!srv_ctx->process_pollReq(srv_ctx, req, certReqId, - &certReq, &check_after)) + &orig_req, &check_after)) return NULL; - if (certReq != NULL) { - msg = process_cert_request(srv_ctx, certReq); - OSSL_CMP_MSG_free(certReq); + if (orig_req != NULL) { + msg = process_non_polling_request(srv_ctx, orig_req); + OSSL_CMP_MSG_free(orig_req); } else { if ((msg = ossl_cmp_pollRep_new(srv_ctx->ctx, certReqId, check_after)) == NULL) @@ -509,6 +603,10 @@ OSSL_CMP_MSG *OSSL_CMP_SRV_process_request(OSSL_CMP_SRV_CTX *srv_ctx, if (!OSSL_CMP_CTX_set1_transactionID(ctx, NULL) || !OSSL_CMP_CTX_set1_senderNonce(ctx, NULL)) goto err; + + if (srv_ctx->reset_transaction != NULL) + (void)srv_ctx->reset_transaction(srv_ctx); + break; default: /* transactionID should be already initialized */ @@ -528,50 +626,17 @@ OSSL_CMP_MSG *OSSL_CMP_SRV_process_request(OSSL_CMP_SRV_CTX *srv_ctx, if (!req_verified) goto err; - switch (req_type) { - case OSSL_CMP_PKIBODY_IR: - case OSSL_CMP_PKIBODY_CR: - case OSSL_CMP_PKIBODY_P10CR: - case OSSL_CMP_PKIBODY_KUR: - if (srv_ctx->process_cert_request == NULL) - ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY); - else - rsp = process_cert_request(srv_ctx, req); - break; - case OSSL_CMP_PKIBODY_RR: - if (srv_ctx->process_rr == NULL) - ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY); - else - rsp = process_rr(srv_ctx, req); - break; - case OSSL_CMP_PKIBODY_GENM: - if (srv_ctx->process_genm == NULL) - ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY); - else - rsp = process_genm(srv_ctx, req); - break; - case OSSL_CMP_PKIBODY_ERROR: - if (srv_ctx->process_error == NULL) - ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY); - else - rsp = process_error(srv_ctx, req); - break; - case OSSL_CMP_PKIBODY_CERTCONF: - if (srv_ctx->process_certConf == NULL) - ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY); - else - rsp = process_certConf(srv_ctx, req); - break; - case OSSL_CMP_PKIBODY_POLLREQ: + if (req_type == OSSL_CMP_PKIBODY_POLLREQ) { if (srv_ctx->process_pollReq == NULL) ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY); else rsp = process_pollReq(srv_ctx, req); - break; - default: - /* Other request message types are not supported */ - ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY); - break; + } else { + if (srv_ctx->delayed_delivery != NULL + && (rsp = delayed_delivery(srv_ctx, req)) != NULL) { + goto err; + } + rsp = process_non_polling_request(srv_ctx, req); } err: @@ -627,15 +692,22 @@ OSSL_CMP_MSG *OSSL_CMP_SRV_process_request(OSSL_CMP_SRV_CTX *srv_ctx, break; /* fall through */ + case OSSL_CMP_PKIBODY_ERROR: + if (rsp != NULL + && ossl_cmp_is_error_with_waiting(rsp)) + break; + /* fall through */ + case OSSL_CMP_PKIBODY_RP: case OSSL_CMP_PKIBODY_PKICONF: case OSSL_CMP_PKIBODY_GENP: - case OSSL_CMP_PKIBODY_ERROR: /* Other terminating response message types are not supported */ /* Prepare for next transaction, ignoring any errors here: */ (void)OSSL_CMP_CTX_set1_transactionID(ctx, NULL); (void)OSSL_CMP_CTX_set1_senderNonce(ctx, NULL); ctx->status = OSSL_CMP_PKISTATUS_unspecified; /* transaction closed */ + if (srv_ctx->reset_transaction != NULL) + (void)srv_ctx->reset_transaction(srv_ctx); default: /* not closing transaction in other cases */ break; diff --git a/crypto/cmp/cmp_vfy.c b/crypto/cmp/cmp_vfy.c index 1869fae696..8d4de1017d 100644 --- a/crypto/cmp/cmp_vfy.c +++ b/crypto/cmp/cmp_vfy.c @@ -786,10 +786,27 @@ int ossl_cmp_msg_check_update(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg, CMP_R_TRANSACTIONID_UNMATCHED)) return 0; + /* + * enable clearing irrelevant errors in attempts to validate recipient nonce + * in case of delayed delivery. + */ + (void)ERR_set_mark(); /* compare received nonce with the one we sent */ if (!check_transactionID_or_nonce(ctx->senderNonce, hdr->recipNonce, - CMP_R_RECIPNONCE_UNMATCHED)) - return 0; + CMP_R_RECIPNONCE_UNMATCHED)) { + /* check if we are polling and received final response */ + if (ctx->first_senderNonce == NULL + || OSSL_CMP_MSG_get_bodytype(msg) == OSSL_CMP_PKIBODY_POLLREP + /* compare received nonce with our sender nonce at poll start */ + || !check_transactionID_or_nonce(ctx->first_senderNonce, + hdr->recipNonce, + CMP_R_RECIPNONCE_UNMATCHED)) { + (void)ERR_clear_last_mark(); + return 0; + } + } + /* discard any intermediate error while trying to check recipient nonce */ + (void)ERR_pop_to_mark(); /* if not yet present, learn transactionID */ if (ctx->transactionID == NULL diff --git a/doc/man3/OSSL_CMP_SRV_CTX_new.pod b/doc/man3/OSSL_CMP_SRV_CTX_new.pod index d7f1a2e4db..fada992e3d 100644 --- a/doc/man3/OSSL_CMP_SRV_CTX_new.pod +++ b/doc/man3/OSSL_CMP_SRV_CTX_new.pod @@ -12,7 +12,10 @@ OSSL_CMP_SRV_certConf_cb_t, OSSL_CMP_SRV_genm_cb_t, OSSL_CMP_SRV_error_cb_t, OSSL_CMP_SRV_pollReq_cb_t, +OSSL_CMP_SRV_reset_transaction_cb_t, +OSSL_CMP_SRV_delayed_delivery_cb_t, OSSL_CMP_SRV_CTX_init, +OSSL_CMP_SRV_CTX_setup_polling, OSSL_CMP_SRV_CTX_get0_cmp_ctx, OSSL_CMP_SRV_CTX_get0_custom_ctx, OSSL_CMP_SRV_CTX_set_send_unprotected_errors, @@ -64,6 +67,9 @@ OSSL_CMP_SRV_CTX_set_grant_implicit_confirm int certReqId, OSSL_CMP_MSG **certReq, int64_t *check_after); + typedef int (*OSSL_CMP_SRV_reset_transaction_cb_t)(OSSL_CMP_SRV_CTX *srv_ctx); + typedef int (*OSSL_CMP_SRV_delayed_delivery_cb_t)(OSSL_CMP_SRV_CTX *srv_ctx, + const OSSL_CMP_MSG *req); int OSSL_CMP_SRV_CTX_init(OSSL_CMP_SRV_CTX *srv_ctx, void *custom_ctx, OSSL_CMP_SRV_cert_request_cb_t process_cert_request, OSSL_CMP_SRV_rr_cb_t process_rr, @@ -71,6 +77,9 @@ OSSL_CMP_SRV_CTX_set_grant_implicit_confirm OSSL_CMP_SRV_error_cb_t process_error, OSSL_CMP_SRV_certConf_cb_t process_certConf, OSSL_CMP_SRV_pollReq_cb_t process_pollReq); + int OSSL_CMP_SRV_CTX_setup_polling(OSSL_CMP_SRV_CTX *srv_ctx, + OSSL_CMP_SRV_reset_transaction_cb_t reset_transaction, + OSSL_CMP_SRV_delayed_delivery_cb_t delayed_delivery); OSSL_CMP_CTX *OSSL_CMP_SRV_CTX_get0_cmp_ctx(const OSSL_CMP_SRV_CTX *srv_ctx); void *OSSL_CMP_SRV_CTX_get0_custom_ctx(const OSSL_CMP_SRV_CTX *srv_ctx); @@ -113,6 +122,9 @@ All arguments except I may be NULL. If a callback for some message type is not given this means that the respective type of CMP message is not supported by the server. +OSSL_CMP_SRV_CTX_setup_polling() sets in the given I callback functions +for reseting transaction and intitiating delayed delivery. + OSSL_CMP_SRV_CTX_get0_cmp_ctx() returns the B from the I. OSSL_CMP_SRV_CTX_get0_custom_ctx() returns the custom server context from diff --git a/fuzz/cmp.c b/fuzz/cmp.c index 490c4211f8..37b6c310c3 100644 --- a/fuzz/cmp.c +++ b/fuzz/cmp.c @@ -155,6 +155,17 @@ static int process_pollReq(OSSL_CMP_SRV_CTX *srv_ctx, return 0; } +static int reset_transaction(OSSL_CMP_SRV_CTX *srv_ctx) +{ + return 1; +} + +static int delayed_delivery(OSSL_CMP_SRV_CTX *srv_ctx, + const OSSL_CMP_MSG *req) +{ + return 0; +} + int FuzzerTestOneInput(const uint8_t *buf, size_t len) { OSSL_CMP_MSG *msg; @@ -183,7 +194,9 @@ int FuzzerTestOneInput(const uint8_t *buf, size_t len) print_noop) && OSSL_CMP_SRV_CTX_init(srv_ctx, NULL, process_cert_request, process_rr, process_genm, process_error, - process_certConf, process_pollReq)) + process_certConf, process_pollReq) + && OSSL_CMP_SRV_CTX_setup_polling(srv_ctx, reset_transaction, + delayed_delivery)) OSSL_CMP_MSG_free(OSSL_CMP_SRV_process_request(srv_ctx, msg)); OSSL_CMP_CTX_free(client_ctx); diff --git a/include/openssl/cmp.h.in b/include/openssl/cmp.h.in index fa4fe000ba..2e92510446 100644 --- a/include/openssl/cmp.h.in +++ b/include/openssl/cmp.h.in @@ -469,6 +469,9 @@ typedef int (*OSSL_CMP_SRV_pollReq_cb_t)(OSSL_CMP_SRV_CTX *srv_ctx, const OSSL_CMP_MSG *req, int certReqId, OSSL_CMP_MSG **certReq, int64_t *check_after); +typedef int (*OSSL_CMP_SRV_reset_transaction_cb_t)(OSSL_CMP_SRV_CTX *srv_ctx); +typedef int (*OSSL_CMP_SRV_delayed_delivery_cb_t)(OSSL_CMP_SRV_CTX *srv_ctx, + const OSSL_CMP_MSG *req); int OSSL_CMP_SRV_CTX_init(OSSL_CMP_SRV_CTX *srv_ctx, void *custom_ctx, OSSL_CMP_SRV_cert_request_cb_t process_cert_request, OSSL_CMP_SRV_rr_cb_t process_rr, @@ -476,6 +479,9 @@ int OSSL_CMP_SRV_CTX_init(OSSL_CMP_SRV_CTX *srv_ctx, void *custom_ctx, OSSL_CMP_SRV_error_cb_t process_error, OSSL_CMP_SRV_certConf_cb_t process_certConf, OSSL_CMP_SRV_pollReq_cb_t process_pollReq); +int OSSL_CMP_SRV_CTX_setup_polling(OSSL_CMP_SRV_CTX *srv_ctx, + OSSL_CMP_SRV_reset_transaction_cb_t reset_transaction, + OSSL_CMP_SRV_delayed_delivery_cb_t delayed_delivery); OSSL_CMP_CTX *OSSL_CMP_SRV_CTX_get0_cmp_ctx(const OSSL_CMP_SRV_CTX *srv_ctx); void *OSSL_CMP_SRV_CTX_get0_custom_ctx(const OSSL_CMP_SRV_CTX *srv_ctx); int OSSL_CMP_SRV_CTX_set_send_unprotected_errors(OSSL_CMP_SRV_CTX *srv_ctx, @@ -492,6 +498,8 @@ X509 *OSSL_CMP_exec_certreq(OSSL_CMP_CTX *ctx, int req_type, # define OSSL_CMP_CR 2 # define OSSL_CMP_P10CR 4 # define OSSL_CMP_KUR 7 +# define OSSL_CMP_GENM 21 +# define OSSL_CMP_ERROR 23 # define OSSL_CMP_exec_IR_ses(ctx) \ OSSL_CMP_exec_certreq(ctx, OSSL_CMP_IR, NULL) # define OSSL_CMP_exec_CR_ses(ctx) \ diff --git a/test/cmp_client_test.c b/test/cmp_client_test.c index 44c369bc90..ad78c86ec2 100644 --- a/test/cmp_client_test.c +++ b/test/cmp_client_test.c @@ -184,7 +184,7 @@ static int test_exec_RR_ses_receive_error(void) static int test_exec_IR_ses(void) { SETUP_TEST_FIXTURE(CMP_SES_TEST_FIXTURE, set_up); - fixture->req_type = OSSL_CMP_IR; + fixture->req_type = OSSL_CMP_PKIBODY_IR; fixture->expected = OSSL_CMP_PKISTATUS_accepted; fixture->caPubs = sk_X509_new_null(); sk_X509_push(fixture->caPubs, server_cert); @@ -194,42 +194,55 @@ static int test_exec_IR_ses(void) return result; } -static int test_exec_IR_ses_poll(int check_after, int poll_count, - int total_timeout, int expect) +static int test_exec_any_ses_poll(int req_type, int check_after, + int poll_count, int total_timeout, + int expect) { SETUP_TEST_FIXTURE(CMP_SES_TEST_FIXTURE, set_up); - fixture->req_type = OSSL_CMP_IR; + fixture->req_type = req_type; fixture->expected = expect; ossl_cmp_mock_srv_set_checkAfterTime(fixture->srv_ctx, check_after); ossl_cmp_mock_srv_set_pollCount(fixture->srv_ctx, poll_count); OSSL_CMP_CTX_set_option(fixture->cmp_ctx, OSSL_CMP_OPT_TOTAL_TIMEOUT, total_timeout); - EXECUTE_TEST(execute_exec_certrequest_ses_test, tear_down); + + if (req_type == OSSL_CMP_PKIBODY_IR || req_type == OSSL_CMP_PKIBODY_CR + || req_type == OSSL_CMP_PKIBODY_KUR + || req_type == OSSL_CMP_PKIBODY_P10CR) { + EXECUTE_TEST(execute_exec_certrequest_ses_test, tear_down); + } else if (req_type == OSSL_CMP_PKIBODY_GENM) { + EXECUTE_TEST(execute_exec_GENM_ses_test, tear_down); + } else { + result = 0; + } return result; } static int checkAfter = 1; static int test_exec_IR_ses_poll_ok(void) { - return test_exec_IR_ses_poll(checkAfter, 2, 0, OSSL_CMP_PKISTATUS_accepted); + return test_exec_any_ses_poll(OSSL_CMP_PKIBODY_IR, checkAfter, 2, 0, + OSSL_CMP_PKISTATUS_accepted); } static int test_exec_IR_ses_poll_no_timeout(void) { - return test_exec_IR_ses_poll(checkAfter, 1 /* pollCount */, checkAfter + 1, - OSSL_CMP_PKISTATUS_accepted); + return test_exec_any_ses_poll(OSSL_CMP_PKIBODY_IR, checkAfter, + 2 /* pollCount */, checkAfter + 4, + OSSL_CMP_PKISTATUS_accepted); } static int test_exec_IR_ses_poll_total_timeout(void) { - return test_exec_IR_ses_poll(checkAfter + 1, 2 /* pollCount */, checkAfter, - OSSL_CMP_PKISTATUS_waiting); + return !test_exec_any_ses_poll(OSSL_CMP_PKIBODY_IR, checkAfter + 1, + 3 /* pollCount */, checkAfter + 6, + OSSL_CMP_PKISTATUS_waiting); } static int test_exec_CR_ses(int implicit_confirm, int granted, int reject) { SETUP_TEST_FIXTURE(CMP_SES_TEST_FIXTURE, set_up); - fixture->req_type = OSSL_CMP_CR; + fixture->req_type = OSSL_CMP_PKIBODY_CR; OSSL_CMP_CTX_set_option(fixture->cmp_ctx, OSSL_CMP_OPT_IMPLICIT_CONFIRM, implicit_confirm); OSSL_CMP_SRV_CTX_set_grant_implicit_confirm(fixture->srv_ctx, granted); @@ -256,7 +269,7 @@ static int test_exec_CR_ses_implicit_confirm(void) static int test_exec_KUR_ses(int transfer_error, int pubkey, int raverified) { SETUP_TEST_FIXTURE(CMP_SES_TEST_FIXTURE, set_up); - fixture->req_type = OSSL_CMP_KUR; + fixture->req_type = OSSL_CMP_PKIBODY_KUR; /* ctx->oldCert has already been set */ if (transfer_error) @@ -324,7 +337,7 @@ static int test_exec_P10CR_ses(int reject) X509_REQ *csr = NULL; SETUP_TEST_FIXTURE(CMP_SES_TEST_FIXTURE, set_up); - fixture->req_type = OSSL_CMP_P10CR; + fixture->req_type = OSSL_CMP_PKIBODY_P10CR; fixture->expected = reject ? OSSL_CMP_PKISTATUS_rejection : OSSL_CMP_PKISTATUS_accepted; ctx = fixture->cmp_ctx; @@ -354,8 +367,8 @@ static int execute_try_certreq_poll_test(CMP_SES_TEST_FIXTURE *fixture) { OSSL_CMP_CTX *ctx = fixture->cmp_ctx; int check_after; - const int CHECK_AFTER = 5; - const int TYPE = OSSL_CMP_KUR; + const int CHECK_AFTER = 0; + const int TYPE = OSSL_CMP_PKIBODY_KUR; ossl_cmp_mock_srv_set_pollCount(fixture->srv_ctx, 3); ossl_cmp_mock_srv_set_checkAfterTime(fixture->srv_ctx, CHECK_AFTER); @@ -384,7 +397,7 @@ static int execute_try_certreq_poll_abort_test(CMP_SES_TEST_FIXTURE *fixture) OSSL_CMP_CTX *ctx = fixture->cmp_ctx; int check_after; const int CHECK_AFTER = 99; - const int TYPE = OSSL_CMP_CR; + const int TYPE = OSSL_CMP_PKIBODY_CR; ossl_cmp_mock_srv_set_pollCount(fixture->srv_ctx, 3); ossl_cmp_mock_srv_set_checkAfterTime(fixture->srv_ctx, CHECK_AFTER); @@ -404,6 +417,26 @@ static int test_try_certreq_poll_abort(void) return result; } +static int test_exec_GENM_ses_poll_ok(void) +{ + return test_exec_any_ses_poll(OSSL_CMP_PKIBODY_GENM, checkAfter, 2, 0, + OSSL_CMP_PKISTATUS_accepted); +} + +static int test_exec_GENM_ses_poll_no_timeout(void) +{ + return test_exec_any_ses_poll(OSSL_CMP_PKIBODY_GENM, checkAfter, + 1 /* pollCount */, checkAfter + 1, + OSSL_CMP_PKISTATUS_accepted); +} + +static int test_exec_GENM_ses_poll_total_timeout(void) +{ + return test_exec_any_ses_poll(OSSL_CMP_PKIBODY_GENM, checkAfter + 1, + 3 /* pollCount */, checkAfter + 2, + OSSL_CMP_PKISTATUS_waiting); +} + static int test_exec_GENM_ses(int transfer_error, int total_timeout, int expect) { SETUP_TEST_FIXTURE(CMP_SES_TEST_FIXTURE, set_up); @@ -539,6 +572,9 @@ int setup_tests(void) ADD_TEST(test_exec_GENM_ses_ok); ADD_TEST(test_exec_GENM_ses_transfer_error); ADD_TEST(test_exec_GENM_ses_total_timeout); + ADD_TEST(test_exec_GENM_ses_poll_ok); + ADD_TEST(test_exec_GENM_ses_poll_no_timeout); + ADD_TEST(test_exec_GENM_ses_poll_total_timeout); ADD_TEST(test_exchange_certConf); ADD_TEST(test_exchange_error); return 1; diff --git a/test/cmp_server_test.c b/test/cmp_server_test.c index e270bb924b..e375ae3d9c 100644 --- a/test/cmp_server_test.c +++ b/test/cmp_server_test.c @@ -76,6 +76,7 @@ static int execute_test_handle_request(CMP_SRV_TEST_FIXTURE *fixture) if (!TEST_true(OSSL_CMP_SRV_CTX_init(ctx, dummy_custom_ctx, process_cert_request, NULL, NULL, NULL, NULL, NULL)) + || !TEST_true(OSSL_CMP_SRV_CTX_setup_polling(ctx, NULL, NULL)) || !TEST_ptr(custom_ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(ctx)) || !TEST_int_eq(strcmp(custom_ctx, dummy_custom_ctx), 0)) goto end; diff --git a/util/libcrypto.num b/util/libcrypto.num index 0b72559f86..6b7e6c212b 100644 --- a/util/libcrypto.num +++ b/util/libcrypto.num @@ -5540,5 +5540,6 @@ OSSL_CMP_CTX_get0_geninfo_ITAVs ? 3_3_0 EXIST::FUNCTION:CMP OSSL_CMP_HDR_get0_geninfo_ITAVs ? 3_3_0 EXIST::FUNCTION:CMP OSSL_CMP_ITAV_new0_certProfile ? 3_3_0 EXIST::FUNCTION:CMP OSSL_CMP_ITAV_get0_certProfile ? 3_3_0 EXIST::FUNCTION:CMP +OSSL_CMP_SRV_CTX_setup_polling ? 3_3_0 EXIST::FUNCTION:CMP EVP_DigestSqueeze ? 3_3_0 EXIST::FUNCTION: ERR_pop ? 3_3_0 EXIST::FUNCTION: diff --git a/util/other.syms b/util/other.syms index fa7a59d6a8..bf7eb8b22e 100644 --- a/util/other.syms +++ b/util/other.syms @@ -461,6 +461,8 @@ OSSL_CMP_SRV_certConf_cb_t datatype OSSL_CMP_SRV_genm_cb_t datatype OSSL_CMP_SRV_error_cb_t datatype OSSL_CMP_SRV_pollReq_cb_t datatype +OSSL_CMP_SRV_delayed_delivery_cb_t datatype +OSSL_CMP_SRV_clean_transaction_cb_t datatype OSSL_CORE_MAKE_FUNC define OSSL_PARAM_TYPE define OSSL_PARAM_octet_ptr define -- Gitee From 7acb5b0e201d9a046867b064694d45480b6dbd38 Mon Sep 17 00:00:00 2001 From: "Dr. David von Oheimb" Date: Fri, 28 Apr 2023 13:45:21 +0200 Subject: [PATCH 90/92] crypto/cmp/,apps/lib/cmp_mock_srv.c: various improvements on delayed delivery Reviewed-by: Shane Lontis Reviewed-by: Tomas Mraz Reviewed-by: David von Oheimb (Merged from https://github.com/openssl/openssl/pull/20727) Signed-off-by: lanming1120 --- CHANGES.md | 1 + apps/lib/cmp_mock_srv.c | 35 ++++++------- crypto/cmp/cmp_client.c | 60 ++++++++++----------- crypto/cmp/cmp_err.c | 4 ++ crypto/cmp/cmp_msg.c | 3 +- crypto/cmp/cmp_server.c | 84 +++++++++++++++--------------- crypto/cmp/cmp_vfy.c | 5 +- crypto/err/openssl.txt | 3 ++ doc/man3/OSSL_CMP_SRV_CTX_new.pod | 38 ++++++++++---- doc/man3/OSSL_CMP_exec_certreq.pod | 13 +++-- fuzz/cmp.c | 11 ++-- include/openssl/cmp.h.in | 13 ++--- include/openssl/cmperr.h | 3 ++ test/cmp_client_test.c | 20 +++---- test/cmp_server_test.c | 2 +- util/libcrypto.num | 2 +- 16 files changed, 163 insertions(+), 134 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 0f8db22dce..271af03894 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -43,6 +43,7 @@ OpenSSL 3.3 * Added several new features of CMPv3 defined in RFC 9480 and RFC 9483: - `certProfile` request message header and respective `-profile` CLI option + - support for delayed delivery of all types of response messages *David von Oheimb* diff --git a/apps/lib/cmp_mock_srv.c b/apps/lib/cmp_mock_srv.c index edfb1d0c75..d44c3581e7 100644 --- a/apps/lib/cmp_mock_srv.c +++ b/apps/lib/cmp_mock_srv.c @@ -183,15 +183,15 @@ int ossl_cmp_mock_srv_set_checkAfterTime(OSSL_CMP_SRV_CTX *srv_ctx, int sec) return 1; } -static int delayed_delivery(OSSL_CMP_SRV_CTX *srv_ctx, - const OSSL_CMP_MSG *req) +/* determine whether to delay response to (non-polling) request */ +static int delayed_delivery(OSSL_CMP_SRV_CTX *srv_ctx, const OSSL_CMP_MSG *req) { mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx); int req_type = OSSL_CMP_MSG_get_bodytype(req); if (ctx == NULL || req == NULL) { ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); - return 0; + return -1; } /* @@ -211,11 +211,10 @@ static int delayed_delivery(OSSL_CMP_SRV_CTX *srv_ctx, if (ctx->req != NULL) { /* TODO: move this check to cmp_server.c */ /* already in polling mode */ ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY); - return 0; + return -1; } if ((ctx->req = OSSL_CMP_MSG_dup(req)) == NULL) return -1; - return 1; } return 0; @@ -236,17 +235,17 @@ static int refcert_cmp(const X509 *refcert, && (ref_serial == NULL || ASN1_INTEGER_cmp(serial, ref_serial) == 0); } -/* Reset dynamic variable in case of incomplete tansaction */ -static int reset_transaction(OSSL_CMP_SRV_CTX *srv_ctx) +/* reset the state that belongs to a transaction */ +static int clean_transaction(OSSL_CMP_SRV_CTX *srv_ctx, + ossl_unused const ASN1_OCTET_STRING *id) { - mock_srv_ctx *ctx = NULL; + mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx); - if (srv_ctx == NULL) { + if (ctx == NULL) { ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); return 0; } - ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx); ctx->curr_pollCount = 0; OSSL_CMP_MSG_free(ctx->req); ctx->req = NULL; @@ -533,6 +532,7 @@ static int process_certConf(OSSL_CMP_SRV_CTX *srv_ctx, return 1; } +/* return 0 on failure, 1 on success, setting *req or otherwise *check_after */ static int process_pollReq(OSSL_CMP_SRV_CTX *srv_ctx, const OSSL_CMP_MSG *pollReq, ossl_unused int certReqId, @@ -540,21 +540,21 @@ static int process_pollReq(OSSL_CMP_SRV_CTX *srv_ctx, { mock_srv_ctx *ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(srv_ctx); + if (req != NULL) + *req = NULL; if (ctx == NULL || pollReq == NULL || req == NULL || check_after == NULL) { ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); return 0; } + if (ctx->sendError == 1 || ctx->sendError == OSSL_CMP_MSG_get_bodytype(pollReq)) { - *req = NULL; ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_PROCESSING_MESSAGE); return 0; } - if (ctx->req == NULL) { /* TODO: move this check to cmp_server.c */ - /* not currently in polling mode */ - *req = NULL; - ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY); + if (ctx->req == NULL) { /* not currently in polling mode */ + ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_POLLREQ); return 0; } @@ -564,7 +564,6 @@ static int process_pollReq(OSSL_CMP_SRV_CTX *srv_ctx, ctx->req = NULL; *check_after = 0; } else { - *req = NULL; *check_after = ctx->checkAfterTime; } return 1; @@ -579,8 +578,8 @@ OSSL_CMP_SRV_CTX *ossl_cmp_mock_srv_new(OSSL_LIB_CTX *libctx, const char *propq) && OSSL_CMP_SRV_CTX_init(srv_ctx, ctx, process_cert_request, process_rr, process_genm, process_error, process_certConf, process_pollReq) - && OSSL_CMP_SRV_CTX_setup_polling(srv_ctx, reset_transaction, - delayed_delivery)) + && OSSL_CMP_SRV_CTX_init_trans(srv_ctx, + delayed_delivery, clean_transaction)) return srv_ctx; mock_srv_ctx_free(ctx); diff --git a/crypto/cmp/cmp_client.c b/crypto/cmp/cmp_client.c index cf352c9d71..23b3a8bd05 100644 --- a/crypto/cmp/cmp_client.c +++ b/crypto/cmp/cmp_client.c @@ -113,7 +113,7 @@ static int save_statusInfo(OSSL_CMP_CTX *ctx, OSSL_CMP_PKISI *si) return 1; } -static int is_crep_with_waiting(OSSL_CMP_MSG *resp, int rid) +static int is_crep_with_waiting(const OSSL_CMP_MSG *resp, int rid) { OSSL_CMP_CERTREPMESSAGE *crepmsg; OSSL_CMP_CERTRESPONSE *crep; @@ -210,11 +210,11 @@ static int send_receive_check(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *req, return 0; /* - * 'rep' can have the expected response type, which during polling is - * pollRep. When polling, also any other non-error response (the final - * response) is fine here. When not yet polling, delayed delivery may - * be started by an error with 'waiting' status (while it may also be - * started by an expected response type ip/cp/kup). + * rep can have the expected response type, which during polling is pollRep. + * When polling, also any other non-error response (the final response) + * is fine here. When not yet polling, delayed delivery may be initiated + * by the server returning an error message with 'waiting' status (or a + * response message of expected type ip/cp/kup with 'waiting' status). */ if (bt == expected_type || (expected_type == OSSL_CMP_PKIBODY_POLLREP @@ -272,8 +272,8 @@ static int send_receive_check(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *req, * Returns -1 on receiving pollRep if sleep == 0, setting the checkAfter value. * Returns 1 on success and provides the received PKIMESSAGE in *rep. * In this case the caller is responsible for freeing *rep. - * Returns 0 on error (which includes the case that timeout has been reached or - * received response with waiting status). + * Returns 0 on error (which includes the cases that timeout has been reached + * or a response with 'waiting' status has been received). */ static int poll_for_response(OSSL_CMP_CTX *ctx, int sleep, int rid, OSSL_CMP_MSG **rep, int *checkAfter) @@ -364,7 +364,7 @@ static int poll_for_response(OSSL_CMP_CTX *ctx, int sleep, int rid, } } else if (is_crep_with_waiting(prep, rid) || ossl_cmp_is_error_with_waiting(prep)) { - /* status cannot be 'waiting' at this point */ + /* received status must not be 'waiting' */ (void)ossl_cmp_exchange_error(ctx, OSSL_CMP_PKISTATUS_rejection, OSSL_CMP_CTX_FAILINFO_badRequest, "polling already started", @@ -393,12 +393,12 @@ static int poll_for_response(OSSL_CMP_CTX *ctx, int sleep, int rid, } static int save_senderNonce_if_waiting(OSSL_CMP_CTX *ctx, - OSSL_CMP_MSG *rep, int rid) + const OSSL_CMP_MSG *rep, int rid) { /* - * LWCMP section 4.4 states: the senderNonce of the preceding request - * message because this value will be needed for checking the recipNonce - * of the final response to be received after polling. + * Lightweight CMP Profile section 4.4 states: the senderNonce of the + * preceding request message because this value will be needed for checking + * the recipNonce of the final response to be received after polling. */ if ((is_crep_with_waiting(rep, rid) || ossl_cmp_is_error_with_waiting(rep)) @@ -409,8 +409,8 @@ static int save_senderNonce_if_waiting(OSSL_CMP_CTX *ctx, } /* - * send request and get response possibly with polling initiated by error msg. - * Polling for ip/cp/kup/ with 'waiting' status is handled elsewhere. + * Send request and get response possibly with polling initiated by error msg. + * Polling for ip/cp/kup/ with 'waiting' status is handled by cert_response(). */ static int send_receive_also_delayed(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *req, OSSL_CMP_MSG **rep, int expected_type) @@ -420,12 +420,9 @@ static int send_receive_also_delayed(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *req, return 0; if (ossl_cmp_is_error_with_waiting(*rep)) { - if (!save_senderNonce_if_waiting(ctx, *rep, -1 /* rid */)) + if (!save_senderNonce_if_waiting(ctx, *rep, OSSL_CMP_CERTREQID_NONE)) return 0; - /* - * not modifying ctx->status during the certConf & error exchange, - * because these additional exchanges should not change the status. - */ + /* not modifying ctx->status during certConf and error exchanges */ if (expected_type != OSSL_CMP_PKIBODY_PKICONF && !save_statusInfo(ctx, (*rep)->body->value.error->pKIStatusInfo)) return 0; @@ -433,7 +430,7 @@ static int send_receive_also_delayed(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *req, OSSL_CMP_MSG_free(*rep); *rep = NULL; - if (poll_for_response(ctx, 1 /* can sleep */, -1 /* rid */, + if (poll_for_response(ctx, 1 /* can sleep */, OSSL_CMP_CERTREQID_NONE, rep, NULL /* checkAfter */) <= 0) { ERR_raise(ERR_LIB_CMP, CMP_R_POLLING_FAILED); return 0; @@ -462,8 +459,8 @@ int ossl_cmp_exchange_certConf(OSSL_CMP_CTX *ctx, int certReqId, if (certConf == NULL) goto err; - res = send_receive_also_delayed(ctx, certConf, - &PKIconf, OSSL_CMP_PKIBODY_PKICONF); + res = send_receive_also_delayed(ctx, certConf, &PKIconf, + OSSL_CMP_PKIBODY_PKICONF); err: OSSL_CMP_MSG_free(certConf); @@ -683,10 +680,10 @@ static int cert_response(OSSL_CMP_CTX *ctx, int sleep, int rid, return 0; si = crep->status; - if (rid == OSSL_CMP_CERTREQID_NONE) { + if (rid == OSSL_CMP_CERTREQID_NONE) { /* for OSSL_CMP_PKIBODY_P10CR learn CertReqId from response */ rid = ossl_cmp_asn1_get_int(crep->certReqId); - if (rid == OSSL_CMP_CERTREQID_NONE) { + if (rid != OSSL_CMP_CERTREQID_NONE) { ERR_raise(ERR_LIB_CMP, CMP_R_BAD_REQUEST_ID); return 0; } @@ -702,7 +699,11 @@ static int cert_response(OSSL_CMP_CTX *ctx, int sleep, int rid, return 0; if (ossl_cmp_pkisi_get_status(si) == OSSL_CMP_PKISTATUS_waiting) { - /* here we allow different flavor of ip/cp/kup & error with waiting */ + /* + * Here we allow both and error message with waiting indication + * as well as a certificate response with waiting indication, where + * its flavor (ip, cp, or kup) may not strictly match ir/cr/p10cr/kur. + */ OSSL_CMP_MSG_free(*resp); *resp = NULL; if ((ret = poll_for_response(ctx, sleep, rid, resp, checkAfter)) != 0) { @@ -715,12 +716,12 @@ static int cert_response(OSSL_CMP_CTX *ctx, int sleep, int rid, } } - /* at this point, ip/cp/kup or error without waiting */ + /* at this point, we have received ip/cp/kup/error without waiting */ if (rcvd_type == OSSL_CMP_PKIBODY_ERROR) { ERR_raise(ERR_LIB_CMP, CMP_R_RECEIVED_ERROR); return 0; } - /* here we are strict on the flavor of ip/cp/kup */ + /* here we are strict on the flavor of ip/cp/kup: must match request */ if (rcvd_type != expected_type) { ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY); return 0; @@ -738,8 +739,7 @@ static int cert_response(OSSL_CMP_CTX *ctx, int sleep, int rid, * if the CMP server returned certificates in the caPubs field, copy them * to the context so that they can be retrieved if necessary */ - if (crepmsg != NULL - && crepmsg->caPubs != NULL + if (crepmsg != NULL && crepmsg->caPubs != NULL && !ossl_cmp_ctx_set1_caPubs(ctx, crepmsg->caPubs)) return 0; diff --git a/crypto/cmp/cmp_err.c b/crypto/cmp/cmp_err.c index c4d5c97f9e..6c2588d4d4 100644 --- a/crypto/cmp/cmp_err.c +++ b/crypto/cmp/cmp_err.c @@ -76,6 +76,7 @@ static const ERR_STRING_DATA CMP_str_reasons[] = { "error validating protection"}, {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_ERROR_VALIDATING_SIGNATURE), "error validating signature"}, + {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_EXPECTED_POLLREQ), "expected pollreq"}, {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_FAILED_BUILDING_OWN_CHAIN), "failed building own chain"}, {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_FAILED_EXTRACTING_PUBKEY), @@ -149,6 +150,7 @@ static const ERR_STRING_DATA CMP_str_reasons[] = { {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNEXPECTED_PKIBODY), "unexpected pkibody"}, {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNEXPECTED_PKISTATUS), "unexpected pkistatus"}, + {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNEXPECTED_POLLREQ), "unexpected pollreq"}, {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNEXPECTED_PVNO), "unexpected pvno"}, {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNKNOWN_ALGORITHM_ID), "unknown algorithm id"}, @@ -158,6 +160,8 @@ static const ERR_STRING_DATA CMP_str_reasons[] = { "unsupported algorithm"}, {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNSUPPORTED_KEY_TYPE), "unsupported key type"}, + {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNSUPPORTED_PKIBODY), + "unsupported pkibody"}, {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_UNSUPPORTED_PROTECTION_ALG_DHBASEDMAC), "unsupported protection alg dhbasedmac"}, {ERR_PACK(ERR_LIB_CMP, 0, CMP_R_VALUE_TOO_LARGE), "value too large"}, diff --git a/crypto/cmp/cmp_msg.c b/crypto/cmp/cmp_msg.c index 1b9e275d7a..2b421ee83b 100644 --- a/crypto/cmp/cmp_msg.c +++ b/crypto/cmp/cmp_msg.c @@ -984,8 +984,7 @@ static int suitable_rid(const ASN1_INTEGER *certReqId, int rid) return 1; trid = ossl_cmp_asn1_get_int(certReqId); - - if (trid == OSSL_CMP_CERTREQID_NONE) { + if (trid < OSSL_CMP_CERTREQID_NONE) { ERR_raise(ERR_LIB_CMP, CMP_R_BAD_REQUEST_ID); return 0; } diff --git a/crypto/cmp/cmp_server.c b/crypto/cmp/cmp_server.c index 1e3ca15e89..f8dd03e69a 100644 --- a/crypto/cmp/cmp_server.c +++ b/crypto/cmp/cmp_server.c @@ -22,9 +22,9 @@ /* the context for the generic CMP server */ struct ossl_cmp_srv_ctx_st { - void *custom_ctx; /* pointer to application-specific server context */ - OSSL_CMP_CTX *ctx; /* Client CMP context, reusing transactionID etc. */ - int certReqId; /* id of last ir/cr/kur, OSSL_CMP_CERTREQID_NONE for p10cr */ + OSSL_CMP_CTX *ctx; /* CMP client context reused for transactionID etc. */ + void *custom_ctx; /* application-specific server context */ + int certReqId; /* of ir/cr/kur, OSSL_CMP_CERTREQID_NONE for p10cr */ OSSL_CMP_SRV_cert_request_cb_t process_cert_request; OSSL_CMP_SRV_rr_cb_t process_rr; @@ -32,8 +32,8 @@ struct ossl_cmp_srv_ctx_st OSSL_CMP_SRV_error_cb_t process_error; OSSL_CMP_SRV_certConf_cb_t process_certConf; OSSL_CMP_SRV_pollReq_cb_t process_pollReq; - OSSL_CMP_SRV_reset_transaction_cb_t reset_transaction; OSSL_CMP_SRV_delayed_delivery_cb_t delayed_delivery; + OSSL_CMP_SRV_clean_transaction_cb_t clean_transaction; int sendUnprotectedErrors; /* Send error and rejection msgs unprotected */ int acceptUnprotected; /* Accept requests with no/invalid prot. */ @@ -91,16 +91,16 @@ int OSSL_CMP_SRV_CTX_init(OSSL_CMP_SRV_CTX *srv_ctx, void *custom_ctx, return 1; } -int OSSL_CMP_SRV_CTX_setup_polling(OSSL_CMP_SRV_CTX *srv_ctx, - OSSL_CMP_SRV_reset_transaction_cb_t reset_transaction, - OSSL_CMP_SRV_delayed_delivery_cb_t delayed_delivery) +int OSSL_CMP_SRV_CTX_init_trans(OSSL_CMP_SRV_CTX *srv_ctx, + OSSL_CMP_SRV_delayed_delivery_cb_t delay, + OSSL_CMP_SRV_clean_transaction_cb_t clean) { if (srv_ctx == NULL) { ERR_raise(ERR_LIB_CMP, CMP_R_NULL_ARGUMENT); return 0; } - srv_ctx->reset_transaction = reset_transaction; - srv_ctx->delayed_delivery = delayed_delivery; + srv_ctx->delayed_delivery = delay; + srv_ctx->clean_transaction = clean; return 1; } @@ -164,13 +164,13 @@ int OSSL_CMP_SRV_CTX_set_grant_implicit_confirm(OSSL_CMP_SRV_CTX *srv_ctx, return 1; } -/* Return error msg with waiting status if polling is initiated, else NULL. */ +/* return error msg with waiting status if polling is initiated, else NULL */ static OSSL_CMP_MSG *delayed_delivery(OSSL_CMP_SRV_CTX *srv_ctx, const OSSL_CMP_MSG *req) { - OSSL_CMP_MSG *msg = NULL; - OSSL_CMP_PKISI *si = NULL; int ret; + OSSL_CMP_PKISI *si; + OSSL_CMP_MSG *msg; if (!ossl_assert(srv_ctx != NULL && srv_ctx->ctx != NULL && req != NULL && srv_ctx->delayed_delivery != NULL)) @@ -180,8 +180,8 @@ static OSSL_CMP_MSG *delayed_delivery(OSSL_CMP_SRV_CTX *srv_ctx, if (ret == 0 || !ossl_assert(ret != -1)) return NULL; - if ((si = OSSL_CMP_STATUSINFO_new(OSSL_CMP_PKISTATUS_waiting, 0, NULL)) - == NULL) + si = OSSL_CMP_STATUSINFO_new(OSSL_CMP_PKISTATUS_waiting, 0, NULL); + if (si == NULL) return NULL; msg = ossl_cmp_error_new(srv_ctx->ctx, si, 0, @@ -236,15 +236,14 @@ static OSSL_CMP_MSG *process_cert_request(OSSL_CMP_SRV_CTX *srv_ctx, ERR_raise(ERR_LIB_CMP, CMP_R_MULTIPLE_REQUESTS_NOT_SUPPORTED); return NULL; } - - if ((crm = sk_OSSL_CRMF_MSG_value(reqs, OSSL_CMP_CERTREQID)) == NULL) { + if ((crm = sk_OSSL_CRMF_MSG_value(reqs, 0)) == NULL) { ERR_raise(ERR_LIB_CMP, CMP_R_CERTREQMSG_NOT_FOUND); return NULL; } certReqId = OSSL_CRMF_MSG_get_certReqId(crm); - if (certReqId != OSSL_CMP_CERTREQID) { + if (certReqId != OSSL_CMP_CERTREQID) { /* so far, only possible value */ ERR_raise(ERR_LIB_CMP, CMP_R_BAD_REQUEST_ID); - return 0; + return NULL; } } srv_ctx->certReqId = certReqId; @@ -306,9 +305,8 @@ static OSSL_CMP_MSG *process_rr(OSSL_CMP_SRV_CTX *srv_ctx, ERR_raise(ERR_LIB_CMP, CMP_R_MULTIPLE_REQUESTS_NOT_SUPPORTED); return NULL; } - - if ((details = sk_OSSL_CMP_REVDETAILS_value(req->body->value.rr, - OSSL_CMP_REVREQSID)) == NULL) { + details = sk_OSSL_CMP_REVDETAILS_value(req->body->value.rr, 0); + if (details == NULL) { ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_PROCESSING_MESSAGE); return NULL; } @@ -397,7 +395,7 @@ static OSSL_CMP_MSG *process_certConf(OSSL_CMP_SRV_CTX *srv_ctx, } else { if (num > 1) ossl_cmp_warn(ctx, "All CertStatus but the first will be ignored"); - status = sk_OSSL_CMP_CERTSTATUS_value(ccc, OSSL_CMP_CERTREQID); + status = sk_OSSL_CMP_CERTSTATUS_value(ccc, 0); } if (status != NULL) { @@ -428,7 +426,7 @@ static OSSL_CMP_MSG *process_certConf(OSSL_CMP_SRV_CTX *srv_ctx, return msg; } -/* pollreq should be handled separately, to avoid recursive call */ +/* pollReq is handled separately, to avoid recursive call */ static OSSL_CMP_MSG *process_non_polling_request(OSSL_CMP_SRV_CTX *srv_ctx, const OSSL_CMP_MSG *req) { @@ -444,38 +442,41 @@ static OSSL_CMP_MSG *process_non_polling_request(OSSL_CMP_SRV_CTX *srv_ctx, case OSSL_CMP_PKIBODY_P10CR: case OSSL_CMP_PKIBODY_KUR: if (srv_ctx->process_cert_request == NULL) - ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY); + ERR_raise(ERR_LIB_CMP, CMP_R_UNSUPPORTED_PKIBODY); else rsp = process_cert_request(srv_ctx, req); break; case OSSL_CMP_PKIBODY_RR: if (srv_ctx->process_rr == NULL) - ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY); + ERR_raise(ERR_LIB_CMP, CMP_R_UNSUPPORTED_PKIBODY); else rsp = process_rr(srv_ctx, req); break; case OSSL_CMP_PKIBODY_GENM: if (srv_ctx->process_genm == NULL) - ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY); + ERR_raise(ERR_LIB_CMP, CMP_R_UNSUPPORTED_PKIBODY); else rsp = process_genm(srv_ctx, req); break; case OSSL_CMP_PKIBODY_ERROR: if (srv_ctx->process_error == NULL) - ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY); + ERR_raise(ERR_LIB_CMP, CMP_R_UNSUPPORTED_PKIBODY); else rsp = process_error(srv_ctx, req); break; case OSSL_CMP_PKIBODY_CERTCONF: if (srv_ctx->process_certConf == NULL) - ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY); + ERR_raise(ERR_LIB_CMP, CMP_R_UNSUPPORTED_PKIBODY); else rsp = process_certConf(srv_ctx, req); break; - default: - /* Other request message types are not supported */ + + case OSSL_CMP_PKIBODY_POLLREQ: ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY); break; + default: + ERR_raise(ERR_LIB_CMP, CMP_R_UNSUPPORTED_PKIBODY); + break; } return rsp; @@ -500,12 +501,8 @@ static OSSL_CMP_MSG *process_pollReq(OSSL_CMP_SRV_CTX *srv_ctx, return NULL; } - pr = sk_OSSL_CMP_POLLREQ_value(prc, OSSL_CMP_CERTREQID); + pr = sk_OSSL_CMP_POLLREQ_value(prc, 0); certReqId = ossl_cmp_asn1_get_int(pr->certReqId); - if (certReqId != srv_ctx->certReqId) { - ERR_raise(ERR_LIB_CMP, CMP_R_BAD_REQUEST_ID); - return NULL; - } if (!srv_ctx->process_pollReq(srv_ctx, req, certReqId, &orig_req, &check_after)) return NULL; @@ -604,8 +601,11 @@ OSSL_CMP_MSG *OSSL_CMP_SRV_process_request(OSSL_CMP_SRV_CTX *srv_ctx, || !OSSL_CMP_CTX_set1_senderNonce(ctx, NULL)) goto err; - if (srv_ctx->reset_transaction != NULL) - (void)srv_ctx->reset_transaction(srv_ctx); + if (srv_ctx->clean_transaction != NULL + && !srv_ctx->clean_transaction(srv_ctx, NULL)) { + ERR_raise(ERR_LIB_CMP, CMP_R_ERROR_PROCESSING_MESSAGE); + goto err; + } break; default: @@ -628,7 +628,7 @@ OSSL_CMP_MSG *OSSL_CMP_SRV_process_request(OSSL_CMP_SRV_CTX *srv_ctx, if (req_type == OSSL_CMP_PKIBODY_POLLREQ) { if (srv_ctx->process_pollReq == NULL) - ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY); + ERR_raise(ERR_LIB_CMP, CMP_R_UNSUPPORTED_PKIBODY); else rsp = process_pollReq(srv_ctx, req); } else { @@ -693,8 +693,7 @@ OSSL_CMP_MSG *OSSL_CMP_SRV_process_request(OSSL_CMP_SRV_CTX *srv_ctx, /* fall through */ case OSSL_CMP_PKIBODY_ERROR: - if (rsp != NULL - && ossl_cmp_is_error_with_waiting(rsp)) + if (rsp != NULL && ossl_cmp_is_error_with_waiting(rsp)) break; /* fall through */ @@ -702,12 +701,13 @@ OSSL_CMP_MSG *OSSL_CMP_SRV_process_request(OSSL_CMP_SRV_CTX *srv_ctx, case OSSL_CMP_PKIBODY_PKICONF: case OSSL_CMP_PKIBODY_GENP: /* Other terminating response message types are not supported */ + srv_ctx->certReqId = OSSL_CMP_CERTREQID_INVALID; /* Prepare for next transaction, ignoring any errors here: */ + if (srv_ctx->clean_transaction != NULL) + (void)srv_ctx->clean_transaction(srv_ctx, ctx->transactionID); (void)OSSL_CMP_CTX_set1_transactionID(ctx, NULL); (void)OSSL_CMP_CTX_set1_senderNonce(ctx, NULL); ctx->status = OSSL_CMP_PKISTATUS_unspecified; /* transaction closed */ - if (srv_ctx->reset_transaction != NULL) - (void)srv_ctx->reset_transaction(srv_ctx); default: /* not closing transaction in other cases */ break; diff --git a/crypto/cmp/cmp_vfy.c b/crypto/cmp/cmp_vfy.c index 8d4de1017d..5944b43526 100644 --- a/crypto/cmp/cmp_vfy.c +++ b/crypto/cmp/cmp_vfy.c @@ -787,8 +787,8 @@ int ossl_cmp_msg_check_update(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg, return 0; /* - * enable clearing irrelevant errors in attempts to validate recipient nonce - * in case of delayed delivery. + * enable clearing irrelevant errors + * in attempts to validate recipient nonce in case of delayed delivery. */ (void)ERR_set_mark(); /* compare received nonce with the one we sent */ @@ -805,7 +805,6 @@ int ossl_cmp_msg_check_update(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg, return 0; } } - /* discard any intermediate error while trying to check recipient nonce */ (void)ERR_pop_to_mark(); /* if not yet present, learn transactionID */ diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt index eaa568bfa8..fd6b128a2a 100644 --- a/crypto/err/openssl.txt +++ b/crypto/err/openssl.txt @@ -227,6 +227,7 @@ CMP_R_ERROR_SETTING_CERTHASH:128:error setting certhash CMP_R_ERROR_UNEXPECTED_CERTCONF:160:error unexpected certconf CMP_R_ERROR_VALIDATING_PROTECTION:140:error validating protection CMP_R_ERROR_VALIDATING_SIGNATURE:171:error validating signature +CMP_R_EXPECTED_POLLREQ:104:expected pollreq CMP_R_FAILED_BUILDING_OWN_CHAIN:164:failed building own chain CMP_R_FAILED_EXTRACTING_PUBKEY:141:failed extracting pubkey CMP_R_FAILURE_OBTAINING_RANDOM:110:failure obtaining random @@ -275,12 +276,14 @@ CMP_R_UNCLEAN_CTX:191:unclean ctx CMP_R_UNEXPECTED_CERTPROFILE:196:unexpected certprofile CMP_R_UNEXPECTED_PKIBODY:133:unexpected pkibody CMP_R_UNEXPECTED_PKISTATUS:185:unexpected pkistatus +CMP_R_UNEXPECTED_POLLREQ:105:unexpected pollreq CMP_R_UNEXPECTED_PVNO:153:unexpected pvno CMP_R_UNKNOWN_ALGORITHM_ID:134:unknown algorithm id CMP_R_UNKNOWN_CERT_TYPE:135:unknown cert type CMP_R_UNKNOWN_PKISTATUS:186:unknown pkistatus CMP_R_UNSUPPORTED_ALGORITHM:136:unsupported algorithm CMP_R_UNSUPPORTED_KEY_TYPE:137:unsupported key type +CMP_R_UNSUPPORTED_PKIBODY:101:unsupported pkibody CMP_R_UNSUPPORTED_PROTECTION_ALG_DHBASEDMAC:154:\ unsupported protection alg dhbasedmac CMP_R_VALUE_TOO_LARGE:175:value too large diff --git a/doc/man3/OSSL_CMP_SRV_CTX_new.pod b/doc/man3/OSSL_CMP_SRV_CTX_new.pod index fada992e3d..66d722c291 100644 --- a/doc/man3/OSSL_CMP_SRV_CTX_new.pod +++ b/doc/man3/OSSL_CMP_SRV_CTX_new.pod @@ -12,10 +12,10 @@ OSSL_CMP_SRV_certConf_cb_t, OSSL_CMP_SRV_genm_cb_t, OSSL_CMP_SRV_error_cb_t, OSSL_CMP_SRV_pollReq_cb_t, -OSSL_CMP_SRV_reset_transaction_cb_t, -OSSL_CMP_SRV_delayed_delivery_cb_t, OSSL_CMP_SRV_CTX_init, -OSSL_CMP_SRV_CTX_setup_polling, +OSSL_CMP_SRV_delayed_delivery_cb_t, +OSSL_CMP_SRV_clean_transaction_cb_t, +OSSL_CMP_SRV_CTX_init_trans, OSSL_CMP_SRV_CTX_get0_cmp_ctx, OSSL_CMP_SRV_CTX_get0_custom_ctx, OSSL_CMP_SRV_CTX_set_send_unprotected_errors, @@ -67,9 +67,6 @@ OSSL_CMP_SRV_CTX_set_grant_implicit_confirm int certReqId, OSSL_CMP_MSG **certReq, int64_t *check_after); - typedef int (*OSSL_CMP_SRV_reset_transaction_cb_t)(OSSL_CMP_SRV_CTX *srv_ctx); - typedef int (*OSSL_CMP_SRV_delayed_delivery_cb_t)(OSSL_CMP_SRV_CTX *srv_ctx, - const OSSL_CMP_MSG *req); int OSSL_CMP_SRV_CTX_init(OSSL_CMP_SRV_CTX *srv_ctx, void *custom_ctx, OSSL_CMP_SRV_cert_request_cb_t process_cert_request, OSSL_CMP_SRV_rr_cb_t process_rr, @@ -77,9 +74,13 @@ OSSL_CMP_SRV_CTX_set_grant_implicit_confirm OSSL_CMP_SRV_error_cb_t process_error, OSSL_CMP_SRV_certConf_cb_t process_certConf, OSSL_CMP_SRV_pollReq_cb_t process_pollReq); - int OSSL_CMP_SRV_CTX_setup_polling(OSSL_CMP_SRV_CTX *srv_ctx, - OSSL_CMP_SRV_reset_transaction_cb_t reset_transaction, - OSSL_CMP_SRV_delayed_delivery_cb_t delayed_delivery); + typedef int (*OSSL_CMP_SRV_delayed_delivery_cb_t)(OSSL_CMP_SRV_CTX *srv_ctx, + const OSSL_CMP_MSG *req); + typedef int (*OSSL_CMP_SRV_clean_transaction_cb_t)(OSSL_CMP_SRV_CTX *srv_ctx, + const ASN1_OCTET_STRING *id); + int OSSL_CMP_SRV_CTX_init_trans(OSSL_CMP_SRV_CTX *srv_ctx, + OSSL_CMP_SRV_delayed_delivery_cb_t delay, + OSSL_CMP_SRV_clean_transaction_cb_t clean); OSSL_CMP_CTX *OSSL_CMP_SRV_CTX_get0_cmp_ctx(const OSSL_CMP_SRV_CTX *srv_ctx); void *OSSL_CMP_SRV_CTX_get0_custom_ctx(const OSSL_CMP_SRV_CTX *srv_ctx); @@ -122,8 +123,19 @@ All arguments except I may be NULL. If a callback for some message type is not given this means that the respective type of CMP message is not supported by the server. -OSSL_CMP_SRV_CTX_setup_polling() sets in the given I callback functions -for reseting transaction and intitiating delayed delivery. +OSSL_CMP_SRV_CTX_init_trans() sets in I the optional callback +functions for initiating delayed delivery and cleaning up a transaction. +If the function is NULL then delivery of responses is never delayed. +Otherwise I takes a custom server context and a request message as input. +It must return 1 if delivery of the respecive response shall be delayed, +0 if not, and -1 on error. +If the function is NULL then no specific cleanup is performed. +Otherwise I takes a custom server context and a transaction ID pointer +as input, where the pointer is NULL in case a new transaction is being started +and otherwise provides the ID of the transaction being terminated. +The function should reset the respective portions of the state +and free related memory. +It must return 1 on success and 0 on error. OSSL_CMP_SRV_CTX_get0_cmp_ctx() returns the B from the I. @@ -168,6 +180,10 @@ All other functions return 1 on success, 0 on error. The OpenSSL CMP support was added in OpenSSL 3.0. +OSSL_CMP_SRV_CTX_init_trans() +supporting delayed delivery of all types of response messages +was added in OpenSSL 3.3. + =head1 COPYRIGHT Copyright 2007-2021 The OpenSSL Project Authors. All Rights Reserved. diff --git a/doc/man3/OSSL_CMP_exec_certreq.pod b/doc/man3/OSSL_CMP_exec_certreq.pod index 38aa4abc83..54632ce936 100644 --- a/doc/man3/OSSL_CMP_exec_certreq.pod +++ b/doc/man3/OSSL_CMP_exec_certreq.pod @@ -78,8 +78,8 @@ Typically I is NULL, then the template ingredients are taken from I and need to be filled in using L, L, L, etc. For P10CR, L needs to be used instead. -The enrollment session may be blocked by sleeping until the addressed -CA (or an intermediate PKI component) can fully process and answer the request. +The enrollment session may be blocked (with polling and sleeping in between) +until the server side can fully process and ultimately answer the request. OSSL_CMP_try_certreq() is an alternative to the above functions that is more flexible regarding what to do after receiving a checkAfter value. @@ -118,11 +118,15 @@ We take "accepted" and "grantedWithMods" as clear success and handle typically return them as an indication that the certificate was already revoked. "rejection" is a clear error. The values "waiting" and "keyUpdateWarning" make no sense for revocation and thus are treated as an error as well. +The revocation session may be blocked (with polling and sleeping in between) +until the server can fully process and ultimately answer the request. OSSL_CMP_exec_GENM_ses() sends a genm general message containing the sequence of infoType and infoValue pairs (InfoTypeAndValue; short: B) optionally provided in the I using L. -On success it records in I the status B +The message exchange may be blocked (with polling and sleeping in between) +until the server can fully process and ultimately answer the request. +On success the function records in I status B and returns the list of Bs received in a genp response message. This can be used, for instance, with infoType C to obtain the set of signature @@ -216,6 +220,9 @@ The OpenSSL CMP support was added in OpenSSL 3.0. OSSL_CMP_get1_caCerts() and OSSL_CMP_get1_rootCaKeyUpdate() were added in OpenSSL 3.2. +Support for delayed delivery of all types of response messages +was added in OpenSSL 3.3. + =head1 COPYRIGHT Copyright 2007-2023 The OpenSSL Project Authors. All Rights Reserved. diff --git a/fuzz/cmp.c b/fuzz/cmp.c index 37b6c310c3..16d2fade22 100644 --- a/fuzz/cmp.c +++ b/fuzz/cmp.c @@ -155,13 +155,14 @@ static int process_pollReq(OSSL_CMP_SRV_CTX *srv_ctx, return 0; } -static int reset_transaction(OSSL_CMP_SRV_CTX *srv_ctx) +static int clean_transaction(ossl_unused OSSL_CMP_SRV_CTX *srv_ctx, + ossl_unused const ASN1_OCTET_STRING *id) { return 1; } -static int delayed_delivery(OSSL_CMP_SRV_CTX *srv_ctx, - const OSSL_CMP_MSG *req) +static int delayed_delivery(ossl_unused OSSL_CMP_SRV_CTX *srv_ctx, + ossl_unused const OSSL_CMP_MSG *req) { return 0; } @@ -195,8 +196,8 @@ int FuzzerTestOneInput(const uint8_t *buf, size_t len) && OSSL_CMP_SRV_CTX_init(srv_ctx, NULL, process_cert_request, process_rr, process_genm, process_error, process_certConf, process_pollReq) - && OSSL_CMP_SRV_CTX_setup_polling(srv_ctx, reset_transaction, - delayed_delivery)) + && OSSL_CMP_SRV_CTX_init_trans(srv_ctx, delayed_delivery, + clean_transaction)) OSSL_CMP_MSG_free(OSSL_CMP_SRV_process_request(srv_ctx, msg)); OSSL_CMP_CTX_free(client_ctx); diff --git a/include/openssl/cmp.h.in b/include/openssl/cmp.h.in index 2e92510446..d53d74a6e1 100644 --- a/include/openssl/cmp.h.in +++ b/include/openssl/cmp.h.in @@ -469,9 +469,6 @@ typedef int (*OSSL_CMP_SRV_pollReq_cb_t)(OSSL_CMP_SRV_CTX *srv_ctx, const OSSL_CMP_MSG *req, int certReqId, OSSL_CMP_MSG **certReq, int64_t *check_after); -typedef int (*OSSL_CMP_SRV_reset_transaction_cb_t)(OSSL_CMP_SRV_CTX *srv_ctx); -typedef int (*OSSL_CMP_SRV_delayed_delivery_cb_t)(OSSL_CMP_SRV_CTX *srv_ctx, - const OSSL_CMP_MSG *req); int OSSL_CMP_SRV_CTX_init(OSSL_CMP_SRV_CTX *srv_ctx, void *custom_ctx, OSSL_CMP_SRV_cert_request_cb_t process_cert_request, OSSL_CMP_SRV_rr_cb_t process_rr, @@ -479,9 +476,13 @@ int OSSL_CMP_SRV_CTX_init(OSSL_CMP_SRV_CTX *srv_ctx, void *custom_ctx, OSSL_CMP_SRV_error_cb_t process_error, OSSL_CMP_SRV_certConf_cb_t process_certConf, OSSL_CMP_SRV_pollReq_cb_t process_pollReq); -int OSSL_CMP_SRV_CTX_setup_polling(OSSL_CMP_SRV_CTX *srv_ctx, - OSSL_CMP_SRV_reset_transaction_cb_t reset_transaction, - OSSL_CMP_SRV_delayed_delivery_cb_t delayed_delivery); +typedef int (*OSSL_CMP_SRV_delayed_delivery_cb_t)(OSSL_CMP_SRV_CTX *srv_ctx, + const OSSL_CMP_MSG *req); +typedef int (*OSSL_CMP_SRV_clean_transaction_cb_t)(OSSL_CMP_SRV_CTX *srv_ctx, + const ASN1_OCTET_STRING *id); +int OSSL_CMP_SRV_CTX_init_trans(OSSL_CMP_SRV_CTX *srv_ctx, + OSSL_CMP_SRV_delayed_delivery_cb_t delay, + OSSL_CMP_SRV_clean_transaction_cb_t clean); OSSL_CMP_CTX *OSSL_CMP_SRV_CTX_get0_cmp_ctx(const OSSL_CMP_SRV_CTX *srv_ctx); void *OSSL_CMP_SRV_CTX_get0_custom_ctx(const OSSL_CMP_SRV_CTX *srv_ctx); int OSSL_CMP_SRV_CTX_set_send_unprotected_errors(OSSL_CMP_SRV_CTX *srv_ctx, diff --git a/include/openssl/cmperr.h b/include/openssl/cmperr.h index dec9e0be45..c6ca3d10d3 100644 --- a/include/openssl/cmperr.h +++ b/include/openssl/cmperr.h @@ -55,6 +55,7 @@ # define CMP_R_ERROR_UNEXPECTED_CERTCONF 160 # define CMP_R_ERROR_VALIDATING_PROTECTION 140 # define CMP_R_ERROR_VALIDATING_SIGNATURE 171 +# define CMP_R_EXPECTED_POLLREQ 104 # define CMP_R_FAILED_BUILDING_OWN_CHAIN 164 # define CMP_R_FAILED_EXTRACTING_PUBKEY 141 # define CMP_R_FAILURE_OBTAINING_RANDOM 110 @@ -101,12 +102,14 @@ # define CMP_R_UNEXPECTED_CERTPROFILE 196 # define CMP_R_UNEXPECTED_PKIBODY 133 # define CMP_R_UNEXPECTED_PKISTATUS 185 +# define CMP_R_UNEXPECTED_POLLREQ 105 # define CMP_R_UNEXPECTED_PVNO 153 # define CMP_R_UNKNOWN_ALGORITHM_ID 134 # define CMP_R_UNKNOWN_CERT_TYPE 135 # define CMP_R_UNKNOWN_PKISTATUS 186 # define CMP_R_UNSUPPORTED_ALGORITHM 136 # define CMP_R_UNSUPPORTED_KEY_TYPE 137 +# define CMP_R_UNSUPPORTED_PKIBODY 101 # define CMP_R_UNSUPPORTED_PROTECTION_ALG_DHBASEDMAC 154 # define CMP_R_VALUE_TOO_LARGE 175 # define CMP_R_VALUE_TOO_SMALL 177 diff --git a/test/cmp_client_test.c b/test/cmp_client_test.c index ad78c86ec2..208e0a1767 100644 --- a/test/cmp_client_test.c +++ b/test/cmp_client_test.c @@ -194,7 +194,7 @@ static int test_exec_IR_ses(void) return result; } -static int test_exec_any_ses_poll(int req_type, int check_after, +static int test_exec_REQ_ses_poll(int req_type, int check_after, int poll_count, int total_timeout, int expect) { @@ -206,14 +206,10 @@ static int test_exec_any_ses_poll(int req_type, int check_after, OSSL_CMP_CTX_set_option(fixture->cmp_ctx, OSSL_CMP_OPT_TOTAL_TIMEOUT, total_timeout); - if (req_type == OSSL_CMP_PKIBODY_IR || req_type == OSSL_CMP_PKIBODY_CR - || req_type == OSSL_CMP_PKIBODY_KUR - || req_type == OSSL_CMP_PKIBODY_P10CR) { + if (req_type == OSSL_CMP_PKIBODY_IR) { EXECUTE_TEST(execute_exec_certrequest_ses_test, tear_down); } else if (req_type == OSSL_CMP_PKIBODY_GENM) { EXECUTE_TEST(execute_exec_GENM_ses_test, tear_down); - } else { - result = 0; } return result; } @@ -221,20 +217,20 @@ static int test_exec_any_ses_poll(int req_type, int check_after, static int checkAfter = 1; static int test_exec_IR_ses_poll_ok(void) { - return test_exec_any_ses_poll(OSSL_CMP_PKIBODY_IR, checkAfter, 2, 0, + return test_exec_REQ_ses_poll(OSSL_CMP_PKIBODY_IR, checkAfter, 2, 0, OSSL_CMP_PKISTATUS_accepted); } static int test_exec_IR_ses_poll_no_timeout(void) { - return test_exec_any_ses_poll(OSSL_CMP_PKIBODY_IR, checkAfter, + return test_exec_REQ_ses_poll(OSSL_CMP_PKIBODY_IR, checkAfter, 2 /* pollCount */, checkAfter + 4, OSSL_CMP_PKISTATUS_accepted); } static int test_exec_IR_ses_poll_total_timeout(void) { - return !test_exec_any_ses_poll(OSSL_CMP_PKIBODY_IR, checkAfter + 1, + return !test_exec_REQ_ses_poll(OSSL_CMP_PKIBODY_IR, checkAfter + 1, 3 /* pollCount */, checkAfter + 6, OSSL_CMP_PKISTATUS_waiting); } @@ -419,20 +415,20 @@ static int test_try_certreq_poll_abort(void) static int test_exec_GENM_ses_poll_ok(void) { - return test_exec_any_ses_poll(OSSL_CMP_PKIBODY_GENM, checkAfter, 2, 0, + return test_exec_REQ_ses_poll(OSSL_CMP_PKIBODY_GENM, checkAfter, 2, 0, OSSL_CMP_PKISTATUS_accepted); } static int test_exec_GENM_ses_poll_no_timeout(void) { - return test_exec_any_ses_poll(OSSL_CMP_PKIBODY_GENM, checkAfter, + return test_exec_REQ_ses_poll(OSSL_CMP_PKIBODY_GENM, checkAfter, 1 /* pollCount */, checkAfter + 1, OSSL_CMP_PKISTATUS_accepted); } static int test_exec_GENM_ses_poll_total_timeout(void) { - return test_exec_any_ses_poll(OSSL_CMP_PKIBODY_GENM, checkAfter + 1, + return test_exec_REQ_ses_poll(OSSL_CMP_PKIBODY_GENM, checkAfter + 1, 3 /* pollCount */, checkAfter + 2, OSSL_CMP_PKISTATUS_waiting); } diff --git a/test/cmp_server_test.c b/test/cmp_server_test.c index e375ae3d9c..5e778ab656 100644 --- a/test/cmp_server_test.c +++ b/test/cmp_server_test.c @@ -76,7 +76,7 @@ static int execute_test_handle_request(CMP_SRV_TEST_FIXTURE *fixture) if (!TEST_true(OSSL_CMP_SRV_CTX_init(ctx, dummy_custom_ctx, process_cert_request, NULL, NULL, NULL, NULL, NULL)) - || !TEST_true(OSSL_CMP_SRV_CTX_setup_polling(ctx, NULL, NULL)) + || !TEST_true(OSSL_CMP_SRV_CTX_init_trans(ctx, NULL, NULL)) || !TEST_ptr(custom_ctx = OSSL_CMP_SRV_CTX_get0_custom_ctx(ctx)) || !TEST_int_eq(strcmp(custom_ctx, dummy_custom_ctx), 0)) goto end; diff --git a/util/libcrypto.num b/util/libcrypto.num index 6b7e6c212b..9d92ca67ca 100644 --- a/util/libcrypto.num +++ b/util/libcrypto.num @@ -5540,6 +5540,6 @@ OSSL_CMP_CTX_get0_geninfo_ITAVs ? 3_3_0 EXIST::FUNCTION:CMP OSSL_CMP_HDR_get0_geninfo_ITAVs ? 3_3_0 EXIST::FUNCTION:CMP OSSL_CMP_ITAV_new0_certProfile ? 3_3_0 EXIST::FUNCTION:CMP OSSL_CMP_ITAV_get0_certProfile ? 3_3_0 EXIST::FUNCTION:CMP -OSSL_CMP_SRV_CTX_setup_polling ? 3_3_0 EXIST::FUNCTION:CMP +OSSL_CMP_SRV_CTX_init_trans ? 3_3_0 EXIST::FUNCTION:CMP EVP_DigestSqueeze ? 3_3_0 EXIST::FUNCTION: ERR_pop ? 3_3_0 EXIST::FUNCTION: -- Gitee From 4b9fbee968ba1a9045096d7cc2eb4e673a75c834 Mon Sep 17 00:00:00 2001 From: Rajeev Ranjan Date: Wed, 3 May 2023 16:19:36 +0200 Subject: [PATCH 91/92] cmp_server.c,apps/lib/cmp_mock_srv.c: move polling state checks to cmp_server.c Reviewed-by: Shane Lontis Reviewed-by: Tomas Mraz Reviewed-by: David von Oheimb (Merged from https://github.com/openssl/openssl/pull/20727) Signed-off-by: lanming1120 --- apps/lib/cmp_mock_srv.c | 10 ---------- crypto/cmp/cmp_server.c | 38 ++++++++++++++++++++++++++++++++++---- 2 files changed, 34 insertions(+), 14 deletions(-) diff --git a/apps/lib/cmp_mock_srv.c b/apps/lib/cmp_mock_srv.c index d44c3581e7..5fed3a9fd0 100644 --- a/apps/lib/cmp_mock_srv.c +++ b/apps/lib/cmp_mock_srv.c @@ -208,11 +208,6 @@ static int delayed_delivery(OSSL_CMP_SRV_CTX *srv_ctx, const OSSL_CMP_MSG *req) if (ctx->pollCount > 0 && ctx->curr_pollCount == 0) { /* start polling */ - if (ctx->req != NULL) { /* TODO: move this check to cmp_server.c */ - /* already in polling mode */ - ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY); - return -1; - } if ((ctx->req = OSSL_CMP_MSG_dup(req)) == NULL) return -1; return 1; @@ -282,11 +277,6 @@ static OSSL_CMP_PKISI *process_cert_request(OSSL_CMP_SRV_CTX *srv_ctx, if (ctx->pollCount > 0 && ctx->curr_pollCount == 0) { /* start polling */ - if (ctx->req != NULL) { - /* already in polling mode */ - ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY); - return NULL; - } if ((ctx->req = OSSL_CMP_MSG_dup(cert_req)) == NULL) return NULL; return OSSL_CMP_STATUSINFO_new(OSSL_CMP_PKISTATUS_waiting, 0, NULL); diff --git a/crypto/cmp/cmp_server.c b/crypto/cmp/cmp_server.c index f8dd03e69a..4e2ca09966 100644 --- a/crypto/cmp/cmp_server.c +++ b/crypto/cmp/cmp_server.c @@ -25,6 +25,7 @@ struct ossl_cmp_srv_ctx_st OSSL_CMP_CTX *ctx; /* CMP client context reused for transactionID etc. */ void *custom_ctx; /* application-specific server context */ int certReqId; /* of ir/cr/kur, OSSL_CMP_CERTREQID_NONE for p10cr */ + int polling; /* current tranaction is in polling mode */ OSSL_CMP_SRV_cert_request_cb_t process_cert_request; OSSL_CMP_SRV_rr_cb_t process_rr; @@ -61,6 +62,7 @@ OSSL_CMP_SRV_CTX *OSSL_CMP_SRV_CTX_new(OSSL_LIB_CTX *libctx, const char *propq) if ((ctx->ctx = OSSL_CMP_CTX_new(libctx, propq)) == NULL) goto err; ctx->certReqId = OSSL_CMP_CERTREQID_INVALID; + ctx->polling = 0; /* all other elements are initialized to 0 or NULL, respectively */ return ctx; @@ -169,6 +171,10 @@ static OSSL_CMP_MSG *delayed_delivery(OSSL_CMP_SRV_CTX *srv_ctx, const OSSL_CMP_MSG *req) { int ret; + unsigned long err; + int status = OSSL_CMP_PKISTATUS_waiting, + fail_info = 0, errorCode = 0; + const char *txt = NULL, *details = NULL; OSSL_CMP_PKISI *si; OSSL_CMP_MSG *msg; @@ -177,15 +183,25 @@ static OSSL_CMP_MSG *delayed_delivery(OSSL_CMP_SRV_CTX *srv_ctx, return NULL; ret = srv_ctx->delayed_delivery(srv_ctx, req); - if (ret == 0 || !ossl_assert(ret != -1)) + if (ret == 0) return NULL; + if (ret == 1) { + srv_ctx->polling = 1; + } else { + status = OSSL_CMP_PKISTATUS_rejection; + fail_info = 1 << OSSL_CMP_PKIFAILUREINFO_systemFailure; + txt = "server application error"; + err = ERR_peek_error(); + errorCode = ERR_GET_REASON(err); + details = ERR_reason_error_string(err); + } - si = OSSL_CMP_STATUSINFO_new(OSSL_CMP_PKISTATUS_waiting, 0, NULL); + si = OSSL_CMP_STATUSINFO_new(status, fail_info, txt); if (si == NULL) return NULL; - msg = ossl_cmp_error_new(srv_ctx->ctx, si, 0, - NULL, srv_ctx->sendUnprotectedErrors); + msg = ossl_cmp_error_new(srv_ctx->ctx, si, errorCode, details, + srv_ctx->sendUnprotectedErrors); OSSL_CMP_PKISI_free(si); return msg; } @@ -262,6 +278,8 @@ static OSSL_CMP_MSG *process_cert_request(OSSL_CMP_SRV_CTX *srv_ctx, &certOut, &chainOut, &caPubs); if (si == NULL) goto err; + if (ossl_cmp_pkisi_get_status(si) == OSSL_CMP_PKISTATUS_waiting) + srv_ctx->polling = 1; /* set OSSL_CMP_OPT_IMPLICIT_CONFIRM if and only if transaction ends */ if (!OSSL_CMP_CTX_set_option(srv_ctx->ctx, OSSL_CMP_OPT_IMPLICIT_CONFIRM, @@ -495,6 +513,11 @@ static OSSL_CMP_MSG *process_pollReq(OSSL_CMP_SRV_CTX *srv_ctx, if (!ossl_assert(srv_ctx != NULL && srv_ctx->ctx != NULL && req != NULL)) return NULL; + if (!srv_ctx->polling) { + ERR_raise(ERR_LIB_CMP, CMP_R_UNEXPECTED_PKIBODY); + return NULL; + } + prc = req->body->value.pollReq; if (sk_OSSL_CMP_POLLREQ_num(prc) != 1) { ERR_raise(ERR_LIB_CMP, CMP_R_MULTIPLE_REQUESTS_NOT_SUPPORTED); @@ -508,6 +531,7 @@ static OSSL_CMP_MSG *process_pollReq(OSSL_CMP_SRV_CTX *srv_ctx, return NULL; if (orig_req != NULL) { + srv_ctx->polling = 0; msg = process_non_polling_request(srv_ctx, orig_req); OSSL_CMP_MSG_free(orig_req); } else { @@ -579,6 +603,12 @@ OSSL_CMP_MSG *OSSL_CMP_SRV_process_request(OSSL_CMP_SRV_CTX *srv_ctx, if (!OSSL_CMP_CTX_set1_recipient(ctx, hdr->sender->d.directoryName)) goto err; + if (srv_ctx->polling && req_type != OSSL_CMP_PKIBODY_POLLREQ + && req_type != OSSL_CMP_PKIBODY_ERROR) { + ERR_raise(ERR_LIB_CMP, CMP_R_EXPECTED_POLLREQ); + goto err; + } + switch (req_type) { case OSSL_CMP_PKIBODY_IR: case OSSL_CMP_PKIBODY_CR: -- Gitee From cb335f8130a3fc9ddf2be597f5edfe20c1a6901b Mon Sep 17 00:00:00 2001 From: "Dr. David von Oheimb" Date: Thu, 27 Jul 2023 20:03:16 +0200 Subject: [PATCH 92/92] crypto/cmp: fix clash of OSSL_CMP_CERTREQID_NONE with error result of ossl_cmp_asn1_get_int() Reviewed-by: Shane Lontis Reviewed-by: Tomas Mraz Reviewed-by: David von Oheimb (Merged from https://github.com/openssl/openssl/pull/20727) Signed-off-by: lanming1120 --- crypto/cmp/cmp_client.c | 2 +- crypto/cmp/cmp_msg.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crypto/cmp/cmp_client.c b/crypto/cmp/cmp_client.c index 23b3a8bd05..91876ee948 100644 --- a/crypto/cmp/cmp_client.c +++ b/crypto/cmp/cmp_client.c @@ -683,7 +683,7 @@ static int cert_response(OSSL_CMP_CTX *ctx, int sleep, int rid, if (rid == OSSL_CMP_CERTREQID_NONE) { /* for OSSL_CMP_PKIBODY_P10CR learn CertReqId from response */ rid = ossl_cmp_asn1_get_int(crep->certReqId); - if (rid != OSSL_CMP_CERTREQID_NONE) { + if (rid < OSSL_CMP_CERTREQID_NONE) { ERR_raise(ERR_LIB_CMP, CMP_R_BAD_REQUEST_ID); return 0; } diff --git a/crypto/cmp/cmp_msg.c b/crypto/cmp/cmp_msg.c index 2b421ee83b..a7e22d874a 100644 --- a/crypto/cmp/cmp_msg.c +++ b/crypto/cmp/cmp_msg.c @@ -984,7 +984,7 @@ static int suitable_rid(const ASN1_INTEGER *certReqId, int rid) return 1; trid = ossl_cmp_asn1_get_int(certReqId); - if (trid < OSSL_CMP_CERTREQID_NONE) { + if (trid <= OSSL_CMP_CERTREQID_INVALID) { ERR_raise(ERR_LIB_CMP, CMP_R_BAD_REQUEST_ID); return 0; } -- Gitee