.github/workflows/fips-old.yml | 74 ++++ .github/workflows/fuzz-checker.yml | 4 +- .github/workflows/run-checker-merge.yml | 2 +- .github/workflows/windows.yml | 6 +- Configurations/10-main.conf | 2 +- Configurations/50-djgpp.conf | 1 + Configure | 17 +- apps/ciphers.c | 7 + apps/dgst.c | 27 +- apps/dhparam.c | 6 +- apps/ecparam.c | 12 +- apps/genrsa.c | 3 +- apps/include/apps.h | 1 + apps/mac.c | 3 - apps/pkeyparam.c | 9 +- apps/rsa.c | 2 +- apps/speed.c | 20 +- crypto/armcap.c | 10 +- crypto/bio/bio_lib.c | 21 +- crypto/bn/bn_prime.c | 5 +- crypto/bn/bn_rand.c | 5 + crypto/cmp/cmp_msg.c | 15 +- crypto/cmp/cmp_util.c | 4 +- crypto/cms/cms_lib.c | 5 +- crypto/conf/conf_def.c | 2 +- crypto/conf/conf_sap.c | 4 + crypto/dh/dh_pmeth.c | 3 +- crypto/ec/ecx_meth.c | 16 +- crypto/evp/digest.c | 4 +- crypto/evp/evp_enc.c | 19 +- crypto/evp/evp_lib.c | 47 ++- crypto/evp/evp_local.h | 1 + crypto/evp/p_lib.c | 13 +- crypto/mem.c | 4 +- crypto/packet.c | 6 +- crypto/pkcs7/pk7_smime.c | 3 +- crypto/property/property.c | 14 +- crypto/stack/stack.c | 94 +++-- crypto/x509/x509_req.c | 74 +++- crypto/x509/x509_vfy.c | 24 +- crypto/x509/x509_vpm.c | 82 ++--- crypto/x509/x_all.c | 112 ++++-- demos/cipher/Makefile | 9 +- demos/cipher/aeskeywrap.c | 181 ++++++++++ demos/encode/Makefile | 20 ++ demos/encode/ec_encode.c | 205 +++++++++++ doc/build.info | 6 + doc/man1/openssl-cmp.pod.in | 13 +- doc/man1/openssl-dgst.pod.in | 15 +- doc/man1/openssl-mac.pod.in | 3 +- doc/man1/openssl-pkcs12.pod.in | 2 +- doc/man1/openssl.pod | 28 +- doc/man3/BIO_ctrl.pod | 7 +- doc/man3/BIO_f_ssl.pod | 9 +- doc/man3/BIO_s_accept.pod | 2 +- doc/man3/EVP_PBE_CipherInit.pod | 14 +- doc/man3/EVP_PKEY_CTX_set_hkdf_md.pod | 2 +- doc/man3/EVP_PKEY_fromdata.pod | 3 + doc/man3/OPENSSL_gmtime.pod | 62 ++++ doc/man3/OPENSSL_malloc.pod | 17 +- doc/man3/OSSL_CMP_MSG_get0_header.pod | 21 +- doc/man3/OSSL_LIB_CTX.pod | 4 +- doc/man3/OSSL_PROVIDER.pod | 7 +- doc/man3/X509_STORE_add_cert.pod | 2 +- doc/man3/X509_cmp_time.pod | 37 +- doc/man7/EVP_MD-SHAKE.pod | 16 +- doc/man7/EVP_PKEY-EC.pod | 4 +- doc/man7/migration_guide.pod | 2 +- e_os.h | 2 +- include/crypto/evp.h | 2 +- include/internal/packet.h | 37 +- include/internal/sockets.h | 4 +- include/openssl/bio.h.in | 1 + .../implementations/include/prov/ciphercommon.h | 4 +- providers/implementations/keymgmt/ec_kmgmt.c | 13 +- ssl/record/rec_layer_s3.c | 14 +- ssl/ssl_ciph.c | 3 +- ssl/ssl_lib.c | 27 +- ssl/ssl_local.h | 2 + ssl/ssl_rsa.c | 81 +++-- ssl/statem/extensions.c | 16 +- ssl/statem/extensions_clnt.c | 5 +- ssl/statem/extensions_srvr.c | 19 +- ssl/statem/statem.c | 22 +- ssl/statem/statem_dtls.c | 95 ++++- ssl/statem/statem_local.h | 5 + ssl/statem/statem_srvr.c | 66 +++- ssl/tls13_enc.c | 18 +- test/aesgcmtest.c | 4 - test/asynctest.c | 1 + test/build.info | 14 +- test/cmsapitest.c | 54 ++- test/drbgtest.c | 47 +-- test/dtlstest.c | 158 ++++++-- test/endecode_test.c | 8 +- test/evp_extra_test.c | 103 +++++- test/evp_extra_test2.c | 31 ++ test/evp_test.c | 60 +++- test/ext_internal_test.c | 105 ++++++ test/fips_version_test.c | 78 ++++ test/helpers/ssltestlib.c | 47 ++- test/helpers/ssltestlib.h | 1 + test/recipes/02-test_internal_exts.t | 15 + test/recipes/15-test_ec.t | 26 +- test/recipes/15-test_ecparam.t | 33 +- test/recipes/15-test_genrsa.t | 13 +- test/recipes/20-test_cli_fips.t | 14 +- test/recipes/20-test_dgst.t | 28 +- test/recipes/20-test_dhparam.t | 34 +- test/recipes/25-test_verify.t | 12 +- .../30-test_evp_data/evpciph_des3_common.txt | 2 + test/recipes/30-test_evp_data/evppkey_ffdhe.txt | 2 + test/recipes/80-test_ssl_new.t | 13 +- test/rsa_complex.c | 13 +- test/sslapitest.c | 232 ++++++++---- test/test_test.c | 396 ++++++++++----------- test/testec-p112r1.pem | 7 + test/testutil.h | 38 +- test/testutil/output.h | 1 + test/testutil/provider.c | 140 ++++++++ util/missingcrypto.txt | 6 - util/perl/OpenSSL/config.pm | 71 +++- util/wrap.pl.in | 5 +- 123 files changed, 2923 insertions(+), 799 deletions(-) diff --git a/.github/workflows/fips-old.yml b/.github/workflows/fips-old.yml new file mode 100644 index 0000000000..72b7179125 --- /dev/null +++ b/.github/workflows/fips-old.yml @@ -0,0 +1,74 @@ +# Copyright 2022 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 + +name: Provider old versions compat +on: [pull_request, push] + +permissions: + contents: read + +jobs: + fips-provider-validation: + strategy: + matrix: + module: [ + { + dir: openssl-3.0.0, + tgz: openssl-3.0.0.tar.gz, + url: "https://www.openssl.org/source/old/3.0/openssl-3.0.0.tar.gz" + }, + ] + runs-on: ubuntu-latest + steps: + - name: create directory + run: mkdir ./current + - uses: actions/checkout@v2 + with: + path: current + - name: download module source + run: wget --no-verbose ${{ matrix.module.url }} + - name: unpack module source + run: tar xzf ${{ matrix.module.tgz }} + - name: localegen + run: sudo locale-gen tr_TR.UTF-8 + - name: config current + run: ./config --banner=Configured enable-shared enable-fips + working-directory: ./current + - name: config dump current + run: ./configdata.pm --dump + working-directory: ./current + - name: make current + run: make -s -j4 + working-directory: ./current + - name: show module from current + run: | + ./util/wrap.pl -fips apps/openssl list -provider-path providers \ + -provider fips -providers + working-directory: ./current + - name: test current + run: make test HARNESS_JOBS=${HARNESS_JOBS:-4} + working-directory: ./current + - name: config module + run: ./config --banner=Configured enable-shared enable-fips + working-directory: ${{ matrix.module.dir }} + - name: config dump module + run: ./configdata.pm --dump + working-directory: ${{ matrix.module.dir }} + - name: make module + run: make -s -j4 + working-directory: ${{ matrix.module.dir }} + - name: setup module cross validation + run: cp providers/fips{module.cnf,.so} ../current/providers/ + working-directory: ${{ matrix.module.dir }} + - name: show module used for cross validation + run: | + ./util/wrap.pl -fips apps/openssl list -provider-path providers \ + -provider fips -providers + working-directory: ./current + - name: test module cross validation + run: make test HARNESS_JOBS=${HARNESS_JOBS:-4} + working-directory: ./current diff --git a/.github/workflows/fuzz-checker.yml b/.github/workflows/fuzz-checker.yml index 9e5627fd03..2347ebae41 100644 --- a/.github/workflows/fuzz-checker.yml +++ b/.github/workflows/fuzz-checker.yml @@ -25,7 +25,7 @@ jobs: cc: afl-clang-fast }, { name: libFuzzer, - config: enable-fuzz-libfuzzer -DPEDANTIC enable-asan enable-ubsan, + config: enable-fuzz-libfuzzer enable-asan enable-ubsan, libs: --with-fuzzer-lib=/usr/lib/llvm-12/lib/libFuzzer.a --with-fuzzer-include=/usr/lib/llvm-12/build/lib/clang/12.0.0/include/fuzzer, install: libfuzzer-12-dev, cc: clang-12, @@ -33,7 +33,7 @@ jobs: tests: -test_memleak }, { name: libFuzzer+, - config: enable-fuzz-libfuzzer -DPEDANTIC enable-asan enable-ubsan -fsanitize-coverage=trace-cmp -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION, + config: enable-fuzz-libfuzzer enable-asan enable-ubsan -fsanitize-coverage=trace-cmp -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION, libs: --with-fuzzer-lib=/usr/lib/llvm-12/lib/libFuzzer.a --with-fuzzer-include=/usr/lib/llvm-12/build/lib/clang/12.0.0/include/fuzzer, extra: enable-fips enable-ec_nistp_64_gcc_128 -fno-sanitize=alignment enable-tls1_3 enable-weak-ssl-ciphers enable-rc5 enable-md2 enable-ssl3 enable-ssl3-method enable-nextprotoneg, install: libfuzzer-12-dev, diff --git a/.github/workflows/run-checker-merge.yml b/.github/workflows/run-checker-merge.yml index dcc9d0d15f..82f3b29b0e 100644 --- a/.github/workflows/run-checker-merge.yml +++ b/.github/workflows/run-checker-merge.yml @@ -25,7 +25,7 @@ jobs: no-engine no-shared, no-err, no-filenames, - enable-ubsan no-asm -DPEDANTIC -DOPENSSL_SMALL_FOOTPRINT -fno-sanitize=alignment, + enable-ubsan no-asm -DOPENSSL_SMALL_FOOTPRINT -fno-sanitize=alignment, no-unit-test, enable-weak-ssl-ciphers, enable-zlib, diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 92052cf49b..f5b33dde05 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -22,9 +22,9 @@ jobs: - windows-2022 platform: - arch: win64 - config: VC-WIN64A enable-fips + config: enable-fips - arch: win32 - config: VC-WIN32 --strict-warnings no-fips + config: --strict-warnings no-fips runs-on: ${{matrix.os}} steps: - uses: actions/checkout@v2 @@ -95,7 +95,7 @@ jobs: - name: config working-directory: _build run: | - perl ..\Configure --banner=Configured no-makedepend no-bulk no-deprecated no-fips no-asm -DOPENSSL_SMALL_FOOTPRINT VC-WIN64A + perl ..\Configure --banner=Configured no-makedepend no-bulk no-deprecated no-fips no-asm -DOPENSSL_SMALL_FOOTPRINT perl configdata.pm --dump - name: build working-directory: _build diff --git a/Configurations/10-main.conf b/Configurations/10-main.conf index 73ace78bc4..b578a3c2a8 100644 --- a/Configurations/10-main.conf +++ b/Configurations/10-main.conf @@ -797,7 +797,7 @@ my %targets = ( inherit_from => [ "linux-latomic" ], cflags => add("-mabi=n32"), cxxflags => add("-mabi=n32"), - bn_ops => "RC4_CHAR", + bn_ops => "RC4_CHAR SIXTY_FOUR_BIT", asm_arch => 'mips64', perlasm_scheme => "n32", multilib => "32", diff --git a/Configurations/50-djgpp.conf b/Configurations/50-djgpp.conf index 16888924d6..fbe4911c42 100644 --- a/Configurations/50-djgpp.conf +++ b/Configurations/50-djgpp.conf @@ -4,6 +4,7 @@ my %targets = ( "DJGPP" => { + inherit_from => [ "BASE_unix" ], CC => "gcc", CFLAGS => "-fomit-frame-pointer -O2 -Wall", cflags => "-I/dev/env/WATT_ROOT/inc -DTERMIOS -DL_ENDIAN", diff --git a/Configure b/Configure index 379f668177..a558e5ab1a 100755 --- a/Configure +++ b/Configure @@ -1502,9 +1502,7 @@ unless ($disabled{asan} || defined $detected_sanitizers{asan}) { } unless ($disabled{ubsan} || defined $detected_sanitizers{ubsan}) { - # -DPEDANTIC or -fnosanitize=alignment may also be required on some - # platforms. - push @{$config{cflags}}, "-fsanitize=undefined", "-fno-sanitize-recover=all"; + push @{$config{cflags}}, "-fsanitize=undefined", "-fno-sanitize-recover=all", "-DPEDANTIC"; } unless ($disabled{msan} || defined $detected_sanitizers{msan}) { @@ -1716,20 +1714,13 @@ unless ($disabled{devcryptoeng}) { unless ($disabled{ktls}) { $config{ktls}=""; + my $cc = $config{CROSS_COMPILE}.$config{CC}; if ($target =~ m/^linux/) { - my $usr = "/usr/$config{cross_compile_prefix}"; - chop($usr); - if ($config{cross_compile_prefix} eq "") { - $usr = "/usr"; - } - my $minver = (4 << 16) + (13 << 8) + 0; - my @verstr = split(" ",`cat $usr/include/linux/version.h | grep LINUX_VERSION_CODE`); - - if ($verstr[2] < $minver) { + system("printf '#include \n#include ' | $cc -E - >/dev/null 2>&1"); + if ($? != 0) { disable('too-old-kernel', 'ktls'); } } elsif ($target =~ m/^BSD/) { - my $cc = $config{CROSS_COMPILE}.$config{CC}; system("printf '#include \n#include ' | $cc -E - >/dev/null 2>&1"); if ($? != 0) { disable('too-old-freebsd', 'ktls'); diff --git a/apps/ciphers.c b/apps/ciphers.c index 4dc3fa9454..42a0bb79f6 100644 --- a/apps/ciphers.c +++ b/apps/ciphers.c @@ -227,6 +227,10 @@ int ciphers_main(int argc, char **argv) if (!verbose) { for (i = 0; i < sk_SSL_CIPHER_num(sk); i++) { const SSL_CIPHER *c = sk_SSL_CIPHER_value(sk, i); + + if (!ossl_assert(c != NULL)) + continue; + p = SSL_CIPHER_get_name(c); if (p == NULL) break; @@ -242,6 +246,9 @@ int ciphers_main(int argc, char **argv) c = sk_SSL_CIPHER_value(sk, i); + if (!ossl_assert(c != NULL)) + continue; + if (Verbose) { unsigned long id = SSL_CIPHER_get_id(c); int id0 = (int)(id >> 24); diff --git a/apps/dgst.c b/apps/dgst.c index bd23b76996..f117e1b835 100644 --- a/apps/dgst.c +++ b/apps/dgst.c @@ -66,7 +66,7 @@ const OPTIONS dgst_options[] = { {"keyform", OPT_KEYFORM, 'f', "Key file format (ENGINE, other values ignored)"}, {"hex", OPT_HEX, '-', "Print as hex dump"}, {"binary", OPT_BINARY, '-', "Print in binary form"}, - {"xoflen", OPT_XOFLEN, 'p', "Output length for XOF algorithms"}, + {"xoflen", OPT_XOFLEN, 'p', "Output length for XOF algorithms. To obtain the maximum security strength set this to 32 (or greater) for SHAKE128, and 64 (or greater) for SHAKE256"}, {"d", OPT_DEBUG, '-', "Print debug info"}, {"debug", OPT_DEBUG, '-', "Print debug info"}, @@ -321,8 +321,10 @@ int dgst_main(int argc, char **argv) } if (hmac_key != NULL) { - if (md == NULL) + if (md == NULL) { md = (EVP_MD *)EVP_sha256(); + digestname = SN_sha256; + } sigkey = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, impl, (unsigned char *)hmac_key, strlen(hmac_key)); @@ -340,9 +342,19 @@ int dgst_main(int argc, char **argv) goto end; } if (do_verify) - res = EVP_DigestVerifyInit(mctx, &pctx, md, impl, sigkey); + if (impl == NULL) + res = EVP_DigestVerifyInit_ex(mctx, &pctx, digestname, + app_get0_libctx(), + app_get0_propq(), sigkey, NULL); + else + res = EVP_DigestVerifyInit(mctx, &pctx, md, impl, sigkey); else - res = EVP_DigestSignInit(mctx, &pctx, md, impl, sigkey); + if (impl == NULL) + res = EVP_DigestSignInit_ex(mctx, &pctx, digestname, + app_get0_libctx(), + app_get0_propq(), sigkey, NULL); + else + res = EVP_DigestSignInit(mctx, &pctx, md, impl, sigkey); if (res == 0) { BIO_printf(bio_err, "Error setting context\n"); goto end; @@ -406,6 +418,11 @@ int dgst_main(int argc, char **argv) BIO_printf(bio_err, "Length can only be specified for XOF\n"); goto end; } + /* + * Signing using XOF is not supported by any algorithms currently since + * each algorithm only calls EVP_DigestFinal_ex() in their sign_final + * and verify_final methods. + */ if (sigkey != NULL) { BIO_printf(bio_err, "Signing key cannot be specified for XOF\n"); goto end; @@ -467,7 +484,7 @@ static void show_digests(const OBJ_NAME *name, void *arg) return; /* Filter out message digests that we cannot use */ - md = EVP_get_digestbyname(name->name); + md = EVP_MD_fetch(app_get0_libctx(), name->name, app_get0_propq()); if (md == NULL) return; diff --git a/apps/dhparam.c b/apps/dhparam.c index d255129ed1..43906cea56 100644 --- a/apps/dhparam.c +++ b/apps/dhparam.c @@ -185,7 +185,7 @@ int dhparam_main(int argc, char **argv) BIO_printf(bio_err, "Warning, input file %s ignored\n", infile); } - ctx = EVP_PKEY_CTX_new_from_name(NULL, alg, NULL); + ctx = EVP_PKEY_CTX_new_from_name(app_get0_libctx(), alg, app_get0_propq()); if (ctx == NULL) { BIO_printf(bio_err, "Error, %s param generation context allocation failed\n", @@ -313,7 +313,7 @@ int dhparam_main(int argc, char **argv) EVP_PKEY_print_params(out, pkey, 4, NULL); if (check) { - ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey, NULL); + ctx = EVP_PKEY_CTX_new_from_pkey(app_get0_libctx(), pkey, app_get0_propq()); if (ctx == NULL) { BIO_printf(bio_err, "Error, failed to check DH parameters\n"); goto end; @@ -385,7 +385,7 @@ static EVP_PKEY *dsa_to_dh(EVP_PKEY *dh) goto err; } - ctx = EVP_PKEY_CTX_new_from_name(NULL, "DHX", NULL); + ctx = EVP_PKEY_CTX_new_from_name(app_get0_libctx(), "DHX", app_get0_propq()); if (ctx == NULL || EVP_PKEY_fromdata_init(ctx) <= 0 || EVP_PKEY_fromdata(ctx, &pkey, EVP_PKEY_KEY_PARAMETERS, params) <= 0) { diff --git a/apps/ecparam.c b/apps/ecparam.c index 5d869cfd14..9e9ad13683 100644 --- a/apps/ecparam.c +++ b/apps/ecparam.c @@ -230,9 +230,11 @@ int ecparam_main(int argc, char **argv) *p = OSSL_PARAM_construct_end(); if (OPENSSL_strcasecmp(curve_name, "SM2") == 0) - gctx_params = EVP_PKEY_CTX_new_from_name(NULL, "sm2", NULL); + gctx_params = EVP_PKEY_CTX_new_from_name(app_get0_libctx(), "sm2", + app_get0_propq()); else - gctx_params = EVP_PKEY_CTX_new_from_name(NULL, "ec", NULL); + gctx_params = EVP_PKEY_CTX_new_from_name(app_get0_libctx(), "ec", + app_get0_propq()); if (gctx_params == NULL || EVP_PKEY_keygen_init(gctx_params) <= 0 || EVP_PKEY_CTX_set_params(gctx_params, params) <= 0 @@ -283,7 +285,8 @@ int ecparam_main(int argc, char **argv) BIO_printf(bio_err, "unable to set check_type\n"); goto end; } - pctx = EVP_PKEY_CTX_new_from_pkey(NULL, params_key, NULL); + pctx = EVP_PKEY_CTX_new_from_pkey(app_get0_libctx(), params_key, + app_get0_propq()); if (pctx == NULL || EVP_PKEY_param_check(pctx) <= 0) { BIO_printf(bio_err, "failed\n"); goto end; @@ -313,7 +316,8 @@ int ecparam_main(int argc, char **argv) * EVP_PKEY_CTX_set_group_name(gctx, curvename); * EVP_PKEY_keygen(gctx, &key) <= 0) */ - gctx_key = EVP_PKEY_CTX_new_from_pkey(NULL, params_key, NULL); + gctx_key = EVP_PKEY_CTX_new_from_pkey(app_get0_libctx(), params_key, + app_get0_propq()); if (EVP_PKEY_keygen_init(gctx_key) <= 0 || EVP_PKEY_keygen(gctx_key, &key) <= 0) { BIO_printf(bio_err, "unable to generate key\n"); diff --git a/apps/genrsa.c b/apps/genrsa.c index e709ea38ce..9721e63d64 100644 --- a/apps/genrsa.c +++ b/apps/genrsa.c @@ -179,7 +179,8 @@ opthelp: if (out == NULL) goto end; - if (!init_gen_str(&ctx, "RSA", eng, 0, NULL, NULL)) + if (!init_gen_str(&ctx, "RSA", eng, 0, app_get0_libctx(), + app_get0_propq())) goto end; EVP_PKEY_CTX_set_cb(ctx, genrsa_cb); diff --git a/apps/include/apps.h b/apps/include/apps.h index 848d111bbd..9e39076e29 100644 --- a/apps/include/apps.h +++ b/apps/include/apps.h @@ -13,6 +13,7 @@ # include "e_os.h" /* struct timeval for DTLS */ # include "internal/nelem.h" # include "internal/sockets.h" /* for openssl_fdset() */ +# include "internal/cryptlib.h" /* ossl_assert() */ # include # include diff --git a/apps/mac.c b/apps/mac.c index 5f80ca22c7..b66a69fe00 100644 --- a/apps/mac.c +++ b/apps/mac.c @@ -170,9 +170,6 @@ opthelp: goto err; } - /* Use text mode for stdin */ - if (infile == NULL || strcmp(infile, "-") == 0) - inform = FORMAT_TEXT; in = bio_open_default(infile, 'r', inform); if (in == NULL) goto err; diff --git a/apps/pkeyparam.c b/apps/pkeyparam.c index 45647341ce..9f38c19cb8 100644 --- a/apps/pkeyparam.c +++ b/apps/pkeyparam.c @@ -101,7 +101,8 @@ int pkeyparam_main(int argc, char **argv) out = bio_open_default(outfile, 'w', FORMAT_PEM); if (out == NULL) goto end; - pkey = PEM_read_bio_Parameters(in, NULL); + pkey = PEM_read_bio_Parameters_ex(in, NULL, app_get0_libctx(), + app_get0_propq()); if (pkey == NULL) { BIO_printf(bio_err, "Error reading parameters\n"); ERR_print_errors(bio_err); @@ -109,7 +110,11 @@ int pkeyparam_main(int argc, char **argv) } if (check) { - ctx = EVP_PKEY_CTX_new(pkey, e); + if (e == NULL) + ctx = EVP_PKEY_CTX_new_from_pkey(app_get0_libctx(), pkey, + app_get0_propq()); + else + ctx = EVP_PKEY_CTX_new(pkey, e); if (ctx == NULL) { ERR_print_errors(bio_err); goto end; diff --git a/apps/rsa.c b/apps/rsa.c index 4cc45c5533..0da342c38f 100644 --- a/apps/rsa.c +++ b/apps/rsa.c @@ -61,7 +61,7 @@ const OPTIONS rsa_options[] = { OPT_SECTION("Input"), {"in", OPT_IN, 's', "Input file"}, - {"inform", OPT_INFORM, 'f', "Input format (DER/PEM/P12/ENGINE"}, + {"inform", OPT_INFORM, 'f', "Input format (DER/PEM/P12/ENGINE)"}, {"pubin", OPT_PUBIN, '-', "Expect a public key in input file"}, {"RSAPublicKey_in", OPT_RSAPUBKEY_IN, '-', "Input is an RSAPublicKey"}, {"passin", OPT_PASSIN, 's', "Input file pass phrase source"}, diff --git a/apps/speed.c b/apps/speed.c index c8ad19a2bf..d180a41f36 100644 --- a/apps/speed.c +++ b/apps/speed.c @@ -67,6 +67,7 @@ # define HAVE_FORK 0 # else # define HAVE_FORK 1 +# include # endif #endif @@ -2007,7 +2008,7 @@ int speed_main(int argc, char **argv) goto end; if (!EVP_MAC_CTX_set_params(loopargs[i].mctx, params)) - goto end; + goto skip_hmac; /* Digest not found */ } for (testnum = 0; testnum < size_num; testnum++) { print_message(names[D_HMAC], c[D_HMAC][testnum], lengths[testnum], @@ -2024,7 +2025,7 @@ int speed_main(int argc, char **argv) EVP_MAC_free(mac); mac = NULL; } - +skip_hmac: if (doit[D_CBC_DES]) { int st = 1; @@ -3419,6 +3420,7 @@ static int do_multi(int multi, int size_num) int n; int fd[2]; int *fds; + int status; static char sep[] = ":"; fds = app_malloc(sizeof(*fds) * multi, "fd buffer for do_multi"); @@ -3577,6 +3579,20 @@ static int do_multi(int multi, int size_num) fclose(f); } OPENSSL_free(fds); + for (n = 0; n < multi; ++n) { + while (wait(&status) == -1) + if (errno != EINTR) { + BIO_printf(bio_err, "Waitng for child failed with 0x%x\n", + errno); + return 1; + } + if (WIFEXITED(status) && WEXITSTATUS(status)) { + BIO_printf(bio_err, "Child exited with %d\n", WEXITSTATUS(status)); + } else if (WIFSIGNALED(status)) { + BIO_printf(bio_err, "Child terminated by signal %d\n", + WTERMSIG(status)); + } + } return 1; } #endif diff --git a/crypto/armcap.c b/crypto/armcap.c index 5b45a9d0f4..3c8522b8ae 100644 --- a/crypto/armcap.c +++ b/crypto/armcap.c @@ -257,11 +257,11 @@ void OPENSSL_cpuid_setup(void) } # endif - /* Things that getauxval didn't tell us */ - if (sigsetjmp(ill_jmp, 1) == 0) { - _armv7_tick(); - OPENSSL_armcap_P |= ARMV7_TICK; - } + /* + * Probing for ARMV7_TICK is known to produce unreliable results, + * so we will only use the feature when the user explicitly enables + * it with OPENSSL_armcap. + */ sigaction(SIGILL, &ill_oact, NULL); sigprocmask(SIG_SETMASK, &oset, NULL); diff --git a/crypto/bio/bio_lib.c b/crypto/bio/bio_lib.c index b5454f14b2..cddbc5eebb 100644 --- a/crypto/bio/bio_lib.c +++ b/crypto/bio/bio_lib.c @@ -12,6 +12,7 @@ #include #include #include +#include "internal/numbers.h" #include "bio_local.h" /* @@ -620,12 +621,28 @@ long BIO_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) */ size_t BIO_ctrl_pending(BIO *bio) { - return BIO_ctrl(bio, BIO_CTRL_PENDING, 0, NULL); + long ret = BIO_ctrl(bio, BIO_CTRL_PENDING, 0, NULL); + + if (ret < 0) + ret = 0; +#if LONG_MAX > SIZE_MAX + if (ret > SIZE_MAX) + ret = SIZE_MAX; +#endif + return (size_t)ret; } size_t BIO_ctrl_wpending(BIO *bio) { - return BIO_ctrl(bio, BIO_CTRL_WPENDING, 0, NULL); + long ret = BIO_ctrl(bio, BIO_CTRL_WPENDING, 0, NULL); + + if (ret < 0) + ret = 0; +#if LONG_MAX > SIZE_MAX + if (ret > SIZE_MAX) + ret = SIZE_MAX; +#endif + return (size_t)ret; } /* put the 'bio' on the end of b's list of operators */ diff --git a/crypto/bn/bn_prime.c b/crypto/bn/bn_prime.c index 9e2f6861a5..54f7ca611f 100644 --- a/crypto/bn/bn_prime.c +++ b/crypto/bn/bn_prime.c @@ -308,9 +308,10 @@ static int bn_is_prime_int(const BIGNUM *w, int checks, BN_CTX *ctx, goto err; #endif - ret = ossl_bn_miller_rabin_is_prime(w, checks, ctx, cb, 0, &status); - if (!ret) + if (!ossl_bn_miller_rabin_is_prime(w, checks, ctx, cb, 0, &status)) { + ret = -1; goto err; + } ret = (status == BN_PRIMETEST_PROBABLY_PRIME); err: #ifndef FIPS_MODULE diff --git a/crypto/bn/bn_rand.c b/crypto/bn/bn_rand.c index 1b49596990..fd17e7a601 100644 --- a/crypto/bn/bn_rand.c +++ b/crypto/bn/bn_rand.c @@ -136,6 +136,11 @@ static int bnrand_range(BNRAND_FLAG flag, BIGNUM *r, const BIGNUM *range, int n; int count = 100; + if (r == NULL) { + ERR_raise(ERR_LIB_BN, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + if (range->neg || BN_is_zero(range)) { ERR_raise(ERR_LIB_BN, BN_R_INVALID_RANGE); return 0; diff --git a/crypto/cmp/cmp_msg.c b/crypto/cmp/cmp_msg.c index 2da95248ad..9890fc3dcb 100644 --- a/crypto/cmp/cmp_msg.c +++ b/crypto/cmp/cmp_msg.c @@ -253,16 +253,16 @@ OSSL_CMP_MSG *ossl_cmp_msg_create(OSSL_CMP_CTX *ctx, int bodytype) (sk_GENERAL_NAME_num((ctx)->subjectAltNames) > 0 \ || OSSL_CMP_CTX_reqExtensions_have_SAN(ctx) == 1) -static const X509_NAME *determine_subj(OSSL_CMP_CTX *ctx, - const X509_NAME *ref_subj, - int for_KUR) +static const X509_NAME *determine_subj(OSSL_CMP_CTX *ctx, int for_KUR, + const X509_NAME *ref_subj) { if (ctx->subjectName != NULL) return IS_NULL_DN(ctx->subjectName) ? NULL : ctx->subjectName; - - if (ref_subj != NULL && (ctx->p10CSR != NULL || for_KUR || !HAS_SAN(ctx))) + if (ctx->p10CSR != NULL) /* first default is from any given CSR */ + return X509_REQ_get_subject_name(ctx->p10CSR); + if (for_KUR || !HAS_SAN(ctx)) /* - * For KUR, copy subject from the reference. + * For KUR, copy subject from any reference cert as fallback. * For IR or CR, do the same only if there is no subjectAltName. */ return ref_subj; @@ -277,9 +277,8 @@ OSSL_CRMF_MSG *OSSL_CMP_CTX_setup_CRM(OSSL_CMP_CTX *ctx, int for_KUR, int rid) EVP_PKEY *rkey = OSSL_CMP_CTX_get0_newPkey(ctx, 0); STACK_OF(GENERAL_NAME) *default_sans = NULL; const X509_NAME *ref_subj = - ctx->p10CSR != NULL ? X509_REQ_get_subject_name(ctx->p10CSR) : refcert != NULL ? X509_get_subject_name(refcert) : NULL; - const X509_NAME *subject = determine_subj(ctx, ref_subj, for_KUR); + const X509_NAME *subject = determine_subj(ctx, for_KUR, ref_subj); const X509_NAME *issuer = ctx->issuer != NULL || refcert == NULL ? (IS_NULL_DN(ctx->issuer) ? NULL : ctx->issuer) : X509_get_issuer_name(refcert); diff --git a/crypto/cmp/cmp_util.c b/crypto/cmp/cmp_util.c index ed611d64dd..d7b6cab594 100644 --- a/crypto/cmp/cmp_util.c +++ b/crypto/cmp/cmp_util.c @@ -101,8 +101,8 @@ const char *ossl_cmp_log_parse_metadata(const char *buf, *file = OPENSSL_strndup(p_file, p_line - 1 - p_file); /* no real problem if OPENSSL_strndup() returns NULL */ *line = (int)line_number; - msg = strchr(p_level, ':') + 1; - if (*msg == ' ') + msg = strchr(p_level, ':'); + if (msg != NULL && *++msg == ' ') msg++; } } diff --git a/crypto/cms/cms_lib.c b/crypto/cms/cms_lib.c index 4ad9302910..4aeb542eda 100644 --- a/crypto/cms/cms_lib.c +++ b/crypto/cms/cms_lib.c @@ -34,8 +34,11 @@ CMS_ContentInfo *d2i_CMS_ContentInfo(CMS_ContentInfo **a, (CMS_ContentInfo_it()), ossl_cms_ctx_get0_libctx(ctx), ossl_cms_ctx_get0_propq(ctx)); - if (ci != NULL) + if (ci != NULL) { + ERR_set_mark(); ossl_cms_resolve_libctx(ci); + ERR_pop_to_mark(); + } return ci; } diff --git a/crypto/conf/conf_def.c b/crypto/conf/conf_def.c index b5d6668f42..97c9fbc280 100644 --- a/crypto/conf/conf_def.c +++ b/crypto/conf/conf_def.c @@ -296,7 +296,7 @@ static int def_load_bio(CONF *conf, BIO *in, long *line) } #endif /* no more files in directory, continue with processing parent */ - if ((parent = sk_BIO_pop(biosk)) == NULL) { + if (sk_BIO_num(biosk) < 1 || (parent = sk_BIO_pop(biosk)) == NULL) { /* everything processed get out of the loop */ break; } else { diff --git a/crypto/conf/conf_sap.c b/crypto/conf/conf_sap.c index 6742ecf87f..2b50a9fd0d 100644 --- a/crypto/conf/conf_sap.c +++ b/crypto/conf/conf_sap.c @@ -44,16 +44,20 @@ void OPENSSL_config(const char *appname) int ossl_config_int(const OPENSSL_INIT_SETTINGS *settings) { int ret = 0; +#if defined(OPENSSL_INIT_DEBUG) || !defined(OPENSSL_SYS_UEFI) const char *filename; const char *appname; unsigned long flags; +#endif if (openssl_configured) return 1; +#if defined(OPENSSL_INIT_DEBUG) || !defined(OPENSSL_SYS_UEFI) filename = settings ? settings->filename : NULL; appname = settings ? settings->appname : NULL; flags = settings ? settings->flags : DEFAULT_CONF_MFLAGS; +#endif #ifdef OPENSSL_INIT_DEBUG fprintf(stderr, "OPENSSL_INIT: ossl_config_int(%s, %s, %lu)\n", diff --git a/crypto/dh/dh_pmeth.c b/crypto/dh/dh_pmeth.c index 1ad50b850d..bd7902c433 100644 --- a/crypto/dh/dh_pmeth.c +++ b/crypto/dh/dh_pmeth.c @@ -432,7 +432,8 @@ static int pkey_dh_derive(EVP_PKEY_CTX *ctx, unsigned char *key, else if (dctx->kdf_type == EVP_PKEY_DH_KDF_X9_42) { unsigned char *Z = NULL; - size_t Zlen = 0; + int Zlen = 0; + if (!dctx->kdf_outlen || !dctx->kdf_oid) return 0; if (key == NULL) { diff --git a/crypto/ec/ecx_meth.c b/crypto/ec/ecx_meth.c index bd72006c84..4e32210bf4 100644 --- a/crypto/ec/ecx_meth.c +++ b/crypto/ec/ecx_meth.c @@ -1160,12 +1160,10 @@ static int s390x_pkey_ecx_derive25519(EVP_PKEY_CTX *ctx, unsigned char *key, { const unsigned char *privkey, *pubkey; - if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey)) + if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey) + || (key != NULL + && s390x_x25519_mul(key, privkey, pubkey) == 0)) return 0; - - if (key != NULL) - return s390x_x25519_mul(key, pubkey, privkey); - *keylen = X25519_KEYLEN; return 1; } @@ -1175,12 +1173,10 @@ static int s390x_pkey_ecx_derive448(EVP_PKEY_CTX *ctx, unsigned char *key, { const unsigned char *privkey, *pubkey; - if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey)) + if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey) + || (key != NULL + && s390x_x448_mul(key, pubkey, privkey) == 0)) return 0; - - if (key != NULL) - return s390x_x448_mul(key, pubkey, privkey); - *keylen = X448_KEYLEN; return 1; } diff --git a/crypto/evp/digest.c b/crypto/evp/digest.c index de9a1dcda5..e6e03eaf34 100644 --- a/crypto/evp/digest.c +++ b/crypto/evp/digest.c @@ -225,7 +225,9 @@ static int evp_md_init_internal(EVP_MD_CTX *ctx, const EVP_MD *type, || tmpimpl != NULL #endif || (ctx->flags & EVP_MD_CTX_FLAG_NO_INIT) != 0 - || type->origin == EVP_ORIG_METH) { + || (type != NULL && type->origin == EVP_ORIG_METH) + || (type == NULL && ctx->digest != NULL + && ctx->digest->origin == EVP_ORIG_METH)) { if (ctx->digest == ctx->fetched_digest) ctx->digest = NULL; EVP_MD_free(ctx->fetched_digest); diff --git a/crypto/evp/evp_enc.c b/crypto/evp/evp_enc.c index e69da3f9a0..b178d10864 100644 --- a/crypto/evp/evp_enc.c +++ b/crypto/evp/evp_enc.c @@ -43,6 +43,7 @@ int EVP_CIPHER_CTX_reset(EVP_CIPHER_CTX *ctx) if (ctx->fetched_cipher != NULL) EVP_CIPHER_free(ctx->fetched_cipher); memset(ctx, 0, sizeof(*ctx)); + ctx->iv_len = -1; return 1; @@ -61,6 +62,7 @@ int EVP_CIPHER_CTX_reset(EVP_CIPHER_CTX *ctx) ENGINE_finish(ctx->engine); #endif memset(ctx, 0, sizeof(*ctx)); + ctx->iv_len = -1; return 1; } @@ -87,6 +89,9 @@ static int evp_cipher_init_internal(EVP_CIPHER_CTX *ctx, #if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE) ENGINE *tmpimpl = NULL; #endif + + ctx->iv_len = -1; + /* * enc == 1 means we are encrypting. * enc == 0 means we are decrypting. @@ -131,7 +136,10 @@ static int evp_cipher_init_internal(EVP_CIPHER_CTX *ctx, #if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE) || tmpimpl != NULL #endif - || impl != NULL) { + || impl != NULL + || (cipher != NULL && cipher->origin == EVP_ORIG_METH) + || (cipher == NULL && ctx->cipher != NULL + && ctx->cipher->origin == EVP_ORIG_METH)) { if (ctx->cipher == ctx->fetched_cipher) ctx->cipher = NULL; EVP_CIPHER_free(ctx->fetched_cipher); @@ -143,11 +151,12 @@ static int evp_cipher_init_internal(EVP_CIPHER_CTX *ctx, * (legacy code) */ if (cipher != NULL && ctx->cipher != NULL) { + if (ctx->cipher->cleanup != NULL && !ctx->cipher->cleanup(ctx)) + return 0; OPENSSL_clear_free(ctx->cipher_data, ctx->cipher->ctx_size); ctx->cipher_data = NULL; } - /* Start of non-legacy code below */ /* Ensure a context left lying around from last time is cleared */ @@ -1085,12 +1094,14 @@ int EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr) if (arg < 0) return 0; params[0] = OSSL_PARAM_construct_size_t(OSSL_CIPHER_PARAM_IVLEN, &sz); + ctx->iv_len = -1; break; case EVP_CTRL_CCM_SET_L: if (arg < 2 || arg > 8) return 0; sz = 15 - arg; params[0] = OSSL_PARAM_construct_size_t(OSSL_CIPHER_PARAM_IVLEN, &sz); + ctx->iv_len = -1; break; case EVP_CTRL_AEAD_SET_IV_FIXED: params[0] = OSSL_PARAM_construct_octet_string( @@ -1254,8 +1265,10 @@ int EVP_CIPHER_get_params(EVP_CIPHER *cipher, OSSL_PARAM params[]) int EVP_CIPHER_CTX_set_params(EVP_CIPHER_CTX *ctx, const OSSL_PARAM params[]) { - if (ctx->cipher != NULL && ctx->cipher->set_ctx_params != NULL) + if (ctx->cipher != NULL && ctx->cipher->set_ctx_params != NULL) { + ctx->iv_len = -1; return ctx->cipher->set_ctx_params(ctx->algctx, params); + } return 0; } diff --git a/crypto/evp/evp_lib.c b/crypto/evp/evp_lib.c index d5ae5ca4ad..d88066d0a2 100644 --- a/crypto/evp/evp_lib.c +++ b/crypto/evp/evp_lib.c @@ -504,23 +504,38 @@ int EVP_CIPHER_get_iv_length(const EVP_CIPHER *cipher) int EVP_CIPHER_CTX_get_iv_length(const EVP_CIPHER_CTX *ctx) { - int rv, len = EVP_CIPHER_get_iv_length(ctx->cipher); - size_t v = len; - OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END }; - - params[0] = OSSL_PARAM_construct_size_t(OSSL_CIPHER_PARAM_IVLEN, &v); - rv = evp_do_ciph_ctx_getparams(ctx->cipher, ctx->algctx, params); - if (rv == EVP_CTRL_RET_UNSUPPORTED) - goto legacy; - return rv != 0 ? (int)v : -1; - /* Code below to be removed when legacy support is dropped. */ -legacy: - if ((EVP_CIPHER_get_flags(ctx->cipher) & EVP_CIPH_CUSTOM_IV_LENGTH) != 0) { - rv = EVP_CIPHER_CTX_ctrl((EVP_CIPHER_CTX *)ctx, EVP_CTRL_GET_IVLEN, - 0, &len); - return (rv == 1) ? len : -1; + if (ctx->iv_len < 0) { + int rv, len = EVP_CIPHER_get_iv_length(ctx->cipher); + size_t v = len; + OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END }; + + if (ctx->cipher->get_ctx_params != NULL) { + params[0] = OSSL_PARAM_construct_size_t(OSSL_CIPHER_PARAM_IVLEN, + &v); + rv = evp_do_ciph_ctx_getparams(ctx->cipher, ctx->algctx, params); + if (rv > 0) { + if (OSSL_PARAM_modified(params) + && !OSSL_PARAM_get_int(params, &len)) + return -1; + } else if (rv != EVP_CTRL_RET_UNSUPPORTED) { + return -1; + } + } + /* Code below to be removed when legacy support is dropped. */ + else if ((EVP_CIPHER_get_flags(ctx->cipher) + & EVP_CIPH_CUSTOM_IV_LENGTH) != 0) { + rv = EVP_CIPHER_CTX_ctrl((EVP_CIPHER_CTX *)ctx, EVP_CTRL_GET_IVLEN, + 0, &len); + if (rv <= 0) + return -1; + } + /*- + * Casting away the const is annoying but required here. We need to + * cache the result for performance reasons. + */ + ((EVP_CIPHER_CTX *)ctx)->iv_len = len; } - return len; + return ctx->iv_len; } int EVP_CIPHER_CTX_get_tag_length(const EVP_CIPHER_CTX *ctx) diff --git a/crypto/evp/evp_local.h b/crypto/evp/evp_local.h index 13e248d384..3ccfaeb37c 100644 --- a/crypto/evp/evp_local.h +++ b/crypto/evp/evp_local.h @@ -46,6 +46,7 @@ struct evp_cipher_ctx_st { /* FIXME: Should this even exist? It appears unused */ void *app_data; /* application stuff */ int key_len; /* May change for variable length cipher */ + int iv_len; /* IV length */ unsigned long flags; /* Various flags */ void *cipher_data; /* per EVP data */ int final_used; diff --git a/crypto/evp/p_lib.c b/crypto/evp/p_lib.c index 170cb89cb0..c8c342b3e9 100644 --- a/crypto/evp/p_lib.c +++ b/crypto/evp/p_lib.c @@ -339,9 +339,16 @@ int EVP_PKEY_eq(const EVP_PKEY *a, const EVP_PKEY *b) if (a == NULL || b == NULL) return 0; - if (a->keymgmt != NULL || b->keymgmt != NULL) - return evp_pkey_cmp_any(a, b, (SELECT_PARAMETERS - | OSSL_KEYMGMT_SELECT_KEYPAIR)); + if (a->keymgmt != NULL || b->keymgmt != NULL) { + int selection = SELECT_PARAMETERS; + + if (evp_keymgmt_util_has((EVP_PKEY *)a, OSSL_KEYMGMT_SELECT_PUBLIC_KEY) + && evp_keymgmt_util_has((EVP_PKEY *)b, OSSL_KEYMGMT_SELECT_PUBLIC_KEY)) + selection |= OSSL_KEYMGMT_SELECT_PUBLIC_KEY; + else + selection |= OSSL_KEYMGMT_SELECT_KEYPAIR; + return evp_pkey_cmp_any(a, b, selection); + } /* All legacy keys */ if (a->type != b->type) diff --git a/crypto/mem.c b/crypto/mem.c index 2cf240061a..f6cdcf5a42 100644 --- a/crypto/mem.c +++ b/crypto/mem.c @@ -285,12 +285,12 @@ int CRYPTO_set_mem_debug(int flag) int CRYPTO_mem_debug_push(const char *info, const char *file, int line) { (void)info; (void)file; (void)line; - return -1; + return 0; } int CRYPTO_mem_debug_pop(void) { - return -1; + return 0; } void CRYPTO_mem_debug_malloc(void *addr, size_t num, int flag, diff --git a/crypto/packet.c b/crypto/packet.c index 09f6a9cea9..a9eb1ec4e4 100644 --- a/crypto/packet.c +++ b/crypto/packet.c @@ -207,7 +207,7 @@ int WPACKET_set_flags(WPACKET *pkt, unsigned int flags) } /* Store the |value| of length |len| at location |data| */ -static int put_value(unsigned char *data, size_t value, size_t len) +static int put_value(unsigned char *data, uint64_t value, size_t len) { if (data == NULL) return 1; @@ -379,12 +379,12 @@ int WPACKET_start_sub_packet(WPACKET *pkt) return WPACKET_start_sub_packet_len__(pkt, 0); } -int WPACKET_put_bytes__(WPACKET *pkt, unsigned int val, size_t size) +int WPACKET_put_bytes__(WPACKET *pkt, uint64_t val, size_t size) { unsigned char *data; /* Internal API, so should not fail */ - if (!ossl_assert(size <= sizeof(unsigned int)) + if (!ossl_assert(size <= sizeof(uint64_t)) || !WPACKET_allocate_bytes(pkt, size, &data) || !put_value(data, val, size)) return 0; diff --git a/crypto/pkcs7/pk7_smime.c b/crypto/pkcs7/pk7_smime.c index cc5f0b33e8..4593da8f5b 100644 --- a/crypto/pkcs7/pk7_smime.c +++ b/crypto/pkcs7/pk7_smime.c @@ -280,7 +280,8 @@ int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store, ERR_raise(ERR_LIB_PKCS7, ERR_R_X509_LIB); goto err; } - X509_STORE_CTX_set_default(cert_ctx, "smime_sign"); + if (!X509_STORE_CTX_set_default(cert_ctx, "smime_sign")) + goto err; } else if (!X509_STORE_CTX_init(cert_ctx, store, signer, NULL)) { ERR_raise(ERR_LIB_PKCS7, ERR_R_X509_LIB); goto err; diff --git a/crypto/property/property.c b/crypto/property/property.c index dec0bdb45e..2c92cb5e50 100644 --- a/crypto/property/property.c +++ b/crypto/property/property.c @@ -15,6 +15,7 @@ #include "internal/core.h" #include "internal/property.h" #include "internal/provider.h" +#include "internal/tsan_assist.h" #include "crypto/ctype.h" #include #include @@ -89,6 +90,7 @@ typedef struct { LHASH_OF(QUERY) *cache; size_t nelem; uint32_t seed; + unsigned char using_global_seed; } IMPL_CACHE_FLUSH; DEFINE_SPARSE_ARRAY_OF(ALGORITHM); @@ -657,13 +659,21 @@ static void impl_cache_flush_one_alg(ossl_uintmax_t idx, ALGORITHM *alg, static void ossl_method_cache_flush_some(OSSL_METHOD_STORE *store) { IMPL_CACHE_FLUSH state; + static TSAN_QUALIFIER uint32_t global_seed = 1; state.nelem = 0; - if ((state.seed = OPENSSL_rdtsc()) == 0) - state.seed = 1; + state.using_global_seed = 0; + if ((state.seed = OPENSSL_rdtsc()) == 0) { + /* If there is no timer available, seed another way */ + state.using_global_seed = 1; + state.seed = tsan_load(&global_seed); + } store->cache_need_flush = 0; ossl_sa_ALGORITHM_doall_arg(store->algs, &impl_cache_flush_one_alg, &state); store->cache_nelem = state.nelem; + /* Without a timer, update the global seed */ + if (state.using_global_seed) + tsan_store(&global_seed, state.seed); } int ossl_method_store_cache_get(OSSL_METHOD_STORE *store, OSSL_PROVIDER *prov, diff --git a/crypto/stack/stack.c b/crypto/stack/stack.c index 3d8e4746cf..9942848d88 100644 --- a/crypto/stack/stack.c +++ b/crypto/stack/stack.c @@ -19,8 +19,7 @@ */ static const int min_nodes = 4; static const int max_nodes = SIZE_MAX / sizeof(void *) < INT_MAX - ? (int)(SIZE_MAX / sizeof(void *)) - : INT_MAX; + ? (int)(SIZE_MAX / sizeof(void *)) : INT_MAX; struct stack_st { int num; @@ -30,7 +29,8 @@ struct stack_st { OPENSSL_sk_compfunc comp; }; -OPENSSL_sk_compfunc OPENSSL_sk_set_cmp_func(OPENSSL_STACK *sk, OPENSSL_sk_compfunc c) +OPENSSL_sk_compfunc OPENSSL_sk_set_cmp_func(OPENSSL_STACK *sk, + OPENSSL_sk_compfunc c) { OPENSSL_sk_compfunc old = sk->comp; @@ -65,7 +65,8 @@ OPENSSL_STACK *OPENSSL_sk_dup(const OPENSSL_STACK *sk) } /* duplicate |sk->data| content */ - if ((ret->data = OPENSSL_malloc(sizeof(*ret->data) * sk->num_alloc)) == NULL) + ret->data = OPENSSL_malloc(sizeof(*ret->data) * sk->num_alloc); + if (ret->data == NULL) goto err; memcpy(ret->data, sk->data, sizeof(void *) * sk->num); return ret; @@ -77,8 +78,8 @@ OPENSSL_STACK *OPENSSL_sk_dup(const OPENSSL_STACK *sk) } OPENSSL_STACK *OPENSSL_sk_deep_copy(const OPENSSL_STACK *sk, - OPENSSL_sk_copyfunc copy_func, - OPENSSL_sk_freefunc free_func) + OPENSSL_sk_copyfunc copy_func, + OPENSSL_sk_freefunc free_func) { OPENSSL_STACK *ret; int i; @@ -175,8 +176,10 @@ static int sk_reserve(OPENSSL_STACK *st, int n, int exact) int num_alloc; /* Check to see the reservation isn't exceeding the hard limit */ - if (n > max_nodes - st->num) + if (n > max_nodes - st->num) { + ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_TOO_MANY_RECORDS); return 0; + } /* Figure out the new size */ num_alloc = st->num + n; @@ -201,15 +204,19 @@ static int sk_reserve(OPENSSL_STACK *st, int n, int exact) if (num_alloc <= st->num_alloc) return 1; num_alloc = compute_growth(num_alloc, st->num_alloc); - if (num_alloc == 0) + if (num_alloc == 0) { + ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_TOO_MANY_RECORDS); return 0; + } } else if (num_alloc == st->num_alloc) { return 1; } tmpdata = OPENSSL_realloc((void *)st->data, sizeof(void *) * num_alloc); - if (tmpdata == NULL) + if (tmpdata == NULL) { + ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE); return 0; + } st->data = tmpdata; st->num_alloc = num_alloc; @@ -220,8 +227,10 @@ OPENSSL_STACK *OPENSSL_sk_new_reserve(OPENSSL_sk_compfunc c, int n) { OPENSSL_STACK *st = OPENSSL_zalloc(sizeof(OPENSSL_STACK)); - if (st == NULL) + if (st == NULL) { + ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE); return NULL; + } st->comp = c; @@ -238,8 +247,10 @@ OPENSSL_STACK *OPENSSL_sk_new_reserve(OPENSSL_sk_compfunc c, int n) int OPENSSL_sk_reserve(OPENSSL_STACK *st, int n) { - if (st == NULL) + if (st == NULL) { + ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER); return 0; + } if (n < 0) return 1; @@ -248,8 +259,14 @@ int OPENSSL_sk_reserve(OPENSSL_STACK *st, int n) int OPENSSL_sk_insert(OPENSSL_STACK *st, const void *data, int loc) { - if (st == NULL || st->num == max_nodes) + if (st == NULL) { + ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER); return 0; + } + if (st->num == max_nodes) { + ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_TOO_MANY_RECORDS); + return 0; + } if (!sk_reserve(st, 1, 0)) return 0; @@ -271,8 +288,8 @@ static ossl_inline void *internal_delete(OPENSSL_STACK *st, int loc) const void *ret = st->data[loc]; if (loc != st->num - 1) - memmove(&st->data[loc], &st->data[loc + 1], - sizeof(st->data[0]) * (st->num - loc - 1)); + memmove(&st->data[loc], &st->data[loc + 1], + sizeof(st->data[0]) * (st->num - loc - 1)); st->num--; return (void *)ret; @@ -290,8 +307,15 @@ void *OPENSSL_sk_delete_ptr(OPENSSL_STACK *st, const void *p) void *OPENSSL_sk_delete(OPENSSL_STACK *st, int loc) { - if (st == NULL || loc < 0 || loc >= st->num) + if (st == NULL) { + ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + if (loc < 0 || loc >= st->num) { + ERR_raise_data(ERR_LIB_X509, ERR_R_PASSED_INVALID_ARGUMENT, + "loc=%d", loc); return NULL; + } return internal_delete(st, loc); } @@ -375,21 +399,37 @@ int OPENSSL_sk_unshift(OPENSSL_STACK *st, const void *data) void *OPENSSL_sk_shift(OPENSSL_STACK *st) { - if (st == NULL || st->num == 0) + if (st == NULL) { + ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER); return NULL; + } + if (st->num == 0) { + ERR_raise(ERR_LIB_X509, ERR_R_PASSED_INVALID_ARGUMENT); + return NULL; + } return internal_delete(st, 0); } void *OPENSSL_sk_pop(OPENSSL_STACK *st) { - if (st == NULL || st->num == 0) + if (st == NULL) { + ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + if (st->num == 0) { + ERR_raise(ERR_LIB_X509, ERR_R_PASSED_INVALID_ARGUMENT); return NULL; + } return internal_delete(st, st->num - 1); } void OPENSSL_sk_zero(OPENSSL_STACK *st) { - if (st == NULL || st->num == 0) + if (st == NULL) { + ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER); + return; + } + if (st->num == 0) return; memset(st->data, 0, sizeof(*st->data) * st->num); st->num = 0; @@ -422,15 +462,29 @@ int OPENSSL_sk_num(const OPENSSL_STACK *st) void *OPENSSL_sk_value(const OPENSSL_STACK *st, int i) { - if (st == NULL || i < 0 || i >= st->num) + if (st == NULL) { + ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + if (i < 0 || i >= st->num) { + ERR_raise_data(ERR_LIB_X509, ERR_R_PASSED_INVALID_ARGUMENT, + "i=%d", i); return NULL; + } return (void *)st->data[i]; } void *OPENSSL_sk_set(OPENSSL_STACK *st, int i, const void *data) { - if (st == NULL || i < 0 || i >= st->num) + if (st == NULL) { + ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER); return NULL; + } + if (i < 0 || i >= st->num) { + ERR_raise_data(ERR_LIB_X509, ERR_R_PASSED_INVALID_ARGUMENT, + "i=%d", i); + return NULL; + } st->data[i] = data; st->sorted = 0; return (void *)st->data[i]; diff --git a/crypto/x509/x509_req.c b/crypto/x509/x509_req.c index e3f5c2add1..ad48f34a30 100644 --- a/crypto/x509/x509_req.c +++ b/crypto/x509/x509_req.c @@ -116,6 +116,7 @@ static int *ext_nids = ext_nid_list; int X509_REQ_extension_nid(int req_nid) { int i, nid; + for (i = 0;; i++) { nid = ext_nids[i]; if (nid == NID_undef) @@ -142,7 +143,7 @@ STACK_OF(X509_EXTENSION) *X509_REQ_get_extensions(X509_REQ *req) int idx, *pnid; const unsigned char *p; - if ((req == NULL) || !ext_nids) + if (req == NULL || !ext_nids) return NULL; for (pnid = ext_nids; *pnid != NID_undef; pnid++) { idx = X509_REQ_get_attr_by_NID(req, *pnid, -1); @@ -214,44 +215,73 @@ X509_ATTRIBUTE *X509_REQ_get_attr(const X509_REQ *req, int loc) X509_ATTRIBUTE *X509_REQ_delete_attr(X509_REQ *req, int loc) { - return X509at_delete_attr(req->req_info.attributes, loc); + X509_ATTRIBUTE *attr; + + if (req == NULL) { + ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + attr = X509at_delete_attr(req->req_info.attributes, loc); + if (attr != NULL) + req->req_info.enc.modified = 1; + return attr; } int X509_REQ_add1_attr(X509_REQ *req, X509_ATTRIBUTE *attr) { - if (X509at_add1_attr(&req->req_info.attributes, attr)) - return 1; - return 0; + if (req == NULL) { + ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + if (!X509at_add1_attr(&req->req_info.attributes, attr)) + return 0; + req->req_info.enc.modified = 1; + return 1; } int X509_REQ_add1_attr_by_OBJ(X509_REQ *req, const ASN1_OBJECT *obj, int type, const unsigned char *bytes, int len) { - if (X509at_add1_attr_by_OBJ(&req->req_info.attributes, obj, - type, bytes, len)) - return 1; - return 0; + if (req == NULL) { + ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + if (!X509at_add1_attr_by_OBJ(&req->req_info.attributes, obj, + type, bytes, len)) + return 0; + req->req_info.enc.modified = 1; + return 1; } int X509_REQ_add1_attr_by_NID(X509_REQ *req, int nid, int type, const unsigned char *bytes, int len) { - if (X509at_add1_attr_by_NID(&req->req_info.attributes, nid, - type, bytes, len)) - return 1; - return 0; + if (req == NULL) { + ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + if (!X509at_add1_attr_by_NID(&req->req_info.attributes, nid, + type, bytes, len)) + return 0; + req->req_info.enc.modified = 1; + return 1; } int X509_REQ_add1_attr_by_txt(X509_REQ *req, const char *attrname, int type, const unsigned char *bytes, int len) { - if (X509at_add1_attr_by_txt(&req->req_info.attributes, attrname, - type, bytes, len)) - return 1; - return 0; + if (req == NULL) { + ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + if (!X509at_add1_attr_by_txt(&req->req_info.attributes, attrname, + type, bytes, len)) + return 0; + req->req_info.enc.modified = 1; + return 1; } long X509_REQ_get_version(const X509_REQ *req) @@ -276,7 +306,7 @@ void X509_REQ_get0_signature(const X509_REQ *req, const ASN1_BIT_STRING **psig, void X509_REQ_set0_signature(X509_REQ *req, ASN1_BIT_STRING *psig) { if (req->signature) - ASN1_BIT_STRING_free(req->signature); + ASN1_BIT_STRING_free(req->signature); req->signature = psig; } @@ -292,6 +322,12 @@ int X509_REQ_get_signature_nid(const X509_REQ *req) int i2d_re_X509_REQ_tbs(X509_REQ *req, unsigned char **pp) { + if (req == NULL) { + ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + if (!i2d_X509_REQ_INFO(&req->req_info, pp)) + return 0; req->req_info.enc.modified = 1; - return i2d_X509_REQ_INFO(&req->req_info, pp); + return 1; } diff --git a/crypto/x509/x509_vfy.c b/crypto/x509/x509_vfy.c index 575047cdb6..9384f1da9b 100644 --- a/crypto/x509/x509_vfy.c +++ b/crypto/x509/x509_vfy.c @@ -1007,14 +1007,14 @@ static int check_crl_time(X509_STORE_CTX *ctx, X509_CRL *crl, int notify) time_t *ptime; int i; - if (notify) - ctx->current_crl = crl; if ((ctx->param->flags & X509_V_FLAG_USE_CHECK_TIME) != 0) ptime = &ctx->param->check_time; else if ((ctx->param->flags & X509_V_FLAG_NO_CHECK_TIME) != 0) return 1; else ptime = NULL; + if (notify) + ctx->current_crl = crl; i = X509_cmp_time(X509_CRL_get0_lastUpdate(crl), ptime); if (i == 0) { @@ -2313,8 +2313,6 @@ void X509_STORE_CTX_free(X509_STORE_CTX *ctx) int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509, STACK_OF(X509) *chain) { - int ret = 1; - if (ctx == NULL) { ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER); return 0; @@ -2412,19 +2410,13 @@ int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509, } /* Inherit callbacks and flags from X509_STORE if not set use defaults. */ - if (store != NULL) - ret = X509_VERIFY_PARAM_inherit(ctx->param, store->param); - else + if (store == NULL) ctx->param->inh_flags |= X509_VP_FLAG_DEFAULT | X509_VP_FLAG_ONCE; + else if (X509_VERIFY_PARAM_inherit(ctx->param, store->param) == 0) + goto err; - if (ret) - ret = X509_VERIFY_PARAM_inherit(ctx->param, - X509_VERIFY_PARAM_lookup("default")); - - if (ret == 0) { - ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE); + if (!X509_STORE_CTX_set_default(ctx, "default")) goto err; - } /* * XXX: For now, continue to inherit trust from VPM, but infer from the @@ -2626,8 +2618,10 @@ int X509_STORE_CTX_set_default(X509_STORE_CTX *ctx, const char *name) const X509_VERIFY_PARAM *param; param = X509_VERIFY_PARAM_lookup(name); - if (param == NULL) + if (param == NULL) { + ERR_raise_data(ERR_LIB_X509, X509_R_UNKNOWN_PURPOSE_ID, "name=%s", name); return 0; + } return X509_VERIFY_PARAM_inherit(ctx->param, param); } diff --git a/crypto/x509/x509_vpm.c b/crypto/x509/x509_vpm.c index d11aa2341a..4d139124fc 100644 --- a/crypto/x509/x509_vpm.c +++ b/crypto/x509/x509_vpm.c @@ -44,7 +44,8 @@ static int int_x509_param_set_hosts(X509_VERIFY_PARAM *vpm, int mode, */ if (namelen == 0 || name == NULL) namelen = name ? strlen(name) : 0; - else if (name && memchr(name, '\0', namelen > 1 ? namelen - 1 : namelen)) + else if (name != NULL + && memchr(name, '\0', namelen > 1 ? namelen - 1 : namelen) != NULL) return 0; if (namelen > 0 && name[namelen - 1] == '\0') --namelen; @@ -78,7 +79,6 @@ static int int_x509_param_set_hosts(X509_VERIFY_PARAM *vpm, int mode, return 1; } - X509_VERIFY_PARAM *X509_VERIFY_PARAM_new(void) { X509_VERIFY_PARAM *param; @@ -142,8 +142,7 @@ void X509_VERIFY_PARAM_free(X509_VERIFY_PARAM *param) /* Macro to test if a field should be copied from src to dest */ #define test_x509_verify_param_copy(field, def) \ - (to_overwrite \ - || ((src->field != def) && (to_default || (dest->field == def)))) + (to_overwrite || (src->field != def && (to_default || dest->field == def))) /* Macro to test and copy a field if necessary */ @@ -156,25 +155,19 @@ int X509_VERIFY_PARAM_inherit(X509_VERIFY_PARAM *dest, { unsigned long inh_flags; int to_default, to_overwrite; - if (!src) + + if (src == NULL) return 1; inh_flags = dest->inh_flags | src->inh_flags; - if (inh_flags & X509_VP_FLAG_ONCE) + if ((inh_flags & X509_VP_FLAG_ONCE) != 0) dest->inh_flags = 0; - if (inh_flags & X509_VP_FLAG_LOCKED) + if ((inh_flags & X509_VP_FLAG_LOCKED) != 0) return 1; - if (inh_flags & X509_VP_FLAG_DEFAULT) - to_default = 1; - else - to_default = 0; - - if (inh_flags & X509_VP_FLAG_OVERWRITE) - to_overwrite = 1; - else - to_overwrite = 0; + to_default = (inh_flags & X509_VP_FLAG_DEFAULT) != 0; + to_overwrite = (inh_flags & X509_VP_FLAG_OVERWRITE) != 0; x509_verify_param_copy(purpose, 0); x509_verify_param_copy(trust, X509_TRUST_DEFAULT); @@ -183,13 +176,13 @@ int X509_VERIFY_PARAM_inherit(X509_VERIFY_PARAM *dest, /* If overwrite or check time not set, copy across */ - if (to_overwrite || !(dest->flags & X509_V_FLAG_USE_CHECK_TIME)) { + if (to_overwrite || (dest->flags & X509_V_FLAG_USE_CHECK_TIME) == 0) { dest->check_time = src->check_time; dest->flags &= ~X509_V_FLAG_USE_CHECK_TIME; /* Don't need to copy flag: that is done below */ } - if (inh_flags & X509_VP_FLAG_RESET_FLAGS) + if ((inh_flags & X509_VP_FLAG_RESET_FLAGS) != 0) dest->flags = 0; dest->flags |= src->flags; @@ -204,7 +197,7 @@ int X509_VERIFY_PARAM_inherit(X509_VERIFY_PARAM *dest, if (test_x509_verify_param_copy(hosts, NULL)) { sk_OPENSSL_STRING_pop_free(dest->hosts, str_free); dest->hosts = NULL; - if (src->hosts) { + if (src->hosts != NULL) { dest->hosts = sk_OPENSSL_STRING_deep_copy(src->hosts, str_copy, str_free); if (dest->hosts == NULL) @@ -228,8 +221,14 @@ int X509_VERIFY_PARAM_inherit(X509_VERIFY_PARAM *dest, int X509_VERIFY_PARAM_set1(X509_VERIFY_PARAM *to, const X509_VERIFY_PARAM *from) { - unsigned long save_flags = to->inh_flags; + unsigned long save_flags; int ret; + + if (to == NULL) { + ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + save_flags = to->inh_flags; to->inh_flags |= X509_VP_FLAG_DEFAULT; ret = X509_VERIFY_PARAM_inherit(to, from); to->inh_flags = save_flags; @@ -240,7 +239,8 @@ static int int_x509_param_set1(char **pdest, size_t *pdestlen, const char *src, size_t srclen) { char *tmp; - if (src) { + + if (src != NULL) { if (srclen == 0) srclen = strlen(src); @@ -264,15 +264,13 @@ int X509_VERIFY_PARAM_set1_name(X509_VERIFY_PARAM *param, const char *name) { OPENSSL_free(param->name); param->name = OPENSSL_strdup(name); - if (param->name) - return 1; - return 0; + return param->name != NULL; } int X509_VERIFY_PARAM_set_flags(X509_VERIFY_PARAM *param, unsigned long flags) { param->flags |= flags; - if (flags & X509_V_FLAG_POLICY_MASK) + if ((flags & X509_V_FLAG_POLICY_MASK) != 0) param->flags |= X509_V_FLAG_POLICY_CHECK; return 1; } @@ -339,9 +337,7 @@ int X509_VERIFY_PARAM_add0_policy(X509_VERIFY_PARAM *param, if (param->policies == NULL) return 0; } - if (!sk_ASN1_OBJECT_push(param->policies, policy)) - return 0; - return 1; + return sk_ASN1_OBJECT_push(param->policies, policy); } int X509_VERIFY_PARAM_set1_policies(X509_VERIFY_PARAM *param, @@ -350,8 +346,10 @@ int X509_VERIFY_PARAM_set1_policies(X509_VERIFY_PARAM *param, int i; ASN1_OBJECT *oid, *doid; - if (param == NULL) + if (param == NULL) { + ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER); return 0; + } sk_ASN1_OBJECT_pop_free(param->policies, ASN1_OBJECT_free); if (policies == NULL) { @@ -366,7 +364,7 @@ int X509_VERIFY_PARAM_set1_policies(X509_VERIFY_PARAM *param, for (i = 0; i < sk_ASN1_OBJECT_num(policies); i++) { oid = sk_ASN1_OBJECT_value(policies, i); doid = OBJ_dup(oid); - if (!doid) + if (doid == NULL) return 0; if (!sk_ASN1_OBJECT_push(param->policies, doid)) { ASN1_OBJECT_free(doid); @@ -424,7 +422,7 @@ void X509_VERIFY_PARAM_move_peername(X509_VERIFY_PARAM *to, OPENSSL_free(to->peername); to->peername = peername; } - if (from) + if (from != NULL) from->peername = NULL; } @@ -443,8 +441,10 @@ int X509_VERIFY_PARAM_set1_email(X509_VERIFY_PARAM *param, static unsigned char *int_X509_VERIFY_PARAM_get0_ip(X509_VERIFY_PARAM *param, size_t *plen) { - if (param == NULL || param->ip == NULL) + if (param == NULL || param->ip == NULL) { + ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER); return NULL; + } if (plen != NULL) *plen = param->iplen; return param->ip; @@ -455,14 +455,16 @@ char *X509_VERIFY_PARAM_get1_ip_asc(X509_VERIFY_PARAM *param) size_t iplen; unsigned char *ip = int_X509_VERIFY_PARAM_get0_ip(param, &iplen); - return ip == NULL ? NULL : ossl_ipaddr_to_asc(ip, iplen); + return ip == NULL ? NULL : ossl_ipaddr_to_asc(ip, iplen); } int X509_VERIFY_PARAM_set1_ip(X509_VERIFY_PARAM *param, const unsigned char *ip, size_t iplen) { - if (iplen != 0 && iplen != 4 && iplen != 16) + if (iplen != 0 && iplen != 4 && iplen != 16) { + ERR_raise(ERR_LIB_X509, ERR_R_PASSED_INVALID_ARGUMENT); return 0; + } return int_x509_param_set1((char **)¶m->ip, ¶m->iplen, (char *)ip, iplen); } @@ -470,9 +472,8 @@ int X509_VERIFY_PARAM_set1_ip(X509_VERIFY_PARAM *param, int X509_VERIFY_PARAM_set1_ip_asc(X509_VERIFY_PARAM *param, const char *ipasc) { unsigned char ipout[16]; - size_t iplen; + size_t iplen = (size_t)ossl_a2i_ipadd(ipout, ipasc); - iplen = (size_t)ossl_a2i_ipadd(ipout, ipasc); if (iplen == 0) return 0; return X509_VERIFY_PARAM_set1_ip(param, ipout, iplen); @@ -579,6 +580,7 @@ int X509_VERIFY_PARAM_add0_table(X509_VERIFY_PARAM *param) { int idx; X509_VERIFY_PARAM *ptmp; + if (param_table == NULL) { param_table = sk_X509_VERIFY_PARAM_new(param_cmp); if (param_table == NULL) @@ -590,15 +592,14 @@ int X509_VERIFY_PARAM_add0_table(X509_VERIFY_PARAM *param) X509_VERIFY_PARAM_free(ptmp); } } - if (!sk_X509_VERIFY_PARAM_push(param_table, param)) - return 0; - return 1; + return sk_X509_VERIFY_PARAM_push(param_table, param); } int X509_VERIFY_PARAM_get_count(void) { int num = OSSL_NELEM(default_table); - if (param_table) + + if (param_table != NULL) num += sk_X509_VERIFY_PARAM_num(param_table); return num; } @@ -606,6 +607,7 @@ int X509_VERIFY_PARAM_get_count(void) const X509_VERIFY_PARAM *X509_VERIFY_PARAM_get0(int id) { int num = OSSL_NELEM(default_table); + if (id < num) return default_table + id; return sk_X509_VERIFY_PARAM_value(param_table, id - num); diff --git a/crypto/x509/x_all.c b/crypto/x509/x_all.c index 87d5ce97e8..a8d36f1e59 100644 --- a/crypto/x509/x_all.c +++ b/crypto/x509/x_all.c @@ -30,7 +30,7 @@ int X509_verify(X509 *a, EVP_PKEY *r) { - if (X509_ALGOR_cmp(&a->sig_alg, &a->cert_info.signature)) + if (X509_ALGOR_cmp(&a->sig_alg, &a->cert_info.signature) != 0) return 0; return ASN1_item_verify_ex(ASN1_ITEM_rptr(X509_CINF), &a->sig_alg, @@ -59,25 +59,41 @@ int NETSCAPE_SPKI_verify(NETSCAPE_SPKI *a, EVP_PKEY *r) int X509_sign(X509 *x, EVP_PKEY *pkey, const EVP_MD *md) { - x->cert_info.enc.modified = 1; - return ASN1_item_sign_ex(ASN1_ITEM_rptr(X509_CINF), &x->cert_info.signature, - &x->sig_alg, &x->signature, &x->cert_info, NULL, - pkey, md, x->libctx, x->propq); + int ret; + + if (x == NULL) { + ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + ret = ASN1_item_sign_ex(ASN1_ITEM_rptr(X509_CINF), &x->cert_info.signature, + &x->sig_alg, &x->signature, &x->cert_info, NULL, + pkey, md, x->libctx, x->propq); + if (ret > 0) + x->cert_info.enc.modified = 1; + return ret; } int X509_sign_ctx(X509 *x, EVP_MD_CTX *ctx) { - x->cert_info.enc.modified = 1; - return ASN1_item_sign_ctx(ASN1_ITEM_rptr(X509_CINF), - &x->cert_info.signature, - &x->sig_alg, &x->signature, &x->cert_info, ctx); + int ret; + + if (x == NULL) { + ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + ret = ASN1_item_sign_ctx(ASN1_ITEM_rptr(X509_CINF), + &x->cert_info.signature, + &x->sig_alg, &x->signature, &x->cert_info, ctx); + if (ret > 0) + x->cert_info.enc.modified = 1; + return ret; } static ASN1_VALUE *simple_get_asn1(const char *url, BIO *bio, BIO *rbio, int timeout, const ASN1_ITEM *it) { BIO *mem = OSSL_HTTP_get(url, NULL /* proxy */, NULL /* no_proxy */, - bio, rbio, NULL /* cb */ , NULL /* arg */, + bio, rbio, NULL /* cb */, NULL /* arg */, 1024 /* buf_size */, NULL /* headers */, NULL /* expected_ct */, 1 /* expect_asn1 */, OSSL_HTTP_DEFAULT_MAX_RESP_LEN, timeout); @@ -95,32 +111,66 @@ X509 *X509_load_http(const char *url, BIO *bio, BIO *rbio, int timeout) int X509_REQ_sign(X509_REQ *x, EVP_PKEY *pkey, const EVP_MD *md) { - return ASN1_item_sign_ex(ASN1_ITEM_rptr(X509_REQ_INFO), &x->sig_alg, NULL, - x->signature, &x->req_info, NULL, - pkey, md, x->libctx, x->propq); + int ret; + + if (x == NULL) { + ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + ret = ASN1_item_sign_ex(ASN1_ITEM_rptr(X509_REQ_INFO), &x->sig_alg, NULL, + x->signature, &x->req_info, NULL, + pkey, md, x->libctx, x->propq); + if (ret > 0) + x->req_info.enc.modified = 1; + return ret; } int X509_REQ_sign_ctx(X509_REQ *x, EVP_MD_CTX *ctx) { - return ASN1_item_sign_ctx(ASN1_ITEM_rptr(X509_REQ_INFO), - &x->sig_alg, NULL, x->signature, &x->req_info, - ctx); + int ret; + + if (x == NULL) { + ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + ret = ASN1_item_sign_ctx(ASN1_ITEM_rptr(X509_REQ_INFO), + &x->sig_alg, NULL, x->signature, &x->req_info, + ctx); + if (ret > 0) + x->req_info.enc.modified = 1; + return ret; } int X509_CRL_sign(X509_CRL *x, EVP_PKEY *pkey, const EVP_MD *md) { - x->crl.enc.modified = 1; - return ASN1_item_sign_ex(ASN1_ITEM_rptr(X509_CRL_INFO), &x->crl.sig_alg, - &x->sig_alg, &x->signature, &x->crl, NULL, - pkey, md, x->libctx, x->propq); + int ret; + + if (x == NULL) { + ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + ret = ASN1_item_sign_ex(ASN1_ITEM_rptr(X509_CRL_INFO), &x->crl.sig_alg, + &x->sig_alg, &x->signature, &x->crl, NULL, + pkey, md, x->libctx, x->propq); + if (ret > 0) + x->crl.enc.modified = 1; + return ret; } int X509_CRL_sign_ctx(X509_CRL *x, EVP_MD_CTX *ctx) { - x->crl.enc.modified = 1; - return ASN1_item_sign_ctx(ASN1_ITEM_rptr(X509_CRL_INFO), - &x->crl.sig_alg, &x->sig_alg, &x->signature, - &x->crl, ctx); + int ret; + + if (x == NULL) { + ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + ret = ASN1_item_sign_ctx(ASN1_ITEM_rptr(X509_CRL_INFO), + &x->crl.sig_alg, &x->sig_alg, &x->signature, + &x->crl, ctx); + if (ret > 0) + x->crl.enc.modified = 1; + return ret; } X509_CRL *X509_CRL_load_http(const char *url, BIO *bio, BIO *rbio, int timeout) @@ -131,7 +181,8 @@ X509_CRL *X509_CRL_load_http(const char *url, BIO *bio, BIO *rbio, int timeout) int NETSCAPE_SPKI_sign(NETSCAPE_SPKI *x, EVP_PKEY *pkey, const EVP_MD *md) { - return ASN1_item_sign_ex(ASN1_ITEM_rptr(NETSCAPE_SPKAC), &x->sig_algor, NULL, + return + ASN1_item_sign_ex(ASN1_ITEM_rptr(NETSCAPE_SPKAC), &x->sig_algor, NULL, x->signature, x->spkac, NULL, pkey, md, NULL, NULL); } @@ -214,7 +265,6 @@ PKCS7 *d2i_PKCS7_bio(BIO *bp, PKCS7 **p7) propq = (*p7)->ctx.propq; } - ret = ASN1_item_d2i_bio_ex(ASN1_ITEM_rptr(PKCS7), bp, p7, libctx, propq); if (ret != NULL) ossl_pkcs7_resolve_libctx(ret); @@ -411,9 +461,9 @@ int i2d_ECPrivateKey_bio(BIO *bp, const EC_KEY *eckey) int X509_pubkey_digest(const X509 *data, const EVP_MD *type, unsigned char *md, unsigned int *len) { - ASN1_BIT_STRING *key; - key = X509_get0_pubkey_bitstr(data); - if (!key) + ASN1_BIT_STRING *key = X509_get0_pubkey_bitstr(data); + + if (key == NULL) return 0; return EVP_Digest(key->data, key->length, md, len, type, NULL); } @@ -469,7 +519,7 @@ ASN1_OCTET_STRING *X509_digest_sig(const X509 *cert, || !ossl_rsa_pss_get_param_unverified(pss, &mmd, &mgf1md, &saltlen, &trailerfield) - || mmd == NULL) { + || mmd == NULL) { RSA_PSS_PARAMS_free(pss); ERR_raise(ERR_LIB_X509, X509_R_UNSUPPORTED_ALGORITHM); return NULL; @@ -512,7 +562,7 @@ ASN1_OCTET_STRING *X509_digest_sig(const X509 *cert, if (!X509_digest(cert, md, hash, &len) || (new = ASN1_OCTET_STRING_new()) == NULL) goto err; - if ((ASN1_OCTET_STRING_set(new, hash, len))) { + if (ASN1_OCTET_STRING_set(new, hash, len)) { if (md_used != NULL) *md_used = md; else diff --git a/demos/cipher/Makefile b/demos/cipher/Makefile index b4f08a3746..81f526535e 100644 --- a/demos/cipher/Makefile +++ b/demos/cipher/Makefile @@ -7,18 +7,21 @@ # # LD_LIBRARY_PATH=../.. ./aesccm # LD_LIBRARY_PATH=../.. ./aesgcm +# LD_LIBRARY_PATH=../.. ./aeskeywrap +# LD_LIBRARY_PATH=../.. ./ariacbc CFLAGS = $(OPENSSL_INCS_LOCATION) LDFLAGS = $(OPENSSL_LIBS_LOCATION) -lssl -lcrypto -all: aesccm aesgcm ariacbc +all: aesccm aesgcm aeskeywrap ariacbc aesccm: aesccm.o aesgcm: aesgcm.o +aeskeywrap: aeskeywrap.o ariacbc: ariacbc.o -aesccm aesgcm ariacbc: +aesccm aesgcm aeskeywrap ariacbc: $(CC) $(CFLAGS) -o $@ $< $(LDFLAGS) clean: - $(RM) aesccm aesgcm ariacbc *.o + $(RM) aesccm aesgcm aeskeywrap ariacbc *.o diff --git a/demos/cipher/aeskeywrap.c b/demos/cipher/aeskeywrap.c new file mode 100644 index 0000000000..f987772e4f --- /dev/null +++ b/demos/cipher/aeskeywrap.c @@ -0,0 +1,181 @@ +/* + * Copyright 2022 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 + */ + +/* + * Simple aes wrap encryption demonstration program. + */ + +#include +#include +#include +#include +#include +#include + +/* aes key */ +static const unsigned char wrap_key[] = { + 0xee, 0xbc, 0x1f, 0x57, 0x48, 0x7f, 0x51, 0x92, 0x1c, 0x04, 0x65, 0x66, + 0x5f, 0x8a, 0xe6, 0xd1, 0x65, 0x8b, 0xb2, 0x6d, 0xe6, 0xf8, 0xa0, 0x69, + 0xa3, 0x52, 0x02, 0x93, 0xa5, 0x72, 0x07, 0x8f +}; + +/* Unique initialisation vector */ +static const unsigned char wrap_iv[] = { + 0x99, 0xaa, 0x3e, 0x68, 0xed, 0x81, 0x73, 0xa0, 0xee, 0xd0, 0x66, 0x84, + 0x99, 0xaa, 0x3e, 0x68, +}; + +/* Example plaintext to encrypt */ +static const unsigned char wrap_pt[] = { + 0xad, 0x4f, 0xc9, 0xfc, 0x77, 0x69, 0xc9, 0xea, 0xfc, 0xdf, 0x00, 0xac, + 0x34, 0xec, 0x40, 0xbc, 0x28, 0x3f, 0xa4, 0x5e, 0xd8, 0x99, 0xe4, 0x5d, + 0x5e, 0x7a, 0xc4, 0xe6, 0xca, 0x7b, 0xa5, 0xb7, +}; + +/* Expected ciphertext value */ +static const unsigned char wrap_ct[] = { + 0x97, 0x99, 0x55, 0xca, 0xf6, 0x3e, 0x95, 0x54, 0x39, 0xd6, 0xaf, 0x63, 0xff, 0x2c, 0xe3, 0x96, + 0xf7, 0x0d, 0x2c, 0x9c, 0xc7, 0x43, 0xc0, 0xb6, 0x31, 0x43, 0xb9, 0x20, 0xac, 0x6b, 0xd3, 0x67, + 0xad, 0x01, 0xaf, 0xa7, 0x32, 0x74, 0x26, 0x92, +}; + +/* + * A library context and property query can be used to select & filter + * algorithm implementations. If they are NULL then the default library + * context and properties are used. + */ +OSSL_LIB_CTX *libctx = NULL; +const char *propq = NULL; + +int aes_wrap_encrypt(void) +{ + int ret = 0; + EVP_CIPHER_CTX *ctx; + EVP_CIPHER *cipher = NULL; + int outlen, tmplen; + unsigned char outbuf[1024]; + + printf("aes wrap Encrypt:\n"); + printf("Plaintext:\n"); + BIO_dump_fp(stdout, wrap_pt, sizeof(wrap_pt)); + + /* Create a context for the encrypt operation */ + if ((ctx = EVP_CIPHER_CTX_new()) == NULL) + goto err; + + EVP_CIPHER_CTX_set_flags(ctx, EVP_CIPHER_CTX_FLAG_WRAP_ALLOW); + + /* Fetch the cipher implementation */ + if ((cipher = EVP_CIPHER_fetch(libctx, "AES-256-WRAP", propq)) == NULL) + goto err; + + /* + * Initialise an encrypt operation with the cipher/mode, key and IV. + * We are not setting any custom params so let params be just NULL. + */ + if (!EVP_EncryptInit_ex2(ctx, cipher, wrap_key, wrap_iv, /* params */ NULL)) + goto err; + + /* Encrypt plaintext */ + if (!EVP_EncryptUpdate(ctx, outbuf, &outlen, wrap_pt, sizeof(wrap_pt))) + goto err; + + /* Finalise: there can be some additional output from padding */ + if (!EVP_EncryptFinal_ex(ctx, outbuf + outlen, &tmplen)) + goto err; + outlen += tmplen; + + /* Output encrypted block */ + printf("Ciphertext (outlen:%d):\n", outlen); + BIO_dump_fp(stdout, outbuf, outlen); + + if (sizeof(wrap_ct) == outlen && !CRYPTO_memcmp(outbuf, wrap_ct, outlen)) + printf("Final ciphertext matches expected ciphertext\n"); + else + printf("Final ciphertext differs from expected ciphertext\n"); + + ret = 1; +err: + if (!ret) + ERR_print_errors_fp(stderr); + + EVP_CIPHER_free(cipher); + EVP_CIPHER_CTX_free(ctx); + + return ret; +} + +int aes_wrap_decrypt(void) +{ + int ret = 0; + EVP_CIPHER_CTX *ctx; + EVP_CIPHER *cipher = NULL; + int outlen, tmplen; + unsigned char outbuf[1024]; + + printf("aes wrap Decrypt:\n"); + printf("Ciphertext:\n"); + BIO_dump_fp(stdout, wrap_ct, sizeof(wrap_ct)); + + if ((ctx = EVP_CIPHER_CTX_new()) == NULL) + goto err; + + EVP_CIPHER_CTX_set_flags(ctx, EVP_CIPHER_CTX_FLAG_WRAP_ALLOW); + + /* Fetch the cipher implementation */ + if ((cipher = EVP_CIPHER_fetch(libctx, "aes-256-wrap", propq)) == NULL) + goto err; + + /* + * Initialise an encrypt operation with the cipher/mode, key and IV. + * We are not setting any custom params so let params be just NULL. + */ + if (!EVP_DecryptInit_ex2(ctx, cipher, wrap_key, wrap_iv, /* params */ NULL)) + goto err; + + /* Decrypt plaintext */ + if (!EVP_DecryptUpdate(ctx, outbuf, &outlen, wrap_ct, sizeof(wrap_ct))) + goto err; + + /* Finalise: there can be some additional output from padding */ + if (!EVP_DecryptFinal_ex(ctx, outbuf + outlen, &tmplen)) + goto err; + outlen += tmplen; + + /* Output decrypted block */ + printf("Plaintext (outlen:%d):\n", outlen); + BIO_dump_fp(stdout, outbuf, outlen); + + if (sizeof(wrap_pt) == outlen && !CRYPTO_memcmp(outbuf, wrap_pt, outlen)) + printf("Final plaintext matches original plaintext\n"); + else + printf("Final plaintext differs from original plaintext\n"); + + ret = 1; +err: + if (!ret) + ERR_print_errors_fp(stderr); + + EVP_CIPHER_free(cipher); + EVP_CIPHER_CTX_free(ctx); + + return ret; +} + +int main(int argc, char **argv) +{ + if (!aes_wrap_encrypt()) + return 1; + + if (!aes_wrap_decrypt()) + return 1; + + return 0; +} + diff --git a/demos/encode/Makefile b/demos/encode/Makefile new file mode 100644 index 0000000000..b88d76b51d --- /dev/null +++ b/demos/encode/Makefile @@ -0,0 +1,20 @@ +# +# To run the demos when linked with a shared library (default): +# +# LD_LIBRARY_PATH=../.. ./rsa_encode + +CFLAGS = -I../../include -g -Wall +LDFLAGS = -L../.. +LDLIBS = -lcrypto + +all: ec_encode rsa_encode + +%.o: %.c + $(CC) $(CFLAGS) -c $< + +%_encode: %_encode.o + +test: ; + +clean: + $(RM) *.o rsa_encode ec_encode diff --git a/demos/encode/ec_encode.c b/demos/encode/ec_encode.c new file mode 100644 index 0000000000..8c296fbad8 --- /dev/null +++ b/demos/encode/ec_encode.c @@ -0,0 +1,205 @@ +/*- + * Copyright 2022 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 +#include +#include + +/* + * Example showing the encoding and decoding of EC public and private keys. A + * PEM-encoded EC key is read in from stdin, decoded, and then re-encoded and + * output for demonstration purposes. Both public and private keys are accepted. + * + * This can be used to load EC keys from a file or save EC keys to a file. + */ + +/* A property query used for selecting algorithm implementations. */ +static const char *propq = NULL; + +/* + * Load a PEM-encoded EC key from a file, optionally decrypting it with a + * supplied passphrase. + */ +static EVP_PKEY *load_key(OSSL_LIB_CTX *libctx, FILE *f, const char *passphrase) +{ + int rv = 0; + EVP_PKEY *pkey = NULL; + OSSL_DECODER_CTX *dctx = NULL; + int selection = 0; + + /* + * Create PEM decoder context expecting an EC key. + * + * For raw (non-PEM-encoded) keys, change "PEM" to "DER". + * + * The selection argument here specifies whether we are willing to accept a + * public key, private key, or either. If it is set to zero, either will be + * accepted. If set to EVP_PKEY_KEYPAIR, a private key will be required, and + * if set to EVP_PKEY_PUBLIC_KEY, a public key will be required. + */ + dctx = OSSL_DECODER_CTX_new_for_pkey(&pkey, "PEM", NULL, "EC", + selection, + libctx, propq); + if (dctx == NULL) { + fprintf(stderr, "OSSL_DECODER_CTX_new_for_pkey() failed\n"); + goto cleanup; + } + + /* + * Set passphrase if provided; needed to decrypt encrypted PEM files. + * If the input is not encrypted, any passphrase provided is ignored. + * + * Alternative methods for specifying passphrases exist, such as a callback + * (see OSSL_DECODER_CTX_set_passphrase_cb(3)), which may be more useful for + * interactive applications which do not know if a passphrase should be + * prompted for in advance, or for GUI applications. + */ + if (passphrase != NULL) { + if (OSSL_DECODER_CTX_set_passphrase(dctx, + (const unsigned char *)passphrase, + strlen(passphrase)) == 0) { + fprintf(stderr, "OSSL_DECODER_CTX_set_passphrase() failed\n"); + goto cleanup; + } + } + + /* Do the decode, reading from file. */ + if (OSSL_DECODER_from_fp(dctx, f) == 0) { + fprintf(stderr, "OSSL_DECODER_from_fp() failed\n"); + goto cleanup; + } + + rv = 1; +cleanup: + OSSL_DECODER_CTX_free(dctx); + + /* + * pkey is created by OSSL_DECODER_CTX_new_for_pkey, but we + * might fail subsequently, so ensure it's properly freed + * in this case. + */ + if (rv == 0) { + EVP_PKEY_free(pkey); + pkey = NULL; + } + + return pkey; +} + +/* + * Store a EC public or private key to a file using PEM encoding. + * + * If a passphrase is supplied, the file is encrypted, otherwise + * it is unencrypted. + */ +static int store_key(EVP_PKEY *pkey, FILE *f, const char *passphrase) +{ + int rv = 0; + int selection; + OSSL_ENCODER_CTX *ectx = NULL; + + /* + * Create a PEM encoder context. + * + * For raw (non-PEM-encoded) output, change "PEM" to "DER". + * + * The selection argument controls whether the private key is exported + * (EVP_PKEY_KEYPAIR), or only the public key (EVP_PKEY_PUBLIC_KEY). The + * former will fail if we only have a public key. + * + * Note that unlike the decode API, you cannot specify zero here. + * + * Purely for the sake of demonstration, here we choose to export the whole + * key if a passphrase is provided and the public key otherwise. + */ + selection = (passphrase != NULL) + ? EVP_PKEY_KEYPAIR + : EVP_PKEY_PUBLIC_KEY; + + ectx = OSSL_ENCODER_CTX_new_for_pkey(pkey, selection, "PEM", NULL, propq); + if (ectx == NULL) { + fprintf(stderr, "OSSL_ENCODER_CTX_new_for_pkey() failed\n"); + goto cleanup; + } + + /* + * Set passphrase if provided; the encoded output will then be encrypted + * using the passphrase. + * + * Alternative methods for specifying passphrases exist, such as a callback + * (see OSSL_ENCODER_CTX_set_passphrase_cb(3), just as for OSSL_DECODER_CTX; + * however you are less likely to need them as you presumably know whether + * encryption is desired in advance. + * + * Note that specifying a passphrase alone is not enough to cause the + * key to be encrypted. You must set both a cipher and a passphrase. + */ + if (passphrase != NULL) { + /* + * Set cipher. Let's use AES-256-CBC, because it is + * more quantum resistant. + */ + if (OSSL_ENCODER_CTX_set_cipher(ectx, "AES-256-CBC", propq) == 0) { + fprintf(stderr, "OSSL_ENCODER_CTX_set_cipher() failed\n"); + goto cleanup; + } + + /* Set passphrase. */ + if (OSSL_ENCODER_CTX_set_passphrase(ectx, + (const unsigned char *)passphrase, + strlen(passphrase)) == 0) { + fprintf(stderr, "OSSL_ENCODER_CTX_set_passphrase() failed\n"); + goto cleanup; + } + } + + /* Do the encode, writing to the given file. */ + if (OSSL_ENCODER_to_fp(ectx, f) == 0) { + fprintf(stderr, "OSSL_ENCODER_to_fp() failed\n"); + goto cleanup; + } + + rv = 1; +cleanup: + OSSL_ENCODER_CTX_free(ectx); + return rv; +} + +int main(int argc, char **argv) +{ + int rv = 1; + OSSL_LIB_CTX *libctx = NULL; + EVP_PKEY *pkey = NULL; + const char *passphrase_in = NULL, *passphrase_out = NULL; + + /* usage: ec_encode */ + if (argc > 1 && argv[1][0]) + passphrase_in = argv[1]; + + if (argc > 2 && argv[2][0]) + passphrase_out = argv[2]; + + /* Decode PEM key from stdin and then PEM encode it to stdout. */ + pkey = load_key(libctx, stdin, passphrase_in); + if (pkey == NULL) { + fprintf(stderr, "Failed to decode key\n"); + goto cleanup; + } + + if (store_key(pkey, stdout, passphrase_out) == 0) { + fprintf(stderr, "Failed to encode key\n"); + goto cleanup; + } + + rv = 0; +cleanup: + EVP_PKEY_free(pkey); + OSSL_LIB_CTX_free(libctx); + return rv; +} diff --git a/doc/build.info b/doc/build.info index 7e86de588a..36a792c2bd 100644 --- a/doc/build.info +++ b/doc/build.info @@ -1495,6 +1495,10 @@ DEPEND[html/man3/OPENSSL_fork_prepare.html]=man3/OPENSSL_fork_prepare.pod GENERATE[html/man3/OPENSSL_fork_prepare.html]=man3/OPENSSL_fork_prepare.pod DEPEND[man/man3/OPENSSL_fork_prepare.3]=man3/OPENSSL_fork_prepare.pod GENERATE[man/man3/OPENSSL_fork_prepare.3]=man3/OPENSSL_fork_prepare.pod +DEPEND[html/man3/OPENSSL_gmtime.html]=man3/OPENSSL_gmtime.pod +GENERATE[html/man3/OPENSSL_gmtime.html]=man3/OPENSSL_gmtime.pod +DEPEND[man/man3/OPENSSL_gmtime.3]=man3/OPENSSL_gmtime.pod +GENERATE[man/man3/OPENSSL_gmtime.3]=man3/OPENSSL_gmtime.pod DEPEND[html/man3/OPENSSL_hexchar2int.html]=man3/OPENSSL_hexchar2int.pod GENERATE[html/man3/OPENSSL_hexchar2int.html]=man3/OPENSSL_hexchar2int.pod DEPEND[man/man3/OPENSSL_hexchar2int.3]=man3/OPENSSL_hexchar2int.pod @@ -3105,6 +3109,7 @@ html/man3/OPENSSL_LH_COMPFUNC.html \ html/man3/OPENSSL_LH_stats.html \ html/man3/OPENSSL_config.html \ html/man3/OPENSSL_fork_prepare.html \ +html/man3/OPENSSL_gmtime.html \ html/man3/OPENSSL_hexchar2int.html \ html/man3/OPENSSL_ia32cap.html \ html/man3/OPENSSL_init_crypto.html \ @@ -3700,6 +3705,7 @@ man/man3/OPENSSL_LH_COMPFUNC.3 \ man/man3/OPENSSL_LH_stats.3 \ man/man3/OPENSSL_config.3 \ man/man3/OPENSSL_fork_prepare.3 \ +man/man3/OPENSSL_gmtime.3 \ man/man3/OPENSSL_hexchar2int.3 \ man/man3/OPENSSL_ia32cap.3 \ man/man3/OPENSSL_init_crypto.3 \ diff --git a/doc/man1/openssl-cmp.pod.in b/doc/man1/openssl-cmp.pod.in index ee62833f8e..2982b2ad0b 100644 --- a/doc/man1/openssl-cmp.pod.in +++ b/doc/man1/openssl-cmp.pod.in @@ -266,11 +266,11 @@ L. X509 Distinguished Name (DN) of subject to use in the requested certificate template. -For KUR, it defaults to the public key -in the PKCS#10 CSR given with the B<-csr> option, if provided, -or of the reference certificate (see B<-oldcert>) if provided. -This default is used for IR and CR only if no SANs are set. If the NULL-DN (C<"/">) is given then no subject is placed in the template. +Default is the subject DN of any PKCS#10 CSR given with the B<-csr> option. +For KUR, a further fallback is the subject DN +of the reference certificate (see B<-oldcert>) if provided. +This fallback is used for IR and CR only if no SANs are set. If provided and neither B<-cert> nor B<-oldcert> is given, the subject DN is used as fallback sender of outgoing CMP messages. @@ -354,8 +354,9 @@ is provided via the B<-newkey> or B<-key> options. PKCS#10 CSR in PEM or DER format containing a certificate request. With B<-cmd> I it is used directly in a legacy P10CR message. -When used with B<-cmd> I, I, or I, it is transformed into the -respective regular CMP request. +When used with B<-cmd> I, I, or I, +it is transformed into the respective regular CMP request, +while its public key is ignored if I<-newkey> is given. It may also be used with B<-cmd> I to specify the certificate to be revoked via the included subject name and public key. diff --git a/doc/man1/openssl-dgst.pod.in b/doc/man1/openssl-dgst.pod.in index 8a091131cf..5dcdbe548e 100644 --- a/doc/man1/openssl-dgst.pod.in +++ b/doc/man1/openssl-dgst.pod.in @@ -86,7 +86,20 @@ Output the digest or signature in binary form. =item B<-xoflen> I -Set the output length for XOF algorithms, such as B. +Set the output length for XOF algorithms, such as B and B. +This option is not supported for signing operations. + +For OpenSSL providers it is recommended to set this value for shake algorithms, +since the default values are set to only supply half of the maximum security +strength. + +For backwards compatibility reasons the default xoflen length for B is +16 (bytes) which results in a security strength of only 64 bits. To ensure the +maximum security strength of 128 bits, the xoflen should be set to at least 32. + +For backwards compatibility reasons the default xoflen length for B is +32 (bytes) which results in a security strength of only 128 bits. To ensure the +maximum security strength of 256 bits, the xoflen should be set to at least 64. =item B<-r> diff --git a/doc/man1/openssl-mac.pod.in b/doc/man1/openssl-mac.pod.in index e76e185e08..452c546637 100644 --- a/doc/man1/openssl-mac.pod.in +++ b/doc/man1/openssl-mac.pod.in @@ -35,8 +35,7 @@ Print a usage message. Input filename to calculate a MAC for, or standard input by default. Standard input is used if the filename is '-'. -Files are expected to be in binary format, standard input uses hexadecimal text -format. +Files and standard input are expected to be in binary format. =item B<-out> I diff --git a/doc/man1/openssl-pkcs12.pod.in b/doc/man1/openssl-pkcs12.pod.in index 92503dc914..69ed46d76f 100644 --- a/doc/man1/openssl-pkcs12.pod.in +++ b/doc/man1/openssl-pkcs12.pod.in @@ -341,7 +341,7 @@ then both, the private key and the certificates are encrypted using triple DES. =item B<-macalg> I -Specify the MAC digest algorithm. If not included SHA1 will be used. +Specify the MAC digest algorithm. If not included SHA256 will be used. =item B<-iter> I diff --git a/doc/man1/openssl.pod b/doc/man1/openssl.pod index 5c7bf94657..d673d49cc9 100644 --- a/doc/man1/openssl.pod +++ b/doc/man1/openssl.pod @@ -11,16 +11,6 @@ I [ I ... ] [ I ... ] -B -B -B | -B | -B | -B | -B | -B | -B - B BI [ I ] =head1 DESCRIPTION @@ -50,21 +40,8 @@ Each command can have many options and argument parameters, shown above as I and I. Detailed documentation and use cases for most standard subcommands are available -(e.g., L). - -The list options B<-standard-commands>, B<-digest-commands>, -and B<-cipher-commands> output a list (one entry per line) of the names -of all standard commands, message digest commands, or cipher commands, -respectively, that are available. - -The list parameters B<-cipher-algorithms>, B<-digest-algorithms>, -and B<-mac-algorithms> list all cipher, message digest, and message -authentication code names, one entry per line. Aliases are listed as: - - from => to - -The list parameter B<-public-key-algorithms> lists all supported public -key algorithms. +(e.g., L). The subcommand L may be used to list +subcommands. The command BI tests whether a command of the specified name is available. If no command named I exists, it @@ -799,6 +776,7 @@ L, L, L, L, +L, L, L, L, diff --git a/doc/man3/BIO_ctrl.pod b/doc/man3/BIO_ctrl.pod index d07d8db614..ce31b2254c 100644 --- a/doc/man3/BIO_ctrl.pod +++ b/doc/man3/BIO_ctrl.pod @@ -100,7 +100,9 @@ BIO_get_close() returns the close flag value: BIO_CLOSE or BIO_NOCLOSE. It also returns other negative values if an error occurs. BIO_pending(), BIO_ctrl_pending(), BIO_wpending() and BIO_ctrl_wpending() -return the amount of pending data. +return the amount of pending data. BIO_pending() and BIO_wpending() return +negative value or 0 on error. BIO_ctrl_pending() and BIO_ctrl_wpending() return +0 on error. BIO_get_ktls_send() returns 1 if the BIO is using the Kernel TLS data-path for sending. Otherwise, it returns zero. @@ -139,6 +141,9 @@ particular a return value of 0 can be returned if an operation is not supported, if an error occurred, if EOF has not been reached and in the case of BIO_seek() on a file BIO for a successful operation. +In older versions of OpenSSL the BIO_ctrl_pending() and +BIO_ctrl_wpending() could return values greater than INT_MAX on error. + =head1 HISTORY The BIO_get_ktls_send() and BIO_get_ktls_recv() macros were added in diff --git a/doc/man3/BIO_f_ssl.pod b/doc/man3/BIO_f_ssl.pod index c6dc53c105..365168646a 100644 --- a/doc/man3/BIO_f_ssl.pod +++ b/doc/man3/BIO_f_ssl.pod @@ -243,13 +243,20 @@ a client and also echoes the request to standard output. BIO_set_accept_bios(acpt, sbio); out = BIO_new_fp(stdout, BIO_NOCLOSE); - /* Setup accept BIO */ + /* First call to BIO_do_accept() sets up accept BIO */ if (BIO_do_accept(acpt) <= 0) { fprintf(stderr, "Error setting up accept BIO\n"); ERR_print_errors_fp(stderr); exit(1); } +/* Second call to BIO_do_accept() waits for incoming connection */ + if (BIO_do_accept(acpt) <= 0) { + fprintf(stderr, "Error accepting connection\n"); + ERR_print_errors_fp(stderr); + exit(1); + } + /* We only want one connection so remove and free accept BIO */ sbio = BIO_pop(acpt); BIO_free_all(acpt); diff --git a/doc/man3/BIO_s_accept.pod b/doc/man3/BIO_s_accept.pod index c3826a609f..f6df26a52d 100644 --- a/doc/man3/BIO_s_accept.pod +++ b/doc/man3/BIO_s_accept.pod @@ -189,7 +189,7 @@ down each and finally closes both down. BIO *abio, *cbio, *cbio2; - /* First call to BIO_accept() sets up accept BIO */ + /* First call to BIO_do_accept() sets up accept BIO */ abio = BIO_new_accept("4444"); if (BIO_do_accept(abio) <= 0) { fprintf(stderr, "Error setting up accept\n"); diff --git a/doc/man3/EVP_PBE_CipherInit.pod b/doc/man3/EVP_PBE_CipherInit.pod index 8f2a53397e..c3b551e602 100644 --- a/doc/man3/EVP_PBE_CipherInit.pod +++ b/doc/man3/EVP_PBE_CipherInit.pod @@ -3,7 +3,8 @@ =head1 NAME EVP_PBE_CipherInit, EVP_PBE_CipherInit_ex, -EVP_PBE_find, EVP_PBE_find_ex - Password based encryption routines +EVP_PBE_find, EVP_PBE_find_ex, +EVP_PBE_alg_add_type, EVP_PBE_alg_add - Password based encryption routines =head1 SYNOPSIS @@ -20,6 +21,11 @@ EVP_PBE_find, EVP_PBE_find_ex - Password based encryption routines int EVP_PBE_find_ex(int type, int pbe_nid, int *pcnid, int *pmnid, EVP_PBE_KEYGEN **pkeygen, EVP_PBE_KEYGEN_EX **keygen_ex); + int EVP_PBE_alg_add_type(int pbe_type, int pbe_nid, int cipher_nid, + int md_nid, EVP_PBE_KEYGEN *keygen); + int EVP_PBE_alg_add(int nid, const EVP_CIPHER *cipher, const EVP_MD *md, + EVP_PBE_KEYGEN *keygen); + =head1 DESCRIPTION =head2 PBE operations @@ -66,6 +72,12 @@ context and property query. If a NULL is supplied for any of I, I, I or I then this parameter is not returned. +=head2 PBE algorithm add + +EVP_PBE_alg_add_type() and EVP_PBE_alg_add() add an algorithm to the list +of known algorithms. Their parameters have the same meaning as for +EVP_PBE_find() and EVP_PBE_find_ex() functions. + =head1 NOTES The arguments I and I to EVP_PBE_CipherInit() and EVP_PBE_CipherInit_ex() diff --git a/doc/man3/EVP_PKEY_CTX_set_hkdf_md.pod b/doc/man3/EVP_PKEY_CTX_set_hkdf_md.pod index 15b908e540..81ee5c485b 100644 --- a/doc/man3/EVP_PKEY_CTX_set_hkdf_md.pod +++ b/doc/man3/EVP_PKEY_CTX_set_hkdf_md.pod @@ -99,7 +99,7 @@ A context for HKDF can be obtained by calling: EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, NULL); -The total length of the info buffer cannot exceed 1024 bytes in length: this +The total length of the info buffer cannot exceed 2048 bytes in length: this should be more than enough for any normal use of HKDF. The output length of an HKDF expand operation is specified via the length diff --git a/doc/man3/EVP_PKEY_fromdata.pod b/doc/man3/EVP_PKEY_fromdata.pod index fdab94cd4f..158d1bf42d 100644 --- a/doc/man3/EVP_PKEY_fromdata.pod +++ b/doc/man3/EVP_PKEY_fromdata.pod @@ -53,6 +53,9 @@ the settable parameters that can be used with EVP_PKEY_fromdata(). I is described in L. See L for the use of B as parameter descriptor. +Parameters in the I array that are not among the settable parameters +for the given I are ignored. + =head2 Selections The following constants can be used for I: diff --git a/doc/man3/OPENSSL_gmtime.pod b/doc/man3/OPENSSL_gmtime.pod new file mode 100644 index 0000000000..b86557f3ca --- /dev/null +++ b/doc/man3/OPENSSL_gmtime.pod @@ -0,0 +1,62 @@ +=pod + +=head1 NAME + +OPENSSL_gmtime, +OPENSSL_gmtime_adj, +OPENSSL_gmtime_diff - platform-agnostic OpenSSL time routines + +=head1 SYNOPSIS + + #include + + struct tm *OPENSSL_gmtime(const time_t *timer, struct tm *result); + int OPENSSL_gmtime_adj(struct tm *tm, int offset_day, long offset_sec); + int OPENSSL_gmtime_diff(int *pday, int *psec, + const struct tm *from, const struct tm *to); + +=head1 DESCRIPTION + +OPENSSL_gmtime() returns the UTC time specified by I into the provided +I argument. + +OPENSSL_gmtime_adj() adds the offsets in I and I to I. + +OPENSSL_gmtime_diff() calculates the difference between I and I. + +=head1 NOTES + +It is an error to call OPENSSL_gmtime() with I equal to NULL. The +contents of the time_t given by I are stored into the I. Calling +with I equal to NULL means use the current time. + +OPENSSL_gmtime_adj() converts I into a days and seconds value, adds the +offsets, then converts back into a I specified by I. Leap seconds +are not considered. + +OPENSSL_gmtime_diff() calculates the difference between the two I +structures I and I. The difference in days is placed into I<*pday>, +the remaining seconds are placed to I<*psec>. The value in I<*psec> will be less +than the number of seconds per day (3600). Leap seconds are not considered. + +=head1 RETURN VALUES + +OPENSSL_gmtime() returns NULL on error, or I on success. + +OPENSSL_gmtime_adj() and OPENSSL_gmtime_diff() return 0 on error, and 1 on success. + +=head1 HISTORY + +OPENSSL_gmtime(), OPENSSL_gmtime_adj() and OPENSSL_gmtime_diff() have been +in OpenSSL since 1.0.0. + +=head1 COPYRIGHT + +Copyright 2022 The OpenSSL Project Authors. All Rights Reserved. + +Licensed under the Apache License 2.0 (the "License"). You may not use +this file except in compliance with the License. You can obtain a copy +in the file LICENSE in the source distribution or at +L. + +=cut diff --git a/doc/man3/OPENSSL_malloc.pod b/doc/man3/OPENSSL_malloc.pod index 99a76e000d..7dc6468f0e 100644 --- a/doc/man3/OPENSSL_malloc.pod +++ b/doc/man3/OPENSSL_malloc.pod @@ -149,12 +149,12 @@ other allocations (until the program exits or crashes) have a 25% chance of failing. If the variable B is parsed as a positive integer, then -it is taken as an open file descriptor, and a record of all allocations is -written to that descriptor. If an allocation will fail, and the platform -supports it, then a backtrace will be written to the descriptor. This can -be useful because a malloc may fail but not be checked, and problems will -only occur later. The following example in classic shell syntax shows how -to use this (will not work on all platforms): +it is taken as an open file descriptor. This is used in conjunction with +B described above. For every allocation it will log +details about how many allocations there have been so far, what percentage +chance there is for this allocation failing, and whether it has actually failed. +The following example in classic shell syntax shows how to use this (will not +work on all platforms): OPENSSL_MALLOC_FAILURES='200;@10' export OPENSSL_MALLOC_FAILURES @@ -179,10 +179,11 @@ CRYPTO_set_mem_functions() returns 1 on success or 0 on failure (almost always because allocations have already happened). CRYPTO_mem_leaks(), CRYPTO_mem_leaks_fp(), CRYPTO_mem_leaks_cb(), -CRYPTO_set_mem_debug(), and CRYPTO_mem_ctrl() are deprecated and return -1. +CRYPTO_set_mem_debug(), and CRYPTO_mem_ctrl() are deprecated and are no-ops that +always return -1. OPENSSL_mem_debug_push(), OPENSSL_mem_debug_pop(), CRYPTO_mem_debug_push(), and CRYPTO_mem_debug_pop() -are deprecated and return 0. +are deprecated and are no-ops that always return 0. =head1 HISTORY diff --git a/doc/man3/OSSL_CMP_MSG_get0_header.pod b/doc/man3/OSSL_CMP_MSG_get0_header.pod index 76e24e1bad..6fc620f83b 100644 --- a/doc/man3/OSSL_CMP_MSG_get0_header.pod +++ b/doc/man3/OSSL_CMP_MSG_get0_header.pod @@ -45,12 +45,14 @@ the first available value of these: =over 4 -=item any subject name in I set via L, +=item any subject name in I set via L - +if it is the NULL-DN (i.e., any empty sequence of RDNs), no subject is included, -=item the subject field of any PKCS#10 CSR is given in I, or +=item the subject field of any PKCS#10 CSR set in I +via L, =item the subject field of any reference certificate given in I -(see L), if I is nonzero +(see L), but only if I is nonzero or the I does not include a Subject Alternative Name. =back @@ -61,9 +63,9 @@ The public key included is the first available value of these: =item the public key derived from any key set via L, -=item the public key of any PKCS#10 CSR is given in I, +=item the public key of any PKCS#10 CSR given in I, -=item the public key of any reference certificate given in I, or +=item the public key of any reference certificate given in I, =item the public key derived from any client's private key set via L. @@ -108,7 +110,7 @@ or NULL if the respective entry does not exist and on error. OSSL_CMP_MSG_get_bodytype() returns the body type or -1 on error. -OSSL_CMP_CTX_setup_CRM() returns a pointer to a OSSL_CRMF_MSG on success, +OSSL_CMP_CTX_setup_CRM() returns a pointer to a B on success, NULL on error. d2i_OSSL_CMP_MSG_bio() returns the parsed message or NULL on error. @@ -121,6 +123,13 @@ the number of bytes successfully encoded or a negative value if an error occurs. OSSL_CMP_MSG_update_transactionID() returns 1 on success, 0 on error. +=head1 SEE ALSO + +L, L, +L, L, +L, L, +L, L + =head1 HISTORY The OpenSSL CMP support was added in OpenSSL 3.0. diff --git a/doc/man3/OSSL_LIB_CTX.pod b/doc/man3/OSSL_LIB_CTX.pod index 98a3896fe4..cf8bd8b067 100644 --- a/doc/man3/OSSL_LIB_CTX.pod +++ b/doc/man3/OSSL_LIB_CTX.pod @@ -83,7 +83,7 @@ B function returns then the new provider is available in the application's library context and will be similarly mirrored in the child library context. -OSSL_LIB_CTX_load_config() loads a configuration file using the given C. +OSSL_LIB_CTX_load_config() loads a configuration file using the given I. This can be used to associate a library context with providers that are loaded from a configuration. @@ -118,6 +118,8 @@ on error. OSSL_LIB_CTX_free() doesn't return any value. +OSSL_LIB_CTX_load_config() returns 1 on success, 0 on error. + =head1 HISTORY All of the functions described on this page were added in OpenSSL 3.0. diff --git a/doc/man3/OSSL_PROVIDER.pod b/doc/man3/OSSL_PROVIDER.pod index 3c18f5ca10..47e296c186 100644 --- a/doc/man3/OSSL_PROVIDER.pod +++ b/doc/man3/OSSL_PROVIDER.pod @@ -18,8 +18,8 @@ OSSL_PROVIDER_self_test typedef struct ossl_provider_st OSSL_PROVIDER; - void OSSL_PROVIDER_set_default_search_path(OSSL_LIB_CTX *libctx, - const char *path); + int OSSL_PROVIDER_set_default_search_path(OSSL_LIB_CTX *libctx, + const char *path); OSSL_PROVIDER *OSSL_PROVIDER_load(OSSL_LIB_CTX *libctx, const char *name); OSSL_PROVIDER *OSSL_PROVIDER_try_load(OSSL_LIB_CTX *libctx, const char *name, @@ -157,7 +157,8 @@ L. =head1 RETURN VALUES -OSSL_PROVIDER_add(), OSSL_PROVIDER_unload(), OSSL_PROVIDER_get_params() and +OSSL_PROVIDER_set_default_search_path(), OSSL_PROVIDER_add(), +OSSL_PROVIDER_unload(), OSSL_PROVIDER_get_params() and OSSL_PROVIDER_get_capabilities() return 1 on success, or 0 on error. OSSL_PROVIDER_load() and OSSL_PROVIDER_try_load() return a pointer to a diff --git a/doc/man3/X509_STORE_add_cert.pod b/doc/man3/X509_STORE_add_cert.pod index f53a345621..419690d3c0 100644 --- a/doc/man3/X509_STORE_add_cert.pod +++ b/doc/man3/X509_STORE_add_cert.pod @@ -115,7 +115,7 @@ X509_STORE_load_store() is similar to X509_STORE_load_store_ex() but uses NULL for the library context I and property query I. X509_STORE_load_locations_ex() combines -X509_STORE_load_file_ex() and X509_STORE_load_dir() for a given file +X509_STORE_load_file_ex() and X509_STORE_load_path() for a given file and/or directory path. It is permitted to specify just a file, just a directory, or both paths. diff --git a/doc/man3/X509_cmp_time.pod b/doc/man3/X509_cmp_time.pod index 73ef9e3fbc..30a09f25f9 100644 --- a/doc/man3/X509_cmp_time.pod +++ b/doc/man3/X509_cmp_time.pod @@ -3,7 +3,7 @@ =head1 NAME X509_cmp_time, X509_cmp_current_time, X509_cmp_timeframe, -X509_time_adj, X509_time_adj_ex +X509_time_adj, X509_time_adj_ex, X509_gmtime_adj - X509 time functions =head1 SYNOPSIS @@ -15,36 +15,41 @@ X509_time_adj, X509_time_adj_ex ASN1_TIME *X509_time_adj(ASN1_TIME *asn1_time, long offset_sec, time_t *in_tm); ASN1_TIME *X509_time_adj_ex(ASN1_TIME *asn1_time, int offset_day, long offset_sec, time_t *in_tm); + ASN1_TIME *X509_gmtime_adj(ASN1_TIME *asn1_time, long offset_sec); =head1 DESCRIPTION -X509_cmp_time() compares the ASN1_TIME in B with the time +X509_cmp_time() compares the ASN1_TIME in I with the time in . X509_cmp_current_time() compares the ASN1_TIME in -B with the current time, expressed as time_t. +I with the current time, expressed as time_t. X509_cmp_timeframe() compares the given time period with the reference time -included in the verification parameters B if they are not NULL and contain +included in the verification parameters I if they are not NULL and contain B; else the current time is used as reference time. -X509_time_adj_ex() sets the ASN1_TIME structure B to the time -B and B after B. +X509_time_adj_ex() sets the ASN1_TIME structure I to the time +I and I after I. -X509_time_adj() sets the ASN1_TIME structure B to the time -B after B. This method can only handle second +X509_time_adj() sets the ASN1_TIME structure I to the time +I after I. This method can only handle second offsets up to the capacity of long, so the newer X509_time_adj_ex() API should be preferred. -In both methods, if B is NULL, a new ASN1_TIME structure +In both methods, if I is NULL, a new ASN1_TIME structure is allocated and returned. -In all methods, if B is NULL, the current time, expressed as +In all methods, if I is NULL, the current time, expressed as time_t, is used. -B must satisfy the ASN1_TIME format mandated by RFC 5280, +I must satisfy the ASN1_TIME format mandated by RFC 5280, i.e., its format must be either YYMMDDHHMMSSZ or YYYYMMDDHHMMSSZ. +X509_gmtime_adj() sets the ASN1_TIME structure I to the time +I after the current time. It is equivalent to calling +X509_time_adj() with the last parameter as NULL. + =head1 BUGS Unlike many standard comparison functions, X509_cmp_time() and @@ -52,11 +57,11 @@ X509_cmp_current_time() return 0 on error. =head1 RETURN VALUES -X509_cmp_time() and X509_cmp_current_time() return -1 if B -is earlier than, or equal to, B (resp. current time), and 1 +X509_cmp_time() and X509_cmp_current_time() return -1 if I +is earlier than, or equal to, I (resp. current time), and 1 otherwise. These methods return 0 on error. -X509_cmp_timeframe() returns 0 if B is not NULL and the verification +X509_cmp_timeframe() returns 0 if I is not NULL and the verification parameters do not contain B but do contain B. Otherwise it returns 1 if the end time is not NULL and the reference time (which has determined as @@ -64,8 +69,8 @@ stated above) is past the end time, -1 if the start time is not NULL and the reference time is before, else 0 to indicate that the reference time is in range (implying that the end time is not before the start time if both are present). -X509_time_adj() and X509_time_adj_ex() return a pointer to the updated -ASN1_TIME structure, and NULL on error. +X509_time_adj(), X509_time_adj_ex() and X509_gmtime_adj() return a pointer to +the updated ASN1_TIME structure, and NULL on error. =head1 HISTORY diff --git a/doc/man7/EVP_MD-SHAKE.pod b/doc/man7/EVP_MD-SHAKE.pod index 2426d5a4a2..8a31cd53a8 100644 --- a/doc/man7/EVP_MD-SHAKE.pod +++ b/doc/man7/EVP_MD-SHAKE.pod @@ -15,18 +15,20 @@ implementation (see L). =head2 Identities -This implementation is only available with the default provider, and -includes the following varieties: +This implementation is available in the FIPS provider as well as the default +provider, and includes the following varieties: =over 4 =item KECCAK-KMAC-128 Known names are "KECCAK-KMAC-128" and "KECCAK-KMAC128" +This is used by L =item KECCAK-KMAC-256 Known names are "KECCAK-KMAC-256" and "KECCAK-KMAC256" +This is used by L =item SHAKE-128 @@ -55,6 +57,14 @@ settable for an B with L: Sets the digest length for extendable output functions. The length of the "xoflen" parameter should not exceed that of a B. +For backwards compatibility reasons the default xoflen length for SHAKE-128 is +16 (bytes) which results in a security strength of only 64 bits. To ensure the +maximum security strength of 128 bits, the xoflen should be set to at least 32. + +For backwards compatibility reasons the default xoflen length for SHAKE-256 is +32 (bytes) which results in a security strength of only 128 bits. To ensure the +maximum security strength of 256 bits, the xoflen should be set to at least 64. + =back =head1 SEE ALSO @@ -63,7 +73,7 @@ L, L, L =head1 COPYRIGHT -Copyright 2020 The OpenSSL Project Authors. All Rights Reserved. +Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved. Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy diff --git a/doc/man7/EVP_PKEY-EC.pod b/doc/man7/EVP_PKEY-EC.pod index c58f35547a..d9b1666b2e 100644 --- a/doc/man7/EVP_PKEY-EC.pod +++ b/doc/man7/EVP_PKEY-EC.pod @@ -110,7 +110,9 @@ per-operation basis. =item "pub" (B) -The public key value in EC point format. +The public key value in encoded EC point format. This parameter is used +when importing or exporting the public key value with the EVP_PKEY_fromdata() +and EVP_PKEY_todata() functions. =item "priv" (B) diff --git a/doc/man7/migration_guide.pod b/doc/man7/migration_guide.pod index a45a15d5d2..c2d885d492 100644 --- a/doc/man7/migration_guide.pod +++ b/doc/man7/migration_guide.pod @@ -1194,7 +1194,7 @@ Use the respective non-deprecated _ex() functions. BN_is_prime_ex(), BN_is_prime_fasttest_ex() -Use L which that avoids possible misuse and always uses at least +Use L which avoids possible misuse and always uses at least 64 rounds of the Miller-Rabin primality test. =item * diff --git a/e_os.h b/e_os.h index 9e2f14072f..db05b7f815 100644 --- a/e_os.h +++ b/e_os.h @@ -287,7 +287,7 @@ struct servent *getservbyname(const char *name, const char *proto); /* end vxworks */ /* system-specific variants defining ossl_sleep() */ -#ifdef OPENSSL_SYS_UNIX +#if defined(OPENSSL_SYS_UNIX) || defined(__DJGPP__) # include static ossl_inline void ossl_sleep(unsigned long millis) { diff --git a/include/crypto/evp.h b/include/crypto/evp.h index eeac4ee9f1..e571c546c6 100644 --- a/include/crypto/evp.h +++ b/include/crypto/evp.h @@ -365,7 +365,7 @@ static int cname##_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const uns return 1;\ } -#define EVP_MAXCHUNK ((size_t)1<<(sizeof(long)*8-2)) +#define EVP_MAXCHUNK ((size_t)1 << 30) #define BLOCK_CIPHER_func_ofb(cname, cprefix, cbits, kstruct, ksched) \ static int cname##_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl) \ diff --git a/include/internal/packet.h b/include/internal/packet.h index 170997db60..b7bb59d7ae 100644 --- a/include/internal/packet.h +++ b/include/internal/packet.h @@ -228,6 +228,28 @@ __owur static ossl_inline int PACKET_peek_net_4(const PACKET *pkt, return 1; } +/* + * Peek ahead at 8 bytes in network order from |pkt| and store the value in + * |*data| + */ +__owur static ossl_inline int PACKET_peek_net_8(const PACKET *pkt, + uint64_t *data) +{ + if (PACKET_remaining(pkt) < 8) + return 0; + + *data = ((uint64_t)(*pkt->curr)) << 56; + *data |= ((uint64_t)(*(pkt->curr + 1))) << 48; + *data |= ((uint64_t)(*(pkt->curr + 2))) << 40; + *data |= ((uint64_t)(*(pkt->curr + 3))) << 32; + *data |= ((uint64_t)(*(pkt->curr + 4))) << 24; + *data |= ((uint64_t)(*(pkt->curr + 5))) << 16; + *data |= ((uint64_t)(*(pkt->curr + 6))) << 8; + *data |= *(pkt->curr + 7); + + return 1; +} + /* Equivalent of n2l */ /* Get 4 bytes in network order from |pkt| and store the value in |*data| */ __owur static ossl_inline int PACKET_get_net_4(PACKET *pkt, unsigned long *data) @@ -252,6 +274,17 @@ __owur static ossl_inline int PACKET_get_net_4_len(PACKET *pkt, size_t *data) return ret; } +/* Get 8 bytes in network order from |pkt| and store the value in |*data| */ +__owur static ossl_inline int PACKET_get_net_8(PACKET *pkt, uint64_t *data) +{ + if (!PACKET_peek_net_8(pkt, data)) + return 0; + + packet_forward(pkt, 8); + + return 1; +} + /* Peek ahead at 1 byte from |pkt| and store the value in |*data| */ __owur static ossl_inline int PACKET_peek_1(const PACKET *pkt, unsigned int *data) @@ -833,7 +866,7 @@ int WPACKET_sub_reserve_bytes__(WPACKET *pkt, size_t len, * 1 byte will fail. Don't call this directly. Use the convenience macros below * instead. */ -int WPACKET_put_bytes__(WPACKET *pkt, unsigned int val, size_t bytes); +int WPACKET_put_bytes__(WPACKET *pkt, uint64_t val, size_t bytes); /* * Convenience macros for calling WPACKET_put_bytes with different @@ -847,6 +880,8 @@ int WPACKET_put_bytes__(WPACKET *pkt, unsigned int val, size_t bytes); WPACKET_put_bytes__((pkt), (val), 3) #define WPACKET_put_bytes_u32(pkt, val) \ WPACKET_put_bytes__((pkt), (val), 4) +#define WPACKET_put_bytes_u64(pkt, val) \ + WPACKET_put_bytes__((pkt), (val), 8) /* Set a maximum size that we will not allow the WPACKET to grow beyond */ int WPACKET_set_max_size(WPACKET *pkt, size_t maxsize); diff --git a/include/internal/sockets.h b/include/internal/sockets.h index 4701eb7e0e..1876af8faf 100644 --- a/include/internal/sockets.h +++ b/include/internal/sockets.h @@ -28,6 +28,8 @@ # elif defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) # if defined(__DJGPP__) +# define WATT32 +# define WATT32_NO_OLDIES # include # include # include @@ -134,8 +136,6 @@ struct servent *PASCAL getservbyname(const char *, const char *); # define readsocket(s,b,n) recv((s),(b),(n),0) # define writesocket(s,b,n) send((s),(b),(n),0) # elif defined(__DJGPP__) -# define WATT32 -# define WATT32_NO_OLDIES # define closesocket(s) close_s(s) # define readsocket(s,b,n) read_s(s,b,n) # define writesocket(s,b,n) send(s,b,n,0) diff --git a/include/openssl/bio.h.in b/include/openssl/bio.h.in index 651843b629..c521e41e4a 100644 --- a/include/openssl/bio.h.in +++ b/include/openssl/bio.h.in @@ -796,6 +796,7 @@ void BIO_copy_next_retry(BIO *b); # define ossl_bio__attr__(x) # if defined(__GNUC__) && defined(__STDC_VERSION__) \ + && !defined(__MINGW32__) && !defined(__MINGW64__) \ && !defined(__APPLE__) /* * Because we support the 'z' modifier, which made its appearance in C99, diff --git a/providers/implementations/include/prov/ciphercommon.h b/providers/implementations/include/prov/ciphercommon.h index 91c4c914be..30a59e5572 100644 --- a/providers/implementations/include/prov/ciphercommon.h +++ b/providers/implementations/include/prov/ciphercommon.h @@ -14,8 +14,8 @@ #include "internal/cryptlib.h" #include "crypto/modes.h" -#define MAXCHUNK ((size_t)1 << (sizeof(long) * 8 - 2)) -#define MAXBITCHUNK ((size_t)1 << (sizeof(size_t) * 8 - 4)) +# define MAXCHUNK ((size_t)1 << 30) +# define MAXBITCHUNK ((size_t)1 << (sizeof(size_t) * 8 - 4)) #define GENERIC_BLOCK_SIZE 16 #define IV_STATE_UNINITIALISED 0 /* initial state is not initialized */ diff --git a/providers/implementations/keymgmt/ec_kmgmt.c b/providers/implementations/keymgmt/ec_kmgmt.c index 6e18f7063e..3938e5c1c0 100644 --- a/providers/implementations/keymgmt/ec_kmgmt.c +++ b/providers/implementations/keymgmt/ec_kmgmt.c @@ -637,8 +637,10 @@ int common_get_params(void *key, OSSL_PARAM params[], int sm2) BN_CTX *bnctx = NULL; ecg = EC_KEY_get0_group(eck); - if (ecg == NULL) + if (ecg == NULL) { + ERR_raise(ERR_LIB_PROV, PROV_R_NO_PARAMETERS_SET); return 0; + } libctx = ossl_ec_key_get_libctx(eck); propq = ossl_ec_key_get0_propq(eck); @@ -727,8 +729,13 @@ int common_get_params(void *key, OSSL_PARAM params[], int sm2) } if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY)) != NULL) { - p->return_size = EC_POINT_point2oct(EC_KEY_get0_group(key), - EC_KEY_get0_public_key(key), + const EC_POINT *ecp = EC_KEY_get0_public_key(key); + + if (ecp == NULL) { + ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PUBLIC_KEY); + goto err; + } + p->return_size = EC_POINT_point2oct(ecg, ecp, POINT_CONVERSION_UNCOMPRESSED, p->data, p->return_size, bnctx); if (p->return_size == 0) diff --git a/ssl/record/rec_layer_s3.c b/ssl/record/rec_layer_s3.c index e8b5654c1e..7e950e6457 100644 --- a/ssl/record/rec_layer_s3.c +++ b/ssl/record/rec_layer_s3.c @@ -115,10 +115,22 @@ size_t ssl3_pending(const SSL *s) if (s->rlayer.rstate == SSL_ST_READ_BODY) return 0; + /* Take into account DTLS buffered app data */ + if (SSL_IS_DTLS(s)) { + DTLS1_RECORD_DATA *rdata; + pitem *item, *iter; + + iter = pqueue_iterator(s->rlayer.d->buffered_app_data.q); + while ((item = pqueue_next(&iter)) != NULL) { + rdata = item->data; + num += rdata->rrec.length; + } + } + for (i = 0; i < RECORD_LAYER_get_numrpipes(&s->rlayer); i++) { if (SSL3_RECORD_get_type(&s->rlayer.rrec[i]) != SSL3_RT_APPLICATION_DATA) - return 0; + return num; num += SSL3_RECORD_get_length(&s->rlayer.rrec[i]); } diff --git a/ssl/ssl_ciph.c b/ssl/ssl_ciph.c index 942ab5c6db..726c45044a 100644 --- a/ssl/ssl_ciph.c +++ b/ssl/ssl_ciph.c @@ -532,7 +532,8 @@ int ssl_cipher_get_evp(SSL_CTX *ctx, const SSL_SESSION *s, ctmp.id = s->compress_meth; if (ssl_comp_methods != NULL) { i = sk_SSL_COMP_find(ssl_comp_methods, &ctmp); - *comp = sk_SSL_COMP_value(ssl_comp_methods, i); + if (i >= 0) + *comp = sk_SSL_COMP_value(ssl_comp_methods, i); } /* If were only interested in comp then return success */ if ((enc == NULL) && (md == NULL)) diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c index 28304a700d..f32074b585 100644 --- a/ssl/ssl_lib.c +++ b/ssl/ssl_lib.c @@ -1550,12 +1550,26 @@ int SSL_has_pending(const SSL *s) { /* * Similar to SSL_pending() but returns a 1 to indicate that we have - * unprocessed data available or 0 otherwise (as opposed to the number of - * bytes available). Unlike SSL_pending() this will take into account - * read_ahead data. A 1 return simply indicates that we have unprocessed - * data. That data may not result in any application data, or we may fail - * to parse the records for some reason. + * processed or unprocessed data available or 0 otherwise (as opposed to the + * number of bytes available). Unlike SSL_pending() this will take into + * account read_ahead data. A 1 return simply indicates that we have data. + * That data may not result in any application data, or we may fail to parse + * the records for some reason. */ + + /* Check buffered app data if any first */ + if (SSL_IS_DTLS(s)) { + DTLS1_RECORD_DATA *rdata; + pitem *item, *iter; + + iter = pqueue_iterator(s->rlayer.d->buffered_app_data.q); + while ((item = pqueue_next(&iter)) != NULL) { + rdata = item->data; + if (rdata->rrec.length > 0) + return 1; + } + } + if (RECORD_LAYER_processed_read_pending(&s->rlayer)) return 1; @@ -4973,7 +4987,8 @@ static int ct_move_scts(STACK_OF(SCT) **dst, STACK_OF(SCT) *src, } } - while ((sct = sk_SCT_pop(src)) != NULL) { + while (sk_SCT_num(src) > 0) { + sct = sk_SCT_pop(src); if (SCT_set_source(sct, origin) != 1) goto err; diff --git a/ssl/ssl_local.h b/ssl/ssl_local.h index 5471e900b8..5fb1feb801 100644 --- a/ssl/ssl_local.h +++ b/ssl/ssl_local.h @@ -2752,7 +2752,9 @@ __owur int ssl_log_secret(SSL *ssl, const char *label, #define CLIENT_HANDSHAKE_LABEL "CLIENT_HANDSHAKE_TRAFFIC_SECRET" #define SERVER_HANDSHAKE_LABEL "SERVER_HANDSHAKE_TRAFFIC_SECRET" #define CLIENT_APPLICATION_LABEL "CLIENT_TRAFFIC_SECRET_0" +#define CLIENT_APPLICATION_N_LABEL "CLIENT_TRAFFIC_SECRET_N" #define SERVER_APPLICATION_LABEL "SERVER_TRAFFIC_SECRET_0" +#define SERVER_APPLICATION_N_LABEL "SERVER_TRAFFIC_SECRET_N" #define EARLY_EXPORTER_SECRET_LABEL "EARLY_EXPORTER_SECRET" #define EXPORTER_SECRET_LABEL "EXPORTER_SECRET" diff --git a/ssl/ssl_rsa.c b/ssl/ssl_rsa.c index 69c7bc2f9d..4f45e60535 100644 --- a/ssl/ssl_rsa.c +++ b/ssl/ssl_rsa.c @@ -703,16 +703,68 @@ static int serverinfo_process_buffer(unsigned int version, return 1; } +static size_t extension_contextoff(unsigned int version) +{ + return version == SSL_SERVERINFOV1 ? 4 : 0; +} + +static size_t extension_append_length(unsigned int version, size_t extension_length) +{ + return extension_length + extension_contextoff(version); +} + +static void extension_append(unsigned int version, + const unsigned char *extension, + const size_t extension_length, + unsigned char *serverinfo) +{ + const size_t contextoff = extension_contextoff(version); + + if (contextoff > 0) { + /* We know this only uses the last 2 bytes */ + serverinfo[0] = 0; + serverinfo[1] = 0; + serverinfo[2] = (SYNTHV1CONTEXT >> 8) & 0xff; + serverinfo[3] = SYNTHV1CONTEXT & 0xff; + } + + memcpy(serverinfo + contextoff, extension, extension_length); +} + int SSL_CTX_use_serverinfo_ex(SSL_CTX *ctx, unsigned int version, const unsigned char *serverinfo, size_t serverinfo_length) { - unsigned char *new_serverinfo; + unsigned char *new_serverinfo = NULL; if (ctx == NULL || serverinfo == NULL || serverinfo_length == 0) { ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_NULL_PARAMETER); return 0; } + if (version == SSL_SERVERINFOV1) { + /* + * Convert serverinfo version v1 to v2 and call yourself recursively + * over the converted serverinfo. + */ + const size_t sinfo_length = extension_append_length(SSL_SERVERINFOV1, + serverinfo_length); + unsigned char *sinfo; + int ret; + + sinfo = OPENSSL_malloc(sinfo_length); + if (sinfo == NULL) { + ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE); + return 0; + } + + extension_append(SSL_SERVERINFOV1, serverinfo, serverinfo_length, sinfo); + + ret = SSL_CTX_use_serverinfo_ex(ctx, SSL_SERVERINFOV2, sinfo, + sinfo_length); + + OPENSSL_free(sinfo); + return ret; + } if (!serverinfo_process_buffer(version, serverinfo, serverinfo_length, NULL)) { ERR_raise(ERR_LIB_SSL, SSL_R_INVALID_SERVERINFO_DATA); @@ -765,7 +817,7 @@ int SSL_CTX_use_serverinfo_file(SSL_CTX *ctx, const char *file) unsigned int name_len; int ret = 0; BIO *bin = NULL; - size_t num_extensions = 0, contextoff = 0; + size_t num_extensions = 0; if (ctx == NULL || file == NULL) { ERR_raise(ERR_LIB_SSL, ERR_R_PASSED_NULL_PARAMETER); @@ -784,6 +836,7 @@ int SSL_CTX_use_serverinfo_file(SSL_CTX *ctx, const char *file) for (num_extensions = 0;; num_extensions++) { unsigned int version; + size_t append_length; if (PEM_read_bio(bin, &name, &header, &extension, &extension_length) == 0) { @@ -826,11 +879,6 @@ int SSL_CTX_use_serverinfo_file(SSL_CTX *ctx, const char *file) ERR_raise(ERR_LIB_SSL, SSL_R_BAD_DATA); goto end; } - /* - * File does not have a context value so we must take account of - * this later. - */ - contextoff = 4; } else { /* 8 byte header: 4 bytes context, 2 bytes type, 2 bytes len */ if (extension_length < 8 @@ -841,25 +889,16 @@ int SSL_CTX_use_serverinfo_file(SSL_CTX *ctx, const char *file) } } /* Append the decoded extension to the serverinfo buffer */ - tmp = OPENSSL_realloc(serverinfo, serverinfo_length + extension_length - + contextoff); + append_length = extension_append_length(version, extension_length); + tmp = OPENSSL_realloc(serverinfo, serverinfo_length + append_length); if (tmp == NULL) { ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE); goto end; } serverinfo = tmp; - if (contextoff > 0) { - unsigned char *sinfo = serverinfo + serverinfo_length; - - /* We know this only uses the last 2 bytes */ - sinfo[0] = 0; - sinfo[1] = 0; - sinfo[2] = (SYNTHV1CONTEXT >> 8) & 0xff; - sinfo[3] = SYNTHV1CONTEXT & 0xff; - } - memcpy(serverinfo + serverinfo_length + contextoff, - extension, extension_length); - serverinfo_length += extension_length + contextoff; + extension_append(version, extension, extension_length, + serverinfo + serverinfo_length); + serverinfo_length += append_length; OPENSSL_free(name); name = NULL; diff --git a/ssl/statem/extensions.c b/ssl/statem/extensions.c index c0bab081a2..8c9c16ec21 100644 --- a/ssl/statem/extensions.c +++ b/ssl/statem/extensions.c @@ -98,6 +98,9 @@ typedef struct extensions_definition_st { * Definitions of all built-in extensions. NOTE: Changes in the number or order * of these extensions should be mirrored with equivalent changes to the * indexes ( TLSEXT_IDX_* ) defined in ssl_local.h. + * Extensions should be added to test/ext_internal_test.c as well, as that + * tests the ordering of the extensions. + * * Each extension has an initialiser, a client and * server side parser and a finaliser. The initialiser is called (if the * extension is relevant to the given context) even if we did not see the @@ -118,7 +121,7 @@ typedef struct extensions_definition_st { * NOTE: WebSphere Application Server 7+ cannot handle empty extensions at * the end, keep these extensions before signature_algorithm. */ -#define INVALID_EXTENSION { 0x10000, 0, NULL, NULL, NULL, NULL, NULL, NULL } +#define INVALID_EXTENSION { TLSEXT_TYPE_invalid, 0, NULL, NULL, NULL, NULL, NULL, NULL } static const EXTENSION_DEFINITION ext_defs[] = { { TLSEXT_TYPE_renegotiate, @@ -385,6 +388,17 @@ static const EXTENSION_DEFINITION ext_defs[] = { } }; +/* Returns a TLSEXT_TYPE for the given index */ +unsigned int ossl_get_extension_type(size_t idx) +{ + size_t num_exts = OSSL_NELEM(ext_defs); + + if (idx >= num_exts) + return TLSEXT_TYPE_out_of_range; + + return ext_defs[idx].type; +} + /* Check whether an extension's context matches the current context */ static int validate_context(SSL *s, unsigned int extctx, unsigned int thisctx) { diff --git a/ssl/statem/extensions_clnt.c b/ssl/statem/extensions_clnt.c index 5a3c7a48ec..e1cf3945a6 100644 --- a/ssl/statem/extensions_clnt.c +++ b/ssl/statem/extensions_clnt.c @@ -974,7 +974,7 @@ EXT_RETURN tls_construct_ctos_psk(SSL *s, WPACKET *pkt, unsigned int context, X509 *x, size_t chainidx) { #ifndef OPENSSL_NO_TLS1_3 - uint32_t now, agesec, agems = 0; + uint32_t agesec, agems = 0; size_t reshashsize = 0, pskhashsize = 0, binderoffset, msglen; unsigned char *resbinder = NULL, *pskbinder = NULL, *msgstart = NULL; const EVP_MD *handmd = NULL, *mdres = NULL, *mdpsk = NULL; @@ -1030,8 +1030,7 @@ EXT_RETURN tls_construct_ctos_psk(SSL *s, WPACKET *pkt, unsigned int context, * this in multiple places in the code, so portability shouldn't be an * issue. */ - now = (uint32_t)time(NULL); - agesec = now - (uint32_t)s->session->time; + agesec = (uint32_t)(time(NULL) - s->session->time); /* * We calculate the age in seconds but the server may work in ms. Due to * rounding errors we could overestimate the age by up to 1s. It is diff --git a/ssl/statem/extensions_srvr.c b/ssl/statem/extensions_srvr.c index bf89e8247d..15c4e8af9e 100644 --- a/ssl/statem/extensions_srvr.c +++ b/ssl/statem/extensions_srvr.c @@ -12,16 +12,16 @@ #include "statem_local.h" #include "internal/cryptlib.h" -#define COOKIE_STATE_FORMAT_VERSION 0 +#define COOKIE_STATE_FORMAT_VERSION 1 /* * 2 bytes for packet length, 2 bytes for format version, 2 bytes for * protocol version, 2 bytes for group id, 2 bytes for cipher id, 1 byte for - * key_share present flag, 4 bytes for timestamp, 2 bytes for the hashlen, + * key_share present flag, 8 bytes for timestamp, 2 bytes for the hashlen, * EVP_MAX_MD_SIZE for transcript hash, 1 byte for app cookie length, app cookie * length bytes, SHA256_DIGEST_LENGTH bytes for the HMAC of the whole thing. */ -#define MAX_COOKIE_SIZE (2 + 2 + 2 + 2 + 2 + 1 + 4 + 2 + EVP_MAX_MD_SIZE + 1 \ +#define MAX_COOKIE_SIZE (2 + 2 + 2 + 2 + 2 + 1 + 8 + 2 + EVP_MAX_MD_SIZE + 1 \ + SSL_COOKIE_LENGTH + SHA256_DIGEST_LENGTH) /* @@ -690,7 +690,7 @@ int tls_parse_ctos_cookie(SSL *s, PACKET *pkt, unsigned int context, X509 *x, unsigned char hmac[SHA256_DIGEST_LENGTH]; unsigned char hrr[MAX_HRR_SIZE]; size_t rawlen, hmaclen, hrrlen, ciphlen; - unsigned long tm, now; + uint64_t tm, now; /* Ignore any cookie if we're not set up to verify it */ if (s->ctx->verify_stateless_cookie_cb == NULL @@ -791,7 +791,7 @@ int tls_parse_ctos_cookie(SSL *s, PACKET *pkt, unsigned int context, X509 *x, } if (!PACKET_get_1(&cookie, &key_share) - || !PACKET_get_net_4(&cookie, &tm) + || !PACKET_get_net_8(&cookie, &tm) || !PACKET_get_length_prefixed_2(&cookie, &chhash) || !PACKET_get_length_prefixed_1(&cookie, &appcookie) || PACKET_remaining(&cookie) != SHA256_DIGEST_LENGTH) { @@ -800,7 +800,7 @@ int tls_parse_ctos_cookie(SSL *s, PACKET *pkt, unsigned int context, X509 *x, } /* We tolerate a cookie age of up to 10 minutes (= 60 * 10 seconds) */ - now = (unsigned long)time(NULL); + now = time(NULL); if (tm > now || (now - tm) > 600) { /* Cookie is stale. Ignore it */ return 1; @@ -1087,7 +1087,7 @@ int tls_parse_ctos_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x, s->ext.early_data_ok = 1; s->ext.ticket_expected = 1; } else { - uint32_t ticket_age = 0, now, agesec, agems; + uint32_t ticket_age = 0, agesec, agems; int ret; /* @@ -1127,8 +1127,7 @@ int tls_parse_ctos_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x, } ticket_age = (uint32_t)ticket_agel; - now = (uint32_t)time(NULL); - agesec = now - (uint32_t)sess->time; + agesec = (uint32_t)(time(NULL) - sess->time); agems = agesec * (uint32_t)1000; ticket_age -= sess->ext.tick_age_add; @@ -1741,7 +1740,7 @@ EXT_RETURN tls_construct_stoc_cookie(SSL *s, WPACKET *pkt, unsigned int context, &ciphlen) /* Is there a key_share extension present in this HRR? */ || !WPACKET_put_bytes_u8(pkt, s->s3.peer_tmp == NULL) - || !WPACKET_put_bytes_u32(pkt, (unsigned int)time(NULL)) + || !WPACKET_put_bytes_u64(pkt, time(NULL)) || !WPACKET_start_sub_packet_u16(pkt) || !WPACKET_reserve_bytes(pkt, EVP_MAX_MD_SIZE, &hashval1)) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); diff --git a/ssl/statem/statem.c b/ssl/statem/statem.c index 4c463974ea..a1f40fd29b 100644 --- a/ssl/statem/statem.c +++ b/ssl/statem/statem.c @@ -849,10 +849,24 @@ static SUB_STATE_RETURN write_state_machine(SSL *s) SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); return SUB_STATE_ERROR; } - if (confunc != NULL && !confunc(s, &pkt)) { - WPACKET_cleanup(&pkt); - check_fatal(s); - return SUB_STATE_ERROR; + if (confunc != NULL) { + int tmpret; + + tmpret = confunc(s, &pkt); + if (tmpret <= 0) { + WPACKET_cleanup(&pkt); + check_fatal(s); + return SUB_STATE_ERROR; + } else if (tmpret == 2) { + /* + * The construction function decided not to construct the + * message after all and continue. Skip sending. + */ + WPACKET_cleanup(&pkt); + st->write_state = WRITE_STATE_POST_WORK; + st->write_state_work = WORK_MORE_A; + break; + } /* else success */ } if (!ssl_close_construct_packet(s, &pkt, mt) || !WPACKET_finish(&pkt)) { diff --git a/ssl/statem/statem_dtls.c b/ssl/statem/statem_dtls.c index 2838d51bdb..788d0eff65 100644 --- a/ssl/statem/statem_dtls.c +++ b/ssl/statem/statem_dtls.c @@ -491,23 +491,64 @@ static int dtls1_retrieve_buffered_fragment(SSL *s, size_t *len) * (2) update s->init_num */ pitem *item; + piterator iter; hm_fragment *frag; int ret; + int chretran = 0; + iter = pqueue_iterator(s->d1->buffered_messages); do { - item = pqueue_peek(s->d1->buffered_messages); + item = pqueue_next(&iter); if (item == NULL) return 0; frag = (hm_fragment *)item->data; if (frag->msg_header.seq < s->d1->handshake_read_seq) { - /* This is a stale message that has been buffered so clear it */ - pqueue_pop(s->d1->buffered_messages); - dtls1_hm_fragment_free(frag); - pitem_free(item); - item = NULL; - frag = NULL; + pitem *next; + hm_fragment *nextfrag; + + if (!s->server + || frag->msg_header.seq != 0 + || s->d1->handshake_read_seq != 1 + || s->statem.hand_state != DTLS_ST_SW_HELLO_VERIFY_REQUEST) { + /* + * This is a stale message that has been buffered so clear it. + * It is safe to pop this message from the queue even though + * we have an active iterator + */ + pqueue_pop(s->d1->buffered_messages); + dtls1_hm_fragment_free(frag); + pitem_free(item); + item = NULL; + frag = NULL; + } else { + /* + * We have fragments for a ClientHello without a cookie, + * even though we have sent a HelloVerifyRequest. It is possible + * that the HelloVerifyRequest got lost and this is a + * retransmission of the original ClientHello + */ + next = pqueue_next(&iter); + if (next != NULL) { + nextfrag = (hm_fragment *)next->data; + if (nextfrag->msg_header.seq == s->d1->handshake_read_seq) { + /* + * We have fragments for both a ClientHello without + * cookie and one with. Ditch the one without. + */ + pqueue_pop(s->d1->buffered_messages); + dtls1_hm_fragment_free(frag); + pitem_free(item); + item = next; + frag = nextfrag; + } else { + chretran = 1; + } + } else { + chretran = 1; + } + } } } while (item == NULL); @@ -515,7 +556,7 @@ static int dtls1_retrieve_buffered_fragment(SSL *s, size_t *len) if (frag->reassembly != NULL) return 0; - if (s->d1->handshake_read_seq == frag->msg_header.seq) { + if (s->d1->handshake_read_seq == frag->msg_header.seq || chretran) { size_t frag_len = frag->msg_header.frag_len; pqueue_pop(s->d1->buffered_messages); @@ -533,6 +574,16 @@ static int dtls1_retrieve_buffered_fragment(SSL *s, size_t *len) pitem_free(item); if (ret) { + if (chretran) { + /* + * We got a new ClientHello with a message sequence of 0. + * Reset the read/write sequences back to the beginning. + * We process it like this is the first time we've seen a + * ClientHello from the client. + */ + s->d1->handshake_read_seq = 0; + s->d1->next_handshake_write_seq = 0; + } *len = frag_len; return 1; } @@ -759,6 +810,7 @@ static int dtls_get_reassembled_message(SSL *s, int *errtype, size_t *len) int i, ret, recvd_type; struct hm_header_st msg_hdr; size_t readbytes; + int chretran = 0; *errtype = 0; @@ -828,8 +880,20 @@ static int dtls_get_reassembled_message(SSL *s, int *errtype, size_t *len) * although we're still expecting seq 0 (ClientHello) */ if (msg_hdr.seq != s->d1->handshake_read_seq) { - *errtype = dtls1_process_out_of_seq_message(s, &msg_hdr); - return 0; + if (!s->server + || msg_hdr.seq != 0 + || s->d1->handshake_read_seq != 1 + || wire[0] != SSL3_MT_CLIENT_HELLO + || s->statem.hand_state != DTLS_ST_SW_HELLO_VERIFY_REQUEST) { + *errtype = dtls1_process_out_of_seq_message(s, &msg_hdr); + return 0; + } + /* + * We received a ClientHello and sent back a HelloVerifyRequest. We + * now seem to have received a retransmitted initial ClientHello. That + * is allowed (possibly our HelloVerifyRequest got lost). + */ + chretran = 1; } if (frag_len && frag_len < mlen) { @@ -895,6 +959,17 @@ static int dtls_get_reassembled_message(SSL *s, int *errtype, size_t *len) goto f_err; } + if (chretran) { + /* + * We got a new ClientHello with a message sequence of 0. + * Reset the read/write sequences back to the beginning. + * We process it like this is the first time we've seen a ClientHello + * from the client. + */ + s->d1->handshake_read_seq = 0; + s->d1->next_handshake_write_seq = 0; + } + /* * Note that s->init_num is *not* used as current offset in * s->init_buf->data, but as a counter summing up fragments' lengths: as diff --git a/ssl/statem/statem_local.h b/ssl/statem/statem_local.h index 1883b0166f..01f60ebabb 100644 --- a/ssl/statem/statem_local.h +++ b/ssl/statem/statem_local.h @@ -37,6 +37,11 @@ /* Dummy message type */ #define SSL3_MT_DUMMY -1 +/* Invalid extension ID for non-supported extensions */ +#define TLSEXT_TYPE_invalid 0x10000 +#define TLSEXT_TYPE_out_of_range 0x10001 +unsigned int ossl_get_extension_type(size_t idx); + extern const unsigned char hrrrandom[]; /* Message processing return codes */ diff --git a/ssl/statem/statem_srvr.c b/ssl/statem/statem_srvr.c index 5626e4ea2a..b6b5e79d00 100644 --- a/ssl/statem/statem_srvr.c +++ b/ssl/statem/statem_srvr.c @@ -3551,7 +3551,7 @@ MSG_PROCESS_RETURN tls_process_client_certificate(SSL *s, PACKET *pkt) } X509_free(s->session->peer); - s->session->peer = sk_X509_shift(sk); + s->session->peer = sk_X509_num(sk) == 0 ? NULL: sk_X509_shift(sk); s->session->verify_result = s->verify_result; sk_X509_pop_free(s->session->peer_chain, X509_free); @@ -3660,6 +3660,10 @@ static int create_ticket_prequel(SSL *s, WPACKET *pkt, uint32_t age_add, return 1; } +/* + * Returns 1 on success, 0 to abort construction of the ticket (non-fatal), or + * -1 on fatal error + */ static int construct_stateless_ticket(SSL *s, WPACKET *pkt, uint32_t age_add, unsigned char *tick_nonce) { @@ -3674,7 +3678,7 @@ static int construct_stateless_ticket(SSL *s, WPACKET *pkt, uint32_t age_add, SSL_CTX *tctx = s->session_ctx; unsigned char iv[EVP_MAX_IV_LENGTH]; unsigned char key_name[TLSEXT_KEYNAME_LENGTH]; - int iv_len, ok = 0; + int iv_len, ok = -1; size_t macoffset, macendoffset; /* get session encoding length */ @@ -3755,7 +3759,15 @@ static int construct_stateless_ticket(SSL *s, WPACKET *pkt, uint32_t age_add, #endif if (ret == 0) { - + /* + * In TLSv1.2 we construct a 0 length ticket. In TLSv1.3 a 0 + * length ticket is not allowed so we abort construction of the + * ticket + */ + if (SSL_IS_TLS13(s)) { + ok = 0; + goto err; + } /* Put timeout and length */ if (!WPACKET_put_bytes_u32(pkt, 0) || !WPACKET_put_bytes_u16(pkt, 0)) { @@ -3868,6 +3880,20 @@ static int construct_stateful_ticket(SSL *s, WPACKET *pkt, uint32_t age_add, return 1; } +static void tls_update_ticket_counts(SSL *s) +{ + /* + * Increment both |sent_tickets| and |next_ticket_nonce|. |sent_tickets| + * gets reset to 0 if we send more tickets following a post-handshake + * auth, but |next_ticket_nonce| does not. If we're sending extra + * tickets, decrement the count of pending extra tickets. + */ + s->sent_tickets++; + s->next_ticket_nonce++; + if (s->ext.extra_tickets_expected > 0) + s->ext.extra_tickets_expected--; +} + int tls_construct_new_session_ticket(SSL *s, WPACKET *pkt) { SSL_CTX *tctx = s->session_ctx; @@ -3876,6 +3902,7 @@ int tls_construct_new_session_ticket(SSL *s, WPACKET *pkt) unsigned char age_add_c[sizeof(uint32_t)]; uint32_t age_add; } age_add_u; + int ret = 0; age_add_u.age_add = 0; @@ -3973,10 +4000,20 @@ int tls_construct_new_session_ticket(SSL *s, WPACKET *pkt) /* SSLfatal() already called */ goto err; } - } else if (!construct_stateless_ticket(s, pkt, age_add_u.age_add, - tick_nonce)) { - /* SSLfatal() already called */ - goto err; + } else { + int tmpret; + + tmpret = construct_stateless_ticket(s, pkt, age_add_u.age_add, + tick_nonce); + if (tmpret != 1) { + if (tmpret == 0) { + ret = 2; /* Non-fatal. Abort construction but continue */ + /* We count this as a success so update the counts anwyay */ + tls_update_ticket_counts(s); + } + /* else SSLfatal() already called */ + goto err; + } } if (SSL_IS_TLS13(s)) { @@ -3986,22 +4023,13 @@ int tls_construct_new_session_ticket(SSL *s, WPACKET *pkt) /* SSLfatal() already called */ goto err; } - /* - * Increment both |sent_tickets| and |next_ticket_nonce|. |sent_tickets| - * gets reset to 0 if we send more tickets following a post-handshake - * auth, but |next_ticket_nonce| does not. If we're sending extra - * tickets, decrement the count of pending extra tickets. - */ - s->sent_tickets++; - s->next_ticket_nonce++; - if (s->ext.extra_tickets_expected > 0) - s->ext.extra_tickets_expected--; + tls_update_ticket_counts(s); ssl_update_cache(s, SSL_SESS_CACHE_SERVER); } - return 1; + ret = 1; err: - return 0; + return ret; } /* diff --git a/ssl/tls13_enc.c b/ssl/tls13_enc.c index 07d065e35e..ddcff5eb89 100644 --- a/ssl/tls13_enc.c +++ b/ssl/tls13_enc.c @@ -751,12 +751,19 @@ int tls13_update_key(SSL *s, int sending) static const unsigned char application_traffic[] = "traffic upd"; #endif const EVP_MD *md = ssl_handshake_md(s); - size_t hashlen = EVP_MD_get_size(md); + size_t hashlen; unsigned char key[EVP_MAX_KEY_LENGTH]; unsigned char *insecret, *iv; unsigned char secret[EVP_MAX_MD_SIZE]; + char *log_label; EVP_CIPHER_CTX *ciph_ctx; - int ret = 0; + int ret = 0, l; + + if ((l = EVP_MD_get_size(md)) <= 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); + return 0; + } + hashlen = (size_t)l; if (s->server == sending) insecret = s->server_app_traffic_secret; @@ -785,6 +792,13 @@ int tls13_update_key(SSL *s, int sending) memcpy(insecret, secret, hashlen); + /* Call Key log on successful traffic secret update */ + log_label = s->server == sending ? SERVER_APPLICATION_N_LABEL : CLIENT_APPLICATION_N_LABEL; + if (!ssl_log_secret(s, log_label, secret, hashlen)) { + /* SSLfatal() already called */ + goto err; + } + s->statem.enc_write_state = ENC_WRITE_STATE_VALID; ret = 1; err: diff --git a/test/aesgcmtest.c b/test/aesgcmtest.c index 04cd91db98..cdb0cbd021 100644 --- a/test/aesgcmtest.c +++ b/test/aesgcmtest.c @@ -116,7 +116,6 @@ static int badkeylen_test(void) return ret; } -#ifdef FIPS_MODULE static int ivgen_test(void) { unsigned char iv_gen[16]; @@ -127,14 +126,11 @@ static int ivgen_test(void) return do_encrypt(iv_gen, ct, &ctlen, tag, &taglen) && do_decrypt(iv_gen, ct, ctlen, tag, taglen); } -#endif /* FIPS_MODULE */ int setup_tests(void) { ADD_TEST(kat_test); ADD_TEST(badkeylen_test); -#ifdef FIPS_MODULE ADD_TEST(ivgen_test); -#endif /* FIPS_MODULE */ return 1; } diff --git a/test/asynctest.c b/test/asynctest.c index 6502ee9845..628d0d86ea 100644 --- a/test/asynctest.c +++ b/test/asynctest.c @@ -409,6 +409,7 @@ static int test_ASYNC_start_job_ex(void) ret = 1; err: ASYNC_WAIT_CTX_free(waitctx); + ASYNC_cleanup_thread(); OSSL_LIB_CTX_free(libctx); return ret; } diff --git a/test/build.info b/test/build.info index ee059973d3..9d2d41e417 100644 --- a/test/build.info +++ b/test/build.info @@ -62,7 +62,7 @@ IF[{- !$disabled{tests} -}] context_internal_test aesgcmtest params_test evp_pkey_dparams_test \ keymgmt_internal_test hexstr_test provider_status_test defltfips_test \ bio_readbuffer_test user_property_test pkcs7_test upcallstest \ - provfetchtest prov_config_test rand_test + provfetchtest prov_config_test rand_test fips_version_test IF[{- !$disabled{'deprecated-3.0'} -}] PROGRAMS{noinst}=enginetest @@ -185,9 +185,6 @@ IF[{- !$disabled{tests} -}] SOURCE[evp_fetch_prov_test]=evp_fetch_prov_test.c INCLUDE[evp_fetch_prov_test]=../include ../apps/include DEPEND[evp_fetch_prov_test]=../libcrypto libtestutil.a - IF[{- $disabled{fips} || !$target{dso_scheme} -}] - DEFINE[evp_extra_test]=NO_FIPS_MODULE - ENDIF SOURCE[provfetchtest]=provfetchtest.c INCLUDE[provfetchtest]=../include ../apps/include @@ -394,6 +391,10 @@ IF[{- !$disabled{tests} -}] INCLUDE[defltfips_test]=../include ../apps/include DEPEND[defltfips_test]=../libcrypto libtestutil.a + SOURCE[fips_version_test]=fips_version_test.c + INCLUDE[fips_version_test]=../include ../apps/include + DEPEND[fips_version_test]=../libcrypto libtestutil.a + SOURCE[ocspapitest]=ocspapitest.c INCLUDE[ocspapitest]=../include ../apps/include DEPEND[ocspapitest]=../libcrypto libtestutil.a @@ -777,6 +778,11 @@ IF[{- !$disabled{tests} -}] INCLUDE[ssl_old_test]=.. ../include ../apps/include DEPEND[ssl_old_test]=../libcrypto.a ../libssl.a libtestutil.a + PROGRAMS{noinst}=ext_internal_test + SOURCE[ext_internal_test]=ext_internal_test.c + INCLUDE[ext_internal_test]=.. ../include ../apps/include + DEPEND[ext_internal_test]=../libcrypto.a ../libssl.a libtestutil.a + PROGRAMS{noinst}=algorithmid_test SOURCE[algorithmid_test]=algorithmid_test.c INCLUDE[algorithmid_test]=../include ../apps/include diff --git a/test/cmsapitest.c b/test/cmsapitest.c index b40089becd..a19fb0683c 100644 --- a/test/cmsapitest.c +++ b/test/cmsapitest.c @@ -289,18 +289,63 @@ static int test_d2i_CMS_bio_NULL(void) return ret; } -static int test_d2i_CMS_bio_file_encrypted_data(void) +static unsigned char *read_all(BIO *bio, long *p_len) +{ + const int step = 256; + unsigned char *buf = NULL; + unsigned char *tmp = NULL; + int ret; + + *p_len = 0; + for (;;) { + tmp = OPENSSL_realloc(buf, *p_len + step); + if (tmp == NULL) + break; + buf = tmp; + ret = BIO_read(bio, buf + *p_len, step); + if (ret < 0) + break; + + *p_len += ret; + + if (ret < step) + return buf; + } + + /* Error */ + OPENSSL_free(buf); + *p_len = 0; + return NULL; +} + +static int test_d2i_CMS_decode(const int idx) { BIO *bio = NULL; CMS_ContentInfo *cms = NULL; + unsigned char *buf = NULL; + const unsigned char *tmp = NULL; + long buf_len = 0; int ret = 0; ERR_clear_error(); - if (!TEST_ptr(bio = BIO_new_file(derin, "r")) - || !TEST_ptr(cms = d2i_CMS_bio(bio, NULL))) + if (!TEST_ptr(bio = BIO_new_file(derin, "r"))) goto end; + switch (idx) { + case 0: + if (!TEST_ptr(cms = d2i_CMS_bio(bio, NULL))) + goto end; + break; + case 1: + if (!TEST_ptr(buf = read_all(bio, &buf_len))) + goto end; + tmp = buf; + if (!TEST_ptr(cms = d2i_CMS_ContentInfo(NULL, &tmp, buf_len))) + goto end; + break; + } + if (!TEST_int_eq(ERR_peek_error(), 0)) goto end; @@ -308,6 +353,7 @@ static int test_d2i_CMS_bio_file_encrypted_data(void) end: CMS_ContentInfo_free(cms); BIO_free(bio); + OPENSSL_free(buf); return ret; } @@ -357,7 +403,7 @@ int setup_tests(void) ADD_TEST(test_encrypt_decrypt_aes_192_gcm); ADD_TEST(test_encrypt_decrypt_aes_256_gcm); ADD_TEST(test_d2i_CMS_bio_NULL); - ADD_TEST(test_d2i_CMS_bio_file_encrypted_data); + ADD_ALL_TESTS(test_d2i_CMS_decode, 2); return 1; } diff --git a/test/drbgtest.c b/test/drbgtest.c index 58d53ac038..a1a786218b 100644 --- a/test/drbgtest.c +++ b/test/drbgtest.c @@ -132,15 +132,23 @@ static time_t reseed_time(EVP_RAND_CTX *drbg) /* * When building the FIPS module, it isn't possible to disable the continuous - * RNG tests. Tests that require this are skipped. + * RNG tests. Tests that require this are skipped and this means a detection + * mechanism for the FIPS provider being in use. */ -static int crngt_skip(void) +static int using_fips_rng(void) { -#ifdef FIPS_MODULE - return 1; -#else - return 0; -#endif + EVP_RAND_CTX *primary = RAND_get0_primary(NULL); + const OSSL_PROVIDER *prov; + const char *name; + + if (!TEST_ptr(primary)) + return 0; + + prov = EVP_RAND_get0_provider(EVP_RAND_CTX_get0_rand(primary)); + if (!TEST_ptr(prov)) + return 0; + name = OSSL_PROVIDER_get0_name(prov); + return strcmp(name, "OpenSSL FIPS Provider") == 0; } /* @@ -540,7 +548,7 @@ static int test_rand_fork_safety(int i) /* * Test whether the default rand_method (RAND_OpenSSL()) is - * setup correctly, in particular whether reseeding works + * setup correctly, in particular whether reseeding works * as designed. */ static int test_rand_reseed(void) @@ -550,7 +558,7 @@ static int test_rand_reseed(void) int rv = 0; time_t before_reseed; - if (crngt_skip()) + if (using_fips_rng()) return TEST_skip("CRNGT cannot be disabled"); #ifndef OPENSSL_NO_DEPRECATED_3_0 @@ -582,7 +590,6 @@ static int test_rand_reseed(void) EVP_RAND_uninstantiate(private); EVP_RAND_uninstantiate(public); - /* * Test initial seeding of shared DRBGs */ @@ -592,7 +599,6 @@ static int test_rand_reseed(void) 1, 1, 1, 0))) goto error; - /* * Test initial state of shared DRBGs */ @@ -640,7 +646,6 @@ static int test_rand_reseed(void) /* fill 'randomness' buffer with some arbitrary data */ memset(rand_add_buf, 'r', sizeof(rand_add_buf)); -#ifndef FIPS_MODULE /* * Test whether all three DRBGs are reseeded by RAND_add(). * The before_reseed time has to be measured here and passed into the @@ -657,22 +662,6 @@ static int test_rand_reseed(void) 1, 1, 1, before_reseed))) goto error; -#else /* FIPS_MODULE */ - /* - * In FIPS mode, random data provided by the application via RAND_add() - * is not considered a trusted entropy source. It is only treated as - * additional_data and no reseeding is forced. This test assures that - * no reseeding occurs. - */ - before_reseed = time(NULL); - RAND_add(rand_add_buf, sizeof(rand_add_buf), sizeof(rand_add_buf)); - if (!TEST_true(test_drbg_reseed(1, - primary, public, private, - NULL, NULL, - 0, 0, 0, - before_reseed))) - goto error; -#endif rv = 1; @@ -822,7 +811,7 @@ static int test_rand_prediction_resistance(void) unsigned char buf1[51], buf2[sizeof(buf1)]; int ret = 0, xreseed, yreseed, zreseed; - if (crngt_skip()) + if (using_fips_rng()) return TEST_skip("CRNGT cannot be disabled"); /* Initialise a three long DRBG chain */ diff --git a/test/dtlstest.c b/test/dtlstest.c index 2f3fcae0f6..e01c445645 100644 --- a/test/dtlstest.c +++ b/test/dtlstest.c @@ -42,6 +42,22 @@ static unsigned char certstatus[] = { #define RECORD_SEQUENCE 10 +static const char dummy_cookie[] = "0123456"; + +static int generate_cookie_cb(SSL *ssl, unsigned char *cookie, + unsigned int *cookie_len) +{ + memcpy(cookie, dummy_cookie, sizeof(dummy_cookie)); + *cookie_len = sizeof(dummy_cookie); + return 1; +} + +static int verify_cookie_cb(SSL *ssl, const unsigned char *cookie, + unsigned int cookie_len) +{ + return TEST_mem_eq(cookie, cookie_len, dummy_cookie, sizeof(dummy_cookie)); +} + static unsigned int timer_cb(SSL *s, unsigned int timer_us) { ++timer_cb_count; @@ -127,6 +143,17 @@ static int test_dtls_unprocessed(int testidx) return testresult; } +/* One record for the cookieless initial ClientHello */ +#define CLI_TO_SRV_COOKIE_EXCH 1 + +/* + * In a resumption handshake we use 2 records for the initial ClientHello in + * this test because we are using a very small MTU and the ClientHello is + * bigger than in the non resumption case. + */ +#define CLI_TO_SRV_RESUME_COOKIE_EXCH 2 +#define SRV_TO_CLI_COOKIE_EXCH 1 + #define CLI_TO_SRV_EPOCH_0_RECS 3 #define CLI_TO_SRV_EPOCH_1_RECS 1 #if !defined(OPENSSL_NO_EC) || !defined(OPENSSL_NO_DH) @@ -141,7 +168,8 @@ static int test_dtls_unprocessed(int testidx) #endif #define SRV_TO_CLI_EPOCH_1_RECS 1 #define TOTAL_FULL_HAND_RECORDS \ - (CLI_TO_SRV_EPOCH_0_RECS + CLI_TO_SRV_EPOCH_1_RECS + \ + (CLI_TO_SRV_COOKIE_EXCH + SRV_TO_CLI_COOKIE_EXCH + \ + CLI_TO_SRV_EPOCH_0_RECS + CLI_TO_SRV_EPOCH_1_RECS + \ SRV_TO_CLI_EPOCH_0_RECS + SRV_TO_CLI_EPOCH_1_RECS) #define CLI_TO_SRV_RESUME_EPOCH_0_RECS 3 @@ -149,7 +177,8 @@ static int test_dtls_unprocessed(int testidx) #define SRV_TO_CLI_RESUME_EPOCH_0_RECS 2 #define SRV_TO_CLI_RESUME_EPOCH_1_RECS 1 #define TOTAL_RESUME_HAND_RECORDS \ - (CLI_TO_SRV_RESUME_EPOCH_0_RECS + CLI_TO_SRV_RESUME_EPOCH_1_RECS + \ + (CLI_TO_SRV_RESUME_COOKIE_EXCH + SRV_TO_CLI_COOKIE_EXCH + \ + CLI_TO_SRV_RESUME_EPOCH_0_RECS + CLI_TO_SRV_RESUME_EPOCH_1_RECS + \ SRV_TO_CLI_RESUME_EPOCH_0_RECS + SRV_TO_CLI_RESUME_EPOCH_1_RECS) #define TOTAL_RECORDS (TOTAL_FULL_HAND_RECORDS + TOTAL_RESUME_HAND_RECORDS) @@ -167,7 +196,8 @@ static int test_dtls_drop_records(int idx) int testresult = 0; int epoch = 0; SSL_SESSION *sess = NULL; - int cli_to_srv_epoch0, cli_to_srv_epoch1, srv_to_cli_epoch0; + int cli_to_srv_cookie, cli_to_srv_epoch0, cli_to_srv_epoch1; + int srv_to_cli_epoch0; if (!TEST_true(create_ssl_ctx_pair(NULL, DTLS_server_method(), DTLS_client_method(), @@ -186,6 +216,10 @@ static int test_dtls_drop_records(int idx) if (!TEST_true(SSL_CTX_set_dh_auto(sctx, 1))) goto end; + SSL_CTX_set_options(sctx, SSL_OP_COOKIE_EXCHANGE); + SSL_CTX_set_cookie_generate_cb(sctx, generate_cookie_cb); + SSL_CTX_set_cookie_verify_cb(sctx, verify_cookie_cb); + if (idx >= TOTAL_FULL_HAND_RECORDS) { /* We're going to do a resumption handshake. Get a session first. */ if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl, @@ -204,11 +238,13 @@ static int test_dtls_drop_records(int idx) cli_to_srv_epoch0 = CLI_TO_SRV_RESUME_EPOCH_0_RECS; cli_to_srv_epoch1 = CLI_TO_SRV_RESUME_EPOCH_1_RECS; srv_to_cli_epoch0 = SRV_TO_CLI_RESUME_EPOCH_0_RECS; + cli_to_srv_cookie = CLI_TO_SRV_RESUME_COOKIE_EXCH; idx -= TOTAL_FULL_HAND_RECORDS; } else { cli_to_srv_epoch0 = CLI_TO_SRV_EPOCH_0_RECS; cli_to_srv_epoch1 = CLI_TO_SRV_EPOCH_1_RECS; srv_to_cli_epoch0 = SRV_TO_CLI_EPOCH_0_RECS; + cli_to_srv_cookie = CLI_TO_SRV_COOKIE_EXCH; } c_to_s_fbio = BIO_new(bio_f_tls_dump_filter()); @@ -229,18 +265,18 @@ static int test_dtls_drop_records(int idx) DTLS_set_timer_cb(serverssl, timer_cb); /* Work out which record to drop based on the test number */ - if (idx >= cli_to_srv_epoch0 + cli_to_srv_epoch1) { + if (idx >= cli_to_srv_cookie + cli_to_srv_epoch0 + cli_to_srv_epoch1) { mempackbio = SSL_get_wbio(serverssl); - idx -= cli_to_srv_epoch0 + cli_to_srv_epoch1; - if (idx >= srv_to_cli_epoch0) { + idx -= cli_to_srv_cookie + cli_to_srv_epoch0 + cli_to_srv_epoch1; + if (idx >= SRV_TO_CLI_COOKIE_EXCH + srv_to_cli_epoch0) { epoch = 1; - idx -= srv_to_cli_epoch0; + idx -= SRV_TO_CLI_COOKIE_EXCH + srv_to_cli_epoch0; } } else { mempackbio = SSL_get_wbio(clientssl); - if (idx >= cli_to_srv_epoch0) { + if (idx >= cli_to_srv_cookie + cli_to_srv_epoch0) { epoch = 1; - idx -= cli_to_srv_epoch0; + idx -= cli_to_srv_cookie + cli_to_srv_epoch0; } mempackbio = BIO_next(mempackbio); } @@ -270,22 +306,6 @@ static int test_dtls_drop_records(int idx) } #endif /* !defined(OPENSSL_NO_DH) || !defined(OPENSSL_NO_EC) */ -static const char dummy_cookie[] = "0123456"; - -static int generate_cookie_cb(SSL *ssl, unsigned char *cookie, - unsigned int *cookie_len) -{ - memcpy(cookie, dummy_cookie, sizeof(dummy_cookie)); - *cookie_len = sizeof(dummy_cookie); - return 1; -} - -static int verify_cookie_cb(SSL *ssl, const unsigned char *cookie, - unsigned int cookie_len) -{ - return TEST_mem_eq(cookie, cookie_len, dummy_cookie, sizeof(dummy_cookie)); -} - static int test_cookie(void) { SSL_CTX *sctx = NULL, *cctx = NULL; @@ -442,6 +462,93 @@ static int test_just_finished(void) return testresult; } +/* + * Test that swapping an app data record so that it is received before the + * Finished message still works. + */ +static int test_swap_app_data(void) +{ + SSL_CTX *sctx = NULL, *cctx = NULL; + SSL *sssl = NULL, *cssl = NULL; + int testresult = 0; + BIO *bio; + char msg[] = { 0x00, 0x01, 0x02, 0x03 }; + char buf[10]; + + if (!TEST_true(create_ssl_ctx_pair(NULL, DTLS_server_method(), + DTLS_client_method(), + DTLS1_VERSION, 0, + &sctx, &cctx, cert, privkey))) + return 0; + +#ifndef OPENSSL_NO_DTLS1_2 + if (!TEST_true(SSL_CTX_set_cipher_list(cctx, "AES128-SHA"))) + goto end; +#else + /* Default sigalgs are SHA1 based in ctx, NULL, &got_len) <= 0) { - t->err = "INTERNAL_ERROR"; - goto err; - } - - /* - * We may get an absurd output size, which signals that anything goes. - * If not, we specify a too big buffer for the output, to test that - * EVP_PKEY_derive() can cope with it. - */ - if (got_len == SIZE_MAX || got_len == 0) + if (fips_provider_version_eq(libctx, 3, 0, 0)) { + /* FIPS(3.0.0): can't deal with oversized output buffers #18533 */ got_len = expected->output_len; - else - got_len = expected->output_len * 2; + } else { + /* Find out the KDF output size */ + if (EVP_PKEY_derive(expected->ctx, NULL, &got_len) <= 0) { + t->err = "INTERNAL_ERROR"; + goto err; + } + + /* + * We may get an absurd output size, which signals that anything goes. + * If not, we specify a too big buffer for the output, to test that + * EVP_PKEY_derive() can cope with it. + */ + if (got_len == SIZE_MAX || got_len == 0) + got_len = expected->output_len; + else + got_len = expected->output_len * 2; + } if (!TEST_ptr(got = OPENSSL_malloc(got_len == 0 ? 1 : got_len))) { t->err = "INTERNAL_ERROR"; @@ -3699,7 +3705,7 @@ static int parse(EVP_TEST *t) KEY_LIST *key, **klist; EVP_PKEY *pkey; PAIR *pp; - int i, skip_availablein = 0; + int i, j, skipped = 0; top: do { @@ -3786,7 +3792,23 @@ start: t->skip = 1; return 0; } - skip_availablein++; + skipped++; + pp++; + goto start; + } else if (strcmp(pp->key, "FIPSversion") == 0) { + if (prov_available("fips")) { + j = fips_provider_version_match(libctx, pp->value); + if (j < 0) { + TEST_info("Line %d: error matching FIPS versions\n", t->s.curr); + return 0; + } else if (j == 0) { + TEST_info("skipping, FIPS provider incompatible version: %s:%d", + t->s.test_file, t->s.start); + t->skip = 1; + return 0; + } + } + skipped++; pp++; goto start; } @@ -3805,7 +3827,7 @@ start: *klist = key; /* Go back and start a new stanza. */ - if ((t->s.numpairs - skip_availablein) != 1) + if ((t->s.numpairs - skipped) != 1) TEST_info("Line %d: missing blank line\n", t->s.curr); goto top; } @@ -3822,7 +3844,7 @@ start: return 0; } - for (pp++, i = 1; i < (t->s.numpairs - skip_availablein); pp++, i++) { + for (pp++, i = 1; i < (t->s.numpairs - skipped); pp++, i++) { if (strcmp(pp->key, "Securitycheck") == 0) { #if defined(OPENSSL_NO_FIPS_SECURITYCHECKS) #else diff --git a/test/ext_internal_test.c b/test/ext_internal_test.c new file mode 100644 index 0000000000..dc1420aba8 --- /dev/null +++ b/test/ext_internal_test.c @@ -0,0 +1,105 @@ +/* + * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "internal/nelem.h" +#include "../ssl/ssl_local.h" +#include "../ssl/statem/statem_local.h" +#include "testutil.h" + +#define EXT_ENTRY(name) { TLSEXT_IDX_##name, TLSEXT_TYPE_##name, #name } +#define EXT_EXCEPTION(name) { TLSEXT_IDX_##name, TLSEXT_TYPE_invalid, #name } +#define EXT_END(name) { TLSEXT_IDX_##name, TLSEXT_TYPE_out_of_range, #name } + +typedef struct { + size_t idx; + unsigned int type; + char *name; +} EXT_LIST; + +/* The order here does matter! */ +static EXT_LIST ext_list[] = { + + EXT_ENTRY(renegotiate), + EXT_ENTRY(server_name), + EXT_ENTRY(max_fragment_length), +#ifndef OPENSSL_NO_SRP + EXT_ENTRY(srp), +#else + EXT_EXCEPTION(srp), +#endif + EXT_ENTRY(ec_point_formats), + EXT_ENTRY(supported_groups), + EXT_ENTRY(session_ticket), +#ifndef OPENSSL_NO_OCSP + EXT_ENTRY(status_request), +#else + EXT_EXCEPTION(status_request), +#endif +#ifndef OPENSSL_NO_NEXTPROTONEG + EXT_ENTRY(next_proto_neg), +#else + EXT_EXCEPTION(next_proto_neg), +#endif + EXT_ENTRY(application_layer_protocol_negotiation), +#ifndef OPENSSL_NO_SRTP + EXT_ENTRY(use_srtp), +#else + EXT_EXCEPTION(use_srtp), +#endif + EXT_ENTRY(encrypt_then_mac), +#ifndef OPENSSL_NO_CT + EXT_ENTRY(signed_certificate_timestamp), +#else + EXT_EXCEPTION(signed_certificate_timestamp), +#endif + EXT_ENTRY(extended_master_secret), + EXT_ENTRY(signature_algorithms_cert), + EXT_ENTRY(post_handshake_auth), + EXT_ENTRY(signature_algorithms), + EXT_ENTRY(supported_versions), + EXT_ENTRY(psk_kex_modes), + EXT_ENTRY(key_share), + EXT_ENTRY(cookie), + EXT_ENTRY(cryptopro_bug), + EXT_ENTRY(early_data), + EXT_ENTRY(certificate_authorities), + EXT_ENTRY(padding), + EXT_ENTRY(psk), + EXT_END(num_builtins) +}; + +static int test_extension_list(void) +{ + size_t n = OSSL_NELEM(ext_list); + size_t i; + unsigned int type; + int retval = 1; + + for (i = 0; i < n; i++) { + if (!TEST_size_t_eq(i, ext_list[i].idx)) { + retval = 0; + TEST_error("TLSEXT_IDX_%s=%zd, found at=%zd\n", + ext_list[i].name, ext_list[i].idx, i); + } + type = ossl_get_extension_type(ext_list[i].idx); + if (!TEST_uint_eq(type, ext_list[i].type)) { + retval = 0; + TEST_error("TLSEXT_IDX_%s=%zd expected=0x%05X got=0x%05X", + ext_list[i].name, ext_list[i].idx, ext_list[i].type, + type); + } + } + return retval; +} + +int setup_tests(void) +{ + ADD_TEST(test_extension_list); + return 1; +} diff --git a/test/fips_version_test.c b/test/fips_version_test.c new file mode 100644 index 0000000000..dd23bb51e5 --- /dev/null +++ b/test/fips_version_test.c @@ -0,0 +1,78 @@ +/* + * Copyright 2022 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 +#include "testutil.h" + +static OSSL_LIB_CTX *libctx = NULL; +static OSSL_PROVIDER *libprov = NULL; + +typedef enum OPTION_choice { + OPT_ERR = -1, + OPT_EOF = 0, + OPT_CONFIG_FILE, + OPT_TEST_ENUM +} OPTION_CHOICE; + +const OPTIONS *test_get_options(void) +{ + static const OPTIONS test_options[] = { + OPT_TEST_OPTIONS_DEFAULT_USAGE, + { "config", OPT_CONFIG_FILE, '<', + "The configuration file to use for the libctx" }, + { NULL } + }; + return test_options; +} + +static int test_fips_version(int n) +{ + const char *version = test_get_argument(n); + + if (!TEST_ptr(version)) + return 0; + return TEST_int_eq(fips_provider_version_match(libctx, version), 1); +} + +int setup_tests(void) +{ + char *config_file = NULL; + OPTION_CHOICE o; + int n; + + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_CONFIG_FILE: + config_file = opt_arg(); + break; + case OPT_TEST_CASES: + break; + default: + case OPT_ERR: + return 0; + } + } + + if (!test_get_libctx(&libctx, NULL, config_file, &libprov, NULL)) + return 0; + + n = test_get_argument_count(); + if (n == 0) + return 0; + + ADD_ALL_TESTS(test_fips_version, n); + return 1; +} + +void cleanup_tests(void) +{ + OSSL_PROVIDER_unload(libprov); + OSSL_LIB_CTX_free(libctx); +} diff --git a/test/helpers/ssltestlib.c b/test/helpers/ssltestlib.c index 2d992cde23..51740f3599 100644 --- a/test/helpers/ssltestlib.c +++ b/test/helpers/ssltestlib.c @@ -350,8 +350,9 @@ static int mempacket_test_read(BIO *bio, char *out, int outl) unsigned int seq, offset, len, epoch; BIO_clear_retry_flags(bio); - thispkt = sk_MEMPACKET_value(ctx->pkts, 0); - if (thispkt == NULL || thispkt->num != ctx->currpkt) { + if (sk_MEMPACKET_num(ctx->pkts) <= 0 + || (thispkt = sk_MEMPACKET_value(ctx->pkts, 0)) == NULL + || thispkt->num != ctx->currpkt) { /* Probably run out of data */ BIO_set_retry_read(bio); return -1; @@ -410,6 +411,39 @@ static int mempacket_test_read(BIO *bio, char *out, int outl) return outl; } +/* Take the last and penultimate packets and swap them around */ +int mempacket_swap_recent(BIO *bio) +{ + MEMPACKET_TEST_CTX *ctx = BIO_get_data(bio); + MEMPACKET *thispkt; + int numpkts = sk_MEMPACKET_num(ctx->pkts); + + /* We need at least 2 packets to be able to swap them */ + if (numpkts <= 1) + return 0; + + /* Get the penultimate packet */ + thispkt = sk_MEMPACKET_value(ctx->pkts, numpkts - 2); + if (thispkt == NULL) + return 0; + + if (sk_MEMPACKET_delete(ctx->pkts, numpkts - 2) != thispkt) + return 0; + + /* Re-add it to the end of the list */ + thispkt->num++; + if (sk_MEMPACKET_insert(ctx->pkts, thispkt, numpkts - 1) <= 0) + return 0; + + /* We also have to adjust the packet number of the other packet */ + thispkt = sk_MEMPACKET_value(ctx->pkts, numpkts - 2); + if (thispkt == NULL) + return 0; + thispkt->num--; + + return 1; +} + int mempacket_test_inject(BIO *bio, const char *in, int inl, int pktnum, int type) { @@ -469,7 +503,9 @@ int mempacket_test_inject(BIO *bio, const char *in, int inl, int pktnum, thispkt->type = type; } - for(i = 0; (looppkt = sk_MEMPACKET_value(ctx->pkts, i)) != NULL; i++) { + for (i = 0; i < sk_MEMPACKET_num(ctx->pkts); i++) { + if (!TEST_ptr(looppkt = sk_MEMPACKET_value(ctx->pkts, i))) + goto err; /* Check if we found the right place to insert this packet */ if (looppkt->num > thispkt->num) { if (sk_MEMPACKET_insert(ctx->pkts, thispkt, i) == 0) @@ -485,8 +521,9 @@ int mempacket_test_inject(BIO *bio, const char *in, int inl, int pktnum, ctx->lastpkt++; do { i++; - nextpkt = sk_MEMPACKET_value(ctx->pkts, i); - if (nextpkt != NULL && nextpkt->num == ctx->lastpkt) + if (i < sk_MEMPACKET_num(ctx->pkts) + && (nextpkt = sk_MEMPACKET_value(ctx->pkts, i)) != NULL + && nextpkt->num == ctx->lastpkt) ctx->lastpkt++; else return inl; diff --git a/test/helpers/ssltestlib.h b/test/helpers/ssltestlib.h index 0466286365..aa8a6dbfb2 100644 --- a/test/helpers/ssltestlib.h +++ b/test/helpers/ssltestlib.h @@ -49,6 +49,7 @@ void bio_s_always_retry_free(void); #define MEMPACKET_CTRL_GET_DROP_REC (3 << 15) #define MEMPACKET_CTRL_SET_DUPLICATE_REC (4 << 15) +int mempacket_swap_recent(BIO *bio); int mempacket_test_inject(BIO *bio, const char *in, int inl, int pktnum, int type); diff --git a/test/recipes/02-test_internal_exts.t b/test/recipes/02-test_internal_exts.t new file mode 100644 index 0000000000..bec4a216cb --- /dev/null +++ b/test/recipes/02-test_internal_exts.t @@ -0,0 +1,15 @@ +#! /usr/bin/env perl +# Copyright 2022 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the Apache License 2.0 (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +use strict; +use OpenSSL::Test; +use OpenSSL::Test::Simple; + +setup("test_internal_exts"); + +simple_test("test_internal_exts", "ext_internal_test"); diff --git a/test/recipes/15-test_ec.t b/test/recipes/15-test_ec.t index acd1b3960d..354c360362 100644 --- a/test/recipes/15-test_ec.t +++ b/test/recipes/15-test_ec.t @@ -18,7 +18,9 @@ setup("test_ec"); plan skip_all => 'EC is not supported in this build' if disabled('ec'); -plan tests => 14; +plan tests => 15; + +my $no_fips = disabled('fips') || ($ENV{NO_FIPS} // 0); require_ok(srctop_file('test','recipes','tconversion.pl')); @@ -85,3 +87,25 @@ subtest 'Ed448 conversions -- public key' => sub { -in => srctop_file("test", "tested448pub.pem"), -args => ["pkey", "-pubin", "-pubout"] ); }; + +subtest 'Check loading of fips and non-fips keys' => sub { + plan skip_all => "FIPS is disabled" + if $no_fips; + + plan tests => 2; + + my $fipsconf = srctop_file("test", "fips-and-base.cnf"); + $ENV{OPENSSL_CONF} = $fipsconf; + + ok(!run(app(['openssl', 'pkey', + '-check', '-in', srctop_file("test", "testec-p112r1.pem")])), + "Checking non-fips curve key fails in FIPS provider"); + + ok(run(app(['openssl', 'pkey', + '-provider', 'default', + '-propquery', '?fips!=yes', + '-check', '-in', srctop_file("test", "testec-p112r1.pem")])), + "Checking non-fips curve key succeeds with non-fips property query"); + + delete $ENV{OPENSSL_CONF}; +} diff --git a/test/recipes/15-test_ecparam.t b/test/recipes/15-test_ecparam.t index 34efe7adb0..37bf620f35 100644 --- a/test/recipes/15-test_ecparam.t +++ b/test/recipes/15-test_ecparam.t @@ -119,7 +119,7 @@ subtest "Check pkeyparam does not change the parameter file on output" => sub { subtest "Check loading of fips and non-fips params" => sub { plan skip_all => "FIPS is disabled" if $no_fips; - plan tests => 3; + plan tests => 8; my $fipsconf = srctop_file("test", "fips-and-base.cnf"); my $defaultconf = srctop_file("test", "default.cnf"); @@ -141,5 +141,36 @@ subtest "Check loading of fips and non-fips params" => sub { '-check'])), "Fail loading named non-fips curve"); + ok(!run(app(['openssl', 'pkeyparam', + '-in', data_file('valid', 'secp112r1-named.pem'), + '-check'])), + "Fail loading named non-fips curve using pkeyparam"); + + ok(run(app(['openssl', 'ecparam', + '-provider', 'default', + '-propquery', '?fips!=yes', + '-in', data_file('valid', 'secp112r1-named.pem'), + '-check'])), + "Loading named non-fips curve in FIPS mode with non-FIPS property". + " query"); + + ok(run(app(['openssl', 'pkeyparam', + '-provider', 'default', + '-propquery', '?fips!=yes', + '-in', data_file('valid', 'secp112r1-named.pem'), + '-check'])), + "Loading named non-fips curve in FIPS mode with non-FIPS property". + " query using pkeyparam"); + + ok(!run(app(['openssl', 'ecparam', + '-genkey', '-name', 'secp112r1'])), + "Fail generating key for named non-fips curve"); + + ok(run(app(['openssl', 'ecparam', + '-provider', 'default', + '-propquery', '?fips!=yes', + '-genkey', '-name', 'secp112r1'])), + "Generating key for named non-fips curve with non-FIPS property query"); + $ENV{OPENSSL_CONF} = $defaultconf; }; diff --git a/test/recipes/15-test_genrsa.t b/test/recipes/15-test_genrsa.t index 70f080a6db..fe99f33694 100644 --- a/test/recipes/15-test_genrsa.t +++ b/test/recipes/15-test_genrsa.t @@ -24,7 +24,7 @@ use lib bldtop_dir('.'); my $no_fips = disabled('fips') || ($ENV{NO_FIPS} // 0); plan tests => - ($no_fips ? 0 : 3) # Extra FIPS related tests + ($no_fips ? 0 : 5) # Extra FIPS related tests + 15; # We want to know that an absurdly small number of bits isn't support @@ -129,6 +129,17 @@ unless ($no_fips) { '-out', 'genrsatest3072.pem'])), "Generating RSA key with 3072 bits"); + ok(!run(app(['openssl', 'genrsa', @prov, '512'])), + "Generating RSA key with 512 bits should fail in FIPS provider"); + + ok(!run(app(['openssl', 'genrsa', + @prov, + '-provider', 'default', + '-propquery', '?fips!=yes', + '512'])), + "Generating RSA key with 512 bits should succeed with FIPS provider as". + " default with a non-FIPS property query"); + # We want to know that an absurdly large number of bits fails the RNG check is(run(app([ 'openssl', 'genpkey', @prov, diff --git a/test/recipes/20-test_cli_fips.t b/test/recipes/20-test_cli_fips.t index ee78bd7c5f..6d3c5ba1bb 100644 --- a/test/recipes/20-test_cli_fips.t +++ b/test/recipes/20-test_cli_fips.t @@ -67,7 +67,7 @@ sub pubfrompriv { } -my $tsignverify_count = 8; +my $tsignverify_count = 9; sub tsignverify { my $prefix = shift; my $fips_key = shift; @@ -148,6 +148,18 @@ sub tsignverify { $tbs_data])), $testtext); + $testtext = $prefix.': '. + 'Verify something with a non-FIPS key'. + ' in FIPS mode but with a non-FIPS property query'; + ok(run(app(['openssl', 'dgst', + '-provider', 'default', + '-propquery', '?fips!=yes', + '-sha256', + '-verify', $nonfips_pub_key, + '-signature', $sigfile, + $tbs_data])), + $testtext); + $testtext = $prefix.': '. 'Verify a valid signature against the wrong data with a non-FIPS key'. ' (should fail)'; diff --git a/test/recipes/20-test_dgst.t b/test/recipes/20-test_dgst.t index 31254de684..f5895747ca 100644 --- a/test/recipes/20-test_dgst.t +++ b/test/recipes/20-test_dgst.t @@ -17,7 +17,7 @@ use OpenSSL::Test::Utils; setup("test_dgst"); -plan tests => 10; +plan tests => 12; sub tsignverify { my $testtext = shift; @@ -178,3 +178,29 @@ subtest "Custom length XOF digest generation with `dgst` CLI" => sub { ok($xofdata[1] =~ $expected, "XOF: Check second digest value is consistent with the first ($xofdata[1]) vs ($expected)"); }; + +subtest "SHAKE digest generation with no xoflen set `dgst` CLI" => sub { + plan tests => 1; + + my $testdata = srctop_file('test', 'data.bin'); + my @xofdata = run(app(['openssl', 'dgst', '-shake128', $testdata], stderr => "outerr.txt"), capture => 1); + chomp(@xofdata); + my $expected = qr/SHAKE-128\(\Q$testdata\E\)= bb565dac72640109e1c926ef441d3fa6/; + ok($xofdata[0] =~ $expected, "Check short digest is output"); +}; + +SKIP: { + skip "ECDSA is not supported by this OpenSSL build", 1 + if disabled("ec"); + + subtest "signing with xoflen is not supported `dgst` CLI" => sub { + plan tests => 1; + my $data_to_sign = srctop_file('test', 'data.bin'); + + ok(!run(app(['openssl', 'dgst', '-shake256', '-xoflen', '64', + '-sign', srctop_file("test","testec-p256.pem"), + '-out', 'test.sig', + srctop_file('test', 'data.bin')])), + "Generating signature with xoflen should fail"); + } +} diff --git a/test/recipes/20-test_dhparam.t b/test/recipes/20-test_dhparam.t index 78a63508b3..7ca363196e 100644 --- a/test/recipes/20-test_dhparam.t +++ b/test/recipes/20-test_dhparam.t @@ -10,7 +10,7 @@ use strict; use warnings; -use OpenSSL::Test qw(:DEFAULT data_file); +use OpenSSL::Test qw(:DEFAULT data_file srctop_file); use OpenSSL::Test::Utils; #Tests for the dhparam CLI application @@ -19,7 +19,9 @@ setup("test_dhparam"); plan skip_all => "DH is not supported in this build" if disabled("dh"); -plan tests => 17; +plan tests => 21; + +my $fipsconf = srctop_file("test", "fips-and-base.cnf"); sub checkdhparams { my $file = shift; #Filename containing params @@ -171,6 +173,34 @@ SKIP: { checkdhparams("gen-x942-0-512.der", "X9.42", 0, "DER", 512); }; } +SKIP: { + skip "Skipping tests that are only supported in a fips build with security ". + "checks", 4 if (disabled("fips") || disabled("fips-securitychecks")); + + $ENV{OPENSSL_CONF} = $fipsconf; + + ok(!run(app(['openssl', 'dhparam', '-check', '512'])), + "Generating 512 bit DH params should fail in FIPS mode"); + + ok(run(app(['openssl', 'dhparam', '-provider', 'default', '-propquery', + '?fips!=yes', '-check', '512'])), + "Generating 512 bit DH params should succeed in FIPS mode using". + " non-FIPS property query"); + + SKIP: { + skip "Skipping tests that require DSA", 2 if disabled("dsa"); + + ok(!run(app(['openssl', 'dhparam', '-dsaparam', '-check', '512'])), + "Generating 512 bit DSA-style DH params should fail in FIPS mode"); + + ok(run(app(['openssl', 'dhparam', '-provider', 'default', '-propquery', + '?fips!=yes', '-dsaparam', '-check', '512'])), + "Generating 512 bit DSA-style DH params should succeed in FIPS". + " mode using non-FIPS property query"); + } + + delete $ENV{OPENSSL_CONF}; +} ok(run(app(["openssl", "dhparam", "-noout", "-text"], stdin => data_file("pkcs3-2-1024.pem"))), diff --git a/test/recipes/25-test_verify.t b/test/recipes/25-test_verify.t index bf85ba57c1..4613489f57 100644 --- a/test/recipes/25-test_verify.t +++ b/test/recipes/25-test_verify.t @@ -312,12 +312,18 @@ SKIP: { # Same as above but with base provider used for decoding SKIP: { my $no_fips = disabled('fips') || ($ENV{NO_FIPS} // 0); - skip "EC is not supported or FIPS is disabled", 3 - if disabled("ec") || $no_fips; - my $provconf = srctop_file("test", "fips-and-base.cnf"); my $provpath = bldtop_dir("providers"); my @prov = ("-provider-path", $provpath); + + skip "EC is not supported or FIPS is disabled", 3 + if disabled("ec") || $no_fips; + + run(test(["fips_version_test", "-config", $provconf, ">3.0.0"]), + capture => 1, statusvar => \my $exit); + skip "FIPS provider version is too old", 3 + if !$exit; + $ENV{OPENSSL_CONF} = $provconf; ok(!verify("ee-cert-ec-explicit", "", ["root-cert"], diff --git a/test/recipes/30-test_evp_data/evpciph_des3_common.txt b/test/recipes/30-test_evp_data/evpciph_des3_common.txt index dd2b26c145..aa238df2d9 100644 --- a/test/recipes/30-test_evp_data/evpciph_des3_common.txt +++ b/test/recipes/30-test_evp_data/evpciph_des3_common.txt @@ -22,6 +22,8 @@ Ciphertext = 3FE301C962AC01D02213763C1CBD4CDC799657C064ECF5D41C673812CFDE9675 NextIV = 1c673812cfde9675 # DES EDE3 ECB test +# FIPS(3.0.0): has a bug in the IV length #17591 +FIPSversion = >3.0.0 Cipher = DES-EDE3-ECB Key = 0123456789abcdeff1e0d3c2b5a49786fedcba9876543210 Plaintext = 37363534333231204E6F77206973207468652074696D6520666F722000000000 diff --git a/test/recipes/30-test_evp_data/evppkey_ffdhe.txt b/test/recipes/30-test_evp_data/evppkey_ffdhe.txt index 2dc732bfcb..b6b1a8e8a0 100644 --- a/test/recipes/30-test_evp_data/evppkey_ffdhe.txt +++ b/test/recipes/30-test_evp_data/evppkey_ffdhe.txt @@ -105,6 +105,8 @@ CEKAlg=id-aes128-wrap Ctrl = dh_pad:1 SharedSecret=89A249DF4EE9033B89C2B4E52072A736D94F51143A1ED5C8F1E91FCBEBE09654 +# FIPS(3.0.0): allows the padding to be set, later versions do not #17859 +FIPSversion = >3.0.0 Derive=ffdhe2048-2 PeerKey=ffdhe2048-1-pub KDFType=X942KDF-ASN1 diff --git a/test/recipes/80-test_ssl_new.t b/test/recipes/80-test_ssl_new.t index a1828094db..a8c2429538 100644 --- a/test/recipes/80-test_ssl_new.t +++ b/test/recipes/80-test_ssl_new.t @@ -6,6 +6,10 @@ # in the file LICENSE in the source distribution or at # https://www.openssl.org/source/license.html +# For manually running these tests, set specific environment variables like this: +# CTLOG_FILE=test/ct/log_list.cnf +# TEST_CERTS_DIR=test/certs +# For details on the environment variables needed, see test/README.ssltest.md use strict; use warnings; @@ -163,13 +167,14 @@ sub test_conf { skip "No tests available; skipping tests", 1 if $skip; skip "Stale sources; skipping tests", 1 if !$run_test; + my $msg = "running CTLOG_FILE=test/ct/log_list.cnf". # $ENV{CTLOG_FILE}. + " TEST_CERTS_DIR=test/certs". # $ENV{TEST_CERTS_DIR}. + " test/ssl_test test/ssl-tests/$conf $provider"; if ($provider eq "fips") { ok(run(test(["ssl_test", $output_file, $provider, - srctop_file("test", "fips-and-base.cnf")])), - "running ssl_test $conf"); + srctop_file("test", "fips-and-base.cnf")])), $msg); } else { - ok(run(test(["ssl_test", $output_file, $provider])), - "running ssl_test $conf"); + ok(run(test(["ssl_test", $output_file, $provider])), $msg); } } } diff --git a/test/rsa_complex.c b/test/rsa_complex.c index 66b85f0ca0..7c77980f54 100644 --- a/test/rsa_complex.c +++ b/test/rsa_complex.c @@ -11,13 +11,18 @@ * Check to see if there is a conflict between complex.h and openssl/rsa.h. * The former defines "I" as a macro and earlier versions of the latter use * for function arguments. + * + * Will always succeed on djgpp, since its libc does not have complex.h. */ -#if defined(__STDC_VERSION__) -# if __STDC_VERSION__ >= 199901L -# include + +#if !defined(__DJGPP__) +# if defined(__STDC_VERSION__) +# if __STDC_VERSION__ >= 199901L +# include +# endif # endif +# include #endif -#include #include int main(int argc, char *argv[]) diff --git a/test/sslapitest.c b/test/sslapitest.c index ac49f3ba91..19adc96b73 100644 --- a/test/sslapitest.c +++ b/test/sslapitest.c @@ -134,20 +134,6 @@ struct sslapitest_log_counts { }; -static unsigned char serverinfov1[] = { - 0xff, 0xff, /* Dummy extension type */ - 0x00, 0x01, /* Extension length is 1 byte */ - 0xff /* Dummy extension data */ -}; - -static unsigned char serverinfov2[] = { - 0x00, 0x00, 0x00, - (unsigned char)(SSL_EXT_CLIENT_HELLO & 0xff), /* Dummy context - 4 bytes */ - 0xff, 0xff, /* Dummy extension type */ - 0x00, 0x01, /* Extension length is 1 byte */ - 0xff /* Dummy extension data */ -}; - static int hostname_cb(SSL *s, int *al, void *arg) { const char *hostname = SSL_get_servername(s, TLSEXT_NAMETYPE_host_name); @@ -5831,62 +5817,138 @@ end: return testresult; } -/* - * Test loading of serverinfo data in various formats. test_sslmessages actually - * tests to make sure the extensions appear in the handshake - */ -static int test_serverinfo(int tst) -{ - unsigned int version; - unsigned char *sibuf; - size_t sibuflen; - int ret, expected, testresult = 0; - SSL_CTX *ctx; +#if !defined(OPENSSL_NO_TLS1_2) && !defined(OSSL_NO_USABLE_TLS1_3) - ctx = SSL_CTX_new_ex(libctx, NULL, TLS_method()); - if (!TEST_ptr(ctx)) - goto end; +#define SYNTHV1CONTEXT (SSL_EXT_TLS1_2_AND_BELOW_ONLY \ + | SSL_EXT_CLIENT_HELLO \ + | SSL_EXT_TLS1_2_SERVER_HELLO \ + | SSL_EXT_IGNORE_ON_RESUMPTION) - if ((tst & 0x01) == 0x01) - version = SSL_SERVERINFOV2; - else - version = SSL_SERVERINFOV1; +#define TLS13CONTEXT (SSL_EXT_TLS1_3_CERTIFICATE \ + | SSL_EXT_TLS1_2_SERVER_HELLO \ + | SSL_EXT_CLIENT_HELLO) - if ((tst & 0x02) == 0x02) { - sibuf = serverinfov2; - sibuflen = sizeof(serverinfov2); - expected = (version == SSL_SERVERINFOV2); - } else { - sibuf = serverinfov1; - sibuflen = sizeof(serverinfov1); - expected = (version == SSL_SERVERINFOV1); +#define SERVERINFO_CUSTOM \ + 0x00, (char)TLSEXT_TYPE_signed_certificate_timestamp, \ + 0x00, 0x03, \ + 0x04, 0x05, 0x06 \ + +static const unsigned char serverinfo_custom_tls13[] = { + 0x00, 0x00, (TLS13CONTEXT >> 8) & 0xff, TLS13CONTEXT & 0xff, + SERVERINFO_CUSTOM +}; +static const unsigned char serverinfo_custom_v2[] = { + 0x00, 0x00, (SYNTHV1CONTEXT >> 8) & 0xff, SYNTHV1CONTEXT & 0xff, + SERVERINFO_CUSTOM +}; +static const unsigned char serverinfo_custom_v1[] = { + SERVERINFO_CUSTOM +}; +static const size_t serverinfo_custom_tls13_len = sizeof(serverinfo_custom_tls13); +static const size_t serverinfo_custom_v2_len = sizeof(serverinfo_custom_v2); +static const size_t serverinfo_custom_v1_len = sizeof(serverinfo_custom_v1); + +static int serverinfo_custom_parse_cb(SSL *s, unsigned int ext_type, + unsigned int context, + const unsigned char *in, + size_t inlen, X509 *x, + size_t chainidx, int *al, + void *parse_arg) +{ + const size_t len = serverinfo_custom_v1_len; + const unsigned char *si = &serverinfo_custom_v1[len - 3]; + int *p_cb_result = (int*)parse_arg; + *p_cb_result = TEST_mem_eq(in, inlen, si, 3); + return 1; +} + +static int test_serverinfo_custom(const int idx) +{ + SSL_CTX *sctx = NULL, *cctx = NULL; + SSL *clientssl = NULL, *serverssl = NULL; + int testresult = 0; + int cb_result = 0; + + /* + * Following variables are set in the switch statement + * according to the test iteration. + * Default values do not make much sense: test would fail with them. + */ + int serverinfo_version = 0; + int protocol_version = 0; + unsigned int extension_context = 0; + const unsigned char *si = NULL; + size_t si_len = 0; + + const int call_use_serverinfo_ex = idx > 0; + switch (idx) { + case 0: /* FALLTHROUGH */ + case 1: + serverinfo_version = SSL_SERVERINFOV1; + protocol_version = TLS1_2_VERSION; + extension_context = SYNTHV1CONTEXT; + si = serverinfo_custom_v1; + si_len = serverinfo_custom_v1_len; + break; + case 2: + serverinfo_version = SSL_SERVERINFOV2; + protocol_version = TLS1_2_VERSION; + extension_context = SYNTHV1CONTEXT; + si = serverinfo_custom_v2; + si_len = serverinfo_custom_v2_len; + break; + case 3: + serverinfo_version = SSL_SERVERINFOV2; + protocol_version = TLS1_3_VERSION; + extension_context = TLS13CONTEXT; + si = serverinfo_custom_tls13; + si_len = serverinfo_custom_tls13_len; + break; } - if ((tst & 0x04) == 0x04) { - ret = SSL_CTX_use_serverinfo_ex(ctx, version, sibuf, sibuflen); - } else { - ret = SSL_CTX_use_serverinfo(ctx, sibuf, sibuflen); + if (!TEST_true(create_ssl_ctx_pair(libctx, + TLS_method(), + TLS_method(), + protocol_version, + protocol_version, + &sctx, &cctx, cert, privkey))) + goto end; - /* - * The version variable is irrelevant in this case - it's what is in the - * buffer that matters - */ - if ((tst & 0x02) == 0x02) - expected = 0; - else - expected = 1; + if (call_use_serverinfo_ex) { + if (!TEST_true(SSL_CTX_use_serverinfo_ex(sctx, serverinfo_version, + si, si_len))) + goto end; + } else { + if (!TEST_true(SSL_CTX_use_serverinfo(sctx, si, si_len))) + goto end; } - if (!TEST_true(ret == expected)) + if (!TEST_true(SSL_CTX_add_custom_ext(cctx, TLSEXT_TYPE_signed_certificate_timestamp, + extension_context, + NULL, NULL, NULL, + serverinfo_custom_parse_cb, + &cb_result)) + || !TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl, + NULL, NULL)) + || !TEST_true(create_ssl_connection(serverssl, clientssl, + SSL_ERROR_NONE)) + || !TEST_int_eq(SSL_do_handshake(clientssl), 1)) + goto end; + + if (!TEST_true(cb_result)) goto end; testresult = 1; end: - SSL_CTX_free(ctx); + SSL_free(serverssl); + SSL_free(clientssl); + SSL_CTX_free(sctx); + SSL_CTX_free(cctx); return testresult; } +#endif /* * Test that SSL_export_keying_material() produces expected results. There are @@ -7548,11 +7610,24 @@ static int tick_key_cb(SSL *s, unsigned char key_name[16], { const unsigned char tick_aes_key[16] = "0123456789abcdef"; const unsigned char tick_hmac_key[16] = "0123456789abcdef"; - EVP_CIPHER *aes128cbc = EVP_CIPHER_fetch(libctx, "AES-128-CBC", NULL); - EVP_MD *sha256 = EVP_MD_fetch(libctx, "SHA-256", NULL); + EVP_CIPHER *aes128cbc; + EVP_MD *sha256; int ret; tick_key_cb_called = 1; + + if (tick_key_renew == -1) + return 0; + + aes128cbc = EVP_CIPHER_fetch(libctx, "AES-128-CBC", NULL); + if (!TEST_ptr(aes128cbc)) + return 0; + sha256 = EVP_MD_fetch(libctx, "SHA-256", NULL); + if (!TEST_ptr(sha256)) { + EVP_CIPHER_free(aes128cbc); + return 0; + } + memset(iv, 0, AES_BLOCK_SIZE); memset(key_name, 0, 16); if (aes128cbc == NULL @@ -7578,10 +7653,18 @@ static int tick_key_evp_cb(SSL *s, unsigned char key_name[16], const unsigned char tick_aes_key[16] = "0123456789abcdef"; unsigned char tick_hmac_key[16] = "0123456789abcdef"; OSSL_PARAM params[2]; - EVP_CIPHER *aes128cbc = EVP_CIPHER_fetch(libctx, "AES-128-CBC", NULL); + EVP_CIPHER *aes128cbc; int ret; tick_key_cb_called = 1; + + if (tick_key_renew == -1) + return 0; + + aes128cbc = EVP_CIPHER_fetch(libctx, "AES-128-CBC", NULL); + if (!TEST_ptr(aes128cbc)) + return 0; + memset(iv, 0, AES_BLOCK_SIZE); memset(key_name, 0, 16); params[0] = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST, @@ -7614,10 +7697,14 @@ static int tick_key_evp_cb(SSL *s, unsigned char key_name[16], * Test 9: TLSv1.3, old ticket key callback, ticket, no renewal * Test 10: TLSv1.2, old ticket key callback, ticket, renewal * Test 11: TLSv1.3, old ticket key callback, ticket, renewal - * Test 12: TLSv1.2, ticket key callback, ticket, no renewal - * Test 13: TLSv1.3, ticket key callback, ticket, no renewal - * Test 14: TLSv1.2, ticket key callback, ticket, renewal - * Test 15: TLSv1.3, ticket key callback, ticket, renewal + * Test 12: TLSv1.2, old ticket key callback, no ticket + * Test 13: TLSv1.3, old ticket key callback, no ticket + * Test 14: TLSv1.2, ticket key callback, ticket, no renewal + * Test 15: TLSv1.3, ticket key callback, ticket, no renewal + * Test 16: TLSv1.2, ticket key callback, ticket, renewal + * Test 17: TLSv1.3, ticket key callback, ticket, renewal + * Test 18: TLSv1.2, ticket key callback, no ticket + * Test 19: TLSv1.3, ticket key callback, no ticket */ static int test_ticket_callbacks(int tst) { @@ -7635,15 +7722,18 @@ static int test_ticket_callbacks(int tst) return 1; #endif #ifdef OPENSSL_NO_DEPRECATED_3_0 - if (tst >= 8 && tst <= 11) + if (tst >= 8 && tst <= 13) return 1; #endif gen_tick_called = dec_tick_called = tick_key_cb_called = 0; /* Which tests the ticket key callback should request renewal for */ - if (tst == 10 || tst == 11 || tst == 14 || tst == 15) + + if (tst == 10 || tst == 11 || tst == 16 || tst == 17) tick_key_renew = 1; + else if (tst == 12 || tst == 13 || tst == 18 || tst == 19) + tick_key_renew = -1; /* abort sending the ticket/0-length ticket */ else tick_key_renew = 0; @@ -7692,7 +7782,7 @@ static int test_ticket_callbacks(int tst) NULL))) goto end; - if (tst >= 12) { + if (tst >= 14) { if (!TEST_true(SSL_CTX_set_tlsext_ticket_key_evp_cb(sctx, tick_key_evp_cb))) goto end; #ifndef OPENSSL_NO_DEPRECATED_3_0 @@ -7737,7 +7827,8 @@ static int test_ticket_callbacks(int tst) goto end; if (tick_dec_ret == SSL_TICKET_RETURN_IGNORE - || tick_dec_ret == SSL_TICKET_RETURN_IGNORE_RENEW) { + || tick_dec_ret == SSL_TICKET_RETURN_IGNORE_RENEW + || tick_key_renew == -1) { if (!TEST_false(SSL_session_reused(clientssl))) goto end; } else { @@ -7750,7 +7841,8 @@ static int test_ticket_callbacks(int tst) || tick_dec_ret == SSL_TICKET_RETURN_IGNORE_RENEW || tick_dec_ret == SSL_TICKET_RETURN_USE_RENEW) ? 1 : 0) - || !TEST_int_eq(dec_tick_called, 1)) + /* There is no ticket to decrypt in tests 13 and 19 */ + || !TEST_int_eq(dec_tick_called, (tst == 13 || tst == 19) ? 0 : 1)) goto end; testresult = 1; @@ -8437,7 +8529,7 @@ static int test_multiblock_write(int test_index) * Check if the cipher exists before attempting to use it since it only has * a hardware specific implementation. */ - ciph = EVP_CIPHER_fetch(NULL, fetchable_ciphers[test_index], ""); + ciph = EVP_CIPHER_fetch(libctx, fetchable_ciphers[test_index], ""); if (ciph == NULL) { TEST_skip("Multiblock cipher is not available for %s", cipherlist); return 1; @@ -10001,7 +10093,6 @@ int setup_tests(void) #else ADD_ALL_TESTS(test_custom_exts, 3); #endif - ADD_ALL_TESTS(test_serverinfo, 8); ADD_ALL_TESTS(test_export_key_mat, 6); #ifndef OSSL_NO_USABLE_TLS1_3 ADD_ALL_TESTS(test_export_key_mat_early, 3); @@ -10019,7 +10110,7 @@ int setup_tests(void) ADD_ALL_TESTS(test_info_callback, 6); ADD_ALL_TESTS(test_ssl_pending, 2); ADD_ALL_TESTS(test_ssl_get_shared_ciphers, OSSL_NELEM(shared_ciphers_data)); - ADD_ALL_TESTS(test_ticket_callbacks, 16); + ADD_ALL_TESTS(test_ticket_callbacks, 20); ADD_ALL_TESTS(test_shutdown, 7); ADD_ALL_TESTS(test_incorrect_shutdown, 2); ADD_ALL_TESTS(test_cert_cb, 6); @@ -10053,6 +10144,9 @@ int setup_tests(void) ADD_TEST(test_set_verify_cert_store_ssl); ADD_ALL_TESTS(test_session_timeout, 1); ADD_TEST(test_load_dhfile); +#if !defined(OPENSSL_NO_TLS1_2) && !defined(OSSL_NO_USABLE_TLS1_3) + ADD_ALL_TESTS(test_serverinfo_custom, 4); +#endif return 1; err: diff --git a/test/test_test.c b/test/test_test.c index 35c612726f..b31f5eb432 100644 --- a/test/test_test.c +++ b/test/test_test.c @@ -33,19 +33,19 @@ static int test_case(int expected, const char *test, int result) static int test_int(void) { if (!TEST(1, TEST_int_eq(1, 1)) - | !TEST(0, TEST_int_eq(1, -1)) - | !TEST(1, TEST_int_ne(1, 2)) - | !TEST(0, TEST_int_ne(3, 3)) - | !TEST(1, TEST_int_lt(4, 9)) - | !TEST(0, TEST_int_lt(9, 4)) - | !TEST(1, TEST_int_le(4, 9)) - | !TEST(1, TEST_int_le(5, 5)) - | !TEST(0, TEST_int_le(9, 4)) - | !TEST(1, TEST_int_gt(8, 5)) - | !TEST(0, TEST_int_gt(5, 8)) - | !TEST(1, TEST_int_ge(8, 5)) - | !TEST(1, TEST_int_ge(6, 6)) - | !TEST(0, TEST_int_ge(5, 8))) + || !TEST(0, TEST_int_eq(1, -1)) + || !TEST(1, TEST_int_ne(1, 2)) + || !TEST(0, TEST_int_ne(3, 3)) + || !TEST(1, TEST_int_lt(4, 9)) + || !TEST(0, TEST_int_lt(9, 4)) + || !TEST(1, TEST_int_le(4, 9)) + || !TEST(1, TEST_int_le(5, 5)) + || !TEST(0, TEST_int_le(9, 4)) + || !TEST(1, TEST_int_gt(8, 5)) + || !TEST(0, TEST_int_gt(5, 8)) + || !TEST(1, TEST_int_ge(8, 5)) + || !TEST(1, TEST_int_ge(6, 6)) + || !TEST(0, TEST_int_ge(5, 8))) goto err; return 1; @@ -56,19 +56,19 @@ err: static int test_uint(void) { if (!TEST(1, TEST_uint_eq(3u, 3u)) - | !TEST(0, TEST_uint_eq(3u, 5u)) - | !TEST(1, TEST_uint_ne(4u, 2u)) - | !TEST(0, TEST_uint_ne(6u, 6u)) - | !TEST(1, TEST_uint_lt(5u, 9u)) - | !TEST(0, TEST_uint_lt(9u, 5u)) - | !TEST(1, TEST_uint_le(5u, 9u)) - | !TEST(1, TEST_uint_le(7u, 7u)) - | !TEST(0, TEST_uint_le(9u, 5u)) - | !TEST(1, TEST_uint_gt(11u, 1u)) - | !TEST(0, TEST_uint_gt(1u, 11u)) - | !TEST(1, TEST_uint_ge(11u, 1u)) - | !TEST(1, TEST_uint_ge(6u, 6u)) - | !TEST(0, TEST_uint_ge(1u, 11u))) + || !TEST(0, TEST_uint_eq(3u, 5u)) + || !TEST(1, TEST_uint_ne(4u, 2u)) + || !TEST(0, TEST_uint_ne(6u, 6u)) + || !TEST(1, TEST_uint_lt(5u, 9u)) + || !TEST(0, TEST_uint_lt(9u, 5u)) + || !TEST(1, TEST_uint_le(5u, 9u)) + || !TEST(1, TEST_uint_le(7u, 7u)) + || !TEST(0, TEST_uint_le(9u, 5u)) + || !TEST(1, TEST_uint_gt(11u, 1u)) + || !TEST(0, TEST_uint_gt(1u, 11u)) + || !TEST(1, TEST_uint_ge(11u, 1u)) + || !TEST(1, TEST_uint_ge(6u, 6u)) + || !TEST(0, TEST_uint_ge(1u, 11u))) goto err; return 1; @@ -79,19 +79,19 @@ err: static int test_char(void) { if (!TEST(1, TEST_char_eq('a', 'a')) - | !TEST(0, TEST_char_eq('a', 'A')) - | !TEST(1, TEST_char_ne('a', 'c')) - | !TEST(0, TEST_char_ne('e', 'e')) - | !TEST(1, TEST_char_lt('i', 'x')) - | !TEST(0, TEST_char_lt('x', 'i')) - | !TEST(1, TEST_char_le('i', 'x')) - | !TEST(1, TEST_char_le('n', 'n')) - | !TEST(0, TEST_char_le('x', 'i')) - | !TEST(1, TEST_char_gt('w', 'n')) - | !TEST(0, TEST_char_gt('n', 'w')) - | !TEST(1, TEST_char_ge('w', 'n')) - | !TEST(1, TEST_char_ge('p', 'p')) - | !TEST(0, TEST_char_ge('n', 'w'))) + || !TEST(0, TEST_char_eq('a', 'A')) + || !TEST(1, TEST_char_ne('a', 'c')) + || !TEST(0, TEST_char_ne('e', 'e')) + || !TEST(1, TEST_char_lt('i', 'x')) + || !TEST(0, TEST_char_lt('x', 'i')) + || !TEST(1, TEST_char_le('i', 'x')) + || !TEST(1, TEST_char_le('n', 'n')) + || !TEST(0, TEST_char_le('x', 'i')) + || !TEST(1, TEST_char_gt('w', 'n')) + || !TEST(0, TEST_char_gt('n', 'w')) + || !TEST(1, TEST_char_ge('w', 'n')) + || !TEST(1, TEST_char_ge('p', 'p')) + || !TEST(0, TEST_char_ge('n', 'w'))) goto err; return 1; @@ -102,19 +102,19 @@ err: static int test_uchar(void) { if (!TEST(1, TEST_uchar_eq(49, 49)) - | !TEST(0, TEST_uchar_eq(49, 60)) - | !TEST(1, TEST_uchar_ne(50, 2)) - | !TEST(0, TEST_uchar_ne(66, 66)) - | !TEST(1, TEST_uchar_lt(60, 80)) - | !TEST(0, TEST_uchar_lt(80, 60)) - | !TEST(1, TEST_uchar_le(60, 80)) - | !TEST(1, TEST_uchar_le(78, 78)) - | !TEST(0, TEST_uchar_le(80, 60)) - | !TEST(1, TEST_uchar_gt(88, 37)) - | !TEST(0, TEST_uchar_gt(37, 88)) - | !TEST(1, TEST_uchar_ge(88, 37)) - | !TEST(1, TEST_uchar_ge(66, 66)) - | !TEST(0, TEST_uchar_ge(37, 88))) + || !TEST(0, TEST_uchar_eq(49, 60)) + || !TEST(1, TEST_uchar_ne(50, 2)) + || !TEST(0, TEST_uchar_ne(66, 66)) + || !TEST(1, TEST_uchar_lt(60, 80)) + || !TEST(0, TEST_uchar_lt(80, 60)) + || !TEST(1, TEST_uchar_le(60, 80)) + || !TEST(1, TEST_uchar_le(78, 78)) + || !TEST(0, TEST_uchar_le(80, 60)) + || !TEST(1, TEST_uchar_gt(88, 37)) + || !TEST(0, TEST_uchar_gt(37, 88)) + || !TEST(1, TEST_uchar_ge(88, 37)) + || !TEST(1, TEST_uchar_ge(66, 66)) + || !TEST(0, TEST_uchar_ge(37, 88))) goto err; return 1; @@ -125,19 +125,19 @@ err: static int test_long(void) { if (!TEST(1, TEST_long_eq(123l, 123l)) - | !TEST(0, TEST_long_eq(123l, -123l)) - | !TEST(1, TEST_long_ne(123l, 500l)) - | !TEST(0, TEST_long_ne(1000l, 1000l)) - | !TEST(1, TEST_long_lt(-8923l, 102934563l)) - | !TEST(0, TEST_long_lt(102934563l, -8923l)) - | !TEST(1, TEST_long_le(-8923l, 102934563l)) - | !TEST(1, TEST_long_le(12345l, 12345l)) - | !TEST(0, TEST_long_le(102934563l, -8923l)) - | !TEST(1, TEST_long_gt(84325677l, 12345l)) - | !TEST(0, TEST_long_gt(12345l, 84325677l)) - | !TEST(1, TEST_long_ge(84325677l, 12345l)) - | !TEST(1, TEST_long_ge(465869l, 465869l)) - | !TEST(0, TEST_long_ge(12345l, 84325677l))) + || !TEST(0, TEST_long_eq(123l, -123l)) + || !TEST(1, TEST_long_ne(123l, 500l)) + || !TEST(0, TEST_long_ne(1000l, 1000l)) + || !TEST(1, TEST_long_lt(-8923l, 102934563l)) + || !TEST(0, TEST_long_lt(102934563l, -8923l)) + || !TEST(1, TEST_long_le(-8923l, 102934563l)) + || !TEST(1, TEST_long_le(12345l, 12345l)) + || !TEST(0, TEST_long_le(102934563l, -8923l)) + || !TEST(1, TEST_long_gt(84325677l, 12345l)) + || !TEST(0, TEST_long_gt(12345l, 84325677l)) + || !TEST(1, TEST_long_ge(84325677l, 12345l)) + || !TEST(1, TEST_long_ge(465869l, 465869l)) + || !TEST(0, TEST_long_ge(12345l, 84325677l))) goto err; return 1; @@ -148,19 +148,19 @@ err: static int test_ulong(void) { if (!TEST(1, TEST_ulong_eq(919ul, 919ul)) - | !TEST(0, TEST_ulong_eq(919ul, 10234ul)) - | !TEST(1, TEST_ulong_ne(8190ul, 66ul)) - | !TEST(0, TEST_ulong_ne(10555ul, 10555ul)) - | !TEST(1, TEST_ulong_lt(10234ul, 1000000ul)) - | !TEST(0, TEST_ulong_lt(1000000ul, 10234ul)) - | !TEST(1, TEST_ulong_le(10234ul, 1000000ul)) - | !TEST(1, TEST_ulong_le(100000ul, 100000ul)) - | !TEST(0, TEST_ulong_le(1000000ul, 10234ul)) - | !TEST(1, TEST_ulong_gt(100000000ul, 22ul)) - | !TEST(0, TEST_ulong_gt(22ul, 100000000ul)) - | !TEST(1, TEST_ulong_ge(100000000ul, 22ul)) - | !TEST(1, TEST_ulong_ge(10555ul, 10555ul)) - | !TEST(0, TEST_ulong_ge(22ul, 100000000ul))) + || !TEST(0, TEST_ulong_eq(919ul, 10234ul)) + || !TEST(1, TEST_ulong_ne(8190ul, 66ul)) + || !TEST(0, TEST_ulong_ne(10555ul, 10555ul)) + || !TEST(1, TEST_ulong_lt(10234ul, 1000000ul)) + || !TEST(0, TEST_ulong_lt(1000000ul, 10234ul)) + || !TEST(1, TEST_ulong_le(10234ul, 1000000ul)) + || !TEST(1, TEST_ulong_le(100000ul, 100000ul)) + || !TEST(0, TEST_ulong_le(1000000ul, 10234ul)) + || !TEST(1, TEST_ulong_gt(100000000ul, 22ul)) + || !TEST(0, TEST_ulong_gt(22ul, 100000000ul)) + || !TEST(1, TEST_ulong_ge(100000000ul, 22ul)) + || !TEST(1, TEST_ulong_ge(10555ul, 10555ul)) + || !TEST(0, TEST_ulong_ge(22ul, 100000000ul))) goto err; return 1; @@ -171,19 +171,19 @@ err: static int test_size_t(void) { if (!TEST(1, TEST_size_t_eq((size_t)10, (size_t)10)) - | !TEST(0, TEST_size_t_eq((size_t)10, (size_t)12)) - | !TEST(1, TEST_size_t_ne((size_t)10, (size_t)12)) - | !TEST(0, TEST_size_t_ne((size_t)24, (size_t)24)) - | !TEST(1, TEST_size_t_lt((size_t)30, (size_t)88)) - | !TEST(0, TEST_size_t_lt((size_t)88, (size_t)30)) - | !TEST(1, TEST_size_t_le((size_t)30, (size_t)88)) - | !TEST(1, TEST_size_t_le((size_t)33, (size_t)33)) - | !TEST(0, TEST_size_t_le((size_t)88, (size_t)30)) - | !TEST(1, TEST_size_t_gt((size_t)52, (size_t)33)) - | !TEST(0, TEST_size_t_gt((size_t)33, (size_t)52)) - | !TEST(1, TEST_size_t_ge((size_t)52, (size_t)33)) - | !TEST(1, TEST_size_t_ge((size_t)38, (size_t)38)) - | !TEST(0, TEST_size_t_ge((size_t)33, (size_t)52))) + || !TEST(0, TEST_size_t_eq((size_t)10, (size_t)12)) + || !TEST(1, TEST_size_t_ne((size_t)10, (size_t)12)) + || !TEST(0, TEST_size_t_ne((size_t)24, (size_t)24)) + || !TEST(1, TEST_size_t_lt((size_t)30, (size_t)88)) + || !TEST(0, TEST_size_t_lt((size_t)88, (size_t)30)) + || !TEST(1, TEST_size_t_le((size_t)30, (size_t)88)) + || !TEST(1, TEST_size_t_le((size_t)33, (size_t)33)) + || !TEST(0, TEST_size_t_le((size_t)88, (size_t)30)) + || !TEST(1, TEST_size_t_gt((size_t)52, (size_t)33)) + || !TEST(0, TEST_size_t_gt((size_t)33, (size_t)52)) + || !TEST(1, TEST_size_t_ge((size_t)52, (size_t)33)) + || !TEST(1, TEST_size_t_ge((size_t)38, (size_t)38)) + || !TEST(0, TEST_size_t_ge((size_t)33, (size_t)52))) goto err; return 1; @@ -194,19 +194,19 @@ err: static int test_time_t(void) { if (!TEST(1, TEST_time_t_eq((time_t)10, (time_t)10)) - | !TEST(0, TEST_time_t_eq((time_t)10, (time_t)12)) - | !TEST(1, TEST_time_t_ne((time_t)10, (time_t)12)) - | !TEST(0, TEST_time_t_ne((time_t)24, (time_t)24)) - | !TEST(1, TEST_time_t_lt((time_t)30, (time_t)88)) - | !TEST(0, TEST_time_t_lt((time_t)88, (time_t)30)) - | !TEST(1, TEST_time_t_le((time_t)30, (time_t)88)) - | !TEST(1, TEST_time_t_le((time_t)33, (time_t)33)) - | !TEST(0, TEST_time_t_le((time_t)88, (time_t)30)) - | !TEST(1, TEST_time_t_gt((time_t)52, (time_t)33)) - | !TEST(0, TEST_time_t_gt((time_t)33, (time_t)52)) - | !TEST(1, TEST_time_t_ge((time_t)52, (time_t)33)) - | !TEST(1, TEST_time_t_ge((time_t)38, (time_t)38)) - | !TEST(0, TEST_time_t_ge((time_t)33, (time_t)52))) + || !TEST(0, TEST_time_t_eq((time_t)10, (time_t)12)) + || !TEST(1, TEST_time_t_ne((time_t)10, (time_t)12)) + || !TEST(0, TEST_time_t_ne((time_t)24, (time_t)24)) + || !TEST(1, TEST_time_t_lt((time_t)30, (time_t)88)) + || !TEST(0, TEST_time_t_lt((time_t)88, (time_t)30)) + || !TEST(1, TEST_time_t_le((time_t)30, (time_t)88)) + || !TEST(1, TEST_time_t_le((time_t)33, (time_t)33)) + || !TEST(0, TEST_time_t_le((time_t)88, (time_t)30)) + || !TEST(1, TEST_time_t_gt((time_t)52, (time_t)33)) + || !TEST(0, TEST_time_t_gt((time_t)33, (time_t)52)) + || !TEST(1, TEST_time_t_ge((time_t)52, (time_t)33)) + || !TEST(1, TEST_time_t_ge((time_t)38, (time_t)38)) + || !TEST(0, TEST_time_t_ge((time_t)33, (time_t)52))) goto err; return 1; @@ -220,19 +220,19 @@ static int test_pointer(void) char y = 1; if (!TEST(1, TEST_ptr(&y)) - | !TEST(0, TEST_ptr(NULL)) - | !TEST(0, TEST_ptr_null(&y)) - | !TEST(1, TEST_ptr_null(NULL)) - | !TEST(1, TEST_ptr_eq(NULL, NULL)) - | !TEST(0, TEST_ptr_eq(NULL, &y)) - | !TEST(0, TEST_ptr_eq(&y, NULL)) - | !TEST(0, TEST_ptr_eq(&y, &x)) - | !TEST(1, TEST_ptr_eq(&x, &x)) - | !TEST(0, TEST_ptr_ne(NULL, NULL)) - | !TEST(1, TEST_ptr_ne(NULL, &y)) - | !TEST(1, TEST_ptr_ne(&y, NULL)) - | !TEST(1, TEST_ptr_ne(&y, &x)) - | !TEST(0, TEST_ptr_ne(&x, &x))) + || !TEST(0, TEST_ptr(NULL)) + || !TEST(0, TEST_ptr_null(&y)) + || !TEST(1, TEST_ptr_null(NULL)) + || !TEST(1, TEST_ptr_eq(NULL, NULL)) + || !TEST(0, TEST_ptr_eq(NULL, &y)) + || !TEST(0, TEST_ptr_eq(&y, NULL)) + || !TEST(0, TEST_ptr_eq(&y, &x)) + || !TEST(1, TEST_ptr_eq(&x, &x)) + || !TEST(0, TEST_ptr_ne(NULL, NULL)) + || !TEST(1, TEST_ptr_ne(NULL, &y)) + || !TEST(1, TEST_ptr_ne(&y, NULL)) + || !TEST(1, TEST_ptr_ne(&y, &x)) + || !TEST(0, TEST_ptr_ne(&x, &x))) goto err; return 1; @@ -243,9 +243,9 @@ err: static int test_bool(void) { if (!TEST(0, TEST_true(0)) - | !TEST(1, TEST_true(1)) - | !TEST(1, TEST_false(0)) - | !TEST(0, TEST_false(1))) + || !TEST(1, TEST_true(1)) + || !TEST(1, TEST_false(0)) + || !TEST(0, TEST_false(1))) goto err; return 1; @@ -258,19 +258,19 @@ static int test_string(void) static char buf[] = "abc"; if (!TEST(1, TEST_str_eq(NULL, NULL)) - | !TEST(1, TEST_str_eq("abc", buf)) - | !TEST(0, TEST_str_eq("abc", NULL)) - | !TEST(0, TEST_str_eq("abc", "")) - | !TEST(0, TEST_str_eq(NULL, buf)) - | !TEST(0, TEST_str_ne(NULL, NULL)) - | !TEST(0, TEST_str_eq("", NULL)) - | !TEST(0, TEST_str_eq(NULL, "")) - | !TEST(0, TEST_str_ne("", "")) - | !TEST(0, TEST_str_eq("\1\2\3\4\5", "\1x\3\6\5")) - | !TEST(0, TEST_str_ne("abc", buf)) - | !TEST(1, TEST_str_ne("abc", NULL)) - | !TEST(1, TEST_str_ne(NULL, buf)) - | !TEST(0, TEST_str_eq("abcdef", "abcdefghijk"))) + || !TEST(1, TEST_str_eq("abc", buf)) + || !TEST(0, TEST_str_eq("abc", NULL)) + || !TEST(0, TEST_str_eq("abc", "")) + || !TEST(0, TEST_str_eq(NULL, buf)) + || !TEST(0, TEST_str_ne(NULL, NULL)) + || !TEST(0, TEST_str_eq("", NULL)) + || !TEST(0, TEST_str_eq(NULL, "")) + || !TEST(0, TEST_str_ne("", "")) + || !TEST(0, TEST_str_eq("\1\2\3\4\5", "\1x\3\6\5")) + || !TEST(0, TEST_str_ne("abc", buf)) + || !TEST(1, TEST_str_ne("abc", NULL)) + || !TEST(1, TEST_str_ne(NULL, buf)) + || !TEST(0, TEST_str_eq("abcdef", "abcdefghijk"))) goto err; return 1; @@ -283,16 +283,16 @@ static int test_memory(void) static char buf[] = "xyz"; if (!TEST(1, TEST_mem_eq(NULL, 0, NULL, 0)) - | !TEST(1, TEST_mem_eq(NULL, 1, NULL, 2)) - | !TEST(0, TEST_mem_eq(NULL, 0, "xyz", 3)) - | !TEST(0, TEST_mem_eq(NULL, 7, "abc", 3)) - | !TEST(0, TEST_mem_ne(NULL, 0, NULL, 0)) - | !TEST(0, TEST_mem_eq(NULL, 0, "", 0)) - | !TEST(0, TEST_mem_eq("", 0, NULL, 0)) - | !TEST(0, TEST_mem_ne("", 0, "", 0)) - | !TEST(0, TEST_mem_eq("xyz", 3, NULL, 0)) - | !TEST(0, TEST_mem_eq("xyz", 3, buf, sizeof(buf))) - | !TEST(1, TEST_mem_eq("xyz", 4, buf, sizeof(buf)))) + || !TEST(1, TEST_mem_eq(NULL, 1, NULL, 2)) + || !TEST(0, TEST_mem_eq(NULL, 0, "xyz", 3)) + || !TEST(0, TEST_mem_eq(NULL, 7, "abc", 3)) + || !TEST(0, TEST_mem_ne(NULL, 0, NULL, 0)) + || !TEST(0, TEST_mem_eq(NULL, 0, "", 0)) + || !TEST(0, TEST_mem_eq("", 0, NULL, 0)) + || !TEST(0, TEST_mem_ne("", 0, "", 0)) + || !TEST(0, TEST_mem_eq("xyz", 3, NULL, 0)) + || !TEST(0, TEST_mem_eq("xyz", 3, buf, sizeof(buf))) + || !TEST(1, TEST_mem_eq("xyz", 4, buf, sizeof(buf)))) goto err; return 1; @@ -315,61 +315,61 @@ static int test_bignum(void) int r = 0; if (!TEST(1, TEST_int_eq(BN_dec2bn(&a, "0"), 1)) - | !TEST(1, TEST_BN_eq_word(a, 0)) - | !TEST(0, TEST_BN_eq_word(a, 30)) - | !TEST(1, TEST_BN_abs_eq_word(a, 0)) - | !TEST(0, TEST_BN_eq_one(a)) - | !TEST(1, TEST_BN_eq_zero(a)) - | !TEST(0, TEST_BN_ne_zero(a)) - | !TEST(1, TEST_BN_le_zero(a)) - | !TEST(0, TEST_BN_lt_zero(a)) - | !TEST(1, TEST_BN_ge_zero(a)) - | !TEST(0, TEST_BN_gt_zero(a)) - | !TEST(1, TEST_BN_even(a)) - | !TEST(0, TEST_BN_odd(a)) - | !TEST(1, TEST_BN_eq(b, c)) - | !TEST(0, TEST_BN_eq(a, b)) - | !TEST(0, TEST_BN_ne(NULL, c)) - | !TEST(1, TEST_int_eq(BN_dec2bn(&b, "1"), 1)) - | !TEST(1, TEST_BN_eq_word(b, 1)) - | !TEST(1, TEST_BN_eq_one(b)) - | !TEST(0, TEST_BN_abs_eq_word(b, 0)) - | !TEST(1, TEST_BN_abs_eq_word(b, 1)) - | !TEST(0, TEST_BN_eq_zero(b)) - | !TEST(1, TEST_BN_ne_zero(b)) - | !TEST(0, TEST_BN_le_zero(b)) - | !TEST(0, TEST_BN_lt_zero(b)) - | !TEST(1, TEST_BN_ge_zero(b)) - | !TEST(1, TEST_BN_gt_zero(b)) - | !TEST(0, TEST_BN_even(b)) - | !TEST(1, TEST_BN_odd(b)) - | !TEST(1, TEST_int_eq(BN_dec2bn(&c, "-334739439"), 10)) - | !TEST(0, TEST_BN_eq_word(c, 334739439)) - | !TEST(1, TEST_BN_abs_eq_word(c, 334739439)) - | !TEST(0, TEST_BN_eq_zero(c)) - | !TEST(1, TEST_BN_ne_zero(c)) - | !TEST(1, TEST_BN_le_zero(c)) - | !TEST(1, TEST_BN_lt_zero(c)) - | !TEST(0, TEST_BN_ge_zero(c)) - | !TEST(0, TEST_BN_gt_zero(c)) - | !TEST(0, TEST_BN_even(c)) - | !TEST(1, TEST_BN_odd(c)) - | !TEST(1, TEST_BN_eq(a, a)) - | !TEST(0, TEST_BN_ne(a, a)) - | !TEST(0, TEST_BN_eq(a, b)) - | !TEST(1, TEST_BN_ne(a, b)) - | !TEST(0, TEST_BN_lt(a, c)) - | !TEST(1, TEST_BN_lt(c, b)) - | !TEST(0, TEST_BN_lt(b, c)) - | !TEST(0, TEST_BN_le(a, c)) - | !TEST(1, TEST_BN_le(c, b)) - | !TEST(0, TEST_BN_le(b, c)) - | !TEST(1, TEST_BN_gt(a, c)) - | !TEST(0, TEST_BN_gt(c, b)) - | !TEST(1, TEST_BN_gt(b, c)) - | !TEST(1, TEST_BN_ge(a, c)) - | !TEST(0, TEST_BN_ge(c, b)) - | !TEST(1, TEST_BN_ge(b, c))) + || !TEST(1, TEST_BN_eq_word(a, 0)) + || !TEST(0, TEST_BN_eq_word(a, 30)) + || !TEST(1, TEST_BN_abs_eq_word(a, 0)) + || !TEST(0, TEST_BN_eq_one(a)) + || !TEST(1, TEST_BN_eq_zero(a)) + || !TEST(0, TEST_BN_ne_zero(a)) + || !TEST(1, TEST_BN_le_zero(a)) + || !TEST(0, TEST_BN_lt_zero(a)) + || !TEST(1, TEST_BN_ge_zero(a)) + || !TEST(0, TEST_BN_gt_zero(a)) + || !TEST(1, TEST_BN_even(a)) + || !TEST(0, TEST_BN_odd(a)) + || !TEST(1, TEST_BN_eq(b, c)) + || !TEST(0, TEST_BN_eq(a, b)) + || !TEST(0, TEST_BN_ne(NULL, c)) + || !TEST(1, TEST_int_eq(BN_dec2bn(&b, "1"), 1)) + || !TEST(1, TEST_BN_eq_word(b, 1)) + || !TEST(1, TEST_BN_eq_one(b)) + || !TEST(0, TEST_BN_abs_eq_word(b, 0)) + || !TEST(1, TEST_BN_abs_eq_word(b, 1)) + || !TEST(0, TEST_BN_eq_zero(b)) + || !TEST(1, TEST_BN_ne_zero(b)) + || !TEST(0, TEST_BN_le_zero(b)) + || !TEST(0, TEST_BN_lt_zero(b)) + || !TEST(1, TEST_BN_ge_zero(b)) + || !TEST(1, TEST_BN_gt_zero(b)) + || !TEST(0, TEST_BN_even(b)) + || !TEST(1, TEST_BN_odd(b)) + || !TEST(1, TEST_int_eq(BN_dec2bn(&c, "-334739439"), 10)) + || !TEST(0, TEST_BN_eq_word(c, 334739439)) + || !TEST(1, TEST_BN_abs_eq_word(c, 334739439)) + || !TEST(0, TEST_BN_eq_zero(c)) + || !TEST(1, TEST_BN_ne_zero(c)) + || !TEST(1, TEST_BN_le_zero(c)) + || !TEST(1, TEST_BN_lt_zero(c)) + || !TEST(0, TEST_BN_ge_zero(c)) + || !TEST(0, TEST_BN_gt_zero(c)) + || !TEST(0, TEST_BN_even(c)) + || !TEST(1, TEST_BN_odd(c)) + || !TEST(1, TEST_BN_eq(a, a)) + || !TEST(0, TEST_BN_ne(a, a)) + || !TEST(0, TEST_BN_eq(a, b)) + || !TEST(1, TEST_BN_ne(a, b)) + || !TEST(0, TEST_BN_lt(a, c)) + || !TEST(1, TEST_BN_lt(c, b)) + || !TEST(0, TEST_BN_lt(b, c)) + || !TEST(0, TEST_BN_le(a, c)) + || !TEST(1, TEST_BN_le(c, b)) + || !TEST(0, TEST_BN_le(b, c)) + || !TEST(1, TEST_BN_gt(a, c)) + || !TEST(0, TEST_BN_gt(c, b)) + || !TEST(1, TEST_BN_gt(b, c)) + || !TEST(1, TEST_BN_ge(a, c)) + || !TEST(0, TEST_BN_ge(c, b)) + || !TEST(1, TEST_BN_ge(b, c))) goto err; r = 1; diff --git a/test/testec-p112r1.pem b/test/testec-p112r1.pem new file mode 100644 index 0000000000..c81398e7d7 --- /dev/null +++ b/test/testec-p112r1.pem @@ -0,0 +1,7 @@ +-----BEGIN EC PARAMETERS----- +BgUrgQQABg== +-----END EC PARAMETERS----- +-----BEGIN EC PRIVATE KEY----- +MD4CAQEEDqpz3/ZgfdnaauL3MgNsoAcGBSuBBAAGoSADHgAErmlghD+XSf6spLhs +7CqP1x1K6h2kfELB84SYKg== +-----END EC PRIVATE KEY----- diff --git a/test/testutil.h b/test/testutil.h index c28df702cc..d621204557 100644 --- a/test/testutil.h +++ b/test/testutil.h @@ -235,6 +235,40 @@ void add_all_tests(const char *test_case_name, int (*test_fn)(int idx), int num, int global_init(void); int setup_tests(void); void cleanup_tests(void); + +/* + * Helper functions to detect specific versions of the FIPS provider being in use. + * Because of FIPS rules, code changes after a module has been validated are + * difficult and because we provide a hard guarantee of ABI and behavioural + * stability going forwards, it is a requirement to have tests be conditional + * on specific FIPS provider versions. Without this, bug fixes cannot be tested + * in later releases. + * + * The reason for not including e.g. a less than test is to help avoid any + * temptation to use FIPS provider version numbers that don't exist. Until the + * `new' provider is validated, its version isn't set in stone. Thus a change + * in test behaviour must depend on already validated module versions only. + * + * In all cases, the function returns true if: + * 1. the FIPS provider version matches the criteria specified or + * 2. the FIPS provider isn't being used. + */ +int fips_provider_version_eq(OSSL_LIB_CTX *libctx, int major, int minor, int patch); +int fips_provider_version_ne(OSSL_LIB_CTX *libctx, int major, int minor, int patch); +int fips_provider_version_le(OSSL_LIB_CTX *libctx, int major, int minor, int patch); +int fips_provider_version_gt(OSSL_LIB_CTX *libctx, int major, int minor, int patch); + +/* + * This function matches fips provider version with (potentially multiple) + * maj.min.patch version strings in versions. + * The operator can be one of = ! <= or > comparison symbols. + * If the fips provider matches all the version comparisons (or if there is no + * fips provider available) the function returns 1. + * If the fips provider does not match the version comparisons, it returns 0. + * On error the function returns -1. + */ +int fips_provider_version_match(OSSL_LIB_CTX *libctx, const char *versions); + /* * Used to supply test specific command line options, * If non optional parameters are used, then the first entry in the OPTIONS[] @@ -251,7 +285,9 @@ const OPTIONS *test_get_options(void); */ # define PRINTF_FORMAT(a, b) -# if defined(__GNUC__) && defined(__STDC_VERSION__) +# if defined(__GNUC__) && defined(__STDC_VERSION__) \ + && !defined(__MINGW32__) && !defined(__MINGW64__) \ + && !defined(__APPLE__) /* * Because we support the 'z' modifier, which made its appearance in C99, * we can't use __attribute__ with pre C99 dialects. diff --git a/test/testutil/output.h b/test/testutil/output.h index 5e4f4c2390..0e4de09704 100644 --- a/test/testutil/output.h +++ b/test/testutil/output.h @@ -14,6 +14,7 @@ # define ossl_test__attr__(x) # if defined(__GNUC__) && defined(__STDC_VERSION__) \ + && !defined(__MINGW32__) && !defined(__MINGW64__) \ && !defined(__APPLE__) /* * Because we support the 'z' modifier, which made its appearance in C99, diff --git a/test/testutil/provider.c b/test/testutil/provider.c index d073d732da..c8b5dfc061 100644 --- a/test/testutil/provider.c +++ b/test/testutil/provider.c @@ -8,7 +8,9 @@ */ #include "../testutil.h" +#include #include +#include #include int test_get_libctx(OSSL_LIB_CTX **libctx, OSSL_PROVIDER **default_null_prov, @@ -62,3 +64,141 @@ int test_arg_libctx(OSSL_LIB_CTX **libctx, OSSL_PROVIDER **default_null_prov, return test_get_libctx(libctx, default_null_prov, test_get_argument(argn + 1), provider, module_name); } + +typedef struct { + int major, minor, patch; +} FIPS_VERSION; + +/* + * Query the FIPS provider to determine it's version number. + * Returns 1 if the version is retrieved correctly, 0 if the FIPS provider isn't + * loaded and -1 on error. + */ +static int fips_provider_version(OSSL_LIB_CTX *libctx, FIPS_VERSION *vers) +{ + OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END }; + OSSL_PROVIDER *fips_prov; + char *vs; + + if (!OSSL_PROVIDER_available(libctx, "fips")) + return 0; + *params = OSSL_PARAM_construct_utf8_ptr(OSSL_PROV_PARAM_VERSION, &vs, 0); + if ((fips_prov = OSSL_PROVIDER_load(libctx, "fips")) == NULL) + return -1; + if (!OSSL_PROVIDER_get_params(fips_prov, params) + || sscanf(vs, "%d.%d.%d", &vers->major, &vers->minor, &vers->patch) != 3) + goto err; + if (!OSSL_PROVIDER_unload(fips_prov)) + return -1; + return 1; + err: + OSSL_PROVIDER_unload(fips_prov); + return -1; +} + +int fips_provider_version_eq(OSSL_LIB_CTX *libctx, int major, int minor, int patch) +{ + FIPS_VERSION prov; + int res; + + if ((res = fips_provider_version(libctx, &prov)) <= 0) + return res == 0; + return major == prov.major && minor == prov.minor && patch == prov.patch; +} + +int fips_provider_version_ne(OSSL_LIB_CTX *libctx, int major, int minor, int patch) +{ + FIPS_VERSION prov; + int res; + + if ((res = fips_provider_version(libctx, &prov)) <= 0) + return res == 0; + return major != prov.major || minor != prov.minor || patch != prov.patch; +} + +int fips_provider_version_le(OSSL_LIB_CTX *libctx, int major, int minor, int patch) +{ + FIPS_VERSION prov; + int res; + + if ((res = fips_provider_version(libctx, &prov)) <= 0) + return res == 0; + return prov.major < major + || (prov.major == major + && (prov.minor < minor + || (prov.minor == minor && prov.patch <= patch))); +} + +int fips_provider_version_gt(OSSL_LIB_CTX *libctx, int major, int minor, int patch) +{ + FIPS_VERSION prov; + int res; + + if ((res = fips_provider_version(libctx, &prov)) <= 0) + return res == 0; + return prov.major > major + || (prov.major == major + && (prov.minor > minor + || (prov.minor == minor && prov.patch > patch))); +} + +int fips_provider_version_match(OSSL_LIB_CTX *libctx, const char *versions) +{ + const char *p; + int major, minor, patch, r; + enum { + MODE_EQ, MODE_NE, MODE_LE, MODE_GT + } mode; + + while (*versions != '\0') { + for (; isspace(*versions); versions++) + continue; + if (*versions == '\0') + break; + for (p = versions; *versions != '\0' && !isspace(*versions); versions++) + continue; + if (*p == '!') { + mode = MODE_NE; + p++; + } else if (*p == '=') { + mode = MODE_EQ; + p++; + } else if (*p == '<' && p[1] == '=') { + mode = MODE_LE; + p += 2; + } else if (*p == '>') { + mode = MODE_GT; + p++; + } else if (isdigit(*p)) { + mode = MODE_EQ; + } else { + TEST_info("Error matching FIPS version: mode %s\n", p); + return -1; + } + if (sscanf(p, "%d.%d.%d", &major, &minor, &patch) != 3) { + TEST_info("Error matching FIPS version: version %s\n", p); + return -1; + } + switch (mode) { + case MODE_EQ: + r = fips_provider_version_eq(libctx, major, minor, patch); + break; + case MODE_NE: + r = fips_provider_version_ne(libctx, major, minor, patch); + break; + case MODE_LE: + r = fips_provider_version_le(libctx, major, minor, patch); + break; + case MODE_GT: + r = fips_provider_version_gt(libctx, major, minor, patch); + break; + } + if (r < 0) { + TEST_info("Error matching FIPS version: internal error\n"); + return -1; + } + if (r == 0) + return 0; + } + return 1; +} diff --git a/util/missingcrypto.txt b/util/missingcrypto.txt index 9afa1b8c00..7851872b66 100644 --- a/util/missingcrypto.txt +++ b/util/missingcrypto.txt @@ -635,8 +635,6 @@ EVP_CIPHER_impl_ctx_size(3) EVP_CIPHER_set_asn1_iv(3) EVP_MD_do_all(3) EVP_MD_do_all_sorted(3) -EVP_PBE_alg_add(3) -EVP_PBE_alg_add_type(3) EVP_PBE_cleanup(3) EVP_PBE_get(3) EVP_PKEY_CTX_get0_peerkey(3) @@ -811,9 +809,6 @@ OPENSSL_LH_set_down_load(3) OPENSSL_LH_strhash(3) OPENSSL_asc2uni(3) OPENSSL_die(3) -OPENSSL_gmtime(3) -OPENSSL_gmtime_adj(3) -OPENSSL_gmtime_diff(3) OPENSSL_init(3) OPENSSL_isservice(3) OPENSSL_issetugid(3) @@ -1327,7 +1322,6 @@ X509_get_default_cert_file_env(3) X509_get_default_private_dir(3) X509_get_pubkey_parameters(3) X509_get_signature_type(3) -X509_gmtime_adj(3) X509_issuer_and_serial_hash(3) X509_issuer_name_hash(3) X509_issuer_name_hash_old(3) diff --git a/util/perl/OpenSSL/config.pm b/util/perl/OpenSSL/config.pm index 84485abae5..2f1edcafb6 100755 --- a/util/perl/OpenSSL/config.pm +++ b/util/perl/OpenSSL/config.pm @@ -15,8 +15,10 @@ use strict; use warnings; use Getopt::Std; use File::Basename; +use File::Spec; use IPC::Cmd; use POSIX; +use Config; use Carp; # These control our behavior. @@ -32,6 +34,7 @@ my $SYSTEM; my $VERSION; my $CCVENDOR; my $CCVER; +my $CL_ARCH; my $GCC_BITS; my $GCC_ARCH; @@ -49,12 +52,15 @@ my @c_compilers = qw(clang gcc cc); my @cc_version = ( clang => sub { + return undef unless IPC::Cmd::can_run("$CROSS_COMPILE$CC"); my $v = `$CROSS_COMPILE$CC -v 2>&1`; $v =~ m/(?:(?:clang|LLVM) version|.*based on LLVM)\s+([0-9]+\.[0-9]+)/; return $1; }, gnu => sub { - my $v = `$CROSS_COMPILE$CC -dumpversion 2>/dev/null`; + return undef unless IPC::Cmd::can_run("$CROSS_COMPILE$CC"); + my $nul = File::Spec->devnull(); + my $v = `$CROSS_COMPILE$CC -dumpversion 2> $nul`; # Strip off whatever prefix egcs prepends the number with. # Hopefully, this will work for any future prefixes as well. $v =~ s/^[a-zA-Z]*\-//; @@ -159,6 +165,12 @@ my $guess_patterns = [ [ 'CYGWIN.*', '${MACHINE}-pc-cygwin' ], [ 'vxworks.*', '${MACHINE}-whatever-vxworks' ], + # The MACHINE part of the array POSIX::uname() returns on VMS isn't + # worth the bits wasted on it. It's better, then, to rely on perl's + # %Config, which has a trustworthy item 'archname', especially since + # VMS installation aren't multiarch (yet) + [ 'OpenVMS:.*', "$Config{archname}-whatever-OpenVMS" ], + # Note: there's also NEO and NSR, but they are old and unsupported [ 'NONSTOP_KERNEL:.*:NSE-.*?', 'nse-tandem-nsk${RELEASE}' ], [ 'NONSTOP_KERNEL:.*:NSV-.*?', 'nsv-tandem-nsk${RELEASE}' ], @@ -378,6 +390,22 @@ sub determine_compiler_settings { $CCVER = $v; } } + + # 'Windows NT' is the system name according to POSIX::uname()! + if ( $SYSTEM eq "Windows NT" ) { + # favor vendor cl over gcc + if (IPC::Cmd::can_run('cl')) { + $CC = 'cl'; + $CCVENDOR = ''; # Determine later + $CCVER = 0; + + my $v = `cl 2>&1`; + if ( $v =~ /Microsoft .* Version ([0-9\.]+) for (x86|x64|ARM|ia64)/ ) { + $CCVER = $1; + $CL_ARCH = $2; + } + } + } } # If no C compiler has been determined at this point, we die. Hard. @@ -876,22 +904,43 @@ EOF } else { $config{disable} = [ 'asm' ]; } - return %config; + return { %config }; } ], # Windows values found by looking at Perl 5's win32/win32.c - [ 'amd64-.*?-Windows NT', { target => 'VC-WIN64A' } ], - [ 'ia64-.*?-Windows NT', { target => 'VC-WIN64I' } ], - [ 'x86-.*?-Windows NT', { target => 'VC-WIN32' } ], + [ '(amd64|ia64|x86|ARM)-.*?-Windows NT', + sub { + # If we determined the arch by asking cl, take that value, + # otherwise the SYSTEM we got from from POSIX::uname(). + my $arch = $CL_ARCH // $1; + my $config; + + if ($arch) { + $config = { 'amd64' => { target => 'VC-WIN64A' }, + 'ia64' => { target => 'VC-WIN64I' }, + 'x86' => { target => 'VC-WIN32' }, + 'x64' => { target => 'VC-WIN64A' }, + 'ARM' => { target => 'VC-WIN64-ARM' }, + } -> {$arch}; + die <<_____ unless defined $config; +ERROR +I do not know how to handle ${arch}. +_____ + } + die <<_____ unless defined $config; +ERROR +Could not figure out the architecture. +_____ + + return $config; + } + ], # VMS values found by observation on existing machinery. - # Unfortunately, the machine part is a bit... overdone. It seems, - # though, that 'Alpha' exists in that part for Alphas, making it - # distinguishable from Itanium. It will be interesting to see what - # we'll get in the upcoming x86_64 port... - [ '.*Alpha.*?-.*?-OpenVMS', { target => 'vms-alpha' } ], - [ '.*?-.*?-OpenVMS', { target => 'vms-ia64' } ], + [ 'VMS_AXP-.*?-OpenVMS', { target => 'vms-alpha' } ], + [ 'VMS_IA64-.*?-OpenVMS', { target => 'vms-ia64' } ], + [ 'VMS_x86_64-.*?-OpenVMS', { target => 'vms-x86_64' } ], # TODO: There are a few more choices among OpenSSL config targets, but # reaching them involves a bit more than just a host tripet. Select diff --git a/util/wrap.pl.in b/util/wrap.pl.in index b13c34d851..5126513d4c 100644 --- a/util/wrap.pl.in +++ b/util/wrap.pl.in @@ -68,7 +68,10 @@ my $waitcode = system @cmd; die "wrap.pl: Failed to execute '", join(' ', @cmd), "': $!\n" if $waitcode == -1; -# When the subprocess aborted on a signal, mimic what Unix shells do, by +# When the subprocess aborted on a signal, we simply raise the same signal. +kill(($? & 255) => $$) if ($? & 255) != 0; + +# If that didn't stop this script, mimic what Unix shells do, by # converting the signal code to an exit code by setting the high bit. # This only happens on Unix flavored operating systems, the others don't # have this sort of signaling to date, and simply leave the low byte zero.