diff --git a/.github/workflows/coveralls.yml b/.github/workflows/coveralls.yml index 7771f5fd38f76570ab9121ff2cf9ab6ac31cd448..bdb576fd650a57ff94a1eb2178a1e0b411eabde7 100644 --- a/.github/workflows/coveralls.yml +++ b/.github/workflows/coveralls.yml @@ -25,16 +25,14 @@ jobs: matrix: branches: [ { - branch: OpenSSL_1_1_1-stable - }, { branch: openssl-3.1, - extra_config: enable-fips + extra_config: no-afalgeng enable-fips enable-ssl-trace enable-trace enable-zlib enable-rc5 enable-md2 enable-weak-ssl-ciphers enable-ec_nistp_64_gcc_128 }, { branch: openssl-3.0, - extra_config: enable-fips + extra_config: no-afalgeng enable-fips enable-ssl-trace enable-trace enable-zlib enable-rc5 enable-md2 enable-weak-ssl-ciphers enable-ec_nistp_64_gcc_128 }, { branch: master, - extra_config: no-afalgeng enable-fips enable-tfo + extra_config: no-afalgeng enable-fips enable-ssl-trace enable-trace enable-zlib enable-rc5 enable-md2 enable-weak-ssl-ciphers enable-ec_nistp_64_gcc_128 enable-tfo } ] runs-on: ubuntu-latest diff --git a/.github/workflows/os-zoo.yml b/.github/workflows/os-zoo.yml index ee327f4c1bfe295973291a908b1472399e58e51f..98fe0c744cc42c84e290300fee1823e34ba7339d 100644 --- a/.github/workflows/os-zoo.yml +++ b/.github/workflows/os-zoo.yml @@ -15,80 +15,116 @@ permissions: contents: read jobs: - # This has to be a separate job, it seems, because we want to use a - # container for it. - unix-container: + alpine: strategy: fail-fast: false matrix: - image: ['alpine:edge', 'alpine:latest'] - cc: ['gcc', 'clang'] + tag: [edge, latest] + cc: [gcc, clang] + branch: [openssl-3.0, openssl-3.1, master] runs-on: ubuntu-latest container: - image: ${{ matrix.image }} + image: docker.io/library/alpine:${{ matrix.tag }} + env: + # https://www.openwall.com/lists/musl/2022/02/16/14 + EXTRA_CFLAGS: ${{ matrix.cc == 'clang' && '-Wno-sign-compare' || '' }} + CC: ${{ matrix.cc }} steps: - name: install packages - run: | - apk --no-cache add build-base perl linux-headers git ${{ matrix.cc }} - + run: apk --no-cache add build-base perl linux-headers ${{ matrix.cc }} - uses: actions/checkout@v4 - + with: + ref: ${{ matrix.branch }} - name: config run: | - cc="${{ matrix.cc }}" - - extra_cflags="" - if [[ ${cc} == "clang" ]] ; then - # https://www.openwall.com/lists/musl/2022/02/16/14 - extra_cflags="-Wno-sign-compare" - fi - - CC=${{ matrix.cc }} ./config --banner=Configured no-shared \ - -Wall -Werror enable-fips --strict-warnings -DOPENSSL_USE_IPV6=0 ${extra_cflags} - + ./config --banner=Configured no-shared -Wall -Werror enable-fips --strict-warnings -DOPENSSL_USE_IPV6=0 \ + ${EXTRA_CFLAGS} - name: config dump run: ./configdata.pm --dump - name: make run: make -s -j4 - name: make test run: make test HARNESS_JOBS=${HARNESS_JOBS:-4} - unix: + + linux: + strategy: + fail-fast: false + matrix: + branch: [openssl-3.0, openssl-3.1, master] + zoo: + - image: docker.io/library/debian:10 + install: apt-get update && apt-get install -y gcc make perl + - image: docker.io/library/debian:11 + install: apt-get update && apt-get install -y gcc make perl + - image: docker.io/library/debian:12 + install: apt-get update && apt-get install -y gcc make perl + - image: docker.io/library/ubuntu:20.04 + install: apt-get update && apt-get install -y gcc make perl + - image: docker.io/library/ubuntu:22.04 + install: apt-get update && apt-get install -y gcc make perl + - image: docker.io/library/fedora:38 + install: dnf install -y gcc make perl-core + - image: docker.io/library/fedora:39 + install: dnf install -y gcc make perl-core + - image: docker.io/library/centos:8 + install: | + sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-* && \ + sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-* && \ + dnf install -y gcc make perl-core + - image: docker.io/library/rockylinux:8 + install: dnf install -y gcc make perl-core + - image: docker.io/library/rockylinux:9 + install: dnf install -y gcc make perl-core + runs-on: ubuntu-latest + container: ${{ matrix.zoo.image }} + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ matrix.branch }} + - name: install packages + run: ${{ matrix.zoo.install }} + - name: config + run: ./config + - name: config dump + run: ./configdata.pm --dump + - name: make + run: make -j4 + - name: make test + run: make test HARNESS_JOBS=${HARNESS_JOBS:-4} + + macos: strategy: fail-fast: false matrix: - os: [ - macos-11, - macos-12, - macos-13, - ubuntu-20.04, - ubuntu-22.04, - ] + branch: [openssl-3.0, openssl-3.1, master] + os: [macos-11, macos-12, macos-13] runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 + with: + ref: ${{ matrix.branch }} - name: checkout fuzz/corpora submodule run: git submodule update --init --depth 1 fuzz/corpora - name: config - run: | - CC=${{ matrix.zoo.cc }} ./config --banner=Configured \ - -Wall -Werror --strict-warnings enable-fips + run: ./config --banner=Configured -Wall -Werror --strict-warnings enable-fips - name: config dump run: ./configdata.pm --dump - name: make run: make -s -j4 - name: make test run: make test HARNESS_JOBS=${HARNESS_JOBS:-4} + windows: strategy: fail-fast: false matrix: - os: [ - windows-2019, - windows-2022 - ] + branch: [openssl-3.0, openssl-3.1, master] + os: [windows-2019, windows-2022] runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 + with: + ref: ${{ matrix.branch }} - name: checkout fuzz/corpora submodule run: git submodule update --init --depth 1 fuzz/corpora - uses: ilammy/msvc-dev-cmd@v1 @@ -98,8 +134,7 @@ jobs: run: mkdir _build - name: config working-directory: _build - run: | - perl ..\Configure --banner=Configured no-makedepend enable-fips + run: perl ..\Configure --banner=Configured no-makedepend enable-fips - name: config dump working-directory: _build run: ./configdata.pm --dump diff --git a/.github/workflows/provider-compatibility.yml b/.github/workflows/provider-compatibility.yml index b675e426c173da1850145c1ac6082e1a4b82a203..f118db1aee5f900d24f5264aa15be624a7fdb918 100644 --- a/.github/workflows/provider-compatibility.yml +++ b/.github/workflows/provider-compatibility.yml @@ -179,7 +179,7 @@ jobs: # later providers. Problems in these situations ought to be # caught by cross branch testing before the release. tree_a: [ branch-master, branch-3.1, branch-3.0, - openssl-3.0.0, openssl-3.0.8, openssl-3.0.9, openssl-3.1.1 ] + openssl-3.0.0, openssl-3.0.8, openssl-3.0.9, openssl-3.1.2 ] tree_b: [ branch-master, branch-3.1, branch-3.0 ] steps: - name: early exit checks diff --git a/NEWS.md b/NEWS.md index 6c440b68eb8172769a36fa1f46acc60b1cfab264..d0312961dfdc8b81b0cde836de8864b8ccf96a04 100644 --- a/NEWS.md +++ b/NEWS.md @@ -135,7 +135,7 @@ OpenSSL 3.0 * Fixed a bug where the RC4-MD5 ciphersuite incorrectly used the AAD data as the MAC key ([CVE-2022-1434]) * Fix a bug in the OPENSSL_LH_flush() function that breaks reuse of the memory - occuppied by the removed hash table entries ([CVE-2022-1473]) + occupied by the removed hash table entries ([CVE-2022-1473]) ### Major changes between OpenSSL 3.0.1 and OpenSSL 3.0.2 [15 Mar 2022] diff --git a/apps/dgst.c b/apps/dgst.c index fe05b312d7b2dae4ec2a8a6da5535c3a5683a7fa..28123f813f112efe0a0233dc81c1470a638d2884 100644 --- a/apps/dgst.c +++ b/apps/dgst.c @@ -321,6 +321,8 @@ int dgst_main(int argc, char **argv) sigkey = app_keygen(mac_ctx, mac_name, 0, 0 /* not verbose */); /* Verbose output would make external-tests gost-engine fail */ EVP_PKEY_CTX_free(mac_ctx); + if (sigkey == NULL) + goto end; } if (hmac_key != NULL) { diff --git a/apps/dhparam.c b/apps/dhparam.c index a41e70fe3833098c519d785ceceaaf987ea91f07..d14c569503013a1484dcf161636f651ba4f7758c 100644 --- a/apps/dhparam.c +++ b/apps/dhparam.c @@ -233,6 +233,8 @@ int dhparam_main(int argc, char **argv) } tmppkey = app_paramgen(ctx, alg); + if (tmppkey == NULL) + goto end; EVP_PKEY_CTX_free(ctx); ctx = NULL; if (dsaparam) { diff --git a/apps/dsaparam.c b/apps/dsaparam.c index 4eb157042e562ac2a0fc5595115a3cc7cb118da9..8bd2e1361bf522549880e775cc8ed448ab39cd2f 100644 --- a/apps/dsaparam.c +++ b/apps/dsaparam.c @@ -232,6 +232,8 @@ int dsaparam_main(int argc, char **argv) goto end; } pkey = app_keygen(ctx, "DSA", numbits, verbose); + if (pkey == NULL) + goto end; assert(private); if (outformat == FORMAT_ASN1) i = i2d_PrivateKey_bio(out, pkey); diff --git a/apps/enc.c b/apps/enc.c index 26e009e43791cd8431b11d3009e801fe81735769..d94f5236d7bbee617230f1382369876132cf5f11 100644 --- a/apps/enc.c +++ b/apps/enc.c @@ -701,7 +701,10 @@ int enc_main(int argc, char **argv) break; } if (!BIO_flush(wbio)) { - BIO_printf(bio_err, "bad decrypt\n"); + if (enc) + BIO_printf(bio_err, "bad encrypt\n"); + else + BIO_printf(bio_err, "bad decrypt\n"); goto end; } diff --git a/apps/gendsa.c b/apps/gendsa.c index bd8aecedbd9c695285e7324db3901be2666e1b9f..b6d1d0f5b3f76ab0b0a6eb1834af77ec6fb3762c 100644 --- a/apps/gendsa.c +++ b/apps/gendsa.c @@ -148,6 +148,8 @@ int gendsa_main(int argc, char **argv) goto end; } pkey = app_keygen(ctx, "DSA", nbits, verbose); + if (pkey == NULL) + goto end; assert(private); if (!PEM_write_bio_PrivateKey(out, pkey, enc, NULL, 0, NULL, passout)) { diff --git a/apps/genpkey.c b/apps/genpkey.c index 5a59dae6811d6adac0b773dc7c03e3233396d322..080f1f60756e7824107f0a5dbcbed7b33f47b7d1 100644 --- a/apps/genpkey.c +++ b/apps/genpkey.c @@ -234,6 +234,8 @@ int genpkey_main(int argc, char **argv) pkey = do_param ? app_paramgen(ctx, algname) : app_keygen(ctx, algname, 0, 0 /* not verbose */); + if (pkey == NULL) + goto end; if (do_param) { rv = PEM_write_bio_Parameters(out, pkey); diff --git a/apps/genrsa.c b/apps/genrsa.c index 3151de646bca5beeeed4fe2591c8bb56b39823f6..f71bc6eeb111d7b820f467702c4c35d51f50efd6 100644 --- a/apps/genrsa.c +++ b/apps/genrsa.c @@ -204,6 +204,8 @@ opthelp: goto end; } pkey = app_keygen(ctx, "RSA", num, verbose); + if (pkey == NULL) + goto end; if (verbose) { BIGNUM *e = NULL; diff --git a/apps/lib/apps.c b/apps/lib/apps.c index 8aad9a1ef7cf92f0e7d84423d5132c4a89674e80..6b2a4b86ce670313ba2b0fac17f9accb9489e341 100644 --- a/apps/lib/apps.c +++ b/apps/lib/apps.c @@ -3417,8 +3417,8 @@ EVP_PKEY *app_keygen(EVP_PKEY_CTX *ctx, const char *alg, int bits, int verbose) BIO_printf(bio_err, "Warning: generating random key material may take a long time\n" "if the system has a poor entropy source\n"); if (EVP_PKEY_keygen(ctx, &res) <= 0) - app_bail_out("%s: Error generating %s key\n", opt_getprog(), - alg != NULL ? alg : "asymmetric"); + BIO_printf(bio_err, "%s: Error generating %s key\n", opt_getprog(), + alg != NULL ? alg : "asymmetric"); return res; } @@ -3430,8 +3430,8 @@ EVP_PKEY *app_paramgen(EVP_PKEY_CTX *ctx, const char *alg) BIO_printf(bio_err, "Warning: generating random key parameters may take a long time\n" "if the system has a poor entropy source\n"); if (EVP_PKEY_paramgen(ctx, &res) <= 0) - app_bail_out("%s: Generating %s key parameters failed\n", - opt_getprog(), alg != NULL ? alg : "asymmetric"); + BIO_printf(bio_err, "%s: Generating %s key parameters failed\n", + opt_getprog(), alg != NULL ? alg : "asymmetric"); return res; } diff --git a/apps/openssl.c b/apps/openssl.c index dd41ac3a84e443a7a4341509249ab043ddabaedc..adf77096c7f31cda452ac11c05a5d0f6d47b5016 100644 --- a/apps/openssl.c +++ b/apps/openssl.c @@ -157,8 +157,6 @@ static void tracedata_free(tracedata *data) OPENSSL_free(data); } -static STACK_OF(tracedata) *trace_data_stack; - static void cleanup_trace(void) { sk_tracedata_pop_free(trace_data_stack, tracedata_free); diff --git a/apps/progs.pl b/apps/progs.pl index f27ccfbba3cad6e6d345444b07271c2e74bb5a10..120ae05f07388c3efa3f25c627383f2c719af870 100644 --- a/apps/progs.pl +++ b/apps/progs.pl @@ -104,7 +104,7 @@ EOF # The format of this table is: # [0] = alternative command to use instead # [1] = deprecented in this version -# [2] = preprocessor conditional for exclusing irrespective of deprecation +# [2] = preprocessor conditional for excluding irrespective of deprecation # rsa => [ "pkey", "3_0", "rsa" ], # genrsa => [ "genpkey", "3_0", "rsa" ], rsautl => [ "pkeyutl", "3_0", "rsa" ], diff --git a/apps/req.c b/apps/req.c index c4c9ba292cb057a78c9b159e714daed148350575..3ce2b384969b67dd2ad5d1a6ec06bb8628b71886 100644 --- a/apps/req.c +++ b/apps/req.c @@ -663,6 +663,8 @@ int req_main(int argc, char **argv) EVP_PKEY_CTX_set_cb(genctx, progress_cb); pkey = app_keygen(genctx, keyalgstr, newkey_len, verbose); + if (pkey == NULL) + goto end; EVP_PKEY_CTX_free(genctx); genctx = NULL; diff --git a/crypto/bio/bio_print.c b/crypto/bio/bio_print.c index e5397c8b7a071d14945d0ef545d7e86f50fca88e..5f2543030e54d723ddf157f8c0b692acd8e4acae 100644 --- a/crypto/bio/bio_print.c +++ b/crypto/bio/bio_print.c @@ -62,7 +62,7 @@ static int _dopr(char **sbuffer, char **buffer, #define DP_F_NUM (1 << 3) /* print leading zeroes */ #define DP_F_ZERO (1 << 4) -/* print HEX in UPPPERcase */ +/* print HEX in UPPERcase */ #define DP_F_UP (1 << 5) /* treat value as unsigned */ #define DP_F_UNSIGNED (1 << 6) diff --git a/crypto/bio/bss_dgram_pair.c b/crypto/bio/bss_dgram_pair.c index 534a2216aa42a9c8df8f31217d4d7bfc014470a9..08dd802d8fd42a1b0b457175bde7a7a3693e6ea7 100644 --- a/crypto/bio/bss_dgram_pair.c +++ b/crypto/bio/bss_dgram_pair.c @@ -279,8 +279,9 @@ static int dgram_pair_init(BIO *bio) if (b == NULL) return 0; - b->req_buf_len = 17*1024; /* default buffer size */ b->mtu = 1472; /* conservative default MTU */ + /* default buffer size */ + b->req_buf_len = 9 * (sizeof(struct dgram_hdr) + b->mtu); b->lock = CRYPTO_THREAD_lock_new(); if (b->lock == NULL) { diff --git a/crypto/bio/bss_sock.c b/crypto/bio/bss_sock.c index f64eb8c843a4ba110ebf658446b6f754f4bcdf2c..4ff4defadff46fe6af5c1771cc683952fb6fdde8 100644 --- a/crypto/bio/bss_sock.c +++ b/crypto/bio/bss_sock.c @@ -215,6 +215,20 @@ static long sock_ctrl(BIO *b, int cmd, long num, void *ptr) case BIO_CTRL_FLUSH: ret = 1; break; + case BIO_CTRL_GET_RPOLL_DESCRIPTOR: + case BIO_CTRL_GET_WPOLL_DESCRIPTOR: + { + BIO_POLL_DESCRIPTOR *pd = ptr; + + if (!b->init) { + ret = 0; + break; + } + + pd->type = BIO_POLL_DESCRIPTOR_TYPE_SOCK_FD; + pd->value.fd = b->num; + } + break; # ifndef OPENSSL_NO_KTLS case BIO_CTRL_SET_KTLS: crypto_info = (ktls_crypto_info_t *)ptr; diff --git a/crypto/build.info b/crypto/build.info index ef568070c14e46d80c8b228be7e79faed9a22db3..2d5b22fcff4e9a577fafbad681b70b9673d11a5b 100644 --- a/crypto/build.info +++ b/crypto/build.info @@ -102,8 +102,6 @@ $UTIL_COMMON=\ param_build_set.c der_writer.c threads_lib.c params_dup.c \ time.c params_idx.c -SHARED_SOURCE[../libssl]=sparse_array.c - SOURCE[../libcrypto]=$UTIL_COMMON \ mem.c mem_sec.c \ cversion.c info.c cpt_err.c ebcdic.c uid.c o_time.c o_dir.c \ diff --git a/crypto/cmp/cmp_vfy.c b/crypto/cmp/cmp_vfy.c index 2d7b2388ced41a792e5e797bf7d0f6b25e24dcca..1869fae696357bb1aab7860416461d1b152b9c2a 100644 --- a/crypto/cmp/cmp_vfy.c +++ b/crypto/cmp/cmp_vfy.c @@ -139,6 +139,24 @@ int OSSL_CMP_validate_cert_path(const OSSL_CMP_CTX *ctx, return valid; } +static int verify_cb_cert(X509_STORE *ts, X509 *cert, int err) +{ + X509_STORE_CTX_verify_cb verify_cb; + X509_STORE_CTX *csc; + int ok = 0; + + if (ts == NULL || (verify_cb = X509_STORE_get_verify_cb(ts)) == NULL) + return ok; + if ((csc = X509_STORE_CTX_new()) != NULL + && X509_STORE_CTX_init(csc, ts, cert, NULL)) { + X509_STORE_CTX_set_error(csc, err); + X509_STORE_CTX_set_current_cert(csc, cert); + ok = (*verify_cb)(0, csc); + } + X509_STORE_CTX_free(csc); + return ok; +} + /* Return 0 if expect_name != NULL and there is no matching actual_name */ static int check_name(const OSSL_CMP_CTX *ctx, int log_success, const char *actual_desc, const X509_NAME *actual_name, @@ -256,9 +274,14 @@ static int cert_acceptable(const OSSL_CMP_CTX *ctx, time_cmp = X509_cmp_timeframe(vpm, X509_get0_notBefore(cert), X509_get0_notAfter(cert)); if (time_cmp != 0) { + int err = time_cmp > 0 ? X509_V_ERR_CERT_HAS_EXPIRED + : X509_V_ERR_CERT_NOT_YET_VALID; + ossl_cmp_warn(ctx, time_cmp > 0 ? "cert has expired" : "cert is not yet valid"); - return 0; + if (ctx->log_cb != NULL /* logging not temporarily disabled */ + && verify_cb_cert(ts, cert, err) <= 0) + return 0; } if (!check_name(ctx, 1, @@ -432,12 +455,6 @@ static int check_msg_all_certs(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg, return ret; } -static int no_log_cb(const char *func, const char *file, int line, - OSSL_CMP_severity level, const char *msg) -{ - return 1; -} - /*- * Verify message signature with any acceptable and valid candidate cert. * On success cache the found cert using ossl_cmp_ctx_set1_validatedSrvCert(). @@ -465,7 +482,7 @@ static int check_msg_find_cert(OSSL_CMP_CTX *ctx, const OSSL_CMP_MSG *msg) /* enable clearing irrelevant errors in attempts to validate sender certs */ (void)ERR_set_mark(); - ctx->log_cb = no_log_cb; /* temporarily disable logging */ + ctx->log_cb = NULL; /* temporarily disable logging */ /* * try first cached scrt, used successfully earlier in same transaction, diff --git a/crypto/engine/eng_lib.c b/crypto/engine/eng_lib.c index 8345f684c813f5c72dad27e1cd080ff61579c1b6..412363fa371e3f9da2efdf96bac6bee29ac7cd66 100644 --- a/crypto/engine/eng_lib.c +++ b/crypto/engine/eng_lib.c @@ -135,28 +135,34 @@ static ENGINE_CLEANUP_ITEM *int_cleanup_item(ENGINE_CLEANUP_CB *cb) return item; } -void engine_cleanup_add_first(ENGINE_CLEANUP_CB *cb) +int engine_cleanup_add_first(ENGINE_CLEANUP_CB *cb) { ENGINE_CLEANUP_ITEM *item; if (!int_cleanup_check(1)) - return; + return 0; item = int_cleanup_item(cb); - if (item != NULL) - if (sk_ENGINE_CLEANUP_ITEM_insert(cleanup_stack, item, 0) <= 0) - OPENSSL_free(item); + if (item != NULL) { + if (sk_ENGINE_CLEANUP_ITEM_insert(cleanup_stack, item, 0)) + return 1; + OPENSSL_free(item); + } + return 0; } -void engine_cleanup_add_last(ENGINE_CLEANUP_CB *cb) +int engine_cleanup_add_last(ENGINE_CLEANUP_CB *cb) { ENGINE_CLEANUP_ITEM *item; + if (!int_cleanup_check(1)) - return; + return 0; item = int_cleanup_item(cb); if (item != NULL) { - if (sk_ENGINE_CLEANUP_ITEM_push(cleanup_stack, item) <= 0) - OPENSSL_free(item); + if (sk_ENGINE_CLEANUP_ITEM_push(cleanup_stack, item) > 0) + return 1; + OPENSSL_free(item); } + return 0; } /* The API function that performs all cleanup */ diff --git a/crypto/engine/eng_list.c b/crypto/engine/eng_list.c index 119e1c60459a8d39eed6b54ad3b554130368832f..a2c151d64a04ae13ee492fc32c429b4b5ae83bda 100644 --- a/crypto/engine/eng_list.c +++ b/crypto/engine/eng_list.c @@ -89,12 +89,16 @@ static int engine_list_add(ENGINE *e) ERR_raise(ERR_LIB_ENGINE, ENGINE_R_INTERNAL_LIST_ERROR); return 0; } - engine_list_head = e; - e->prev = NULL; /* * The first time the list allocates, we should register the cleanup. */ - engine_cleanup_add_last(engine_list_cleanup); + if (!engine_cleanup_add_last(engine_list_cleanup)) { + CRYPTO_DOWN_REF(&e->struct_ref, &ref); + ERR_raise(ERR_LIB_ENGINE, ENGINE_R_INTERNAL_LIST_ERROR); + return 0; + } + engine_list_head = e; + e->prev = NULL; } else { /* We are adding to the tail of an existing list. */ if ((engine_list_tail == NULL) || (engine_list_tail->next != NULL)) { diff --git a/crypto/engine/eng_local.h b/crypto/engine/eng_local.h index 6f5d380d02a43e647a48fdc6f2c48214daf19162..24920973e7b53e60b0171aa8b11984acdad8f12d 100644 --- a/crypto/engine/eng_local.h +++ b/crypto/engine/eng_local.h @@ -46,8 +46,8 @@ typedef struct st_engine_cleanup_item { ENGINE_CLEANUP_CB *cb; } ENGINE_CLEANUP_ITEM; DEFINE_STACK_OF(ENGINE_CLEANUP_ITEM) -void engine_cleanup_add_first(ENGINE_CLEANUP_CB *cb); -void engine_cleanup_add_last(ENGINE_CLEANUP_CB *cb); +int engine_cleanup_add_first(ENGINE_CLEANUP_CB *cb); +int engine_cleanup_add_last(ENGINE_CLEANUP_CB *cb); /* We need stacks of ENGINEs for use in eng_table.c */ DEFINE_STACK_OF(ENGINE) diff --git a/crypto/engine/eng_table.c b/crypto/engine/eng_table.c index 17225d0ad44cb6261f8c8e9c2ad960fe4cf4d5b7..9dc3144bbfd7b610c1cd73f056a9c7a0ea862bc8 100644 --- a/crypto/engine/eng_table.c +++ b/crypto/engine/eng_table.c @@ -93,9 +93,12 @@ int engine_table_register(ENGINE_TABLE **table, ENGINE_CLEANUP_CB *cleanup, added = 1; if (!int_table_check(table, 1)) goto end; - if (added) - /* The cleanup callback needs to be added */ - engine_cleanup_add_first(cleanup); + /* The cleanup callback needs to be added */ + if (added && !engine_cleanup_add_first(cleanup)) { + lh_ENGINE_PILE_free(&(*table)->piles); + *table = NULL; + goto end; + } while (num_nids--) { tmplate.nid = *nids; fnd = lh_ENGINE_PILE_retrieve(&(*table)->piles, &tmplate); diff --git a/crypto/err/err.c b/crypto/err/err.c index 3fc296929c5f64583075f6d6b3e45ec827c84379..7b7f309951554ca586273966a236253883b3da51 100644 --- a/crypto/err/err.c +++ b/crypto/err/err.c @@ -831,7 +831,7 @@ void ERR_add_error_vdata(int num, va_list args) i = es->top; /* - * If err_data is allocated already, re-use the space. + * If err_data is allocated already, reuse the space. * Otherwise, allocate a small new buffer. */ if ((es->err_data_flags[i] & flags) == flags) { diff --git a/crypto/evp/legacy_blake2.c b/crypto/evp/legacy_blake2.c index 6a18e5fe01b6a7192c1d67bd489b3f024ac189a6..4301ae4857913556f94880e4cca0c19964003d51 100644 --- a/crypto/evp/legacy_blake2.c +++ b/crypto/evp/legacy_blake2.c @@ -11,11 +11,31 @@ #include "prov/blake2.h" /* diverse BLAKE2 macros */ #include "legacy_meth.h" -#define ossl_blake2b_init ossl_blake2b512_init -#define ossl_blake2s_init ossl_blake2s256_init +/* + * Local hack to adapt the BLAKE2 init functions to what the + * legacy function signatures demand. + */ +static int blake2s_init(BLAKE2S_CTX *C) +{ + BLAKE2S_PARAM P; + + ossl_blake2s_param_init(&P); + return ossl_blake2s_init(C, &P); +} +static int blake2b_init(BLAKE2B_CTX *C) +{ + BLAKE2B_PARAM P; + + ossl_blake2b_param_init(&P); + return ossl_blake2b_init(C, &P); +} +#define blake2s_update ossl_blake2s_update +#define blake2b_update ossl_blake2b_update +#define blake2s_final ossl_blake2s_final +#define blake2b_final ossl_blake2b_final -IMPLEMENT_LEGACY_EVP_MD_METH_LC(blake2s_int, ossl_blake2s) -IMPLEMENT_LEGACY_EVP_MD_METH_LC(blake2b_int, ossl_blake2b) +IMPLEMENT_LEGACY_EVP_MD_METH_LC(blake2s_int, blake2s) +IMPLEMENT_LEGACY_EVP_MD_METH_LC(blake2b_int, blake2b) static const EVP_MD blake2b_md = { NID_blake2b512, diff --git a/crypto/evp/pmeth_gn.c b/crypto/evp/pmeth_gn.c index c8981227d40f1a1bc22baaa24efc884df2b0723a..6a38fe511a6362adc412fcb59b24481e939ed915 100644 --- a/crypto/evp/pmeth_gn.c +++ b/crypto/evp/pmeth_gn.c @@ -153,7 +153,7 @@ int EVP_PKEY_generate(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey) goto legacy; /* - * Asssigning gentmp to ctx->keygen_info is something our legacy + * Assigning gentmp to ctx->keygen_info is something our legacy * implementations do. Because the provider implementations aren't * allowed to reach into our EVP_PKEY_CTX, we need to provide similar * space for backward compatibility. It's ok that we attach a local diff --git a/crypto/evp/pmeth_lib.c b/crypto/evp/pmeth_lib.c index 6bd999407263295b45ca0007acd60f3fef32bdcb..268b1617e37993f98f857e7a8e320137babdcb5d 100644 --- a/crypto/evp/pmeth_lib.c +++ b/crypto/evp/pmeth_lib.c @@ -247,10 +247,11 @@ static EVP_PKEY_CTX *int_ctx_new(OSSL_LIB_CTX *libctx, */ if (e != NULL) pmeth = ENGINE_get_pkey_meth(e, id); - else if (pkey != NULL && pkey->foreign) + else +# endif /* OPENSSL_NO_ENGINE */ + if (pkey != NULL && pkey->foreign) pmeth = EVP_PKEY_meth_find(id); else -# endif app_pmeth = pmeth = evp_pkey_meth_find_added_by_application(id); /* END legacy */ diff --git a/crypto/ex_data.c b/crypto/ex_data.c index c9ec9d33370d2ec7345242e22cba37241f83d6e7..0412f38e9baae8eeac11073016fc208fbb80cc52 100644 --- a/crypto/ex_data.c +++ b/crypto/ex_data.c @@ -171,6 +171,8 @@ int ossl_crypto_get_ex_new_index_ex(OSSL_LIB_CTX *ctx, int class_index, * "app_data" routines use ex_data index zero. See RT 3710. */ if (ip->meth == NULL || !sk_EX_CALLBACK_push(ip->meth, NULL)) { + sk_EX_CALLBACK_free(ip->meth); + ip->meth = NULL; ERR_raise(ERR_LIB_CRYPTO, ERR_R_CRYPTO_LIB); goto err; } diff --git a/crypto/lhash/lhash.c b/crypto/lhash/lhash.c index 526af83026064ad379713454072f16aeac332c24..9d2b284ae0fa2777f9b205a1bc32b6728f446b8d 100644 --- a/crypto/lhash/lhash.c +++ b/crypto/lhash/lhash.c @@ -260,12 +260,12 @@ static void contract(OPENSSL_LHASH *lh) if (n == NULL) { /* fputs("realloc error in lhash", stderr); */ lh->error++; - return; + } else { + lh->b = n; } lh->num_alloc_nodes /= 2; lh->pmax /= 2; lh->p = lh->pmax - 1; - lh->b = n; } else lh->p--; diff --git a/crypto/o_str.c b/crypto/o_str.c index 119d791e2072bfbd5549fee7e3a243174fc6d39d..274b8476140b14ca9cc3f369a1797941c625961a 100644 --- a/crypto/o_str.c +++ b/crypto/o_str.c @@ -279,13 +279,13 @@ char *ossl_buf2hexstr_sep(const unsigned char *buf, long buflen, char sep) /* - * Given a buffer of length 'len' return a OPENSSL_malloc'ed string with its - * hex representation @@@ (Contents of buffer are always kept in ASCII, also - * on EBCDIC machines) + * Given a buffer of length 'buflen' return a OPENSSL_malloc'ed string with + * its hex representation @@@ (Contents of buffer are always kept in ASCII, + * also on EBCDIC machines) */ char *OPENSSL_buf2hexstr(const unsigned char *buf, long buflen) { - return ossl_buf2hexstr_sep(buf, buflen, ':'); + return ossl_buf2hexstr_sep(buf, buflen, DEFAULT_SEPARATOR); } int openssl_strerror_r(int errnum, char *buf, size_t buflen) diff --git a/crypto/pkcs12/p12_crt.c b/crypto/pkcs12/p12_crt.c index 3246fbb7e847955bea0c1c5b5b5c1ed13117d07f..7681731207b151dd2434df98db9b728ade61f33b 100644 --- a/crypto/pkcs12/p12_crt.c +++ b/crypto/pkcs12/p12_crt.c @@ -16,6 +16,12 @@ static int pkcs12_add_bag(STACK_OF(PKCS12_SAFEBAG) **pbags, PKCS12_SAFEBAG *bag); static int pkcs12_remove_bag(STACK_OF(PKCS12_SAFEBAG) **pbags, PKCS12_SAFEBAG *bag); +static PKCS12_SAFEBAG *pkcs12_add_cert_bag(STACK_OF(PKCS12_SAFEBAG) **pbags, + X509 *cert, + const char *name, + int namelen, + unsigned char *keyid, + int keyidlen); static int copy_bag_attr(PKCS12_SAFEBAG *bag, EVP_PKEY *pkey, int nid) { @@ -39,6 +45,9 @@ PKCS12 *PKCS12_create_ex2(const char *pass, const char *name, EVP_PKEY *pkey, int i, cbret; unsigned char keyid[EVP_MAX_MD_SIZE]; unsigned int keyidlen = 0; + int namelen = -1; + unsigned char *pkeyid = NULL; + int pkeyidlen = -1; /* Set defaults */ if (nid_cert == NID_undef) @@ -63,11 +72,16 @@ PKCS12 *PKCS12_create_ex2(const char *pass, const char *name, EVP_PKEY *pkey, } if (cert) { - bag = PKCS12_add_cert(&bags, cert); - if (name && !PKCS12_add_friendlyname(bag, name, -1)) - goto err; - if (keyidlen && !PKCS12_add_localkeyid(bag, keyid, keyidlen)) - goto err; + if (name == NULL) + name = (char *)X509_alias_get0(cert, &namelen); + if (keyidlen > 0) { + pkeyid = keyid; + pkeyidlen = keyidlen; + } else { + pkeyid = X509_keyid_get0(cert, &pkeyidlen); + } + + bag = pkcs12_add_cert_bag(&bags, cert, name, namelen, pkeyid, pkeyidlen); if (cb != NULL) { cbret = cb(bag, cbarg); if (cbret == -1) { @@ -175,30 +189,23 @@ PKCS12 *PKCS12_create(const char *pass, const char *name, EVP_PKEY *pkey, X509 * iter, mac_iter, keytype, NULL, NULL); } -PKCS12_SAFEBAG *PKCS12_add_cert(STACK_OF(PKCS12_SAFEBAG) **pbags, X509 *cert) +static PKCS12_SAFEBAG *pkcs12_add_cert_bag(STACK_OF(PKCS12_SAFEBAG) **pbags, + X509 *cert, + const char *name, + int namelen, + unsigned char *keyid, + int keyidlen) { PKCS12_SAFEBAG *bag = NULL; - char *name; - int namelen = -1; - unsigned char *keyid; - int keyidlen = -1; /* Add user certificate */ if ((bag = PKCS12_SAFEBAG_create_cert(cert)) == NULL) goto err; - /* - * Use friendlyName and localKeyID in certificate. (if present) - */ - - name = (char *)X509_alias_get0(cert, &namelen); - - if (name && !PKCS12_add_friendlyname(bag, name, namelen)) + if (name != NULL && !PKCS12_add_friendlyname(bag, name, namelen)) goto err; - keyid = X509_keyid_get0(cert, &keyidlen); - - if (keyid && !PKCS12_add_localkeyid(bag, keyid, keyidlen)) + if (keyid != NULL && !PKCS12_add_localkeyid(bag, keyid, keyidlen)) goto err; if (!pkcs12_add_bag(pbags, bag)) @@ -209,7 +216,22 @@ PKCS12_SAFEBAG *PKCS12_add_cert(STACK_OF(PKCS12_SAFEBAG) **pbags, X509 *cert) err: PKCS12_SAFEBAG_free(bag); return NULL; +} + +PKCS12_SAFEBAG *PKCS12_add_cert(STACK_OF(PKCS12_SAFEBAG) **pbags, X509 *cert) +{ + char *name = NULL; + int namelen = -1; + unsigned char *keyid = NULL; + int keyidlen = -1; + + /* + * Use friendlyName and localKeyID in certificate. (if present) + */ + name = (char *)X509_alias_get0(cert, &namelen); + keyid = X509_keyid_get0(cert, &keyidlen); + return pkcs12_add_cert_bag(pbags, cert, name, namelen, keyid, keyidlen); } PKCS12_SAFEBAG *PKCS12_add_key_ex(STACK_OF(PKCS12_SAFEBAG) **pbags, diff --git a/crypto/store/store_lib.c b/crypto/store/store_lib.c index df3180c04847cefbc540685bc55c87753b89981b..d0561f636cfde859e852355d7809a70ef1f30406 100644 --- a/crypto/store/store_lib.c +++ b/crypto/store/store_lib.c @@ -66,6 +66,7 @@ OSSL_STORE_open_ex(const char *uri, OSSL_LIB_CTX *libctx, const char *propq, OSSL_STORE_post_process_info_fn post_process, void *post_process_data) { + struct ossl_passphrase_data_st pwdata = { 0 }; const OSSL_STORE_LOADER *loader = NULL; OSSL_STORE_LOADER *fetched_loader = NULL; OSSL_STORE_LOADER_CTX *loader_ctx = NULL; @@ -102,6 +103,13 @@ OSSL_STORE_open_ex(const char *uri, OSSL_LIB_CTX *libctx, const char *propq, ERR_set_mark(); + if (ui_method != NULL + && (!ossl_pw_set_ui_method(&pwdata, ui_method, ui_data) + || !ossl_pw_enable_passphrase_caching(&pwdata))) { + ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_CRYPTO_LIB); + goto err; + } + /* * Try each scheme until we find one that could open the URI. * @@ -135,17 +143,28 @@ OSSL_STORE_open_ex(const char *uri, OSSL_LIB_CTX *libctx, const char *propq, void *provctx = OSSL_PROVIDER_get0_provider_ctx(provider); no_loader_found = 0; - loader_ctx = fetched_loader->p_open(provctx, uri); + if (fetched_loader->p_open_ex != NULL) { + loader_ctx = + fetched_loader->p_open_ex(provctx, uri, params, + ossl_pw_passphrase_callback_dec, + &pwdata); + } else { + loader_ctx = fetched_loader->p_open(provctx, uri); + if (loader_ctx != NULL && + !loader_set_params(fetched_loader, loader_ctx, + params, propq)) { + (void)fetched_loader->p_close(loader_ctx); + loader_ctx = NULL; + } + } if (loader_ctx == NULL) { OSSL_STORE_LOADER_free(fetched_loader); fetched_loader = NULL; - } else if (!loader_set_params(fetched_loader, loader_ctx, - params, propq)) { - (void)fetched_loader->p_close(loader_ctx); - OSSL_STORE_LOADER_free(fetched_loader); - fetched_loader = NULL; } loader = fetched_loader; + + /* Clear any internally cached passphrase */ + (void)ossl_pw_clear_passphrase_cache(&pwdata); } } @@ -171,18 +190,13 @@ OSSL_STORE_open_ex(const char *uri, OSSL_LIB_CTX *libctx, const char *propq, || (ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL) goto err; - if (ui_method != NULL - && (!ossl_pw_set_ui_method(&ctx->pwdata, ui_method, ui_data) - || !ossl_pw_enable_passphrase_caching(&ctx->pwdata))) { - ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_CRYPTO_LIB); - goto err; - } ctx->properties = propq_copy; ctx->fetched_loader = fetched_loader; ctx->loader = loader; ctx->loader_ctx = loader_ctx; ctx->post_process = post_process; ctx->post_process_data = post_process_data; + ctx->pwdata = pwdata; /* * If the attempt to open with the 'file' scheme loader failed and the @@ -480,6 +494,53 @@ OSSL_STORE_INFO *OSSL_STORE_load(OSSL_STORE_CTX *ctx) return v; } +int OSSL_STORE_delete(const char *uri, OSSL_LIB_CTX *libctx, const char *propq, + const UI_METHOD *ui_method, void *ui_data, + const OSSL_PARAM params[]) +{ + OSSL_STORE_LOADER *fetched_loader = NULL; + char scheme[256], *p; + int res = 0; + struct ossl_passphrase_data_st pwdata = {0}; + + OPENSSL_strlcpy(scheme, uri, sizeof(scheme)); + if ((p = strchr(scheme, ':')) != NULL) + *p++ = '\0'; + else /* We don't work without explicit scheme */ + return 0; + + if (ui_method != NULL + && (!ossl_pw_set_ui_method(&pwdata, ui_method, ui_data) + || !ossl_pw_enable_passphrase_caching(&pwdata))) { + ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_CRYPTO_LIB); + return 0; + } + + OSSL_TRACE1(STORE, "Looking up scheme %s\n", scheme); + fetched_loader = OSSL_STORE_LOADER_fetch(libctx, scheme, propq); + + if (fetched_loader != NULL && fetched_loader->p_delete != NULL) { + const OSSL_PROVIDER *provider = + OSSL_STORE_LOADER_get0_provider(fetched_loader); + void *provctx = OSSL_PROVIDER_get0_provider_ctx(provider); + + /* + * It's assumed that the loader's delete() method reports its own + * errors + */ + OSSL_TRACE1(STORE, "Performing URI delete %s\n", uri); + res = fetched_loader->p_delete(provctx, uri, params, + ossl_pw_passphrase_callback_dec, + &pwdata); + } + /* Clear any internally cached passphrase */ + (void)ossl_pw_clear_passphrase_cache(&pwdata); + + OSSL_STORE_LOADER_free(fetched_loader); + + return res; +} + int OSSL_STORE_error(OSSL_STORE_CTX *ctx) { int ret = 1; diff --git a/crypto/store/store_local.h b/crypto/store/store_local.h index 223758ab2b7180df426f5f805ed9f8c09d8ea5ef..6ad79180a091f620707bf904dfa674c7d43ab71b 100644 --- a/crypto/store/store_local.h +++ b/crypto/store/store_local.h @@ -112,6 +112,8 @@ struct ossl_store_loader_st { OSSL_FUNC_store_eof_fn *p_eof; OSSL_FUNC_store_close_fn *p_close; OSSL_FUNC_store_export_object_fn *p_export_object; + OSSL_FUNC_store_delete_fn *p_delete; + OSSL_FUNC_store_open_ex_fn *p_open_ex; }; DEFINE_LHASH_OF_EX(OSSL_STORE_LOADER); diff --git a/crypto/store/store_meth.c b/crypto/store/store_meth.c index 7fc79e2989087d4e8c1d8a2ac7dcd115915e2cb7..6ac8fd5f9374b61f47125c65eca0d334dde46cd9 100644 --- a/crypto/store/store_meth.c +++ b/crypto/store/store_meth.c @@ -219,6 +219,14 @@ static void *loader_from_algorithm(int scheme_id, const OSSL_ALGORITHM *algodef, if (loader->p_export_object == NULL) loader->p_export_object = OSSL_FUNC_store_export_object(fns); break; + case OSSL_FUNC_STORE_DELETE: + if (loader->p_delete == NULL) + loader->p_delete = OSSL_FUNC_store_delete(fns); + break; + case OSSL_FUNC_STORE_OPEN_EX: + if (loader->p_open_ex == NULL) + loader->p_open_ex = OSSL_FUNC_store_open_ex(fns); + break; } } @@ -226,7 +234,7 @@ static void *loader_from_algorithm(int scheme_id, const OSSL_ALGORITHM *algodef, || loader->p_load == NULL || loader->p_eof == NULL || loader->p_close == NULL) { - /* Only set_ctx_params is optionaal */ + /* Only set_ctx_params is optional */ OSSL_STORE_LOADER_free(loader); ERR_raise(ERR_LIB_OSSL_STORE, OSSL_STORE_R_LOADER_INCOMPLETE); return NULL; diff --git a/doc/designs/prov_loadex.md b/doc/designs/ossl-provider-load-ex.md similarity index 54% rename from doc/designs/prov_loadex.md rename to doc/designs/ossl-provider-load-ex.md index 818f5cce2d78fe86338ee7fcef37bb6d65feafc4..62d5c8c327663076f330178e63f3482a4637213e 100644 --- a/doc/designs/prov_loadex.md +++ b/doc/designs/ossl-provider-load-ex.md @@ -1,12 +1,12 @@ -Providers run-time configuration -================================ +OSSL_PROVIDER_load_ex - activating providers with run-time configuration +======================================================================== -Currently any provider run-time activation requires presence of the +Currently any provider run-time activation requires the presence of the initialization parameters in the OpenSSL configuration file. Otherwise the -provider will be activated with some "default" settings, that may or may not +provider will be activated with some default settings, that may or may not work for a particular application. For real-world systems it may require -providing a specially designed OpenSSL config and passing it somehow (e.g. via -environment) that has its obvious drawbacks. +providing a specially designed OpenSSL configuration file and passing it somehow +(e.g. via environment), which has obvious drawbacks. We need a possibility to initialize providers on per-application level according to per-application parameters. It's necessary for example for PKCS#11 @@ -21,23 +21,23 @@ OSSL_PROVIDER *OSSL_PROVIDER_load_ex(OSSL_LIB_CTX *libctx, const char *name, OSSL_PARAM params[]); ``` -intended to configure the provider in load time. +intended to configure the provider at load time. It accepts only parameters of type `OSSL_PARAM_UTF8_STRING` because any provider can be initialized from the config file where the values are represented as strings and provider init function has to deal with it. -Explicitly configured parameters can contradict the parameters named in the +Explicitly configured parameters can differ from the parameters named in the configuration file. Here are the current design decisions and some possible future steps. Real-world cases ---------------- -Many applications use PKCS#11 API with a specific drivers. OpenSSL PKCS#11 +Many applications use PKCS#11 API with specific drivers. OpenSSL PKCS#11 provider also provides a set of -tweaks usable in particular situations. So there are at least several scenarios -I have in mind: +tweaks usable in particular situations. So there are several scenarios for which +the new API can be used: 1. Configure a provider in the config file, activate on demand 2. Load/activate a provider run-time with parameters @@ -45,26 +45,25 @@ I have in mind: Current design -------------- -When the provider is loaded in the current library context and activated, the -currently loaded provider will be returned as the result of -`OSSL_PROVIDER_load_ex` call. +When the provider is already loaded an activated in the current library context, +the `OSSL_PROVIDER_load_ex` call simply returns the active provider and the +extra parameters are ignored. -When the provider is loaded in the current library context and NOT activated, -the parameters provided int the `OSSL_PROVIDER_load_ex` call will have the -preference. +In all other cases, the extra parameters provided by the `OSSL_PROVIDER_load_ex` +call are applied and the values from the config file are ignored. Separate instances of the provider can be loaded in the separate library contexts. -Several instances of the same provider in the same context using different -section names, module names (e.g. via symlinks) and provider names. But unless -the provider does not support some configuration options, the algorithms in +Several instances of the same provider can be loaded in the same context using +different section names, module names (e.g. via symlinks) and provider names. +But unless the provider supports some configuration options, the algorithms in this case will have the same `provider` property and the result of fetching is not determined. We strongly discourage against this trick. -The run-time change of the loaded provider configuration is not supported. If -it is necessary, the calls to `OSSL_PROVIDER_unload` with the following call to -the `OSSL_PROVIDER_load` or `OSSL_PROVIDER_load_ex` should be used. +Changing the loaded provider configuration at runtime is not supported. If +it is necessary, the provider needs to be unloaded using `OSSL_PROVIDER_unload` +and reloaded using `OSSL_PROVIDER_load` or `OSSL_PROVIDER_load_ex` should be used. Possible future steps --------------------- diff --git a/doc/designs/quic-design/quic-fault-injector.md b/doc/designs/quic-design/quic-fault-injector.md index 30db905ee84a6a7e3275e258eec7c598ef35ff4c..bea36b98cbf6211730eb5746fe920e2d4e868515 100644 --- a/doc/designs/quic-design/quic-fault-injector.md +++ b/doc/designs/quic-design/quic-fault-injector.md @@ -215,7 +215,7 @@ typedef struct ossl_qf_encrypted_extensions { int qtest_create_quic_objects(OSSL_LIB_CTX *libctx, SSL_CTX *clientctx, SSL_CTX *serverctx, char *certfile, char *keyfile, int block, QUIC_TSERVER **qtserv, SSL **cssl, - OSSL_QUIC_FAULT **fault); + OSSL_QUIC_FAULT **fault, BIO **tracebio); /* * Free up a Fault Injector instance @@ -440,7 +440,7 @@ static int test_unknown_frame(void) goto err; if (!TEST_true(qtest_create_quic_objects(NULL, cctx, NULL, cert, privkey, 0, - &qtserv, &cssl, &fault))) + &qtserv, &cssl, &fault, NULL))) goto err; if (!TEST_true(qtest_create_quic_connection(qtserv, cssl))) @@ -523,7 +523,7 @@ static int test_no_transport_params(void) goto err; if (!TEST_true(qtest_create_quic_objects(NULL, cctx, NULL, cert, privkey, 0, - &qtserv, &cssl, &fault))) + &qtserv, &cssl, &fault, NULL))) goto err; if (!TEST_true(ossl_quic_fault_set_hand_enc_ext_listener(fault, diff --git a/doc/internal/man3/ossl_provider_new.pod b/doc/internal/man3/ossl_provider_new.pod index e170edf343af7aa43df53599f7286fcff5132c47..d30e400894376a9d7f0be7d4d9aa4209aa29c653 100644 --- a/doc/internal/man3/ossl_provider_new.pod +++ b/doc/internal/man3/ossl_provider_new.pod @@ -291,7 +291,7 @@ in a bitstring that's internal to I. ossl_provider_test_operation_bit() checks if the bit operation I is set (1) or not (0) in the internal I bitstring, and sets -I<*result> to 1 or 0 accorddingly. +I<*result> to 1 or 0 accordingly. ossl_provider_init_as_child() stores in the library context I references to the necessary upcalls for managing child providers. The I and I diff --git a/doc/man1/openssl-cms.pod.in b/doc/man1/openssl-cms.pod.in index 50845b772e4ea7f013fc728f4bf1ffe8255d071a..a3ef9c01812055b4b35662ce9de3e2bcdfffdf89 100644 --- a/doc/man1/openssl-cms.pod.in +++ b/doc/man1/openssl-cms.pod.in @@ -402,7 +402,7 @@ option. =item I ... This is an alternative to using the B<-recip> option when encrypting a message. -One or more certificate filennames may be given. +One or more certificate filenames may be given. =item B<-I> diff --git a/doc/man3/EVP_MAC.pod b/doc/man3/EVP_MAC.pod index 13482ac5e188e7b7016e7ff49d59d15790167a47..8fd237599e29d2765029009e9171573e6de25062 100644 --- a/doc/man3/EVP_MAC.pod +++ b/doc/man3/EVP_MAC.pod @@ -181,7 +181,7 @@ EVP_MAC_CTX_set_params() passes chosen parameters to the underlying context, given a context I. The set of parameters given with I determine exactly what parameters are passed down. -If I are NULL, the unterlying context should do nothing and return 1. +If I are NULL, the underlying context should do nothing and return 1. Note that a parameter that is unknown in the underlying context is simply ignored. Also, what happens when a needed parameter isn't passed down is diff --git a/doc/man3/EVP_SIGNATURE.pod b/doc/man3/EVP_SIGNATURE.pod index 600522085398c271ecf946cb3c36428488fb52f3..a4ee9c4807d7aa034bdf632f9f785f5756b20049 100644 --- a/doc/man3/EVP_SIGNATURE.pod +++ b/doc/man3/EVP_SIGNATURE.pod @@ -61,7 +61,7 @@ EVP_SIGNATURE_get0_provider() returns the provider that I was fetched from. EVP_SIGNATURE_do_all_provided() traverses all SIGNATURE implemented by all -activated roviders in the given library context I, and for each of the +activated providers in the given library context I, and for each of the implementations, calls the given function I with the implementation method and the given I as argument. diff --git a/doc/man3/OSSL_CMP_validate_msg.pod b/doc/man3/OSSL_CMP_validate_msg.pod index 9fe7f4385f0f12c9ff757ad48a9a3bac2eaf74dc..7dbe3f74ca1ebf3c9625eaf1efd33678aa30f22c 100644 --- a/doc/man3/OSSL_CMP_validate_msg.pod +++ b/doc/man3/OSSL_CMP_validate_msg.pod @@ -30,10 +30,12 @@ is preferably the one provided by a call to L. If no such sender cert has been pinned then candidate sender certificates are taken from the list of certificates received in the I extraCerts, then any certificates provided before via L, and -then all trusted certificates provided via L, -where a candidate is acceptable only if has not expired, its subject DN matches +then all trusted certificates provided via L. +A candidate certificate is acceptable only if it is currently valid +(or the trust store contains a verification callback that overrides the verdict +that the certificate is expired or not yet valid), its subject DN matches the I sender DN (as far as present), and its subject key identifier -is present and matches the senderKID (as far as the latter present). +is present and matches the senderKID (as far as the latter is present). Each acceptable cert is tried in the given order to see if the message signature check succeeds and the cert and its path can be verified using any trust store set via L. diff --git a/doc/man3/OSSL_STORE_open.pod b/doc/man3/OSSL_STORE_open.pod index fe51912e84c05396c640caf8d2dd4e0f42b4dfcf..8e4a9a79267850b87dbe960dc20983f1a9290f05 100644 --- a/doc/man3/OSSL_STORE_open.pod +++ b/doc/man3/OSSL_STORE_open.pod @@ -4,7 +4,7 @@ OSSL_STORE_CTX, OSSL_STORE_post_process_info_fn, OSSL_STORE_open, OSSL_STORE_open_ex, -OSSL_STORE_ctrl, OSSL_STORE_load, OSSL_STORE_eof, +OSSL_STORE_ctrl, OSSL_STORE_load, OSSL_STORE_eof, OSSL_STORE_delete, OSSL_STORE_error, OSSL_STORE_close - Types and functions to read objects from a URI @@ -30,6 +30,9 @@ OSSL_STORE_error, OSSL_STORE_close OSSL_STORE_INFO *OSSL_STORE_load(OSSL_STORE_CTX *ctx); int OSSL_STORE_eof(OSSL_STORE_CTX *ctx); + int OSSL_STORE_delete(const char *uri, OSSL_LIB_CTX *libctx, const char *propq, + const UI_METHOD *ui_method, void *ui_data, + const OSSL_PARAM params[]); int OSSL_STORE_error(OSSL_STORE_CTX *ctx); int OSSL_STORE_close(OSSL_STORE_CTX *ctx); @@ -104,6 +107,8 @@ Any other value is an error. OSSL_STORE_load() takes a B and tries to load the next available object and return it wrapped with B. +OSSL_STORE_delete() deletes the object identified by I. + OSSL_STORE_eof() takes a B and checks if we've reached the end of data. @@ -152,7 +157,8 @@ or an error occurred, 0 otherwise. OSSL_STORE_error() returns 1 if an error occurred in an OSSL_STORE_load() call, otherwise 0. -OSSL_STORE_ctrl() and OSSL_STORE_close() returns 1 on success, or 0 on failure. +OSSL_STORE_delete(), OSSL_STORE_ctrl() and OSSL_STORE_close() return 1 on +success, or 0 on failure. =head1 SEE ALSO @@ -161,6 +167,8 @@ L =head1 HISTORY +OSSL_STORE_delete() was added in OpenSSL 3.2. + OSSL_STORE_open_ex() was added in OpenSSL 3.0. B, OSSL_STORE_post_process_info_fn(), OSSL_STORE_open(), @@ -170,8 +178,6 @@ were added in OpenSSL 1.1.1. Handling of NULL I argument for OSSL_STORE_close() was introduced in OpenSSL 1.1.1h. -OSSL_STORE_open_ex() was added in OpenSSL 3.0. - OSSL_STORE_ctrl() and OSSL_STORE_vctrl() were deprecated in OpenSSL 3.0. =head1 COPYRIGHT diff --git a/doc/man3/SSL_CONF_CTX_set_ssl_ctx.pod b/doc/man3/SSL_CONF_CTX_set_ssl_ctx.pod index 06cc1e4ec539d23d9d3588efc1d76e7748da1f47..b74c869b83d2dc99df397e9ef00a8f85ac00dc96 100644 --- a/doc/man3/SSL_CONF_CTX_set_ssl_ctx.pod +++ b/doc/man3/SSL_CONF_CTX_set_ssl_ctx.pod @@ -2,6 +2,7 @@ =head1 NAME +SSL_CONF_CTX_finish, SSL_CONF_CTX_set_ssl_ctx, SSL_CONF_CTX_set_ssl - set context to configure =head1 SYNOPSIS @@ -10,6 +11,7 @@ SSL_CONF_CTX_set_ssl_ctx, SSL_CONF_CTX_set_ssl - set context to configure void SSL_CONF_CTX_set_ssl_ctx(SSL_CONF_CTX *cctx, SSL_CTX *ctx); void SSL_CONF_CTX_set_ssl(SSL_CONF_CTX *cctx, SSL *ssl); + int SSL_CONF_CTX_finish(SSL_CONF_CTX *cctx); =head1 DESCRIPTION @@ -23,6 +25,10 @@ B structure B. Any previous B or B associated with B is cleared. Subsequent calls to SSL_CONF_cmd() will be sent to B. +The function SSL_CONF_CTX_finish() must be called after all configuration +operations have been completed. It is used to finalise any operations +or to process defaults. + =head1 NOTES The context need not be set or it can be set to B in which case only @@ -32,6 +38,8 @@ syntax checking of commands is performed, where possible. SSL_CONF_CTX_set_ssl_ctx() and SSL_CTX_set_ssl() do not return a value. +SSL_CONF_CTX_finish() returns 1 for success and 0 for failure. + =head1 SEE ALSO L, diff --git a/doc/man3/SSL_get_rpoll_descriptor.pod b/doc/man3/SSL_get_rpoll_descriptor.pod index 5e1879580e82f78822946108fd264fc04c0a1caf..3bdd0a924c646d75c3a695463ca71c3a86edfd25 100644 --- a/doc/man3/SSL_get_rpoll_descriptor.pod +++ b/doc/man3/SSL_get_rpoll_descriptor.pod @@ -66,7 +66,14 @@ may change in response to any call to the SSL object other than SSL_net_read_desired(), SSL_net_write_desired(), SSL_get_rpoll_descriptor(), SSL_get_wpoll_descriptor() and SSL_get_event_timeout(). -These functions are not supported on non-QUIC SSL objects. +On non-QUIC SSL objects, calls to SSL_get_rpoll_descriptor() and +SSL_get_wpoll_descriptor() function the same as calls to +BIO_get_rpoll_descriptor() and BIO_get_wpoll_descriptor() on the respective read +and write BIOs configured on the SSL object. + +On non-QUIC SSL objects, calls to SSL_net_read_desired() and +SSL_net_write_desired() function identically to calls to SSL_want_read() and +SSL_want_write() respectively. =head1 RETURN VALUES diff --git a/doc/man3/d2i_RSAPrivateKey.pod b/doc/man3/d2i_RSAPrivateKey.pod index b3ea95c692a0dd7d83151d6de386f5d00caee8a5..08cd2c85e5bd79d50dc757f7e9d5ff4c60e835d7 100644 --- a/doc/man3/d2i_RSAPrivateKey.pod +++ b/doc/man3/d2i_RSAPrivateKey.pod @@ -28,7 +28,6 @@ d2i_RSA_PUBKEY_fp, d2i_DHparams, d2i_DHparams_bio, d2i_DHparams_fp, -d2i_ECPKParameters, d2i_ECParameters, d2i_ECPrivateKey, d2i_ECPrivateKey_bio, @@ -56,7 +55,6 @@ i2d_DSA_PUBKEY, i2d_DSA_PUBKEY_bio, i2d_DSA_PUBKEY_fp, i2d_DSAparams, -i2d_ECPKParameters, i2d_ECParameters, i2d_ECPrivateKey, i2d_ECPrivateKey_bio, diff --git a/doc/man3/d2i_X509.pod b/doc/man3/d2i_X509.pod index c79a964e6d7f981aef97b0e2f8e1faa5a08051b7..9226ef77c3946b0f5e181c03d86200ffd2957b11 100644 --- a/doc/man3/d2i_X509.pod +++ b/doc/man3/d2i_X509.pod @@ -53,6 +53,7 @@ d2i_DIST_POINT, d2i_DIST_POINT_NAME, d2i_DSA_SIG, d2i_ECDSA_SIG, +d2i_ECPKParameters, d2i_EDIPARTYNAME, d2i_ESS_CERT_ID, d2i_ESS_CERT_ID_V2, @@ -223,6 +224,7 @@ i2d_DIST_POINT, i2d_DIST_POINT_NAME, i2d_DSA_SIG, i2d_ECDSA_SIG, +i2d_ECPKParameters, i2d_EDIPARTYNAME, i2d_ESS_CERT_ID, i2d_ESS_CERT_ID_V2, diff --git a/doc/man5/x509v3_config.pod b/doc/man5/x509v3_config.pod index 2440f23dddc281e1c92d4fca53b3b94e6c71e017..ab33b7e7afe03ec589da0d94ab7ac844675f5dba 100644 --- a/doc/man5/x509v3_config.pod +++ b/doc/man5/x509v3_config.pod @@ -93,7 +93,7 @@ numeric identifier, as shown here: email.2 = steve@example.org The syntax of raw extensions is defined by the source code that parses -the extension but should be documened. +the extension but should be documented. See L for an example of a raw extension. If an extension type is unsupported, then the I extension syntax diff --git a/doc/man7/ossl-guide-libraries-introduction.pod b/doc/man7/ossl-guide-libraries-introduction.pod index 78e0853d8e68db83c692513766ee5cd34561e0c4..d54e98cd86396e4b0fd8d017122b956d3aa51878 100644 --- a/doc/man7/ossl-guide-libraries-introduction.pod +++ b/doc/man7/ossl-guide-libraries-introduction.pod @@ -15,12 +15,12 @@ encryption, digital signatures, hash functions, etc. It additionally supplies supporting APIs for cryptography related standards, e.g. for reading and writing digital certificates (also known as X.509 certificates). Finally it also supplies various additional supporting APIs that are not directly cryptography -related but are nonetheless useful and dependended upon by other APIs. For +related but are nonetheless useful and depended upon by other APIs. For example the "BIO" functions provide capabilities for abstracting I/O, e.g. via a file or over a network. The C library provides functions to perform secure communication between -two peers across a network. Most signficiantly it implements support for the +two peers across a network. Most significantly it implements support for the SSL/TLS, DTLS and QUIC standards. The C library depends on and uses many of the capabilities supplied by diff --git a/doc/man7/ossl-guide-quic-client-non-block.pod b/doc/man7/ossl-guide-quic-client-non-block.pod index 8187bb9b77d54f0959a3da1257f3c1023d291350..0c2b916b803b00b0c601353c7586ca3982024dc3 100644 --- a/doc/man7/ossl-guide-quic-client-non-block.pod +++ b/doc/man7/ossl-guide-quic-client-non-block.pod @@ -43,7 +43,7 @@ L or L will return immediately with a non-fatal error if they are currently unable to read or write respectively. Since this page is building on the example developed on the -L page we assume that you are familar with it +L page we assume that you are familiar with it and we only explain how this example differs. =head2 Performing work while waiting for the socket @@ -407,7 +407,7 @@ L. Since our application is initiating the shutdown then we might expect to see L give a return value of 0, and then we should continue to call -it until we recieve a return value of 1 (meaning we have successfully completed +it until we receive a return value of 1 (meaning we have successfully completed the shutdown). Since we are using a nonblocking B object we might expect to have to retry this operation several times. If L returns a negative result then we must call L to work out what to do diff --git a/doc/man7/ossl-guide-quic-multi-stream.pod b/doc/man7/ossl-guide-quic-multi-stream.pod index 4e4d852b035e2e4e59e659dddf0e099ec7a625a6..877d2208ae787bb3ed7ae51e229a2280ce2b5903 100644 --- a/doc/man7/ossl-guide-quic-multi-stream.pod +++ b/doc/man7/ossl-guide-quic-multi-stream.pod @@ -96,7 +96,7 @@ When using a default stream OpenSSL will prevent new streams from being accepted. To override this behaviour you must call L to set the policy to B. See the man page for further details. This -is not relevant if the default stream has been disabed as described in +is not relevant if the default stream has been disabled as described in L above. Any stream may be bi-directional or uni-directional. If it is uni-directional diff --git a/doc/man7/ossl-guide-tls-client-block.pod b/doc/man7/ossl-guide-tls-client-block.pod index 865a5353b3fa3322519e324f1531099c6cbb9f4e..646b58081ad4c7564c5a580d8def67120c0328a9 100644 --- a/doc/man7/ossl-guide-tls-client-block.pod +++ b/doc/man7/ossl-guide-tls-client-block.pod @@ -124,7 +124,7 @@ function and passing the B we created as an argument. =head2 Creating the socket and BIO TLS data is transmitted over an underlying transport layer. Normally a TCP -socket. It is the application's resonsibility for ensuring that the socket is +socket. It is the application's responsibility for ensuring that the socket is created and associated with an SSL object (via a BIO). Socket creation for use by a client is typically a 2 step process, i.e. @@ -549,7 +549,7 @@ intermediate CAs, or the issuer is simply unrecognised). =head1 FURTHER READING See L to read a tutorial on how to modify -the client devloped on this page to support a nonblocking socket. +the client developed on this page to support a nonblocking socket. See L to read a tutorial on how to modify the client developed on this page to support QUIC instead of TLS. diff --git a/doc/man7/ossl-guide-tls-client-non-block.pod b/doc/man7/ossl-guide-tls-client-non-block.pod index ea5e40bd1cadb5714a22500bcb50a152574d2411..1eabcc0b576bee153e4cfcaf8995002d0a0b2910 100644 --- a/doc/man7/ossl-guide-tls-client-non-block.pod +++ b/doc/man7/ossl-guide-tls-client-non-block.pod @@ -41,7 +41,7 @@ behaviour is propagated up to the application so that OpenSSL I/O functions such as L or L will not block. Since this page is building on the example developed on the -L page we assume that you are familar with it +L page we assume that you are familiar with it and we only explain how this example differs. =head2 Setting the socket to be nonblocking @@ -162,7 +162,7 @@ Fatal errors that may occur are B and B. These indicate that the underlying connection has failed. You should not attempt to shut it down with L. B indicates that OpenSSL attempted to make a syscall that failed. You can consult B for -further details. B indicates that some OpenSSL error occured. You +further details. B indicates that some OpenSSL error occurred. You can consult the OpenSSL error stack for further details (for example by calling L to print out details of errors that have occurred). @@ -313,7 +313,7 @@ finished with it. If our application was initiating the shutdown then we would expect to see L give a return value of 0, and then we would continue to call -it until we recieved a return value of 1 (meaning we have successfully completed +it until we received a return value of 1 (meaning we have successfully completed the shutdown). In this particular example we don't expect SSL_shutdown() to return 0 because we have already received EOF from the server indicating that it has shutdown already. So we just keep calling it until SSL_shutdown() returns 1. diff --git a/doc/man7/provider-storemgmt.pod b/doc/man7/provider-storemgmt.pod index 615ff7ef8e552732a5a2ab967c2827097f2c4657..a8ce43c4bb2b5202789503d6d686abb3dccada9a 100644 --- a/doc/man7/provider-storemgmt.pod +++ b/doc/man7/provider-storemgmt.pod @@ -27,6 +27,14 @@ provider-storemgmt - The OSSL_STORE library E-E provider functions int OSSL_FUNC_store_export_object (void *loaderctx, const void *objref, size_t objref_sz, OSSL_CALLBACK *export_cb, void *export_cbarg); + void *OSSL_FUNC_store_open_ex(void *provctx, const char *uri, + const OSSL_PARAM params[], + OSSL_PASSPHRASE_CALLBACK *pw_cb, + void *pw_cbarg); + + int OSSL_FUNC_store_delete(void *provctx, const char *uri, + const OSSL_PARAM params[], + OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg); =head1 DESCRIPTION @@ -70,6 +78,8 @@ in L, as follows: OSSL_FUNC_store_eof OSSL_FUNC_STORE_EOF OSSL_FUNC_store_close OSSL_FUNC_STORE_CLOSE OSSL_FUNC_store_export_object OSSL_FUNC_STORE_EXPORT_OBJECT + OSSL_FUNC_store_delete OSSL_FUNC_STORE_DELETE + OSSL_FUNC_store_open_ex OSSL_FUNC_STORE_OPEN_EX =head2 Functions @@ -114,6 +124,18 @@ OSSL_FUNC_store_export_object() should export the object of size I referenced by I as an L array and pass that to the I as well as the given I. +OSSL_FUNC_store_delete() deletes the object identified by the I. The +implementation is entirely responsible for the interpretation of the URI. In +case a passphrase needs to be prompted to remove an object, I should be +called. + +OSSL_FUNC_store_open_ex() is an extended variant of OSSL_FUNC_store_open(). If +the provider does not implement this function the code internally falls back to +use the original OSSL_FUNC_store_open(). +This variant additionally accepts an L object and a I +callback that can be used to request a passphrase in cases where the whole +store needs to be unlocked before performing any load operation. + =head2 Load Parameters =over 4 @@ -186,6 +208,8 @@ L The STORE interface was introduced in OpenSSL 3.0. +OSSL_FUNC_store_delete() callback was added in OpenSSL 3.2 + =head1 COPYRIGHT Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved. diff --git a/include/internal/e_os.h b/include/internal/e_os.h index d0e903f653ed62044863a84cfc586131d84bc612..d1ed62e890298c679760258431be3ab7b2c0629f 100644 --- a/include/internal/e_os.h +++ b/include/internal/e_os.h @@ -22,15 +22,6 @@ * outside; this file e_os.h is not part of the exported interface. */ -/* ossl_static_assert_type_eq: gcc-only variable type static assertion */ -# if defined(__GNUC__) && !defined(__clang__) -# define ossl_static_assert_type_eq(type, x) \ - _Static_assert((__builtin_types_compatible_p(type, __typeof__(x))), \ - #x " type check failed, expected: " #type) -# else -# define ossl_static_assert_type_eq(type, x) -# endif - # if defined(OPENSSL_SYS_VXWORKS) || defined(OPENSSL_SYS_UEFI) # define NO_CHMOD # define NO_SYSLOG diff --git a/include/internal/quic_ssl.h b/include/internal/quic_ssl.h index 260cef87b97632560bbffa5ed4fd8dce53659f99..66cea1bfe12ce5962fa59e26ed187522726d4f6f 100644 --- a/include/internal/quic_ssl.h +++ b/include/internal/quic_ssl.h @@ -36,6 +36,7 @@ __owur long ossl_quic_ctx_callback_ctrl(SSL_CTX *ctx, int cmd, void (*fp) (void) __owur size_t ossl_quic_pending(const SSL *s); __owur int ossl_quic_key_update(SSL *s, int update_type); __owur int ossl_quic_get_key_update_type(const SSL *s); +__owur const SSL_CIPHER *ossl_quic_get_cipher_by_char(const unsigned char *p); __owur int ossl_quic_num_ciphers(void); __owur const SSL_CIPHER *ossl_quic_get_cipher(unsigned int u); int ossl_quic_renegotiate_check(SSL *ssl, int initok); diff --git a/include/internal/quic_tserver.h b/include/internal/quic_tserver.h index 9213f60666aa6ac8392fd3480d15ed3736e8b46d..4f358dd4e87c58bdef39817361c52a0fdd5ab470 100644 --- a/include/internal/quic_tserver.h +++ b/include/internal/quic_tserver.h @@ -211,6 +211,10 @@ int ossl_quic_tserver_new_ticket(QUIC_TSERVER *srv); int ossl_quic_tserver_set_max_early_data(QUIC_TSERVER *srv, uint32_t max_early_data); +/* Set the find session callback for getting a server PSK */ +void ossl_quic_tserver_set_psk_find_session_cb(QUIC_TSERVER *srv, + SSL_psk_find_session_cb_func cb); + # endif #endif diff --git a/include/openssl/core_dispatch.h b/include/openssl/core_dispatch.h index 7c48bd7f863d4a61f8a351841f93cf1f666a6f6f..73f040285cd5134172b80855a7611ab34db6a169 100644 --- a/include/openssl/core_dispatch.h +++ b/include/openssl/core_dispatch.h @@ -936,6 +936,8 @@ OSSL_CORE_MAKE_FUNC(int, decoder_export_object, #define OSSL_FUNC_STORE_EOF 6 #define OSSL_FUNC_STORE_CLOSE 7 #define OSSL_FUNC_STORE_EXPORT_OBJECT 8 +#define OSSL_FUNC_STORE_DELETE 9 +#define OSSL_FUNC_STORE_OPEN_EX 10 OSSL_CORE_MAKE_FUNC(void *, store_open, (void *provctx, const char *uri)) OSSL_CORE_MAKE_FUNC(void *, store_attach, (void *provctx, OSSL_CORE_BIO *in)) OSSL_CORE_MAKE_FUNC(const OSSL_PARAM *, store_settable_ctx_params, @@ -951,6 +953,12 @@ OSSL_CORE_MAKE_FUNC(int, store_close, (void *loaderctx)) OSSL_CORE_MAKE_FUNC(int, store_export_object, (void *loaderctx, const void *objref, size_t objref_sz, OSSL_CALLBACK *export_cb, void *export_cbarg)) +OSSL_CORE_MAKE_FUNC(int, store_delete, + (void *provctx, const char *uri, const OSSL_PARAM params[], + OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg)) +OSSL_CORE_MAKE_FUNC(void *, store_open_ex, + (void *provctx, const char *uri, const OSSL_PARAM params[], + OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg)) # ifdef __cplusplus } diff --git a/include/openssl/store.h b/include/openssl/store.h index dafb16fd90d3ec11c3d2c98aab0daa588d88b483..46fb4d40f0fd490fafe475a8383e81d46d3f2424 100644 --- a/include/openssl/store.h +++ b/include/openssl/store.h @@ -98,6 +98,14 @@ OSSL_DEPRECATEDIN_3_0 int OSSL_STORE_vctrl(OSSL_STORE_CTX *ctx, int cmd, */ OSSL_STORE_INFO *OSSL_STORE_load(OSSL_STORE_CTX *ctx); +/* + * Deletes the object in the store by URI. + * Returns 1 on success, 0 otherwise. + */ +int OSSL_STORE_delete(const char *uri, OSSL_LIB_CTX *libctx, const char *propq, + const UI_METHOD *ui_method, void *ui_data, + const OSSL_PARAM params[]); + /* * Check if end of data (end of file) is reached * Returns 1 on end, 0 otherwise. diff --git a/providers/implementations/ciphers/cipher_aes_cbc_hmac_sha.c b/providers/implementations/ciphers/cipher_aes_cbc_hmac_sha.c index f0ebfb6836732df6825180832920244f88a99556..28d3909c4d689ef58aa684b415bef686e9fa3830 100644 --- a/providers/implementations/ciphers/cipher_aes_cbc_hmac_sha.c +++ b/providers/implementations/ciphers/cipher_aes_cbc_hmac_sha.c @@ -334,6 +334,16 @@ static void *aes_cbc_hmac_sha1_newctx(void *provctx, size_t kbits, return ctx; } +static void *aes_cbc_hmac_sha1_dupctx(void *provctx) +{ + PROV_AES_HMAC_SHA1_CTX *ctx = provctx; + + if (ctx == NULL) + return NULL; + + return OPENSSL_memdup(ctx, sizeof(*ctx)); +} + static void aes_cbc_hmac_sha1_freectx(void *vctx) { PROV_AES_HMAC_SHA1_CTX *ctx = (PROV_AES_HMAC_SHA1_CTX *)vctx; @@ -361,6 +371,13 @@ static void *aes_cbc_hmac_sha256_newctx(void *provctx, size_t kbits, return ctx; } +static void *aes_cbc_hmac_sha256_dupctx(void *provctx) +{ + PROV_AES_HMAC_SHA256_CTX *ctx = provctx; + + return OPENSSL_memdup(ctx, sizeof(*ctx)); +} + static void aes_cbc_hmac_sha256_freectx(void *vctx) { PROV_AES_HMAC_SHA256_CTX *ctx = (PROV_AES_HMAC_SHA256_CTX *)vctx; @@ -386,6 +403,7 @@ static int nm##_##kbits##_##sub##_get_params(OSSL_PARAM params[]) \ const OSSL_DISPATCH ossl_##nm##kbits##sub##_functions[] = { \ { OSSL_FUNC_CIPHER_NEWCTX, (void (*)(void))nm##_##kbits##_##sub##_newctx },\ { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))nm##_##sub##_freectx }, \ + { OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void))nm##_##sub##_dupctx}, \ { OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))nm##_einit }, \ { OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))nm##_dinit }, \ { OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))nm##_update }, \ diff --git a/providers/implementations/ciphers/cipher_aes_ccm.c b/providers/implementations/ciphers/cipher_aes_ccm.c index bb4b1e1e64907a4fc204b6811bbd6cebc7a0f322..3930f52d60650e5ab4ab8adf0771c465f9094f48 100644 --- a/providers/implementations/ciphers/cipher_aes_ccm.c +++ b/providers/implementations/ciphers/cipher_aes_ccm.c @@ -33,6 +33,26 @@ static void *aes_ccm_newctx(void *provctx, size_t keybits) return ctx; } +static void *aes_ccm_dupctx(void *provctx) +{ + PROV_AES_CCM_CTX *ctx = provctx; + PROV_AES_CCM_CTX *dupctx = NULL; + + if (ctx == NULL) + return NULL; + dupctx = OPENSSL_memdup(provctx, sizeof(*ctx)); + if (dupctx == NULL) + return NULL; + /* + * ossl_cm_initctx, via the ossl_prov_aes_hw_ccm functions assign a + * provctx->ccm.ks.ks to the ccm context key so we need to point it to + * the memduped copy + */ + dupctx->base.ccm_ctx.key = &dupctx->ccm.ks.ks; + + return dupctx; +} + static OSSL_FUNC_cipher_freectx_fn aes_ccm_freectx; static void aes_ccm_freectx(void *vctx) { diff --git a/providers/implementations/ciphers/cipher_aes_gcm.c b/providers/implementations/ciphers/cipher_aes_gcm.c index 0081ca6cd776fc4f8f2a0718f8e1becc966150c9..edc3cc262ef958133f4d50b0aa9ce6e5e0544c80 100644 --- a/providers/implementations/ciphers/cipher_aes_gcm.c +++ b/providers/implementations/ciphers/cipher_aes_gcm.c @@ -34,6 +34,21 @@ static void *aes_gcm_newctx(void *provctx, size_t keybits) return ctx; } +static void *aes_gcm_dupctx(void *provctx) +{ + PROV_AES_GCM_CTX *ctx = provctx; + PROV_AES_GCM_CTX *dctx = NULL; + + if (ctx == NULL) + return NULL; + + dctx = OPENSSL_memdup(ctx, sizeof(*ctx)); + if (dctx != NULL && dctx->base.gcm.key != NULL) + dctx->base.gcm.key = &dctx->ks.ks; + + return dctx; +} + static OSSL_FUNC_cipher_freectx_fn aes_gcm_freectx; static void aes_gcm_freectx(void *vctx) { diff --git a/providers/implementations/ciphers/cipher_aes_gcm_siv.c b/providers/implementations/ciphers/cipher_aes_gcm_siv.c index 64f7f95039b66e488982a3191c7ebecbf8e5d1a9..2d4fd886583e50bea3baf26e1093be8e5026a4b6 100644 --- a/providers/implementations/ciphers/cipher_aes_gcm_siv.c +++ b/providers/implementations/ciphers/cipher_aes_gcm_siv.c @@ -71,7 +71,7 @@ static void *ossl_aes_gcm_siv_dupctx(void *vctx) ret->aad = NULL; ret->ecb_ctx = NULL; - if (in->aad == NULL) { + if (in->aad != NULL) { if ((ret->aad = OPENSSL_memdup(in->aad, UP16(ret->aad_len))) == NULL) goto err; } diff --git a/providers/implementations/ciphers/cipher_aes_wrp.c b/providers/implementations/ciphers/cipher_aes_wrp.c index ecebf213e2631d4873a11a6cdb9b6f90cc52850f..912a47e3fe88ced9dadbd6ab45182124a928e646 100644 --- a/providers/implementations/ciphers/cipher_aes_wrp.c +++ b/providers/implementations/ciphers/cipher_aes_wrp.c @@ -66,6 +66,26 @@ static void *aes_wrap_newctx(size_t kbits, size_t blkbits, return wctx; } +static void *aes_wrap_dupctx(void *wctx) +{ + PROV_AES_WRAP_CTX *ctx = wctx; + PROV_AES_WRAP_CTX *dctx = wctx; + + if (ctx == NULL) + return NULL; + dctx = OPENSSL_memdup(ctx, sizeof(*ctx)); + + if (dctx != NULL && dctx->base.tlsmac != NULL && dctx->base.alloced) { + dctx->base.tlsmac = OPENSSL_memdup(dctx->base.tlsmac, + dctx->base.tlsmacsize); + if (dctx->base.tlsmac == NULL) { + OPENSSL_free(dctx); + dctx = NULL; + } + } + return dctx; +} + static void aes_wrap_freectx(void *vctx) { PROV_AES_WRAP_CTX *wctx = (PROV_AES_WRAP_CTX *)vctx; @@ -281,6 +301,7 @@ static int aes_wrap_set_ctx_params(void *vctx, const OSSL_PARAM params[]) { OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))aes_##mode##_cipher }, \ { OSSL_FUNC_CIPHER_FINAL, (void (*)(void))aes_##mode##_final }, \ { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))aes_##mode##_freectx }, \ + { OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void))aes_##mode##_dupctx }, \ { OSSL_FUNC_CIPHER_GET_PARAMS, \ (void (*)(void))aes_##kbits##_##fname##_get_params }, \ { OSSL_FUNC_CIPHER_GETTABLE_PARAMS, \ diff --git a/providers/implementations/ciphers/cipher_aria_ccm.c b/providers/implementations/ciphers/cipher_aria_ccm.c index d6b5517ee0965f62a7123c357a3e6342c4138374..5fae5934698a2d7a43ec43a156c8386623a0a94e 100644 --- a/providers/implementations/ciphers/cipher_aria_ccm.c +++ b/providers/implementations/ciphers/cipher_aria_ccm.c @@ -28,6 +28,21 @@ static void *aria_ccm_newctx(void *provctx, size_t keybits) return ctx; } +static void *aria_ccm_dupctx(void *provctx) +{ + PROV_ARIA_CCM_CTX *ctx = provctx; + PROV_ARIA_CCM_CTX *dctx = NULL; + + if (ctx == NULL) + return NULL; + + dctx = OPENSSL_memdup(ctx, sizeof(*ctx)); + if (dctx != NULL && dctx->base.ccm_ctx.key != NULL) + dctx->base.ccm_ctx.key = &dctx->ks.ks; + + return dctx; +} + static void aria_ccm_freectx(void *vctx) { PROV_ARIA_CCM_CTX *ctx = (PROV_ARIA_CCM_CTX *)vctx; diff --git a/providers/implementations/ciphers/cipher_aria_gcm.c b/providers/implementations/ciphers/cipher_aria_gcm.c index b412bd3202f82e470372695c02ddc9775e993e37..f9eb64cc194f6f1b5a307adaca2d166bd4ce4ec2 100644 --- a/providers/implementations/ciphers/cipher_aria_gcm.c +++ b/providers/implementations/ciphers/cipher_aria_gcm.c @@ -27,6 +27,21 @@ static void *aria_gcm_newctx(void *provctx, size_t keybits) return ctx; } +static void *aria_gcm_dupctx(void *provctx) +{ + PROV_ARIA_GCM_CTX *ctx = provctx; + PROV_ARIA_GCM_CTX *dctx = NULL; + + if (ctx == NULL) + return NULL; + + dctx = OPENSSL_memdup(ctx, sizeof(*ctx)); + if (dctx != NULL && dctx->base.gcm.key != NULL) + dctx->base.gcm.key = &dctx->ks.ks; + + return dctx; +} + static OSSL_FUNC_cipher_freectx_fn aria_gcm_freectx; static void aria_gcm_freectx(void *vctx) { diff --git a/providers/implementations/ciphers/cipher_chacha20_poly1305.c b/providers/implementations/ciphers/cipher_chacha20_poly1305.c index 662b4e03e54246b3d69a6758ce7becbb8529dbac..d5d4e1a251b1c54afbe6503f4a6ff8ff24cf3de7 100644 --- a/providers/implementations/ciphers/cipher_chacha20_poly1305.c +++ b/providers/implementations/ciphers/cipher_chacha20_poly1305.c @@ -23,6 +23,7 @@ static OSSL_FUNC_cipher_newctx_fn chacha20_poly1305_newctx; static OSSL_FUNC_cipher_freectx_fn chacha20_poly1305_freectx; +static OSSL_FUNC_cipher_dupctx_fn chacha20_poly1305_dupctx; static OSSL_FUNC_cipher_encrypt_init_fn chacha20_poly1305_einit; static OSSL_FUNC_cipher_decrypt_init_fn chacha20_poly1305_dinit; static OSSL_FUNC_cipher_get_params_fn chacha20_poly1305_get_params; @@ -58,6 +59,25 @@ static void *chacha20_poly1305_newctx(void *provctx) return ctx; } +static void *chacha20_poly1305_dupctx(void *provctx) +{ + PROV_CHACHA20_POLY1305_CTX *ctx = provctx; + PROV_CHACHA20_POLY1305_CTX *dctx = NULL; + + if (ctx == NULL) + return NULL; + dctx = OPENSSL_memdup(ctx, sizeof(*ctx)); + if (dctx != NULL && dctx->base.tlsmac != NULL && dctx->base.alloced) { + dctx->base.tlsmac = OPENSSL_memdup(dctx->base.tlsmac, + dctx->base.tlsmacsize); + if (dctx->base.tlsmac == NULL) { + OPENSSL_free(dctx); + dctx = NULL; + } + } + return dctx; +} + static void chacha20_poly1305_freectx(void *vctx) { PROV_CHACHA20_POLY1305_CTX *ctx = (PROV_CHACHA20_POLY1305_CTX *)vctx; @@ -310,6 +330,7 @@ static int chacha20_poly1305_final(void *vctx, unsigned char *out, size_t *outl, const OSSL_DISPATCH ossl_chacha20_ossl_poly1305_functions[] = { { OSSL_FUNC_CIPHER_NEWCTX, (void (*)(void))chacha20_poly1305_newctx }, { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))chacha20_poly1305_freectx }, + { OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void))chacha20_poly1305_dupctx }, { OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))chacha20_poly1305_einit }, { OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))chacha20_poly1305_dinit }, { OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))chacha20_poly1305_update }, diff --git a/providers/implementations/ciphers/cipher_rc4_hmac_md5.c b/providers/implementations/ciphers/cipher_rc4_hmac_md5.c index 99d5dd716926f071b2aeb19ddd418779300312c2..82ef7890b54d6706513cd3571839e2c223df1f39 100644 --- a/providers/implementations/ciphers/cipher_rc4_hmac_md5.c +++ b/providers/implementations/ciphers/cipher_rc4_hmac_md5.c @@ -34,6 +34,7 @@ static OSSL_FUNC_cipher_encrypt_init_fn rc4_hmac_md5_einit; static OSSL_FUNC_cipher_decrypt_init_fn rc4_hmac_md5_dinit; static OSSL_FUNC_cipher_newctx_fn rc4_hmac_md5_newctx; static OSSL_FUNC_cipher_freectx_fn rc4_hmac_md5_freectx; +static OSSL_FUNC_cipher_dupctx_fn rc4_hmac_md5_dupctx; static OSSL_FUNC_cipher_get_ctx_params_fn rc4_hmac_md5_get_ctx_params; static OSSL_FUNC_cipher_gettable_ctx_params_fn rc4_hmac_md5_gettable_ctx_params; static OSSL_FUNC_cipher_set_ctx_params_fn rc4_hmac_md5_set_ctx_params; @@ -71,6 +72,15 @@ static void rc4_hmac_md5_freectx(void *vctx) OPENSSL_clear_free(ctx, sizeof(*ctx)); } +static void *rc4_hmac_md5_dupctx(void *vctx) +{ + PROV_RC4_HMAC_MD5_CTX *ctx = vctx; + + if (ctx == NULL) + return NULL; + return OPENSSL_memdup(ctx, sizeof(*ctx)); +} + static int rc4_hmac_md5_einit(void *ctx, const unsigned char *key, size_t keylen, const unsigned char *iv, size_t ivlen, const OSSL_PARAM params[]) @@ -214,6 +224,7 @@ static int rc4_hmac_md5_get_params(OSSL_PARAM params[]) const OSSL_DISPATCH ossl_rc4_hmac_ossl_md5_functions[] = { { OSSL_FUNC_CIPHER_NEWCTX, (void (*)(void))rc4_hmac_md5_newctx }, { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))rc4_hmac_md5_freectx }, + { OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void))rc4_hmac_md5_dupctx }, { OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))rc4_hmac_md5_einit }, { OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))rc4_hmac_md5_dinit }, { OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))rc4_hmac_md5_update }, diff --git a/providers/implementations/ciphers/cipher_sm4_ccm.c b/providers/implementations/ciphers/cipher_sm4_ccm.c index f0295a5ca28ad8bde3bf589c648cdb179e1a4e15..47fc6e103cce00b84281e37eb2c8e2acee6dd07a 100644 --- a/providers/implementations/ciphers/cipher_sm4_ccm.c +++ b/providers/implementations/ciphers/cipher_sm4_ccm.c @@ -28,6 +28,21 @@ static void *sm4_ccm_newctx(void *provctx, size_t keybits) return ctx; } +static void *sm4_ccm_dupctx(void *provctx) +{ + PROV_SM4_CCM_CTX *ctx = provctx; + PROV_SM4_CCM_CTX *dctx = NULL; + + if (ctx == NULL) + return NULL; + + dctx = OPENSSL_memdup(ctx, sizeof(*ctx)); + if (dctx != NULL && dctx->base.ccm_ctx.key != NULL) + dctx->base.ccm_ctx.key = &dctx->ks.ks; + + return dctx; +} + static void sm4_ccm_freectx(void *vctx) { PROV_SM4_CCM_CTX *ctx = (PROV_SM4_CCM_CTX *)vctx; diff --git a/providers/implementations/ciphers/cipher_sm4_gcm.c b/providers/implementations/ciphers/cipher_sm4_gcm.c index 7a936f00ee55aedfaeef27c22730c26a701821b5..e8fcf5787e48986e9850e575b6c176a0ec7b7de7 100644 --- a/providers/implementations/ciphers/cipher_sm4_gcm.c +++ b/providers/implementations/ciphers/cipher_sm4_gcm.c @@ -29,6 +29,21 @@ static void *sm4_gcm_newctx(void *provctx, size_t keybits) return ctx; } +static void *sm4_gcm_dupctx(void *provctx) +{ + PROV_SM4_GCM_CTX *ctx = provctx; + PROV_SM4_GCM_CTX *dctx = NULL; + + if (ctx == NULL) + return NULL; + + dctx = OPENSSL_memdup(ctx, sizeof(*ctx)); + if (dctx != NULL && dctx->base.gcm.key != NULL) + dctx->base.gcm.key = &dctx->ks.ks; + + return dctx; +} + static void sm4_gcm_freectx(void *vctx) { PROV_SM4_GCM_CTX *ctx = (PROV_SM4_GCM_CTX *)vctx; diff --git a/providers/implementations/digests/blake2_prov.c b/providers/implementations/digests/blake2_prov.c index 2288286bbe44ecfcbcb837c0c7a2abf172cddd19..298bc66de65a5b3179e80a308c6705896dd09671 100644 --- a/providers/implementations/digests/blake2_prov.c +++ b/providers/implementations/digests/blake2_prov.c @@ -12,7 +12,7 @@ #include "prov/digestcommon.h" #include "prov/implementations.h" -int ossl_blake2s256_init(void *ctx) +static int ossl_blake2s256_init(void *ctx) { BLAKE2S_PARAM P; @@ -20,7 +20,7 @@ int ossl_blake2s256_init(void *ctx) return ossl_blake2s_init((BLAKE2S_CTX *)ctx, &P); } -int ossl_blake2b512_init(void *ctx) +static int ossl_blake2b512_init(void *ctx) { struct blake2b_md_data_st *mdctx = ctx; diff --git a/providers/implementations/digests/sha3_prov.c b/providers/implementations/digests/sha3_prov.c index 0c643f82382842bd1e30a622351d6af1eff05890..423bed7983e05d671018463e715951d86dd92db5 100644 --- a/providers/implementations/digests/sha3_prov.c +++ b/providers/implementations/digests/sha3_prov.c @@ -249,7 +249,7 @@ static PROV_SHA3_METHOD kmac_s390x_md = } else { \ ctx->meth = sha3_generic_md; \ } -#elif defined(__aarch64__) +#elif defined(__aarch64__) && defined(KECCAK1600_ASM) # include "arm_arch.h" static sha3_absorb_fn armsha3_sha3_absorb; diff --git a/providers/implementations/encode_decode/encode_key2any.c b/providers/implementations/encode_decode/encode_key2any.c index c1b0dea7803e4204f601d4897aca998028970a94..ae6d7d0a681d306d3e5579ff548e49018bbe4380 100644 --- a/providers/implementations/encode_decode/encode_key2any.c +++ b/providers/implementations/encode_decode/encode_key2any.c @@ -856,14 +856,17 @@ static int prepare_rsa_params(const void *rsa, int nid, int save, case 1: if ((str = OPENSSL_malloc(str_sz)) == NULL || !WPACKET_init_der(&pkt, str, str_sz)) { + WPACKET_cleanup(&pkt); goto err; } break; } if (!ossl_DER_w_RSASSA_PSS_params(&pkt, -1, pss) || !WPACKET_finish(&pkt) - || !WPACKET_get_total_written(&pkt, &str_sz)) + || !WPACKET_get_total_written(&pkt, &str_sz)) { + WPACKET_cleanup(&pkt); goto err; + } WPACKET_cleanup(&pkt); /* diff --git a/providers/implementations/include/prov/blake2.h b/providers/implementations/include/prov/blake2.h index 4ec780c21f50b8cba6e2eeb34d52480b6fcea864..bcd0bb9bcd4a4fca00de471cebbb19f27aa4cec9 100644 --- a/providers/implementations/include/prov/blake2.h +++ b/providers/implementations/include/prov/blake2.h @@ -88,9 +88,6 @@ struct blake2b_md_data_st { BLAKE2B_PARAM params; }; -int ossl_blake2s256_init(void *ctx); -int ossl_blake2b512_init(void *ctx); - int ossl_blake2b_init(BLAKE2B_CTX *c, const BLAKE2B_PARAM *P); int ossl_blake2b_init_key(BLAKE2B_CTX *c, const BLAKE2B_PARAM *P, const void *key); diff --git a/providers/implementations/include/prov/ciphercommon_aead.h b/providers/implementations/include/prov/ciphercommon_aead.h index 0dd63cbe5343d4a11700dae988a64dc127efedfd..8d709f10ea64e37376ca6365646ca0d3b504931e 100644 --- a/providers/implementations/include/prov/ciphercommon_aead.h +++ b/providers/implementations/include/prov/ciphercommon_aead.h @@ -27,9 +27,14 @@ static void * alg##kbits##lc##_newctx(void *provctx) \ { \ return alg##_##lc##_newctx(provctx, kbits); \ } \ +static void * alg##kbits##lc##_dupctx(void *src) \ +{ \ + return alg##_##lc##_dupctx(src); \ +} \ const OSSL_DISPATCH ossl_##alg##kbits##lc##_functions[] = { \ { OSSL_FUNC_CIPHER_NEWCTX, (void (*)(void))alg##kbits##lc##_newctx }, \ { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))alg##_##lc##_freectx }, \ + { OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void))alg##kbits##lc##_dupctx }, \ { OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))ossl_##lc##_einit }, \ { OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))ossl_##lc##_dinit }, \ { OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))ossl_##lc##_stream_update }, \ diff --git a/providers/implementations/kdfs/argon2.c b/providers/implementations/kdfs/argon2.c index 323b0f3ab6b87c018b2696e940c1a9521bc01c9b..d93381c410440cdee906d8a41d1b8fdcdb2b38a4 100644 --- a/providers/implementations/kdfs/argon2.c +++ b/providers/implementations/kdfs/argon2.c @@ -1185,8 +1185,7 @@ static int kdf_argon2_ctx_set_lanes(KDF_ARGON2 *ctx, uint32_t lanes) static int kdf_argon2_ctx_set_t_cost(KDF_ARGON2 *ctx, uint32_t t_cost) { - /* ARGON2_MAX_MEMORY == max m_cost value, skip check, enforce type */ - ossl_static_assert_type_eq(uint32_t, t_cost); + /* ARGON2_MAX_MEMORY == max m_cost value, so skip check */ if (t_cost < ARGON2_MIN_TIME) { ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_ITERATION_COUNT, @@ -1200,8 +1199,7 @@ static int kdf_argon2_ctx_set_t_cost(KDF_ARGON2 *ctx, uint32_t t_cost) static int kdf_argon2_ctx_set_m_cost(KDF_ARGON2 *ctx, uint32_t m_cost) { - /* ARGON2_MAX_MEMORY == max m_cost value, skip check, enforce type */ - ossl_static_assert_type_eq(uint32_t, m_cost); + /* ARGON2_MAX_MEMORY == max m_cost value, so skip check */ if (m_cost < ARGON2_MIN_MEMORY) { ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_MEMORY_SIZE, "min: %u", @@ -1218,11 +1216,8 @@ static int kdf_argon2_ctx_set_out_length(KDF_ARGON2 *ctx, uint32_t outlen) /* * ARGON2_MAX_OUT_LENGTH == max outlen value, so upper bounds checks * are always satisfied; to suppress compiler if statement tautology - * warnings, these checks are skipped; however, to ensure that these - * limits are met and implementation conforming to Argon2 RFC, we need - * to fix the type + * warnings, these checks are skipped. */ - ossl_static_assert_type_eq(uint32_t, outlen); if (outlen < ARGON2_MIN_OUT_LENGTH) { ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_OUTPUT_LENGTH, "min: %u", diff --git a/providers/implementations/rands/drbg_ctr.c b/providers/implementations/rands/drbg_ctr.c index 2dc51d03c16533bed2f9bf1b9d66a1b517c046c4..cc4ed25cfd722c26c15f96d65cc98ef6c20ea69c 100644 --- a/providers/implementations/rands/drbg_ctr.c +++ b/providers/implementations/rands/drbg_ctr.c @@ -507,10 +507,10 @@ static int drbg_ctr_verify_zeroization(void *vdrbg) if (drbg->lock != NULL && !CRYPTO_THREAD_read_lock(drbg->lock)) return 0; - PROV_DRBG_VERYIFY_ZEROIZATION(ctr->K); - PROV_DRBG_VERYIFY_ZEROIZATION(ctr->V); - PROV_DRBG_VERYIFY_ZEROIZATION(ctr->bltmp); - PROV_DRBG_VERYIFY_ZEROIZATION(ctr->KX); + PROV_DRBG_VERIFY_ZEROIZATION(ctr->K); + PROV_DRBG_VERIFY_ZEROIZATION(ctr->V); + PROV_DRBG_VERIFY_ZEROIZATION(ctr->bltmp); + PROV_DRBG_VERIFY_ZEROIZATION(ctr->KX); if (ctr->bltmp_pos != 0) goto err; diff --git a/providers/implementations/rands/drbg_hash.c b/providers/implementations/rands/drbg_hash.c index 246aab58c96c07658cb7aebcccef0e435fed298d..a216910d831a9164dc9f9519c7654e14db13a1a6 100644 --- a/providers/implementations/rands/drbg_hash.c +++ b/providers/implementations/rands/drbg_hash.c @@ -405,9 +405,9 @@ static int drbg_hash_verify_zeroization(void *vdrbg) if (drbg->lock != NULL && !CRYPTO_THREAD_read_lock(drbg->lock)) return 0; - PROV_DRBG_VERYIFY_ZEROIZATION(hash->V); - PROV_DRBG_VERYIFY_ZEROIZATION(hash->C); - PROV_DRBG_VERYIFY_ZEROIZATION(hash->vtmp); + PROV_DRBG_VERIFY_ZEROIZATION(hash->V); + PROV_DRBG_VERIFY_ZEROIZATION(hash->C); + PROV_DRBG_VERIFY_ZEROIZATION(hash->vtmp); ret = 1; err: diff --git a/providers/implementations/rands/drbg_hmac.c b/providers/implementations/rands/drbg_hmac.c index ca190a740e4ca57e36f2ac8c2b44591fee8b1038..74d47886b4444a5089952d8a6be352c9bad0a137 100644 --- a/providers/implementations/rands/drbg_hmac.c +++ b/providers/implementations/rands/drbg_hmac.c @@ -298,8 +298,8 @@ static int drbg_hmac_verify_zeroization(void *vdrbg) if (drbg->lock != NULL && !CRYPTO_THREAD_read_lock(drbg->lock)) return 0; - PROV_DRBG_VERYIFY_ZEROIZATION(hmac->K); - PROV_DRBG_VERYIFY_ZEROIZATION(hmac->V); + PROV_DRBG_VERIFY_ZEROIZATION(hmac->K); + PROV_DRBG_VERIFY_ZEROIZATION(hmac->V); ret = 1; err: diff --git a/providers/implementations/rands/drbg_local.h b/providers/implementations/rands/drbg_local.h index dd46593a5f0967dd00b857227031c2195a9d9a47..50f98a0b61ca3368c0309afd42c78827724f26a3 100644 --- a/providers/implementations/rands/drbg_local.h +++ b/providers/implementations/rands/drbg_local.h @@ -206,7 +206,7 @@ OSSL_FUNC_rand_get_seed_fn ossl_drbg_get_seed; OSSL_FUNC_rand_clear_seed_fn ossl_drbg_clear_seed; /* Verify that an array of numeric values is all zero */ -#define PROV_DRBG_VERYIFY_ZEROIZATION(v) \ +#define PROV_DRBG_VERIFY_ZEROIZATION(v) \ { \ size_t i; \ \ diff --git a/ssl/quic/quic_channel.c b/ssl/quic/quic_channel.c index ce938b70f06a647359032efee913ffa32eb4c632..3da0caa4ea63b9cdf4cb3fa4c239b65569e2cdbc 100644 --- a/ssl/quic/quic_channel.c +++ b/ssl/quic/quic_channel.c @@ -44,6 +44,7 @@ */ #define DEFAULT_MAX_ACK_DELAY QUIC_DEFAULT_MAX_ACK_DELAY +static void ch_save_err_state(QUIC_CHANNEL *ch); static void ch_rx_pre(QUIC_CHANNEL *ch); static int ch_rx(QUIC_CHANNEL *ch); static int ch_tx(QUIC_CHANNEL *ch); @@ -1269,6 +1270,8 @@ static int ch_on_transport_params(const unsigned char *params, int got_initial_max_stream_data_uni = 0; int got_initial_max_streams_bidi = 0; int got_initial_max_streams_uni = 0; + int got_stateless_reset_token = 0; + int got_preferred_addr = 0; int got_ack_delay_exp = 0; int got_max_ack_delay = 0; int got_max_udp_payload_size = 0; @@ -1573,6 +1576,11 @@ static int ch_on_transport_params(const unsigned char *params, break; case QUIC_TPARAM_STATELESS_RESET_TOKEN: + if (got_stateless_reset_token) { + reason = TP_REASON_DUP("STATELESS_RESET_TOKEN"); + goto malformed; + } + /* * We must ensure a client doesn't send them because we don't have * processing for them. @@ -1594,12 +1602,17 @@ static int ch_on_transport_params(const unsigned char *params, goto malformed; } + got_stateless_reset_token = 1; break; case QUIC_TPARAM_PREFERRED_ADDR: { /* TODO(QUIC FUTURE): Handle preferred address. */ QUIC_PREFERRED_ADDR pfa; + if (got_preferred_addr) { + reason = TP_REASON_DUP("PREFERRED_ADDR"); + goto malformed; + } /* * RFC 9000 s. 18.2: "A server that chooses a zero-length @@ -1628,6 +1641,8 @@ static int ch_on_transport_params(const unsigned char *params, reason = "zero-length CID in PREFERRED_ADDR"; goto malformed; } + + got_preferred_addr = 1; } break; @@ -2702,6 +2717,10 @@ int ossl_quic_channel_set_net_wbio(QUIC_CHANNEL *ch, BIO *net_wbio) */ int ossl_quic_channel_start(QUIC_CHANNEL *ch) { + uint64_t error_code; + const char *error_msg; + ERR_STATE *error_state = NULL; + if (ch->is_server) /* * This is not used by the server. The server moves to active @@ -2730,8 +2749,14 @@ int ossl_quic_channel_start(QUIC_CHANNEL *ch) ch->doing_proactive_ver_neg = 0; /* not currently supported */ /* Handshake layer: start (e.g. send CH). */ - if (!ossl_quic_tls_tick(ch->qtls)) + ossl_quic_tls_tick(ch->qtls); + + if (ossl_quic_tls_get_error(ch->qtls, &error_code, &error_msg, + &error_state)) { + ossl_quic_channel_raise_protocol_error_state(ch, error_code, 0, + error_msg, error_state); return 0; + } ossl_quic_reactor_tick(&ch->rtor, 0); /* best effort */ return 1; diff --git a/ssl/quic/quic_impl.c b/ssl/quic/quic_impl.c index ca4ef0ebbbbda5c91475f56deff82380ee9ee306..cb927fa52d131263af5ec8d9dedb7a4985b9321f 100644 --- a/ssl/quic/quic_impl.c +++ b/ssl/quic/quic_impl.c @@ -545,8 +545,8 @@ void ossl_quic_free(SSL *s) ossl_quic_channel_free(ctx.qc->ch); - BIO_free(ctx.qc->net_rbio); - BIO_free(ctx.qc->net_wbio); + BIO_free_all(ctx.qc->net_rbio); + BIO_free_all(ctx.qc->net_wbio); /* Note: SSL_free calls OPENSSL_free(qc) for us */ @@ -876,7 +876,7 @@ void ossl_quic_conn_set0_net_rbio(SSL *s, BIO *net_rbio) if (!ossl_quic_channel_set_net_rbio(ctx.qc->ch, net_rbio)) return; - BIO_free(ctx.qc->net_rbio); + BIO_free_all(ctx.qc->net_rbio); ctx.qc->net_rbio = net_rbio; if (net_rbio != NULL) @@ -903,7 +903,7 @@ void ossl_quic_conn_set0_net_wbio(SSL *s, BIO *net_wbio) if (!ossl_quic_channel_set_net_wbio(ctx.qc->ch, net_wbio)) return; - BIO_free(ctx.qc->net_wbio); + BIO_free_all(ctx.qc->net_wbio); ctx.qc->net_wbio = net_wbio; if (net_wbio != NULL) @@ -1524,6 +1524,7 @@ static int ensure_channel_started(QCTX *ctx) } if (!ossl_quic_channel_start(qc->ch)) { + ossl_quic_channel_restore_err_state(qc->ch); QUIC_RAISE_NON_NORMAL_ERROR(ctx, ERR_R_INTERNAL_ERROR, "failed to start channel"); return 0; @@ -3535,6 +3536,16 @@ int ossl_quic_renegotiate_check(SSL *ssl, int initok) return 0; } +const SSL_CIPHER *ossl_quic_get_cipher_by_char(const unsigned char *p) +{ + const SSL_CIPHER *ciph = ssl3_get_cipher_by_char(p); + + if ((ciph->algorithm2 & SSL_QUIC) == 0) + return NULL; + + return ciph; +} + /* * These functions define the TLSv1.2 (and below) ciphers that are supported by * the SSL_METHOD. Since QUIC only supports TLSv1.3 we don't support any. diff --git a/ssl/quic/quic_local.h b/ssl/quic/quic_local.h index 517904d90f7750b6d0610db2dc7688ca4dd65013..928ae4c6bf3f90c2889c9ed41a438f9aafefb738 100644 --- a/ssl/quic/quic_local.h +++ b/ssl/quic/quic_local.h @@ -69,7 +69,7 @@ struct quic_xso_st { * b2 must equal b1 (validated unless ACCEPT_MOVING_WRITE_BUFFER) * l2 must equal l1 (always validated) * append into sstream from [b2 + aon_buf_pos, b2 + aon_buf_len) - * if done, aon_write_in_progess=0 + * if done, aon_write_in_progress=0 * */ /* Is an AON write in progress? */ @@ -321,7 +321,7 @@ const SSL_METHOD *func_name(void) \ NULL /* dispatch_alert */, \ ossl_quic_ctrl, \ ossl_quic_ctx_ctrl, \ - NULL /* get_cipher_by_char */, \ + ossl_quic_get_cipher_by_char, \ NULL /* put_cipher_by_char */, \ ossl_quic_pending, \ ossl_quic_num_ciphers, \ diff --git a/ssl/quic/quic_tserver.c b/ssl/quic/quic_tserver.c index 788d4780d8e38c037f1db96638104ea3bf76f238..3630577e707b918affe75a4c9a3a2edbd998808c 100644 --- a/ssl/quic/quic_tserver.c +++ b/ssl/quic/quic_tserver.c @@ -99,10 +99,12 @@ QUIC_TSERVER *ossl_quic_tserver_new(const QUIC_TSERVER_ARGS *args, if (srv->ctx == NULL) goto err; - if (SSL_CTX_use_certificate_file(srv->ctx, certfile, SSL_FILETYPE_PEM) <= 0) + if (certfile != NULL + && SSL_CTX_use_certificate_file(srv->ctx, certfile, SSL_FILETYPE_PEM) <= 0) goto err; - if (SSL_CTX_use_PrivateKey_file(srv->ctx, keyfile, SSL_FILETYPE_PEM) <= 0) + if (keyfile != NULL + && SSL_CTX_use_PrivateKey_file(srv->ctx, keyfile, SSL_FILETYPE_PEM) <= 0) goto err; SSL_CTX_set_alpn_select_cb(srv->ctx, alpn_select_cb, srv); @@ -157,8 +159,8 @@ void ossl_quic_tserver_free(QUIC_TSERVER *srv) return; ossl_quic_channel_free(srv->ch); - BIO_free(srv->args.net_rbio); - BIO_free(srv->args.net_wbio); + BIO_free_all(srv->args.net_rbio); + BIO_free_all(srv->args.net_wbio); OPENSSL_free(srv->ssl); SSL_free(srv->tls); SSL_CTX_free(srv->ctx); @@ -556,3 +558,9 @@ int ossl_quic_tserver_set_max_early_data(QUIC_TSERVER *srv, { return SSL_set_max_early_data(srv->tls, max_early_data); } + +void ossl_quic_tserver_set_psk_find_session_cb(QUIC_TSERVER *srv, + SSL_psk_find_session_cb_func cb) +{ + SSL_set_psk_find_session_callback(srv->tls, cb); +} diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c index 29af55bc61e8fa06dc50bdbbb4a57940f384e5ec..1f778c342347310b9672133716b02b5b85c3c110 100644 --- a/ssl/s3_lib.c +++ b/ssl/s3_lib.c @@ -47,7 +47,7 @@ static SSL_CIPHER tls13_ciphers[] = { TLS1_3_VERSION, TLS1_3_VERSION, 0, 0, SSL_HIGH, - SSL_HANDSHAKE_MAC_SHA256, + SSL_HANDSHAKE_MAC_SHA256 | SSL_QUIC, 128, 128, }, { @@ -62,7 +62,7 @@ static SSL_CIPHER tls13_ciphers[] = { TLS1_3_VERSION, TLS1_3_VERSION, 0, 0, SSL_HIGH, - SSL_HANDSHAKE_MAC_SHA384, + SSL_HANDSHAKE_MAC_SHA384 | SSL_QUIC, 256, 256, }, @@ -78,7 +78,7 @@ static SSL_CIPHER tls13_ciphers[] = { TLS1_3_VERSION, TLS1_3_VERSION, 0, 0, SSL_HIGH, - SSL_HANDSHAKE_MAC_SHA256, + SSL_HANDSHAKE_MAC_SHA256 | SSL_QUIC, 256, 256, }, diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c index b7fa9d78f70a92437ab3cf29e1db30c54e76d802..f15fe126a22f54b2d85e186592a1450757a2ce40 100644 --- a/ssl/ssl_lib.c +++ b/ssl/ssl_lib.c @@ -3397,14 +3397,14 @@ char *SSL_get_shared_ciphers(const SSL *s, char *buf, int size) if (sk_SSL_CIPHER_find(srvrsk, c) < 0) continue; - n = strlen(c->name); - if (n + 1 > size) { + n = OPENSSL_strnlen(c->name, size); + if (n >= size) { if (p != buf) --p; *p = '\0'; return buf; } - strcpy(p, c->name); + memcpy(p, c->name, n); p += n; *(p++) = ':'; size -= n + 1; @@ -7318,37 +7318,43 @@ int SSL_get_event_timeout(SSL *s, struct timeval *tv, int *is_infinite) int SSL_get_rpoll_descriptor(SSL *s, BIO_POLL_DESCRIPTOR *desc) { -#ifndef OPENSSL_NO_QUIC - if (!IS_QUIC(s)) - return -1; + SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL(s); - return ossl_quic_get_rpoll_descriptor(s, desc); -#else - return -1; +#ifndef OPENSSL_NO_QUIC + if (IS_QUIC(s)) + return ossl_quic_get_rpoll_descriptor(s, desc); #endif + + if (sc == NULL || sc->rbio == NULL) + return 0; + + return BIO_get_rpoll_descriptor(sc->rbio, desc); } int SSL_get_wpoll_descriptor(SSL *s, BIO_POLL_DESCRIPTOR *desc) { -#ifndef OPENSSL_NO_QUIC - if (!IS_QUIC(s)) - return -1; + SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL(s); - return ossl_quic_get_wpoll_descriptor(s, desc); -#else - return -1; +#ifndef OPENSSL_NO_QUIC + if (IS_QUIC(s)) + return ossl_quic_get_wpoll_descriptor(s, desc); #endif + + if (sc == NULL || sc->wbio == NULL) + return 0; + + return BIO_get_wpoll_descriptor(sc->wbio, desc); } int SSL_net_read_desired(SSL *s) { #ifndef OPENSSL_NO_QUIC if (!IS_QUIC(s)) - return 0; + return SSL_want_read(s); return ossl_quic_get_net_read_desired(s); #else - return 0; + return SSL_want_read(s); #endif } @@ -7356,11 +7362,11 @@ int SSL_net_write_desired(SSL *s) { #ifndef OPENSSL_NO_QUIC if (!IS_QUIC(s)) - return 0; + return SSL_want_write(s); return ossl_quic_get_net_write_desired(s); #else - return 0; + return SSL_want_write(s); #endif } diff --git a/ssl/ssl_local.h b/ssl/ssl_local.h index 29715781ee90ee6feff1b978b1572d742ceef3d7..d1ef358932e00dae7785fad0035e8a7f8597818c 100644 --- a/ssl/ssl_local.h +++ b/ssl/ssl_local.h @@ -236,6 +236,9 @@ */ # define TLS1_TLSTREE 0x20000 +/* Ciphersuite supported in QUIC */ +# define SSL_QUIC 0x00040000U + # define SSL_STRONG_MASK 0x0000001FU # define SSL_DEFAULT_MASK 0X00000020U diff --git a/ssl/statem/statem_clnt.c b/ssl/statem/statem_clnt.c index 92c00ce4ae5aa95dc04b844244975778821c537d..cbf5a57bebf47c31fb82c5b9edbd29388e0b4b3c 100644 --- a/ssl/statem/statem_clnt.c +++ b/ssl/statem/statem_clnt.c @@ -1793,7 +1793,7 @@ MSG_PROCESS_RETURN tls_process_server_hello(SSL_CONNECTION *s, PACKET *pkt) * If we're not doing early-data and we're not going to send a dummy CCS * (i.e. no middlebox compat mode) then we can change the write keys * immediately. Otherwise we have to defer this until after all possible - * early data is written. We could just alway defer until the last + * early data is written. We could just always defer until the last * moment except QUIC needs it done at the same time as the read keys * are changed. Since QUIC doesn't do TLS early data or need middlebox * compat this doesn't cause a problem. diff --git a/test/README.md b/test/README.md index 9a5c91953ddb78e78648749fde98e52daf45a2c9..fe25bd8b4ecbf13c874114a94d6ff20386f17edb 100644 --- a/test/README.md +++ b/test/README.md @@ -149,17 +149,33 @@ To run up to four tests in parallel at any given time: $ make HARNESS_JOBS=4 test +Random numbers in tests +----------------------- + +Some tests use random numbers as part of the test. In some cases a test failure +may occur for some random numbers, but not for others. The seed used for the +rand number generator can be set via the `OPENSSL_TEST_RAND_SEED` environment +variable. It can also be set via the `OPENSSL_TEST_RAND_ORDER` environment +variable which additionally randomises the order tests are run in (see below). + +When a test fails the test harness will display the seed used during the test +(displaying either the `OPENSSL_TEST_RAND_SEED` or `OPENSSL_TEST_RAND_ORDER` +environment variable value that must be used to recreate the results), e.g. + + $ make OPENSSL_TEST_RAND_SEED=42 test + Randomisation of Test Ordering ------------------------------ By default, the test harness will execute tests in the order they were added. By setting the `OPENSSL_TEST_RAND_ORDER` environment variable to zero, the -test ordering will be randomised. If a randomly ordered test fails, the -seed value used will be reported. Setting the `OPENSSL_TEST_RAND_ORDER` -environment variable to this value will rerun the tests in the same -order. This assures repeatability of randomly ordered test runs. -This repeatability is independent of the operating system, processor or -platform used. +test ordering will be randomised. This additionally seeds the random number +generator used within the tests as described in the section above. If a randomly +ordered test fails, the seed value used will be reported. Setting the +`OPENSSL_TEST_RAND_ORDER` environment variable to this value will rerun the +tests in the same order and will also seed the test random number generator. +This assures repeatability of randomly ordered test runs. This repeatability is +independent of the operating system, processor or platform used. To randomise the test ordering: diff --git a/test/bio_dgram_test.c b/test/bio_dgram_test.c index f6c3e30c149255232bbb3dcf61b8f1e860891bb5..aca016ca95b07f50ba63b2f5b8999f18eb568c44 100644 --- a/test/bio_dgram_test.c +++ b/test/bio_dgram_test.c @@ -12,6 +12,7 @@ #include #include "testutil.h" #include "internal/sockets.h" +#include "internal/bio_addr.h" #if !defined(OPENSSL_NO_DGRAM) && !defined(OPENSSL_NO_SOCK) @@ -519,14 +520,24 @@ static int test_bio_dgram_pair(int idx) } else { if (!TEST_ptr(bio1 = bio2 = BIO_new(BIO_s_dgram_mem()))) goto err; - if (idx == 1 && !TEST_true(BIO_set_write_buf_size(bio1, 20 * 1024))) - goto err; } mtu1 = BIO_dgram_get_mtu(bio1); if (!TEST_int_ge(mtu1, 1280)) goto err; + if (idx == 1) { + size_t bufsz; + + /* + * Assume the header contains 2 BIO_ADDR structures and a length. We + * set a buffer big enough for 9 full sized datagrams. + */ + bufsz = 9 * (mtu1 + (sizeof(BIO_ADDR) * 2) + sizeof(size_t)); + if (!TEST_true(BIO_set_write_buf_size(bio1, bufsz))) + goto err; + } + mtu2 = BIO_dgram_get_mtu(bio2); if (!TEST_int_ge(mtu2, 1280)) goto err; @@ -559,8 +570,11 @@ static int test_bio_dgram_pair(int idx) goto err; /* - * Should be able to fit at least 9 datagrams in default write buffer size - * in worst case + * The number of datagrams we can fit depends on the size of the default + * write buffer size, the size of the datagram header and the size of the + * payload data we send in each datagram. The max payload data is based on + * the mtu. The default write buffer size is 9 * (sizeof(header) + mtu) so + * we expect at least 9 maximally sized datagrams to fit in the buffer. */ if (!TEST_int_ge(i, 9)) goto err; diff --git a/test/build.info b/test/build.info index d897f726a86fef67b46264a59c109fb793e901b2..4c81a2b77984c708217a39f3de11ff809a041f6d 100644 --- a/test/build.info +++ b/test/build.info @@ -339,7 +339,9 @@ IF[{- !$disabled{tests} -}] INCLUDE[quic_client_test]=../include ../apps/include DEPEND[quic_client_test]=../libcrypto.a ../libssl.a libtestutil.a - SOURCE[quic_multistream_test]=quic_multistream_test.c helpers/ssltestlib.c helpers/quictestlib.c + $QUICTESTHELPERS=helpers/quictestlib.c helpers/noisydgrambio.c helpers/pktsplitbio.c + + SOURCE[quic_multistream_test]=quic_multistream_test.c helpers/ssltestlib.c $QUICTESTHELPERS INCLUDE[quic_multistream_test]=../include ../apps/include DEPEND[quic_multistream_test]=../libcrypto.a ../libssl.a libtestutil.a @@ -818,15 +820,15 @@ IF[{- !$disabled{tests} -}] INCLUDE[event_queue_test]=../include ../apps/include DEPEND[event_queue_test]=../libcrypto ../libssl.a libtestutil.a - SOURCE[quicfaultstest]=quicfaultstest.c helpers/ssltestlib.c helpers/quictestlib.c + SOURCE[quicfaultstest]=quicfaultstest.c helpers/ssltestlib.c $QUICTESTHELPERS INCLUDE[quicfaultstest]=../include ../apps/include .. DEPEND[quicfaultstest]=../libcrypto.a ../libssl.a libtestutil.a - SOURCE[quicapitest]=quicapitest.c helpers/ssltestlib.c helpers/quictestlib.c + SOURCE[quicapitest]=quicapitest.c helpers/ssltestlib.c $QUICTESTHELPERS INCLUDE[quicapitest]=../include ../apps/include DEPEND[quicapitest]=../libcrypto.a ../libssl.a libtestutil.a - SOURCE[quic_newcid_test]=quic_newcid_test.c helpers/ssltestlib.c helpers/quictestlib.c + SOURCE[quic_newcid_test]=quic_newcid_test.c helpers/ssltestlib.c $QUICTESTHELPERS INCLUDE[quic_newcid_test]=../include ../apps/include .. DEPEND[quic_newcid_test]=../libcrypto.a ../libssl.a libtestutil.a ENDIF diff --git a/test/evp_test.c b/test/evp_test.c index ea1ca65bcde1e857a4fcdb124880fc75c02919fb..309ab94c21b540ae63c85e5c642ffeffc92d09b8 100644 --- a/test/evp_test.c +++ b/test/evp_test.c @@ -73,10 +73,13 @@ typedef enum OPTION_choice { OPT_EOF = 0, OPT_CONFIG_FILE, OPT_IN_PLACE, + OPT_PROVIDER_NAME, + OPT_PROV_PROPQUERY, OPT_TEST_ENUM } OPTION_CHOICE; static OSSL_PROVIDER *prov_null = NULL; +static OSSL_PROVIDER *libprov = NULL; static OSSL_LIB_CTX *libctx = NULL; /* List of public and private keys */ @@ -114,6 +117,7 @@ static int memory_err_compare(EVP_TEST *t, const char *err, /* Option specific for evp test */ static int process_mode_in_place; +static const char *propquery = NULL; static int evp_test_process_mode(char *mode) { @@ -365,7 +369,7 @@ static int digest_test_init(EVP_TEST *t, const char *alg) return 1; } - if ((digest = fetched_digest = EVP_MD_fetch(libctx, alg, NULL)) == NULL + if ((digest = fetched_digest = EVP_MD_fetch(libctx, alg, propquery)) == NULL && (digest = EVP_get_digestbyname(alg)) == NULL) return 0; if (!TEST_ptr(mdat = OPENSSL_zalloc(sizeof(*mdat)))) @@ -594,7 +598,7 @@ static int cipher_test_init(EVP_TEST *t, const char *alg) } ERR_set_mark(); - if ((cipher = fetched_cipher = EVP_CIPHER_fetch(libctx, alg, NULL)) == NULL + if ((cipher = fetched_cipher = EVP_CIPHER_fetch(libctx, alg, propquery)) == NULL && (cipher = EVP_get_cipherbyname(alg)) == NULL) { /* a stitched cipher might not be available */ if (strstr(alg, "HMAC") != NULL) { @@ -735,6 +739,9 @@ static int cipher_test_enc(EVP_TEST *t, int enc, size_t out_misalign, int ok = 0, tmplen, chunklen, tmpflen, i; EVP_CIPHER_CTX *ctx_base = NULL; EVP_CIPHER_CTX *ctx = NULL, *duped; + int fips_dupctx_supported = (fips_provider_version_ge(libctx, 3, 0, 12) + && fips_provider_version_lt(libctx, 3, 1, 0)) + || fips_provider_version_ge(libctx, 3, 1, 4); t->err = "TEST_FAILURE"; if (!TEST_ptr(ctx_base = EVP_CIPHER_CTX_new())) @@ -865,18 +872,35 @@ static int cipher_test_enc(EVP_TEST *t, int enc, size_t out_misalign, /* Test that the cipher dup functions correctly if it is supported */ ERR_set_mark(); - if (EVP_CIPHER_CTX_copy(ctx, ctx_base)) { - EVP_CIPHER_CTX_free(ctx_base); - ctx_base = NULL; - } else { + if (!EVP_CIPHER_CTX_copy(ctx, ctx_base)) { + if (fips_dupctx_supported) { + TEST_info("Doing a copy of Cipher %s Fails!\n", + EVP_CIPHER_get0_name(expected->cipher)); + ERR_print_errors_fp(stderr); + goto err; + } else { + TEST_info("Allowing copy fail as an old fips provider is in use."); + } EVP_CIPHER_CTX_free(ctx); ctx = ctx_base; + } else { + EVP_CIPHER_CTX_free(ctx_base); + ctx_base = NULL; } /* Likewise for dup */ duped = EVP_CIPHER_CTX_dup(ctx); if (duped != NULL) { EVP_CIPHER_CTX_free(ctx); ctx = duped; + } else { + if (fips_dupctx_supported) { + TEST_info("Doing a dup of Cipher %s Fails!\n", + EVP_CIPHER_get0_name(expected->cipher)); + ERR_print_errors_fp(stderr); + goto err; + } else { + TEST_info("Allowing dup fail as an old fips provider is in use."); + } } ERR_pop_to_mark(); @@ -1089,6 +1113,7 @@ static int cipher_test_run(EVP_TEST *t) int rv, frag, fragmax, in_place; size_t out_misalign, inp_misalign; + TEST_info("RUNNING TEST FOR CIPHER %s\n", EVP_CIPHER_get0_name(cdat->cipher)); if (!cdat->key) { t->err = "NO_KEY"; return 0; @@ -1221,7 +1246,7 @@ static int mac_test_init(EVP_TEST *t, const char *alg) t->skip = 1; return 1; } - if ((mac = EVP_MAC_fetch(libctx, alg, NULL)) == NULL) { + if ((mac = EVP_MAC_fetch(libctx, alg, propquery)) == NULL) { /* * Since we didn't find an EVP_MAC, we check for known EVP_PKEY methods * For debugging purposes, we allow 'NNNN by EVP_PKEY' to force running @@ -1398,7 +1423,7 @@ static int mac_test_run_pkey(EVP_TEST *t) t->err = NULL; goto err; } - if (!TEST_ptr(cipher = EVP_CIPHER_fetch(libctx, expected->alg, NULL))) { + if (!TEST_ptr(cipher = EVP_CIPHER_fetch(libctx, expected->alg, propquery))) { t->err = "MAC_KEY_CREATE_ERROR"; goto err; } @@ -1771,7 +1796,7 @@ static int pkey_test_init(EVP_TEST *t, const char *name, return 0; } kdata->keyop = keyop; - if (!TEST_ptr(kdata->ctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey, NULL))) { + if (!TEST_ptr(kdata->ctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey, propquery))) { EVP_PKEY_free(pkey); OPENSSL_free(kdata); return 0; @@ -2270,7 +2295,7 @@ static int pbe_test_run(EVP_TEST *t) #endif } else if (expected->pbe_type == PBE_TYPE_PKCS12) { fetched_digest = EVP_MD_fetch(libctx, EVP_MD_get0_name(expected->md), - NULL); + propquery); if (fetched_digest == NULL) { t->err = "PKCS12_ERROR"; goto err; @@ -2510,7 +2535,7 @@ static int rand_test_init(EVP_TEST *t, const char *name) if (!EVP_RAND_CTX_set_params(rdata->parent, params)) goto err; - rand = EVP_RAND_fetch(libctx, name, NULL); + rand = EVP_RAND_fetch(libctx, name, propquery); if (rand == NULL) goto err; rdata->ctx = EVP_RAND_CTX_new(rand, rdata->parent); @@ -2762,7 +2787,7 @@ static int kdf_test_init(EVP_TEST *t, const char *name) kdata->p = kdata->params; *kdata->p = OSSL_PARAM_construct_end(); - kdf = EVP_KDF_fetch(libctx, name, NULL); + kdf = EVP_KDF_fetch(libctx, name, propquery); if (kdf == NULL) { OPENSSL_free(kdata); return 0; @@ -2971,7 +2996,7 @@ static int pkey_kdf_test_init(EVP_TEST *t, const char *name) if (!TEST_ptr(kdata = OPENSSL_zalloc(sizeof(*kdata)))) return 0; - kdata->ctx = EVP_PKEY_CTX_new_from_name(libctx, name, NULL); + kdata->ctx = EVP_PKEY_CTX_new_from_name(libctx, name, propquery); if (kdata->ctx == NULL || EVP_PKEY_derive_init(kdata->ctx) <= 0) goto err; @@ -3199,7 +3224,7 @@ static int keygen_test_init(EVP_TEST *t, const char *alg) t->skip = 1; return 1; } - if (!TEST_ptr(genctx = EVP_PKEY_CTX_new_from_name(libctx, alg, NULL))) + if (!TEST_ptr(genctx = EVP_PKEY_CTX_new_from_name(libctx, alg, propquery))) goto err; if (EVP_PKEY_keygen_init(genctx) <= 0) { @@ -4096,6 +4121,10 @@ const OPTIONS *test_get_options(void) "The configuration file to use for the libctx" }, { "process", OPT_IN_PLACE, 's', "Mode for data processing by cipher tests [in_place/both], both by default"}, + { "provider", OPT_PROVIDER_NAME, 's', + "The provider to load (when no configuration file, the default value is 'default')" }, + { "propquery", OPT_PROV_PROPQUERY, 's', + "Property query used when fetching algorithms" }, { OPT_HELP_STR, 1, '-', "file\tFile to run tests on.\n" }, { NULL } }; @@ -4106,6 +4135,7 @@ int setup_tests(void) { size_t n; char *config_file = NULL; + char *provider_name = NULL; OPTION_CHOICE o; @@ -4118,6 +4148,12 @@ int setup_tests(void) if ((process_mode_in_place = evp_test_process_mode(opt_arg())) == -1) return 0; break; + case OPT_PROVIDER_NAME: + provider_name = opt_arg(); + break; + case OPT_PROV_PROPQUERY: + propquery = opt_arg(); + break; case OPT_TEST_CASES: break; default: @@ -4131,7 +4167,9 @@ int setup_tests(void) * Load the 'null' provider into the default library context to ensure that * the tests do not fallback to using the default provider. */ - if (!test_get_libctx(&libctx, &prov_null, config_file, NULL, NULL)) + if (config_file == NULL && provider_name == NULL) + provider_name = "default"; + if (!test_get_libctx(&libctx, &prov_null, config_file, &libprov, provider_name)) return 0; n = test_get_argument_count(); @@ -4144,6 +4182,7 @@ int setup_tests(void) void cleanup_tests(void) { + OSSL_PROVIDER_unload(libprov); OSSL_PROVIDER_unload(prov_null); OSSL_LIB_CTX_free(libctx); } diff --git a/test/fake_rsaprov.c b/test/fake_rsaprov.c index a4f81be0232ea2f6ab1da23ccdafdf36e456ac0e..c1b8e28286143f4994dc5e17924e6ab6221dc9d4 100644 --- a/test/fake_rsaprov.c +++ b/test/fake_rsaprov.c @@ -30,12 +30,18 @@ static int has_selection; static int imptypes_selection; static int exptypes_selection; static int query_id; +static int key_deleted; struct fake_rsa_keydata { int selection; int status; }; +void fake_rsa_restore_store_state(void) +{ + key_deleted = 0; +} + static void *fake_rsa_keymgmt_new(void *provctx) { struct fake_rsa_keydata *key; @@ -519,15 +525,22 @@ static const OSSL_ALGORITHM fake_rsa_sig_algs[] = { }; static OSSL_FUNC_store_open_fn fake_rsa_st_open; +static OSSL_FUNC_store_open_ex_fn fake_rsa_st_open_ex; static OSSL_FUNC_store_settable_ctx_params_fn fake_rsa_st_settable_ctx_params; static OSSL_FUNC_store_set_ctx_params_fn fake_rsa_st_set_ctx_params; static OSSL_FUNC_store_load_fn fake_rsa_st_load; static OSSL_FUNC_store_eof_fn fake_rsa_st_eof; static OSSL_FUNC_store_close_fn fake_rsa_st_close; +static OSSL_FUNC_store_delete_fn fake_rsa_st_delete; static const char fake_rsa_scheme[] = "fake_rsa:"; +static const char fake_rsa_openpwtest[] = "fake_rsa:openpwtest"; +static const char fake_rsa_prompt[] = "Fake Prompt Info"; -static void *fake_rsa_st_open(void *provctx, const char *uri) +static void *fake_rsa_st_open_ex(void *provctx, const char *uri, + const OSSL_PARAM params[], + OSSL_PASSPHRASE_CALLBACK *pw_cb, + void *pw_cbarg) { unsigned char *storectx = NULL; @@ -535,10 +548,47 @@ static void *fake_rsa_st_open(void *provctx, const char *uri) if (strncmp(uri, fake_rsa_scheme, sizeof(fake_rsa_scheme) - 1) != 0) return NULL; + if (strncmp(uri, fake_rsa_openpwtest, + sizeof(fake_rsa_openpwtest) - 1) == 0) { + const char *pw_check = FAKE_PASSPHRASE; + char fakepw[sizeof(FAKE_PASSPHRASE) + 1] = { 0 }; + size_t fakepw_len = 0; + OSSL_PARAM pw_params[2] = { + OSSL_PARAM_utf8_string(OSSL_PASSPHRASE_PARAM_INFO, + (void *)fake_rsa_prompt, + sizeof(fake_rsa_prompt) - 1), + OSSL_PARAM_END, + }; + + if (pw_cb == NULL) { + return NULL; + } + + if (!pw_cb(fakepw, sizeof(fakepw), &fakepw_len, pw_params, pw_cbarg)) { + TEST_info("fake_rsa_open_ex failed passphrase callback"); + return NULL; + } + if (strncmp(pw_check, fakepw, sizeof(pw_check) - 1) != 0) { + TEST_info("fake_rsa_open_ex failed passphrase check"); + return NULL; + } + } + storectx = OPENSSL_zalloc(1); if (!TEST_ptr(storectx)) return NULL; + TEST_info("fake_rsa_open_ex called"); + + return storectx; +} + +static void *fake_rsa_st_open(void *provctx, const char *uri) +{ + unsigned char *storectx = NULL; + + storectx = fake_rsa_st_open_ex(provctx, uri, NULL, NULL, NULL); + TEST_info("fake_rsa_open called"); return storectx; @@ -570,6 +620,11 @@ static int fake_rsa_st_load(void *loaderctx, switch (*storectx) { case 0: + if (key_deleted == 1) { + *storectx = 1; + break; + } + /* Construct a new key using our keymgmt functions */ if (!TEST_ptr(key = fake_rsa_keymgmt_new(NULL))) break; @@ -600,13 +655,21 @@ static int fake_rsa_st_load(void *loaderctx, TEST_info("fake_rsa_load called - rv: %d", rv); - if (rv == 0) { + if (rv == 0 && key_deleted == 0) { fake_rsa_keymgmt_free(key); *storectx = 2; } return rv; } +static int fake_rsa_st_delete(void *loaderctx, const char *uri, + const OSSL_PARAM params[], + OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg) +{ + key_deleted = 1; + return 1; +} + static int fake_rsa_st_eof(void *loaderctx) { unsigned char *storectx = loaderctx; @@ -623,12 +686,14 @@ static int fake_rsa_st_close(void *loaderctx) static const OSSL_DISPATCH fake_rsa_store_funcs[] = { { OSSL_FUNC_STORE_OPEN, (void (*)(void))fake_rsa_st_open }, + { OSSL_FUNC_STORE_OPEN_EX, (void (*)(void))fake_rsa_st_open_ex }, { OSSL_FUNC_STORE_SETTABLE_CTX_PARAMS, (void (*)(void))fake_rsa_st_settable_ctx_params }, { OSSL_FUNC_STORE_SET_CTX_PARAMS, (void (*)(void))fake_rsa_st_set_ctx_params }, { OSSL_FUNC_STORE_LOAD, (void (*)(void))fake_rsa_st_load }, { OSSL_FUNC_STORE_EOF, (void (*)(void))fake_rsa_st_eof }, { OSSL_FUNC_STORE_CLOSE, (void (*)(void))fake_rsa_st_close }, + { OSSL_FUNC_STORE_DELETE, (void (*)(void))fake_rsa_st_delete }, OSSL_DISPATCH_END, }; diff --git a/test/fake_rsaprov.h b/test/fake_rsaprov.h index 190c46a285c0ae9a7a6b7f19142c3718f8073374..9c353b386f3b6b817c1cb2c8f310ab6dc14b7a55 100644 --- a/test/fake_rsaprov.h +++ b/test/fake_rsaprov.h @@ -9,7 +9,10 @@ #include +#define FAKE_PASSPHRASE "Passphrase Testing" + /* Fake RSA provider implementation */ OSSL_PROVIDER *fake_rsa_start(OSSL_LIB_CTX *libctx); void fake_rsa_finish(OSSL_PROVIDER *p); OSSL_PARAM *fake_rsa_key_params(int priv); +void fake_rsa_restore_store_state(void); diff --git a/test/helpers/handshake_srp.c b/test/helpers/handshake_srp.c index 43a5a4fd605a54176997f666186ed315fd90db75..95fb101059f2e4d1fecb6a4aa97fc032e041972e 100644 --- a/test/helpers/handshake_srp.c +++ b/test/helpers/handshake_srp.c @@ -8,8 +8,9 @@ */ /* - * SRP is deprecated and there is no replacent. When SRP is removed, the code in - * this file can be removed too. Until then we have to use the deprecated APIs. + * SRP is deprecated and there is no replacement. When SRP is removed, + * the code in this file can be removed too. Until then we have to use + * the deprecated APIs. */ #define OPENSSL_SUPPRESS_DEPRECATED diff --git a/test/helpers/noisydgrambio.c b/test/helpers/noisydgrambio.c new file mode 100644 index 0000000000000000000000000000000000000000..8b68726dd2b4c4fa1751c4588d43850fd4786195 --- /dev/null +++ b/test/helpers/noisydgrambio.c @@ -0,0 +1,325 @@ +/* + * 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 +#include "quictestlib.h" +#include "../testutil.h" + +#define MSG_DATA_LEN_MAX 1472 + +struct noisy_dgram_st { + uint64_t this_dgram; + BIO_MSG msg; + uint64_t reinject_dgram; +}; + +static long noisy_dgram_ctrl(BIO *bio, int cmd, long num, void *ptr) +{ + long ret; + BIO *next = BIO_next(bio); + + if (next == NULL) + return 0; + + switch (cmd) { + case BIO_CTRL_DUP: + ret = 0L; + break; + default: + ret = BIO_ctrl(next, cmd, num, ptr); + break; + } + return ret; +} + +static int noisy_dgram_sendmmsg(BIO *bio, BIO_MSG *msg, size_t stride, + size_t num_msg, uint64_t flags, + size_t *msgs_processed) +{ + BIO *next = BIO_next(bio); + + if (next == NULL) + return 0; + + /* + * We only introduce noise when receiving messages. We just pass this on + * to the underlying BIO. + */ + return BIO_sendmmsg(next, msg, stride, num_msg, flags, msgs_processed); +} + +/* 1 in NOISE_RATE datagrams will be noisy. With a value of 5 that is 20% */ +#define NOISE_RATE 5 + +/* + * We have 3 different types of noise: drop, duplicate and delay + * Each of these have equal probability. + */ +#define NOISE_TYPE_DROP 0 +#define NOISE_TYPE_DUPLICATE 1 +#define NOISE_TYPE_DELAY 2 +#define NUM_NOISE_TYPES 3 + +/* + * When a duplicate occurs we reinject the new datagram after up to + * MAX_DGRAM_REINJECT datagrams have been sent. A reinject of 1 means that the + * duplicate follows immediately after the original datagram. A reinject of 4 + * means that original datagram plus 3 other datagrams are sent before the + * reinjected datagram is inserted. + * This also controls when a delay (not a duplicate) occurs. In that case + * we add 1 to the number because there is no point in skipping the current + * datagram only to immediately reinject it in the next datagram. + */ +#define MAX_DGRAM_REINJECT 4 + +static void get_noise(uint64_t *reinject, int *should_drop) +{ + uint32_t type; + + if (test_random() % NOISE_RATE != 0) { + *reinject = 0; + *should_drop = 0; + return; + } + + type = test_random() % NUM_NOISE_TYPES; + + /* + * Of noisy datagrams, 33% drop, 33% duplicate, 33% delay + * A duplicated datagram keeps the current datagram and reinjects a new + * identical one after up to MAX_DGRAM_DELAY datagrams have been sent. + * A delayed datagram is implemented as both a reinject and a drop, i.e. an + * identical datagram is reinjected after the given number of datagrams have + * been sent and the current datagram is dropped. + */ + *should_drop = (type == NOISE_TYPE_DROP || type == NOISE_TYPE_DELAY); + + /* + * Where a duplicate occurs we reinject the copy of the datagram up to + * MAX_DGRAM_DELAY datagrams later + */ + *reinject = (type == NOISE_TYPE_DROP) + ? 0 + : (uint64_t)((test_random() % MAX_DGRAM_REINJECT) + 1); + + /* + * No point in reinjecting after 1 datagram if the current datagram is also + * dropped (i.e. this is a delay not a duplicate), so we reinject after an + * extra datagram in that case + */ + *reinject += (uint64_t)(*should_drop); +} + +static int noisy_dgram_recvmmsg(BIO *bio, BIO_MSG *msg, size_t stride, + size_t num_msg, uint64_t flags, + size_t *msgs_processed) +{ + BIO *next = BIO_next(bio); + size_t i, j, data_len = 0, msg_cnt = 0; + BIO_MSG *thismsg; + struct noisy_dgram_st *data; + + if (!TEST_ptr(next)) + return 0; + + data = BIO_get_data(bio); + if (!TEST_ptr(data)) + return 0; + + /* + * For simplicity we assume that all elements in the msg array have the + * same data_len. They are not required to by the API, but it would be quite + * strange for that not to be the case - and our code that calls + * BIO_recvmmsg does do this (which is all that is important for this test + * code). We test the invariant here. + */ + for (i = 0; i < num_msg; i++) { + if (i == 0) { + data_len = msg[i].data_len; + if (!TEST_size_t_le(data_len, MSG_DATA_LEN_MAX)) + return 0; + } else if (!TEST_size_t_eq(msg[i].data_len, data_len)) { + return 0; + } + } + + if (!BIO_recvmmsg(next, msg, stride, num_msg, flags, msgs_processed)) + return 0; + +#ifdef OSSL_NOISY_DGRAM_DEBUG + printf("Pre-filter datagram list:\n"); + for (i = 0; i < *msgs_processed; i++) { + printf("Pre-filter Datagram:\n"); + BIO_dump_fp(stdout, msg[i].data, msg[i].data_len); + printf("\n"); + } + printf("End of pre-filter datagram list\nApplying noise filters:\n"); +#endif + + msg_cnt = *msgs_processed; + + /* Introduce noise */ + for (i = 0, thismsg = msg; + i < msg_cnt; + i++, thismsg++, data->this_dgram++) { + uint64_t reinject; + int should_drop; + + /* If we have a message to reinject then insert it now */ + if (data->reinject_dgram > 0 + && data->reinject_dgram == data->this_dgram) { + if (msg_cnt < num_msg) { + /* Make space for the injected message */ + for (j = msg_cnt; j > i; j--) { + if (!bio_msg_copy(&msg[j], &msg[j - 1])) + return 0; + } + if (!bio_msg_copy(thismsg, &data->msg)) + return 0; + msg_cnt++; + data->reinject_dgram = 0; +#ifdef OSSL_NOISY_DGRAM_DEBUG + printf("**Injecting a datagram\n"); + BIO_dump_fp(stdout, thismsg->data, thismsg->data_len); + printf("\n"); +#endif + continue; + } /* else we have no space for the injection, so just drop it */ + data->reinject_dgram = 0; + } + + get_noise(&reinject, &should_drop); + + /* + * We ignore reinjection if a message is already waiting to be + * reinjected + */ + if (reinject > 0 && data->reinject_dgram == 0) { + /* + * Both duplicated and delayed datagrams get reintroduced after the + * delay period. Datagrams that are delayed only (not duplicated) + * will also have the current copy of the datagram dropped (i.e + * should_drop below will be true). + */ + if (!bio_msg_copy(&data->msg, thismsg)) + return 0; + + data->reinject_dgram = data->this_dgram + reinject; + +#ifdef OSSL_NOISY_DGRAM_DEBUG + printf("**Scheduling a reinject after %u messages%s\n", + (unsigned int)reinject, should_drop ? "" : "(duplicating)"); + BIO_dump_fp(stdout, thismsg->data, thismsg->data_len); + printf("\n"); +#endif + } + + if (should_drop) { +#ifdef OSSL_NOISY_DGRAM_DEBUG + printf("**Dropping a datagram\n"); + BIO_dump_fp(stdout, thismsg->data, thismsg->data_len); + printf("\n"); +#endif + for (j = i + 1; j < msg_cnt; j++) { + if (!bio_msg_copy(&msg[j - 1], &msg[j])) + return 0; + } + msg_cnt--; + } + } + +#ifdef OSSL_NOISY_DGRAM_DEBUG + printf("End of noise filters\nPost-filter datagram list:\n"); + for (i = 0; i < msg_cnt; i++) { + printf("Post-filter Datagram:\n"); + BIO_dump_fp(stdout, msg[i].data, msg[i].data_len); + printf("\n"); + } + printf("End of post-filter datagram list\n"); +#endif + + *msgs_processed = msg_cnt; + + if (msg_cnt == 0) { + ERR_raise(ERR_LIB_BIO, BIO_R_NON_FATAL); + return 0; + } + + return 1; +} + +static void data_free(struct noisy_dgram_st *data) +{ + if (data == NULL) + return; + + OPENSSL_free(data->msg.data); + BIO_ADDR_free(data->msg.peer); + BIO_ADDR_free(data->msg.local); + OPENSSL_free(data); +} + +static int noisy_dgram_new(BIO *bio) +{ + struct noisy_dgram_st *data = OPENSSL_zalloc(sizeof(*data)); + + if (!TEST_ptr(data)) + return 0; + + data->msg.data = OPENSSL_malloc(MSG_DATA_LEN_MAX); + data->msg.peer = BIO_ADDR_new(); + data->msg.local = BIO_ADDR_new(); + if (data->msg.data == NULL + || data->msg.peer == NULL + || data->msg.local == NULL) { + data_free(data); + return 0; + } + + BIO_set_data(bio, data); + BIO_set_init(bio, 1); + + return 1; +} + +static int noisy_dgram_free(BIO *bio) +{ + data_free(BIO_get_data(bio)); + BIO_set_data(bio, NULL); + BIO_set_init(bio, 0); + + return 1; +} + +/* Choose a sufficiently large type likely to be unused for this custom BIO */ +#define BIO_TYPE_NOISY_DGRAM_FILTER (0x80 | BIO_TYPE_FILTER) + +static BIO_METHOD *method_noisy_dgram = NULL; + +/* Note: Not thread safe! */ +const BIO_METHOD *bio_f_noisy_dgram_filter(void) +{ + if (method_noisy_dgram == NULL) { + method_noisy_dgram = BIO_meth_new(BIO_TYPE_NOISY_DGRAM_FILTER, + "Nosiy datagram filter"); + if (method_noisy_dgram == NULL + || !BIO_meth_set_ctrl(method_noisy_dgram, noisy_dgram_ctrl) + || !BIO_meth_set_sendmmsg(method_noisy_dgram, noisy_dgram_sendmmsg) + || !BIO_meth_set_recvmmsg(method_noisy_dgram, noisy_dgram_recvmmsg) + || !BIO_meth_set_create(method_noisy_dgram, noisy_dgram_new) + || !BIO_meth_set_destroy(method_noisy_dgram, noisy_dgram_free)) + return NULL; + } + return method_noisy_dgram; +} + +void bio_f_noisy_dgram_filter_free(void) +{ + BIO_meth_free(method_noisy_dgram); +} diff --git a/test/helpers/pktsplitbio.c b/test/helpers/pktsplitbio.c new file mode 100644 index 0000000000000000000000000000000000000000..536e62f8a0030d1951e16807a7553befa7f0d11b --- /dev/null +++ b/test/helpers/pktsplitbio.c @@ -0,0 +1,141 @@ +/* + * 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 +#include "quictestlib.h" +#include "../testutil.h" + +static long pkt_split_dgram_ctrl(BIO *bio, int cmd, long num, void *ptr) +{ + long ret; + BIO *next = BIO_next(bio); + + if (next == NULL) + return 0; + + switch (cmd) { + case BIO_CTRL_DUP: + ret = 0L; + break; + default: + ret = BIO_ctrl(next, cmd, num, ptr); + break; + } + return ret; +} + +static int pkt_split_dgram_sendmmsg(BIO *bio, BIO_MSG *msg, size_t stride, + size_t num_msg, uint64_t flags, + size_t *msgs_processed) +{ + BIO *next = BIO_next(bio); + + if (next == NULL) + return 0; + + /* + * We only introduce noise when receiving messages. We just pass this on + * to the underlying BIO. + */ + return BIO_sendmmsg(next, msg, stride, num_msg, flags, msgs_processed); +} + +static int pkt_split_dgram_recvmmsg(BIO *bio, BIO_MSG *msg, size_t stride, + size_t num_msg, uint64_t flags, + size_t *msgs_processed) +{ + BIO *next = BIO_next(bio); + size_t i, j, data_len = 0, msg_cnt = 0; + BIO_MSG *thismsg; + + if (!TEST_ptr(next)) + return 0; + + /* + * For simplicity we assume that all elements in the msg array have the + * same data_len. They are not required to by the API, but it would be quite + * strange for that not to be the case - and our code that calls + * BIO_recvmmsg does do this (which is all that is important for this test + * code). We test the invariant here. + */ + for (i = 0; i < num_msg; i++) { + if (i == 0) + data_len = msg[i].data_len; + else if (!TEST_size_t_eq(msg[i].data_len, data_len)) + return 0; + } + + if (!BIO_recvmmsg(next, msg, stride, num_msg, flags, msgs_processed)) + return 0; + + msg_cnt = *msgs_processed; + if (msg_cnt == num_msg) + return 1; /* We've used all our slots and can't split any more */ + assert(msg_cnt < num_msg); + + for (i = 0, thismsg = msg; i < msg_cnt; i++, thismsg++) { + QUIC_PKT_HDR hdr; + PACKET pkt; + size_t remain; + + if (!PACKET_buf_init(&pkt, thismsg->data, thismsg->data_len)) + return 0; + + /* Decode the packet header */ + /* + * TODO(QUIC SERVER): We need to query the short connection id len + * here, e.g. via some API SSL_get_short_conn_id_len() + */ + if (ossl_quic_wire_decode_pkt_hdr(&pkt, 0, 0, 0, &hdr, NULL) != 1) + return 0; + remain = PACKET_remaining(&pkt); + if (remain > 0) { + for (j = msg_cnt; j > i; j--) { + if (!bio_msg_copy(&msg[j], &msg[j - 1])) + return 0; + } + thismsg->data_len -= remain; + msg[i + 1].data_len = remain; + memmove(msg[i + 1].data, + (unsigned char *)msg[i + 1].data + thismsg->data_len, + remain); + msg_cnt++; + } + } + + *msgs_processed = msg_cnt; + return 1; +} + +/* Choose a sufficiently large type likely to be unused for this custom BIO */ +#define BIO_TYPE_PKT_SPLIT_DGRAM_FILTER (0x81 | BIO_TYPE_FILTER) + +static BIO_METHOD *method_pkt_split_dgram = NULL; + +/* Note: Not thread safe! */ +const BIO_METHOD *bio_f_pkt_split_dgram_filter(void) +{ + if (method_pkt_split_dgram == NULL) { + method_pkt_split_dgram = BIO_meth_new(BIO_TYPE_PKT_SPLIT_DGRAM_FILTER, + "Packet splitting datagram filter"); + if (method_pkt_split_dgram == NULL + || !BIO_meth_set_ctrl(method_pkt_split_dgram, pkt_split_dgram_ctrl) + || !BIO_meth_set_sendmmsg(method_pkt_split_dgram, + pkt_split_dgram_sendmmsg) + || !BIO_meth_set_recvmmsg(method_pkt_split_dgram, + pkt_split_dgram_recvmmsg)) + return NULL; + } + return method_pkt_split_dgram; +} + +void bio_f_pkt_split_dgram_filter_free(void) +{ + BIO_meth_free(method_pkt_split_dgram); +} diff --git a/test/helpers/quictestlib.c b/test/helpers/quictestlib.c index f0955559dcac251fdd172771b1f5699502fbea9e..f5a46efb6f01601acd25be95015290b6dda4c640 100644 --- a/test/helpers/quictestlib.c +++ b/test/helpers/quictestlib.c @@ -66,6 +66,7 @@ struct qtest_fault { static void packet_plain_finish(void *arg); static void handshake_finish(void *arg); +static int using_fake_time = 0; static OSSL_TIME fake_now; static OSSL_TIME fake_now_cb(void *arg) @@ -76,7 +77,7 @@ static OSSL_TIME fake_now_cb(void *arg) int qtest_create_quic_objects(OSSL_LIB_CTX *libctx, SSL_CTX *clientctx, SSL_CTX *serverctx, char *certfile, char *keyfile, int flags, QUIC_TSERVER **qtserv, SSL **cssl, - QTEST_FAULT **fault) + QTEST_FAULT **fault, BIO **tracebio) { /* ALPN value as recognised by QUIC_TSERVER */ unsigned char alpn[] = { 8, 'o', 's', 's', 'l', 't', 'e', 's', 't' }; @@ -84,6 +85,7 @@ int qtest_create_quic_objects(OSSL_LIB_CTX *libctx, SSL_CTX *clientctx, BIO *cbio = NULL, *sbio = NULL, *fisbio = NULL; BIO_ADDR *peeraddr = NULL; struct in_addr ina = {0}; + BIO *tmpbio = NULL; *qtserv = NULL; if (fault != NULL) @@ -95,6 +97,17 @@ int qtest_create_quic_objects(OSSL_LIB_CTX *libctx, SSL_CTX *clientctx, return 0; } + if ((flags & QTEST_FLAG_CLIENT_TRACE) != 0) { + tmpbio = BIO_new_fp(stdout, BIO_NOCLOSE); + if (!TEST_ptr(tmpbio)) + goto err; + + SSL_set_msg_callback(*cssl, SSL_trace); + SSL_set_msg_callback_arg(*cssl, tmpbio); + } + if (tracebio != NULL) + *tracebio = tmpbio; + /* SSL_set_alpn_protos returns 0 for success! */ if (!TEST_false(SSL_set_alpn_protos(*cssl, alpn, sizeof(alpn)))) goto err; @@ -140,6 +153,33 @@ int qtest_create_quic_objects(OSSL_LIB_CTX *libctx, SSL_CTX *clientctx, goto err; } + if ((flags & QTEST_FLAG_PACKET_SPLIT) != 0) { + BIO *pktsplitbio = BIO_new(bio_f_pkt_split_dgram_filter()); + + if (!TEST_ptr(pktsplitbio)) + goto err; + cbio = BIO_push(pktsplitbio, cbio); + + pktsplitbio = BIO_new(bio_f_pkt_split_dgram_filter()); + if (!TEST_ptr(pktsplitbio)) + goto err; + sbio = BIO_push(pktsplitbio, sbio); + } + + if ((flags & QTEST_FLAG_NOISE) != 0) { + BIO *noisebio = BIO_new(bio_f_noisy_dgram_filter()); + + if (!TEST_ptr(noisebio)) + goto err; + cbio = BIO_push(noisebio, cbio); + + noisebio = BIO_new(bio_f_noisy_dgram_filter()); + + if (!TEST_ptr(noisebio)) + goto err; + sbio = BIO_push(noisebio, sbio); + } + SSL_set_bio(*cssl, cbio, cbio); if (!TEST_true(SSL_set_blocking_mode(*cssl, @@ -161,8 +201,12 @@ int qtest_create_quic_objects(OSSL_LIB_CTX *libctx, SSL_CTX *clientctx, BIO_set_data(fisbio, fault == NULL ? NULL : *fault); - if (!TEST_ptr(BIO_push(fisbio, sbio))) + if (!BIO_up_ref(sbio)) + goto err; + if (!TEST_ptr(BIO_push(fisbio, sbio))) { + BIO_free(sbio); goto err; + } tserver_args.libctx = libctx; tserver_args.net_rbio = sbio; @@ -172,11 +216,14 @@ int qtest_create_quic_objects(OSSL_LIB_CTX *libctx, SSL_CTX *clientctx, goto err; tserver_args.ctx = serverctx; if ((flags & QTEST_FLAG_FAKE_TIME) != 0) { + using_fake_time = 1; fake_now = ossl_time_zero(); /* zero time can have a special meaning, bump it */ qtest_add_time(1); tserver_args.now_cb = fake_now_cb; (void)ossl_quic_conn_set_override_now_cb(*cssl, fake_now_cb, NULL); + } else { + using_fake_time = 0; } if (!TEST_ptr(*qtserv = ossl_quic_tserver_new(&tserver_args, certfile, @@ -196,14 +243,17 @@ int qtest_create_quic_objects(OSSL_LIB_CTX *libctx, SSL_CTX *clientctx, err: SSL_CTX_free(tserver_args.ctx); BIO_ADDR_free(peeraddr); - BIO_free(cbio); - BIO_free(fisbio); - BIO_free(sbio); + BIO_free_all(cbio); + BIO_free_all(fisbio); + BIO_free_all(sbio); SSL_free(*cssl); *cssl = NULL; ossl_quic_tserver_free(*qtserv); if (fault != NULL) OPENSSL_free(*fault); + BIO_free(tmpbio); + if (tracebio != NULL) + *tracebio = NULL; return 0; } @@ -254,6 +304,47 @@ static void run_server_thread(void) } #endif +int qtest_wait_for_timeout(SSL *s, QUIC_TSERVER *qtserv) +{ + struct timeval tv; + OSSL_TIME ctimeout, stimeout, mintimeout, now; + int cinf; + + /* We don't need to wait in blocking mode */ + if (s == NULL || SSL_get_blocking_mode(s)) + return 1; + + /* Don't wait if either BIO has data waiting */ + if (BIO_pending(SSL_get_rbio(s)) > 0 + || BIO_pending(ossl_quic_tserver_get0_rbio(qtserv)) > 0) + return 1; + + /* + * Neither endpoint has data waiting to be read. We assume data transmission + * is instantaneous due to using mem based BIOs, so there is no data "in + * flight" and no more data will be sent by either endpoint until some time + * based event has occurred. Therefore, wait for a timeout to occur. This + * might happen if we are using the noisy BIO and datagrams have been lost. + */ + if (!SSL_get_event_timeout(s, &tv, &cinf)) + return 0; + if (using_fake_time) + now = fake_now; + else + now = ossl_time_now(); + ctimeout = cinf ? ossl_time_infinite() : ossl_time_from_timeval(tv); + stimeout = ossl_time_subtract(ossl_quic_tserver_get_deadline(qtserv), now); + mintimeout = ossl_time_min(ctimeout, stimeout); + if (ossl_time_is_infinite(mintimeout)) + return 0; + if (using_fake_time) + fake_now = ossl_time_add(now, mintimeout); + else + OSSL_sleep(ossl_time2ms(mintimeout)); + + return 1; +} + int qtest_create_quic_connection_ex(QUIC_TSERVER *qtserv, SSL *clientssl, int wanterr) { @@ -319,19 +410,13 @@ int qtest_create_quic_connection_ex(QUIC_TSERVER *qtserv, SSL *clientssl, } } - /* - * We're cheating. We don't take any notice of SSL_get_tick_timeout() - * and tick every time around the loop anyway. This is inefficient. We - * can get away with it in test code because we control both ends of - * the communications and don't expect network delays. This shouldn't - * be done in a real application. - */ - if (!clienterr && retc <= 0) + qtest_add_time(1); + if (clientssl != NULL) SSL_handle_events(clientssl); + if (qtserv != NULL) + ossl_quic_tserver_tick(qtserv); if (!servererr && rets <= 0) { - qtest_add_time(1); - ossl_quic_tserver_tick(qtserv); servererr = ossl_quic_tserver_is_term_any(qtserv); if (!servererr) rets = ossl_quic_tserver_is_handshake_confirmed(qtserv); @@ -344,6 +429,11 @@ int qtest_create_quic_connection_ex(QUIC_TSERVER *qtserv, SSL *clientssl, TEST_info("No progress made"); goto err; } + + if ((retc <= 0 && !clienterr) || (rets <= 0 && !servererr)) { + if (!qtest_wait_for_timeout(clientssl, qtserv)) + goto err; + } } while ((retc <= 0 && !clienterr) || (rets <= 0 && !servererr #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG) @@ -995,3 +1085,64 @@ int qtest_fault_resize_datagram(QTEST_FAULT *fault, size_t newlen) return 1; } + +/* There isn't a public function to do BIO_ADDR_copy() so we create one */ +int bio_addr_copy(BIO_ADDR *dst, BIO_ADDR *src) +{ + size_t len; + void *data = NULL; + int res = 0; + int family; + + if (src == NULL || dst == NULL) + return 0; + + family = BIO_ADDR_family(src); + if (family == AF_UNSPEC) { + BIO_ADDR_clear(dst); + return 1; + } + + if (!BIO_ADDR_rawaddress(src, NULL, &len)) + return 0; + + if (len > 0) { + data = OPENSSL_malloc(len); + if (!TEST_ptr(data)) + return 0; + } + + if (!BIO_ADDR_rawaddress(src, data, &len)) + goto err; + + if (!BIO_ADDR_rawmake(src, family, data, len, BIO_ADDR_rawport(src))) + goto err; + + res = 1; + err: + OPENSSL_free(data); + return res; +} + +int bio_msg_copy(BIO_MSG *dst, BIO_MSG *src) +{ + /* + * Note it is assumed that the originally allocated data sizes for dst and + * src are the same + */ + memcpy(dst->data, src->data, src->data_len); + dst->data_len = src->data_len; + dst->flags = src->flags; + if (dst->local != NULL) { + if (src->local != NULL) { + if (!TEST_true(bio_addr_copy(dst->local, src->local))) + return 0; + } else { + BIO_ADDR_clear(dst->local); + } + } + if (!TEST_true(bio_addr_copy(dst->peer, src->peer))) + return 0; + + return 1; +} diff --git a/test/helpers/quictestlib.h b/test/helpers/quictestlib.h index 45f6ebec7918e231bb9f40bef4e85f2c53481d1d..844aec8a60be63ab302b7f4ef605076e2743bb3a 100644 --- a/test/helpers/quictestlib.h +++ b/test/helpers/quictestlib.h @@ -27,10 +27,15 @@ typedef struct qtest_fault_encrypted_extensions { /* Flags for use with qtest_create_quic_objects() */ /* Indicates whether we are using blocking mode or not */ -#define QTEST_FLAG_BLOCK 1 +#define QTEST_FLAG_BLOCK (1 << 0) /* Use fake time rather than real time */ -#define QTEST_FLAG_FAKE_TIME 2 - +#define QTEST_FLAG_FAKE_TIME (1 << 1) +/* Introduce noise in the BIO */ +#define QTEST_FLAG_NOISE (1 << 2) +/* Split datagrams such that each datagram contains one packet */ +#define QTEST_FLAG_PACKET_SPLIT (1 << 3) +/* Turn on client side tracing */ +#define QTEST_FLAG_CLIENT_TRACE (1 << 4) /* * Given an SSL_CTX for the client and filenames for the server certificate and * keyfile, create a server and client instances as well as a fault injector @@ -39,7 +44,7 @@ typedef struct qtest_fault_encrypted_extensions { int qtest_create_quic_objects(OSSL_LIB_CTX *libctx, SSL_CTX *clientctx, SSL_CTX *serverctx, char *certfile, char *keyfile, int flags, QUIC_TSERVER **qtserv, SSL **cssl, - QTEST_FAULT **fault); + QTEST_FAULT **fault, BIO **tracebio); /* Where QTEST_FLAG_FAKE_TIME is used, add millis to the current time */ void qtest_add_time(uint64_t millis); @@ -62,6 +67,12 @@ int qtest_supports_blocking(void); */ int qtest_create_quic_connection(QUIC_TSERVER *qtserv, SSL *clientssl); +/* + * Check if both client and server have no data to read and are waiting on a + * timeout. If so, wait until the timeout has expired. + */ +int qtest_wait_for_timeout(SSL *s, QUIC_TSERVER *qtserv); + /* * Same as qtest_create_quic_connection but will stop (successfully) if the * clientssl indicates SSL_ERROR_WANT_XXX as specified by |wanterr| @@ -230,3 +241,24 @@ int qtest_fault_set_datagram_listener(QTEST_FAULT *fault, * exceeds the over allocation. */ int qtest_fault_resize_datagram(QTEST_FAULT *fault, size_t newlen); + +/* Copy a BIO_ADDR */ +int bio_addr_copy(BIO_ADDR *dst, BIO_ADDR *src); + +/* Copy a BIO_MSG */ +int bio_msg_copy(BIO_MSG *dst, BIO_MSG *src); + +/* BIO filter for simulating a noisy UDP socket */ +const BIO_METHOD *bio_f_noisy_dgram_filter(void); + +/* Free the BIO filter method object */ +void bio_f_noisy_dgram_filter_free(void); + +/* + * BIO filter for splitting QUIC datagrams containing multiple packets into + * individual datagrams. + */ +const BIO_METHOD *bio_f_pkt_split_dgram_filter(void); + +/* Free the BIO filter method object */ +void bio_f_pkt_split_dgram_filter_free(void); diff --git a/test/helpers/ssltestlib.c b/test/helpers/ssltestlib.c index 94a170b9a52f440a2a0364880938195215359392..3ae3e7d4eaf47ee1996a9e5c6ef435b811e08161 100644 --- a/test/helpers/ssltestlib.c +++ b/test/helpers/ssltestlib.c @@ -985,6 +985,7 @@ int create_ssl_objects2(SSL_CTX *serverctx, SSL_CTX *clientctx, SSL **sssl, { SSL *serverssl = NULL, *clientssl = NULL; BIO *s_to_c_bio = NULL, *c_to_s_bio = NULL; + BIO_POLL_DESCRIPTOR rdesc = {0}, wdesc = {0}; if (*sssl != NULL) serverssl = *sssl; @@ -999,8 +1000,29 @@ int create_ssl_objects2(SSL_CTX *serverctx, SSL_CTX *clientctx, SSL **sssl, || !TEST_ptr(c_to_s_bio = BIO_new_socket(cfd, BIO_NOCLOSE))) goto error; + if (!TEST_false(SSL_get_rpoll_descriptor(clientssl, &rdesc) + || !TEST_false(SSL_get_wpoll_descriptor(clientssl, &wdesc)))) + goto error; + SSL_set_bio(clientssl, c_to_s_bio, c_to_s_bio); SSL_set_bio(serverssl, s_to_c_bio, s_to_c_bio); + + if (!TEST_true(SSL_get_rpoll_descriptor(clientssl, &rdesc)) + || !TEST_true(SSL_get_wpoll_descriptor(clientssl, &wdesc)) + || !TEST_int_eq(rdesc.type, BIO_POLL_DESCRIPTOR_TYPE_SOCK_FD) + || !TEST_int_eq(wdesc.type, BIO_POLL_DESCRIPTOR_TYPE_SOCK_FD) + || !TEST_int_eq(rdesc.value.fd, cfd) + || !TEST_int_eq(wdesc.value.fd, cfd)) + goto error; + + if (!TEST_true(SSL_get_rpoll_descriptor(serverssl, &rdesc)) + || !TEST_true(SSL_get_wpoll_descriptor(serverssl, &wdesc)) + || !TEST_int_eq(rdesc.type, BIO_POLL_DESCRIPTOR_TYPE_SOCK_FD) + || !TEST_int_eq(wdesc.type, BIO_POLL_DESCRIPTOR_TYPE_SOCK_FD) + || !TEST_int_eq(rdesc.value.fd, sfd) + || !TEST_int_eq(wdesc.value.fd, sfd)) + goto error; + *sssl = serverssl; *cssl = clientssl; return 1; @@ -1247,3 +1269,41 @@ void shutdown_ssl_connection(SSL *serverssl, SSL *clientssl) SSL_free(serverssl); SSL_free(clientssl); } + +SSL_SESSION *create_a_psk(SSL *ssl, size_t mdsize) +{ + const SSL_CIPHER *cipher = NULL; + const unsigned char key[SHA384_DIGEST_LENGTH] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, + 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, + 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, + 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, + 0x2c, 0x2d, 0x2e, 0x2f + }; + SSL_SESSION *sess = NULL; + + if (mdsize == SHA384_DIGEST_LENGTH) { + cipher = SSL_CIPHER_find(ssl, TLS13_AES_256_GCM_SHA384_BYTES); + } else if (mdsize == SHA256_DIGEST_LENGTH) { + /* + * Any ciphersuite using SHA256 will do - it will be compatible with + * the actual ciphersuite selected as long as it too is based on SHA256 + */ + cipher = SSL_CIPHER_find(ssl, TLS13_AES_128_GCM_SHA256_BYTES); + } else { + /* Should not happen */ + return NULL; + } + sess = SSL_SESSION_new(); + if (!TEST_ptr(sess) + || !TEST_ptr(cipher) + || !TEST_true(SSL_SESSION_set1_master_key(sess, key, mdsize)) + || !TEST_true(SSL_SESSION_set_cipher(sess, cipher)) + || !TEST_true( + SSL_SESSION_set_protocol_version(sess, + TLS1_3_VERSION))) { + SSL_SESSION_free(sess); + return NULL; + } + return sess; +} diff --git a/test/helpers/ssltestlib.h b/test/helpers/ssltestlib.h index c8dcb8a82d28d269d1b4bda47bc3f2cf4108277b..c513769ddd956027957dd7022af260a84e6e47ba 100644 --- a/test/helpers/ssltestlib.h +++ b/test/helpers/ssltestlib.h @@ -12,6 +12,12 @@ # include +#define TLS13_AES_128_GCM_SHA256_BYTES ((const unsigned char *)"\x13\x01") +#define TLS13_AES_256_GCM_SHA384_BYTES ((const unsigned char *)"\x13\x02") +#define TLS13_CHACHA20_POLY1305_SHA256_BYTES ((const unsigned char *)"\x13\x03") +#define TLS13_AES_128_CCM_SHA256_BYTES ((const unsigned char *)"\x13\x04") +#define TLS13_AES_128_CCM_8_SHA256_BYTES ((const unsigned char *)"\x13\05") + int create_ssl_ctx_pair(OSSL_LIB_CTX *libctx, const SSL_METHOD *sm, const SSL_METHOD *cm, int min_proto_version, int max_proto_version, SSL_CTX **sctx, SSL_CTX **cctx, @@ -60,4 +66,6 @@ typedef struct mempacket_st MEMPACKET; DEFINE_STACK_OF(MEMPACKET) +SSL_SESSION *create_a_psk(SSL *ssl, size_t mdsize); + #endif /* OSSL_TEST_SSLTESTLIB_H */ diff --git a/test/pkcs12_format_test.c b/test/pkcs12_format_test.c index 507a9baf07475f99a254e8eab48524468363e10a..e2048bc27e75b8cd047864013422f2108c56b805 100644 --- a/test/pkcs12_format_test.c +++ b/test/pkcs12_format_test.c @@ -882,6 +882,70 @@ err: } #endif +static int pkcs12_recreate_test(void) +{ + int ret = 0; + X509 *cert = NULL; + X509 *cert_parsed = NULL; + EVP_PKEY *pkey = NULL; + EVP_PKEY *pkey_parsed = NULL; + PKCS12 *p12 = NULL; + PKCS12 *p12_parsed = NULL; + PKCS12 *p12_recreated = NULL; + const unsigned char *cert_bytes = CERT1; + const unsigned char *key_bytes = KEY1; + BIO *bio = NULL; + + cert = d2i_X509(NULL, &cert_bytes, sizeof(CERT1)); + if (!TEST_ptr(cert)) + goto err; + pkey = d2i_AutoPrivateKey(NULL, &key_bytes, sizeof(KEY1)); + if (!TEST_ptr(pkey)) + goto err; + p12 = PKCS12_create("pass", NULL, pkey, cert, NULL, NID_aes_256_cbc, + NID_aes_256_cbc, 2, 1, 0); + if (!TEST_ptr(p12)) + goto err; + if (!TEST_int_eq(ERR_peek_error(), 0)) + goto err; + + bio = BIO_new(BIO_s_mem()); + if (!TEST_ptr(bio)) + goto err; + if (!TEST_int_eq(i2d_PKCS12_bio(bio, p12), 1)) + goto err; + p12_parsed = PKCS12_init_ex(NID_pkcs7_data, testctx, NULL); + if (!TEST_ptr(p12_parsed)) + goto err; + p12_parsed = d2i_PKCS12_bio(bio, &p12_parsed); + if (!TEST_ptr(p12_parsed)) + goto err; + if (!TEST_int_eq(PKCS12_parse(p12_parsed, "pass", &pkey_parsed, + &cert_parsed, NULL), 1)) + goto err; + + /* cert_parsed also contains auxiliary data */ + p12_recreated = PKCS12_create("new_pass", NULL, pkey_parsed, cert_parsed, + NULL, NID_aes_256_cbc, NID_aes_256_cbc, + 2, 1, 0); + if (!TEST_ptr(p12_recreated)) + goto err; + if (!TEST_int_eq(ERR_peek_error(), 0)) + goto err; + + ret = 1; +err: + BIO_free(bio); + PKCS12_free(p12); + PKCS12_free(p12_parsed); + PKCS12_free(p12_recreated); + EVP_PKEY_free(pkey); + EVP_PKEY_free(pkey_parsed); + X509_free(cert); + X509_free(cert_parsed); + return ret; +} + typedef enum OPTION_choice { OPT_ERR = -1, OPT_EOF = 0, @@ -963,6 +1027,8 @@ int setup_tests(void) if (default_libctx) ADD_TEST(pkcs12_create_test); #endif + if (default_libctx) + ADD_TEST(pkcs12_recreate_test); ADD_ALL_TESTS(test_single_key_enc_pass, OSSL_NELEM(passwords)); ADD_ALL_TESTS(test_single_key_enc_iter, OSSL_NELEM(iters)); ADD_TEST(test_single_key_with_attrs); diff --git a/test/provider_pkey_test.c b/test/provider_pkey_test.c index 7e69f4bbd50b0faae07f6323cbce8db094c35828..7d5fcfa647e78948bbb18408aa389f1e15f3a564 100644 --- a/test/provider_pkey_test.c +++ b/test/provider_pkey_test.c @@ -14,10 +14,12 @@ #include #include #include +#include #include "testutil.h" #include "fake_rsaprov.h" static OSSL_LIB_CTX *libctx = NULL; +extern int key_deleted; /* From fake_rsaprov.c */ /* Fetch SIGNATURE method using a libctx and propq */ static int fetch_sig(OSSL_LIB_CTX *ctx, const char *alg, const char *propq, @@ -288,6 +290,140 @@ end: return ret; } +static int test_pkey_delete(void) +{ + OSSL_PROVIDER *deflt = NULL; + OSSL_PROVIDER *fake_rsa = NULL; + int ret = 0; + EVP_PKEY *pkey = NULL; + OSSL_STORE_LOADER *loader = NULL; + OSSL_STORE_CTX *ctx = NULL; + OSSL_STORE_INFO *info; + const char *propq = "?provider=fake-rsa"; + + /* It's important to load the default provider first for this test */ + if (!TEST_ptr(deflt = OSSL_PROVIDER_load(libctx, "default"))) + goto end; + + if (!TEST_ptr(fake_rsa = fake_rsa_start(libctx))) + goto end; + + if (!TEST_ptr(loader = OSSL_STORE_LOADER_fetch(libctx, "fake_rsa", + propq))) + goto end; + + OSSL_STORE_LOADER_free(loader); + + /* First iteration: load key, check it, delete it */ + if (!TEST_ptr(ctx = OSSL_STORE_open_ex("fake_rsa:test", libctx, propq, + NULL, NULL, NULL, NULL, NULL))) + goto end; + + while (!OSSL_STORE_eof(ctx) + && (info = OSSL_STORE_load(ctx)) != NULL + && pkey == NULL) { + if (OSSL_STORE_INFO_get_type(info) == OSSL_STORE_INFO_PKEY) + pkey = OSSL_STORE_INFO_get1_PKEY(info); + OSSL_STORE_INFO_free(info); + info = NULL; + } + + if (!TEST_ptr(pkey) || !TEST_int_eq(EVP_PKEY_is_a(pkey, "RSA"), 1)) + goto end; + EVP_PKEY_free(pkey); + pkey = NULL; + + if (!TEST_int_eq(OSSL_STORE_delete("fake_rsa:test", libctx, propq, + NULL, NULL, NULL), 1)) + goto end; + if (!TEST_int_eq(OSSL_STORE_close(ctx), 1)) + goto end; + + /* Second iteration: load key should fail */ + if (!TEST_ptr(ctx = OSSL_STORE_open_ex("fake_rsa:test", libctx, propq, + NULL, NULL, NULL, NULL, NULL))) + goto end; + + while (!OSSL_STORE_eof(ctx)) { + info = OSSL_STORE_load(ctx); + if (!TEST_ptr_null(info)) + goto end; + } + + ret = 1; + +end: + fake_rsa_finish(fake_rsa); + OSSL_PROVIDER_unload(deflt); + OSSL_STORE_close(ctx); + fake_rsa_restore_store_state(); + return ret; +} + +static int fake_pw_read_string(UI *ui, UI_STRING *uis) +{ + const char *passphrase = FAKE_PASSPHRASE; + + if (UI_get_string_type(uis) == UIT_PROMPT) { + UI_set_result(ui, uis, passphrase); + return 1; + } + + return 0; +} + +static int test_pkey_store_open_ex(void) +{ + OSSL_PROVIDER *deflt = NULL; + OSSL_PROVIDER *fake_rsa = NULL; + int ret = 0; + EVP_PKEY *pkey = NULL; + OSSL_STORE_LOADER *loader = NULL; + OSSL_STORE_CTX *ctx = NULL; + const char *propq = "?provider=fake-rsa"; + UI_METHOD *ui_method = NULL; + + /* It's important to load the default provider first for this test */ + if (!TEST_ptr(deflt = OSSL_PROVIDER_load(libctx, "default"))) + goto end; + + if (!TEST_ptr(fake_rsa = fake_rsa_start(libctx))) + goto end; + + if (!TEST_ptr(loader = OSSL_STORE_LOADER_fetch(libctx, "fake_rsa", + propq))) + goto end; + + OSSL_STORE_LOADER_free(loader); + + if (!TEST_ptr(ui_method= UI_create_method("PW Callbacks"))) + goto end; + + if (UI_method_set_reader(ui_method, fake_pw_read_string)) + goto end; + + if (!TEST_ptr(ctx = OSSL_STORE_open_ex("fake_rsa:openpwtest", libctx, propq, + ui_method, NULL, NULL, NULL, NULL))) + goto end; + + /* retry w/o ui_method to ensure we actually enter pw checks and fail */ + OSSL_STORE_close(ctx); + if (!TEST_ptr_null(ctx = OSSL_STORE_open_ex("fake_rsa:openpwtest", libctx, + propq, NULL, NULL, NULL, NULL, + NULL))) + goto end; + + ret = 1; + +end: + UI_destroy_method(ui_method); + fake_rsa_finish(fake_rsa); + OSSL_PROVIDER_unload(deflt); + OSSL_STORE_close(ctx); + EVP_PKEY_free(pkey); + return ret; +} + int setup_tests(void) { libctx = OSSL_LIB_CTX_new(); @@ -298,6 +434,8 @@ int setup_tests(void) ADD_TEST(test_alternative_keygen_init); ADD_TEST(test_pkey_eq); ADD_ALL_TESTS(test_pkey_store, 2); + ADD_TEST(test_pkey_delete); + ADD_TEST(test_pkey_store_open_ex); return 1; } diff --git a/test/quic_multistream_test.c b/test/quic_multistream_test.c index bc0ae12cdb17ea09ca1da79833e40abfc16395b8..2ad4ef292e2d8ab60bc4693ef74289e03713d794 100644 --- a/test/quic_multistream_test.c +++ b/test/quic_multistream_test.c @@ -746,10 +746,8 @@ static int helper_init(struct helper *h, int free_order, int blocking, BIO_set_data(h->s_qtf_wbio, h->qtf); } - if (!need_injector) - h->s_net_bio_own = NULL; - - h->s_qtf_wbio_own = NULL; + h->s_net_bio_own = NULL; + h->s_qtf_wbio_own = NULL; h->c_fd = BIO_socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP, 0); if (!TEST_int_ge(h->c_fd, 0)) @@ -4329,7 +4327,7 @@ static int script_61_inject_plain(struct helper *h, QUIC_PKT_HDR *hdr, || !TEST_true(WPACKET_quic_write_vlint(&wpkt, /* stream ID */ h->inject_word1)) || !TEST_true(WPACKET_quic_write_vlint(&wpkt, 123)) - || (h->inject_word1 == OSSL_QUIC_FRAME_TYPE_RESET_STREAM + || (h->inject_word0 == OSSL_QUIC_FRAME_TYPE_RESET_STREAM && !TEST_true(WPACKET_quic_write_vlint(&wpkt, 0)))) /* final size */ goto err; diff --git a/test/quic_newcid_test.c b/test/quic_newcid_test.c index cda55abca3cd3c6292bb1cebba99a42846b51f76..80a15e1b7ab0f66f218281dc5b3ac79b712ad75f 100644 --- a/test/quic_newcid_test.c +++ b/test/quic_newcid_test.c @@ -68,7 +68,7 @@ static int test_ncid_frame(int fail) goto err; if (!TEST_true(qtest_create_quic_objects(NULL, cctx, NULL, cert, privkey, 0, - &qtserv, &cssl, &fault))) + &qtserv, &cssl, &fault, NULL))) goto err; if (!TEST_true(qtest_create_quic_connection(qtserv, cssl))) diff --git a/test/quic_tserver_test.c b/test/quic_tserver_test.c index 3d1249863b2ae1b43e339cecdefc3c65d16ebc37..980c9a83ff0acee7ace72709fb5a1768c6dbacb4 100644 --- a/test/quic_tserver_test.c +++ b/test/quic_tserver_test.c @@ -312,7 +312,7 @@ static int do_test(int use_thread_assist, int use_fake_time, int use_inject) ++idle_units_done; ossl_quic_conn_force_assist_thread_wake(c_ssl); - OSSL_sleep(1); /* Ensure CPU scheduling for test purposes */ + OSSL_sleep(100); /* Ensure CPU scheduling for test purposes */ } else { c_done_idle_test = 1; } diff --git a/test/quicapitest.c b/test/quicapitest.c index 87c134eb88bf36527282f3443844984cfe674465..b02db15d65cbc07febe8e3c3cce06523c90ae8b6 100644 --- a/test/quicapitest.c +++ b/test/quicapitest.c @@ -69,7 +69,7 @@ static int test_quic_write_read(int idx) ? QTEST_FLAG_BLOCK : 0, &qtserv, &clientquic, - NULL)) + NULL, NULL)) || !TEST_true(SSL_set_tlsext_host_name(clientquic, "localhost"))) goto end; @@ -220,7 +220,7 @@ static int test_fin_only_blocking(void) cert, privkey, QTEST_FLAG_BLOCK, &qtserv, &clientquic, - NULL)) + NULL, NULL)) || !TEST_true(SSL_set_tlsext_host_name(clientquic, "localhost"))) goto end; @@ -321,6 +321,49 @@ static int test_ciphersuites(void) return testresult; } +static int test_cipher_find(void) +{ + SSL_CTX *cctx = SSL_CTX_new_ex(libctx, NULL, OSSL_QUIC_client_method()); + SSL *clientquic = NULL; + struct { + const unsigned char *cipherbytes; + int ok; + } testciphers[] = { + { TLS13_AES_128_GCM_SHA256_BYTES, 1 }, + { TLS13_AES_256_GCM_SHA384_BYTES, 1 }, + { TLS13_CHACHA20_POLY1305_SHA256_BYTES, 1 }, + { TLS13_AES_128_CCM_SHA256_BYTES, 0 }, + { TLS13_AES_128_CCM_8_SHA256_BYTES, 0 } + }; + size_t i; + int testresult = 0; + + if (!TEST_ptr(cctx)) + goto err; + + clientquic = SSL_new(cctx); + if (!TEST_ptr(clientquic)) + goto err; + + for (i = 0; i < OSSL_NELEM(testciphers); i++) + if (testciphers[i].ok) { + if (!TEST_ptr(SSL_CIPHER_find(clientquic, + testciphers[i].cipherbytes))) + goto err; + } else { + if (!TEST_ptr_null(SSL_CIPHER_find(clientquic, + testciphers[i].cipherbytes))) + goto err; + } + + testresult = 1; + err: + SSL_free(clientquic); + SSL_CTX_free(cctx); + + return testresult; +} + /* * Test that SSL_version, SSL_get_version, SSL_is_quic, SSL_is_tls and * SSL_is_dtls return the expected results for a QUIC connection. Compare with @@ -337,7 +380,7 @@ static int test_version(void) if (!TEST_ptr(cctx) || !TEST_true(qtest_create_quic_objects(libctx, cctx, NULL, cert, privkey, 0, &qtserv, - &clientquic, NULL)) + &clientquic, NULL, NULL)) || !TEST_true(qtest_create_quic_connection(qtserv, clientquic))) goto err; @@ -459,7 +502,7 @@ static int test_ssl_trace(void) privkey, QTEST_FLAG_FAKE_TIME, &qtserv, - &clientquic, NULL))) + &clientquic, NULL, NULL))) goto err; SSL_set_msg_callback(clientquic, SSL_trace); @@ -786,7 +829,8 @@ static int test_bio_ssl(void) goto err; if (!TEST_true(qtest_create_quic_objects(libctx, NULL, NULL, cert, privkey, - 0, &qtserv, &clientquic, NULL))) + 0, &qtserv, &clientquic, NULL, + NULL))) goto err; msglen = strlen(msg); @@ -903,7 +947,7 @@ static int test_back_pressure(void) if (!TEST_ptr(cctx) || !TEST_true(qtest_create_quic_objects(libctx, cctx, NULL, cert, privkey, 0, &qtserv, - &clientquic, NULL)) + &clientquic, NULL, NULL)) || !TEST_true(qtest_create_quic_connection(qtserv, clientquic))) goto err; @@ -981,7 +1025,7 @@ static int test_multiple_dgrams(void) || !TEST_ptr(buf) || !TEST_true(qtest_create_quic_objects(libctx, cctx, NULL, cert, privkey, 0, &qtserv, - &clientquic, NULL)) + &clientquic, NULL, NULL)) || !TEST_true(qtest_create_quic_connection(qtserv, clientquic))) goto err; @@ -1045,7 +1089,8 @@ static int test_non_io_retry(int idx) flags = (idx >= 1) ? QTEST_FLAG_BLOCK : 0; if (!TEST_true(qtest_create_quic_objects(libctx, cctx, NULL, cert, privkey, - flags, &qtserv, &clientquic, NULL)) + flags, &qtserv, &clientquic, NULL, + NULL)) || !TEST_true(qtest_create_quic_connection_ex(qtserv, clientquic, SSL_ERROR_WANT_RETRY_VERIFY)) || !TEST_int_eq(SSL_want(clientquic), SSL_RETRY_VERIFY) @@ -1061,6 +1106,314 @@ static int test_non_io_retry(int idx) return testresult; } +static int use_session_cb_cnt = 0; +static int find_session_cb_cnt = 0; +static const char *pskid = "Identity"; +static SSL_SESSION *serverpsk = NULL, *clientpsk = NULL; + +static int use_session_cb(SSL *ssl, const EVP_MD *md, const unsigned char **id, + size_t *idlen, SSL_SESSION **sess) +{ + use_session_cb_cnt++; + + if (clientpsk == NULL) + return 0; + + SSL_SESSION_up_ref(clientpsk); + + *sess = clientpsk; + *id = (const unsigned char *)pskid; + *idlen = strlen(pskid); + + return 1; +} + +static int find_session_cb(SSL *ssl, const unsigned char *identity, + size_t identity_len, SSL_SESSION **sess) +{ + find_session_cb_cnt++; + + if (serverpsk == NULL) + return 0; + + /* Identity should match that set by the client */ + if (strlen(pskid) != identity_len + || strncmp(pskid, (const char *)identity, identity_len) != 0) + return 0; + + SSL_SESSION_up_ref(serverpsk); + *sess = serverpsk; + + return 1; +} + +static int test_quic_psk(void) +{ + SSL_CTX *cctx = SSL_CTX_new_ex(libctx, NULL, OSSL_QUIC_client_method()); + SSL *clientquic = NULL; + QUIC_TSERVER *qtserv = NULL; + int testresult = 0; + + if (!TEST_ptr(cctx) + /* No cert or private key for the server, i.e. PSK only */ + || !TEST_true(qtest_create_quic_objects(libctx, cctx, NULL, NULL, + NULL, 0, &qtserv, + &clientquic, NULL, NULL))) + goto end; + + SSL_set_psk_use_session_callback(clientquic, use_session_cb); + ossl_quic_tserver_set_psk_find_session_cb(qtserv, find_session_cb); + use_session_cb_cnt = 0; + find_session_cb_cnt = 0; + + clientpsk = serverpsk = create_a_psk(clientquic, SHA384_DIGEST_LENGTH); + if (!TEST_ptr(clientpsk)) + goto end; + /* We already had one ref. Add another one */ + SSL_SESSION_up_ref(clientpsk); + + if (!TEST_true(qtest_create_quic_connection(qtserv, clientquic)) + || !TEST_int_eq(1, find_session_cb_cnt) + || !TEST_int_eq(1, use_session_cb_cnt) + /* Check that we actually used the PSK */ + || !TEST_true(SSL_session_reused(clientquic))) + goto end; + + testresult = 1; + + end: + SSL_free(clientquic); + ossl_quic_tserver_free(qtserv); + SSL_CTX_free(cctx); + SSL_SESSION_free(clientpsk); + SSL_SESSION_free(serverpsk); + clientpsk = serverpsk = NULL; + + return testresult; +} + +/* + * Test that we correctly handle ALPN supplied by the application + * Test 0: ALPN is provided + * Test 1: No ALPN is provided + */ +static int test_alpn(int idx) +{ + SSL_CTX *cctx = SSL_CTX_new_ex(libctx, NULL, OSSL_QUIC_client_method()); + SSL *clientquic = NULL; + QUIC_TSERVER *qtserv = NULL; + int testresult = 0; + int ret; + + /* + * Ensure we only configure ciphersuites that are available with both the + * default and fips providers to get the same output in both cases + */ + if (!TEST_true(SSL_CTX_set_ciphersuites(cctx, "TLS_AES_128_GCM_SHA256"))) + goto err; + + if (!TEST_ptr(cctx) + || !TEST_true(qtest_create_quic_objects(libctx, cctx, NULL, cert, + privkey, + QTEST_FLAG_FAKE_TIME, + &qtserv, + &clientquic, NULL, NULL))) + goto err; + + if (idx == 0) { + /* + * Clear the ALPN we set in qtest_create_quic_objects. We use TEST_false + * because SSL_set_alpn_protos returns 0 for success. + */ + if (!TEST_false(SSL_set_alpn_protos(clientquic, NULL, 0))) + goto err; + } + + ret = SSL_connect(clientquic); + if (!TEST_int_le(ret, 0)) + goto err; + if (idx == 0) { + /* We expect an immediate error due to lack of ALPN */ + if (!TEST_int_eq(SSL_get_error(clientquic, ret), SSL_ERROR_SSL)) + goto err; + } else { + /* ALPN was provided so we expect the connection to succeed */ + if (!TEST_int_eq(SSL_get_error(clientquic, ret), SSL_ERROR_WANT_READ) + || !TEST_true(qtest_create_quic_connection(qtserv, clientquic))) + goto err; + } + + testresult = 1; + err: + ossl_quic_tserver_free(qtserv); + SSL_free(clientquic); + SSL_CTX_free(cctx); + + return testresult; +} + +#define MAX_LOOPS 2000 + +/* + * Keep retrying SSL_read_ex until it succeeds or we give up. Accept a stream + * if we don't already have one + */ +static int unreliable_client_read(SSL *clientquic, SSL **stream, void *buf, + size_t buflen, size_t *readbytes, + QUIC_TSERVER *qtserv) +{ + int abortctr; + + /* We just do this in a loop with a sleep for simplicity */ + for (abortctr = 0; abortctr < MAX_LOOPS; abortctr++) { + if (*stream == NULL) { + SSL_handle_events(clientquic); + *stream = SSL_accept_stream(clientquic, 0); + } + + if (*stream != NULL) { + if (SSL_read_ex(*stream, buf, buflen, readbytes)) + return 1; + if (!TEST_int_eq(SSL_get_error(*stream, 0), SSL_ERROR_WANT_READ)) + return 0; + } + ossl_quic_tserver_tick(qtserv); + qtest_add_time(1); + qtest_wait_for_timeout(clientquic, qtserv); + } + + TEST_error("No progress made"); + return 0; +} + +/* Keep retrying ossl_quic_tserver_read until it succeeds or we give up */ +static int unreliable_server_read(QUIC_TSERVER *qtserv, uint64_t sid, + void *buf, size_t buflen, size_t *readbytes, + SSL *clientquic) +{ + int abortctr; + + /* We just do this in a loop with a sleep for simplicity */ + for (abortctr = 0; abortctr < MAX_LOOPS; abortctr++) { + if (ossl_quic_tserver_read(qtserv, sid, buf, buflen, readbytes) + && *readbytes > 1) + return 1; + ossl_quic_tserver_tick(qtserv); + SSL_handle_events(clientquic); + qtest_add_time(1); + qtest_wait_for_timeout(clientquic, qtserv); + } + + TEST_error("No progress made"); + return 0; +} + +/* + * Create a connection and send data using an unreliable transport. We introduce + * random noise to drop, delay and duplicate datagrams. + * Test 0: Introduce random noise to datagrams + * Test 1: As with test 0 but also split datagrams containing multiple packets + * into individual datagrams so that individual packets can be affected + * by noise - not just a whole datagram. + */ +static int test_noisy_dgram(int idx) +{ + SSL_CTX *cctx = SSL_CTX_new_ex(libctx, NULL, OSSL_QUIC_client_method()); + SSL *clientquic = NULL, *stream[2] = { NULL, NULL }; + QUIC_TSERVER *qtserv = NULL; + int testresult = 0; + uint64_t sid = 0; + char *msg = "Hello world!"; + size_t msglen = strlen(msg), written, readbytes, i, j; + unsigned char buf[80]; + int flags = QTEST_FLAG_NOISE | QTEST_FLAG_FAKE_TIME; + + if (idx == 1) + flags |= QTEST_FLAG_PACKET_SPLIT; + + if (!TEST_ptr(cctx) + || !TEST_true(qtest_create_quic_objects(libctx, cctx, NULL, cert, + privkey, flags, + &qtserv, + &clientquic, NULL, NULL))) + goto err; + + if (!TEST_true(qtest_create_quic_connection(qtserv, clientquic))) + goto err; + + if (!TEST_true(SSL_set_incoming_stream_policy(clientquic, + SSL_INCOMING_STREAM_POLICY_ACCEPT, + 0)) + || !TEST_true(SSL_set_default_stream_mode(clientquic, + SSL_DEFAULT_STREAM_MODE_NONE))) + goto err; + + for (j = 0; j < 2; j++) { + if (!TEST_true(ossl_quic_tserver_stream_new(qtserv, 0, &sid))) + goto err; + ossl_quic_tserver_tick(qtserv); + qtest_add_time(1); + + /* + * Send data from the server to the client. Some datagrams may get lost, + * dropped or re-ordered. We repeat 10 times to ensure we are sending + * enough datagrams for problems to be noticed. + */ + for (i = 0; i < 10; i++) { + if (!TEST_true(ossl_quic_tserver_write(qtserv, sid, + (unsigned char *)msg, msglen, + &written)) + || !TEST_size_t_eq(msglen, written)) + goto err; + ossl_quic_tserver_tick(qtserv); + qtest_add_time(1); + + /* + * Since the underlying BIO is now noisy we may get failures that + * need to be retried - so we use unreliable_client_read() to handle + * that + */ + if (!TEST_true(unreliable_client_read(clientquic, &stream[j], buf, + sizeof(buf), &readbytes, + qtserv)) + || !TEST_mem_eq(msg, msglen, buf, readbytes)) + goto err; + } + + /* Send data from the client to the server */ + for (i = 0; i < 10; i++) { + if (!TEST_true(SSL_write_ex(stream[j], (unsigned char *)msg, + msglen, &written)) + || !TEST_size_t_eq(msglen, written)) + goto err; + + ossl_quic_tserver_tick(qtserv); + qtest_add_time(1); + + /* + * Since the underlying BIO is now noisy we may get failures that + * need to be retried - so we use unreliable_server_read() to handle + * that + */ + if (!TEST_true(unreliable_server_read(qtserv, sid, buf, sizeof(buf), + &readbytes, clientquic)) + || !TEST_mem_eq(msg, msglen, buf, readbytes)) + goto err; + } + } + + testresult = 1; + err: + ossl_quic_tserver_free(qtserv); + SSL_free(stream[0]); + SSL_free(stream[1]); + SSL_free(clientquic); + SSL_CTX_free(cctx); + + return testresult; +} + + OPT_TEST_DECLARE_USAGE("provider config certsdir datadir\n") int setup_tests(void) @@ -1119,6 +1472,7 @@ int setup_tests(void) ADD_ALL_TESTS(test_quic_write_read, 3); ADD_TEST(test_fin_only_blocking); ADD_TEST(test_ciphersuites); + ADD_TEST(test_cipher_find); ADD_TEST(test_version); #if defined(DO_SSL_TRACE_TEST) ADD_TEST(test_ssl_trace); @@ -1131,6 +1485,10 @@ int setup_tests(void) ADD_TEST(test_back_pressure); ADD_TEST(test_multiple_dgrams); ADD_ALL_TESTS(test_non_io_retry, 2); + ADD_TEST(test_quic_psk); + ADD_ALL_TESTS(test_alpn, 2); + ADD_ALL_TESTS(test_noisy_dgram, 2); + return 1; err: cleanup_tests(); @@ -1139,6 +1497,8 @@ int setup_tests(void) void cleanup_tests(void) { + bio_f_noisy_dgram_filter_free(); + bio_f_pkt_split_dgram_filter_free(); OPENSSL_free(cert); OPENSSL_free(privkey); OSSL_PROVIDER_unload(defctxnull); diff --git a/test/quicfaultstest.c b/test/quicfaultstest.c index 3b80385584b6539361c94edbe5d192788dc5e4da..28f52cd6f22a26c923c0363dd1d56cfe4cfbf27c 100644 --- a/test/quicfaultstest.c +++ b/test/quicfaultstest.c @@ -35,7 +35,7 @@ static int test_basic(void) goto err; if (!TEST_true(qtest_create_quic_objects(NULL, cctx, NULL, cert, privkey, 0, - &qtserv, &cssl, NULL))) + &qtserv, &cssl, NULL, NULL))) goto err; if (!TEST_true(qtest_create_quic_connection(qtserv, cssl))) @@ -105,7 +105,7 @@ static int test_unknown_frame(void) goto err; if (!TEST_true(qtest_create_quic_objects(NULL, cctx, NULL, cert, privkey, 0, - &qtserv, &cssl, &fault))) + &qtserv, &cssl, &fault, NULL))) goto err; if (!TEST_true(qtest_create_quic_connection(qtserv, cssl))) @@ -161,36 +161,46 @@ static int test_unknown_frame(void) * Test that a server that fails to provide transport params cannot be * connected to. */ -static int drop_transport_params_cb(QTEST_FAULT *fault, +static int drop_extensions_cb(QTEST_FAULT *fault, QTEST_ENCRYPTED_EXTENSIONS *ee, size_t eelen, void *encextcbarg) { - if (!qtest_fault_delete_extension(fault, - TLSEXT_TYPE_quic_transport_parameters, - ee->extensions, &ee->extensionslen)) + int *ext = (int *)encextcbarg; + + if (!qtest_fault_delete_extension(fault, *ext, ee->extensions, + &ee->extensionslen)) return 0; return 1; } -static int test_no_transport_params(void) +static int test_drop_extensions(int idx) { int testresult = 0; SSL_CTX *cctx = SSL_CTX_new(OSSL_QUIC_client_method()); QUIC_TSERVER *qtserv = NULL; SSL *cssl = NULL; QTEST_FAULT *fault = NULL; + int ext, err; if (!TEST_ptr(cctx)) goto err; if (!TEST_true(qtest_create_quic_objects(NULL, cctx, NULL, cert, privkey, 0, - &qtserv, &cssl, &fault))) + &qtserv, &cssl, &fault, NULL))) goto err; + if (idx == 0) { + ext = TLSEXT_TYPE_quic_transport_parameters; + err = QUIC_ERR_CRYPTO_MISSING_EXT; + } else { + ext = TLSEXT_TYPE_application_layer_protocol_negotiation; + err = QUIC_ERR_CRYPTO_NO_APP_PROTO; + } + if (!TEST_true(qtest_fault_set_hand_enc_ext_listener(fault, - drop_transport_params_cb, - NULL))) + drop_extensions_cb, + &ext))) goto err; /* @@ -200,8 +210,7 @@ static int test_no_transport_params(void) if (!TEST_false(qtest_create_quic_connection(qtserv, cssl))) goto err; - if (!TEST_true(qtest_check_server_transport_err(qtserv, - QUIC_ERR_CRYPTO_MISSING_EXT))) + if (!TEST_true(qtest_check_server_transport_err(qtserv, err))) goto err; testresult = 1; @@ -266,7 +275,7 @@ static int test_corrupted_data(int idx) if (!TEST_true(qtest_create_quic_objects(NULL, cctx, NULL, cert, privkey, QTEST_FLAG_FAKE_TIME, &qtserv, - &cssl, &fault))) + &cssl, &fault, NULL))) goto err; if (idx == 0) { @@ -384,7 +393,7 @@ int setup_tests(void) ADD_TEST(test_basic); ADD_TEST(test_unknown_frame); - ADD_TEST(test_no_transport_params); + ADD_ALL_TESTS(test_drop_extensions, 2); ADD_ALL_TESTS(test_corrupted_data, 2); return 1; diff --git a/test/recipes/80-test_cms.t b/test/recipes/80-test_cms.t index 21c683c4046a7fc75585fc3c6684bff10f8fbe68..385791610577e1a9a315769a034a25e4cf1996bb 100644 --- a/test/recipes/80-test_cms.t +++ b/test/recipes/80-test_cms.t @@ -1144,9 +1144,13 @@ with({ exit_checker => sub { return shift == 6; } }, # Test case for return value mis-check reported in #21986 with({ exit_checker => sub { return shift == 3; } }, sub { - ok(run(app(['openssl', 'cms', '-sign', - '-in', srctop_file("test", "smcont.txt"), - '-signer', srctop_file("test/smime-certs", "smdsa1.pem"), - '-md', 'SHAKE256'])), - "issue#21986"); + SKIP: { + skip "DSA is not supported in this build", 1 if $no_dsa; + + ok(run(app(['openssl', 'cms', '-sign', + '-in', srctop_file("test", "smcont.txt"), + '-signer', srctop_file("test/smime-certs", "smdsa1.pem"), + '-md', 'SHAKE256'])), + "issue#21986"); + } }); diff --git a/test/ssl_old_test.c b/test/ssl_old_test.c index 21834b1a36313c8f793d3797ca093f16dd11920f..fe168472d3022b1dfd2d5c75138ae69214259772 100644 --- a/test/ssl_old_test.c +++ b/test/ssl_old_test.c @@ -1535,8 +1535,10 @@ int main(int argc, char *argv[]) ERR_print_errors(bio_err); goto end; } - SSL_CTX_set0_tmp_dh_pkey(s_ctx, dhpkey); - SSL_CTX_set0_tmp_dh_pkey(s_ctx2, dhpkey); + if (!SSL_CTX_set0_tmp_dh_pkey(s_ctx, dhpkey)) + EVP_PKEY_free(dhpkey); + if (!SSL_CTX_set0_tmp_dh_pkey(s_ctx2, dhpkey)) + EVP_PKEY_free(dhpkey); } #endif diff --git a/test/sslapitest.c b/test/sslapitest.c index 756675c1dce6aa4ce7314ddafd9cef20985220db..9539b4cf3a658ac477b418fbe479974b30580cc5 100644 --- a/test/sslapitest.c +++ b/test/sslapitest.c @@ -77,8 +77,6 @@ static int find_session_cb(SSL *ssl, const unsigned char *identity, static int use_session_cb_cnt = 0; static int find_session_cb_cnt = 0; - -static SSL_SESSION *create_a_psk(SSL *ssl, size_t mdsize); #endif static char *certsdir = NULL; @@ -3385,51 +3383,6 @@ static unsigned int psk_server_cb(SSL *ssl, const char *identity, #define MSG6 "test" #define MSG7 "message." -#define TLS13_AES_128_GCM_SHA256_BYTES ((const unsigned char *)"\x13\x01") -#define TLS13_AES_256_GCM_SHA384_BYTES ((const unsigned char *)"\x13\x02") -#define TLS13_CHACHA20_POLY1305_SHA256_BYTES ((const unsigned char *)"\x13\x03") -#define TLS13_AES_128_CCM_SHA256_BYTES ((const unsigned char *)"\x13\x04") -#define TLS13_AES_128_CCM_8_SHA256_BYTES ((const unsigned char *)"\x13\05") - - -static SSL_SESSION *create_a_psk(SSL *ssl, size_t mdsize) -{ - const SSL_CIPHER *cipher = NULL; - const unsigned char key[] = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, - 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, - 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, - 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, - 0x2c, 0x2d, 0x2e, 0x2f /* SHA384_DIGEST_LENGTH bytes */ - }; - SSL_SESSION *sess = NULL; - - if (mdsize == SHA384_DIGEST_LENGTH) { - cipher = SSL_CIPHER_find(ssl, TLS13_AES_256_GCM_SHA384_BYTES); - } else if (mdsize == SHA256_DIGEST_LENGTH) { - /* - * Any ciphersuite using SHA256 will do - it will be compatible with - * the actual ciphersuite selected as long as it too is based on SHA256 - */ - cipher = SSL_CIPHER_find(ssl, TLS13_AES_128_GCM_SHA256_BYTES); - } else { - /* Should not happen */ - return NULL; - } - sess = SSL_SESSION_new(); - if (!TEST_ptr(sess) - || !TEST_ptr(cipher) - || !TEST_true(SSL_SESSION_set1_master_key(sess, key, mdsize)) - || !TEST_true(SSL_SESSION_set_cipher(sess, cipher)) - || !TEST_true( - SSL_SESSION_set_protocol_version(sess, - TLS1_3_VERSION))) { - SSL_SESSION_free(sess); - return NULL; - } - return sess; -} - static int artificial_ticket_time = 0; static int ed_gen_cb(SSL *s, void *arg) @@ -6648,7 +6601,9 @@ static int test_key_update_peer_in_write(int tst) /* Write data that we know will fail with SSL_ERROR_WANT_WRITE */ if (!TEST_int_eq(SSL_write(peerwrite, mess, strlen(mess)), -1) - || !TEST_int_eq(SSL_get_error(peerwrite, 0), SSL_ERROR_WANT_WRITE)) + || !TEST_int_eq(SSL_get_error(peerwrite, 0), SSL_ERROR_WANT_WRITE) + || !TEST_true(SSL_want_write(peerwrite)) + || !TEST_true(SSL_net_write_desired(peerwrite))) goto end; /* Reinstate the original writing endpoint's write BIO */ @@ -6657,7 +6612,9 @@ static int test_key_update_peer_in_write(int tst) /* Now read some data - we will read the key update */ if (!TEST_int_eq(SSL_read(peerwrite, buf, sizeof(buf)), -1) - || !TEST_int_eq(SSL_get_error(peerwrite, 0), SSL_ERROR_WANT_READ)) + || !TEST_int_eq(SSL_get_error(peerwrite, 0), SSL_ERROR_WANT_READ) + || !TEST_true(SSL_want_read(peerwrite)) + || !TEST_true(SSL_net_read_desired(peerwrite))) goto end; /* @@ -6673,6 +6630,11 @@ static int test_key_update_peer_in_write(int tst) || !TEST_int_eq(SSL_read(peerupdate, buf, sizeof(buf)), strlen(mess))) goto end; + if (!TEST_false(SSL_net_read_desired(peerwrite)) + || !TEST_false(SSL_net_write_desired(peerwrite)) + || !TEST_int_eq(SSL_want(peerwrite), SSL_NOTHING)) + goto end; + testresult = 1; end: diff --git a/test/testutil/driver.c b/test/testutil/driver.c index 6427d235af20e919bfe1fcc6880d2425b86abae3..033be2fcc5e0eb59281a380b9e0a483b5504ee2a 100644 --- a/test/testutil/driver.c +++ b/test/testutil/driver.c @@ -102,15 +102,18 @@ static void set_seed(int s) int setup_test_framework(int argc, char *argv[]) { - char *test_seed = getenv("OPENSSL_TEST_RAND_ORDER"); + char *test_rand_order = getenv("OPENSSL_TEST_RAND_ORDER"); + char *test_rand_seed = getenv("OPENSSL_TEST_RAND_SEED"); char *TAP_levels = getenv("HARNESS_OSSL_LEVEL"); if (TAP_levels != NULL) level = 4 * atoi(TAP_levels); test_adjust_streams_tap_level(level); - if (test_seed != NULL) { + if (test_rand_order != NULL) { rand_order = 1; - set_seed(atoi(test_seed)); + set_seed(atoi(test_rand_order)); + } else if (test_rand_seed != NULL) { + set_seed(atoi(test_rand_seed)); } else { set_seed(0); } @@ -264,8 +267,12 @@ PRINTF_FORMAT(2, 3) static void test_verdict(int verdict, test_flush_stdout(); test_flush_stderr(); - if (verdict == 0 && seed != 0) - test_printf_tapout("# OPENSSL_TEST_RAND_ORDER=%d\n", seed); + if (verdict == 0) { + if (rand_order) + test_printf_tapout("# OPENSSL_TEST_RAND_ORDER=%d\n", seed); + else + test_printf_tapout("# OPENSSL_TEST_RAND_SEED=%d\n", seed); + } test_printf_tapout("%s ", verdict != 0 ? "ok" : "not ok"); va_start(ap, description); test_vprintf_tapout(description, ap); diff --git a/test/testutil/tests.c b/test/testutil/tests.c index 50d4e12e054d72ea31fd3ced8b05111c39ec73e4..efc4fd2b649a7910a13c453c6d899335dffa057f 100644 --- a/test/testutil/tests.c +++ b/test/testutil/tests.c @@ -18,7 +18,7 @@ /* * Output a failed test first line. - * All items are optional are generally not preinted if passed as NULL. + * All items are optional are generally not printed if passed as NULL. * The special cases are for prefix where "ERROR" is assumed and for left * and right where a non-failure message is produced if either is NULL. */ diff --git a/util/libcrypto.num b/util/libcrypto.num index 2656df5d908b92eefaa0386d220163595f615291..e4265b4cef0b66c4f76ac98f279d7f53d46741cf 100644 --- a/util/libcrypto.num +++ b/util/libcrypto.num @@ -5534,3 +5534,4 @@ OSSL_PROVIDER_try_load_ex ? 3_2_0 EXIST::FUNCTION: OSSL_ERR_STATE_save_to_mark ? 3_2_0 EXIST::FUNCTION: X509_STORE_CTX_set_get_crl ? 3_2_0 EXIST::FUNCTION: X509_STORE_CTX_set_current_reasons ? 3_2_0 EXIST::FUNCTION: +OSSL_STORE_delete ? 3_2_0 EXIST::FUNCTION: diff --git a/util/missingssl.txt b/util/missingssl.txt index 224eb84899f5bd265ba4d807b6c2758a8cccc275..1338feed71188983b0d60c4206a58aaff31a234d 100644 --- a/util/missingssl.txt +++ b/util/missingssl.txt @@ -3,7 +3,6 @@ ERR_load_SSL_strings(3) SRP_Calc_A_param(3) SSL_COMP_get_name(3) SSL_COMP_set0_compression_methods(3) -SSL_CONF_CTX_finish(3) SSL_CTX_SRP_CTX_free(3) SSL_CTX_SRP_CTX_init(3) SSL_CTX_get0_certificate(3)