diff --git a/.github/ci-deps/packages-ubuntu-24.04-full.txt b/.github/ci-deps/packages-ubuntu-24.04-full.txt index a0e73e0f3d4..e9d09dde43e 100644 --- a/.github/ci-deps/packages-ubuntu-24.04-full.txt +++ b/.github/ci-deps/packages-ubuntu-24.04-full.txt @@ -58,6 +58,7 @@ libjansson-dev libkrb5-dev libldb-dev libldb2 +libltdl-dev liblz4-dev liblzma-dev liblzo2-dev @@ -82,6 +83,8 @@ libssl-dev libtool liburcu-dev libuv1-dev +libxml2-dev +libxslt1-dev linux-libc-dev make man2html diff --git a/.github/workflows/xmlsec.yml b/.github/workflows/xmlsec.yml new file mode 100644 index 00000000000..b9901784bec --- /dev/null +++ b/.github/workflows/xmlsec.yml @@ -0,0 +1,175 @@ +name: xmlsec Tests + +# START OF COMMON SECTION +on: + push: + branches: [ 'release/**' ] + pull_request: + types: [opened, synchronize, reopened, ready_for_review] + branches: [ '*' ] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +permissions: + contents: read +# END OF COMMON SECTION + +jobs: + build_wolfssl: + name: Build wolfSSL + if: ${{ (github.repository_owner == 'wolfssl') && (github.event_name != 'pull_request' || github.event.pull_request.draft == false) }} + # Just to keep it the same as the testing target + runs-on: ubuntu-24.04 + # This should be a safe limit for the tests to run. + timeout-minutes: 4 + steps: + - name: Build wolfSSL + uses: wolfSSL/actions-build-autotools-project@v1 + with: + path: wolfssl + # The CFLAGS only relax limits for the xmlsec test data: a 512-bit + # RSA CA, rsa-1024 key generation, serial-0 certs and MD5-signed + # certs. + configure: >- + --enable-all + 'CFLAGS=-DWOLFSSL_MIN_RSA_BITS=512 -DRSA_MIN_SIZE=1024 -DWOLFSSL_ASN_ALLOW_0_SERIAL -DWOLFSSL_ALLOW_MD5_CERT_SIGS' + install: true + check: false + + - name: tar build-dir + run: tar -zcf build-dir.tgz build-dir + + - name: Upload built lib + uses: actions/upload-artifact@v6 + with: + name: wolf-install-xmlsec + path: build-dir.tgz + retention-days: 5 + + xmlsec_check: + strategy: + fail-fast: false + matrix: + include: + - ref: 1.2.42 + tag: xmlsec-1_2_42 + sha256: 5359e3c19016ab164b505c1222ef5a2d87b34f50f85ff91d765f4aaa0df42db2 + # wolfSSL PKCS12_parse() does not load DSA keys, and a DSA CA's + # key is not kept for chain verification. + expect_fail: >- + aleksey-xmldsig-01/enveloping-dsa-x509chain + aleksey-xmldsig-01/enveloping-sha256-dsa2048-sha256 + aleksey-xmldsig-01/enveloping-sha256-dsa3072-sha256 + merlin-exc-c14n-one/exc-signature + merlin-xmldsig-twenty-three/signature + merlin-xmldsig-twenty-three/signature-enveloped-dsa + merlin-xmldsig-twenty-three/signature-enveloping-b64-dsa + merlin-xmldsig-twenty-three/signature-enveloping-dsa + merlin-xmldsig-twenty-three/signature-external-b64-dsa + merlin-xmldsig-twenty-three/signature-external-dsa + merlin-xmldsig-twenty-three/signature-keyname + merlin-xmldsig-twenty-three/signature-retrievalmethod-rawx509crt + merlin-xmldsig-twenty-three/signature-x509-crt + merlin-xmldsig-twenty-three/signature-x509-is + merlin-xmldsig-twenty-three/signature-x509-ski + merlin-xmldsig-twenty-three/signature-x509-sn + phaos-xmldsig-three/signature-dsa-detached + phaos-xmldsig-three/signature-dsa-enveloped + phaos-xmldsig-three/signature-dsa-enveloping + name: ${{ matrix.ref }} + if: ${{ (github.repository_owner == 'wolfssl') && (github.event_name != 'pull_request' || github.event.pull_request.draft == false) }} + runs-on: ubuntu-24.04 + # This should be a safe limit for the tests to run. + timeout-minutes: 10 + needs: build_wolfssl + steps: + - name: Checkout wolfSSL CI actions + uses: actions/checkout@v5 + with: + sparse-checkout: .github/actions + fetch-depth: 1 + + - name: Install dependencies + uses: ./.github/actions/install-apt-deps + with: + # Fit the loop inside this job's timeout-minutes. + budget-seconds: '120' + pull-timeout: '60' + packages: libltdl-dev libxml2-dev libxslt1-dev + ghcr-debs-tag: ubuntu-24.04-full + + - name: Download lib + uses: actions/download-artifact@v7 + with: + name: wolf-install-xmlsec + + - name: untar build-dir + run: tar -xf build-dir.tgz + + - name: Checkout OSP + uses: actions/checkout@v5 + with: + repository: wolfssl/osp + path: osp + fetch-depth: 1 + + - name: Download xmlsec + run: | + curl -fLO https://github.com/lsh123/xmlsec/releases/download/${{ matrix.tag }}/xmlsec1-${{ matrix.ref }}.tar.gz + echo "${{ matrix.sha256 }} xmlsec1-${{ matrix.ref }}.tar.gz" | sha256sum -c - + tar xf xmlsec1-${{ matrix.ref }}.tar.gz + + - name: Build xmlsec + working-directory: xmlsec1-${{ matrix.ref }} + run: | + patch -p1 < "$GITHUB_WORKSPACE/osp/xmlsec/${{ matrix.ref }}/xmlsec1-${{ matrix.ref }}.patch" + # --disable-ripemd160: wolfSSL EVP_ripemd160() is a stub + OPENSSL_CFLAGS="-I$GITHUB_WORKSPACE/build-dir/include -I$GITHUB_WORKSPACE/build-dir/include/wolfssl -DWOLFSSL_USE_OPTIONS_H" \ + OPENSSL_LIBS="-L$GITHUB_WORKSPACE/build-dir/lib -Wl,-rpath,$GITHUB_WORKSPACE/build-dir/lib -lwolfssl" \ + ./configure --with-default-crypto=openssl --without-nss --without-gnutls \ + --without-gcrypt --disable-ripemd160 --disable-docs --disable-mans + make -j + ldd src/openssl/.libs/libxmlsec1-openssl.so | grep wolfssl + if ldd src/openssl/.libs/libxmlsec1-openssl.so | grep -E 'libssl|libcrypto'; then + echo "::error::libxmlsec1-openssl is linked against OpenSSL" + exit 1 + fi + + - name: Run xmlsec tests + working-directory: xmlsec1-${{ matrix.ref }} + env: + EXPECT_FAIL: ${{ matrix.expect_fail }} + run: | + export TMPFOLDER="$GITHUB_WORKSPACE/xmlsec-logs" + mkdir -p "$TMPFOLDER" + # make check stops at the first failing script, so run each one + for t in keys dsig enc; do + make "check-$t" > "$TMPFOLDER/check-$t.log" 2>&1 || true + if ! grep -- '--- TOTAL' "$TMPFOLDER/check-$t.log"; then + tail -n 50 "$TMPFOLDER/check-$t.log" + echo "::error::check-$t did not finish" + exit 1 + fi + done + # A test name is an unindented line. Its steps are indented and end + # in OK, Fail or Skip. + for t in keys dsig enc; do + awk '/^--- TOTAL/ {exit} /^[^ \t]/ {name = $0} /[ \t]Fail$/ {print name}' "$TMPFOLDER/check-$t.log" + done | sort -u > "$TMPFOLDER/failed.txt" + # Tests are matched by name: a listed test that fails for another + # reason is not caught. + echo "$EXPECT_FAIL" | tr ' ' '\n' | sed '/^$/d' | sort -u > "$TMPFOLDER/expected.txt" + if ! diff -u "$TMPFOLDER/expected.txt" "$TMPFOLDER/failed.txt"; then + echo "::error::Failed tests differ from expect_fail (- passes now, + new failure)" + exit 1 + fi + + - name: Upload test logs + if: ${{ failure() }} + uses: actions/upload-artifact@v6 + with: + name: xmlsec-${{ matrix.ref }}-logs + path: xmlsec-logs + retention-days: 5 diff --git a/.wolfssl_known_macro_extras b/.wolfssl_known_macro_extras index 36f3f3f5ede..74fc92526ef 100644 --- a/.wolfssl_known_macro_extras +++ b/.wolfssl_known_macro_extras @@ -1020,7 +1020,6 @@ WOLFSSL_HARDEN_TLS_NO_PKEY_CHECK WOLFSSL_HARDEN_TLS_NO_SCR_CHECK WOLFSSL_HAVE_KYBER WOLFSSL_HOSTNAME_VERIFY_ALT_NAME_ONLY -WOLFSSL_I2D_ECDSA_SIG_ALLOC WOLFSSL_IAR_ARM_TIME WOLFSSL_IGNORE_BAD_CERT_PATH WOLFSSL_IMX6 diff --git a/CMakeLists.txt b/CMakeLists.txt index 534714847a1..e41e25e44de 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -474,7 +474,7 @@ if(WOLFSSL_OPENVPN) foreach(_o WOLFSSL_AES WOLFSSL_CRL WOLFSSL_DES3 WOLFSSL_DSA WOLFSSL_MD5 WOLFSSL_OCSP) force_option(${_o} "yes") endforeach() - list(APPEND WOLFSSL_DEFINITIONS "-DHAVE_COMP_KEY" "-DHAVE_CRL" "-DHAVE_EX_DATA" "-DHAVE_KEYING_MATERIAL" "-DHAVE_OPENSSL_CMD" "-DOPENSSL_ALL" "-DOPENSSL_EXTRA" "-DSESSION_CERTS" "-DWC_RSA_NO_PADDING" "-DWOLFSSL_AES_COUNTER" "-DWOLFSSL_AES_DIRECT" "-DWOLFSSL_CERT_EXT" "-DWOLFSSL_CERT_GEN" "-DWOLFSSL_CERT_NAME_ALL" "-DWOLFSSL_DES_ECB" "-DWOLFSSL_EITHER_SIDE" "-DWOLFSSL_ERROR_CODE_OPENSSL" "-DWOLFSSL_KEY_GEN" "-DWOLFSSL_OPENVPN" "-DWOLFSSL_TICKET_HAVE_ID") + list(APPEND WOLFSSL_DEFINITIONS "-DHAVE_COMP_KEY" "-DHAVE_CRL" "-DHAVE_EX_DATA" "-DHAVE_KEYING_MATERIAL" "-DHAVE_OPENSSL_CMD" "-DOPENSSL_ALL" "-DOPENSSL_EXTRA" "-DSESSION_CERTS" "-DWC_RSA_NO_PADDING" "-DWOLFSSL_AES_COUNTER" "-DWOLFSSL_AES_DIRECT" "-DWOLFSSL_CERT_EXT" "-DWOLFSSL_CERT_GEN" "-DWOLFSSL_CERT_NAME_ALL" "-DWOLFSSL_DES_ECB" "-DWOLFSSL_EITHER_SIDE" "-DWOLFSSL_ERROR_CODE_OPENSSL" "-DWOLFSSL_I2D_ECDSA_SIG_ALLOC" "-DWOLFSSL_KEY_GEN" "-DWOLFSSL_OPENVPN" "-DWOLFSSL_TICKET_HAVE_ID") endif() add_option("WOLFSSL_NGINX" "Enable nginx support (default: disabled)" "no" "yes;no") @@ -482,7 +482,7 @@ if(WOLFSSL_NGINX) foreach(_o WOLFSSL_CRL WOLFSSL_DSA WOLFSSL_MD5 WOLFSSL_OCSP WOLFSSL_OCSPSTAPLING WOLFSSL_OCSPSTAPLING_V2) force_option(${_o} "yes") endforeach() - list(APPEND WOLFSSL_DEFINITIONS "-DHAVE_ALPN" "-DHAVE_ANON" "-DHAVE_COMP_KEY" "-DHAVE_CRL" "-DHAVE_EXT_CACHE" "-DHAVE_EX_DATA" "-DHAVE_MAX_FRAGMENT" "-DHAVE_OPENSSL_CMD" "-DHAVE_SESSION_TICKET" "-DHAVE_TRUNCATED_HMAC" "-DHAVE_TRUSTED_CA" "-DKEEP_OUR_CERT" "-DKEEP_PEER_CERT" "-DNO_SESSION_CACHE_REF" "-DOPENSSL_ALL" "-DOPENSSL_COMPATIBLE_DEFAULTS" "-DOPENSSL_EXTRA" "-DSESSION_CERTS" "-DWC_RSA_NO_PADDING" "-DWOLFSSL_ALT_CERT_CHAINS" "-DWOLFSSL_ALWAYS_KEEP_SNI" "-DWOLFSSL_ALWAYS_VERIFY_CB" "-DWOLFSSL_CERT_GEN" "-DWOLFSSL_CERT_NAME_ALL" "-DWOLFSSL_CHECK_ALERT_ON_ERR" "-DWOLFSSL_EITHER_SIDE" "-DWOLFSSL_ERROR_CODE_OPENSSL" "-DWOLFSSL_KEY_GEN" "-DWOLFSSL_NGINX" "-DWOLFSSL_PRIORITIZE_PSK" "-DWOLFSSL_SIGNER_DER_CERT" "-DWOLFSSL_TICKET_HAVE_ID" "-DWOLFSSL_TLS13_NO_PEEK_HANDSHAKE_DONE" "-DWOLFSSL_TRUST_PEER_CERT") + list(APPEND WOLFSSL_DEFINITIONS "-DHAVE_ALPN" "-DHAVE_ANON" "-DHAVE_COMP_KEY" "-DHAVE_CRL" "-DHAVE_EXT_CACHE" "-DHAVE_EX_DATA" "-DHAVE_MAX_FRAGMENT" "-DHAVE_OPENSSL_CMD" "-DHAVE_SESSION_TICKET" "-DHAVE_TRUNCATED_HMAC" "-DHAVE_TRUSTED_CA" "-DKEEP_OUR_CERT" "-DKEEP_PEER_CERT" "-DNO_SESSION_CACHE_REF" "-DOPENSSL_ALL" "-DOPENSSL_COMPATIBLE_DEFAULTS" "-DOPENSSL_EXTRA" "-DSESSION_CERTS" "-DWC_RSA_NO_PADDING" "-DWOLFSSL_ALT_CERT_CHAINS" "-DWOLFSSL_ALWAYS_KEEP_SNI" "-DWOLFSSL_ALWAYS_VERIFY_CB" "-DWOLFSSL_CERT_GEN" "-DWOLFSSL_CERT_NAME_ALL" "-DWOLFSSL_CHECK_ALERT_ON_ERR" "-DWOLFSSL_EITHER_SIDE" "-DWOLFSSL_ERROR_CODE_OPENSSL" "-DWOLFSSL_I2D_ECDSA_SIG_ALLOC" "-DWOLFSSL_KEY_GEN" "-DWOLFSSL_NGINX" "-DWOLFSSL_PRIORITIZE_PSK" "-DWOLFSSL_SIGNER_DER_CERT" "-DWOLFSSL_TICKET_HAVE_ID" "-DWOLFSSL_TLS13_NO_PEEK_HANDSHAKE_DONE" "-DWOLFSSL_TRUST_PEER_CERT") endif() add_option("WOLFSSL_HAPROXY" "Enable HAProxy support (default: disabled)" "no" "yes;no") @@ -490,7 +490,7 @@ if(WOLFSSL_HAPROXY) foreach(_o WOLFSSL_CRL WOLFSSL_MD5 WOLFSSL_OCSP WOLFSSL_OCSPSTAPLING WOLFSSL_OCSPSTAPLING_V2 WOLFSSL_OLD_TLS) force_option(${_o} "yes") endforeach() - list(APPEND WOLFSSL_DEFINITIONS "-DFP_MAX_BITS=16384" "-DHAVE_ALPN" "-DHAVE_ANON" "-DHAVE_COMP_KEY" "-DHAVE_CRL" "-DHAVE_EXT_CACHE" "-DHAVE_EX_DATA" "-DHAVE_MAX_FRAGMENT" "-DHAVE_OPENSSL_CMD" "-DHAVE_SECURE_RENEGOTIATION" "-DHAVE_SESSION_TICKET" "-DHAVE_TRUNCATED_HMAC" "-DHAVE_TRUSTED_CA" "-DKEEP_OUR_CERT" "-DKEEP_PEER_CERT" "-DNO_SESSION_CACHE_REF" "-DOPENSSL_ALL" "-DOPENSSL_COMPATIBLE_DEFAULTS" "-DOPENSSL_EXTRA" "-DRSA_MAX_SIZE=8192" "-DSESSION_CERTS" "-DSP_INT_BITS=8192" "-DWC_RSA_NO_PADDING" "-DWOLFSSL_ALLOW_SSLV3" "-DWOLFSSL_ALT_CERT_CHAINS" "-DWOLFSSL_ALWAYS_KEEP_SNI" "-DWOLFSSL_ALWAYS_VERIFY_CB" "-DWOLFSSL_CERT_GEN" "-DWOLFSSL_CERT_NAME_ALL" "-DWOLFSSL_CERT_REQ" "-DWOLFSSL_CHECK_ALERT_ON_ERR" "-DWOLFSSL_EITHER_SIDE" "-DWOLFSSL_ERROR_CODE_OPENSSL" "-DWOLFSSL_HAPROXY" "-DWOLFSSL_KEEP_RNG_SEED_FD_OPEN" "-DWOLFSSL_KEY_GEN" "-DWOLFSSL_PRIORITIZE_PSK" "-DWOLFSSL_SIGNER_DER_CERT" "-DWOLFSSL_TICKET_HAVE_ID" "-DWOLFSSL_TLS13_NO_PEEK_HANDSHAKE_DONE" "-DWOLFSSL_TRUST_PEER_CERT") + list(APPEND WOLFSSL_DEFINITIONS "-DFP_MAX_BITS=16384" "-DHAVE_ALPN" "-DHAVE_ANON" "-DHAVE_COMP_KEY" "-DHAVE_CRL" "-DHAVE_EXT_CACHE" "-DHAVE_EX_DATA" "-DHAVE_MAX_FRAGMENT" "-DHAVE_OPENSSL_CMD" "-DHAVE_SECURE_RENEGOTIATION" "-DHAVE_SESSION_TICKET" "-DHAVE_TRUNCATED_HMAC" "-DHAVE_TRUSTED_CA" "-DKEEP_OUR_CERT" "-DKEEP_PEER_CERT" "-DNO_SESSION_CACHE_REF" "-DOPENSSL_ALL" "-DOPENSSL_COMPATIBLE_DEFAULTS" "-DOPENSSL_EXTRA" "-DRSA_MAX_SIZE=8192" "-DSESSION_CERTS" "-DSP_INT_BITS=8192" "-DWC_RSA_NO_PADDING" "-DWOLFSSL_ALLOW_SSLV3" "-DWOLFSSL_ALT_CERT_CHAINS" "-DWOLFSSL_ALWAYS_KEEP_SNI" "-DWOLFSSL_ALWAYS_VERIFY_CB" "-DWOLFSSL_CERT_GEN" "-DWOLFSSL_CERT_NAME_ALL" "-DWOLFSSL_CERT_REQ" "-DWOLFSSL_CHECK_ALERT_ON_ERR" "-DWOLFSSL_EITHER_SIDE" "-DWOLFSSL_ERROR_CODE_OPENSSL" "-DWOLFSSL_HAPROXY" "-DWOLFSSL_I2D_ECDSA_SIG_ALLOC" "-DWOLFSSL_KEEP_RNG_SEED_FD_OPEN" "-DWOLFSSL_KEY_GEN" "-DWOLFSSL_PRIORITIZE_PSK" "-DWOLFSSL_SIGNER_DER_CERT" "-DWOLFSSL_TICKET_HAVE_ID" "-DWOLFSSL_TLS13_NO_PEEK_HANDSHAKE_DONE" "-DWOLFSSL_TRUST_PEER_CERT") endif() # Note: no -DSINGLE_THREADED here. configure.ac's --enable-lighty does not @@ -518,7 +518,7 @@ if(WOLFSSL_OPENLDAP) foreach(_o WOLFSSL_MD5 WOLFSSL_OCSP) force_option(${_o} "yes") endforeach() - list(APPEND WOLFSSL_DEFINITIONS "-DHAVE_COMP_KEY" "-DHAVE_OPENSSL_CMD" "-DOPENSSL_ALL" "-DOPENSSL_EXTRA" "-DWC_RSA_NO_PADDING" "-DWOLFSSL_CERT_GEN" "-DWOLFSSL_CERT_NAME_ALL" "-DWOLFSSL_EITHER_SIDE" "-DWOLFSSL_ERROR_CODE_OPENSSL" "-DWOLFSSL_SIGNER_DER_CERT" "-DWOLFSSL_TICKET_HAVE_ID") + list(APPEND WOLFSSL_DEFINITIONS "-DHAVE_COMP_KEY" "-DHAVE_OPENSSL_CMD" "-DOPENSSL_ALL" "-DOPENSSL_EXTRA" "-DWC_RSA_NO_PADDING" "-DWOLFSSL_CERT_GEN" "-DWOLFSSL_CERT_NAME_ALL" "-DWOLFSSL_EITHER_SIDE" "-DWOLFSSL_ERROR_CODE_OPENSSL" "-DWOLFSSL_I2D_ECDSA_SIG_ALLOC" "-DWOLFSSL_SIGNER_DER_CERT" "-DWOLFSSL_TICKET_HAVE_ID") endif() add_option("WOLFSSL_NETSNMP" "Enable net-snmp support (default: disabled)" "no" "yes;no") @@ -526,7 +526,7 @@ if(WOLFSSL_NETSNMP) foreach(_o WOLFSSL_CRL WOLFSSL_DES3 WOLFSSL_DTLS WOLFSSL_MD5 WOLFSSL_OCSP) force_option(${_o} "yes") endforeach() - list(APPEND WOLFSSL_DEFINITIONS "-DHAVE_COMP_KEY" "-DHAVE_CRL" "-DHAVE_EX_DATA" "-DHAVE_OPENSSL_CMD" "-DOPENSSL_ALL" "-DOPENSSL_EXTRA" "-DSESSION_CERTS" "-DWC_RSA_NO_PADDING" "-DWOLFSSL_AES_CFB" "-DWOLFSSL_CERT_NAME_ALL" "-DWOLFSSL_EITHER_SIDE" "-DWOLFSSL_ERROR_CODE_OPENSSL" "-DWOLFSSL_TICKET_HAVE_ID") + list(APPEND WOLFSSL_DEFINITIONS "-DHAVE_COMP_KEY" "-DHAVE_CRL" "-DHAVE_EX_DATA" "-DHAVE_OPENSSL_CMD" "-DOPENSSL_ALL" "-DOPENSSL_EXTRA" "-DSESSION_CERTS" "-DWC_RSA_NO_PADDING" "-DWOLFSSL_AES_CFB" "-DWOLFSSL_CERT_NAME_ALL" "-DWOLFSSL_EITHER_SIDE" "-DWOLFSSL_ERROR_CODE_OPENSSL" "-DWOLFSSL_I2D_ECDSA_SIG_ALLOC" "-DWOLFSSL_TICKET_HAVE_ID") endif() add_option("WOLFSSL_HITCH" "Enable Hitch support (default: disabled)" "no" "yes;no") @@ -534,7 +534,7 @@ if(WOLFSSL_HITCH) foreach(_o WOLFSSL_MD5 WOLFSSL_OCSP) force_option(${_o} "yes") endforeach() - list(APPEND WOLFSSL_DEFINITIONS "-DHAVE_ALPN" "-DHAVE_COMP_KEY" "-DHAVE_EX_DATA" "-DHAVE_OPENSSL_CMD" "-DNO_SESSION_CACHE_REF" "-DOPENSSL_ALL" "-DOPENSSL_COMPATIBLE_DEFAULTS" "-DOPENSSL_EXTRA" "-DSESSION_CERTS" "-DWC_RSA_NO_PADDING" "-DWOLFSSL_ALT_CERT_CHAINS" "-DWOLFSSL_CERT_GEN" "-DWOLFSSL_CERT_NAME_ALL" "-DWOLFSSL_CHECK_ALERT_ON_ERR" "-DWOLFSSL_CIPHER_INTERNALNAME" "-DWOLFSSL_EITHER_SIDE" "-DWOLFSSL_ENCRYPTED_KEYS" "-DWOLFSSL_ERROR_CODE_OPENSSL" "-DWOLFSSL_HITCH" "-DWOLFSSL_KEY_GEN" "-DWOLFSSL_PRIORITIZE_PSK" "-DWOLFSSL_SIGNER_DER_CERT" "-DWOLFSSL_TICKET_HAVE_ID" "-DWOLFSSL_TLS13_NO_PEEK_HANDSHAKE_DONE" "-DWOLFSSL_TRUST_PEER_CERT") + list(APPEND WOLFSSL_DEFINITIONS "-DHAVE_ALPN" "-DHAVE_COMP_KEY" "-DHAVE_EX_DATA" "-DHAVE_OPENSSL_CMD" "-DNO_SESSION_CACHE_REF" "-DOPENSSL_ALL" "-DOPENSSL_COMPATIBLE_DEFAULTS" "-DOPENSSL_EXTRA" "-DSESSION_CERTS" "-DWC_RSA_NO_PADDING" "-DWOLFSSL_ALT_CERT_CHAINS" "-DWOLFSSL_CERT_GEN" "-DWOLFSSL_CERT_NAME_ALL" "-DWOLFSSL_CHECK_ALERT_ON_ERR" "-DWOLFSSL_CIPHER_INTERNALNAME" "-DWOLFSSL_EITHER_SIDE" "-DWOLFSSL_ENCRYPTED_KEYS" "-DWOLFSSL_ERROR_CODE_OPENSSL" "-DWOLFSSL_HITCH" "-DWOLFSSL_I2D_ECDSA_SIG_ALLOC" "-DWOLFSSL_KEY_GEN" "-DWOLFSSL_PRIORITIZE_PSK" "-DWOLFSSL_SIGNER_DER_CERT" "-DWOLFSSL_TICKET_HAVE_ID" "-DWOLFSSL_TLS13_NO_PEEK_HANDSHAKE_DONE" "-DWOLFSSL_TRUST_PEER_CERT") endif() add_option("WOLFSSL_MEMCACHED" "Enable Memcached support (default: disabled)" "no" "yes;no") @@ -547,7 +547,7 @@ if(WOLFSSL_RSYSLOG) foreach(_o WOLFSSL_MD5 WOLFSSL_OCSP) force_option(${_o} "yes") endforeach() - list(APPEND WOLFSSL_DEFINITIONS "-DHAVE_ANON" "-DHAVE_COMP_KEY" "-DHAVE_EX_DATA" "-DHAVE_OPENSSL_CMD" "-DNO_SESSION_CACHE_REF" "-DOPENSSL_ALL" "-DOPENSSL_COMPATIBLE_DEFAULTS" "-DOPENSSL_EXTRA" "-DWC_RSA_NO_PADDING" "-DWOLFSSL_ALT_CERT_CHAINS" "-DWOLFSSL_CERT_NAME_ALL" "-DWOLFSSL_CHECK_ALERT_ON_ERR" "-DWOLFSSL_EITHER_SIDE" "-DWOLFSSL_ERROR_CODE_OPENSSL" "-DWOLFSSL_PRIORITIZE_PSK" "-DWOLFSSL_RSYSLOG" "-DWOLFSSL_TICKET_HAVE_ID" "-DWOLFSSL_TLS13_NO_PEEK_HANDSHAKE_DONE" "-DWOLFSSL_TRUST_PEER_CERT") + list(APPEND WOLFSSL_DEFINITIONS "-DHAVE_ANON" "-DHAVE_COMP_KEY" "-DHAVE_EX_DATA" "-DHAVE_OPENSSL_CMD" "-DNO_SESSION_CACHE_REF" "-DOPENSSL_ALL" "-DOPENSSL_COMPATIBLE_DEFAULTS" "-DOPENSSL_EXTRA" "-DWC_RSA_NO_PADDING" "-DWOLFSSL_ALT_CERT_CHAINS" "-DWOLFSSL_CERT_NAME_ALL" "-DWOLFSSL_CHECK_ALERT_ON_ERR" "-DWOLFSSL_EITHER_SIDE" "-DWOLFSSL_ERROR_CODE_OPENSSL" "-DWOLFSSL_I2D_ECDSA_SIG_ALLOC" "-DWOLFSSL_PRIORITIZE_PSK" "-DWOLFSSL_RSYSLOG" "-DWOLFSSL_TICKET_HAVE_ID" "-DWOLFSSL_TLS13_NO_PEEK_HANDSHAKE_DONE" "-DWOLFSSL_TRUST_PEER_CERT") endif() add_option("WOLFSSL_BIND" "Enable BIND DNS support (default: disabled)" "no" "yes;no") @@ -555,7 +555,7 @@ if(WOLFSSL_BIND) foreach(_o WOLFSSL_AES WOLFSSL_DSA WOLFSSL_MD5 WOLFSSL_OCSP) force_option(${_o} "yes") endforeach() - list(APPEND WOLFSSL_DEFINITIONS "-DHAVE_AES_ECB" "-DHAVE_ALPN" "-DHAVE_COMP_KEY" "-DHAVE_OPENSSL_CMD" "-DNO_SESSION_CACHE_REF" "-DOPENSSL_ALL" "-DOPENSSL_COMPATIBLE_DEFAULTS" "-DOPENSSL_EXTRA" "-DWC_RSA_NO_PADDING" "-DWOLFSSL_AES_DIRECT" "-DWOLFSSL_ALT_CERT_CHAINS" "-DWOLFSSL_BIND" "-DWOLFSSL_CERT_GEN" "-DWOLFSSL_CERT_NAME_ALL" "-DWOLFSSL_CHECK_ALERT_ON_ERR" "-DWOLFSSL_DES_ECB" "-DWOLFSSL_DSA_768_MODULUS" "-DWOLFSSL_EITHER_SIDE" "-DWOLFSSL_ERROR_CODE_OPENSSL" "-DWOLFSSL_KEY_GEN" "-DWOLFSSL_PRIORITIZE_PSK" "-DWOLFSSL_TICKET_HAVE_ID" "-DWOLFSSL_TLS13_NO_PEEK_HANDSHAKE_DONE" "-DWOLFSSL_TRUST_PEER_CERT") + list(APPEND WOLFSSL_DEFINITIONS "-DHAVE_AES_ECB" "-DHAVE_ALPN" "-DHAVE_COMP_KEY" "-DHAVE_OPENSSL_CMD" "-DNO_SESSION_CACHE_REF" "-DOPENSSL_ALL" "-DOPENSSL_COMPATIBLE_DEFAULTS" "-DOPENSSL_EXTRA" "-DWC_RSA_NO_PADDING" "-DWOLFSSL_AES_DIRECT" "-DWOLFSSL_ALT_CERT_CHAINS" "-DWOLFSSL_BIND" "-DWOLFSSL_CERT_GEN" "-DWOLFSSL_CERT_NAME_ALL" "-DWOLFSSL_CHECK_ALERT_ON_ERR" "-DWOLFSSL_DES_ECB" "-DWOLFSSL_DSA_768_MODULUS" "-DWOLFSSL_EITHER_SIDE" "-DWOLFSSL_ERROR_CODE_OPENSSL" "-DWOLFSSL_I2D_ECDSA_SIG_ALLOC" "-DWOLFSSL_KEY_GEN" "-DWOLFSSL_PRIORITIZE_PSK" "-DWOLFSSL_TICKET_HAVE_ID" "-DWOLFSSL_TLS13_NO_PEEK_HANDSHAKE_DONE" "-DWOLFSSL_TRUST_PEER_CERT") endif() add_option("WOLFSSL_NTP" "Enable ntp support (default: disabled)" "no" "yes;no") @@ -563,7 +563,7 @@ if(WOLFSSL_NTP) foreach(_o WOLFSSL_AES WOLFSSL_DSA WOLFSSL_MD5 WOLFSSL_OCSP) force_option(${_o} "yes") endforeach() - list(APPEND WOLFSSL_DEFINITIONS "-DHAVE_COMP_KEY" "-DHAVE_OPENSSL_CMD" "-DOPENSSL_ALL" "-DOPENSSL_EXTRA" "-DWC_RSA_NO_PADDING" "-DWOLFSSL_AES_DIRECT" "-DWOLFSSL_CERT_GEN" "-DWOLFSSL_CERT_NAME_ALL" "-DWOLFSSL_CMAC" "-DWOLFSSL_EITHER_SIDE" "-DWOLFSSL_ERROR_CODE_OPENSSL" "-DWOLFSSL_KEY_GEN" "-DWOLFSSL_TICKET_HAVE_ID") + list(APPEND WOLFSSL_DEFINITIONS "-DHAVE_COMP_KEY" "-DHAVE_OPENSSL_CMD" "-DOPENSSL_ALL" "-DOPENSSL_EXTRA" "-DWC_RSA_NO_PADDING" "-DWOLFSSL_AES_DIRECT" "-DWOLFSSL_CERT_GEN" "-DWOLFSSL_CERT_NAME_ALL" "-DWOLFSSL_CMAC" "-DWOLFSSL_EITHER_SIDE" "-DWOLFSSL_ERROR_CODE_OPENSSL" "-DWOLFSSL_I2D_ECDSA_SIG_ALLOC" "-DWOLFSSL_KEY_GEN" "-DWOLFSSL_TICKET_HAVE_ID") endif() add_option("WOLFSSL_LIBSSH2" "Enable libssh2 support (default: disabled)" "no" "yes;no") @@ -579,7 +579,7 @@ if(WOLFSSL_STRONGSWAN) foreach(_o WOLFSSL_CRL WOLFSSL_DES3 WOLFSSL_DTLS WOLFSSL_MD5 WOLFSSL_OCSP) force_option(${_o} "yes") endforeach() - list(APPEND WOLFSSL_DEFINITIONS "-DHAVE_COMP_KEY" "-DHAVE_CRL" "-DHAVE_EX_DATA" "-DHAVE_OPENSSL_CMD" "-DOPENSSL_ALL" "-DOPENSSL_EXTRA" "-DSESSION_CERTS" "-DWC_RSA_NO_PADDING" "-DWOLFSSL_CERT_EXT" "-DWOLFSSL_CERT_GEN" "-DWOLFSSL_CERT_NAME_ALL" "-DWOLFSSL_CERT_REQ" "-DWOLFSSL_DES_ECB" "-DWOLFSSL_EITHER_SIDE" "-DWOLFSSL_ERROR_CODE_OPENSSL" "-DWOLFSSL_KEY_GEN" "-DWOLFSSL_LOG_PRINTF" "-DWOLFSSL_PUBLIC_MP" "-DWOLFSSL_TICKET_HAVE_ID") + list(APPEND WOLFSSL_DEFINITIONS "-DHAVE_COMP_KEY" "-DHAVE_CRL" "-DHAVE_EX_DATA" "-DHAVE_OPENSSL_CMD" "-DOPENSSL_ALL" "-DOPENSSL_EXTRA" "-DSESSION_CERTS" "-DWC_RSA_NO_PADDING" "-DWOLFSSL_CERT_EXT" "-DWOLFSSL_CERT_GEN" "-DWOLFSSL_CERT_NAME_ALL" "-DWOLFSSL_CERT_REQ" "-DWOLFSSL_DES_ECB" "-DWOLFSSL_EITHER_SIDE" "-DWOLFSSL_ERROR_CODE_OPENSSL" "-DWOLFSSL_I2D_ECDSA_SIG_ALLOC" "-DWOLFSSL_KEY_GEN" "-DWOLFSSL_LOG_PRINTF" "-DWOLFSSL_PUBLIC_MP" "-DWOLFSSL_TICKET_HAVE_ID") endif() add_option("WOLFSSL_QT" "Enable Qt support (default: disabled)" "no" "yes;no") @@ -587,7 +587,7 @@ if(WOLFSSL_QT) foreach(_o WOLFSSL_ARC4 WOLFSSL_DES3 WOLFSSL_DSA WOLFSSL_MD5 WOLFSSL_OCSP WOLFSSL_OLD_TLS) force_option(${_o} "yes") endforeach() - list(APPEND WOLFSSL_DEFINITIONS "-DHAVE_ECC_BRAINPOOL" "-DHAVE_ECC_KOBLITZ" "-DHAVE_ECC_SECPR2" "-DHAVE_ECC_SECPR3" "-DHAVE_EX_DATA" "-DHAVE_OPENSSL_CMD" "-DNO_OLD_MD5_NAME" "-DNO_OLD_RNGNAME" "-DNO_OLD_SHA_NAMES" "-DNO_OLD_SSL_NAMES" "-DNO_OLD_WC_NAMES" "-DOPENSSL_ALL" "-DOPENSSL_EXTRA" "-DOPENSSL_NO_SSL2" "-DSESSION_CERTS" "-DWC_RSA_NO_PADDING" "-DWOLFSSL_ALLOW_RC4" "-DWOLFSSL_ALLOW_SSLV3" "-DWOLFSSL_ALLOW_TLSV10" "-DWOLFSSL_CERT_EXT" "-DWOLFSSL_CERT_GEN" "-DWOLFSSL_CERT_NAME_ALL" "-DWOLFSSL_CUSTOM_CURVES" "-DWOLFSSL_EITHER_SIDE" "-DWOLFSSL_ENCRYPTED_KEYS" "-DWOLFSSL_ERROR_CODE_OPENSSL" "-DWOLFSSL_KEY_GEN" "-DWOLFSSL_QT" "-DWOLFSSL_TICKET_HAVE_ID") + list(APPEND WOLFSSL_DEFINITIONS "-DHAVE_ECC_BRAINPOOL" "-DHAVE_ECC_KOBLITZ" "-DHAVE_ECC_SECPR2" "-DHAVE_ECC_SECPR3" "-DHAVE_EX_DATA" "-DHAVE_OPENSSL_CMD" "-DNO_OLD_MD5_NAME" "-DNO_OLD_RNGNAME" "-DNO_OLD_SHA_NAMES" "-DNO_OLD_SSL_NAMES" "-DNO_OLD_WC_NAMES" "-DOPENSSL_ALL" "-DOPENSSL_EXTRA" "-DOPENSSL_NO_SSL2" "-DSESSION_CERTS" "-DWC_RSA_NO_PADDING" "-DWOLFSSL_ALLOW_RC4" "-DWOLFSSL_ALLOW_SSLV3" "-DWOLFSSL_ALLOW_TLSV10" "-DWOLFSSL_CERT_EXT" "-DWOLFSSL_CERT_GEN" "-DWOLFSSL_CERT_NAME_ALL" "-DWOLFSSL_CUSTOM_CURVES" "-DWOLFSSL_EITHER_SIDE" "-DWOLFSSL_ENCRYPTED_KEYS" "-DWOLFSSL_ERROR_CODE_OPENSSL" "-DWOLFSSL_I2D_ECDSA_SIG_ALLOC" "-DWOLFSSL_KEY_GEN" "-DWOLFSSL_QT" "-DWOLFSSL_TICKET_HAVE_ID") endif() add_option("WOLFSSL_APACHE_HTTPD" "Enable Apache httpd support (default: disabled)" "no" "yes;no") @@ -595,7 +595,7 @@ if(WOLFSSL_APACHE_HTTPD) foreach(_o WOLFSSL_CRL WOLFSSL_OCSP) force_option(${_o} "yes") endforeach() - list(APPEND WOLFSSL_DEFINITIONS "-DHAVE_ALPN" "-DHAVE_CRL" "-DHAVE_EX_DATA" "-DHAVE_OPENSSL_CMD" "-DHAVE_SECURE_RENEGOTIATION" "-DNO_SESSION_CACHE_REF" "-DOPENSSL_ALL" "-DOPENSSL_COMPATIBLE_DEFAULTS" "-DOPENSSL_EXTRA" "-DOPENSSL_NO_COMP" "-DOPENSSL_NO_SSL2" "-DOPENSSL_NO_SSL3" "-DSESSION_CERTS" "-DWC_RSA_NO_PADDING" "-DWOLFSSL_ALT_CERT_CHAINS" "-DWOLFSSL_ALWAYS_KEEP_SNI" "-DWOLFSSL_APACHE_HTTPD" "-DWOLFSSL_CERT_EXT" "-DWOLFSSL_CERT_GEN" "-DWOLFSSL_CERT_NAME_ALL" "-DWOLFSSL_CERT_REQ" "-DWOLFSSL_CHECK_ALERT_ON_ERR" "-DWOLFSSL_EITHER_SIDE" "-DWOLFSSL_ENCRYPTED_KEYS" "-DWOLFSSL_ERROR_CODE_OPENSSL" "-DWOLFSSL_NO_OCSP_ISSUER_CHECK" "-DWOLFSSL_PRIORITIZE_PSK" "-DWOLFSSL_SIGNER_DER_CERT" "-DWOLFSSL_TICKET_HAVE_ID" "-DWOLFSSL_TLS13_NO_PEEK_HANDSHAKE_DONE" "-DWOLFSSL_TRUST_PEER_CERT") + list(APPEND WOLFSSL_DEFINITIONS "-DHAVE_ALPN" "-DHAVE_CRL" "-DHAVE_EX_DATA" "-DHAVE_OPENSSL_CMD" "-DHAVE_SECURE_RENEGOTIATION" "-DNO_SESSION_CACHE_REF" "-DOPENSSL_ALL" "-DOPENSSL_COMPATIBLE_DEFAULTS" "-DOPENSSL_EXTRA" "-DOPENSSL_NO_COMP" "-DOPENSSL_NO_SSL2" "-DOPENSSL_NO_SSL3" "-DSESSION_CERTS" "-DWC_RSA_NO_PADDING" "-DWOLFSSL_ALT_CERT_CHAINS" "-DWOLFSSL_ALWAYS_KEEP_SNI" "-DWOLFSSL_APACHE_HTTPD" "-DWOLFSSL_CERT_EXT" "-DWOLFSSL_CERT_GEN" "-DWOLFSSL_CERT_NAME_ALL" "-DWOLFSSL_CERT_REQ" "-DWOLFSSL_CHECK_ALERT_ON_ERR" "-DWOLFSSL_EITHER_SIDE" "-DWOLFSSL_ENCRYPTED_KEYS" "-DWOLFSSL_ERROR_CODE_OPENSSL" "-DWOLFSSL_I2D_ECDSA_SIG_ALLOC" "-DWOLFSSL_NO_OCSP_ISSUER_CHECK" "-DWOLFSSL_PRIORITIZE_PSK" "-DWOLFSSL_SIGNER_DER_CERT" "-DWOLFSSL_TICKET_HAVE_ID" "-DWOLFSSL_TLS13_NO_PEEK_HANDSHAKE_DONE" "-DWOLFSSL_TRUST_PEER_CERT") endif() add_option("WOLFSSL_JNI" "Enable wolfSSL JNI support (default: disabled)" "no" "yes;no") @@ -603,7 +603,7 @@ if(WOLFSSL_JNI) foreach(_o WOLFSSL_AES WOLFSSL_CRL WOLFSSL_CRL_MONITOR WOLFSSL_DTLS WOLFSSL_DTLS13 WOLFSSL_OCSP WOLFSSL_PKCALLBACKS) force_option(${_o} "yes") endforeach() - list(APPEND WOLFSSL_DEFINITIONS "-DATOMIC_USER" "-DHAVE_ALPN" "-DHAVE_CRL" "-DHAVE_CTS" "-DHAVE_EX_DATA" "-DHAVE_OPENSSL_CMD" "-DKEEP_PEER_CERT" "-DNO_ERROR_QUEUE" "-DOPENSSL_ALL" "-DOPENSSL_EXTRA" "-DPERSIST_CERT_CACHE" "-DPERSIST_SESSION_CACHE" "-DSESSION_CERTS" "-DWC_RSA_NO_PADDING" "-DWOLFSSL_AES_DIRECT" "-DWOLFSSL_ALT_CERT_CHAINS" "-DWOLFSSL_ALT_NAMES" "-DWOLFSSL_ALWAYS_KEEP_SNI" "-DWOLFSSL_ALWAYS_VERIFY_CB" "-DWOLFSSL_CERT_EXT" "-DWOLFSSL_CERT_GEN" "-DWOLFSSL_CERT_NAME_ALL" "-DWOLFSSL_CERT_REQ" "-DWOLFSSL_DTLS_CH_FRAG" "-DWOLFSSL_DTLS_DROP_STATS" "-DWOLFSSL_DTLS_MTU" "-DWOLFSSL_EITHER_SIDE" "-DWOLFSSL_ENCRYPTED_KEYS" "-DWOLFSSL_ERROR_CODE_OPENSSL" "-DWOLFSSL_JNI" "-DWOLFSSL_KEY_GEN" "-DWOLFSSL_PUBLIC_MP" "-DWOLFSSL_SEND_HRR_COOKIE" "-DWOLFSSL_TICKET_HAVE_ID" "-DWOLFSSL_TLS13_MIDDLEBOX_COMPAT") + list(APPEND WOLFSSL_DEFINITIONS "-DATOMIC_USER" "-DHAVE_ALPN" "-DHAVE_CRL" "-DHAVE_CTS" "-DHAVE_EX_DATA" "-DHAVE_OPENSSL_CMD" "-DKEEP_PEER_CERT" "-DNO_ERROR_QUEUE" "-DOPENSSL_ALL" "-DOPENSSL_EXTRA" "-DPERSIST_CERT_CACHE" "-DPERSIST_SESSION_CACHE" "-DSESSION_CERTS" "-DWC_RSA_NO_PADDING" "-DWOLFSSL_AES_DIRECT" "-DWOLFSSL_ALT_CERT_CHAINS" "-DWOLFSSL_ALT_NAMES" "-DWOLFSSL_ALWAYS_KEEP_SNI" "-DWOLFSSL_ALWAYS_VERIFY_CB" "-DWOLFSSL_CERT_EXT" "-DWOLFSSL_CERT_GEN" "-DWOLFSSL_CERT_NAME_ALL" "-DWOLFSSL_CERT_REQ" "-DWOLFSSL_DTLS_CH_FRAG" "-DWOLFSSL_DTLS_DROP_STATS" "-DWOLFSSL_DTLS_MTU" "-DWOLFSSL_EITHER_SIDE" "-DWOLFSSL_ENCRYPTED_KEYS" "-DWOLFSSL_ERROR_CODE_OPENSSL" "-DWOLFSSL_I2D_ECDSA_SIG_ALLOC" "-DWOLFSSL_JNI" "-DWOLFSSL_KEY_GEN" "-DWOLFSSL_PUBLIC_MP" "-DWOLFSSL_SEND_HRR_COOKIE" "-DWOLFSSL_TICKET_HAVE_ID" "-DWOLFSSL_TLS13_MIDDLEBOX_COMPAT") endif() add_option("WOLFSSL_WOLFCLU" "Enable wolfCLU support (default: disabled)" "no" "yes;no") @@ -611,7 +611,7 @@ if(WOLFSSL_WOLFCLU) foreach(_o WOLFSSL_AES WOLFSSL_DES3 WOLFSSL_MD5 WOLFSSL_OCSP WOLFSSL_PKCS7) force_option(${_o} "yes") endforeach() - list(APPEND WOLFSSL_DEFINITIONS "-DHAVE_AES_KEYWRAP" "-DHAVE_ED25519" "-DHAVE_OCSP_RESPONDER" "-DHAVE_OID_ENCODING" "-DHAVE_OPENSSL_CMD" "-DHAVE_X963_KDF" "-DOPENSSL_ALL" "-DOPENSSL_EXTRA" "-DWC_RSA_NO_PADDING" "-DWC_SIG_MIN_HASH_TYPE=WC_HASH_TYPE_MD5" "-DWOLFSSL_AES_COUNTER" "-DWOLFSSL_AES_DIRECT" "-DWOLFSSL_ALT_NAMES" "-DWOLFSSL_CERT_EXT" "-DWOLFSSL_CERT_GEN" "-DWOLFSSL_CERT_NAME_ALL" "-DWOLFSSL_CERT_REQ" "-DWOLFSSL_EITHER_SIDE" "-DWOLFSSL_ERROR_CODE_OPENSSL" "-DWOLFSSL_KEY_GEN" "-DWOLFSSL_NO_ASN_STRICT" "-DWOLFSSL_TICKET_HAVE_ID") + list(APPEND WOLFSSL_DEFINITIONS "-DHAVE_AES_KEYWRAP" "-DHAVE_ED25519" "-DHAVE_OCSP_RESPONDER" "-DHAVE_OID_ENCODING" "-DHAVE_OPENSSL_CMD" "-DHAVE_X963_KDF" "-DOPENSSL_ALL" "-DOPENSSL_EXTRA" "-DWC_RSA_NO_PADDING" "-DWC_SIG_MIN_HASH_TYPE=WC_HASH_TYPE_MD5" "-DWOLFSSL_AES_COUNTER" "-DWOLFSSL_AES_DIRECT" "-DWOLFSSL_ALT_NAMES" "-DWOLFSSL_CERT_EXT" "-DWOLFSSL_CERT_GEN" "-DWOLFSSL_CERT_NAME_ALL" "-DWOLFSSL_CERT_REQ" "-DWOLFSSL_EITHER_SIDE" "-DWOLFSSL_ERROR_CODE_OPENSSL" "-DWOLFSSL_I2D_ECDSA_SIG_ALLOC" "-DWOLFSSL_KEY_GEN" "-DWOLFSSL_NO_ASN_STRICT" "-DWOLFSSL_TICKET_HAVE_ID") endif() add_option("WOLFSSL_SBLIM_SFCB" "Enable SBLIM SFCB support (default: disabled)" "no" "yes;no") @@ -624,7 +624,7 @@ if(WOLFSSL_TAILSCALE) foreach(_o WOLFSSL_MD5 WOLFSSL_OCSP) force_option(${_o} "yes") endforeach() - list(APPEND WOLFSSL_DEFINITIONS "-DHAVE_ALPN" "-DHAVE_COMP_KEY" "-DHAVE_OPENSSL_CMD" "-DOPENSSL_ALL" "-DOPENSSL_EXTRA" "-DSESSION_CERTS" "-DWC_CTC_NAME_SIZE=128" "-DWC_RSA_NO_PADDING" "-DWOLFSSL_ACME_OID" "-DWOLFSSL_AESGCM_STREAM" "-DWOLFSSL_ALWAYS_KEEP_SNI" "-DWOLFSSL_BASE16" "-DWOLFSSL_CERT_EXT" "-DWOLFSSL_CERT_GEN" "-DWOLFSSL_CERT_NAME_ALL" "-DWOLFSSL_CERT_REQ" "-DWOLFSSL_CERT_SETUP_CB" "-DWOLFSSL_EITHER_SIDE" "-DWOLFSSL_ERROR_CODE_OPENSSL" "-DWOLFSSL_NO_INIT_CTX_KEY" "-DWOLFSSL_PUBLIC_MP" "-DWOLFSSL_TICKET_HAVE_ID") + list(APPEND WOLFSSL_DEFINITIONS "-DHAVE_ALPN" "-DHAVE_COMP_KEY" "-DHAVE_OPENSSL_CMD" "-DOPENSSL_ALL" "-DOPENSSL_EXTRA" "-DSESSION_CERTS" "-DWC_CTC_NAME_SIZE=128" "-DWC_RSA_NO_PADDING" "-DWOLFSSL_ACME_OID" "-DWOLFSSL_AESGCM_STREAM" "-DWOLFSSL_ALWAYS_KEEP_SNI" "-DWOLFSSL_BASE16" "-DWOLFSSL_CERT_EXT" "-DWOLFSSL_CERT_GEN" "-DWOLFSSL_CERT_NAME_ALL" "-DWOLFSSL_CERT_REQ" "-DWOLFSSL_CERT_SETUP_CB" "-DWOLFSSL_EITHER_SIDE" "-DWOLFSSL_ERROR_CODE_OPENSSL" "-DWOLFSSL_I2D_ECDSA_SIG_ALLOC" "-DWOLFSSL_NO_INIT_CTX_KEY" "-DWOLFSSL_PUBLIC_MP" "-DWOLFSSL_TICKET_HAVE_ID") endif() add_option("WOLFSSL_CHRONY" "Enable chrony support (default: disabled)" "no" "yes;no") @@ -632,7 +632,7 @@ if(WOLFSSL_CHRONY) foreach(_o WOLFSSL_AES WOLFSSL_MD5 WOLFSSL_OCSP) force_option(${_o} "yes") endforeach() - list(APPEND WOLFSSL_DEFINITIONS "-DHAVE_ALPN" "-DHAVE_COMP_KEY" "-DHAVE_ED25519" "-DHAVE_KEYING_MATERIAL" "-DHAVE_MAX_FRAGMENT" "-DHAVE_OPENSSL_CMD" "-DHAVE_TRUNCATED_HMAC" "-DHAVE_TRUSTED_CA" "-DOPENSSL_ALL" "-DOPENSSL_EXTRA" "-DWC_RSA_NO_PADDING" "-DWOLFSSL_AES_COUNTER" "-DWOLFSSL_AES_DIRECT" "-DWOLFSSL_AES_SIV" "-DWOLFSSL_ALWAYS_KEEP_SNI" "-DWOLFSSL_CERT_GEN" "-DWOLFSSL_CERT_NAME_ALL" "-DWOLFSSL_CMAC" "-DWOLFSSL_EITHER_SIDE" "-DWOLFSSL_ERROR_CODE_OPENSSL" "-DWOLFSSL_TICKET_HAVE_ID") + list(APPEND WOLFSSL_DEFINITIONS "-DHAVE_ALPN" "-DHAVE_COMP_KEY" "-DHAVE_ED25519" "-DHAVE_KEYING_MATERIAL" "-DHAVE_MAX_FRAGMENT" "-DHAVE_OPENSSL_CMD" "-DHAVE_TRUNCATED_HMAC" "-DHAVE_TRUSTED_CA" "-DOPENSSL_ALL" "-DOPENSSL_EXTRA" "-DWC_RSA_NO_PADDING" "-DWOLFSSL_AES_COUNTER" "-DWOLFSSL_AES_DIRECT" "-DWOLFSSL_AES_SIV" "-DWOLFSSL_ALWAYS_KEEP_SNI" "-DWOLFSSL_CERT_GEN" "-DWOLFSSL_CERT_NAME_ALL" "-DWOLFSSL_CMAC" "-DWOLFSSL_EITHER_SIDE" "-DWOLFSSL_ERROR_CODE_OPENSSL" "-DWOLFSSL_I2D_ECDSA_SIG_ALLOC" "-DWOLFSSL_TICKET_HAVE_ID") endif() add_option("WOLFSSL_LIBEST" "Enable libest support (default: disabled)" "no" "yes;no") @@ -640,7 +640,7 @@ if(WOLFSSL_LIBEST) foreach(_o WOLFSSL_AES WOLFSSL_CRL WOLFSSL_OCSP WOLFSSL_PKCS7 WOLFSSL_SRP) force_option(${_o} "yes") endforeach() - list(APPEND WOLFSSL_DEFINITIONS "-DHAVE_AES_KEYWRAP" "-DHAVE_CRL" "-DHAVE_EX_DATA" "-DHAVE_LIBEST" "-DHAVE_OPENSSL_CMD" "-DHAVE_X963_KDF" "-DOPENSSL_ALL" "-DOPENSSL_EXTRA" "-DSESSION_CERTS" "-DWC_RSA_NO_PADDING" "-DWOLFSSL_AES_DIRECT" "-DWOLFSSL_ALT_NAMES" "-DWOLFSSL_CERT_EXT" "-DWOLFSSL_CERT_GEN" "-DWOLFSSL_CERT_NAME_ALL" "-DWOLFSSL_CERT_REQ" "-DWOLFSSL_EITHER_SIDE" "-DWOLFSSL_ENCRYPTED_KEYS" "-DWOLFSSL_ERROR_CODE_OPENSSL" "-DWOLFSSL_KEY_GEN" "-DWOLFSSL_PSS_SALT_LEN_DISCOVER" "-DWOLFSSL_TICKET_HAVE_ID") + list(APPEND WOLFSSL_DEFINITIONS "-DHAVE_AES_KEYWRAP" "-DHAVE_CRL" "-DHAVE_EX_DATA" "-DHAVE_LIBEST" "-DHAVE_OPENSSL_CMD" "-DHAVE_X963_KDF" "-DOPENSSL_ALL" "-DOPENSSL_EXTRA" "-DSESSION_CERTS" "-DWC_RSA_NO_PADDING" "-DWOLFSSL_AES_DIRECT" "-DWOLFSSL_ALT_NAMES" "-DWOLFSSL_CERT_EXT" "-DWOLFSSL_CERT_GEN" "-DWOLFSSL_CERT_NAME_ALL" "-DWOLFSSL_CERT_REQ" "-DWOLFSSL_EITHER_SIDE" "-DWOLFSSL_ENCRYPTED_KEYS" "-DWOLFSSL_ERROR_CODE_OPENSSL" "-DWOLFSSL_I2D_ECDSA_SIG_ALLOC" "-DWOLFSSL_KEY_GEN" "-DWOLFSSL_PSS_SALT_LEN_DISCOVER" "-DWOLFSSL_TICKET_HAVE_ID") endif() add_option("WOLFSSL_OPENRESTY" "Enable OpenResty support (default: disabled)" "no" "yes;no") @@ -648,7 +648,7 @@ if(WOLFSSL_OPENRESTY) foreach(_o WOLFSSL_CRL WOLFSSL_DSA WOLFSSL_MD5 WOLFSSL_OCSP WOLFSSL_OCSPSTAPLING WOLFSSL_OCSPSTAPLING_V2) force_option(${_o} "yes") endforeach() - list(APPEND WOLFSSL_DEFINITIONS "-DHAVE_ALPN" "-DHAVE_ANON" "-DHAVE_COMP_KEY" "-DHAVE_CRL" "-DHAVE_EXT_CACHE" "-DHAVE_EX_DATA" "-DHAVE_MAX_FRAGMENT" "-DHAVE_OPENSSL_CMD" "-DHAVE_SESSION_TICKET" "-DHAVE_TRUNCATED_HMAC" "-DHAVE_TRUSTED_CA" "-DKEEP_OUR_CERT" "-DKEEP_PEER_CERT" "-DNO_SESSION_CACHE_REF" "-DOPENSSL_ALL" "-DOPENSSL_COMPATIBLE_DEFAULTS" "-DOPENSSL_EXTRA" "-DSESSION_CERTS" "-DWC_RSA_NO_PADDING" "-DWOLFSSL_ALT_CERT_CHAINS" "-DWOLFSSL_ALWAYS_KEEP_SNI" "-DWOLFSSL_ALWAYS_VERIFY_CB" "-DWOLFSSL_CERT_GEN" "-DWOLFSSL_CERT_NAME_ALL" "-DWOLFSSL_CHECK_ALERT_ON_ERR" "-DWOLFSSL_EITHER_SIDE" "-DWOLFSSL_ERROR_CODE_OPENSSL" "-DWOLFSSL_KEY_GEN" "-DWOLFSSL_NGINX" "-DWOLFSSL_PRIORITIZE_PSK" "-DWOLFSSL_SIGNER_DER_CERT" "-DWOLFSSL_TICKET_HAVE_ID" "-DWOLFSSL_TLS13_NO_PEEK_HANDSHAKE_DONE" "-DWOLFSSL_TRUST_PEER_CERT") + list(APPEND WOLFSSL_DEFINITIONS "-DHAVE_ALPN" "-DHAVE_ANON" "-DHAVE_COMP_KEY" "-DHAVE_CRL" "-DHAVE_EXT_CACHE" "-DHAVE_EX_DATA" "-DHAVE_MAX_FRAGMENT" "-DHAVE_OPENSSL_CMD" "-DHAVE_SESSION_TICKET" "-DHAVE_TRUNCATED_HMAC" "-DHAVE_TRUSTED_CA" "-DKEEP_OUR_CERT" "-DKEEP_PEER_CERT" "-DNO_SESSION_CACHE_REF" "-DOPENSSL_ALL" "-DOPENSSL_COMPATIBLE_DEFAULTS" "-DOPENSSL_EXTRA" "-DSESSION_CERTS" "-DWC_RSA_NO_PADDING" "-DWOLFSSL_ALT_CERT_CHAINS" "-DWOLFSSL_ALWAYS_KEEP_SNI" "-DWOLFSSL_ALWAYS_VERIFY_CB" "-DWOLFSSL_CERT_GEN" "-DWOLFSSL_CERT_NAME_ALL" "-DWOLFSSL_CHECK_ALERT_ON_ERR" "-DWOLFSSL_EITHER_SIDE" "-DWOLFSSL_ERROR_CODE_OPENSSL" "-DWOLFSSL_I2D_ECDSA_SIG_ALLOC" "-DWOLFSSL_KEY_GEN" "-DWOLFSSL_NGINX" "-DWOLFSSL_PRIORITIZE_PSK" "-DWOLFSSL_SIGNER_DER_CERT" "-DWOLFSSL_TICKET_HAVE_ID" "-DWOLFSSL_TLS13_NO_PEEK_HANDSHAKE_DONE" "-DWOLFSSL_TRUST_PEER_CERT") endif() add_option("WOLFSSL_LIBWEBSOCKETS" "Enable libwebsockets support (default: disabled)" "no" "yes;no") @@ -656,7 +656,7 @@ if(WOLFSSL_LIBWEBSOCKETS) foreach(_o WOLFSSL_MD5 WOLFSSL_OCSP) force_option(${_o} "yes") endforeach() - list(APPEND WOLFSSL_DEFINITIONS "-DHAVE_COMP_KEY" "-DHAVE_EX_DATA" "-DHAVE_OPENSSL_CMD" "-DOPENSSL_ALL" "-DOPENSSL_EXTRA" "-DOPENSSL_NO_EC" "-DWC_RSA_NO_PADDING" "-DWOLFSSL_CERT_NAME_ALL" "-DWOLFSSL_EITHER_SIDE" "-DWOLFSSL_ERROR_CODE_OPENSSL" "-DWOLFSSL_LIBWEBSOCKETS" "-DWOLFSSL_TICKET_HAVE_ID") + list(APPEND WOLFSSL_DEFINITIONS "-DHAVE_COMP_KEY" "-DHAVE_EX_DATA" "-DHAVE_OPENSSL_CMD" "-DOPENSSL_ALL" "-DOPENSSL_EXTRA" "-DOPENSSL_NO_EC" "-DWC_RSA_NO_PADDING" "-DWOLFSSL_CERT_NAME_ALL" "-DWOLFSSL_EITHER_SIDE" "-DWOLFSSL_ERROR_CODE_OPENSSL" "-DWOLFSSL_I2D_ECDSA_SIG_ALLOC" "-DWOLFSSL_LIBWEBSOCKETS" "-DWOLFSSL_TICKET_HAVE_ID") endif() add_option("WOLFSSL_FORTRESS" "Enable wolfSSL fortress build (default: disabled)" "no" "yes;no") @@ -680,7 +680,7 @@ if(WOLFSSL_KRB) foreach(_o WOLFSSL_AES WOLFSSL_ARC4 WOLFSSL_CRL WOLFSSL_DES3 WOLFSSL_MD4 WOLFSSL_MD5 WOLFSSL_OCSP WOLFSSL_PKCS7) force_option(${_o} "yes") endforeach() - list(APPEND WOLFSSL_DEFINITIONS "-DHAVE_AES_KEYWRAP" "-DHAVE_COMP_KEY" "-DHAVE_CRL" "-DHAVE_EX_DATA" "-DHAVE_OPENSSL_CMD" "-DHAVE_X963_KDF" "-DOPENSSL_ALL" "-DOPENSSL_EXTRA" "-DWC_RSA_NO_PADDING" "-DWOLFSSL_AES_DIRECT" "-DWOLFSSL_ALLOW_RC4" "-DWOLFSSL_CERT_NAME_ALL" "-DWOLFSSL_DES_ECB" "-DWOLFSSL_EITHER_SIDE" "-DWOLFSSL_ERROR_CODE_OPENSSL" "-DWOLFSSL_KRB" "-DWOLFSSL_TICKET_HAVE_ID") + list(APPEND WOLFSSL_DEFINITIONS "-DHAVE_AES_KEYWRAP" "-DHAVE_COMP_KEY" "-DHAVE_CRL" "-DHAVE_EX_DATA" "-DHAVE_OPENSSL_CMD" "-DHAVE_X963_KDF" "-DOPENSSL_ALL" "-DOPENSSL_EXTRA" "-DWC_RSA_NO_PADDING" "-DWOLFSSL_AES_DIRECT" "-DWOLFSSL_ALLOW_RC4" "-DWOLFSSL_CERT_NAME_ALL" "-DWOLFSSL_DES_ECB" "-DWOLFSSL_EITHER_SIDE" "-DWOLFSSL_ERROR_CODE_OPENSSL" "-DWOLFSSL_I2D_ECDSA_SIG_ALLOC" "-DWOLFSSL_KRB" "-DWOLFSSL_TICKET_HAVE_ID") endif() add_option("WOLFSSL_SMIME" "Enable S/MIME support (default: disabled)" "no" "yes;no") @@ -688,7 +688,7 @@ if(WOLFSSL_SMIME) foreach(_o WOLFSSL_AES WOLFSSL_MD5 WOLFSSL_OCSP WOLFSSL_PKCS7) force_option(${_o} "yes") endforeach() - list(APPEND WOLFSSL_DEFINITIONS "-DHAVE_AES_KEYWRAP" "-DHAVE_COMP_KEY" "-DHAVE_OPENSSL_CMD" "-DHAVE_SMIME" "-DHAVE_X963_KDF" "-DOPENSSL_ALL" "-DOPENSSL_EXTRA" "-DWC_RSA_NO_PADDING" "-DWOLFSSL_AES_DIRECT" "-DWOLFSSL_CERT_NAME_ALL" "-DWOLFSSL_EITHER_SIDE" "-DWOLFSSL_ERROR_CODE_OPENSSL" "-DWOLFSSL_TICKET_HAVE_ID") + list(APPEND WOLFSSL_DEFINITIONS "-DHAVE_AES_KEYWRAP" "-DHAVE_COMP_KEY" "-DHAVE_OPENSSL_CMD" "-DHAVE_SMIME" "-DHAVE_X963_KDF" "-DOPENSSL_ALL" "-DOPENSSL_EXTRA" "-DWC_RSA_NO_PADDING" "-DWOLFSSL_AES_DIRECT" "-DWOLFSSL_CERT_NAME_ALL" "-DWOLFSSL_EITHER_SIDE" "-DWOLFSSL_ERROR_CODE_OPENSSL" "-DWOLFSSL_I2D_ECDSA_SIG_ALLOC" "-DWOLFSSL_TICKET_HAVE_ID") endif() add_option("WOLFSSL_SCEP" "Enable wolfSCEP support (default: disabled)" "no" "yes;no") @@ -704,7 +704,7 @@ if(WOLFSSL_WPAS_DPP) foreach(_o WOLFSSL_AES WOLFSSL_ARC4 WOLFSSL_CRL WOLFSSL_DES3 WOLFSSL_DSA WOLFSSL_MD4 WOLFSSL_MD5 WOLFSSL_OCSP WOLFSSL_OCSPSTAPLING WOLFSSL_OCSPSTAPLING_V2 WOLFSSL_PKCS7) force_option(${_o} "yes") endforeach() - list(APPEND WOLFSSL_DEFINITIONS "-DATOMIC_USER" "-DHAVE_AES_KEYWRAP" "-DHAVE_ANON" "-DHAVE_COMP_KEY" "-DHAVE_CRL" "-DHAVE_ECC_BRAINPOOL" "-DHAVE_ECC_CDH" "-DHAVE_ECC_KOBLITZ" "-DHAVE_ECC_SECPR2" "-DHAVE_ECC_SECPR3" "-DHAVE_EXT_CACHE" "-DHAVE_EX_DATA" "-DHAVE_KEYING_MATERIAL" "-DHAVE_MAX_FRAGMENT" "-DHAVE_OPENSSL_CMD" "-DHAVE_SECRET_CALLBACK" "-DHAVE_SESSION_TICKET" "-DHAVE_STUNNEL" "-DHAVE_TRUNCATED_HMAC" "-DHAVE_X963_KDF" "-DKEEP_OUR_CERT" "-DKEEP_PEER_CERT" "-DNO_SESSION_CACHE_REF" "-DOPENSSL_ALL" "-DOPENSSL_COMPATIBLE_DEFAULTS" "-DOPENSSL_EXTRA" "-DOPENSSL_EXTRA_X509_SMALL" "-DSESSION_CERTS" "-DWC_CTC_NAME_SIZE=128" "-DWC_RSA_NO_PADDING" "-DWOLFSSL_AES_DIRECT" "-DWOLFSSL_ALLOW_RC4" "-DWOLFSSL_ALT_CERT_CHAINS" "-DWOLFSSL_ALWAYS_KEEP_SNI" "-DWOLFSSL_ALWAYS_VERIFY_CB" "-DWOLFSSL_CERT_EXT" "-DWOLFSSL_CERT_GEN" "-DWOLFSSL_CERT_NAME_ALL" "-DWOLFSSL_CERT_REQ" "-DWOLFSSL_CHECK_ALERT_ON_ERR" "-DWOLFSSL_CMAC" "-DWOLFSSL_CUSTOM_CURVES" "-DWOLFSSL_DER_LOAD" "-DWOLFSSL_DES_ECB" "-DWOLFSSL_EITHER_SIDE" "-DWOLFSSL_ENCRYPTED_KEYS" "-DWOLFSSL_ERROR_CODE_OPENSSL" "-DWOLFSSL_KEY_GEN" "-DWOLFSSL_PRIORITIZE_PSK" "-DWOLFSSL_PUBLIC_ECC_ADD_DBL" "-DWOLFSSL_PUBLIC_MP" "-DWOLFSSL_SIGNER_DER_CERT" "-DWOLFSSL_TICKET_HAVE_ID" "-DWOLFSSL_TLS13_NO_PEEK_HANDSHAKE_DONE" "-DWOLFSSL_TRUST_PEER_CERT" "-DWOLFSSL_VALIDATE_ECC_IMPORT" "-DWOLFSSL_WPAS") + list(APPEND WOLFSSL_DEFINITIONS "-DATOMIC_USER" "-DHAVE_AES_KEYWRAP" "-DHAVE_ANON" "-DHAVE_COMP_KEY" "-DHAVE_CRL" "-DHAVE_ECC_BRAINPOOL" "-DHAVE_ECC_CDH" "-DHAVE_ECC_KOBLITZ" "-DHAVE_ECC_SECPR2" "-DHAVE_ECC_SECPR3" "-DHAVE_EXT_CACHE" "-DHAVE_EX_DATA" "-DHAVE_KEYING_MATERIAL" "-DHAVE_MAX_FRAGMENT" "-DHAVE_OPENSSL_CMD" "-DHAVE_SECRET_CALLBACK" "-DHAVE_SESSION_TICKET" "-DHAVE_STUNNEL" "-DHAVE_TRUNCATED_HMAC" "-DHAVE_X963_KDF" "-DKEEP_OUR_CERT" "-DKEEP_PEER_CERT" "-DNO_SESSION_CACHE_REF" "-DOPENSSL_ALL" "-DOPENSSL_COMPATIBLE_DEFAULTS" "-DOPENSSL_EXTRA" "-DOPENSSL_EXTRA_X509_SMALL" "-DSESSION_CERTS" "-DWC_CTC_NAME_SIZE=128" "-DWC_RSA_NO_PADDING" "-DWOLFSSL_AES_DIRECT" "-DWOLFSSL_ALLOW_RC4" "-DWOLFSSL_ALT_CERT_CHAINS" "-DWOLFSSL_ALWAYS_KEEP_SNI" "-DWOLFSSL_ALWAYS_VERIFY_CB" "-DWOLFSSL_CERT_EXT" "-DWOLFSSL_CERT_GEN" "-DWOLFSSL_CERT_NAME_ALL" "-DWOLFSSL_CERT_REQ" "-DWOLFSSL_CHECK_ALERT_ON_ERR" "-DWOLFSSL_CMAC" "-DWOLFSSL_CUSTOM_CURVES" "-DWOLFSSL_DER_LOAD" "-DWOLFSSL_DES_ECB" "-DWOLFSSL_EITHER_SIDE" "-DWOLFSSL_ENCRYPTED_KEYS" "-DWOLFSSL_ERROR_CODE_OPENSSL" "-DWOLFSSL_I2D_ECDSA_SIG_ALLOC" "-DWOLFSSL_KEY_GEN" "-DWOLFSSL_PRIORITIZE_PSK" "-DWOLFSSL_PUBLIC_ECC_ADD_DBL" "-DWOLFSSL_PUBLIC_MP" "-DWOLFSSL_SIGNER_DER_CERT" "-DWOLFSSL_TICKET_HAVE_ID" "-DWOLFSSL_TLS13_NO_PEEK_HANDSHAKE_DONE" "-DWOLFSSL_TRUST_PEER_CERT" "-DWOLFSSL_VALIDATE_ECC_IMPORT" "-DWOLFSSL_WPAS") endif() add_option("WOLFSSL_QT_TEST" "Enable Qt test support (default: disabled)" "no" "yes;no") @@ -1218,7 +1218,8 @@ if (WOLFSSL_OPENSSLALL) list(APPEND WOLFSSL_DEFINITIONS "-DOPENSSL_ALL" "-DWOLFSSL_EITHER_SIDE" "-DWC_RSA_NO_PADDING" "-DWC_RSA_PSS" "-DWOLFSSL_PSS_LONG_SALT" "-DWOLFSSL_TICKET_HAVE_ID" - "-DWOLFSSL_ERROR_CODE_OPENSSL" "-DWOLFSSL_CERT_NAME_ALL") + "-DWOLFSSL_ERROR_CODE_OPENSSL" "-DWOLFSSL_CERT_NAME_ALL" + "-DWOLFSSL_I2D_ECDSA_SIG_ALLOC") endif() add_option(WOLFSSL_NO_STUB diff --git a/certs/check_cert_chains.sh b/certs/check_cert_chains.sh index e8b1cd936ed..3f4879fdd14 100755 --- a/certs/check_cert_chains.sh +++ b/certs/check_cert_chains.sh @@ -17,11 +17,34 @@ cd "$(dirname "$0")" || exit 1 # stated here, not parsed, since old OpenSSL cannot decode an ML-DSA cert. A # multi-certificate file is checked on its first certificate, which is the leaf. # Add lines here. +# Of the X509_verify_cert() test certs, those whose issuer is kept and in date. +ta=intermediate/trust_anchor pairs="rsapss/ecc-leaf-rsapss.pem rsapss/ca-rsapss.pem classic mldsa/ecc-leaf-mldsa44.pem mldsa/mldsa44-cert.pem mldsa server-cert-sha1.pem ca-cert.pem sha1 client-cert-sha1.pem ca-cert.pem sha1 -server-cert-sha1-root.pem ca-cert.pem classic" +server-cert-sha1-root.pem ca-cert.pem classic +$ta/link-cert.pem $ta/root-cert.pem classic +$ta/leaf-cert.pem $ta/link-cert.pem classic +$ta/notca-twin-cert.pem $ta/root-cert.pem classic +$ta/dated-int-cert.pem $ta/dated-root-cert.pem classic +$ta/dated-int-leaf-cert.pem $ta/dated-int-cert.pem classic +$ta/v1-root-leaf-cert.pem $ta/v1-root-cert.pem classic +$ta/renewed-root-leaf-cert.pem $ta/renewed-root-cert.pem classic +$ta/expired-root-int-leaf-cert.pem $ta/expired-root-int-cert.pem classic +$ta/expired-root-link-leaf-cert.pem $ta/expired-root-link-cert.pem classic +$ta/noaki-root-link-cert.pem $ta/noaki-root-cert.pem classic +$ta/noaki-root-leaf-cert.pem $ta/noaki-root-cert.pem classic +$ta/forge-int-cert.pem $ta/forge-root-cert.pem classic +$ta/forge-fake-int-cert.pem $ta/forge-q-cert.pem classic +$ta/forge-fake-int-leaf-cert.pem $ta/forge-fake-int-cert.pem classic +$ta/forge-sub-leaf-cert.pem $ta/forge-sub-cert.pem classic +$ta/alt-int-cert.pem $ta/alt-root-cert.pem classic +$ta/alt-end-int-cert.pem $ta/alt-end-cert.pem classic +$ta/alt-notca-int-cert.pem $ta/alt-end-cert.pem classic +$ta/alt-int-leaf-cert.pem $ta/alt-int-cert.pem classic +$ta/wrongca-cert.pem $ta/wrongca-root-cert.pem classic +$ta/wrongca-int-leaf-cert.pem $ta/wrongca-int-cert.pem classic" failed=0 diff --git a/certs/check_dates.sh b/certs/check_dates.sh index 64421e76e98..57432f4d14e 100755 --- a/certs/check_dates.sh +++ b/certs/check_dates.sh @@ -18,6 +18,12 @@ exp_expired="\ /test/expired/expired-ca.pem \ /test/expired/expired-cert.der \ /test/expired/expired-ca.der \ +/intermediate/trust_anchor/expired-root-cert.pem \ +/intermediate/trust_anchor/expired-int-cert.pem \ +/intermediate/trust_anchor/expired-root-old-link-cert.pem \ +/intermediate/trust_anchor/badkid-int-cert.pem \ +/intermediate/trust_anchor/alt-old-int-cert.pem \ +/intermediate/trust_anchor/wrongca-old-int-cert.pem \ /certeccrsa.pem \ /certeccrsa.der " diff --git a/certs/intermediate/include.am b/certs/intermediate/include.am index 23634bd3fda..ab05dbab4de 100644 --- a/certs/intermediate/include.am +++ b/certs/intermediate/include.am @@ -70,4 +70,70 @@ EXTRA_DIST += \ certs/intermediate/untrusted_anchor/loop-b-cert.pem \ certs/intermediate/untrusted_anchor/loop-b-key.pem \ certs/intermediate/untrusted_anchor/loop-leaf-cert.pem \ - certs/intermediate/untrusted_anchor/loop-leaf-key.pem + certs/intermediate/untrusted_anchor/loop-leaf-key.pem \ + certs/intermediate/trust_anchor/gen_certs.sh \ + certs/intermediate/trust_anchor/self-cert.pem \ + certs/intermediate/trust_anchor/self-copy-cert.pem \ + certs/intermediate/trust_anchor/self-key.pem \ + certs/intermediate/trust_anchor/root-cert.pem \ + certs/intermediate/trust_anchor/root-key.pem \ + certs/intermediate/trust_anchor/link-cert.pem \ + certs/intermediate/trust_anchor/link-key.pem \ + certs/intermediate/trust_anchor/link-noaki-cert.pem \ + certs/intermediate/trust_anchor/leaf-cert.pem \ + certs/intermediate/trust_anchor/leaf-key.pem \ + certs/intermediate/trust_anchor/notca-twin-cert.pem \ + certs/intermediate/trust_anchor/gen_dated_certs.sh \ + certs/intermediate/trust_anchor/dated-root-cert.pem \ + certs/intermediate/trust_anchor/dated-root-late-cert.pem \ + certs/intermediate/trust_anchor/expired-root-cert.pem \ + certs/intermediate/trust_anchor/expired-root-leaf-cert.pem \ + certs/intermediate/trust_anchor/expired-int-cert.pem \ + certs/intermediate/trust_anchor/dated-int-cert.pem \ + certs/intermediate/trust_anchor/dated-int-leaf-cert.pem \ + certs/intermediate/trust_anchor/notca-root-cert.pem \ + certs/intermediate/trust_anchor/notca-root-leaf-cert.pem \ + certs/intermediate/trust_anchor/nobc-root-cert.pem \ + certs/intermediate/trust_anchor/nobc-root-leaf-cert.pem \ + certs/intermediate/trust_anchor/v1-root-cert.pem \ + certs/intermediate/trust_anchor/v1-root-leaf-cert.pem \ + certs/intermediate/trust_anchor/cross-root-cert.pem \ + certs/intermediate/trust_anchor/cross-root-late-cert.pem \ + certs/intermediate/trust_anchor/renewed-root-cert.pem \ + certs/intermediate/trust_anchor/renewed-root-leaf-cert.pem \ + certs/intermediate/trust_anchor/expired-root-int-cert.pem \ + certs/intermediate/trust_anchor/expired-root-int-leaf-cert.pem \ + certs/intermediate/trust_anchor/expired-root-link-cert.pem \ + certs/intermediate/trust_anchor/expired-root-old-link-cert.pem \ + certs/intermediate/trust_anchor/expired-root-link-leaf-cert.pem \ + certs/intermediate/trust_anchor/expired-root-nokid-cert.pem \ + certs/intermediate/trust_anchor/ec-name-root-cert.pem \ + certs/intermediate/trust_anchor/nokid-root-cert.pem \ + certs/intermediate/trust_anchor/badkid-int-cert.pem \ + certs/intermediate/trust_anchor/badkid-int-leaf-cert.pem \ + certs/intermediate/trust_anchor/noaki-root-cert.pem \ + certs/intermediate/trust_anchor/noaki-root-link-cert.pem \ + certs/intermediate/trust_anchor/noaki-root-leaf-cert.pem \ + certs/intermediate/trust_anchor/forge-root-cert.pem \ + certs/intermediate/trust_anchor/forge-int-cert.pem \ + certs/intermediate/trust_anchor/forge-fake-int-cert.pem \ + certs/intermediate/trust_anchor/forge-fake-int-leaf-cert.pem \ + certs/intermediate/trust_anchor/forge-q-cert.pem \ + certs/intermediate/trust_anchor/forge-bad-sub-cert.pem \ + certs/intermediate/trust_anchor/forge-sub-cert.pem \ + certs/intermediate/trust_anchor/forge-sub-leaf-cert.pem \ + certs/intermediate/trust_anchor/alt-root-cert.pem \ + certs/intermediate/trust_anchor/alt-int-cert.pem \ + certs/intermediate/trust_anchor/alt-end-cert.pem \ + certs/intermediate/trust_anchor/alt-end-int-cert.pem \ + certs/intermediate/trust_anchor/alt-old-int-cert.pem \ + certs/intermediate/trust_anchor/alt-notca-int-cert.pem \ + certs/intermediate/trust_anchor/alt-int-leaf-cert.pem \ + certs/intermediate/trust_anchor/wrongca-root-cert.pem \ + certs/intermediate/trust_anchor/wrongca-cert.pem \ + certs/intermediate/trust_anchor/wrongca-int-cert.pem \ + certs/intermediate/trust_anchor/wrongca-old-int-cert.pem \ + certs/intermediate/trust_anchor/wrongca-int-leaf-cert.pem \ + certs/intermediate/trust_anchor/int-crl.pem \ + certs/intermediate/trust_anchor/dated-root-empty-crl.pem \ + certs/intermediate/trust_anchor/dated-root-crl.pem diff --git a/certs/intermediate/trust_anchor/alt-end-cert.pem b/certs/intermediate/trust_anchor/alt-end-cert.pem new file mode 100644 index 00000000000..9591fa59e04 --- /dev/null +++ b/certs/intermediate/trust_anchor/alt-end-cert.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDKjCCAhKgAwIBAgICECowDQYJKoZIhvcNAQELBQAwJjEkMCIGA1UEAwwbd29s +ZlNTTCBDaGFpbiBUZXN0IEFsdCBHb25lMB4XDTAwMDEwMTAwMDAwMFoXDTQ5MTIz +MTIzNTk1OVowJTEjMCEGA1UEAwwad29sZlNTTCBDaGFpbiBUZXN0IEFsdCBFbmQw +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC0R/M+x1r1rHnuCnfULuKe +PegFtQ13FmEE3skKXksx1xS49WWaDm/qBzRsv2f/XtB5S/MpNvla/V0XJ6ot0hH/ +ZzJbewINOfSJ4n9n83cmvN6upSt1MlXDl5YJ4Ap4GfMBKFtxNwisyE/g7Wjw14HH +TCMctP4HtssnwjhmgiQ4AWsZaRD0eOUlLzR8SUDaAi6l1W9EGvBVJGpzmFv3zhT2 +7VPDmtIwV9P1BdBXxhTY3NVSXEM8QdGZYmtUbW+1s1wmpLQA+XVVFuEdTzm0K2Fq +U1HzDwbLTp0ilN4MD4kH2ypwc32yzn1oAhVCulysNZYBZC/9z67nMQIWTUZcsowj +AgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1Ud +DgQWBBTwWguQFesj/Hc4vOQnO1RuB4pNvjAfBgNVHSMEGDAWgBSeiHzDRimUgflm +mGWL3evrEbqzWzANBgkqhkiG9w0BAQsFAAOCAQEAupEqyYgrL8PUIaj1m8x1GQ8I +MncaPw2PD+ysKXoLJ3V1yFggl4G/A57ypMkkptTxbfVpz6rKlZ3d3WbBvxBjc/ip +hUD42AkCExs+rICy08e3SsWDuYKAtH2VHzj0j9QgsXsE01v0xGp+icBKA5VTVr+X +2kOFCQd3qDYG5B0XQnhV4itDiyt+c/jOXewGgEAfsT73Jykgu96AbbacYObE5yLM +bMDcle82xKUSysKjE/zj5H/FXy0HEUXW0YGdDbeK78va6eWBhwZBaHCiAfMiJ1ym +FAoXB6Bn+fkEC+GJM7wk1hR2iaqV3Ee3eOnf4zgifr9zmOO7gdFRiOAGlCkn7g== +-----END CERTIFICATE----- diff --git a/certs/intermediate/trust_anchor/alt-end-int-cert.pem b/certs/intermediate/trust_anchor/alt-end-int-cert.pem new file mode 100644 index 00000000000..f1aace8bdc0 --- /dev/null +++ b/certs/intermediate/trust_anchor/alt-end-int-cert.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDKTCCAhGgAwIBAgICECswDQYJKoZIhvcNAQELBQAwJTEjMCEGA1UEAwwad29s +ZlNTTCBDaGFpbiBUZXN0IEFsdCBFbmQwHhcNMDAwMTAxMDAwMDAwWhcNNDkxMjMx +MjM1OTU5WjAlMSMwIQYDVQQDDBp3b2xmU1NMIENoYWluIFRlc3QgQWx0IEludDCC +ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMPLZLmN98lunvgtkdop0AxZ +GCYqpdXRitby2Nfc09x9ZAoEOthKr0KRb5joQ6VyXOdZ6o+fa+gpiEsJV6SKol92 +CSgMo58VI11gF+9jlVGUFoSJ6hMGeCnAzB+iGEIkEDGKG4mfWzuDaTKaWncXOAH8 +imQ1cvjWuNeEV303+vSPtSXopdWlJL7hXHr+bBC6htiPqgfKC/AZoq8Hj2OWOp5U +IbvObU30fKEZkJST+rXavIqS6IQbUHfbYKH+fLePwTEEIQDaOmQIaVoH2daDcDNx +KHtY3lIZnsklmsDEFcRAzkfTEKgVVrHwiketr2siMTWeKwVD/pXA0GlhFQGH5UkC +AwEAAaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0O +BBYEFCwYox/xByzjdVH1K2RqtdVrXLEsMB8GA1UdIwQYMBaAFPBaC5AV6yP8dzi8 +5Cc7VG4Hik2+MA0GCSqGSIb3DQEBCwUAA4IBAQALYSEv93V84F3FOMMeHASBs24V +n5bMlVmdoCflL4W4g4jIYRWNdcTe+LZ91xb9nMtaUDzcoflo6m/2SetC8Nj01cMP +gH6w4Iw+5XVgRrVGx5gnQhkht7/Tb2JBM1vzWLhe5HYL9TAbrESsdIJRgDVQF9GA +Pm4u8i7EbxCKCZDUzeTZ0rVB3o+x17nq2Ui4hlbBRZ0Dgrct8THCgzHJPxHx7yPQ +8kRcuVkukNBxcEzYoRwoxLi2jIUrmhxPL/kptL0wxqcPrBHUDEUtAi5t0ut0c/wF +2uCdnY1usXnI5r4ByU4fWfWGL8twlDj0kVkVi0cpp7pIOhZ5pHUeecfr60g2 +-----END CERTIFICATE----- diff --git a/certs/intermediate/trust_anchor/alt-int-cert.pem b/certs/intermediate/trust_anchor/alt-int-cert.pem new file mode 100644 index 00000000000..eb218e15ebd --- /dev/null +++ b/certs/intermediate/trust_anchor/alt-int-cert.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDKjCCAhKgAwIBAgICECgwDQYJKoZIhvcNAQELBQAwJjEkMCIGA1UEAwwbd29s +ZlNTTCBDaGFpbiBUZXN0IEFsdCBSb290MB4XDTIwMDEwMTAwMDAwMFoXDTQ5MTIz +MTIzNTk1OVowJTEjMCEGA1UEAwwad29sZlNTTCBDaGFpbiBUZXN0IEFsdCBJbnQw +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDDy2S5jffJbp74LZHaKdAM +WRgmKqXV0YrW8tjX3NPcfWQKBDrYSq9CkW+Y6EOlclznWeqPn2voKYhLCVekiqJf +dgkoDKOfFSNdYBfvY5VRlBaEieoTBngpwMwfohhCJBAxihuJn1s7g2kymlp3FzgB +/IpkNXL41rjXhFd9N/r0j7Ul6KXVpSS+4Vx6/mwQuobYj6oHygvwGaKvB49jljqe +VCG7zm1N9HyhGZCUk/q12ryKkuiEG1B322Ch/ny3j8ExBCEA2jpkCGlaB9nWg3Az +cSh7WN5SGZ7JJZrAxBXEQM5H0xCoFVax8IpHra9rIjE1nisFQ/6VwNBpYRUBh+VJ +AgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1Ud +DgQWBBQsGKMf8Qcs43VR9StkarXVa1yxLDAfBgNVHSMEGDAWgBTXAZX2sreufynj +oPuU8EYr27E2IDANBgkqhkiG9w0BAQsFAAOCAQEALty2RFqt4BofP13PZlxs9M1G +njE3ZZ5opUWHN/Ow/AzMKUvSdsHgQHvYEJpITS8BfFUxxMP+iRlO/GGry5xv0oDQ +CRPADPaW+t28olIsqMTnJ6/0Ftgb4UIVV+8qEHe8uWzq+6no3jKYmx8C1+VpHM9x +Sh6nKpE2i/dsHG5mc7Qgu38uaBLTrGjTaNaF1CXus8HqGrdVXGhSQD2bVBHq5Vy0 +j4pJY9sOSH8WA9SdjzZO4MBRDkOehSHjoaerxXs8BKWK3AycR6wsvwkodpJXheZO +TMVq4qZwKApNnmYPR8Kmk6smpBJLpdc4zc75Uh/rFSLYrfPUjk4PtirdM4m80g== +-----END CERTIFICATE----- diff --git a/certs/intermediate/trust_anchor/alt-int-leaf-cert.pem b/certs/intermediate/trust_anchor/alt-int-leaf-cert.pem new file mode 100644 index 00000000000..50370584eca --- /dev/null +++ b/certs/intermediate/trust_anchor/alt-int-leaf-cert.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDKzCCAhOgAwIBAgICEC4wDQYJKoZIhvcNAQELBQAwJTEjMCEGA1UEAwwad29s +ZlNTTCBDaGFpbiBUZXN0IEFsdCBJbnQwHhcNMDAwMTAxMDAwMDAwWhcNNDkxMjMx +MjM1OTU5WjAqMSgwJgYDVQQDDB93b2xmU1NMIENoYWluIFRlc3QgQWx0IEludCBM +ZWFmMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlzgYcPXTl41ocGCq +vrl5rK4S6MmkQG8oSRihk3Yfy9axvXYY46Xi97XZjI7SngT+x9SMNFuqGvp+Kq9D ++boEBU6UlYOR21Y6aK3qRCzZT/N/hITB+0qXX7Rf59dNfxz99SKfbP7v3SHU8zuN +uMI25+4cLzleREHV1E2vGgpUXJIhdmdYdK+8azbLdJb3kp3bpPZJTaI8zyKYgeF6 +0w+i2RhPVgZ3k5hhUgaYqIHwDAWU3fgJ2lqA0X8SPY99C7odTqXahcpfZOkbq7Sp +mcPgKeczRcr8IGVle3z1TJgmB8vtJYO0Hot09dI0N/5eUJz7uKxTlt6bZpBDc3Nc +s1kIAQIDAQABo2AwXjAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIHgDAdBgNV +HQ4EFgQUnOwtwEg/u+zfuBIvIpGm3jdZbRUwHwYDVR0jBBgwFoAULBijH/EHLON1 +UfUrZGq11WtcsSwwDQYJKoZIhvcNAQELBQADggEBABlQWOjnG1ghCNVoGlHLude7 +4OG6hdTsbyQIKcr8/Y0Qa6SnrNYGbZ779ptNVavJxUaGiptY/m4t4wHk2mUl2Jw3 +qvXEald1uBCl1z7Az3GhoKqLa7y84NNh9lS6BrqoFy5o92O7mZsGp4vqfawWzDwy +y4190nawLc9UXloaoXEwnlsAzmvmK7YJMGaKN59d25/JBHDIuHR29tcqxsrlCoH+ +flc099l5YOWJp9v2+GoJ/jvYzKVmJqLSck5tU4FJbnyvghdrgMV78y67qh5kuOOv ++CZxSJVssxasHaYsq5JDybdaeP5zlLKka82bRg77u3knKnKZkM7slFiqe7nm9hk= +-----END CERTIFICATE----- diff --git a/certs/intermediate/trust_anchor/alt-notca-int-cert.pem b/certs/intermediate/trust_anchor/alt-notca-int-cert.pem new file mode 100644 index 00000000000..dd55b58a66a --- /dev/null +++ b/certs/intermediate/trust_anchor/alt-notca-int-cert.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDFjCCAf6gAwIBAgICEC0wDQYJKoZIhvcNAQELBQAwJTEjMCEGA1UEAwwad29s +ZlNTTCBDaGFpbiBUZXN0IEFsdCBFbmQwHhcNMDAwMTAxMDAwMDAwWhcNNDkxMjMx +MjM1OTU5WjAlMSMwIQYDVQQDDBp3b2xmU1NMIENoYWluIFRlc3QgQWx0IEludDCC +ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMPLZLmN98lunvgtkdop0AxZ +GCYqpdXRitby2Nfc09x9ZAoEOthKr0KRb5joQ6VyXOdZ6o+fa+gpiEsJV6SKol92 +CSgMo58VI11gF+9jlVGUFoSJ6hMGeCnAzB+iGEIkEDGKG4mfWzuDaTKaWncXOAH8 +imQ1cvjWuNeEV303+vSPtSXopdWlJL7hXHr+bBC6htiPqgfKC/AZoq8Hj2OWOp5U +IbvObU30fKEZkJST+rXavIqS6IQbUHfbYKH+fLePwTEEIQDaOmQIaVoH2daDcDNx +KHtY3lIZnsklmsDEFcRAzkfTEKgVVrHwiketr2siMTWeKwVD/pXA0GlhFQGH5UkC +AwEAAaNQME4wDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQULBijH/EHLON1UfUrZGq1 +1WtcsSwwHwYDVR0jBBgwFoAU8FoLkBXrI/x3OLzkJztUbgeKTb4wDQYJKoZIhvcN +AQELBQADggEBAJWdRLg+BBQC7lJwUNBuskWiNB6jtG4/TGwIauOFNbICaLgOZ9rG +s3Fw+P530sVJqFmJFBZAB9jLxh11Ae3nx3zaZnPdfCYlNelrob3LNb3SJq9nk6cD +eGx4g0RA+TWMDsOgVyI1SyzesJ2L5XfK/rxPKDWB5YmKeBMiSJuy7EluRVl3k5R8 +cwclRhk/AyTMp5d2TWlCsJCW+sgzkAW0WDw8MyjFYpKMvKFq8RY2ofvdKHjmB7sw +0L3a4pgw2Xi/h2o+A/5g0Jg2dtGQdsn9Wuz0gXd66ln9QABSxQy7CEzamzfFk/hq +i/nKTvNW7Ah1g9a/ZhhZd5/tIMEbV7Ybfwo= +-----END CERTIFICATE----- diff --git a/certs/intermediate/trust_anchor/alt-old-int-cert.pem b/certs/intermediate/trust_anchor/alt-old-int-cert.pem new file mode 100644 index 00000000000..676810cb6c8 --- /dev/null +++ b/certs/intermediate/trust_anchor/alt-old-int-cert.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDKTCCAhGgAwIBAgICECwwDQYJKoZIhvcNAQELBQAwJTEjMCEGA1UEAwwad29s +ZlNTTCBDaGFpbiBUZXN0IEFsdCBFbmQwHhcNMTAwMTAxMDAwMDAwWhcNMTkxMjMx +MjM1OTU5WjAlMSMwIQYDVQQDDBp3b2xmU1NMIENoYWluIFRlc3QgQWx0IEludDCC +ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMPLZLmN98lunvgtkdop0AxZ +GCYqpdXRitby2Nfc09x9ZAoEOthKr0KRb5joQ6VyXOdZ6o+fa+gpiEsJV6SKol92 +CSgMo58VI11gF+9jlVGUFoSJ6hMGeCnAzB+iGEIkEDGKG4mfWzuDaTKaWncXOAH8 +imQ1cvjWuNeEV303+vSPtSXopdWlJL7hXHr+bBC6htiPqgfKC/AZoq8Hj2OWOp5U +IbvObU30fKEZkJST+rXavIqS6IQbUHfbYKH+fLePwTEEIQDaOmQIaVoH2daDcDNx +KHtY3lIZnsklmsDEFcRAzkfTEKgVVrHwiketr2siMTWeKwVD/pXA0GlhFQGH5UkC +AwEAAaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0O +BBYEFCwYox/xByzjdVH1K2RqtdVrXLEsMB8GA1UdIwQYMBaAFPBaC5AV6yP8dzi8 +5Cc7VG4Hik2+MA0GCSqGSIb3DQEBCwUAA4IBAQAivwDYufI9NPnh+tbbMxGVmW9n +W229A60501HiILp6rYTb3naTzLak0M2fr7BBSgO2vctIWdMlavy16jitgKrCQbsp +KjDLMSeWmYUAKEG5Z9qK74Sg+ONubUhLq8sUV8TRyHE+KufBmhym6mdWUFgdy7ze +UJBKUj6K2UpKkr2/6hYQ7aQ9XvhjDK/z6ZrJJLb7HaoMsT8D7YCc1ZQ7hXvnT5Gj +/IRs8U/13ERoe4vc+BuFWy+HgGjqvplsjUlHVjyGQ6hKWPhWBCja/dX35L7nrX8f +tBkoqCuVEhExIgyEB3QcgnTwlJGyGsybnJ7wRSNDgvf1Qc5Xt/N+mw0T++6K +-----END CERTIFICATE----- diff --git a/certs/intermediate/trust_anchor/alt-root-cert.pem b/certs/intermediate/trust_anchor/alt-root-cert.pem new file mode 100644 index 00000000000..c54c4abccb0 --- /dev/null +++ b/certs/intermediate/trust_anchor/alt-root-cert.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDKzCCAhOgAwIBAgICECcwDQYJKoZIhvcNAQELBQAwJjEkMCIGA1UEAwwbd29s +ZlNTTCBDaGFpbiBUZXN0IEFsdCBSb290MB4XDTAwMDEwMTAwMDAwMFoXDTQ5MTIz +MTIzNTk1OVowJjEkMCIGA1UEAwwbd29sZlNTTCBDaGFpbiBUZXN0IEFsdCBSb290 +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAm1+XGBogLAYryEqy6HN9 +zFSvSijycHR+dQjjFQg2xMabOaFTGJs5e2iV1VSDxSsn/6dgaexpnc0ozlPt94wc +Ldo3NVl5aSSZe9o2tMCeUeiJTaPcUW6yIjDe31WuIkEZrs/urRVo1c6nqw9v0ibC +hrOlYIKmuXxTaEbTjuEDigoG/B9g2WgM5ZjyQgA+h+JdfzWhnkMNc9aQcA/nw+kN +uH6sqcyWh02zZHMT2A0iMYs6n5pCNg3/NG6eMosVLcogfF1hqCY5wufaBH8AsAUX +2q4kbqlrryK1nj7s7PXNxbFV6xMI1hGFY1NtxHIP9nzOHH+cNBbbl1UpBxgpuv9c +dQIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNV +HQ4EFgQU1wGV9rK3rn8p46D7lPBGK9uxNiAwHwYDVR0jBBgwFoAU1wGV9rK3rn8p +46D7lPBGK9uxNiAwDQYJKoZIhvcNAQELBQADggEBAFz6HHnOa8sYuZ4tGXuZmn+9 +tt5CuEXtUeQvq6Mmo4C/QELZBCiPvcgorgVQKqGewFxG181KwOS5sPE0D/tASChQ +EgK0C2Tu+rgZz02Pw42XxlewEcQhrSkI6bj8D00SHoz6W/1y47YzqQ2dWJuNafaR +8xLGXF1QqSBeAv3b1mpalwgWb+aEZUUx7JiiSocLV7vRxEGiYQLhbre/QKluNHcr +l22WhLN8N9ko9MaOYjKiZchXh2ZvhlN+4NVk1Qv2ptdYCuuMBLkCqErqM1P4LIPP +B3bSkrfrYKeAqI7En13HxeF/I1F99tszZP7rMP2nBN0LOKK8JXPKp4TtAmgoPMg= +-----END CERTIFICATE----- diff --git a/certs/intermediate/trust_anchor/badkid-int-cert.pem b/certs/intermediate/trust_anchor/badkid-int-cert.pem new file mode 100644 index 00000000000..32b279a410e --- /dev/null +++ b/certs/intermediate/trust_anchor/badkid-int-cert.pem @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDODCCAiCgAwIBAgICEBUwDQYJKoZIhvcNAQELBQAwLDEqMCgGA1UEAwwhd29s +ZlNTTCBDaGFpbiBUZXN0IE5vIEtleSBJZCBSb290MB4XDTEwMDEwMTAwMDAwMFoX +DTE5MTIzMTIzNTk1OVowLDEqMCgGA1UEAwwhd29sZlNTTCBDaGFpbiBUZXN0IEJh +ZCBLZXkgSWQgSW50MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuYrr +jf6T4u1hnB0WVdiwrNb8DNzgB6tXPIug+HIjCfkLIdS/MZ4c1vFYhJskUtjyntd7 +zFCNjevYpEDa0kNS4hQ8FvgnJCeC5N9lJsA6sM+9juIKLcKsrzDv0g/AVfRCKqIv +Qynkmo3xD5aoFqdTnE992yWJX74ddaJqtI6ZZs0lTx/nE75V+Kvx/7iYS9O2CqmF +2uHD/vKYrieBgNZJMyzyoEtv/nH2asLoajdYGWW7dywUuv5TZrfUgYKVUwmdtVjl +NkheF2oPJXVTf3z2OaSZnyWogvsQCeGm7M2USTx4ADZ84XSFc9RrCC6M/eQIXKb+ +jjJ3hQz5bmr8eFd2EwIDAQABo2QwYjAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB +/wQEAwIBBjAdBgNVHQ4EFgQUqgX9IQlebBX8oDLxDtw5f4iCZcIwIAYDVR0jBBkw +FoAUAQEBAQEBAQEBAQEBAQEBAQEBAQEBMA0GCSqGSIb3DQEBCwUAA4IBAQAS400N +MC2CTRYSYPYvCN0RrJ/3dH81ONZ8mN5oWV+QO7c2TSEAw+fKMHDVVLnaYMZMMTqz +RHR2nyEBgO+eaqr+CcfSdbEG9kM8WsTWcwqzrZmD5IYQoLN73CNPqtTuRhVX3/gv +NJOwx0Z6xAnLNpCI17OHWJRC/YESNFeW/KmErid018Dw1x5mBqBeDGWp9okfZNuf +WNxU0GxuZchHm6EtnsLTRgqAk7oNXregAkughNXp75magxxv6g77NCmPUBBU50pc +Uabg+xnlBXOE1ZzdNcO26Gb+DloQXlC0vB+1O3rF7UPc13wqcYSTIcWBYyiMOpAL +77GJ56lxmwVMUSvF +-----END CERTIFICATE----- diff --git a/certs/intermediate/trust_anchor/badkid-int-leaf-cert.pem b/certs/intermediate/trust_anchor/badkid-int-leaf-cert.pem new file mode 100644 index 00000000000..d5323b6e10b --- /dev/null +++ b/certs/intermediate/trust_anchor/badkid-int-leaf-cert.pem @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDOTCCAiGgAwIBAgICEBYwDQYJKoZIhvcNAQELBQAwLDEqMCgGA1UEAwwhd29s +ZlNTTCBDaGFpbiBUZXN0IEJhZCBLZXkgSWQgSW50MB4XDTAwMDEwMTAwMDAwMFoX +DTQ5MTIzMTIzNTk1OVowMTEvMC0GA1UEAwwmd29sZlNTTCBDaGFpbiBUZXN0IEJh +ZCBLZXkgSWQgSW50IExlYWYwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB +AQDA3idXOiKA8cPeDYbow0+DJrJ+T08L3Td+mM8yHqVKoH++RFenQI+j4sMXXy0y +Yn0mRSTozBNZwrWTpJFpOOqwJ12bMsARoZmJI1Rg3mgo4XWQfIz6MuMLAfy2uWfw +4dX6l1VlbrWtzmBo+++kY0Yu0Q//3aQTTDVX4PXjXNfkjJKtCU7GZTobJcub2A2g +eVhZ+O8BlNmOEylnvEYh5rQ2pkPhAnZQCX9DkX9wX3kj9nE1s5+8MsPdiTcJowly +wkw3OuF06ZuvpLVjL9XxmQ5Naju0tvlPdRIYqIFMdKW/6Vj4I/5S0p1t6nfEu5Vz +qG9E6B38hmVWgswza6vjZx4LAgMBAAGjYDBeMAwGA1UdEwEB/wQCMAAwDgYDVR0P +AQH/BAQDAgeAMB0GA1UdDgQWBBRqgHxv9d/A7yClcJsTIeaFLW5ezDAfBgNVHSME +GDAWgBSqBf0hCV5sFfygMvEO3Dl/iIJlwjANBgkqhkiG9w0BAQsFAAOCAQEAe5L6 +0ZLpwz+7wml/O73HCLaTSN6UkgXBbNJG4WFvGy75+gD4UH3bh+Uf5BN7QD7qmjDL +9tXnInm7V+hOuRLuAgJO8vBQXgzzgXJLdYOjoT4Q0ZgTBp6p21fqysvL5Vz0COTj +MxfHQLDUE59q+Ou7ZhQrp7OlavVkhLVjgdQscu7zZtvuArBlcxEDiyUq4obV4TcL +IGey1UK5w+vAmSvcnFCjqKMOQKFFqcI1gMaf5lNEL6nNfhKo0zHFyP6bdtkcycu7 +gNBpN6IhuPIEj4jn5/TlmhDC4VWwzW5+Rffqtl0rPy4uqERPQ/bR/xbR85krg2eP +pate3ClBuo4pSAbRbg== +-----END CERTIFICATE----- diff --git a/certs/intermediate/trust_anchor/cross-root-cert.pem b/certs/intermediate/trust_anchor/cross-root-cert.pem new file mode 100644 index 00000000000..35f90e664ab --- /dev/null +++ b/certs/intermediate/trust_anchor/cross-root-cert.pem @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDMTCCAhmgAwIBAgICEAowDQYJKoZIhvcNAQELBQAwKjEoMCYGA1UEAwwfd29s +ZlNTTCBDaGFpbiBUZXN0IEV4cGlyZWQgUm9vdDAeFw0wMDAxMDEwMDAwMDBaFw00 +OTEyMzEyMzU5NTlaMCgxJjAkBgNVBAMMHXdvbGZTU0wgQ2hhaW4gVGVzdCBEYXRl +ZCBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAkyIXJjCUUogh +c8/PFpl/DcSCAHV25ZJcc6t2MP4sXfETh438ARFhHuntg+OZY1laZr7ztICqYz46 +fmR+l1WtH7UWkXDwApJr0Z2HsinXNg3qrPEdhS8UZfgiSEXDQRmE4WEdnCMSyQh2 +lBsKkwZtSizrv6D9Esx834e6n8auliTH9flg80c7DKOsubAj/pTp+viQuq4oMELn +6ooNtEomLBIUJn2C9YyajpOrKcDsdTWluiZrp9vBcmI8CR+C7ih9qtGhgzTSDBOC +etqJsVr8jHYz7A51vbk5d2fjazF+beyW6rkQZzNCR1n7d2toegvJ+3cQCzxanQFd +Cg1fiMOR9wIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB +BjAdBgNVHQ4EFgQUq3L7oqCxjNUZzyU91WHWyywepD8wHwYDVR0jBBgwFoAUrbh4 +8JovJ9q46nBja5XO+doYc/YwDQYJKoZIhvcNAQELBQADggEBAA2QE72+Kj1hBtqU +0VCuEKGcx5ZPPmigjqUUr+uiGss7rGIwIIFNWnlHHgISMR4WcAFeogFrT8lB1c7e +kHgkZ46cHCu3t9nXEKJuA8h5kLDtDjTvZCmv9p9Sl4hnXYCCwe3Rvl4XP+dqWIU/ +QxeurRH61AF/I34Wlqa6PMcFe/vD9jr7dwjFe+gRsESQ2Bc+7XzHH2Wf9LRomXRo +z6UiyrWNGkJooT2fEtnln2ZXJZV90TU7cZS5Wn7xYcZ478aPh61XE63/nOFASVk8 +7LwAAYjY+i3zV7MkcmzK/yk0cVz1U6wUUSbKoC1NG7tb6/bUoRYuAv1FYdufRLCZ +hO8uYNM= +-----END CERTIFICATE----- diff --git a/certs/intermediate/trust_anchor/cross-root-late-cert.pem b/certs/intermediate/trust_anchor/cross-root-late-cert.pem new file mode 100644 index 00000000000..f251d0aa36f --- /dev/null +++ b/certs/intermediate/trust_anchor/cross-root-late-cert.pem @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDMTCCAhmgAwIBAgICEBAwDQYJKoZIhvcNAQELBQAwKjEoMCYGA1UEAwwfd29s +ZlNTTCBDaGFpbiBUZXN0IEV4cGlyZWQgUm9vdDAeFw0yMDAxMDEwMDAwMDBaFw00 +OTEyMzEyMzU5NTlaMCgxJjAkBgNVBAMMHXdvbGZTU0wgQ2hhaW4gVGVzdCBEYXRl +ZCBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAkyIXJjCUUogh +c8/PFpl/DcSCAHV25ZJcc6t2MP4sXfETh438ARFhHuntg+OZY1laZr7ztICqYz46 +fmR+l1WtH7UWkXDwApJr0Z2HsinXNg3qrPEdhS8UZfgiSEXDQRmE4WEdnCMSyQh2 +lBsKkwZtSizrv6D9Esx834e6n8auliTH9flg80c7DKOsubAj/pTp+viQuq4oMELn +6ooNtEomLBIUJn2C9YyajpOrKcDsdTWluiZrp9vBcmI8CR+C7ih9qtGhgzTSDBOC +etqJsVr8jHYz7A51vbk5d2fjazF+beyW6rkQZzNCR1n7d2toegvJ+3cQCzxanQFd +Cg1fiMOR9wIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB +BjAdBgNVHQ4EFgQUq3L7oqCxjNUZzyU91WHWyywepD8wHwYDVR0jBBgwFoAUrbh4 +8JovJ9q46nBja5XO+doYc/YwDQYJKoZIhvcNAQELBQADggEBAJxU9slBGgAZUud5 +wTs0ehd8IM4hN8S+vI5fQHRP7aWM3QXQlhK5PWCsYi12SbscMTRPvp2JfxV4OmC0 +vn+f7FIS90aMXO6S3P4RFg8xStK9mpuKEzElf8q3MylUil6RqlaiI+YLAg0OiGAJ +2DzNifRHzpOPE/I13ZFYylRwN0917h3SXtd89lVjMa8mumU9SeLcICtz5hSnWBzS +rEfZ2UYsAU9TCftKhS2wIQOAbDwQV+TdEWe+WWXTeFPsxbOb/3qE0mN1duNX4OKu +QvnXNY8ioSzAc9GTAzJjUZTUVj+3tfKAj9uiEpjtgo4UhVOn497Yqdg6TFhnJDmx +M3R0KrE= +-----END CERTIFICATE----- diff --git a/certs/intermediate/trust_anchor/dated-int-cert.pem b/certs/intermediate/trust_anchor/dated-int-cert.pem new file mode 100644 index 00000000000..9f18773db6e --- /dev/null +++ b/certs/intermediate/trust_anchor/dated-int-cert.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDKDCCAhCgAwIBAgICEAQwDQYJKoZIhvcNAQELBQAwKDEmMCQGA1UEAwwdd29s +ZlNTTCBDaGFpbiBUZXN0IERhdGVkIFJvb3QwHhcNMDAwMTAxMDAwMDAwWhcNNDkx +MjMxMjM1OTU5WjAhMR8wHQYDVQQDDBZ3b2xmU1NMIENoYWluIFRlc3QgSW50MIIB +IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAra+hiNAhh+tgSmzi28PUj7lN +lDCepHySkrkxGgX57yCgl/KgqA4tyEA9hJLf+KyEnjIyRSF/Nnd6UbvBs1dNVy1a +gIItjegWjuGnKbI1ABw760zTPm3+Kx1FVhcKXf9mFkzX7cqMS+0p0AgrJSv1Zz0J +sgRbri7DjFMOPBUWUfOgLkKULFhQAKY5qBofI6HrFKwe9T7OWDCX241AYYlqbT7K +XSegW15DumEtqaXvSd88uvix0IyUsrQRWllx1eaCmn1Mj2qs1RMbis9vT5fPYcoO +TMDRL5agTLEqFJ549mGHw+4mkf8XZ5oKM3Dwk6niAaNLMYJQkTzsl/cRS5cfpQID +AQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4E +FgQUzVh0dmMhuFJUE1ifqEQ7BrarTs0wHwYDVR0jBBgwFoAUq3L7oqCxjNUZzyU9 +1WHWyywepD8wDQYJKoZIhvcNAQELBQADggEBAHMsWLzf77EBf7/gqFYh2fqc9pmg +uuuyIarzcn1v+rXlDtBDNEnEcnIX7bbu0S38AzMeODlbpM0rQL8dYUdXZ4Ypqzup +2+jb+1VFaWDnp99AEGLQ4lIS01roP4JocMXPx3HydoMzKs9GnyxTlcyftSW+G/CL +DLO8drM5X3uQ0eG/YsUe0pa7GWFo9ZEJGVkdMSlFeSkEOPW7cihsFD+4kIaOJ0vd +HnNZkvnhHXp4lRfNL/a9xHhuOB8yX/Z4ov4kwlArneCVphn0bbMjJEqBmQrEawFE +jFLPT7010TRg/3qRf2i0LTRvohAq5b36y8RNBA7x2z3T0ssP8jrcVKB/ibE= +-----END CERTIFICATE----- diff --git a/certs/intermediate/trust_anchor/dated-int-leaf-cert.pem b/certs/intermediate/trust_anchor/dated-int-leaf-cert.pem new file mode 100644 index 00000000000..29e7cb7e880 --- /dev/null +++ b/certs/intermediate/trust_anchor/dated-int-leaf-cert.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDIzCCAgugAwIBAgICEAUwDQYJKoZIhvcNAQELBQAwITEfMB0GA1UEAwwWd29s +ZlNTTCBDaGFpbiBUZXN0IEludDAeFw0wMDAxMDEwMDAwMDBaFw00OTEyMzEyMzU5 +NTlaMCYxJDAiBgNVBAMMG3dvbGZTU0wgQ2hhaW4gVGVzdCBJbnQgTGVhZjCCASIw +DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMDeJ1c6IoDxw94NhujDT4Mmsn5P +TwvdN36YzzIepUqgf75EV6dAj6PiwxdfLTJifSZFJOjME1nCtZOkkWk46rAnXZsy +wBGhmYkjVGDeaCjhdZB8jPoy4wsB/La5Z/Dh1fqXVWVuta3OYGj776RjRi7RD//d +pBNMNVfg9eNc1+SMkq0JTsZlOhsly5vYDaB5WFn47wGU2Y4TKWe8RiHmtDamQ+EC +dlAJf0ORf3BfeSP2cTWzn7wyw92JNwmjCXLCTDc64XTpm6+ktWMv1fGZDk1qO7S2 ++U91EhiogUx0pb/pWPgj/lLSnW3qd8S7lXOob0ToHfyGZVaCzDNrq+NnHgsCAwEA +AaNgMF4wDAYDVR0TAQH/BAIwADAOBgNVHQ8BAf8EBAMCB4AwHQYDVR0OBBYEFGqA +fG/138DvIKVwmxMh5oUtbl7MMB8GA1UdIwQYMBaAFM1YdHZjIbhSVBNYn6hEOwa2 +q07NMA0GCSqGSIb3DQEBCwUAA4IBAQBtvAMkUZ8lUc4Y1GzxlQSJTYYNmb9T+WtI +JpYro++9xu96zq/h1mxuZhfS1+L1cVpxnfSPhsmVpAyeIrXLiDhUrq1zCqFkWcLa +cighqsRc7vsurkYWSi6qVVJQ0whULg3I9h82hFrqDZZMGH6TkkoD3+bU/h53kdxT +cmS6pOhLLXbutcj9dRJv0O4b9JlcmmV58Ba9vG5Fr5tA2iDfvZhLLvZ0i/Me6RDN +XfmCmdyJG28Ws+0DGaXeb6oa2ODVc4EOyYptxgL5rLPxjjhqAJwCeIdK2T7dtWVz +tsg3Vyqt0XhiY+YH/ItGQjvWERN7fXdr083XogCsXCtZUEoQTJ44 +-----END CERTIFICATE----- diff --git a/certs/intermediate/trust_anchor/dated-root-cert.pem b/certs/intermediate/trust_anchor/dated-root-cert.pem new file mode 100644 index 00000000000..13ac16267f1 --- /dev/null +++ b/certs/intermediate/trust_anchor/dated-root-cert.pem @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDLzCCAhegAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwKDEmMCQGA1UEAwwdd29s +ZlNTTCBDaGFpbiBUZXN0IERhdGVkIFJvb3QwHhcNMDAwMTAxMDAwMDAwWhcNNDkx +MjMxMjM1OTU5WjAoMSYwJAYDVQQDDB13b2xmU1NMIENoYWluIFRlc3QgRGF0ZWQg +Um9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJMiFyYwlFKIIXPP +zxaZfw3EggB1duWSXHOrdjD+LF3xE4eN/AERYR7p7YPjmWNZWma+87SAqmM+On5k +fpdVrR+1FpFw8AKSa9Gdh7Ip1zYN6qzxHYUvFGX4IkhFw0EZhOFhHZwjEskIdpQb +CpMGbUos67+g/RLMfN+Hup/GrpYkx/X5YPNHOwyjrLmwI/6U6fr4kLquKDBC5+qK +DbRKJiwSFCZ9gvWMmo6TqynA7HU1pboma6fbwXJiPAkfgu4ofarRoYM00gwTgnra +ibFa/Ix2M+wOdb25OXdn42sxfm3sluq5EGczQkdZ+3draHoLyft3EAs8Wp0BXQoN +X4jDkfcCAwEAAaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYw +HQYDVR0OBBYEFKty+6KgsYzVGc8lPdVh1sssHqQ/MB8GA1UdIwQYMBaAFKty+6Kg +sYzVGc8lPdVh1sssHqQ/MA0GCSqGSIb3DQEBCwUAA4IBAQBctW6m089Eod0SpoGV +tCSum5vuYoEg9diziq6J23CgQpGMdVFkHdyRCK8bKAseBLfkpgVr9K5YKHKHWOEP +nPrSoA4PHPgP9lQ19rwJlnJkpEp/EF1zWpjHxhCNG6mAT7ausOTUFfzYgSrO3CQp +DSqz3SszSOVq8uzH8hWpiegpXvBqCIMibJYkpGM4MSJw+uozFcX4sVTaNmkrXu9k +mk6sgioIIU0fZjI0q8/BDSVfwJRKIcwiFN5ERYtKClZZ9+V58Js4ydFoFUh3SIOZ +q+XJvaCTvdP302a23F3nX/MCgtnZ9XDhOLKsmjy5wJEs2ANmgsEvLOcosreMcFHw +PThu +-----END CERTIFICATE----- diff --git a/certs/intermediate/trust_anchor/dated-root-crl.pem b/certs/intermediate/trust_anchor/dated-root-crl.pem new file mode 100644 index 00000000000..d9855f2a319 --- /dev/null +++ b/certs/intermediate/trust_anchor/dated-root-crl.pem @@ -0,0 +1,12 @@ +-----BEGIN X509 CRL----- +MIIBujCBowIBATANBgkqhkiG9w0BAQsFADAoMSYwJAYDVQQDDB13b2xmU1NMIENo +YWluIFRlc3QgRGF0ZWQgUm9vdBcNMDAwMTAxMDAwMDAwWhcNNDkxMjMxMjM1OTU5 +WjAVMBMCAhADFw0xMDAxMDEwMDAwMDBaoDAwLjAfBgNVHSMEGDAWgBSrcvuioLGM +1RnPJT3VYdbLLB6kPzALBgNVHRQEBAICEAIwDQYJKoZIhvcNAQELBQADggEBACYg +Zsy1i2lCi0l/oLXqFsK2o7ohSvzNIPHv0abE9g5+doUMSU+RaDAYSRWOgtTU7heb +br7UcERFoPAKygBNIw9mu8CWilcOB176CYlWrug9/+S3bS7JI2K2AUzMu3pvEEzy +dgBKxeoBGGqKb/IuHnQzsKQ5wpW4NwHqmhSxPmENiTii+j/x9l4m54L8ZYj3lL/d +WwQpkJwQYFnRqsRRoq6Zr0/0gGMcfinw6gO2WQZ51erQMCA6H8aJ7Ff7Wo67HprI +DcUCPUJDM4yuY02mAp4JKssTUjOPpu41KOuzkJWh9zMFf23Ill972a8WAi3Uqfh2 +CNhR2QrKzKdpsZSmgZY= +-----END X509 CRL----- diff --git a/certs/intermediate/trust_anchor/dated-root-empty-crl.pem b/certs/intermediate/trust_anchor/dated-root-empty-crl.pem new file mode 100644 index 00000000000..9e84f26f327 --- /dev/null +++ b/certs/intermediate/trust_anchor/dated-root-empty-crl.pem @@ -0,0 +1,11 @@ +-----BEGIN X509 CRL----- +MIIBozCBjAIBATANBgkqhkiG9w0BAQsFADAoMSYwJAYDVQQDDB13b2xmU1NMIENo +YWluIFRlc3QgRGF0ZWQgUm9vdBcNMDAwMTAxMDAwMDAwWhcNNDkxMjMxMjM1OTU5 +WqAwMC4wHwYDVR0jBBgwFoAUq3L7oqCxjNUZzyU91WHWyywepD8wCwYDVR0UBAQC +AhABMA0GCSqGSIb3DQEBCwUAA4IBAQAWNz15tEIHbXzRJxY2CTL0G4jC1HSu+5Xr +zkFFcbCoGdCKhU50bzL0w7ADu7pHUmZ9kq8+/vZc+v20zjCVPBsK7kUhPzkY4UGb +T14/tx6Kj4BBC6npCO4jW/IHfqMKpfpPwQwNij0jGtPKhGqcUhhHTfpg/92Ln18Y +ca0IgnkUzbAvRcyHJ0h2kPLnDjRYNag6t2FnWDA4PkzlC//NT7Lum12p6Ar+dJDe +6O+aXWIzDlPcClkf/Yct+39PHc4WZ250pnnYQkduSQKJ/lhtMut7uHFrCwRBMo13 +IPz7X0IWbUw6CMWm8AohkCRtiBiYz4mxAya9n0hnEYhhjjwv/Hlb +-----END X509 CRL----- diff --git a/certs/intermediate/trust_anchor/dated-root-late-cert.pem b/certs/intermediate/trust_anchor/dated-root-late-cert.pem new file mode 100644 index 00000000000..4b1564eab2e --- /dev/null +++ b/certs/intermediate/trust_anchor/dated-root-late-cert.pem @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDLzCCAhegAwIBAgICEA8wDQYJKoZIhvcNAQELBQAwKDEmMCQGA1UEAwwdd29s +ZlNTTCBDaGFpbiBUZXN0IERhdGVkIFJvb3QwHhcNMjAwMTAxMDAwMDAwWhcNNDkx +MjMxMjM1OTU5WjAoMSYwJAYDVQQDDB13b2xmU1NMIENoYWluIFRlc3QgRGF0ZWQg +Um9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJMiFyYwlFKIIXPP +zxaZfw3EggB1duWSXHOrdjD+LF3xE4eN/AERYR7p7YPjmWNZWma+87SAqmM+On5k +fpdVrR+1FpFw8AKSa9Gdh7Ip1zYN6qzxHYUvFGX4IkhFw0EZhOFhHZwjEskIdpQb +CpMGbUos67+g/RLMfN+Hup/GrpYkx/X5YPNHOwyjrLmwI/6U6fr4kLquKDBC5+qK +DbRKJiwSFCZ9gvWMmo6TqynA7HU1pboma6fbwXJiPAkfgu4ofarRoYM00gwTgnra +ibFa/Ix2M+wOdb25OXdn42sxfm3sluq5EGczQkdZ+3draHoLyft3EAs8Wp0BXQoN +X4jDkfcCAwEAAaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYw +HQYDVR0OBBYEFKty+6KgsYzVGc8lPdVh1sssHqQ/MB8GA1UdIwQYMBaAFKty+6Kg +sYzVGc8lPdVh1sssHqQ/MA0GCSqGSIb3DQEBCwUAA4IBAQBVJ6hNnV0Pk5eInSOu +9jh6kbS6mnxWMQ387Fm5PZMfYmxfwkNqOY18oabhU9WjIeGPBeKeaHfigJaBkmt4 +iq6FcTShoN0HlPK4BaYCJ7zSQVUT1O8+5WPXtp7iSEM2BrP1hifbR8MEXdPx/KbB +mNgyTRT6SbY+WTS7tCfM18GVQxrCopVZ+l7ugGBsU0vPjt8OCg5fb2GySSwlEt+L +yyreJjmhC2ChKs1ARdjBgXbCFjk446y6VNFKUqZRjak0upxjh0Ln40NM4Ex0hLFZ +0Z4NLtAxU9xMd+Oqo+JB20+cCpRYqjcb6cfjEWBVJserQabHfqc7ze76vaorLO7E +Wxbk +-----END CERTIFICATE----- diff --git a/certs/intermediate/trust_anchor/ec-name-root-cert.pem b/certs/intermediate/trust_anchor/ec-name-root-cert.pem new file mode 100644 index 00000000000..43c13c33c4f --- /dev/null +++ b/certs/intermediate/trust_anchor/ec-name-root-cert.pem @@ -0,0 +1,10 @@ +-----BEGIN CERTIFICATE----- +MIIBZzCCAQygAwIBAgIBBjAKBggqhkjOPQQDAjApMScwJQYDVQQDDB53b2xmU1NM +IFRydXN0LUFuY2hvciBUZXN0IFJvb3QwIBcNMjYxMDI0MDEyMDExWhgPMjA1NjEw +MjMwMTIwMTFaMCkxJzAlBgNVBAMMHndvbGZTU0wgVHJ1c3QtQW5jaG9yIFRlc3Qg +Um9vdDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABD1vcfxyPXSrpf+/9zrgyx33 +DPiYj/ItQjqnnoslJpa+uAWIlNEoc+EUhli3DpPLpsdomEnb252m9qeZGwrKsfOj +IzAhMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMAoGCCqGSM49BAMC +A0kAMEYCIQDAxCmKyFmUSEAx2tjI6Fw31JPc9IgbR0oQxkA4v9gcEwIhAPU6mTJo +wNj0cRmJF0K1WBtN73AkG4dooJIMeO2kknz3 +-----END CERTIFICATE----- diff --git a/certs/intermediate/trust_anchor/expired-int-cert.pem b/certs/intermediate/trust_anchor/expired-int-cert.pem new file mode 100644 index 00000000000..ffcb84e19de --- /dev/null +++ b/certs/intermediate/trust_anchor/expired-int-cert.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDKDCCAhCgAwIBAgICEAMwDQYJKoZIhvcNAQELBQAwKDEmMCQGA1UEAwwdd29s +ZlNTTCBDaGFpbiBUZXN0IERhdGVkIFJvb3QwHhcNMTAwMTAxMDAwMDAwWhcNMTkx +MjMxMjM1OTU5WjAhMR8wHQYDVQQDDBZ3b2xmU1NMIENoYWluIFRlc3QgSW50MIIB +IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAra+hiNAhh+tgSmzi28PUj7lN +lDCepHySkrkxGgX57yCgl/KgqA4tyEA9hJLf+KyEnjIyRSF/Nnd6UbvBs1dNVy1a +gIItjegWjuGnKbI1ABw760zTPm3+Kx1FVhcKXf9mFkzX7cqMS+0p0AgrJSv1Zz0J +sgRbri7DjFMOPBUWUfOgLkKULFhQAKY5qBofI6HrFKwe9T7OWDCX241AYYlqbT7K +XSegW15DumEtqaXvSd88uvix0IyUsrQRWllx1eaCmn1Mj2qs1RMbis9vT5fPYcoO +TMDRL5agTLEqFJ549mGHw+4mkf8XZ5oKM3Dwk6niAaNLMYJQkTzsl/cRS5cfpQID +AQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4E +FgQUzVh0dmMhuFJUE1ifqEQ7BrarTs0wHwYDVR0jBBgwFoAUq3L7oqCxjNUZzyU9 +1WHWyywepD8wDQYJKoZIhvcNAQELBQADggEBAE0LyOIaHUH7bl+yzSXXQy+WhteK +QsHvdzwJVliWoSPtW5Hqubko2+CCUbpwoQnWv3lZojjuvSrDKSY/UEe2unC27lND +/9YyydaB6ha+NvGPtHi/uBRPLUJAZ8IvHo75cSA1AhcJuT7vXWpj6QD8h7nd6TyV +Fz1VXa7LSjl8rrgUSoKl8VMdDlAuzDAoHJxJenS5TJi+HEUI7R3+vEjz6C+1Uzof +PS0LHJkjF4UiKyVyOh/GE4mED9oqsGS/58oZLYv+e9WRja0pLGp2L+z3cqJHS9MV +n96y+ROEVeFpB9U5eL+kDU201Yx+NzdmiBIF1MwgZnj786X9iVYETSKatzo= +-----END CERTIFICATE----- diff --git a/certs/intermediate/trust_anchor/expired-root-cert.pem b/certs/intermediate/trust_anchor/expired-root-cert.pem new file mode 100644 index 00000000000..9fd862919d0 --- /dev/null +++ b/certs/intermediate/trust_anchor/expired-root-cert.pem @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDMzCCAhugAwIBAgICEAEwDQYJKoZIhvcNAQELBQAwKjEoMCYGA1UEAwwfd29s +ZlNTTCBDaGFpbiBUZXN0IEV4cGlyZWQgUm9vdDAeFw0xMDAxMDEwMDAwMDBaFw0x +OTEyMzEyMzU5NTlaMCoxKDAmBgNVBAMMH3dvbGZTU0wgQ2hhaW4gVGVzdCBFeHBp +cmVkIFJvb3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCi7QJBMSku +R2ymR0jNsScmhj0IQtZUf/7I8HB61qAtYgmB9OEzMFIiqM4Gb8bB3JtacKZZWtwd +ha+GhMUIChn3dEenPeXapw9Skft8dPVXaIDsrumhIMHlpTH787B57xx5mcwarJER +UMel+BmOLqZCmh5kqiqMe96o05BV+X4pp3iNhaJA0Fcy2PaBkyeEZQtyHGAPnnUL +8Dr58WozbZaZnAlSWv7r3XaddXavK9TkDqqO6XXshYgn+BfE/3aMFyURNg1iqzYH +uXS5Ppt8+aP9WbwKwJG4jCitw/MKZQr9KOt7u7szypJdg78/EYBqJQY6Ly+QjHBp +FwrlLv97FJ/VAgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD +AgEGMB0GA1UdDgQWBBStuHjwmi8n2rjqcGNrlc752hhz9jAfBgNVHSMEGDAWgBSt +uHjwmi8n2rjqcGNrlc752hhz9jANBgkqhkiG9w0BAQsFAAOCAQEADQ3LXk9tFPx1 +OitF18NAJ2cTJ4ffWPrTPtTeu8iJGYOvpJg4xsIgaEINMh8sFJj0sQ4Cxq9ZmO8t +Veqk+OsgSeMU8M0MJjAWs2glWbSD23+Ltq2+h4VD2VobDlRUm7f7tSlwq3nLz6MC +JlFrHnRFjSU6Lk2YzlmRHsNggGuy8l/WtA9FXaRdL1PZQyqglYlS60OPUIru4ott +T8kouufaU2blsgUCI3Xl8vLJe6WBCMkB84PfsmRUIERcRR1pZvo6Snqs84sfPmng +MecM4p+a/JYYdyc+FMMXSL0E94hSmlFoQJGBxP/9xuxxQDjlkTb3afAhlNdQ8F8i +Vgm2c1jAJA== +-----END CERTIFICATE----- diff --git a/certs/intermediate/trust_anchor/expired-root-int-cert.pem b/certs/intermediate/trust_anchor/expired-root-int-cert.pem new file mode 100644 index 00000000000..ec363782366 --- /dev/null +++ b/certs/intermediate/trust_anchor/expired-root-int-cert.pem @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDNzCCAh+gAwIBAgICEA0wDQYJKoZIhvcNAQELBQAwKjEoMCYGA1UEAwwfd29s +ZlNTTCBDaGFpbiBUZXN0IEV4cGlyZWQgUm9vdDAeFw0wMDAxMDEwMDAwMDBaFw00 +OTEyMzEyMzU5NTlaMC4xLDAqBgNVBAMMI3dvbGZTU0wgQ2hhaW4gVGVzdCBFeHBp +cmVkIFJvb3QgSW50MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA09rV +b+2yGPF2p6A88z57ZDXxyvuYiDWW70lwzK5o7t3ANnvm/ugTxw0KNFwYcbOt8WHZ +x4FPtUxakRuc6QxZszhhD3Mth1VovBiDGulDQP6btRgZ78quCFshLoYe56ibOnPb +FzbINMglP4p7CntTbMcVCfOncklSOpYVlGL8t302E452/xmYoI90WSrp+52YI2vs +9qIh1IJfMS1hKuPgv6WN2W+jRqxK83PWkO6CadDpD8Lazk2sjxC2oc+fd+8vzugQ +6fcdOV1akA52e9/pTDtczWpQMYrJKF0/yygqQ3pSFy+KIDSLq8Iu+Js7NMNwLizT +2TLM0TohdJYTnWT7bwIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB +/wQEAwIBBjAdBgNVHQ4EFgQU/5HnTSzCFOOpgti90Q0J7HmvH2YwHwYDVR0jBBgw +FoAUrbh48JovJ9q46nBja5XO+doYc/YwDQYJKoZIhvcNAQELBQADggEBAEZ2oh9Z +dUTxAGShbXzh1EwMu790f/4Q2gb/TI0nycD3BvqRZgBYGsGEOhDj2aiMp/OiJZK7 +7TSj+atzS2Rc+7+FiRAfSIRI7d+Ysyxx6YfiKpotqsOQk0Ss5Vh1stMCLfcDl9wp +XCyyX4jI2mT41FIH9WrmrEEgSwnP3nI9+bOHNUc92eaposWa3CrplgLgF0meS/QR +Vw0Hak/IoHwXSrktMwvG024cabyIhC9bUq2ai8MvBP+wbYXSYfz7Y2/44O28b370 +UIo8eILooHiJ12Q6wVcBhbKlBXN9Js2W33f10mDMVGan73v71i9q2HWHP9xg2lxR +O+gsOO2DhUf+g0o= +-----END CERTIFICATE----- diff --git a/certs/intermediate/trust_anchor/expired-root-int-leaf-cert.pem b/certs/intermediate/trust_anchor/expired-root-int-leaf-cert.pem new file mode 100644 index 00000000000..bfd3f0a3ff8 --- /dev/null +++ b/certs/intermediate/trust_anchor/expired-root-int-leaf-cert.pem @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDPTCCAiWgAwIBAgICEA4wDQYJKoZIhvcNAQELBQAwLjEsMCoGA1UEAwwjd29s +ZlNTTCBDaGFpbiBUZXN0IEV4cGlyZWQgUm9vdCBJbnQwHhcNMDAwMTAxMDAwMDAw +WhcNNDkxMjMxMjM1OTU5WjAzMTEwLwYDVQQDDCh3b2xmU1NMIENoYWluIFRlc3Qg +RXhwaXJlZCBSb290IEludCBMZWFmMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEAwN4nVzoigPHD3g2G6MNPgyayfk9PC903fpjPMh6lSqB/vkRXp0CPo+LD +F18tMmJ9JkUk6MwTWcK1k6SRaTjqsCddmzLAEaGZiSNUYN5oKOF1kHyM+jLjCwH8 +trln8OHV+pdVZW61rc5gaPvvpGNGLtEP/92kE0w1V+D141zX5IySrQlOxmU6GyXL +m9gNoHlYWfjvAZTZjhMpZ7xGIea0NqZD4QJ2UAl/Q5F/cF95I/ZxNbOfvDLD3Yk3 +CaMJcsJMNzrhdOmbr6S1Yy/V8ZkOTWo7tLb5T3USGKiBTHSlv+lY+CP+UtKdbep3 +xLuVc6hvROgd/IZlVoLMM2ur42ceCwIDAQABo2AwXjAMBgNVHRMBAf8EAjAAMA4G +A1UdDwEB/wQEAwIHgDAdBgNVHQ4EFgQUaoB8b/XfwO8gpXCbEyHmhS1uXswwHwYD +VR0jBBgwFoAU/5HnTSzCFOOpgti90Q0J7HmvH2YwDQYJKoZIhvcNAQELBQADggEB +AGhBw/o9c9rTP1yO4RywLQ50rD1pRTRGak86JKhJenqRlhvrES8R61NMIeOmly/u +2zTqAFKx1AVnsMlQpgxhloewf+D3VRqolV+JPNfYLmxdpQkulVBCEM2D4dtwXGhQ +NQTH9uNtscJO6UeHO7w6Y19PsGUEVioL+DW4iVckSGjmEcaQuzF51KowG28GMTzs +3CJBz+2afUe41tqI4WKJHnW8V32yrBEcFCCJicxJlWrhtMllk+/PJylT/4fONvXj +Eqwx4x8fHzngcG4Az/p+Wvbe9StBPGK7CzZvtCb5SENJvlcjLObSmsRDuMNkl/iw +SLiSAZoQjFcilVAws5nVjh4= +-----END CERTIFICATE----- diff --git a/certs/intermediate/trust_anchor/expired-root-leaf-cert.pem b/certs/intermediate/trust_anchor/expired-root-leaf-cert.pem new file mode 100644 index 00000000000..28ebd6a254f --- /dev/null +++ b/certs/intermediate/trust_anchor/expired-root-leaf-cert.pem @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDNTCCAh2gAwIBAgICEAIwDQYJKoZIhvcNAQELBQAwKjEoMCYGA1UEAwwfd29s +ZlNTTCBDaGFpbiBUZXN0IEV4cGlyZWQgUm9vdDAeFw0wMDAxMDEwMDAwMDBaFw00 +OTEyMzEyMzU5NTlaMC8xLTArBgNVBAMMJHdvbGZTU0wgQ2hhaW4gVGVzdCBFeHBp +cmVkIFJvb3QgTGVhZjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMDe +J1c6IoDxw94NhujDT4Mmsn5PTwvdN36YzzIepUqgf75EV6dAj6PiwxdfLTJifSZF +JOjME1nCtZOkkWk46rAnXZsywBGhmYkjVGDeaCjhdZB8jPoy4wsB/La5Z/Dh1fqX +VWVuta3OYGj776RjRi7RD//dpBNMNVfg9eNc1+SMkq0JTsZlOhsly5vYDaB5WFn4 +7wGU2Y4TKWe8RiHmtDamQ+ECdlAJf0ORf3BfeSP2cTWzn7wyw92JNwmjCXLCTDc6 +4XTpm6+ktWMv1fGZDk1qO7S2+U91EhiogUx0pb/pWPgj/lLSnW3qd8S7lXOob0To +HfyGZVaCzDNrq+NnHgsCAwEAAaNgMF4wDAYDVR0TAQH/BAIwADAOBgNVHQ8BAf8E +BAMCB4AwHQYDVR0OBBYEFGqAfG/138DvIKVwmxMh5oUtbl7MMB8GA1UdIwQYMBaA +FK24ePCaLyfauOpwY2uVzvnaGHP2MA0GCSqGSIb3DQEBCwUAA4IBAQAce5dStM8f +P+xSlqfr/J5GOiCxk7apO95EUaM7JJoTEIwyY1BdeE/rv9HfqwN1Y2EX+WqAUKjA +yXeVj657P5SOws8rqdteHqi3fHlqYWDUwotoZ5tXKEaiNnik6HDkY/bDeWuOz1ez +hAaWypA1mSkAjo5CsUpdiEbkAN6vaqBWxqhgz8C9c/s+JiX+Po3bpd2AS2ibkauU +pChjY6zQu9K45U0M0mvb9f1qOmEwJfvdL1/NJbzUM524Ha3EX+jRb++BCtx18oxx +0SNCCDSh3hTNxahMChK8W4XT/X+tkyhrR58HYDsM5/ZOOSXhWf7n/lqZNwptvcbD +KqbAPe9ctpiE +-----END CERTIFICATE----- diff --git a/certs/intermediate/trust_anchor/expired-root-link-cert.pem b/certs/intermediate/trust_anchor/expired-root-link-cert.pem new file mode 100644 index 00000000000..d3d9abd48b5 --- /dev/null +++ b/certs/intermediate/trust_anchor/expired-root-link-cert.pem @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDMzCCAhugAwIBAgICEBEwDQYJKoZIhvcNAQELBQAwKjEoMCYGA1UEAwwfd29s +ZlNTTCBDaGFpbiBUZXN0IEV4cGlyZWQgUm9vdDAeFw0wMDAxMDEwMDAwMDBaFw00 +OTEyMzEyMzU5NTlaMCoxKDAmBgNVBAMMH3dvbGZTU0wgQ2hhaW4gVGVzdCBFeHBp +cmVkIFJvb3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCHm9mgnPTx +JhvX7NfamvCMJL3Z7e7y6IqvmfM3j2nXmut0My4cXuabc8nE5e4uPMQQfgVLNpqR +/pcPx4OX3u83GjSzfN6EWfGJq+z5HV13PrjrdleqamUSjLwZArGnwkJFprM2Ya0i +bd9qBCtlXg4Pn0ZlXTHNtFC+zEQbn7Z5HptGgsqv3sMb+ZYbsImkNGA1WyrHLBmK +Wz2fpqziek5uxMarUAt+orw/PcD9GjPkT+KazmyUQpFMGTHRPA68pD+22+PiuE7Q +dzM5GD1Qv4Y5veNP3YAuAj+YDSSD26i1DU2Bfbh9vlSMr5Gtbi7n3zDlOfhegoA3 +qxTmi3tOFUClAgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD +AgEGMB0GA1UdDgQWBBS46CSJ5Mfh5ggjcvqhdQ8WJQat1jAfBgNVHSMEGDAWgBSt +uHjwmi8n2rjqcGNrlc752hhz9jANBgkqhkiG9w0BAQsFAAOCAQEAjlC9dduzr6k3 +0obDzlLXU5BqIK0IdgVSvCzs7vYIt4lfI0LliUtdS4ScnNHodwwgocEHJCqoeQJQ +JqIycVhdKdvb1tFTY4DuW5LrKoNoNyts53wSQ2rhTZmSH2dHMbzcsPxCphMnN8UV +NStyVAgkjJPeGutltnvpUJTMoXSolm6bdyzBoNN2CLnB2PTlKVMQHZgYKniH8Z6D +Fyuo9NTHmLhG2V4G2NVmBesHKJBy5LUGs0oHSvMDVQbE1mBXc+H2jQMr5mzZRQCs +dT0jf3Z907wP5dAkYhmyGmFffbxsG2uJpQ6NWeWZlw41ETh2Ma3DUYdtukd2+wUV +/P9yqKX9Tg== +-----END CERTIFICATE----- diff --git a/certs/intermediate/trust_anchor/expired-root-link-leaf-cert.pem b/certs/intermediate/trust_anchor/expired-root-link-leaf-cert.pem new file mode 100644 index 00000000000..f689b0acacb --- /dev/null +++ b/certs/intermediate/trust_anchor/expired-root-link-leaf-cert.pem @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDOjCCAiKgAwIBAgICEBMwDQYJKoZIhvcNAQELBQAwKjEoMCYGA1UEAwwfd29s +ZlNTTCBDaGFpbiBUZXN0IEV4cGlyZWQgUm9vdDAeFw0wMDAxMDEwMDAwMDBaFw00 +OTEyMzEyMzU5NTlaMDQxMjAwBgNVBAMMKXdvbGZTU0wgQ2hhaW4gVGVzdCBFeHBp +cmVkIFJvb3QgTGluayBMZWFmMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC +AQEAwN4nVzoigPHD3g2G6MNPgyayfk9PC903fpjPMh6lSqB/vkRXp0CPo+LDF18t +MmJ9JkUk6MwTWcK1k6SRaTjqsCddmzLAEaGZiSNUYN5oKOF1kHyM+jLjCwH8trln +8OHV+pdVZW61rc5gaPvvpGNGLtEP/92kE0w1V+D141zX5IySrQlOxmU6GyXLm9gN +oHlYWfjvAZTZjhMpZ7xGIea0NqZD4QJ2UAl/Q5F/cF95I/ZxNbOfvDLD3Yk3CaMJ +csJMNzrhdOmbr6S1Yy/V8ZkOTWo7tLb5T3USGKiBTHSlv+lY+CP+UtKdbep3xLuV +c6hvROgd/IZlVoLMM2ur42ceCwIDAQABo2AwXjAMBgNVHRMBAf8EAjAAMA4GA1Ud +DwEB/wQEAwIHgDAdBgNVHQ4EFgQUaoB8b/XfwO8gpXCbEyHmhS1uXswwHwYDVR0j +BBgwFoAUuOgkieTH4eYII3L6oXUPFiUGrdYwDQYJKoZIhvcNAQELBQADggEBAGae +5WmrNr1mXPfVUgI3XNjEl+cPVlqOYBdjlosXrFZ6YTCMyHgYA9juN+n5Qy3Wu+ER +t98acPxypwPeEYpx7zVjalq5GWNDyEYPJp1VruRmUgjnhhEopk/XvpXYzul++zrI +ts4O9si6vw1QBHtNjbWBusEN3vpDy9ucooh3oDXIDkLeHRgK4vUCHRGwrF3MbGKh +32naCZ0aQA24uScaQw+k5mOQwty2YATPrVGax5Kb44tSdCNNgvwrG+D2ZeJsgW6f +akae9a9frnNqd1gv0GxW9SX5kvXjO8EuzI4orc3NcPMshAnZ02e+Pma1ds2Amhig +9XpCM1nP4gJTz18ag90= +-----END CERTIFICATE----- diff --git a/certs/intermediate/trust_anchor/expired-root-nokid-cert.pem b/certs/intermediate/trust_anchor/expired-root-nokid-cert.pem new file mode 100644 index 00000000000..7eee6dbf444 --- /dev/null +++ b/certs/intermediate/trust_anchor/expired-root-nokid-cert.pem @@ -0,0 +1,18 @@ +-----BEGIN CERTIFICATE----- +MIIC8zCCAdugAwIBAgICEBYwDQYJKoZIhvcNAQELBQAwKjEoMCYGA1UEAwwfd29s +ZlNTTCBDaGFpbiBUZXN0IEV4cGlyZWQgUm9vdDAeFw0wMDAxMDEwMDAwMDBaFw00 +OTEyMzEyMzU5NTlaMCoxKDAmBgNVBAMMH3dvbGZTU0wgQ2hhaW4gVGVzdCBFeHBp +cmVkIFJvb3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvn5QzbWOw +IlMlOzty/66/v+PPKULVRbWC+r/r461CfKC0CgnRm/W9tYMUs8sIQmaLRiwk2E2r +JAjCO9RAfgom8uvWZ+x+tNbt3iou1sW6n0l2aOQFgB7v4gdLORIb71o+kMjjG8Gm +CZVrEbII9uqMxwqjZS/VDuG8WnFFWM+P9aBdhlIKzhsCzZHhTDHV4fJwcWgUJfj8 +7ls2wsBTFX9jpKgLu5ydtvfun1nnuyW79qw5e9B7TMSTnguYF7V2JIIcYGIWwu7P +S7hKuxAUW33LTr5rXT33xS1B7FTC41CR9mFmrL8oKSgviR/gdZElsvWEfslJNUrJ +tTUNjqKF26X/AgMBAAGjIzAhMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD +AgEGMA0GCSqGSIb3DQEBCwUAA4IBAQBASfehZfhyyzykmiUkABwyBArelDKvlHXT +gc1c4xdXvdCTlqjVoyAdCYtWO64TqIqRPZEpJyc55CAS4ZyhM1jWp7CrwprtWmtO +HqF+WVKAZk9si5kMBJ448W6dBlnA07TN+EZRkRtrPAR7qOpop4GSkybFbQs2p1Hu +dDE9NSpqBgdmcALh5w2PTWyEiU5mwwb2QjpDScOQVOtu9S3iUuzD8isnF1keK9xF +mEru1lWAt6X/h5Y3mSZQO0TJPpKw3vkDIldef4kFKOus+/TXsbTIWEEvIRp2lPqT +rS0OUsTiL007PHsnACuGfWMfRZ/RoInr8MfC6r1jYRdkPzyIXuuz +-----END CERTIFICATE----- diff --git a/certs/intermediate/trust_anchor/expired-root-old-link-cert.pem b/certs/intermediate/trust_anchor/expired-root-old-link-cert.pem new file mode 100644 index 00000000000..4b1268091c9 --- /dev/null +++ b/certs/intermediate/trust_anchor/expired-root-old-link-cert.pem @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDMzCCAhugAwIBAgICEBIwDQYJKoZIhvcNAQELBQAwKjEoMCYGA1UEAwwfd29s +ZlNTTCBDaGFpbiBUZXN0IEV4cGlyZWQgUm9vdDAeFw0xMDAxMDEwMDAwMDBaFw0x +OTEyMzEyMzU5NTlaMCoxKDAmBgNVBAMMH3dvbGZTU0wgQ2hhaW4gVGVzdCBFeHBp +cmVkIFJvb3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCHm9mgnPTx +JhvX7NfamvCMJL3Z7e7y6IqvmfM3j2nXmut0My4cXuabc8nE5e4uPMQQfgVLNpqR +/pcPx4OX3u83GjSzfN6EWfGJq+z5HV13PrjrdleqamUSjLwZArGnwkJFprM2Ya0i +bd9qBCtlXg4Pn0ZlXTHNtFC+zEQbn7Z5HptGgsqv3sMb+ZYbsImkNGA1WyrHLBmK +Wz2fpqziek5uxMarUAt+orw/PcD9GjPkT+KazmyUQpFMGTHRPA68pD+22+PiuE7Q +dzM5GD1Qv4Y5veNP3YAuAj+YDSSD26i1DU2Bfbh9vlSMr5Gtbi7n3zDlOfhegoA3 +qxTmi3tOFUClAgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD +AgEGMB0GA1UdDgQWBBS46CSJ5Mfh5ggjcvqhdQ8WJQat1jAfBgNVHSMEGDAWgBSt +uHjwmi8n2rjqcGNrlc752hhz9jANBgkqhkiG9w0BAQsFAAOCAQEAJkUfL5fiMRX9 +I6/tP3wSSkCQ60wdpaffcxtNi8cQfqhK9v5bPUwGS0aggJgFQpuIBMNaMW0e0Qsl +hpW6j5PyuN2fLPrn/PEcCdmBiD59Yk8yV1EG0cihy0keTWNB/9RpV4fV5y4YssjT +Wv7M+HbCeQyCcdFX4AVJuU3g6BjnQrV0QX4MBv6+TrfaAJuPiQJFIrj2wJlM9awc +UX2ZZSGWKQTlEphPN47bxyUZOoLbNwhhrXpKKU+kn/MUrg2kNivuD8PLGRZ2maOe +TSHi80G9N2v+IYeweNFS4tsgzfdKmfgmSAZlIJroXzxhnfXgA+w0/QVlaE7yg/+b +PJo0iqoZGg== +-----END CERTIFICATE----- diff --git a/certs/intermediate/trust_anchor/forge-bad-sub-cert.pem b/certs/intermediate/trust_anchor/forge-bad-sub-cert.pem new file mode 100644 index 00000000000..c1c8a89589b --- /dev/null +++ b/certs/intermediate/trust_anchor/forge-bad-sub-cert.pem @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDLTCCAhWgAwIBAgICECEwDQYJKoZIhvcNAQELBQAwJzElMCMGA1UEAwwcd29s +ZlNTTCBDaGFpbiBUZXN0IEZvcmdlIEludDAeFw0wMDAxMDEwMDAwMDBaFw00OTEy +MzEyMzU5NTlaMCcxJTAjBgNVBAMMHHdvbGZTU0wgQ2hhaW4gVGVzdCBGb3JnZSBT +dWIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDFcXWvVAtvhSNRyNJ2 +HsFne8IIfdoe6zwKExtv7uhIobaruJnfSI/CH4og8MSdP5SI97IGT98XXFHu5JJ6 +n/rA2F+5W9Fl2gxOLnhOx2/qBPNB9I4pEe61KkiIazPwPe5yavw8YAUAuERuEs1M +qk4PzMDfICm9dcEMh6a9nWw3SR2ZkWni2ZdvUqtz0RnGGFK30hGBZfjGldgcHMbt +JaRpYcRYNjDmu2tw1EgWZagrRG805pUN8c588hCpj0MhSSSbx1jALPZyVvI6+Hwa +hSBoi/yuXV78k8G56NDzviocMvh+Ta6+7oZ9Q7WbxkQ1xpGw+lunDl/l1CHwNfLc +aQhFAgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0G +A1UdDgQWBBTeox/CjdGylkh7HI/k3Scy9AW7fjAfBgNVHSMEGDAWgBQAAAAAAAAA +AAAAAAAAAAAAAAAAADANBgkqhkiG9w0BAQsFAAOCAQEAVyvWcuGgAHHNfQ05U+rI +JN2YYWdaW0vyBTLDgOga0NjZe91nccN9nG+HdVWX0+Xl+EM9jj/tSKgWyBFRoZBc +9LJ0m4e+AlV1iHo0gM2KGer77larNIABwdaz8S7FmoWN0Etn4UcUqXrMzKJ85IDp +DAw0sleCd6X1OQ26Er/zrSqqc9Vx+2Fjn3aWUM27z3DIH3pH6OeT/orUKjTyg+yT +TFiIQse+nuvq32q2jVjpHo7rs1gKMzzNW1jOrMJVihICxkWSdmaYk4bL4WOQZ9xP +aGqG11UWmLW9e56n3hMVnkQl7DNGd5IcCuPvBvDKLNIaOwOM/YTcu9lpsLYO36bE +QA== +-----END CERTIFICATE----- diff --git a/certs/intermediate/trust_anchor/forge-fake-int-cert.pem b/certs/intermediate/trust_anchor/forge-fake-int-cert.pem new file mode 100644 index 00000000000..a8bb6ff1f00 --- /dev/null +++ b/certs/intermediate/trust_anchor/forge-fake-int-cert.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDKzCCAhOgAwIBAgICEB8wDQYJKoZIhvcNAQELBQAwJTEjMCEGA1UEAwwad29s +ZlNTTCBDaGFpbiBUZXN0IEZvcmdlIFEwHhcNMDAwMTAxMDAwMDAwWhcNNDkxMjMx +MjM1OTU5WjAnMSUwIwYDVQQDDBx3b2xmU1NMIENoYWluIFRlc3QgRm9yZ2UgSW50 +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqvGdcU39Qy3bRqctGo2F +Pq4dPw7E6QvG5Esj5JRsVR2WtVi8d4A90vBKBwdYPeKIcv03QLO8+pXji5MAZO7T +1yGfQCR9fJrnXj3XDBiR+mIspKxAGYJiRPHr40DE9mmv7hlMUYevnIfBTSm5hPpP +XNe0C525AN+/C7GBkY7jN0Dls6URrTsuZFpfI3smOO3kKUmADecAgLC7zy1+s21L +Uj0cyMY1O3upsT/wHA0TnmeRAbmqiy5IkG7ogZ3g0974N3clFq8zfDs/d2+niIrG +E7Y+R2MplLMsXCx4CAE/JLdqiO4ICvRx7VME67DKsvfXxKbPrxXkDzYixPFXQzm3 +NQIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNV +HQ4EFgQUAAAAAAAAAAAAAAAAAAAAAAAAAAAwHwYDVR0jBBgwFoAUGjMo0gIX0Nw5 +lX7XwWWpjad8mdkwDQYJKoZIhvcNAQELBQADggEBAFUXxoCV9ygFe9fZV2lQiwcP +JLDgWPWqtvFyWrrHLLmlxmZmXVIrzXgzaDd2kegYSnbuBN3dXpk5rnor1sxDGgWU +u5U0/zQgon5UY7PbQhwCAkumZodRqw+ubyPsmVRyFHv9yAG2JhYYtHPppTaHd3eX +7NvZ/7UpYVZVQr1NTFXeacReTyJ1OlQmyaN15FRD+PUeUPbN4/PaxM+rH0ysu3jd +IhvuEfG/pBwKwBDT/hYkMSBdOPKTLAP+c42Ruhq1XMBXtokkH70u7CUmxCoe2lPz +o7SecPre/i5T2MvmCRI7+8dPVLnvY7Z/LSlv5KR6T0scP0Xqieb2c4P4SbRcoDU= +-----END CERTIFICATE----- diff --git a/certs/intermediate/trust_anchor/forge-fake-int-leaf-cert.pem b/certs/intermediate/trust_anchor/forge-fake-int-leaf-cert.pem new file mode 100644 index 00000000000..6181ea46d5f --- /dev/null +++ b/certs/intermediate/trust_anchor/forge-fake-int-leaf-cert.pem @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDNDCCAhygAwIBAgICECAwDQYJKoZIhvcNAQELBQAwJzElMCMGA1UEAwwcd29s +ZlNTTCBDaGFpbiBUZXN0IEZvcmdlIEludDAeFw0wMDAxMDEwMDAwMDBaFw00OTEy +MzEyMzU5NTlaMDExLzAtBgNVBAMMJndvbGZTU0wgQ2hhaW4gVGVzdCBGb3JnZSBG +YWtlIEludCBMZWFmMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvA4j +E64nUe5+rTxkXGXY9s44Z7UOlB86i324ZjyYMZctm5rYULh4Kiceb43j5nWR2Jbv +4Qw/dIwRa2a7NbncphGuyIc/imS5+ZT3dHhXjNw1lz2VGPpqy4LKUn9xFl3sMmqw +QZagDylRcko5wPu5UvgukRlKvHBo6dVTTYK49VgksD3Lll41tNR0GkI1nf0Wwaa8 +1UnSzVCifXTKXchyjg+Q3YfKwO1tk71lWgKGGBH2tKtHyI9m6TANU+9klOoQD1Nt +cs2ln5dfndujoSkDQfd9yjHs8FONeV7bCOnHow6TrwpQZUnlFhwfKw3MdYHBksve +u819EbinbQbybM9hPwIDAQABo2AwXjAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQE +AwIHgDAdBgNVHQ4EFgQUl2/1p1ILjdI2VngSgKCmL7edQ3IwHwYDVR0jBBgwFoAU +AAAAAAAAAAAAAAAAAAAAAAAAAAAwDQYJKoZIhvcNAQELBQADggEBAFZ5Q8lWvfi3 +7c8FbiFxjlEd7WojsibVj8ndSAZ2wjeKqjh1Ms9EDe4sT6JC4Ayl+Rlv8ZlIqUPG +u65D6aUNpASdFq/YHydsOIVgunJYLFIg7GViY40JZz8fdO9BmTtTbikkBNKlZPA4 +VK4n6D2dC9xtJ75C/R+yOK3pN8q9CvqjFuoVCTrGvcAss99lNSEBzFFuPWM05RQd +Qy7l4RUb9QarsEy/wxh/7lWMBkjjZmgV7LeOtjgJyKPL69TgXwWKqf43dl7ktkYB +5sgYjri0q9aBwq7P4ENDijSYCPhCDra/5l1cEJw1UyuMszE9RP0BXJep9B6P2Lmn +l/IVsyhX4do= +-----END CERTIFICATE----- diff --git a/certs/intermediate/trust_anchor/forge-int-cert.pem b/certs/intermediate/trust_anchor/forge-int-cert.pem new file mode 100644 index 00000000000..ced26b9abc9 --- /dev/null +++ b/certs/intermediate/trust_anchor/forge-int-cert.pem @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDLjCCAhagAwIBAgICEBswDQYJKoZIhvcNAQELBQAwKDEmMCQGA1UEAwwdd29s +ZlNTTCBDaGFpbiBUZXN0IEZvcmdlIFJvb3QwHhcNMDAwMTAxMDAwMDAwWhcNNDkx +MjMxMjM1OTU5WjAnMSUwIwYDVQQDDBx3b2xmU1NMIENoYWluIFRlc3QgRm9yZ2Ug +SW50MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtzFpX1AmnJ8iDDYJ +7Zif2/f26guodqeyi2d7HrPM5L0ylGbFyVP3bUhUuD9tFPIC79K0j8M3QrxpjPi2 +BHuRFbnt1OftbXEghyOexLA32NrOjavlsB4E2Vydqb5hg0wTFUEQ5PytPXA781/L +P11lVced52F35lG9GZL4QRhydkC9G3ppNcHiixxI3GGi/cE/JyONt8MgmjjNtwE0 +tesJ3Or32pQyI8w8UadY4lFGWlLKyo7N0JfD9j14gp9gUCLhwRPH0fM5NZEaFpnV +u+A0xovYNZfhhseNrJsQzeRNfkuRV+rGAiQvViAoRvx8Fp5OVVKa+rf5gYu+MBLi +aUGrpQIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAd +BgNVHQ4EFgQUBwcHBwcHBwcHBwcHBwcHBwcHBwcwHwYDVR0jBBgwFoAUi6sJzKDs +7J4Jho4rVpbP+ERdt3QwDQYJKoZIhvcNAQELBQADggEBAIgTYF+oGtld5ri1Rk4x +3PrXn1U+MNkw2UNESUrDDUNVtB0hxcTy7mp653p0UJ2ltXkQz3rO0oyTvuREuFbh ++3cPux5VIcjrnewOinKxq1zZVb5LB2R2yJdMCf47u7Lo+saqhm9s1WhQZIeT4M72 +vA+MJGC8w4Jin4Zg4OQGlRpxVGRCFkjdqgyDqA7gwLnBLVuSzdpI2PQOxQ5XXOtq +TzexmZmPbhqJwLv7Zzsq2vSn8k1sH6OP9OcAHVAlxu4JGB+qrxHheDsCt7vbiKG1 +Ry7mmCl+U/SzP917qLh+0uoMLr7QNFQkBxeGYVXSSFaAsiOve5olfdNmZklGKePa +Gx0= +-----END CERTIFICATE----- diff --git a/certs/intermediate/trust_anchor/forge-q-cert.pem b/certs/intermediate/trust_anchor/forge-q-cert.pem new file mode 100644 index 00000000000..04f2de16ffd --- /dev/null +++ b/certs/intermediate/trust_anchor/forge-q-cert.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDCjCCAfKgAwIBAgICEB4wDQYJKoZIhvcNAQELBQAwJzElMCMGA1UEAwwcd29s +ZlNTTCBDaGFpbiBUZXN0IEZvcmdlIEludDAeFw0wMDAxMDEwMDAwMDBaFw00OTEy +MzEyMzU5NTlaMCUxIzAhBgNVBAMMGndvbGZTU0wgQ2hhaW4gVGVzdCBGb3JnZSBR +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAjxTMwWrqcLPjFpRkmnzT +eLav68exUtBpNcDXrLgA3IG9YtkJPjeSbBXvl10iChdL4VzMT3inHoYicFqQ6rwm +ezP/rX3b4mJNm8+D7ows4IBVB6tlczVWjU04RVNOpRT4NfniBuOiZfQ60bhxbQh1 +sSaEdQyNgpdpJtNB/sAgAtIOUUfWFy5eGmm7UH/I40dsezZj1+m9dVEs6qThE0qu +gw8Dq6FPMUTMy+2lhLKWU3vF1VGOSz3pmnGvdnBKFizzLEJHU+X/3V8eed9pJmgb +efvvRc5/97YubDbWUzHWd3A1M5lVNKqOPl0/s59cZTcG5NMU0TuDZ6mXc6tb/nRx +hQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNV +HQ4EFgQUGjMo0gIX0Nw5lX7XwWWpjad8mdkwDQYJKoZIhvcNAQELBQADggEBABNF +brTrWfUgs/vTfzN96tRtIRN1u7jZ+7NVtPTnuUf3/doYRk/ebohJXSOkh7yYaQFG +XJhBSxFLHTO/O67HLcQr2Ak7RxnxcgkNMToUhbr9IJanT9OdeTQp+T7G/Zn6RPAA +4GoM7dfjg5dp1Gv2+ZHq86LHIP9oHHyntwHUv2HDKWvtEEV2ZLwhOgOLUsmQkG/q +Ik3rLABnhORnFzK/8X3fW9dEapqheICKrsQ1lbUKeN8puAPKH2c3Nu8aFrtsHLLl +OHHQVBg9igMhn+YyRfUmQTxmdp6+H7BhA5JHLSV9+d0tY3TlnuJwqark7jjrdG5f +ZJbx1g/gYAem6BKQ7s4= +-----END CERTIFICATE----- diff --git a/certs/intermediate/trust_anchor/forge-root-cert.pem b/certs/intermediate/trust_anchor/forge-root-cert.pem new file mode 100644 index 00000000000..4acc23e1fbf --- /dev/null +++ b/certs/intermediate/trust_anchor/forge-root-cert.pem @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDLzCCAhegAwIBAgICEBowDQYJKoZIhvcNAQELBQAwKDEmMCQGA1UEAwwdd29s +ZlNTTCBDaGFpbiBUZXN0IEZvcmdlIFJvb3QwHhcNMDAwMTAxMDAwMDAwWhcNNDkx +MjMxMjM1OTU5WjAoMSYwJAYDVQQDDB13b2xmU1NMIENoYWluIFRlc3QgRm9yZ2Ug +Um9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPcxD1n1/tLuqqmt +O/EcuvbdG4JB1crpYEpPfcEgpk6aIzX2KX2KAnwCfQHrRoR1GID0Be3V/Sg7cG7A +020olQ2mVABlfjNMBjEWNdP2Sh3fbzTOS515a/2LWybvkvo0AW5ENjWkyNxLisji +u6pBbNYAZrD3COVIXD+aRXDXFwlApOX6v5OzVjirWaZ+jhyF+SWOfCE3oywH02d2 +muudOBjSvEdXArqNtt/jo3uDCuaj2Iez+ggAzrayZ8qO46g8IOk6vliGFAZmhCVC +mDuc53Y/ebHPh+HIZDYvCN18cVA111eEmG5+jCusHxYkOs7Ra3IZocjV5lBkAyun +Tsb2OF0CAwEAAaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYw +HQYDVR0OBBYEFIurCcyg7OyeCYaOK1aWz/hEXbd0MB8GA1UdIwQYMBaAFIurCcyg +7OyeCYaOK1aWz/hEXbd0MA0GCSqGSIb3DQEBCwUAA4IBAQC79KRxGcNeuJXKd0l7 +K9oywUbYX8Y+WB8zgUvLQqIzRuLoUgH5sUIHW3Y2DrzD3bnLjQQCR1SKsXkgv5EM +a/dnaP3/uWR5GJJW9f+BFw3/XSQq6LW4lNjqT0qpEPV2QFQU4brQOhOGGgireOz4 +tZ0iJ+7B0VBRagGkZbWtc8Y9ea/jRmq6GW/wT0GBi8m3QsRvTqZVX7JHD/4KJX2k +2utiWNGhYGY9Nx+jvWzaektapODG1hofAip1CMfwDWgXZrE/G3xgKFJBkGfnJwJ/ +EofL2XDFdpOVdHp3NQk2t1guyCYZUkFPdUddkISMXs4y/qAxgy4U5OuT4+aolEBf +P6rc +-----END CERTIFICATE----- diff --git a/certs/intermediate/trust_anchor/forge-sub-cert.pem b/certs/intermediate/trust_anchor/forge-sub-cert.pem new file mode 100644 index 00000000000..5bc746f56b7 --- /dev/null +++ b/certs/intermediate/trust_anchor/forge-sub-cert.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDDDCCAfSgAwIBAgICECIwDQYJKoZIhvcNAQELBQAwJzElMCMGA1UEAwwcd29s +ZlNTTCBDaGFpbiBUZXN0IEZvcmdlIEludDAeFw0wMDAxMDEwMDAwMDBaFw00OTEy +MzEyMzU5NTlaMCcxJTAjBgNVBAMMHHdvbGZTU0wgQ2hhaW4gVGVzdCBGb3JnZSBT +dWIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDFcXWvVAtvhSNRyNJ2 +HsFne8IIfdoe6zwKExtv7uhIobaruJnfSI/CH4og8MSdP5SI97IGT98XXFHu5JJ6 +n/rA2F+5W9Fl2gxOLnhOx2/qBPNB9I4pEe61KkiIazPwPe5yavw8YAUAuERuEs1M +qk4PzMDfICm9dcEMh6a9nWw3SR2ZkWni2ZdvUqtz0RnGGFK30hGBZfjGldgcHMbt +JaRpYcRYNjDmu2tw1EgWZagrRG805pUN8c588hCpj0MhSSSbx1jALPZyVvI6+Hwa +hSBoi/yuXV78k8G56NDzviocMvh+Ta6+7oZ9Q7WbxkQ1xpGw+lunDl/l1CHwNfLc +aQhFAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0G +A1UdDgQWBBTeox/CjdGylkh7HI/k3Scy9AW7fjANBgkqhkiG9w0BAQsFAAOCAQEA +Bq4JK7v4da0jx6z0sv4gBIUzMb6v5gQ/b57Qk2VMHzi+mQ205409t0SudqmoXthv +B1qN9F10VwP35fHG0VI459mEBEM1vHfhoOPO1OHe66LnscRauRu0L9P4pv8KIk6Z +9UTDpxmGRTAcSD2Gjeg6/ufYLNXexaA8OZJKpw9pbjhvx1lqdZUyvr1b3wQAesz5 +cg+Qd36yQOSxI/1eFptpcJW6gzvQBhpfnflQfF8tPXL6EAQEybsG0Dn1t3MJifG3 +3UDOHycTZNx0FZAPymx5YLeW8hhf72PAOqEsz7W36feBPo8e4CKHAeLyyROtQUP0 +iSoHzl+vL86c3KI0CcuNTg== +-----END CERTIFICATE----- diff --git a/certs/intermediate/trust_anchor/forge-sub-leaf-cert.pem b/certs/intermediate/trust_anchor/forge-sub-leaf-cert.pem new file mode 100644 index 00000000000..3c71859a941 --- /dev/null +++ b/certs/intermediate/trust_anchor/forge-sub-leaf-cert.pem @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDLzCCAhegAwIBAgICECMwDQYJKoZIhvcNAQELBQAwJzElMCMGA1UEAwwcd29s +ZlNTTCBDaGFpbiBUZXN0IEZvcmdlIFN1YjAeFw0wMDAxMDEwMDAwMDBaFw00OTEy +MzEyMzU5NTlaMCwxKjAoBgNVBAMMIXdvbGZTU0wgQ2hhaW4gVGVzdCBGb3JnZSBT +dWIgTGVhZjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALwOIxOuJ1Hu +fq08ZFxl2PbOOGe1DpQfOot9uGY8mDGXLZua2FC4eConHm+N4+Z1kdiW7+EMP3SM +EWtmuzW53KYRrsiHP4pkufmU93R4V4zcNZc9lRj6asuCylJ/cRZd7DJqsEGWoA8p +UXJKOcD7uVL4LpEZSrxwaOnVU02CuPVYJLA9y5ZeNbTUdBpCNZ39FsGmvNVJ0s1Q +on10yl3Ico4PkN2HysDtbZO9ZVoChhgR9rSrR8iPZukwDVPvZJTqEA9TbXLNpZ+X +X53bo6EpA0H3fcox7PBTjXle2wjpx6MOk68KUGVJ5RYcHysNzHWBwZLL3rvNfRG4 +p20G8mzPYT8CAwEAAaNgMF4wDAYDVR0TAQH/BAIwADAOBgNVHQ8BAf8EBAMCB4Aw +HQYDVR0OBBYEFJdv9adSC43SNlZ4EoCgpi+3nUNyMB8GA1UdIwQYMBaAFN6jH8KN +0bKWSHscj+TdJzL0Bbt+MA0GCSqGSIb3DQEBCwUAA4IBAQC/JXhiLenxhCh5er/G +E1/8qGGcGIWnRqKCTNPZ2qVXqDPtSy0i2nGiGiqZOKZfhc91NjYExgs6I9R2hnT5 +zggo0OYCilmOyf64tVfmtml6/CczWAVh9pqPU7TMdaPfa8/vCD/SdujCKbM3TLAa +fteWr1niIkl4p90Hs+ITNXRYd+YOGk1CZBfwsF6MSttl20K69+KNKvVYindqiXEg +fMi8feXgzdTCdsUTB0vlNk1baogkmXDf8kW4yqB8uvAA5RWmYQcfVbLxLMDPdoio +qlS69r9/1PyJQJGIFrxEzbyz1UYb2tYHvIJKLox9jjRPZXRUNAMmS9afdJ4g8TWO +g9oV +-----END CERTIFICATE----- diff --git a/certs/intermediate/trust_anchor/gen_certs.sh b/certs/intermediate/trust_anchor/gen_certs.sh new file mode 100755 index 00000000000..95a46393e03 --- /dev/null +++ b/certs/intermediate/trust_anchor/gen_certs.sh @@ -0,0 +1,122 @@ +#!/bin/bash + +# Regenerate the certificate set used by the chain tests of +# X509_verify_cert() in tests/api/test_ossl_x509_str.c. +# +# self-cert a self-signed CA +# self-copy-cert the same name and key as self-cert, another serial +# root-cert a self-signed CA +# link-cert the name of root-cert with its own key, issued by +# root-cert: self-issued, but not self-signed +# link-noaki-cert link-cert without an authority key identifier +# leaf-cert issued by link-cert +# notca-twin-cert a CA with the name of notca-root-cert +# (gen_dated_certs.sh) and the key of leaf-cert, issued by +# root-cert, without a subject key id +# ec-name-root-cert an EC P-256 root with the name of root-cert, without +# key ids +# +# RSA-2048 / SHA-256, ~30 year validity so the regression does not expire. +# +# Requires: openssl. + +set -e +cd "$(dirname "$0")" + +OPENSSL="${OPENSSL:-openssl}" +DAYS=10957 +RSA_BITS=2048 + +CA_EXT=$(mktemp) +CA_NOAKI_EXT=$(mktemp) +CA_NOSKID_EXT=$(mktemp) +LEAF_EXT=$(mktemp) +trap 'rm -f "$CA_EXT" "$CA_NOAKI_EXT" "$CA_NOSKID_EXT" "$LEAF_EXT" *.csr' \ + EXIT + +cat > "$CA_EXT" <<'EXT' +basicConstraints = critical, CA:TRUE +keyUsage = critical, digitalSignature, keyCertSign, cRLSign +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always +EXT + +cat > "$CA_NOAKI_EXT" <<'EXT' +basicConstraints = critical, CA:TRUE +keyUsage = critical, digitalSignature, keyCertSign, cRLSign +subjectKeyIdentifier = hash +authorityKeyIdentifier = none +EXT + +cat > "$CA_NOSKID_EXT" <<'EXT' +basicConstraints = critical, CA:TRUE +keyUsage = critical, digitalSignature, keyCertSign, cRLSign +subjectKeyIdentifier = none +authorityKeyIdentifier = keyid:always +EXT + +cat > "$LEAF_EXT" <<'EXT' +basicConstraints = critical, CA:FALSE +keyUsage = critical, digitalSignature +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always +EXT + +genkey() { "$OPENSSL" genrsa -out "$1" "$RSA_BITS" 2>/dev/null; } + +# Self-sign: selfsign +selfsign() { + "$OPENSSL" req -x509 -new -key "$1" -sha256 -subj "/CN=$3" -set_serial "$4" \ + -days "$DAYS" -extensions v3 \ + -config <(printf '[req]\ndistinguished_name=dn\n[dn]\n[v3]\n%s' \ + "$(cat "$CA_EXT")") \ + -out "$2" +} + +# Sign a CSR: signcert +signcert() { + "$OPENSSL" x509 -req -in "$1" -CA "$3" -CAkey "$4" -set_serial "$5" \ + -sha256 -days "$DAYS" -extfile "$6" -out "$2" 2>/dev/null +} + +# Self-signed copies ----------------------------------------------------------- +genkey self-key.pem +selfsign self-key.pem self-cert.pem "wolfSSL Trust-Anchor Test Self-Signed" 1 +selfsign self-key.pem self-copy-cert.pem \ + "wolfSSL Trust-Anchor Test Self-Signed" 2 + +# Self-issued link cert -------------------------------------------------------- +genkey root-key.pem +selfsign root-key.pem root-cert.pem "wolfSSL Trust-Anchor Test Root" 1 + +genkey link-key.pem +"$OPENSSL" req -new -key link-key.pem -sha256 \ + -subj "/CN=wolfSSL Trust-Anchor Test Root" -out link.csr +signcert link.csr link-cert.pem root-cert.pem root-key.pem 2 "$CA_EXT" +signcert link.csr link-noaki-cert.pem root-cert.pem root-key.pem 3 \ + "$CA_NOAKI_EXT" + +genkey leaf-key.pem +"$OPENSSL" req -new -key leaf-key.pem -sha256 \ + -subj "/CN=wolfSSL Trust-Anchor Test Leaf" -out leaf.csr +signcert leaf.csr leaf-cert.pem link-cert.pem link-key.pem 4 "$LEAF_EXT" + +# Another signer's name -------------------------------------------------------- +"$OPENSSL" req -new -key leaf-key.pem -sha256 \ + -subj "/CN=wolfSSL Chain Test Not CA Root" -out twin.csr +signcert twin.csr notca-twin-cert.pem root-cert.pem root-key.pem 5 \ + "$CA_NOSKID_EXT" + +# A root of another key type -------------------------------------------------- +"$OPENSSL" ecparam -name prime256v1 -genkey -noout -out ec-name-root-key.pem +"$OPENSSL" req -x509 -new -key ec-name-root-key.pem -sha256 \ + -subj "/CN=wolfSSL Trust-Anchor Test Root" -set_serial 6 -days "$DAYS" \ + -extensions v3 \ + -config <(printf '[req]\ndistinguished_name=dn\n[dn]\n[v3]\n%s\n%s\n%s\n' \ + "basicConstraints = critical, CA:TRUE" \ + "keyUsage = critical, keyCertSign, cRLSign" \ + "subjectKeyIdentifier = none") \ + -out ec-name-root-cert.pem +rm -f ec-name-root-key.pem + +echo "Completed" diff --git a/certs/intermediate/trust_anchor/gen_dated_certs.sh b/certs/intermediate/trust_anchor/gen_dated_certs.sh new file mode 100755 index 00000000000..f0d75dff51c --- /dev/null +++ b/certs/intermediate/trust_anchor/gen_dated_certs.sh @@ -0,0 +1,432 @@ +#!/bin/bash + +# Regenerate the certificates with fixed dates used by the chain check tests +# of X509_verify_cert() in tests/api/test_ossl_x509_str.c. +# +# dated-root-cert a self-signed CA, valid 2000 to 2049 +# dated-root-late-cert dated-root-cert valid 2020 to 2049, same name and +# key +# expired-root-cert a self-signed CA, valid 2010 to 2019 +# expired-root-leaf-cert issued by expired-root-cert, valid 2000 to 2049 +# expired-int-cert a CA issued by dated-root-cert, valid 2010 to 2019 +# dated-int-cert expired-int-cert valid 2000 to 2049, same name and +# key +# dated-int-leaf-cert issued by dated-int-cert, valid 2000 to 2049 +# notca-root-cert a self-signed cert with CA:FALSE +# notca-root-leaf-cert issued by notca-root-cert +# nobc-root-cert a self-signed v3 cert without basicConstraints or +# keyUsage +# nobc-root-leaf-cert issued by nobc-root-cert +# v1-root-cert a self-signed X.509 v1 cert +# v1-root-leaf-cert issued by v1-root-cert +# cross-root-cert dated-root-cert's name and key, issued by +# expired-root-cert, valid 2000 to 2049 +# cross-root-late-cert cross-root-cert valid 2020 to 2049 +# renewed-root-cert a self-signed CA with expired-root-cert's name and +# a new key, valid 2020 to 2049 +# renewed-root-leaf-cert issued by renewed-root-cert, no authority key id, +# valid 2000 to 2049 +# expired-root-int-cert a CA issued by expired-root-cert, valid 2000 to +# 2049 +# expired-root-int-leaf-cert issued by expired-root-int-cert, valid 2000 to +# 2049 +# expired-root-link-cert a CA with expired-root-cert's name and a new key, +# issued by expired-root-cert, valid 2000 to 2049 +# expired-root-old-link-cert expired-root-link-cert valid 2010 to 2019 +# expired-root-link-leaf-cert issued by expired-root-link-cert, valid 2000 +# to 2049 +# expired-root-nokid-cert a self-signed CA with expired-root-cert's name, a +# new key and no key ids, valid 2000 to 2049 +# nokid-root-cert a self-signed CA without key ids, valid 2000 to +# 2049 +# badkid-int-cert a CA issued by nokid-root-cert with an authority +# key id that does not match, valid 2010 to 2019 +# badkid-int-leaf-cert issued by badkid-int-cert, valid 2000 to 2049 +# noaki-root-cert a self-signed CA without an authority key id, +# valid 2000 to 2049 +# noaki-root-link-cert a CA with noaki-root-cert's name and a new key, +# issued by noaki-root-cert, valid 2000 to 2049 +# noaki-root-leaf-cert issued by noaki-root-cert, valid 2000 to 2049 +# forge-root-cert a self-signed CA +# forge-int-cert a CA issued by forge-root-cert, subject key id +# 07:07:... +# forge-fake-int-cert a CA with forge-int-cert's name, a new key and the +# subject key id 00:00:..., issued by forge-q-cert +# forge-fake-int-leaf-cert issued by forge-fake-int-cert +# forge-q-cert a CA without an authority key id, signed by the +# forge-fake-int-cert key in forge-int-cert's name +# forge-bad-sub-cert a CA with the authority key id 00:00:..., signed +# by another key in forge-int-cert's name +# forge-sub-cert forge-bad-sub-cert's name and key, without an +# authority key id, signed by the +# forge-fake-int-cert key in forge-int-cert's name +# forge-sub-leaf-cert issued by forge-sub-cert +# alt-root-cert a self-signed CA +# alt-int-cert a CA issued by alt-root-cert, valid 2020 to 2049 +# alt-end-cert a CA issued by a CA that is not kept, so no +# chain goes on above it +# alt-end-int-cert alt-int-cert's name and key, issued by +# alt-end-cert, valid 2000 to 2049 +# alt-old-int-cert alt-end-int-cert valid 2010 to 2019 +# alt-notca-int-cert alt-end-int-cert with CA:FALSE +# alt-int-leaf-cert issued by the key of alt-int-cert +# wrongca-root-cert a self-signed CA +# wrongca-cert a CA issued by wrongca-root-cert +# wrongca-int-cert a CA without an authority key id, named as issued +# by wrongca-cert but signed by another key +# wrongca-old-int-cert wrongca-int-cert valid 2010 to 2019, with the +# authority key id of that key +# wrongca-int-leaf-cert issued by wrongca-int-cert +# int-crl an empty CRL of the expired-int-cert key +# dated-root-empty-crl an empty CRL of dated-root-cert +# dated-root-crl a CRL of dated-root-cert, revokes expired-int-cert +# +# RSA-2048 / SHA-256. The keys are not kept. +# +# Requires: OpenSSL 3.0 or later and GNU sed. + +set -e +cd "$(dirname "$0")" + +OPENSSL="${OPENSSL:-openssl}" +WORK=$(mktemp -d) +trap 'rm -rf "$WORK"' EXIT + +cat > "$WORK/ca.cnf" <<'CNF' +[ca] +default_ca = ca_sect +[ca_sect] +dir = . +database = $dir/index.txt +new_certs_dir = $dir +serial = $dir/serial +crlnumber = $dir/crlnumber +crl_extensions = crl_ext +default_md = sha256 +policy = policy_any +unique_subject = no +[policy_any] +commonName = supplied +[req] +distinguished_name = dn +[dn] +[ca_ext] +basicConstraints = critical, CA:TRUE +keyUsage = critical, keyCertSign, cRLSign +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always +[notca_ext] +basicConstraints = critical, CA:FALSE +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always +[nobc_ext] +subjectKeyIdentifier = hash +[leaf_ext] +basicConstraints = critical, CA:FALSE +keyUsage = critical, digitalSignature +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always +[v1_leaf_ext] +basicConstraints = critical, CA:FALSE +keyUsage = critical, digitalSignature +subjectKeyIdentifier = hash +[noaki_leaf_ext] +basicConstraints = critical, CA:FALSE +keyUsage = critical, digitalSignature +subjectKeyIdentifier = hash +authorityKeyIdentifier = none +[nokid_ca_ext] +basicConstraints = critical, CA:TRUE +keyUsage = critical, keyCertSign, cRLSign +subjectKeyIdentifier = none +authorityKeyIdentifier = none +[badkid_ca_ext] +basicConstraints = critical, CA:TRUE +keyUsage = critical, keyCertSign, cRLSign +subjectKeyIdentifier = hash +2.5.29.35 = DER:30168014010101010101010101010101010101010101010101 +[noaki_ca_ext] +basicConstraints = critical, CA:TRUE +keyUsage = critical, keyCertSign, cRLSign +subjectKeyIdentifier = hash +authorityKeyIdentifier = none +[forge_int_ext] +basicConstraints = critical, CA:TRUE +keyUsage = critical, keyCertSign, cRLSign +2.5.29.14 = DER:04140707070707070707070707070707070707070707 +authorityKeyIdentifier = keyid:always +[forge_fake_ext] +basicConstraints = critical, CA:TRUE +keyUsage = critical, keyCertSign, cRLSign +2.5.29.14 = DER:04140000000000000000000000000000000000000000 +authorityKeyIdentifier = keyid:always +[crl_ext] +authorityKeyIdentifier = keyid:always +CNF +: > "$WORK/index.txt" +echo 1000 > "$WORK/crlnumber" + +genkey() { "$OPENSSL" genrsa -out "$WORK/$1" 2048 2>/dev/null; } + +# The serial of each cert, as in the committed set. Sets were made in +# separate runs, so some serials repeat. +serial_of() { + case "$1" in + dated-root-cert.pem|wrongca-root-cert.pem) echo 1000 ;; + expired-root-cert.pem|wrongca-cert.pem) echo 1001 ;; + expired-root-leaf-cert.pem|wrongca-gone-self.pem) echo 1002 ;; + expired-int-cert.pem|wrongca-int-cert.pem) echo 1003 ;; + dated-int-cert.pem|wrongca-old-int-cert.pem) echo 1004 ;; + dated-int-leaf-cert.pem|wrongca-int-leaf-cert.pem) echo 1005 ;; + notca-root-cert.pem) echo 1006 ;; + notca-root-leaf-cert.pem) echo 1007 ;; + nobc-root-cert.pem|v1-root-cert.pem) echo 1008 ;; + nobc-root-leaf-cert.pem|v1-root-leaf-cert.pem) echo 1009 ;; + cross-root-cert.pem) echo 100A ;; + renewed-root-cert.pem) echo 100B ;; + renewed-root-leaf-cert.pem) echo 100C ;; + expired-root-int-cert.pem) echo 100D ;; + expired-root-int-leaf-cert.pem) echo 100E ;; + dated-root-late-cert.pem) echo 100F ;; + cross-root-late-cert.pem) echo 1010 ;; + expired-root-link-cert.pem) echo 1011 ;; + expired-root-old-link-cert.pem) echo 1012 ;; + expired-root-link-leaf-cert.pem) echo 1013 ;; + nokid-root-cert.pem) echo 1014 ;; + badkid-int-cert.pem) echo 1015 ;; + badkid-int-leaf-cert.pem|expired-root-nokid-cert.pem) echo 1016 ;; + noaki-root-cert.pem) echo 1019 ;; + noaki-root-link-cert.pem|forge-root-cert.pem) echo 101A ;; + noaki-root-leaf-cert.pem|forge-int-cert.pem) echo 101B ;; + forge-fake-self.pem) echo 101C ;; + forge-junk-self.pem) echo 101D ;; + forge-q-cert.pem) echo 101E ;; + forge-fake-int-cert.pem) echo 101F ;; + forge-fake-int-leaf-cert.pem) echo 1020 ;; + forge-bad-sub-cert.pem) echo 1021 ;; + forge-sub-cert.pem) echo 1022 ;; + forge-sub-leaf-cert.pem) echo 1023 ;; + alt-root-cert.pem) echo 1027 ;; + alt-int-cert.pem) echo 1028 ;; + alt-gone-self.pem) echo 1029 ;; + alt-end-cert.pem) echo 102A ;; + alt-end-int-cert.pem) echo 102B ;; + alt-old-int-cert.pem) echo 102C ;; + alt-notca-int-cert.pem) echo 102D ;; + alt-int-leaf-cert.pem) echo 102E ;; + *) echo "No serial for $1" >&2; return 1 ;; + esac +} + +# Issue a cert, with a database of its own so that serials can repeat: +# issue +# +issue() { + local sign ext + : > "$WORK/index.txt" + serial_of "$1" > "$WORK/serial" + "$OPENSSL" req -new -key "$WORK/$3" -subj "/CN=$2" -config "$WORK/ca.cnf" \ + -out "$WORK/req.csr" + if [ "$4" = "self" ]; then + sign=(-selfsign -keyfile "$WORK/$5") + else + sign=(-cert "$WORK/$4" -keyfile "$WORK/$5") + fi + ext=() + if [ "$6" != "none" ]; then + ext=(-extensions "$6") + fi + (cd "$WORK" && "$OPENSSL" ca -batch -config ca.cnf -notext \ + "${sign[@]}" "${ext[@]}" -startdate "$7" -enddate "$8" \ + -in req.csr -out "$1" 2>/dev/null) +} + +# Make a CRL that lists the certs revoked so far: +# crl +crl() { + (cd "$WORK" && "$OPENSSL" ca -gencrl -config ca.cnf \ + -cert "$2" -keyfile "$3" -crl_lastupdate "$LONG" \ + -crl_nextupdate "$LONG_END" -out "$1" 2>/dev/null) +} + +# Revoke a cert at the start of 2010: revoke +revoke() { + (cd "$WORK" && "$OPENSSL" ca -config ca.cnf -revoke "$1" \ + -cert "$2" -keyfile "$3" 2>/dev/null) + sed -i 's/^\(R\t[^\t]*\t\)[^\t]*/\1100101000000Z/' "$WORK/index.txt" +} + +OLD=20100101000000Z +OLD_END=20191231235959Z +NEW=20200101000000Z +LONG=20000101000000Z +LONG_END=20491231235959Z + +genkey root.key +genkey expired-root.key +genkey int.key +genkey notca.key +genkey nobc.key +genkey v1.key +genkey leaf.key +genkey renewed-root.key +genkey expired-root-int.key +genkey expired-root-link.key +genkey expired-root-nokid.key +genkey nokid-root.key +genkey badkid-int.key +genkey noaki-root.key +genkey noaki-link.key +genkey forge-root.key +genkey forge-int.key +genkey forge-fake.key +genkey forge-junk.key +genkey forge-q.key +genkey forge-sub.key +genkey alt-root.key +genkey alt-int.key +genkey alt-end.key +genkey alt-gone.key +genkey wrongca-root.key +genkey wrongca.key +genkey wrongca-gone.key +genkey wrongca-int.key + +issue dated-root-cert.pem "wolfSSL Chain Test Dated Root" root.key self \ + root.key ca_ext $LONG $LONG_END +issue expired-root-cert.pem "wolfSSL Chain Test Expired Root" \ + expired-root.key self expired-root.key ca_ext $OLD $OLD_END +issue expired-root-leaf-cert.pem "wolfSSL Chain Test Expired Root Leaf" \ + leaf.key expired-root-cert.pem expired-root.key leaf_ext $LONG $LONG_END +issue expired-int-cert.pem "wolfSSL Chain Test Int" int.key \ + dated-root-cert.pem root.key ca_ext $OLD $OLD_END +issue dated-int-cert.pem "wolfSSL Chain Test Int" int.key \ + dated-root-cert.pem root.key ca_ext $LONG $LONG_END +issue dated-int-leaf-cert.pem "wolfSSL Chain Test Int Leaf" leaf.key \ + dated-int-cert.pem int.key leaf_ext $LONG $LONG_END +issue notca-root-cert.pem "wolfSSL Chain Test Not CA Root" notca.key self \ + notca.key notca_ext $LONG $LONG_END +issue notca-root-leaf-cert.pem "wolfSSL Chain Test Not CA Root Leaf" \ + leaf.key notca-root-cert.pem notca.key leaf_ext $LONG $LONG_END +issue nobc-root-cert.pem "wolfSSL Chain Test No BC Root" nobc.key self \ + nobc.key nobc_ext $LONG $LONG_END +issue nobc-root-leaf-cert.pem "wolfSSL Chain Test No BC Root Leaf" \ + leaf.key nobc-root-cert.pem nobc.key leaf_ext $LONG $LONG_END +issue v1-root-cert.pem "wolfSSL Chain Test V1 Root" v1.key self v1.key \ + none $LONG $LONG_END +issue v1-root-leaf-cert.pem "wolfSSL Chain Test V1 Root Leaf" leaf.key \ + v1-root-cert.pem v1.key v1_leaf_ext $LONG $LONG_END +issue cross-root-cert.pem "wolfSSL Chain Test Dated Root" root.key \ + expired-root-cert.pem expired-root.key ca_ext $LONG $LONG_END +issue renewed-root-cert.pem "wolfSSL Chain Test Expired Root" \ + renewed-root.key self renewed-root.key ca_ext $NEW $LONG_END +issue renewed-root-leaf-cert.pem "wolfSSL Chain Test Renewed Root Leaf" \ + leaf.key renewed-root-cert.pem renewed-root.key noaki_leaf_ext $LONG \ + $LONG_END +issue expired-root-int-cert.pem "wolfSSL Chain Test Expired Root Int" \ + expired-root-int.key expired-root-cert.pem expired-root.key ca_ext \ + $LONG $LONG_END +issue expired-root-int-leaf-cert.pem \ + "wolfSSL Chain Test Expired Root Int Leaf" leaf.key \ + expired-root-int-cert.pem expired-root-int.key leaf_ext $LONG $LONG_END +issue dated-root-late-cert.pem "wolfSSL Chain Test Dated Root" root.key self \ + root.key ca_ext $NEW $LONG_END +issue cross-root-late-cert.pem "wolfSSL Chain Test Dated Root" root.key \ + expired-root-cert.pem expired-root.key ca_ext $NEW $LONG_END +issue expired-root-link-cert.pem "wolfSSL Chain Test Expired Root" \ + expired-root-link.key expired-root-cert.pem expired-root.key ca_ext \ + $LONG $LONG_END +issue expired-root-old-link-cert.pem "wolfSSL Chain Test Expired Root" \ + expired-root-link.key expired-root-cert.pem expired-root.key ca_ext \ + $OLD $OLD_END +issue expired-root-link-leaf-cert.pem \ + "wolfSSL Chain Test Expired Root Link Leaf" leaf.key \ + expired-root-link-cert.pem expired-root-link.key leaf_ext $LONG $LONG_END +issue expired-root-nokid-cert.pem "wolfSSL Chain Test Expired Root" \ + expired-root-nokid.key self expired-root-nokid.key nokid_ca_ext $LONG \ + $LONG_END +issue nokid-root-cert.pem "wolfSSL Chain Test No Key Id Root" nokid-root.key \ + self nokid-root.key nokid_ca_ext $LONG $LONG_END +issue badkid-int-cert.pem "wolfSSL Chain Test Bad Key Id Int" badkid-int.key \ + nokid-root-cert.pem nokid-root.key badkid_ca_ext $OLD $OLD_END +issue badkid-int-leaf-cert.pem "wolfSSL Chain Test Bad Key Id Int Leaf" \ + leaf.key badkid-int-cert.pem badkid-int.key leaf_ext $LONG $LONG_END +issue noaki-root-cert.pem "wolfSSL Chain Test No AKI Root" noaki-root.key \ + self noaki-root.key noaki_ca_ext $LONG $LONG_END +issue noaki-root-link-cert.pem "wolfSSL Chain Test No AKI Root" \ + noaki-link.key noaki-root-cert.pem noaki-root.key ca_ext $LONG $LONG_END +issue noaki-root-leaf-cert.pem "wolfSSL Chain Test No AKI Root Leaf" \ + leaf.key noaki-root-cert.pem noaki-root.key leaf_ext $LONG $LONG_END + +# A forged chain. The subject key id 00:00:... puts forge-fake-int-cert in +# the first row of the cert manager's CA table, before forge-int-cert, so a +# lookup by name finds it first. forge-fake-self and forge-junk-self only +# sign other certs. +issue forge-root-cert.pem "wolfSSL Chain Test Forge Root" forge-root.key \ + self forge-root.key ca_ext $LONG $LONG_END +issue forge-int-cert.pem "wolfSSL Chain Test Forge Int" forge-int.key \ + forge-root-cert.pem forge-root.key forge_int_ext $LONG $LONG_END +issue forge-fake-self.pem "wolfSSL Chain Test Forge Int" forge-fake.key \ + self forge-fake.key forge_fake_ext $LONG $LONG_END +issue forge-junk-self.pem "wolfSSL Chain Test Forge Int" forge-junk.key \ + self forge-junk.key forge_fake_ext $LONG $LONG_END +issue forge-q-cert.pem "wolfSSL Chain Test Forge Q" forge-q.key \ + forge-fake-self.pem forge-fake.key noaki_ca_ext $LONG $LONG_END +issue forge-fake-int-cert.pem "wolfSSL Chain Test Forge Int" forge-fake.key \ + forge-q-cert.pem forge-q.key forge_fake_ext $LONG $LONG_END +issue forge-fake-int-leaf-cert.pem "wolfSSL Chain Test Forge Fake Int Leaf" \ + leaf.key forge-fake-int-cert.pem forge-fake.key leaf_ext $LONG $LONG_END +issue forge-bad-sub-cert.pem "wolfSSL Chain Test Forge Sub" forge-sub.key \ + forge-junk-self.pem forge-junk.key ca_ext $LONG $LONG_END +issue forge-sub-cert.pem "wolfSSL Chain Test Forge Sub" forge-sub.key \ + forge-fake-self.pem forge-fake.key noaki_ca_ext $LONG $LONG_END +issue forge-sub-leaf-cert.pem "wolfSSL Chain Test Forge Sub Leaf" leaf.key \ + forge-sub-cert.pem forge-sub.key leaf_ext $LONG $LONG_END + +# Two paths to the issuer of alt-int-leaf-cert: through alt-int-cert to +# alt-root-cert, or through alt-end-cert, which alt-gone-self signed and so +# ends nowhere. +issue alt-root-cert.pem "wolfSSL Chain Test Alt Root" alt-root.key self \ + alt-root.key ca_ext $LONG $LONG_END +issue alt-int-cert.pem "wolfSSL Chain Test Alt Int" alt-int.key \ + alt-root-cert.pem alt-root.key ca_ext $NEW $LONG_END +issue alt-gone-self.pem "wolfSSL Chain Test Alt Gone" alt-gone.key self \ + alt-gone.key ca_ext $LONG $LONG_END +issue alt-end-cert.pem "wolfSSL Chain Test Alt End" alt-end.key \ + alt-gone-self.pem alt-gone.key ca_ext $LONG $LONG_END +issue alt-end-int-cert.pem "wolfSSL Chain Test Alt Int" alt-int.key \ + alt-end-cert.pem alt-end.key ca_ext $LONG $LONG_END +issue alt-old-int-cert.pem "wolfSSL Chain Test Alt Int" alt-int.key \ + alt-end-cert.pem alt-end.key ca_ext $OLD $OLD_END +issue alt-notca-int-cert.pem "wolfSSL Chain Test Alt Int" alt-int.key \ + alt-end-cert.pem alt-end.key notca_ext $LONG $LONG_END +issue alt-int-leaf-cert.pem "wolfSSL Chain Test Alt Int Leaf" leaf.key \ + alt-int-cert.pem alt-int.key leaf_ext $LONG $LONG_END + +# A trusted issuer whose key did not sign: wrongca-int-cert names +# wrongca-cert's name as its issuer and has no authority key id, but the key +# of wrongca-gone-self signed it. wrongca-old-int-cert is its untrusted twin, +# out of date, with the authority key id of that key. +issue wrongca-root-cert.pem "wolfSSL Chain Test Wrong CA Root" \ + wrongca-root.key self wrongca-root.key ca_ext $LONG $LONG_END +issue wrongca-cert.pem "wolfSSL Chain Test Wrong CA" wrongca.key \ + wrongca-root-cert.pem wrongca-root.key ca_ext $LONG $LONG_END +issue wrongca-gone-self.pem "wolfSSL Chain Test Wrong CA" wrongca-gone.key \ + self wrongca-gone.key ca_ext $LONG $LONG_END +issue wrongca-int-cert.pem "wolfSSL Chain Test Wrong CA Int" \ + wrongca-int.key wrongca-gone-self.pem wrongca-gone.key noaki_ca_ext \ + $LONG $LONG_END +issue wrongca-old-int-cert.pem "wolfSSL Chain Test Wrong CA Int" \ + wrongca-int.key wrongca-gone-self.pem wrongca-gone.key ca_ext $OLD \ + $OLD_END +issue wrongca-int-leaf-cert.pem "wolfSSL Chain Test Wrong CA Int Leaf" \ + leaf.key wrongca-int-cert.pem wrongca-int.key leaf_ext $LONG $LONG_END + +crl int-crl.pem dated-int-cert.pem int.key +crl dated-root-empty-crl.pem dated-root-cert.pem root.key +revoke expired-int-cert.pem dated-root-cert.pem root.key +crl dated-root-crl.pem dated-root-cert.pem root.key + +# Only now, so a failed run leaves the certs and CRLs as they were. +cp "$WORK"/*-cert.pem "$WORK"/*-crl.pem . +echo "Completed" diff --git a/certs/intermediate/trust_anchor/int-crl.pem b/certs/intermediate/trust_anchor/int-crl.pem new file mode 100644 index 00000000000..fc26971c912 --- /dev/null +++ b/certs/intermediate/trust_anchor/int-crl.pem @@ -0,0 +1,11 @@ +-----BEGIN X509 CRL----- +MIIBnDCBhQIBATANBgkqhkiG9w0BAQsFADAhMR8wHQYDVQQDDBZ3b2xmU1NMIENo +YWluIFRlc3QgSW50Fw0wMDAxMDEwMDAwMDBaFw00OTEyMzEyMzU5NTlaoDAwLjAf +BgNVHSMEGDAWgBTNWHR2YyG4UlQTWJ+oRDsGtqtOzTALBgNVHRQEBAICEAAwDQYJ +KoZIhvcNAQELBQADggEBAJtW0FfVR3p8+bJV01Xb4HG2qeHOsjDTSx3yMF10h1aL +xaMt6kQx7BoAQLA/SN1GnyK/h5Jdn6NWioabxbH5qjJ+XMIdRK0tX/uOHL+wiVZ1 +5pm+vR8W/Lko3XR1gd5mL03vm4SDXE5/6ja2AypWIuq8dtfdKBPfhiuxHlUckbDw +w+KllHwnLkVVwrVq7/ilmuj18d5QwyEuHy2nUhr+GcS2L+6VyKfgf2Fv9jqEe1sD +qVnIWADZK7zAIZ05LqCb85dv0lqJV/2L9ko4D5BVJfbv3oX9H/SqxWSE0L1cPs7C +s8WslATFIt6f4tqndj3FpsC5hQNWVDd/wF3o8s9WGqc= +-----END X509 CRL----- diff --git a/certs/intermediate/trust_anchor/leaf-cert.pem b/certs/intermediate/trust_anchor/leaf-cert.pem new file mode 100644 index 00000000000..7adb5adda77 --- /dev/null +++ b/certs/intermediate/trust_anchor/leaf-cert.pem @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDLzCCAhegAwIBAgIBBDANBgkqhkiG9w0BAQsFADApMScwJQYDVQQDDB53b2xm +U1NMIFRydXN0LUFuY2hvciBUZXN0IFJvb3QwIBcNMjYxMDIxMTI0NzAxWhgPMjA1 +NjEwMjAxMjQ3MDFaMCkxJzAlBgNVBAMMHndvbGZTU0wgVHJ1c3QtQW5jaG9yIFRl +c3QgTGVhZjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKcyOCJ5zCTQ +h+pEebPAzTbxb168tT9kDu6BcI6ZY5j/qBiIdHBKAwKnUzYvxXl1oWUshz9lSN60 +pT+Xi4M8BJT7hp1ZeYNCKP+hHBDqoqjlBJZa38YzjWCBWDHfl7LhexKO6PsXPSA8 +IzEcpc798rF5VGT37yY6QJwiuL3JqYGWvys3mJlFV9Q9WD5aCZBJpF8huPgzwdKI +xVZOMEvsyRINyBqx8ixijAOGjZV/AFM1gAUR49AGOBPY/QYiC0LlUm7c1ZvvqQ9b +SsoKU8kqhucYM6EHTk9+VTnPnk+3hSkHjGzs+DcfP55rcZivEN6+LzlIBe8RxW6D +ZeixglU0jjUCAwEAAaNgMF4wDAYDVR0TAQH/BAIwADAOBgNVHQ8BAf8EBAMCB4Aw +HQYDVR0OBBYEFLPjVkrc2IFpN8IOcXQDYuaLIAmNMB8GA1UdIwQYMBaAFID3Ff/B +1OglhclVjdLKGxCuWkyJMA0GCSqGSIb3DQEBCwUAA4IBAQBt2A/Yzw/0BvtJlOoq +duhiATreEm2nH9ej3RVeCOAdcpZuh5Tv0dX0NSgtT6L/p0P0Ag6Sq77qSB2o7DZJ +axxtIxIpn7belfv3A+wsYW67hz0XVBQAwjpoWoq55jel8lov6kfj5btdcO+A+Z05 +RDUnCSlnxnjJxYdcGdyzW4f7LXeWgTGsU3RyqXSzG2kUzV5NMANI08XqdX2eCJJs +oXrkCznaDsRTT4u5JyjtKzCWs5kYvHA4txFBsaKs8fH/+OVp3Xk6mtgIWAzeaz9x +aXl7owqqo3RcUyo3giYojD+IRtlWi8uJ++9g0C1uyjqxOFFMrEFHm1MMl94Wdzu+ +fF0f +-----END CERTIFICATE----- diff --git a/certs/intermediate/trust_anchor/leaf-key.pem b/certs/intermediate/trust_anchor/leaf-key.pem new file mode 100644 index 00000000000..dd9115b5906 --- /dev/null +++ b/certs/intermediate/trust_anchor/leaf-key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCnMjgiecwk0Ifq +RHmzwM028W9evLU/ZA7ugXCOmWOY/6gYiHRwSgMCp1M2L8V5daFlLIc/ZUjetKU/ +l4uDPASU+4adWXmDQij/oRwQ6qKo5QSWWt/GM41ggVgx35ey4XsSjuj7Fz0gPCMx +HKXO/fKxeVRk9+8mOkCcIri9yamBlr8rN5iZRVfUPVg+WgmQSaRfIbj4M8HSiMVW +TjBL7MkSDcgasfIsYowDho2VfwBTNYAFEePQBjgT2P0GIgtC5VJu3NWb76kPW0rK +ClPJKobnGDOhB05PflU5z55Pt4UpB4xs7Pg3Hz+ea3GYrxDevi85SAXvEcVug2Xo +sYJVNI41AgMBAAECggEAIhUXI1P/vNtzcVpvEqjxTEtwH/hI3Di54H2rY646AtTO +v92FGuTDc1WHnWqkjyte8KBgm5g6gAeEDhAG5QQljPcvDEFSh2LDt8RwU7R43wP8 +aOfyaNVWcv866sPBCTp0m6ZdMN4eXEVWCStlU2oqAGqSvRhbfEfwpsNfNHT45Ezx +ldcP2XJfgQGzyX1HJIm9Fqn5fBf5b/RdAcUtIIFYuPezSK2OQsUVtbyEIfJsv3BL +KRcdnBRKrAK/XULyG/wjQk1rru/d8RRLiBzzecKSrl2n2y02YAxtRNbXXqD3CkTO +qpOpAybQwrdSVgLYJeyoDdCQRjOgdEw880sZPaTX4QKBgQDXX0x6n5EKVmO1dwwm +CSp6ie0+2TaTGO+jlxLH2jujxbCfw8NXr+TZPoPZNZRYDhpA9aUArUwF5bZLVKz5 +OIMzG1Q3G63XbXkfmvq9+/kUeuqjkvEvsBET0uE6ij2bkyBgDmt1u5Z9JMJbnVK7 +FQ6bzw4JKInxiZVYOMk5dg64kQKBgQDGvGnJVb8hYc/Fa6PDNFLD62TSJtse6tlu +leyMEELj97me8pJz4xH8pN7zN+xx/End1R5TwkZ6pYdCwJlno+rQCJEjGREP/1V8 +YGxs3dqap7puSNZFAAJQS7V7pfeCVYemaDcIiWRVaXAddVrHp7vb/jmaOlI8seCp +7VdPl9BtZQKBgDqUv1azRF5NdT2Mrg9Cev1tusxXhNKp+7TBiOg3YfV/9jTeqKmX +PGYi7PYN7tWssFNu/XybpowMGXOQCqSXTIiALH3412Y7brC8FOvMN8nsTRpFA7l2 +6I490+l6ZJuGf03hXjVd2ucbMop81l3wslKLFUREdJDwXWDrwUAR7pshAoGBAMZC +iLZWWIqQ7ZnhvEmtFTRmzPnp0YeSer+byZQhVNnf9Mng7MG3seX9BH5XOAauzXIE +fnDIy07ne3zYbzG5kTNgmIoPI7p1225tMz2YRdErqw0ClN/ZFnXMUYy9EaJweRdF +uEFH71RWD4cT4DB14S+i+wwlSo1KVvquz/+TUFcRAoGABO67ydAUOd4tRQf83xNY +OLw8lEcEv+fuTAKDFKTZ4mZKX8ONOe2nShcX6MJTehCKqqkbHtNX66HNeyFNQcp9 +STP2nEp5X6KfZjJPbMZ6Z0jwJFHjMsbXElr37Gff9nEa1F3ckWp+/uuzh3XWNs8C +bDsXCgIZiylm6kVzqSoARmY= +-----END PRIVATE KEY----- diff --git a/certs/intermediate/trust_anchor/link-cert.pem b/certs/intermediate/trust_anchor/link-cert.pem new file mode 100644 index 00000000000..3e349d2abbb --- /dev/null +++ b/certs/intermediate/trust_anchor/link-cert.pem @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDMjCCAhqgAwIBAgIBAjANBgkqhkiG9w0BAQsFADApMScwJQYDVQQDDB53b2xm +U1NMIFRydXN0LUFuY2hvciBUZXN0IFJvb3QwIBcNMjYxMDIxMTI0NzAxWhgPMjA1 +NjEwMjAxMjQ3MDFaMCkxJzAlBgNVBAMMHndvbGZTU0wgVHJ1c3QtQW5jaG9yIFRl +c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMCbixPO1Frv +E9KsBdoku1IDW2vswd98ZlLO524GaOf5wMpkOyM7SpB2CHDfJmC6FGbGHO7WqF35 +LiPbIXc/KaGUndOBg4nyoDo11fPY4ky3b5a6qDqLVys3ZiBvrtEs4DiuAzcurxQj +cv52r9gMaSkc5hFmopR9ljb56IUtv9QlXq/ihD06vv/t9m9GXI8pIwulLH4oMEE0 +bESAozPEo7I4d9veDFpEh4l2wxwE6ukrffMZ+b2WU8Jn6T1tkzB+noyVl+7RdV2h +S3YzQJ+DxB6YSImsYpszpV4uJ/3wZMXaiyfwpp7jcbdj+WbQyeT3+mKj6uGQrQCO +DznAIaDlW88CAwEAAaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +AYYwHQYDVR0OBBYEFID3Ff/B1OglhclVjdLKGxCuWkyJMB8GA1UdIwQYMBaAFIwO +RxqU9YE1l9Tosboq5IOhHV4nMA0GCSqGSIb3DQEBCwUAA4IBAQCQ7y5ehDBrJw82 +C/cmeqwyrv0pNuFcyd3a5NqFsF05rQhTUdA5pJGMLLLPsHAJsy2emEI/AcrX2oX8 +A4Djb2N6yQsMwBptNa4KdfOKjxyw0Htd5ApDPjzIbDjqjwJ/7DeAkzxRUarYLh5D +u4a1Al2xmjxeAK3Joxbxt7++2KCsF3ptr8A2PnUgKh1j8+SvlC9arb4Xi9B4ObWq +pHqZm2lJTt/n2g3/e1IWrKQ7HI5QgtAzmJ1yebqJb8brJ98N7NBe1Kba92kZyWvA +8jTi2YKlQmMLzGbUfVhYmAx2MbS7KdonLX3iy5XKS4YrSV1v4HyCEqDMehrQZZWJ +ssLik18d +-----END CERTIFICATE----- diff --git a/certs/intermediate/trust_anchor/link-key.pem b/certs/intermediate/trust_anchor/link-key.pem new file mode 100644 index 00000000000..3684ce3f4d1 --- /dev/null +++ b/certs/intermediate/trust_anchor/link-key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDAm4sTztRa7xPS +rAXaJLtSA1tr7MHffGZSzuduBmjn+cDKZDsjO0qQdghw3yZguhRmxhzu1qhd+S4j +2yF3PymhlJ3TgYOJ8qA6NdXz2OJMt2+Wuqg6i1crN2Ygb67RLOA4rgM3Lq8UI3L+ +dq/YDGkpHOYRZqKUfZY2+eiFLb/UJV6v4oQ9Or7/7fZvRlyPKSMLpSx+KDBBNGxE +gKMzxKOyOHfb3gxaRIeJdsMcBOrpK33zGfm9llPCZ+k9bZMwfp6MlZfu0XVdoUt2 +M0Cfg8QemEiJrGKbM6VeLif98GTF2osn8Kae43G3Y/lm0Mnk9/pio+rhkK0Ajg85 +wCGg5VvPAgMBAAECggEADwTR+SRv+KXwihqchjXGXuR2H4ShsCyXdK4/lkZtAxG9 +j8qgYI9CBuESqBfZJUJn+YT0l/HTGn4mCT5lbf1V4LdMVe7LyVj1rN7/z6OXhIXq +mfqfcu6PSIZpse5415oZOIeRJp9poDdiGHzmxKu1vjKhBLWtHckWiojoMbevNU/l +7biKAqv6aFxXq4ftI7BiKtQfLNc8uzfDKt0IleSixPIz5aWVEPAsstM14XVMCacK +jUcN03rCR83sIJzHhX1vsyPY0BWY+uT4bbU0XwzgGOKeswaZxGxDf9ohiFMWy1MW +D3eaZdNzG+ISq8ObSBIQoeLftLE81sCm8knv7EvXsQKBgQDw7nAlX5JQjhe04n/u +UiL/u48VQBHD0um+PLiX1R+GEnuSnFjwSvgftMoT7bxmh11CnTd8Hkohgp1Sz3Gx +OjkqzKaROS+A/9jqoVW96u/BdSW5zPEV/71RjrJmfb4OE9pf0T3ETpkYmDTd/+YC +xrZYBUM+e1n+35/5B+BslMuPiQKBgQDMp2QOlkpZjhHEUd4O8cF3KRkleKTp+ntR +rLuZNTSnUk9L4fxuvWYBYyovm0NzDUZ/pgW8Q4uPrkXsg/JbpRp+sQt/vc+WZczj +JMSPO6MyyAk6vxIwuFk58G5HIVpoiqpr5klkQRG+mMVpwhNJC9q0av6kX1p85yEy +wG6iFUeilwKBgHyYkl6BgkUudowQ5l/1Eix2bpRqwcUnecHr3PqIOPk47bbwK/54 +hsC+2hJcS6YqMsyUSXFiqKuTxJBiv0UL+yxrEWjgzfREW4VbUeAZc0v0rUHc/oCF +9P4Mca4XMQZOtgv/RZYTn5DchdqYz/Z3lS0H67KQUAZC15QNwr3kZTEhAoGARw67 +xADU0eFtM9AFHQU92kTv0T3hbMgmt0YVYO3DWXFPzRYrErw6RbMLu7naIoFyf/HC +Pgrp0zp8VtG9faqG14RbbMAX6q1wBVIH2X+oe4JPChG7nCT1/hMIBzSCcpfq8knk +I6YgJiBfMwhKr+soxcn8nk/pWELcGQYNo8NluwMCgYBcjVqrHJ6u5bBmum+kIWi5 ++RS31zflxruy0oX+55NndS4TFqnHP6lmVnnHeZIzBxqfKKjJAqy3o4zF+zKQ+E/+ +5BSQVZ2fHiuHLMdOVfXUNrOR/CTd5TFrP00mCZP6XcLqDC2RyC1oJ1elKpxfGsNF +5eLgn6AYerET6zBr80DH0A== +-----END PRIVATE KEY----- diff --git a/certs/intermediate/trust_anchor/link-noaki-cert.pem b/certs/intermediate/trust_anchor/link-noaki-cert.pem new file mode 100644 index 00000000000..814575c68a1 --- /dev/null +++ b/certs/intermediate/trust_anchor/link-noaki-cert.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDETCCAfmgAwIBAgIBAzANBgkqhkiG9w0BAQsFADApMScwJQYDVQQDDB53b2xm +U1NMIFRydXN0LUFuY2hvciBUZXN0IFJvb3QwIBcNMjYxMDIxMTI0NzAxWhgPMjA1 +NjEwMjAxMjQ3MDFaMCkxJzAlBgNVBAMMHndvbGZTU0wgVHJ1c3QtQW5jaG9yIFRl +c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMCbixPO1Frv +E9KsBdoku1IDW2vswd98ZlLO524GaOf5wMpkOyM7SpB2CHDfJmC6FGbGHO7WqF35 +LiPbIXc/KaGUndOBg4nyoDo11fPY4ky3b5a6qDqLVys3ZiBvrtEs4DiuAzcurxQj +cv52r9gMaSkc5hFmopR9ljb56IUtv9QlXq/ihD06vv/t9m9GXI8pIwulLH4oMEE0 +bESAozPEo7I4d9veDFpEh4l2wxwE6ukrffMZ+b2WU8Jn6T1tkzB+noyVl+7RdV2h +S3YzQJ+DxB6YSImsYpszpV4uJ/3wZMXaiyfwpp7jcbdj+WbQyeT3+mKj6uGQrQCO +DznAIaDlW88CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +AYYwHQYDVR0OBBYEFID3Ff/B1OglhclVjdLKGxCuWkyJMA0GCSqGSIb3DQEBCwUA +A4IBAQCFVADQ0o8nBgvQFcFmu6GWNJmaOVMAlAzB8OAO21UnoobtJSRMKXbM1iaL +9clY2bWPBbGWq97AfLedYZOGuv2d+bXUU/75wfdwyEIKLojSn0LB2QxIwkWLAqHz +yTINOZ8pBkHenFm91dRGs36jTw0D2W7dX3jQK5TL+d6uBrXmVqW/TZ16KvGQ5G4W +CYUtnJmMnim7vJ+tnEpfk3fZpCnzD5c8Y/n1bsE2xzhPs3TDGgubb7ts9lv/sIb0 +gmVae8+kZykJNc+72EASoUN8HUOxkvhGFHnlw1yxi9gxtq2TBl1js1oaxY7F2Gkd +7N/R6igT1mgH3IHbe9853C9pXPBF +-----END CERTIFICATE----- diff --git a/certs/intermediate/trust_anchor/noaki-root-cert.pem b/certs/intermediate/trust_anchor/noaki-root-cert.pem new file mode 100644 index 00000000000..2a2e8252c7a --- /dev/null +++ b/certs/intermediate/trust_anchor/noaki-root-cert.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDEDCCAfigAwIBAgICEBkwDQYJKoZIhvcNAQELBQAwKTEnMCUGA1UEAwwed29s +ZlNTTCBDaGFpbiBUZXN0IE5vIEFLSSBSb290MB4XDTAwMDEwMTAwMDAwMFoXDTQ5 +MTIzMTIzNTk1OVowKTEnMCUGA1UEAwwed29sZlNTTCBDaGFpbiBUZXN0IE5vIEFL +SSBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqwGk6FcP12Wd +9ST4BAyGiVGzwu3EKiT2LKzPcghRsTUWheLfZZYCgnb3hf9yqXcVOsR9ZoIURrHS +MYeQoY4tOGviv7JITa/YEZEkrNBLk0aE9yi/sNhStQ8nA8YvcGrkYyzqKBjml7/F +SmWMSOTCyKxI+TwAMj3JXSPpv3vzeYsl9nyfH+JZrNRRJgQX71vYpFqH9y6o6P7K +rl3wOtWjZebNI/DzJPT0zl7cV6haxBWLovf5QeQZR2b2+JbCvVPWivRO6Dh29WSf +njxYC2HmX6V9xDe9Aj3ApDvsdUdW8Phl0p29iQqU2EQBAPwI3cDkwlLMSXsqX/v7 +ZA+OgddKSQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB +BjAdBgNVHQ4EFgQUYph4W3RTyMWoquBRIxpEKmDhaXowDQYJKoZIhvcNAQELBQAD +ggEBAAWLe4GpwqnTcM7ogMZ5e806v6Ls74Vte+4JHHMykBXBNvheyF7OO35+2PuD +x9sGmmYLyOY/Xc7Q2sbPVGwLvjmBBOcvZywrnFbtUgxbgNLMwhGNQg56bQSyZnXX +FJkELinkFNLEyygcQK/spWm9T9fGzNl85uzMhhuxz6Gm4DLdAFy+FMLi1LRwxWE1 +gxJoPFCFTGkq3q437cIf2+2SnBRlU0PFnDhwYpsO0or/yH1ff+3RH9WQB8FluEkS +RBGHXqBU4AQY6LpDP5KCaXFPSk3a8WdEBM7eBgSA5w+L8YdBlZjp88SYmozJHdXt +nLYjHrhS8tpfR/D5TJAfS5Oi4kg= +-----END CERTIFICATE----- diff --git a/certs/intermediate/trust_anchor/noaki-root-leaf-cert.pem b/certs/intermediate/trust_anchor/noaki-root-leaf-cert.pem new file mode 100644 index 00000000000..15496422307 --- /dev/null +++ b/certs/intermediate/trust_anchor/noaki-root-leaf-cert.pem @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDMzCCAhugAwIBAgICEBswDQYJKoZIhvcNAQELBQAwKTEnMCUGA1UEAwwed29s +ZlNTTCBDaGFpbiBUZXN0IE5vIEFLSSBSb290MB4XDTAwMDEwMTAwMDAwMFoXDTQ5 +MTIzMTIzNTk1OVowLjEsMCoGA1UEAwwjd29sZlNTTCBDaGFpbiBUZXN0IE5vIEFL +SSBSb290IExlYWYwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDQ6M5g +fTl6yl6X0wiRUDORCrdVZVu1pBcl2lq4rsubHgUz9rORSBsS9/Cea8YOt9kVq+gj +ftiVHsSdPiKCVN4Mu1KtPIaAPEljMqOZX9wQK6VPYFjb404gkxAKmijqLeYVHITM +N6NxcG6DBapvlAJqyJtbwtT8lxVN4P3mUdn4Y2eNFOYhOTSou52QXVsxuS0UjCqT +NvvV5P0z3K+nnKEGCUNErcWEmX+zp4j4aNTL5UjpD4UN5PkW71iQBEvXzzwr++ba +Pc7eGUlCZnItjQksv/iam6Hw7M/Gcnc2e2hHdlx3nzswd8gB6So3KyxP9dI9/J72 +8v9stoJiiS+d39UNAgMBAAGjYDBeMAwGA1UdEwEB/wQCMAAwDgYDVR0PAQH/BAQD +AgeAMB0GA1UdDgQWBBTD5WGW3KdPoBYEDzUq1sHQGJK+5DAfBgNVHSMEGDAWgBRi +mHhbdFPIxaiq4FEjGkQqYOFpejANBgkqhkiG9w0BAQsFAAOCAQEAKxgoJbVrPfAB +C4eqadevk9spAHtV9mavIBNP4kSba7lsRNC+JjwXkDjvs0puq30ab2iL5uB5ROMd +02GmTq9WD5kIbY0+ksVIl9Q7rINlozPHP6XVAWWxx2EwlE2vLo7T7YzwRMWr+kr9 +89HbVIjWeFxu2KsRhpr4i6XbQ2Zj+bIgtTK62BzekjMPfGlYE9BpsMAkZAxjVN7t +2VhYPrAez0K7QfluBIhXx7Uv8v78JM2a2Fec3pSr6IRXlts2Fo0CwGMl/CfjVlLg +CyoT+CF+/TQzXgBWC7ly8x8h8RiYY+v9PfeJS/jKEvt9WIPVGgk0z9J+E877hX0Q +berTIgvZZw== +-----END CERTIFICATE----- diff --git a/certs/intermediate/trust_anchor/noaki-root-link-cert.pem b/certs/intermediate/trust_anchor/noaki-root-link-cert.pem new file mode 100644 index 00000000000..c1171d8b01e --- /dev/null +++ b/certs/intermediate/trust_anchor/noaki-root-link-cert.pem @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDMTCCAhmgAwIBAgICEBowDQYJKoZIhvcNAQELBQAwKTEnMCUGA1UEAwwed29s +ZlNTTCBDaGFpbiBUZXN0IE5vIEFLSSBSb290MB4XDTAwMDEwMTAwMDAwMFoXDTQ5 +MTIzMTIzNTk1OVowKTEnMCUGA1UEAwwed29sZlNTTCBDaGFpbiBUZXN0IE5vIEFL +SSBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6EV+czr84HTk +o4xKINhMvQ2DRIiY9XwsP0nZqafTfH8ZwDhLd5ziiIDUDDamB2277exSJzv+5YZh +PaE79OiQBHUjcgy/OX+ewCSyvcegAWpvYwzcQ3hUw5X/c5S/vzQWw6K12eJiILmG +j9k+XpUKpzr+faiGwJYWq3t2STBtwx7qOzxbvS2gaUZGg/dzsHPOiBJGCMvYr2t7 +rlnkFRVnczWx8jrYwO7NozuNvjccCqH5synrT0s2D11QdBqs4WT+bOw9shQyTwUe +j5mgwboR0isjYpuAqVOqinTugVALLRsu/v48GrN+iRY1ahb+74BepsjDGiN8c7iy +Q1IrwrtYtwIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB +BjAdBgNVHQ4EFgQUcjqT/XBIBwt5wH6d5sZyXAvl7zEwHwYDVR0jBBgwFoAUYph4 +W3RTyMWoquBRIxpEKmDhaXowDQYJKoZIhvcNAQELBQADggEBAJiPVTfBz7v/ECbk +bFpwyBqt4jgjeSm8hv/8uaTagygeuWhmRE8zKhKLJvNxIhZxYorWnOqJM68rpCmx +OFCxIk5oa5N9nlPoT6K0zk6Q1i8D6IlDsQ7KHW/sKyoqPnD6N7svV/0P1pzFhrj3 +TC55wNMd/UyRRD+5/WCmLIYGJxapik61oM4qNJZQxqckeLUt7//+eTkkqHmKdcu/ +4HVacI+sXfRHr1+eOWBpkQqYrfbTlrGPXODFefUXDHGuNNizY++JP/niD3Av2Hl1 +gjbA1v0BpiN0KEc+Iu1VMq+84M46Rx5aLF7moxwyspG0KZVA0uMx2Y+aylMsEQ5O +sUPdmZs= +-----END CERTIFICATE----- diff --git a/certs/intermediate/trust_anchor/nobc-root-cert.pem b/certs/intermediate/trust_anchor/nobc-root-cert.pem new file mode 100644 index 00000000000..7b97c7f5dbc --- /dev/null +++ b/certs/intermediate/trust_anchor/nobc-root-cert.pem @@ -0,0 +1,18 @@ +-----BEGIN CERTIFICATE----- +MIIC7TCCAdWgAwIBAgICEAgwDQYJKoZIhvcNAQELBQAwKDEmMCQGA1UEAwwdd29s +ZlNTTCBDaGFpbiBUZXN0IE5vIEJDIFJvb3QwHhcNMDAwMTAxMDAwMDAwWhcNNDkx +MjMxMjM1OTU5WjAoMSYwJAYDVQQDDB13b2xmU1NMIENoYWluIFRlc3QgTm8gQkMg +Um9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPcrAsuJSdliuRlx +XWN62ntyUw/6FVnI9GK6kOMca3RNsqNQp4zX+0oalIW/dTVb6S8M0hGS1bxp1fe2 +t+Z7mT5DHVu4y3mH8yWw1a/mlUayl8GogMPgqwhoZe14ZxE9DV9ElAPz6rwhM9EI +dZmqQ2Er5a2jux71Dcw5fKXj/0I2cTW7t5pCBoD6A4WbWXKIb9hB8bDa5oplYGsN +rXECzxXrzkW0aEiKZ7dkr6Dmwwif/Ll7lIzZWpHLvfywmUSldxJcACN/2PP5XIem +hnk4ause87KYIcVsf1QXVg0sVYTTId0L3EaQbrDbChz4s5X5/sq1aCwf7xtH1sb1 +VbzbWv8CAwEAAaMhMB8wHQYDVR0OBBYEFEGUVuWZbyydxi1h1NJQuRrW2IyYMA0G +CSqGSIb3DQEBCwUAA4IBAQDFLhJgi+dnvjw7PdJ3Ud/XJF+pKQvHIXH4hEVbpUQu +e+bAnG0XhRa1P5sJifUhjNPhzXHrylzhqy+YJa0ISDgnVuFZsMow5WRW5II+He0B +OINZsXv/nouTLhhxCcgolsR3yCpn/noYJizKFahvbc7s2uvVP4E/doz3XU0EnRvk +CxdUrl/8bxazC6KI/dHKXEUtTJes+yLZkG0874OMsEK2Vxo+8TYBi0yhSjJlf76m +jBw3eVT0aPatn7u74GRL2o0z/xc1bU4pV+ZxE8NqHt+dNVLo4xrbO8GfiBMhofok +IjaxWaJTc/IRXOHtKwC3XcUOfhCS1UPfsmI3qlBW+2js +-----END CERTIFICATE----- diff --git a/certs/intermediate/trust_anchor/nobc-root-leaf-cert.pem b/certs/intermediate/trust_anchor/nobc-root-leaf-cert.pem new file mode 100644 index 00000000000..c33bfd6e574 --- /dev/null +++ b/certs/intermediate/trust_anchor/nobc-root-leaf-cert.pem @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDMTCCAhmgAwIBAgICEAkwDQYJKoZIhvcNAQELBQAwKDEmMCQGA1UEAwwdd29s +ZlNTTCBDaGFpbiBUZXN0IE5vIEJDIFJvb3QwHhcNMDAwMTAxMDAwMDAwWhcNNDkx +MjMxMjM1OTU5WjAtMSswKQYDVQQDDCJ3b2xmU1NMIENoYWluIFRlc3QgTm8gQkMg +Um9vdCBMZWFmMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0OjOYH05 +espel9MIkVAzkQq3VWVbtaQXJdpauK7Lmx4FM/azkUgbEvfwnmvGDrfZFavoI37Y +lR7EnT4iglTeDLtSrTyGgDxJYzKjmV/cECulT2BY2+NOIJMQCpoo6i3mFRyEzDej +cXBugwWqb5QCasibW8LU/JcVTeD95lHZ+GNnjRTmITk0qLudkF1bMbktFIwqkzb7 +1eT9M9yvp5yhBglDRK3FhJl/s6eI+GjUy+VI6Q+FDeT5Fu9YkARL1888K/vm2j3O +3hlJQmZyLY0JLL/4mpuh8OzPxnJ3NntoR3Zcd587MHfIAekqNyssT/XSPfye9vL/ +bLaCYokvnd/VDQIDAQABo2AwXjAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIH +gDAdBgNVHQ4EFgQUw+VhltynT6AWBA81KtbB0BiSvuQwHwYDVR0jBBgwFoAUQZRW +5ZlvLJ3GLWHU0lC5GtbYjJgwDQYJKoZIhvcNAQELBQADggEBAIurJthtxaVvX5cl +7F1plvy3WXaprsx9mxWl7w7H4eOJJbxde6c6Dys4SU0Xm7E9G/b4F8Kd/hin9o5M +w09wCNUoV4+IQKdmc7D652FVFT/K4f2tMJc49anOzZFDHX51oFObw45KtEHrE1HU +6xKe4A6zitNCfhYE37OC4cqp5qcl/pAZLqjDtQe+7ZPWKTqhuqxfyu8caiZd9l/a +W+TZr7T+w/dMkg2WpDJ2rb8zAMC1zH3UaExwvnqeQlVYoImU32n9bcRwouxBiCoK +1uIU7C3hil1cKG6ha3MkYbnx+21yHDnMofp3pJo32dOydP4qkqnwmMgO8Hx935JK +VwEHhlk= +-----END CERTIFICATE----- diff --git a/certs/intermediate/trust_anchor/nokid-root-cert.pem b/certs/intermediate/trust_anchor/nokid-root-cert.pem new file mode 100644 index 00000000000..3d3eeabaf29 --- /dev/null +++ b/certs/intermediate/trust_anchor/nokid-root-cert.pem @@ -0,0 +1,18 @@ +-----BEGIN CERTIFICATE----- +MIIC9zCCAd+gAwIBAgICEBQwDQYJKoZIhvcNAQELBQAwLDEqMCgGA1UEAwwhd29s +ZlNTTCBDaGFpbiBUZXN0IE5vIEtleSBJZCBSb290MB4XDTAwMDEwMTAwMDAwMFoX +DTQ5MTIzMTIzNTk1OVowLDEqMCgGA1UEAwwhd29sZlNTTCBDaGFpbiBUZXN0IE5v +IEtleSBJZCBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAppIa +B0paJPNf1sSBAwsjVc/hxxR+BRbmLUwgOsrb9nBWNtCVHxrW1NaMCUtOrj3YFjdq +kuluB6gU46gHsemCayoYhahDtS8YMAoqFATnRowzGpjZ8ukRTd7G0WAd3d8asJXw +/ppi60L/PN7qHe6nyIQROU45SvxL4TcCx+iVnpvQdJQNMVCRzX7hGUo3Kox5niz7 +EdtYEvO6aXfBYtJ769psWVgIaY4YwTN5BNpGSYzvo0T20ChzyXiAmYnwlFvcIQej +ZpXx31Ci4iZs1I/v5UnbNNNoYu3H+27rZB0+Qo7fz8jHfC39xtk1cfuKiAm3zBzI +uaLcbiQjbEdtnp9AzwIDAQABoyMwITAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB +/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAQEAUSfAboAOB2/ns6+vSTwdCLoOMIRL +dk+oyBry9nVMdlsWstvnqyc1jO8+efC+aY3FtdFuIxz74WAAGPMFJfE7dD8hpJCI +1mtg8uMXxA/ddHos7CE0Pt4sKwKxWRDRteR3IEEDj9zluZwFCr0zCyTmIKDBWg/r +8uGQM/H+kgNYT0DoUX8BCqvpm8bbKK3Cr5HJZ/YvotgbbWFa6PcpClLYs4Zx6QZM +2LfAXmwUgvPZ5JtjOAMV94C2UVj6XO+Ka+4UOo/+1W4YLCcLGlyySWCc+KSQ8UGJ +ud49fdRQUqQaSFNISCf6TFnArCOD5Yi+sbmPA4SVUqvdSFy3rkTSLEUOMA== +-----END CERTIFICATE----- diff --git a/certs/intermediate/trust_anchor/notca-root-cert.pem b/certs/intermediate/trust_anchor/notca-root-cert.pem new file mode 100644 index 00000000000..f576fb20ca4 --- /dev/null +++ b/certs/intermediate/trust_anchor/notca-root-cert.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDHjCCAgagAwIBAgICEAYwDQYJKoZIhvcNAQELBQAwKTEnMCUGA1UEAwwed29s +ZlNTTCBDaGFpbiBUZXN0IE5vdCBDQSBSb290MB4XDTAwMDEwMTAwMDAwMFoXDTQ5 +MTIzMTIzNTk1OVowKTEnMCUGA1UEAwwed29sZlNTTCBDaGFpbiBUZXN0IE5vdCBD +QSBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAs5iYZgCCO9nh +ZcdXSfvfFGf+9O/EughyiSpFcOCNXx8WBQ885G50HCWWWlY4Niylo8cx1CZbMKme +FD64uIUXoWIIBe3JZqeQhg2ZvZfv2v0KrqN8YF2X/5jCBWMPKNeBezIfEtekJfNj +N8s++T7jqmbcQNylSMq5OrBfo07DXg4FzYMcHscbjPMVcLivVAA6BvtiuGEBhfTa +oYIRlSWmaSt0h+Arjlqqv1HGbTsQ3mb7D9Wy+LNou0HOTzahJ07wlyF/IajvYcdF +mp69UzIzW9iCzqKjIBoxn5wI/bA90GEHcd8WrJ32LUjNIkbkx3W5eCUlaueiP1Go +7g4lgWv92wIDAQABo1AwTjAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBRaBc3GJMSK +ipWlEFGRK7450eknVjAfBgNVHSMEGDAWgBRaBc3GJMSKipWlEFGRK7450eknVjAN +BgkqhkiG9w0BAQsFAAOCAQEAPVN0cQXZE1kaocsCaKusLIW5ZNk/cDmMtzyvYA+R +pYgUHhlZ4kOvY7Pq7ay1KyAiRsXvRiZ6J64kLUReb7muPNR2HBYlOeZpV9NQn38h +hOxVc0YHHt3Nr3HL4EK7tOPidMeQXYR2/r8BAO9MlPxdN8EE5JaTinUL9DGYOCCz +TSTsYeXiJ1g33r/vwswtEnAS3bI4ZMpZ6VerPfKb5QZaWsizAqbYH/fu0Uv08PjM +1lXd4VJd/ljgd81taf83ediDCtJ/1x0iyf2R/SWd4Ts5q74npKJZKtH8/8hnPLF2 +JStg0tR0DEKTdXWGNpLiZz4p6zyrwCQ2/wCAJ2Hg8r9D+A== +-----END CERTIFICATE----- diff --git a/certs/intermediate/trust_anchor/notca-root-leaf-cert.pem b/certs/intermediate/trust_anchor/notca-root-leaf-cert.pem new file mode 100644 index 00000000000..ebec0c8a6e4 --- /dev/null +++ b/certs/intermediate/trust_anchor/notca-root-leaf-cert.pem @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDMzCCAhugAwIBAgICEAcwDQYJKoZIhvcNAQELBQAwKTEnMCUGA1UEAwwed29s +ZlNTTCBDaGFpbiBUZXN0IE5vdCBDQSBSb290MB4XDTAwMDEwMTAwMDAwMFoXDTQ5 +MTIzMTIzNTk1OVowLjEsMCoGA1UEAwwjd29sZlNTTCBDaGFpbiBUZXN0IE5vdCBD +QSBSb290IExlYWYwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDA3idX +OiKA8cPeDYbow0+DJrJ+T08L3Td+mM8yHqVKoH++RFenQI+j4sMXXy0yYn0mRSTo +zBNZwrWTpJFpOOqwJ12bMsARoZmJI1Rg3mgo4XWQfIz6MuMLAfy2uWfw4dX6l1Vl +brWtzmBo+++kY0Yu0Q//3aQTTDVX4PXjXNfkjJKtCU7GZTobJcub2A2geVhZ+O8B +lNmOEylnvEYh5rQ2pkPhAnZQCX9DkX9wX3kj9nE1s5+8MsPdiTcJowlywkw3OuF0 +6ZuvpLVjL9XxmQ5Naju0tvlPdRIYqIFMdKW/6Vj4I/5S0p1t6nfEu5VzqG9E6B38 +hmVWgswza6vjZx4LAgMBAAGjYDBeMAwGA1UdEwEB/wQCMAAwDgYDVR0PAQH/BAQD +AgeAMB0GA1UdDgQWBBRqgHxv9d/A7yClcJsTIeaFLW5ezDAfBgNVHSMEGDAWgBRa +Bc3GJMSKipWlEFGRK7450eknVjANBgkqhkiG9w0BAQsFAAOCAQEAdGW9W6iiRYQo +vCK5AsBSj/r6QESUb07RGyuhWhZVxfuNYJ4QBpTZFS45dp+JC8rHSAaHlU48eJmZ +hvNAMCYTkAmSvnrdliUpJGF72/7V3pKSOqPzLzA6JwAVCInJc5oxAjOiyrFGAUTU +KIvQBNzQ7EArKb56CCA/NnG2Yl9LO4bGCmCC8jsk3tRPsDaPqn2rSNVioO8JODZI +c5K49EQ6S0L1P5hcp4l1RQ1waVlyzkMf8rFQ58FCdfkalVOCmlQrX7sE92UF8ijb +DodWseMtvfieJKBpAPm9KNDxpQete8vzgEon6jD9zkehqBoucVUS0qGbfP3oR2fx ++XRp9MCGBA== +-----END CERTIFICATE----- diff --git a/certs/intermediate/trust_anchor/notca-twin-cert.pem b/certs/intermediate/trust_anchor/notca-twin-cert.pem new file mode 100644 index 00000000000..a96e65a358a --- /dev/null +++ b/certs/intermediate/trust_anchor/notca-twin-cert.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDEzCCAfugAwIBAgIBBTANBgkqhkiG9w0BAQsFADApMScwJQYDVQQDDB53b2xm +U1NMIFRydXN0LUFuY2hvciBUZXN0IFJvb3QwIBcNMjYxMDIzMTgwMTA3WhgPMjA1 +NjEwMjIxODAxMDdaMCkxJzAlBgNVBAMMHndvbGZTU0wgQ2hhaW4gVGVzdCBOb3Qg +Q0EgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKcyOCJ5zCTQ +h+pEebPAzTbxb168tT9kDu6BcI6ZY5j/qBiIdHBKAwKnUzYvxXl1oWUshz9lSN60 +pT+Xi4M8BJT7hp1ZeYNCKP+hHBDqoqjlBJZa38YzjWCBWDHfl7LhexKO6PsXPSA8 +IzEcpc798rF5VGT37yY6QJwiuL3JqYGWvys3mJlFV9Q9WD5aCZBJpF8huPgzwdKI +xVZOMEvsyRINyBqx8ixijAOGjZV/AFM1gAUR49AGOBPY/QYiC0LlUm7c1ZvvqQ9b +SsoKU8kqhucYM6EHTk9+VTnPnk+3hSkHjGzs+DcfP55rcZivEN6+LzlIBe8RxW6D +ZeixglU0jjUCAwEAAaNEMEIwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +AYYwHwYDVR0jBBgwFoAUjA5HGpT1gTWX1Oixuirkg6EdXicwDQYJKoZIhvcNAQEL +BQADggEBAH4/tD/gV6HCNRfDnO4czp0C8z9K5d/NbtlzmeCnrPImn6WOBluTKWtD +3XBV/bs1yBxFaEql8Z6hm2Bl2TCn/ScMOMLpN4cNeu5zsd6FNP47lJKcdfR6W6wB +3Xy/Vwj6PyORZ6oeTgJxRl+ijguw8Jon2d6Ajg3cCD4wM+RY/c/ITPDz7CRyV6lj +wqhg5aKT7j+hXmdhgMyPuHGE6A4dsdwCXuxP8EyeHRXkbEEUVOIkgumXTEyCoYCN +P8NSoj2nh+MwjDk96Ct/A/63d9ZLe1HB+6n4cCOCVs0AJgz6C9ACu245OVscr1xg +WT5gCjwoL2z7va6GcXYw9eXUNb3c8Zk= +-----END CERTIFICATE----- diff --git a/certs/intermediate/trust_anchor/renewed-root-cert.pem b/certs/intermediate/trust_anchor/renewed-root-cert.pem new file mode 100644 index 00000000000..1bd385436a6 --- /dev/null +++ b/certs/intermediate/trust_anchor/renewed-root-cert.pem @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDMzCCAhugAwIBAgICEAswDQYJKoZIhvcNAQELBQAwKjEoMCYGA1UEAwwfd29s +ZlNTTCBDaGFpbiBUZXN0IEV4cGlyZWQgUm9vdDAeFw0yMDAxMDEwMDAwMDBaFw00 +OTEyMzEyMzU5NTlaMCoxKDAmBgNVBAMMH3dvbGZTU0wgQ2hhaW4gVGVzdCBFeHBp +cmVkIFJvb3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCay6BcEtD2 +TInZEcKzAIuvQFaSU8VI/j3ffB3q6XyQSPC4OVS882W8JpA42FuAXyI+ssecDqF0 +RpqjsN6rgb/sZutN4LPLYd/dBSV9tyut1C7ZD+zFE1tFYAhmiahJGL4UZphG7d4a +GcGEcYp9OOLAJhLUSSd4eclDN+Io7WHh+kiP5eio2oZKCJ217t0FdsY2FszZiqym +RXBY+7nGZUI2cnfNiqTri4RhWWbnyXpMWnWlo6ml7fV8/3m5gkQ1sBemEizXRdEN +HUdBd73k+aRIO9sJmVvaSmC3OOqV3gc7QUqQxe+Sh18vragzXxBTTIjQDyt4BpVq +szuZIYuqkIzTAgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD +AgEGMB0GA1UdDgQWBBQbaf6hJhMp1O/HIDUGOSoZ/hPFizAfBgNVHSMEGDAWgBQb +af6hJhMp1O/HIDUGOSoZ/hPFizANBgkqhkiG9w0BAQsFAAOCAQEAB0DI8UYHv/NA +vbhJy1j2g3fyJRQk8Jy2/h6rNVwGc23ZpiRRpsucuV5oUjtayZpoxCCOiXy5PRbG +M9ZSKrF4FMRWJYeFg47yeNNmnFXgLM8u96f6gJmTId5g/ETx5du1C7FzGYvBttGb +GnpxvdpYX6gBiC73uyl3KmdnMOwSvo6kYR5CMT6AhGp1s651v3EVoxIQ7ReSDTk+ +SvYSErzR4OMhFO9d9ZDZhQnRsWPTzusgvrVppSl0yvRZnrr2NtjNpGYdIZlofZqQ +H54LMGhx5Q02GboKMKbIVY3hC5VnUrHlVkprkwoQvna30N0/F9XMSWiibh4A6cbe +PvIcpJLX3Q== +-----END CERTIFICATE----- diff --git a/certs/intermediate/trust_anchor/renewed-root-leaf-cert.pem b/certs/intermediate/trust_anchor/renewed-root-leaf-cert.pem new file mode 100644 index 00000000000..d790d1f4ffe --- /dev/null +++ b/certs/intermediate/trust_anchor/renewed-root-leaf-cert.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDFDCCAfygAwIBAgICEAwwDQYJKoZIhvcNAQELBQAwKjEoMCYGA1UEAwwfd29s +ZlNTTCBDaGFpbiBUZXN0IEV4cGlyZWQgUm9vdDAeFw0wMDAxMDEwMDAwMDBaFw00 +OTEyMzEyMzU5NTlaMC8xLTArBgNVBAMMJHdvbGZTU0wgQ2hhaW4gVGVzdCBSZW5l +d2VkIFJvb3QgTGVhZjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMDe +J1c6IoDxw94NhujDT4Mmsn5PTwvdN36YzzIepUqgf75EV6dAj6PiwxdfLTJifSZF +JOjME1nCtZOkkWk46rAnXZsywBGhmYkjVGDeaCjhdZB8jPoy4wsB/La5Z/Dh1fqX +VWVuta3OYGj776RjRi7RD//dpBNMNVfg9eNc1+SMkq0JTsZlOhsly5vYDaB5WFn4 +7wGU2Y4TKWe8RiHmtDamQ+ECdlAJf0ORf3BfeSP2cTWzn7wyw92JNwmjCXLCTDc6 +4XTpm6+ktWMv1fGZDk1qO7S2+U91EhiogUx0pb/pWPgj/lLSnW3qd8S7lXOob0To +HfyGZVaCzDNrq+NnHgsCAwEAAaM/MD0wDAYDVR0TAQH/BAIwADAOBgNVHQ8BAf8E +BAMCB4AwHQYDVR0OBBYEFGqAfG/138DvIKVwmxMh5oUtbl7MMA0GCSqGSIb3DQEB +CwUAA4IBAQAvYOTd7r4jmlcvXBbFY3zZCXqvrylQVTT5bmCEjbtlG0gIIGz/Dpfm +oUmvUIVFOYATfHa+LPdpkynovzFpUXVfbmJc6cydcyYwW2CCYeCSqTiXmkr6jdHB +DtgrrhV21xuiPw7trzman3t+0qS3rpo9Y3tKkKoxxjsJZYzZMC0lMseYymllQiZV +RbEbJxhcvVkxpb++rFdw47f6/0TUI+EMshrILKA+ADOjibVF97Vl1lr5VeWi8Ppo +y3FKMo64wm2m5oSWsTncdPoCTLFa8CYnZDw4uOOpy1XnCrlehQcoWcpLADOIInsh +uJx+3QhmqbWFNMqTM0a0++BukQUAUpco +-----END CERTIFICATE----- diff --git a/certs/intermediate/trust_anchor/root-cert.pem b/certs/intermediate/trust_anchor/root-cert.pem new file mode 100644 index 00000000000..cd475011703 --- /dev/null +++ b/certs/intermediate/trust_anchor/root-cert.pem @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDMjCCAhqgAwIBAgIBATANBgkqhkiG9w0BAQsFADApMScwJQYDVQQDDB53b2xm +U1NMIFRydXN0LUFuY2hvciBUZXN0IFJvb3QwIBcNMjYxMDIxMTI0NzAwWhgPMjA1 +NjEwMjAxMjQ3MDBaMCkxJzAlBgNVBAMMHndvbGZTU0wgVHJ1c3QtQW5jaG9yIFRl +c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALpo+V9mn3HN +zFYYbHE2rDeTFizP9MsbpWnOoHWZ51OkGtiB/esUJk41NxEmBSRkY5TuKz6f1QaJ +16iYGZhqMF7DxYMm1x3Kd9i5KHPVjVCpFLMUouJAwLvspk1mUksIrtg35osMwmG+ +skaD/7WRFjjb5aCVkZyrHeWagoxlyO2okHIkYWp10IUrkFpz9Ma5yDRR1cs079bI ++439D98Srm9oedReIUII+9ZA9if0yY5pH4uvkfaJplzhhvAkdnse8RyIkrITTOg0 +QJUNaNPsaLNn2BWWI7x4y5t/tJOVaFcfZLvrIpHqN1lqplCQeRd75uBQLpEa5QHt +GmVrCx3g3BcCAwEAAaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +AYYwHQYDVR0OBBYEFIwORxqU9YE1l9Tosboq5IOhHV4nMB8GA1UdIwQYMBaAFIwO +RxqU9YE1l9Tosboq5IOhHV4nMA0GCSqGSIb3DQEBCwUAA4IBAQBukrxYbF56cotF +s+Oam1nU9mUWoCDRsTYkRe6K2745zaS3r5g9pd4T5ilhAQQn8TgR44ysWY4XkKNc +vcoHxzCRqxbcPrjv+p5+Cim5j99hEXvKL00sz38DoK0eEMCUMpEjt7m+OuFyVjqk +/xUol14SwnGlGEnRfsoVLs/4/okxMtZOOa8sfIvqlJAuUZq9SrvKpVkKYwzCWYU8 +hIXc+BzXUcHWAAGAhiHvyIDvY403JnectFPoIku4T+usJdUIQ7WPoqCKc79Gcfv0 +OcnfyO5VOMFH96JdPfbVcfstrDx7Qe5Xkuv8SPvtF5tzn0Ks94rPFrPPsBkra9l+ +61OiJsHN +-----END CERTIFICATE----- diff --git a/certs/intermediate/trust_anchor/root-key.pem b/certs/intermediate/trust_anchor/root-key.pem new file mode 100644 index 00000000000..b55bebfab19 --- /dev/null +++ b/certs/intermediate/trust_anchor/root-key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC6aPlfZp9xzcxW +GGxxNqw3kxYsz/TLG6VpzqB1medTpBrYgf3rFCZONTcRJgUkZGOU7is+n9UGideo +mBmYajBew8WDJtcdynfYuShz1Y1QqRSzFKLiQMC77KZNZlJLCK7YN+aLDMJhvrJG +g/+1kRY42+WglZGcqx3lmoKMZcjtqJByJGFqddCFK5Bac/TGucg0UdXLNO/WyPuN +/Q/fEq5vaHnUXiFCCPvWQPYn9MmOaR+Lr5H2iaZc4YbwJHZ7HvEciJKyE0zoNECV +DWjT7GizZ9gVliO8eMubf7STlWhXH2S76yKR6jdZaqZQkHkXe+bgUC6RGuUB7Rpl +awsd4NwXAgMBAAECggEAAKQy03a1br1QCi3MVblj708EwQO4Kmi+cXZCDBWK+7kx +VHRiDMiFdzhsp5TzaJQl2ZHWOUFwiLS5tr1LPUCESRcwW0qra9FSBz9f2cIu2cuz +JAiapN+nKh5e1h5XgyWVAG50zx6snox67Y4vt463vltXV22cUicuk6cr8tK41cSA +tYQSEWGLf9PmuFFKmyNtsrGn2tCS0/5slWVCgsHcVZ4bmOL3Sn8nSP5Q1Du4oyda +8pVeI3F0chi1trByoELgaLRPpkP5Hq+sc0WbAGoJRR0mTU9RfAuFDD4upaFKbeoL +0Nt5lRARHH/VFLGGteNexdTEgV3LWeAtMCV9y4mlkQKBgQDkN2sPwYYku/qGVXqa +F0G02kF2AmX0uKRNTWv6VG8Bk/rZEPZ1CDT3xWrKLzr19kuOszX73HZCDgtept1R +c6CpX+IjlUlnoMoAh3zgIuIaBL/IaB6oGr1OfrTCxDRspDq7QwNebYGhGZr6MpAw +sdBZh/Qy9fEE5mBA2ET2oRJbpwKBgQDRGp6LnONRrX2dWqw+YjuGcO9lfofdhkzk +8vrE60gu3lT54x7QmK9eJtwMskhyq/2p5AmDBGZkP+bVhvdRonPeokoToy1cTMIT +1wJRCq610fDQJjwdj5A+YBRLJAapukzYIJfMnSTXc4d+HC08Aa0SglFiMc/xgtO7 +Gbd1hNHKEQKBgCZm/OkF06DS0PFR6POM/k2EfIdzF9z6RQuM/6J8GsHVONzV8eL3 +opIe8j1bfTxuWYCFv4vGKVAsNNWUlqFiJ6LYs6DxOgzqDZPROL4uoIVoTy1V9/Kp +rTlMMPalNX0ilY91U1fMbYfCW0XGxGStRzYJnpoEsK32ZjQDMHef2wr5AoGAJho5 +pasS6QE6EIBDPqLbweW2WcIys7UTMezssRFGd/PffCFcrhoEap2eH1olRW/9qwV4 +jj0xAzd5spMDYga+ImVkJivnyhfajY7yRx4xM8RroyI0dhaA7DzJtd98r1TZR9C4 +mHpSCkhs+hfcTkDn7qV8eu4kvBdgyYkoGuv25mECgYEAilDjJxqvBhQ5nrSquPKk +4gzjTcDH/j38MuTjSmUFNuQQDr3nRKIGHV408e2yW460v0nSLAcBrvnk7aexlZ2y +PZP6FoZsdZpU1nPP6s6eL3i4L47uQPnMVK08DAGZLEDx4oHRk9Xq6j7ySQEU2EMC +R78EOLZWxnb5j+aDrheRie4= +-----END PRIVATE KEY----- diff --git a/certs/intermediate/trust_anchor/self-cert.pem b/certs/intermediate/trust_anchor/self-cert.pem new file mode 100644 index 00000000000..7b630cb942a --- /dev/null +++ b/certs/intermediate/trust_anchor/self-cert.pem @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDQDCCAiigAwIBAgIBATANBgkqhkiG9w0BAQsFADAwMS4wLAYDVQQDDCV3b2xm +U1NMIFRydXN0LUFuY2hvciBUZXN0IFNlbGYtU2lnbmVkMCAXDTI2MTAyMTEyMzM1 +NVoYDzIwNTYxMDIwMTIzMzU1WjAwMS4wLAYDVQQDDCV3b2xmU1NMIFRydXN0LUFu +Y2hvciBUZXN0IFNlbGYtU2lnbmVkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEA0UQi54OPhzLzaD4/mrQuTfsn6SflV5PRm2ENweGp7R3ud5g1+aDrm38J +SvZL7tHERgXqTXsYeUbZbH1HiZ8681NufUTPWKQTf/MU8CUduprQCOmrOXK2z0/j +YRW1KpfOLdLZyZO03QOR2dLKSa3F4JA+V7o9ad+sehAWNiGcyTZbkrfe1sv/M1M1 +nx0mGccB28mPnojLzKE64R06JC0c7/0chyfDCSHSHp/qG9rWx8TYQqcQh6sz3a6k +dJINAMeaSH9dWONRvVI9QvGVOQJiAZi6hmOKVYn1HGwJR9v/aTXonlIdTLDQmIGH +avUA6Ti6SHTLHTGOvzNesDJGQSgQkwIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/ +MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUutrRDd3QT9a6mPVfMxhiI92Sz84w +HwYDVR0jBBgwFoAUutrRDd3QT9a6mPVfMxhiI92Sz84wDQYJKoZIhvcNAQELBQAD +ggEBAAG5cfrgJf+2JSLyF8jez3UaKSxbeyAsBqNBBwaPH5TRr0/0G6DMuJFwf9Qv +MJE+bGo4fkltDzq3jEfHxWa8D4PlLbi/QP2QxUXt8wWZc+rKuKsqgpY1udd53ipe +9Qb8EbpC5yPytVNhgPI0KY6GmrpYuUY3gcuuKhJIQf8Ph4xtZSO7tEgajrgOmvvf +bfDOhKeo0+KjomKUTDzUq/ChYXayM5hKlre1d1qFXrPZNbJ2VV5+CnCa2epzKG6h +4VXc9iUD2nYnlPPfPNAab0eJwf3qwB+TkTOpsBtEpXumbeNP4+axfUJFniEMoBPb +I2u7HV3MVq5OBOI29AWT76iqxkg= +-----END CERTIFICATE----- diff --git a/certs/intermediate/trust_anchor/self-copy-cert.pem b/certs/intermediate/trust_anchor/self-copy-cert.pem new file mode 100644 index 00000000000..923328b02fb --- /dev/null +++ b/certs/intermediate/trust_anchor/self-copy-cert.pem @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDQDCCAiigAwIBAgIBAjANBgkqhkiG9w0BAQsFADAwMS4wLAYDVQQDDCV3b2xm +U1NMIFRydXN0LUFuY2hvciBUZXN0IFNlbGYtU2lnbmVkMCAXDTI2MTAyMTEyMzM1 +NVoYDzIwNTYxMDIwMTIzMzU1WjAwMS4wLAYDVQQDDCV3b2xmU1NMIFRydXN0LUFu +Y2hvciBUZXN0IFNlbGYtU2lnbmVkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEA0UQi54OPhzLzaD4/mrQuTfsn6SflV5PRm2ENweGp7R3ud5g1+aDrm38J +SvZL7tHERgXqTXsYeUbZbH1HiZ8681NufUTPWKQTf/MU8CUduprQCOmrOXK2z0/j +YRW1KpfOLdLZyZO03QOR2dLKSa3F4JA+V7o9ad+sehAWNiGcyTZbkrfe1sv/M1M1 +nx0mGccB28mPnojLzKE64R06JC0c7/0chyfDCSHSHp/qG9rWx8TYQqcQh6sz3a6k +dJINAMeaSH9dWONRvVI9QvGVOQJiAZi6hmOKVYn1HGwJR9v/aTXonlIdTLDQmIGH +avUA6Ti6SHTLHTGOvzNesDJGQSgQkwIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/ +MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUutrRDd3QT9a6mPVfMxhiI92Sz84w +HwYDVR0jBBgwFoAUutrRDd3QT9a6mPVfMxhiI92Sz84wDQYJKoZIhvcNAQELBQAD +ggEBAIqT5m/1O8O6TsCaAcbTizkeg/2ephuAPVee8bHWhEEWm0WAtinVdARYqIzv +wJq5OamnNdvcG/wr2fs2IsDnudnswipcr3Cm0GpX2nCCkOoo18kPnnCHUyKZOWYP +6u/0RJohX4rm78NnoYU4nM4HU9KyGBfI8rHrtFEjBnRcjipjqYXW69a47v+T+2eU +AYzLUWVxJhYtjUtXEIQkYP6a8J2BHKWjt0peiUUJduiwYmH5ysEp8aP12ukhuHvd +LFnC9BbGWlCMAKVfgcpEWnU0/a6Su92gKI87b71QoLifati8OTNmL7m8B5iyfUZ/ +xrslT9Fon/AxReSWWGif0CYcfdc= +-----END CERTIFICATE----- diff --git a/certs/intermediate/trust_anchor/self-key.pem b/certs/intermediate/trust_anchor/self-key.pem new file mode 100644 index 00000000000..c42276be1ca --- /dev/null +++ b/certs/intermediate/trust_anchor/self-key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDRRCLng4+HMvNo +Pj+atC5N+yfpJ+VXk9GbYQ3B4antHe53mDX5oOubfwlK9kvu0cRGBepNexh5Rtls +fUeJnzrzU259RM9YpBN/8xTwJR26mtAI6as5crbPT+NhFbUql84t0tnJk7TdA5HZ +0spJrcXgkD5Xuj1p36x6EBY2IZzJNluSt97Wy/8zUzWfHSYZxwHbyY+eiMvMoTrh +HTokLRzv/RyHJ8MJIdIen+ob2tbHxNhCpxCHqzPdrqR0kg0Ax5pIf11Y41G9Uj1C +8ZU5AmIBmLqGY4pVifUcbAlH2/9pNeieUh1MsNCYgYdq9QDpOLpIdMsdMY6/M16w +MkZBKBCTAgMBAAECggEAONjEjpWbiMObgabfSlxF8+MVPW4cDAVYvFfKD/AIZCRs +YkqT5wMC3dPNp3JuwCp1ofv7YR7eUBuh9qm1pDoAHpd8fUUS+mZf8bML7gx3Hfju +KG2pmMqDxJ9UCkyGUVK5rJMJnIumZx+QIFb1orw088LbXKN4CWm8hdAW6I+K8tF2 +IqLgUnb9j7Vf7DTZPJ+v3SRuGCTHe48PGoDfVSu6//q6Me7WeIhSBi/jsvslFFB6 +kwGOTQRkZjKaW+Mwl1OO2XzprzizbClcOOi0/bDPB9+9LNcDqagk3wU2K5kYIZhc +P0i6aAmlpqZYih0wLA9GU939E1i2S6seW7SL5rv+sQKBgQD82DOZ/cPVroFrRjFz +ExTAmbQ0qZl1mG8Bs0Y7grdtQvNb5QmHSGxSTrBInkQXEpS5EhUZTF6+yzj0Ehqz +oIlEeeLWiQKd39GcSqoT4vVpqDkF2c1wAXewXAg/zenoBY/fgbSAsVTZn1Z9G4uV +ZxfLmCWYAXGZ/lSYnwSKCs0KKQKBgQDT4LVu8kN6R2tmCpHOWuAlx/tlj4gjxRAX +TpjOJF7kYZ77P9jyWp3oodnGhRjl0kxzhOPpIaKvj1FYACUepGo/eZLrJqOCFcXg +G1Z5z1TBz9YXoFFcc1XcBcUptRXMv8zkO7RoaYwrbQKd0urKAenpFCDEzDR2+DYZ +wkd3SXBUWwKBgBcq5EeG5gvNSpR+wQcvR2aCbu2oYKRSzFEWkSfgyVfcm5ne+amI +rEw6Y5Kz1b9bd38htgc0ZTYMPvK2OfYdjpZUqMFJmpDGslkkykK6OAxvWpI7q8RI +jiP9us/F2VnmMJGlO9nS5dhu7ijWfkq5QIfqL/+mmjcnA69cWrkfVjxJAoGBAMk/ +cfXsxO0bc0acGXwg0zDvr7j6yTv4jN0meXusDjntA53wOjeQnNZ/DSRD/a8lvhon +indAzI7mmUP190wQrR6XclZLABmqZqYEMXJH3WCt8dPFIiKnJlFzZZ/E8ezl7U6H +60cVod8Jjuerk/nGMZCC3tEuiVLLVk/HOixyo/BrAoGACqCmwGpNk3XuTihD4j18 +ivJZ5OQm9wvbYkOKjWr+Ly1BiG1fiDfNtQRRj/SYAMzkEJ+V9pWt5B9fvnW2TIFz +HWOfvCs14ppHRhn+VDSfcaUeR17u5reX8/4Dw0ITFlGUPwdEdPhbUSfZqq45UU6W +0rhh21oYeJEIXS3p+TT8uxA= +-----END PRIVATE KEY----- diff --git a/certs/intermediate/trust_anchor/v1-root-cert.pem b/certs/intermediate/trust_anchor/v1-root-cert.pem new file mode 100644 index 00000000000..c9131654acb --- /dev/null +++ b/certs/intermediate/trust_anchor/v1-root-cert.pem @@ -0,0 +1,17 @@ +-----BEGIN CERTIFICATE----- +MIICvzCCAacCAhAIMA0GCSqGSIb3DQEBCwUAMCUxIzAhBgNVBAMMGndvbGZTU0wg +Q2hhaW4gVGVzdCBWMSBSb290MB4XDTAwMDEwMTAwMDAwMFoXDTQ5MTIzMTIzNTk1 +OVowJTEjMCEGA1UEAwwad29sZlNTTCBDaGFpbiBUZXN0IFYxIFJvb3QwggEiMA0G +CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDsluAbe0ORlgwunEt+rNn9bqc/HBos +6JK6/AF/ykztPrqgSeLhKioSqiX5682XDUF/Pv8EdA6q6yuq3PGT0Ltvqu0aI1ag +Y1ZX+8pQc24Mvn7lauyv61iqaY2z/Jc8Jf9UtKS/iq0py0kzCAoh6VupN4hZHw2G +/yMO5bWfwatpv6+yCD8e0+OYEKQKrMtULxhCH6KgGP+YMstj6UHuXif7CZbelESq +L6oiUGatUJy1gimBNdhVTsF8rkWsAtUcknPb65fn1zvgBKI+80SfA/AQsaeJQY0/ +hgXCDzw3s9X5cfM/nLCIClRn6JNzB5H28C/JAlRoFup5j/DV9t91SfEvAgMBAAEw +DQYJKoZIhvcNAQELBQADggEBAGM06Ej/u7wdfQQPnn5DN5CdShIwBtAJSyzCn23a +U4h3ON0e0ZPoYLB4foyP3otvLhaWeAzaUo04a3PsEalyPMtWsd/lv21v2Fg3iPmX +4PuxKsN6mrW1zo+bclBRlHEd8zaRubZmL+4mct+eIJJV1Z8li/hBuA1vKdeWequM +3f0e572BobsVEwR5jtXLaO/U6FtLSlqhf6XzqJ4BM/z5reHee+ZVd/MVqJeL0+RG +XRFGFyhwrzbK9UszCNRpQdB6FeI5QaFDaN4PJglC1irapJrNrIh/Uo0C4akk3go5 +wgmhBse4UNq5g6BV7iejLyeKVB3Ze6R6gfbilBBDUT2V5K0= +-----END CERTIFICATE----- diff --git a/certs/intermediate/trust_anchor/v1-root-leaf-cert.pem b/certs/intermediate/trust_anchor/v1-root-leaf-cert.pem new file mode 100644 index 00000000000..5d5f32c59d5 --- /dev/null +++ b/certs/intermediate/trust_anchor/v1-root-leaf-cert.pem @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDRDCCAiygAwIBAgICEAkwDQYJKoZIhvcNAQELBQAwJTEjMCEGA1UEAwwad29s +ZlNTTCBDaGFpbiBUZXN0IFYxIFJvb3QwHhcNMDAwMTAxMDAwMDAwWhcNNDkxMjMx +MjM1OTU5WjAqMSgwJgYDVQQDDB93b2xmU1NMIENoYWluIFRlc3QgVjEgUm9vdCBM +ZWFmMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwN4nVzoigPHD3g2G +6MNPgyayfk9PC903fpjPMh6lSqB/vkRXp0CPo+LDF18tMmJ9JkUk6MwTWcK1k6SR +aTjqsCddmzLAEaGZiSNUYN5oKOF1kHyM+jLjCwH8trln8OHV+pdVZW61rc5gaPvv +pGNGLtEP/92kE0w1V+D141zX5IySrQlOxmU6GyXLm9gNoHlYWfjvAZTZjhMpZ7xG +Iea0NqZD4QJ2UAl/Q5F/cF95I/ZxNbOfvDLD3Yk3CaMJcsJMNzrhdOmbr6S1Yy/V +8ZkOTWo7tLb5T3USGKiBTHSlv+lY+CP+UtKdbep3xLuVc6hvROgd/IZlVoLMM2ur +42ceCwIDAQABo3kwdzAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIHgDAdBgNV +HQ4EFgQUaoB8b/XfwO8gpXCbEyHmhS1uXswwOAYDVR0jBDEwL6EppCcwJTEjMCEG +A1UEAwwad29sZlNTTCBDaGFpbiBUZXN0IFYxIFJvb3SCAhAIMA0GCSqGSIb3DQEB +CwUAA4IBAQDB3VDjOqmLduuIIWymNLX2ZievqiDixzjNBMzBsn7BjJsduq9KS8VN +FmO/Ym1wJzbtB7e2g3n5fSG/mir4oCOyG0j+esSagC3GIYM8GSLa16dwQf+JTeQq +tFSxN5cIOJaCllowqL56rvI9K6h3DAYnD+wy4MZy6MOJzWENAtFtmQ53PeaSAp0Z +eyj6Oz8SOU1ZQ9W2o9cFgKWkdKl+w6sw2qM4FAx0OqDgmgOEndq7CJJeDoekwUfp +Z9FLRRHs7e1di2I/lHnvmUvxVmZfjr3x7xVE1qgklVBq1dMC0NpGYlq4yjvBDrh4 +IcjXiPPxoWnTHYwvgYzWn5rGq+ePBVXv +-----END CERTIFICATE----- diff --git a/certs/intermediate/trust_anchor/wrongca-cert.pem b/certs/intermediate/trust_anchor/wrongca-cert.pem new file mode 100644 index 00000000000..5e72dd90367 --- /dev/null +++ b/certs/intermediate/trust_anchor/wrongca-cert.pem @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDMDCCAhigAwIBAgICEAEwDQYJKoZIhvcNAQELBQAwKzEpMCcGA1UEAwwgd29s +ZlNTTCBDaGFpbiBUZXN0IFdyb25nIENBIFJvb3QwHhcNMDAwMTAxMDAwMDAwWhcN +NDkxMjMxMjM1OTU5WjAmMSQwIgYDVQQDDBt3b2xmU1NMIENoYWluIFRlc3QgV3Jv +bmcgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDc9Xts5F+9Gr7m +/N0QahL7nm3XId2lRCO4ACqvO03lziWfhAITRShxdDtOZ7neAxamGqoXnFHqrJ7O +EqvOEFvfbUDTXKrxdkDa9eiBgMDSeKXjZFW+OUUYsX7Gx/PivKR3PO87NpPSX3bK +UUuEzMo4dfZuas+nWf46ryM7gV8KNTM2bEVt/AKH4XrlLZMLpv7isgabGteK3TMm +hAVvf94u18DqI38Qomzf7oYOzs3njhpMQmSq5L9dcIu4zuoW5xw9KVQxqrbUD5uQ +k5/jEs0Xc6dDBW4g2d5LIa1wsVoFtGDKDnFqIT79ozRuOYWq7f91FEM3CBRoQumi +ovZ+QNMVAgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEG +MB0GA1UdDgQWBBTf6lmk6NGYrel1Ew0NXhK+v7oGpDAfBgNVHSMEGDAWgBQl8Gzu +vnTplgMSjPn2HH+ilNGkwzANBgkqhkiG9w0BAQsFAAOCAQEACeCPILf7FxXIH8CE +Ar22uJ7s7U1F0KnOrcgYUAjL9LjSgr2JyOFgwPFDNutO7RH+//l/menfxi4KVek0 +jKoNey6fcS4T5U3zQhG6+hYbH2y4i5FZhS6cbOcOE0jiiJbh9/JELsljSYWNJto8 +KAD7fIqaZEOkWQQVpniopmt/mixM26CgGBzzaALLjJJXgSEMAMOA7d1w+piAv3UM +w2IIOSi6+WolwgRhqrgWX1a/tUEKjPnVTCYn5CfB/BUBhFTJDlMLK6FhF6ilOxcz +ZoyKtYIykzHA8a4HUUPKzqiqGTg2TQklqQwdIfbnaBlzpB6cTAiAaNAzC79MOXrS +qD3NAw== +-----END CERTIFICATE----- diff --git a/certs/intermediate/trust_anchor/wrongca-int-cert.pem b/certs/intermediate/trust_anchor/wrongca-int-cert.pem new file mode 100644 index 00000000000..b907f1ac7bf --- /dev/null +++ b/certs/intermediate/trust_anchor/wrongca-int-cert.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDDjCCAfagAwIBAgICEAMwDQYJKoZIhvcNAQELBQAwJjEkMCIGA1UEAwwbd29s +ZlNTTCBDaGFpbiBUZXN0IFdyb25nIENBMB4XDTAwMDEwMTAwMDAwMFoXDTQ5MTIz +MTIzNTk1OVowKjEoMCYGA1UEAwwfd29sZlNTTCBDaGFpbiBUZXN0IFdyb25nIENB +IEludDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKX9EAB9l9T9U65A +zerurYSe977jPQjLCJ6D81QNDL9BCPWftSnjiyQBp7eJ2vLB5OZkT78NCxzT2DLc +yEaF6GlQPih38qtbAjyZgtr+yhTQ3H7xN9gPoeZS6nZdJAM3GOXMm9jJxszBYsDj +5GJ9vz4xjMePe6HDPnT5Wr8ECRDyHX9Tdx4px6s1cHQRsQzA+coU+6RnrHqlYjmD +E+joqoJ/WfEck3bNaF+3pBmwlzD+FfYdDfqPbsWylomkljrWORBIn8tWjrpixIaF +xsVd5bMXhGwcsla0SSUY7FcLhpNvvhWJlVY5tppmON2Ca09A367NdchozmB3LvOU +bY2UCrcCAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYw +HQYDVR0OBBYEFL0NeSssy7n5Kv+lPlXFe1pULThtMA0GCSqGSIb3DQEBCwUAA4IB +AQCQNrwxWXrsw3hlSz5OfwbSn399k/BknFUBQpcZkCpHvXg1WEGtIkolysO8aSPp +Yr21S9ukVnGzGXF7HrY/1aXW/hFD7El4obok8jYUOOC7F/HKfE0qYL0O/74DtkVD +6tMwTn02PJsPznwmgKnxwB26N5YXzWy70ZiWjbr9o7IJYG0fZELQQy0YyvygK49Y +pghskr7GoJpNE55kzK98HUXA87zVDMHFZ17WarOBoXyqGSsGcQwbsHvnfGt/BrLb +QRbPq0m8O7s2015oy4PWiMgqjiL3wiM4T2GscVuOsD1Vj2Iy2KMbhw4n1ULa8b1J +2f1sy6g9Zpyb3pcC8c9IL7dv +-----END CERTIFICATE----- diff --git a/certs/intermediate/trust_anchor/wrongca-int-leaf-cert.pem b/certs/intermediate/trust_anchor/wrongca-int-leaf-cert.pem new file mode 100644 index 00000000000..a7962f206bf --- /dev/null +++ b/certs/intermediate/trust_anchor/wrongca-int-leaf-cert.pem @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDNTCCAh2gAwIBAgICEAUwDQYJKoZIhvcNAQELBQAwKjEoMCYGA1UEAwwfd29s +ZlNTTCBDaGFpbiBUZXN0IFdyb25nIENBIEludDAeFw0wMDAxMDEwMDAwMDBaFw00 +OTEyMzEyMzU5NTlaMC8xLTArBgNVBAMMJHdvbGZTU0wgQ2hhaW4gVGVzdCBXcm9u +ZyBDQSBJbnQgTGVhZjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMF6 +VJMg98OODcrfcfhASghxfkZaT9PVEQmsCXcBdcQdkyQ9wZ70ynjjp53b3muRFtit +4LXM3/ageEJTN/Tam/rFQQh4VdRZlOHbTBVal4sPfufx+Rg97APEfAN61WIrh4G9 +aaPxmhaCxL0G3KXUg/7/BbxJl8xlLImUnoO6LeCSuP6MzoMMxya9BeLpPEo4vs5p +MnsgMdVHbb5YuTBtVenqsbW+0wlYocZwRDxEz9y+NiJdwb7aslh8PJDVcXTK0hCh +1Efq4ajjxG8q3gzokbxEWJNRyjzM0yc7cPsFsMd1i7ZkGc8hhxf5n6Om8ECbhOvV +56n2eNSYGfJ5hksC8zsCAwEAAaNgMF4wDAYDVR0TAQH/BAIwADAOBgNVHQ8BAf8E +BAMCB4AwHQYDVR0OBBYEFBajykWsEqqIXFRNfBoaQPDugZcKMB8GA1UdIwQYMBaA +FL0NeSssy7n5Kv+lPlXFe1pULThtMA0GCSqGSIb3DQEBCwUAA4IBAQA7q34kp+sm +kawfVuaVODiAWG8gQMdBk0zYe8CRyUWS6A/EbHXwB++HafGQSiwtP6ZMJ8Dq12hK +ocxOX6HIG3d03qoaXt1fQqaasCwR0IuLSwEcPjX6EkIRGRLGBYqtfY9CyuAjZmQT +8Dh9moAaTtnwMNrFBpcdX/mUbLtotrG/I8BGZIRlv9pwmfSpiXYWLGnjK4hDcdmn +9mC08SERJqtEdQkzuvG4qc4I/RqxGy2lYHkjy7qkXLdiQRgTB1zlFHkrD8yXlwWF +fSP861GPCM/xBUVq+sOlySbsQCG2b977OZlxVO7Jh4NM7Xd0jQdFmlLHZ1gwle+B +PNnxZ5yxVJfh +-----END CERTIFICATE----- diff --git a/certs/intermediate/trust_anchor/wrongca-old-int-cert.pem b/certs/intermediate/trust_anchor/wrongca-old-int-cert.pem new file mode 100644 index 00000000000..468a9ef6103 --- /dev/null +++ b/certs/intermediate/trust_anchor/wrongca-old-int-cert.pem @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDLzCCAhegAwIBAgICEAQwDQYJKoZIhvcNAQELBQAwJjEkMCIGA1UEAwwbd29s +ZlNTTCBDaGFpbiBUZXN0IFdyb25nIENBMB4XDTEwMDEwMTAwMDAwMFoXDTE5MTIz +MTIzNTk1OVowKjEoMCYGA1UEAwwfd29sZlNTTCBDaGFpbiBUZXN0IFdyb25nIENB +IEludDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKX9EAB9l9T9U65A +zerurYSe977jPQjLCJ6D81QNDL9BCPWftSnjiyQBp7eJ2vLB5OZkT78NCxzT2DLc +yEaF6GlQPih38qtbAjyZgtr+yhTQ3H7xN9gPoeZS6nZdJAM3GOXMm9jJxszBYsDj +5GJ9vz4xjMePe6HDPnT5Wr8ECRDyHX9Tdx4px6s1cHQRsQzA+coU+6RnrHqlYjmD +E+joqoJ/WfEck3bNaF+3pBmwlzD+FfYdDfqPbsWylomkljrWORBIn8tWjrpixIaF +xsVd5bMXhGwcsla0SSUY7FcLhpNvvhWJlVY5tppmON2Ca09A367NdchozmB3LvOU +bY2UCrcCAwEAAaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYw +HQYDVR0OBBYEFL0NeSssy7n5Kv+lPlXFe1pULThtMB8GA1UdIwQYMBaAFM7WAysI +FUnUI71Br4FWNbOoZPkYMA0GCSqGSIb3DQEBCwUAA4IBAQAyxCQ4Qiv93ayBF4zO +Env1kLll0ixjyOzt6sbsWoD/Vtm6SmemDioP7b48zR68rp0WeSVOekoiCu+Q+KYP +psBzEGfpQLfziXHJ8VPBURp0ltkqgDDOZyCdBftKRcv25hHhC+AyLUJB47tyxJfX +3Fb77kOZNtwvO5N6bC0/6kffl2yK3jCM5MA9MxFKkJF7wlwYuZbFy8SwcOaEbNpO +t/a1vrqQMGmB0llhSgTSzKYwDGPyI/ivA9FF+ACsenQnxzgCPphWWk0FEMxGbEj/ +71nO3H8ngJ1lp+Q9f2amWd8cr3cgR4BXdih54tBFdiBycKpiFQV7A9OulSE7GiM7 +bNCO +-----END CERTIFICATE----- diff --git a/certs/intermediate/trust_anchor/wrongca-root-cert.pem b/certs/intermediate/trust_anchor/wrongca-root-cert.pem new file mode 100644 index 00000000000..45fa43f9824 --- /dev/null +++ b/certs/intermediate/trust_anchor/wrongca-root-cert.pem @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDNTCCAh2gAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwKzEpMCcGA1UEAwwgd29s +ZlNTTCBDaGFpbiBUZXN0IFdyb25nIENBIFJvb3QwHhcNMDAwMTAxMDAwMDAwWhcN +NDkxMjMxMjM1OTU5WjArMSkwJwYDVQQDDCB3b2xmU1NMIENoYWluIFRlc3QgV3Jv +bmcgQ0EgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKStDm7T +Jpr7MTRvTqcSHgAWLnaCnDLHm8UzX0lbdadfToLtOJ8IoRiauofU6sQoID5dk35i +JyyKUl/8ONLVB06wIX2HUgoA4uhyo5xXSyUiPQKh9zifctewnDzij1mXCo9iwKES +meyBqPcftv6GjJHF/ywDT2/Da6YmJI9DGGWS0kP/HCJ0TNM5Nw0aghdh20cxznqc +4mC46/mIlC0TLIdagYwNVTBQUF/lDaCzZydfOZ6exg9ARjeZi7Wpiob1q2kShP80 +x/0EfVa/ydLLTW3bWOCXGsB0IVErTUu1wRidcyU5nIR4FF2o49WXKmy5FjRha3bO +yhZL8KADlYTNOwUCAwEAAaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8E +BAMCAQYwHQYDVR0OBBYEFCXwbO6+dOmWAxKM+fYcf6KU0aTDMB8GA1UdIwQYMBaA +FCXwbO6+dOmWAxKM+fYcf6KU0aTDMA0GCSqGSIb3DQEBCwUAA4IBAQApJzCFu2Ds +084NjFnyv8yNNIpPPrcNDgezCh9yULCUXmIMVtYy8gQU+uW66r0StdlDXB0caI2B +1nL7O1BQFCTYnYPTGmURaCec8hShw51fvnH7LMkJWL8spHFH91F0Z078wLyQmCTE +kavU0E1e3kueNG0vLyW8wwYiFar7OOmBvxEcsTgFAARbX/slVoGyDQhqOmLqGkGf +UVEbkXcy/55OQhaOAcrqzwa63qfJl8AMDNdPzlz5BWMnuxRUrVtTkDWzYrNhAPR/ +DvE9MruGdNrFarRdCwHVyRMRBRKoZGVDYnEzHnBjl0ky/BkcueNYO6+KhdSvVw9w +WTtAhrFnupPH +-----END CERTIFICATE----- diff --git a/cmake/options.h.in b/cmake/options.h.in index 6c35a38de09..723253c8655 100644 --- a/cmake/options.h.in +++ b/cmake/options.h.in @@ -363,6 +363,8 @@ extern "C" { #cmakedefine WOLFSSL_ENCRYPTED_KEYS #undef WOLFSSL_ERROR_CODE_OPENSSL #cmakedefine WOLFSSL_ERROR_CODE_OPENSSL +#undef WOLFSSL_I2D_ECDSA_SIG_ALLOC +#cmakedefine WOLFSSL_I2D_ECDSA_SIG_ALLOC #undef WOLFSSL_IP_ALT_NAME #cmakedefine WOLFSSL_IP_ALT_NAME #undef WOLFSSL_KEY_GEN diff --git a/configure.ac b/configure.ac index 8504097da7f..806a10f84d2 100644 --- a/configure.ac +++ b/configure.ac @@ -13827,7 +13827,7 @@ then fi AS_IF([test "x$ENABLED_OPENSSLALL" = "xyes"], - [AM_CFLAGS="$AM_CFLAGS -DOPENSSL_ALL -DWOLFSSL_EITHER_SIDE -DWC_RSA_NO_PADDING -DWC_RSA_PSS -DWOLFSSL_PSS_LONG_SALT -DWOLFSSL_TICKET_HAVE_ID -DWOLFSSL_ERROR_CODE_OPENSSL -DWOLFSSL_CERT_NAME_ALL"]) + [AM_CFLAGS="$AM_CFLAGS -DOPENSSL_ALL -DWOLFSSL_EITHER_SIDE -DWC_RSA_NO_PADDING -DWC_RSA_PSS -DWOLFSSL_PSS_LONG_SALT -DWOLFSSL_TICKET_HAVE_ID -DWOLFSSL_ERROR_CODE_OPENSSL -DWOLFSSL_CERT_NAME_ALL -DWOLFSSL_I2D_ECDSA_SIG_ALLOC"]) AS_IF([test "x$ENABLED_AESSIV" = "xyes"], [AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AES_SIV"]) diff --git a/doc/dox_comments/header_files/ecc.h b/doc/dox_comments/header_files/ecc.h index 589918da90f..419d420e414 100644 --- a/doc/dox_comments/header_files/ecc.h +++ b/doc/dox_comments/header_files/ecc.h @@ -3646,3 +3646,38 @@ int wc_ecc_use_key_id(ecc_key* key, word32 keyId, word32 flags); \sa wc_ecc_use_key_id */ int wc_ecc_get_key_id(ecc_key* key, word32* keyId); + +/*! + \ingroup ECC + \brief Encodes an ECDSA signature as DER, as OpenSSL's i2d_ECDSA_SIG(). + + With pp NULL only the length is returned. When *pp is a buffer, the + encoding is written to it and *pp is moved past it. When *pp is NULL and + WOLFSSL_I2D_ECDSA_SIG_ALLOC is defined, a buffer is allocated for the + encoding and *pp is set to it, as OpenSSL does. Free it with + OPENSSL_free(). Otherwise only the length is returned and *pp stays + NULL. --enable-opensslall defines WOLFSSL_I2D_ECDSA_SIG_ALLOC, and so + do --enable-all, the application options that enable opensslall and the + matching CMake options. Use pp NULL to get the length in every build. + + \return Length of the encoding on success. + \return 0 on error. A buffer allocated here is freed and *pp set to NULL. + + \param sig ECDSA signature to encode. + \param pp NULL, or the address of the output buffer pointer. + + _Example_ + \code + unsigned char* der = NULL; + int derSz = wolfSSL_i2d_ECDSA_SIG(sig, NULL); + // With WOLFSSL_I2D_ECDSA_SIG_ALLOC, allocates der + derSz = wolfSSL_i2d_ECDSA_SIG(sig, &der); + if (derSz > 0) { + // use der + OPENSSL_free(der); + } + \endcode + + \sa wolfSSL_d2i_ECDSA_SIG +*/ +int wolfSSL_i2d_ECDSA_SIG(const WOLFSSL_ECDSA_SIG *sig, unsigned char **pp); diff --git a/doc/dox_comments/header_files/ssl.h b/doc/dox_comments/header_files/ssl.h index 777e649e719..bac64e65508 100644 --- a/doc/dox_comments/header_files/ssl.h +++ b/doc/dox_comments/header_files/ssl.h @@ -5945,6 +5945,11 @@ int wolfSSL_X509_get_signature(WOLFSSL_X509* x509, unsigned char* buf, int* bufS \ingroup CertsKeys \brief This function adds a certificate to the WOLFSSL_X509_STRE structure. + As in OpenSSL, a store made with wolfSSL_X509_STORE_new() also takes a + self-signed certificate that is not valid now. + wolfSSL_X509_verify_cert() checks its dates at the verification time. + It is not trusted for TLS, and it is dropped when the store is given to + an SSL_CTX with wolfSSL_CTX_set_cert_store(). \return SSL_SUCCESS If certificate is added successfully. \return SSL_FATAL_ERROR: If certificate is not added successfully. @@ -17145,6 +17150,48 @@ int wolfSSL_CRYPTO_get_ex_new_index(int class_index, long argl, void *argp, WOLFSSL_CRYPTO_EX_dup* dup_func, WOLFSSL_CRYPTO_EX_free* free_func); +/*! + \ingroup SSL + \brief Get the memory functions set with CRYPTO_set_mem_functions, as + OpenSSL 3.0's CRYPTO_get_mem_functions. Each output may be NULL. + + When none are set, the returned functions use the C library. They do + not call back into wolfSSL, so wrappers of them may be passed to + CRYPTO_set_mem_functions. + + CRYPTO_set_mem_functions needs USE_WOLFSSL_MEMORY and no + WOLFSSL_STATIC_MEMORY. Otherwise it fails and the returned functions + allocate as OPENSSL_malloc does. + + \param [out] m Malloc function. May be NULL. + \param [out] r Realloc function. May be NULL. + \param [out] f Free function. May be NULL. + + _Example_ + \code + static CRYPTO_malloc_fn prev_malloc; + static CRYPTO_realloc_fn prev_realloc; + static CRYPTO_free_fn prev_free; + + static void* my_malloc(size_t sz, const char* file, int line) + { + return prev_malloc(sz, file, line); + } + // my_realloc and my_free alike + + CRYPTO_get_mem_functions(&prev_malloc, &prev_realloc, &prev_free); + CRYPTO_set_mem_functions(my_malloc, my_realloc, my_free); + // ... + CRYPTO_set_mem_functions(prev_malloc, prev_realloc, prev_free); + \endcode + + \sa wolfSSL_CRYPTO_set_mem_functions + \sa wolfSSL_SetAllocators +*/ +void wolfSSL_CRYPTO_get_mem_functions(wolfSSL_OSSL_Malloc_cb* m, + wolfSSL_OSSL_Realloc_cb* r, + wolfSSL_OSSL_Free_cb* f); + /*! \ingroup Setup \brief In case this function is called in a client side, set certificate types diff --git a/src/crl.c b/src/crl.c index 1a62f7f521e..bf25923bb3c 100644 --- a/src/crl.c +++ b/src/crl.c @@ -485,7 +485,7 @@ static int FindRevokedSerial(RevokedCert* rc, byte* serial, int serialSz, /* cacheResult should only be set when cm is the owning cm of crl. A cached * result is not valid for other cms because they can trust different CAs. */ static int VerifyCRLE(const WOLFSSL_CRL* crl, CRL_Entry* crle, - WOLFSSL_CERT_MANAGER* cm, int cacheResult) + WOLFSSL_CERT_MANAGER* cm, int cacheResult, Signer* issuer) { Signer* ca = NULL; SignatureCtx sigCtx; @@ -510,6 +510,27 @@ static int VerifyCRLE(const WOLFSSL_CRL* crl, CRL_Entry* crle, #else /* NO_SKID */ ca = GetCA(cm, crle->issuerHash); #endif /* NO_SKID */ + /* Verified when loaded, it has no signature left: the CA that verified + * it must have the key of the chain issuer */ + if (issuer != NULL && crle->toBeSigned == NULL) { + #ifndef IGNORE_KEY_EXTENSIONS + if ((issuer->keyUsage & KEYUSE_CRL_SIGN) == 0) { + return ASN_CRL_NO_SIGNER_E; + } + #endif + if (crle->verified <= 0 || ca == NULL || ca->publicKey == NULL || + ca->pubKeySize != issuer->pubKeySize || + XMEMCMP(ca->publicKey, issuer->publicKey, + issuer->pubKeySize) != 0) { + return ASN_CRL_CONFIRM_E; + } + return 0; + } + /* As OpenSSL, the issuer on the chain must have signed it */ + if (issuer != NULL) { + ca = issuer; + cacheResult = 0; + } if (ca == NULL) { WOLFSSL_MSG("Did NOT find CRL issuer CA"); return ASN_CRL_NO_SIGNER_E; @@ -536,31 +557,216 @@ static int VerifyCRLE(const WOLFSSL_CRL* crl, CRL_Entry* crle, return ret; } +#if defined(OPENSSL_EXTRA) && !defined(NO_SKID) && !defined(NO_ASN) +/* Returns 1 when crle is the CRL of another key than issuer's: as OpenSSL's + * X509_check_akid(), its authority key id is not the issuer's subject key + * id, both being known. A zero subjectKeyIdHash is not known. */ +static int CrlOfOtherKey(const CRL_Entry* crle, const Signer* issuer) +{ + byte known = 0; + int i; + + for (i = 0; i < KEYID_SIZE; i++) { + known |= issuer->subjectKeyIdHash[i]; + } + return crle->extAuthKeyIdSet && known != 0 && + XMEMCMP(crle->extAuthKeyId, issuer->subjectKeyIdHash, + KEYID_SIZE) != 0; +} +#endif + +#if !defined(NO_ASN_TIME) && !defined(WOLFSSL_NO_CRL_DATE_CHECK) +/* As XVALIDATE_DATE, at checkTime unless it is 0 */ +static int CrlValidDate(const byte* date, byte format, int dateType, + time_t checkTime) +{ +#ifdef USE_WOLF_VALIDDATE + if (checkTime != 0) { + return wc_ValidateDateWithTime(date, format, dateType, checkTime, + MAX_DATE_SIZE); + } +#else + (void)checkTime; +#endif + return XVALIDATE_DATE(date, format, dateType, MAX_DATE_SIZE); +} +#endif + +/* Returns 0 when crle is current. With issuer, as OpenSSL's + * check_crl_time(): always without checkTime, else from its thisUpdate to + * its nextUpdate, if any, at *checkTime, now when it is 0. Without issuer, + * as the handshake checks it: before its nextUpdate, now. + * Returns ASN_BEFORE_DATE_E when it is not yet valid, CRL_CERT_DATE_ERR when + * it has expired. */ +static int CrlDateErr(const CRL_Entry* crle, const Signer* issuer, + const time_t* checkTime) +{ +#if !defined(NO_ASN_TIME) && !defined(WOLFSSL_NO_CRL_DATE_CHECK) + if (issuer != NULL) { + if (checkTime == NULL) { + return 0; + } + if (!CrlValidDate(crle->lastDate, crle->lastDateFormat, ASN_BEFORE, + *checkTime)) { + WOLFSSL_MSG("CRL last date is not yet valid"); + return ASN_BEFORE_DATE_E; + } + /* Expired at its nextUpdate, as OpenSSL's X509_cmp_time() */ + if (crle->nextDateFormat != ASN_OTHER_TYPE && + !CrlValidDate(crle->nextDate, crle->nextDateFormat, ASN_AFTER, + (*checkTime != 0) ? *checkTime + 1 : 0)) { + WOLFSSL_MSG("CRL next date is no longer valid"); + return CRL_CERT_DATE_ERR; + } + return 0; + } +#ifdef WOLFSSL_NO_CRL_NEXT_DATE + if (crle->nextDateFormat == ASN_OTHER_TYPE) { + return 0; + } +#endif + if (!XVALIDATE_DATE(crle->nextDate, crle->nextDateFormat, ASN_AFTER, + MAX_DATE_SIZE)) { + WOLFSSL_MSG("CRL next date is no longer valid"); + return CRL_CERT_DATE_ERR; + } +#else + (void)crle; + (void)issuer; + (void)checkTime; +#endif + return 0; +} + +#ifdef OPENSSL_EXTRA +/* As OpenSSL's get_crl_sk(), of the CRLs in list of the chain issuer: one + * current at *checkTime over one that is not, then a later thisUpdate. + * *cur, 0 for none, and *last are of the best so far. + * Returns the entry that is better, else NULL. */ +static CRL_Entry* CrlPick(CRL_Entry* list, const byte* issuerHash, + const Signer* issuer, const time_t* checkTime, int* cur, + WOLFSSL_ASN1_TIME* last) +{ + CRL_Entry* best = NULL; + int c; + + for (; list != NULL; list = list->next) { + if (XMEMCMP(list->issuerHash, issuerHash, CRL_DIGEST_SIZE) != 0) { + continue; + } + #if !defined(NO_SKID) && !defined(NO_ASN) + if (CrlOfOtherKey(list, issuer)) { + continue; + } + #endif + /* 2 when current, else 1 */ + c = (CrlDateErr(list, issuer, checkTime) == 0) ? 2 : 1; + #ifndef NO_ASN_TIME + if (c < *cur || (c == *cur && + wolfSSL_ASN1_TIME_compare(&list->lastDateAsn1, last) <= 0)) { + continue; + } + #else + if (c <= *cur) { + continue; + } + #endif + best = list; + *cur = c; + *last = list->lastDateAsn1; + } + return best; +} + +/* For X509_verify_cert(): returns 1 when crl has a CRL of cert's issuer, + * the chain issuer, better than *cur and *last, as CrlPick(), else 0 or + * BAD_MUTEX_E. */ +int PickCertCRL(WOLFSSL_CRL* crl, DecodedCert* cert, Signer* issuer, + const time_t* checkTime, int* cur, WOLFSSL_ASN1_TIME* last) +{ + int ret; + + if (wc_LockRwLock_Rd(&crl->crlLock) != 0) { + WOLFSSL_MSG("wc_LockRwLock_Rd failed"); + return BAD_MUTEX_E; + } + ret = CrlPick(crl->crlList, cert->issuerHash, issuer, checkTime, cur, + last) != NULL; + wc_UnLockRwLock(&crl->crlLock); + + return ret; +} +#endif + +/* Without a current CRL, returns the date error of one. With issuer, only + * the CRL CrlPick() picks is checked. */ static int CheckCertCRLList(WOLFSSL_CRL* crl, byte* issuerHash, byte* serial, int serialSz, byte* serialHash, int *pFoundEntry, - WOLFSSL_CERT_MANAGER* cm) + WOLFSSL_CERT_MANAGER* cm, Signer* issuer, const time_t* checkTime) { CRL_Entry* crle; int foundEntry = 0; int ret = 0; + int dateErr = 0; +#ifdef OPENSSL_EXTRA + CRL_Entry* best = NULL; + int cur = 0; + WOLFSSL_ASN1_TIME last; +#endif if (wc_LockRwLock_Rd(&crl->crlLock) != 0) { WOLFSSL_MSG("wc_LockRwLock_Rd failed"); return BAD_MUTEX_E; } +#ifdef OPENSSL_EXTRA + if (issuer != NULL) { + XMEMSET(&last, 0, sizeof(last)); + best = CrlPick(crl->crlList, issuerHash, issuer, checkTime, &cur, + &last); + } +#endif for (crle = crl->crlList; crle != NULL; crle = crle->next) { if (XMEMCMP(crle->issuerHash, issuerHash, CRL_DIGEST_SIZE) == 0) { - int nextDateValid = 1; + int curDateErr; + #ifdef OPENSSL_EXTRA + if (issuer != NULL && crle != best) { + continue; + } + #endif WOLFSSL_MSG("Found CRL Entry on list"); - if (cm != crl->cm) { + #ifndef IGNORE_KEY_EXTENSIONS + /* As OpenSSL's check_crl(), cRLSign before the dates */ + if (issuer != NULL && (issuer->keyUsage & KEYUSE_CRL_SIGN) == 0) { + WOLFSSL_MSG("CA cannot sign CRLs"); + ret = ASN_CRL_NO_SIGNER_E; + foundEntry = 1; + break; + } + #endif + + WOLFSSL_MSG("Checking next date validity"); + curDateErr = CrlDateErr(crle, issuer, checkTime); + /* As OpenSSL, the dates of a CRL of the chain issuer are checked + * before its signature */ + if (curDateErr != 0 && issuer != NULL) { + if (dateErr != WC_NO_ERR_TRACE(ASN_BEFORE_DATE_E)) + dateErr = curDateErr; + continue; + } + + if (cm != crl->cm || issuer != NULL) { /* cm is not the owning cm of crl. The cached result is only * valid for the owning cm. Verify again without caching. */ - ret = VerifyCRLE(crl, crle, cm, 0); + ret = VerifyCRLE(crl, crle, cm, 0, issuer); if (ret != 0) { WOLFSSL_MSG("Cannot use CRL as it didn't verify"); + /* With a chain issuer it is a signature failure, as + * in OpenSSL, not a missing CRL */ + if (issuer != NULL) + foundEntry = 1; break; } } @@ -574,7 +780,7 @@ static int CheckCertCRLList(WOLFSSL_CRL* crl, byte* issuerHash, byte* serial, /* A different thread may have verified the entry while we * were waiting for the mutex. */ if (crle->verified == 0) - ret = VerifyCRLE(crl, crle, cm, 1); + ret = VerifyCRLE(crl, crle, cm, 1, NULL); wc_UnLockMutex(&crle->verifyMutex); @@ -589,35 +795,24 @@ static int CheckCertCRLList(WOLFSSL_CRL* crl, byte* issuerHash, byte* serial, } } - WOLFSSL_MSG("Checking next date validity"); - - #ifdef WOLFSSL_NO_CRL_NEXT_DATE - if (crle->nextDateFormat != ASN_OTHER_TYPE) - #endif - { - #if !defined(NO_ASN_TIME) && !defined(WOLFSSL_NO_CRL_DATE_CHECK) - if (!XVALIDATE_DATE(crle->nextDate, crle->nextDateFormat, - ASN_AFTER, MAX_DATE_SIZE)) { - WOLFSSL_MSG("CRL next date is no longer valid"); - nextDateValid = 0; - } - #endif - } - if (nextDateValid) { + if (curDateErr == 0) { foundEntry = 1; ret = FindRevokedSerial(crle->certs, serial, serialSz, serialHash, crle->totalCerts); if (ret != 0) break; } - else if (foundEntry == 0) { - ret = CRL_CERT_DATE_ERR; + else if (dateErr != WC_NO_ERR_TRACE(ASN_BEFORE_DATE_E)) { + dateErr = curDateErr; } } } wc_UnLockRwLock(&crl->crlLock); + if (foundEntry == 0 && ret == 0) { + ret = dateErr; + } *pFoundEntry = foundEntry; return ret; @@ -629,7 +824,7 @@ static int CheckCertCRLList(WOLFSSL_CRL* crl, byte* issuerHash, byte* serial, static int CheckCertCRLCm(WOLFSSL_CRL* crl, byte* issuerHash, byte* serial, int serialSz, byte* serialHash, const byte* extCrlInfo, int extCrlInfoSz, void* issuerName, WOLFSSL_CERT_MANAGER* cm, - int canRetry) + int canRetry, Signer* issuer, const time_t* checkTime) { int foundEntry = 0; int ret = 0; @@ -644,14 +839,15 @@ static int CheckCertCRLCm(WOLFSSL_CRL* crl, byte* issuerHash, byte* serial, } #ifdef WOLFSSL_CRL_ALLOW_MISSING_CDP - /* Skip CRL verification in case no CDP in peer cert */ - if (!extCrlInfo) { + /* Skip CRL verification in case no CDP in peer cert. As OpenSSL, a chain + * issuer's CRLs are checked. */ + if (!extCrlInfo && issuer == NULL) { return ret; } #endif ret = CheckCertCRLList(crl, issuerHash, serial, serialSz, serialHash, - &foundEntry, cm); + &foundEntry, cm, issuer, checkTime); #ifdef HAVE_CRL_IO if (foundEntry == 0) { @@ -665,7 +861,7 @@ static int CheckCertCRLCm(WOLFSSL_CRL* crl, byte* issuerHash, byte* serial, else if (cbRet >= 0) { /* try again */ ret = CheckCertCRLList(crl, issuerHash, serial, serialSz, - serialHash, &foundEntry, cm); + serialHash, &foundEntry, cm, issuer, checkTime); } } } @@ -684,7 +880,7 @@ static int CheckCertCRLCm(WOLFSSL_CRL* crl, byte* issuerHash, byte* serial, if (loadRet == WOLFSSL_SUCCESS) { /* try again */ ret = CheckCertCRLList(crl, issuerHash, serial, serialSz, - serialHash, &foundEntry, cm); + serialHash, &foundEntry, cm, issuer, checkTime); } } } @@ -696,7 +892,8 @@ static int CheckCertCRLCm(WOLFSSL_CRL* crl, byte* issuerHash, byte* serial, #endif ) { WOLFSSL_MSG("Couldn't find CRL for status check"); - if (ret != WC_NO_ERR_TRACE(CRL_CERT_DATE_ERR)) { + if (ret != WC_NO_ERR_TRACE(CRL_CERT_DATE_ERR) && + ret != WC_NO_ERR_TRACE(ASN_BEFORE_DATE_E)) { ret = CRL_MISSING; } @@ -734,7 +931,7 @@ int CheckCertCRL_ex(WOLFSSL_CRL* crl, byte* issuerHash, byte* serial, int extCrlInfoSz, void* issuerName) { return CheckCertCRLCm(crl, issuerHash, serial, serialSz, serialHash, - extCrlInfo, extCrlInfoSz, issuerName, crl->cm, 1); + extCrlInfo, extCrlInfoSz, issuerName, crl->cm, 1, NULL, NULL); } /* Get the issuer X509_NAME of cert to pass to CheckCertCRLCm(). */ @@ -754,28 +951,34 @@ static void* CertCrlIssuerName(DecodedCert* cert) } static int CheckDecodedCertCRL(WOLFSSL_CRL* crl, DecodedCert* cert, - WOLFSSL_CERT_MANAGER* cm, int canRetry) + WOLFSSL_CERT_MANAGER* cm, int canRetry, Signer* issuer, + const time_t* checkTime) { void* issuerName = CertCrlIssuerName(cert); return CheckCertCRLCm(crl, cert->issuerHash, cert->serial, cert->serialSz, NULL, cert->extCrlInfo, cert->extCrlInfoSz, issuerName, cm, - canRetry); + canRetry, issuer, checkTime); } /* Is the cert ok with CRL, return 0 on success */ int CheckCertCRL(WOLFSSL_CRL* crl, DecodedCert* cert) { - return CheckDecodedCertCRL(crl, cert, crl->cm, 1); + return CheckDecodedCertCRL(crl, cert, crl->cm, 1, NULL, NULL); } /* Check cert against crl using cm for CRL signature verification. Does not * modify crl, so crl can be a caller-owned object shared between threads. - * Return 0 on success. */ + * As in OpenSSL, issuer, the cert's issuer on the chain, must have signed + * the CRL, and a CRL is current from its thisUpdate to its nextUpdate, if + * any, at *checkTime, now when it is 0. Without checkTime CRL dates are not + * checked. + * Return 0 on success, ASN_BEFORE_DATE_E or CRL_CERT_DATE_ERR when no CRL is + * current. */ int CheckCertCRLFromCm(WOLFSSL_CERT_MANAGER* cm, WOLFSSL_CRL* crl, - DecodedCert* cert) + DecodedCert* cert, Signer* issuer, const time_t* checkTime) { - return CheckDecodedCertCRL(crl, cert, cm, 0); + return CheckDecodedCertCRL(crl, cert, cm, 0, issuer, checkTime); } #ifdef HAVE_CRL_UPDATE_CB @@ -2653,6 +2856,13 @@ int wolfSSL_X509_CRL_add_revoked(WOLFSSL_X509_CRL* crl, int i; int allZero = 1; + /* An INTEGER made by the library holds the DER encoding. One built + * by hand holds the content bytes. */ + if (rev->serialNumber->type == WOLFSSL_V_ASN1_INTEGER) { + serial = wolfSSL_ASN1_INTEGER_get0_data(rev->serialNumber); + serialSz = wolfSSL_ASN1_INTEGER_get_length(rev->serialNumber); + } + if (serial == NULL || serialSz <= 0) { return BAD_FUNC_ARG; } diff --git a/src/internal.c b/src/internal.c index 60f13ef08f8..2f2508e2bd4 100644 --- a/src/internal.c +++ b/src/internal.c @@ -3357,6 +3357,7 @@ int InitSSL_Ctx(WOLFSSL_CTX* ctx, WOLFSSL_METHOD* method, void* heap) return MEMORY_E; } XMEMSET(ctx->param, 0, sizeof(WOLFSSL_X509_VERIFY_PARAM)); + ctx->param->depth = -1; /* WOLFSSL_X509_LOOKUP */ if ((ctx->x509_store.lookup.dirs = (WOLFSSL_BY_DIR*)XMALLOC( @@ -3375,6 +3376,7 @@ int InitSSL_Ctx(WOLFSSL_CTX* ctx, WOLFSSL_METHOD* method, void* heap) return MEMORY_E; } XMEMSET(ctx->x509_store.param, 0, sizeof(WOLFSSL_X509_VERIFY_PARAM)); + ctx->x509_store.param->depth = -1; if (wc_InitMutex(&ctx->x509_store.lookup.dirs->lock) != 0) { WOLFSSL_MSG("Bad mutex init"); @@ -6055,6 +6057,10 @@ static void FreeX509Contents(WOLFSSL_X509* x509) if (x509->serialNumber != NULL) { wolfSSL_ASN1_INTEGER_free(x509->serialNumber); } + XFREE(x509->alias, x509->heap, DYNAMIC_TYPE_X509_EXT); + x509->alias = NULL; + XFREE(x509->keyid, x509->heap, DYNAMIC_TYPE_X509_EXT); + x509->keyid = NULL; #endif if (x509->extKeyUsageSrc != NULL) { XFREE(x509->extKeyUsageSrc, x509->heap, DYNAMIC_TYPE_X509_EXT); @@ -9564,6 +9570,7 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) return MEMORY_E; } XMEMSET(ssl->param, 0, sizeof(WOLFSSL_X509_VERIFY_PARAM)); + ssl->param->depth = -1; /* pass on PARAM values from ctx to ssl, including the expected * hostname / IP */ @@ -15768,6 +15775,8 @@ WC_MAYBE_UNUSED static void ResetSessionCertChain(WOLFSSL* ssl) ssl->session->peer = NULL; wolfSSL_sk_X509_pop_free(ssl->peerCertChain, NULL); ssl->peerCertChain = NULL; + wolfSSL_sk_X509_pop_free(ssl->verifiedChain, NULL); + ssl->verifiedChain = NULL; #endif } #endif @@ -16458,6 +16467,8 @@ int CopyDecodedToX509(WOLFSSL_X509* x509, DecodedCert* dCert) /* CSR attributes */ if (x509->isCSR) { + /* As OpenSSL, a request keeps the value of its version field */ + x509->version = dCert->version; copyRet = CopyREQAttributes(x509, dCert); if (copyRet != 0) ret = copyRet; @@ -17224,7 +17235,6 @@ int SetupStoreCtxCallback(WOLFSSL_X509_STORE_CTX** store_pt, #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) store->store = SSL_STORE(ssl); #if defined(OPENSSL_EXTRA) - store->depth = args->count; /* Overwrite with non-default param values in SSL */ if (ssl->param) { if (ssl->param->check_time) @@ -17541,7 +17551,7 @@ void DoCrlCallback(WOLFSSL_CERT_MANAGER* cm, WOLFSSL* ssl, /* Point to current cm to be able to verify CRL */ userCrl->cm = SSL_CM(ssl); *outRet = CheckCertCRLFromCm(SSL_CM(ssl), userCrl, - args->dCert); + args->dCert, NULL, NULL); } else *outRet = CRL_MISSING; @@ -18332,8 +18342,9 @@ static int AdjustCMForParams(WOLFSSL* ssl) param = wolfSSL_get0_param(ssl); flags = wolfSSL_X509_VERIFY_PARAM_get_flags(param); /* 0x2 in a param is X509_V_FLAG_USE_CHECK_TIME, but - * wolfSSL_X509_STORE_set_flags() reads it as WOLFSSL_CRL_CHECK. */ - flags &= ~WOLFSSL_USE_CHECK_TIME; + * wolfSSL_X509_STORE_set_flags() reads it as WOLFSSL_CRL_CHECK. The + * X509_STRICT flag of the connection is not for the store. */ + flags &= ~(WOLFSSL_USE_CHECK_TIME | WOLFSSL_X509_STRICT); /* For now there is a possible contradiction of PARAM flags and store flags. * Do not disable CRL support if it has already been enabled with store. */ @@ -46033,7 +46044,7 @@ static int AddPSKtoPreMasterSecret(WOLFSSL* ssl) #ifdef HAVE_CRL if (ret == 0 && SSL_CM(ssl)->crlEnabled) { ret = CheckCertCRLFromCm(SSL_CM(ssl), SSL_CM(ssl)->crl, - dCert); + dCert, NULL, NULL); } #endif if (ret == 0) { diff --git a/src/pk.c b/src/pk.c index 19f1ca89179..a96f35a3a80 100644 --- a/src/pk.c +++ b/src/pk.c @@ -1017,6 +1017,7 @@ WOLFSSL_DSA* wolfSSL_DSA_new(void) { WOLFSSL_DSA* external; DsaKey* key; + int err = 0; WOLFSSL_MSG("wolfSSL_DSA_new"); @@ -1035,6 +1036,17 @@ WOLFSSL_DSA* wolfSSL_DSA_new(void) } InitwolfSSL_DSA(external); + wolfSSL_RefInit(&external->ref, &err); +#ifdef WOLFSSL_REFCNT_ERROR_RETURN + if (err != 0) { + WOLFSSL_MSG("wolfSSL_DSA_new RefInit failure"); + XFREE(key, NULL, DYNAMIC_TYPE_DSA); + XFREE(external, NULL, DYNAMIC_TYPE_DSA); + return NULL; + } +#else + (void)err; +#endif if (wc_InitDsaKey(key) != 0) { WOLFSSL_MSG("wolfSSL_DSA_new InitDsaKey failure"); XFREE(key, NULL, DYNAMIC_TYPE_DSA); @@ -1049,15 +1061,25 @@ WOLFSSL_DSA* wolfSSL_DSA_new(void) void wolfSSL_DSA_free(WOLFSSL_DSA* dsa) { + int doFree = 0; + WOLFSSL_MSG("wolfSSL_DSA_free"); if (dsa) { + int err; + + /* Only free when the last reference is released. */ + wolfSSL_RefDec(&dsa->ref, &doFree, &err); + (void)err; + } + if (doFree) { + wolfSSL_RefFree(&dsa->ref); if (dsa->internal) { FreeDsaKey((DsaKey*)dsa->internal); XFREE(dsa->internal, NULL, DYNAMIC_TYPE_DSA); dsa->internal = NULL; } - wolfSSL_BN_free(dsa->priv_key); + wolfSSL_BN_clear_free(dsa->priv_key); wolfSSL_BN_free(dsa->pub_key); wolfSSL_BN_free(dsa->g); wolfSSL_BN_free(dsa->q); @@ -1070,6 +1092,25 @@ void wolfSSL_DSA_free(WOLFSSL_DSA* dsa) } } +/* Increments the reference count of the DSA key. + * + * @param [in, out] dsa DSA key. + * @return 1 on success. + * @return 0 on failure. + */ +int wolfSSL_DSA_up_ref(WOLFSSL_DSA* dsa) +{ + int err = 1; + + WOLFSSL_ENTER("wolfSSL_DSA_up_ref"); + + if (dsa != NULL) { + wolfSSL_RefInc(&dsa->ref, &err); + } + + return !err; +} + /* wolfSSL -> OpenSSL */ int SetDsaExternal(WOLFSSL_DSA* dsa) { @@ -1103,9 +1144,16 @@ int SetDsaExternal(WOLFSSL_DSA* dsa) return WOLFSSL_FATAL_ERROR; } - if (wolfssl_bn_set_value(&dsa->priv_key, &key->x) != 1) { - WOLFSSL_MSG("dsa x key error"); - return WOLFSSL_FATAL_ERROR; + if (key->type == DSA_PRIVATE) { + if (wolfssl_bn_set_value(&dsa->priv_key, &key->x) != 1) { + WOLFSSL_MSG("dsa x key error"); + return WOLFSSL_FATAL_ERROR; + } + } + else { + /* Public key or parameters only: no private key. */ + wolfSSL_BN_clear_free(dsa->priv_key); + dsa->priv_key = NULL; } dsa->exSet = 1; @@ -1387,7 +1435,7 @@ int wolfSSL_DSA_set0_key(WOLFSSL_DSA *d, WOLFSSL_BIGNUM *pub_key, d->pub_key = pub_key; } if (priv_key != NULL) { - wolfSSL_BN_free(d->priv_key); + wolfSSL_BN_clear_free(d->priv_key); d->priv_key = priv_key; } @@ -1605,6 +1653,18 @@ WOLFSSL_DSA_SIG* wolfSSL_d2i_DSA_SIG(WOLFSSL_DSA_SIG **sig, #endif /* !HAVE_SELFTEST */ +/* Use the leftmost bytes of the digest up to the size of q. + * FIPS 186-4, 4.6. */ +static int dsa_digest_len(const WOLFSSL_DSA* dsa, int dLen) +{ + int qSz = mp_unsigned_bin_size(&((DsaKey*)dsa->internal)->q); + + if ((qSz > 0) && (dLen > qSz)) { + dLen = qSz; + } + return dLen; +} + int wolfssl_local_dsa_do_sign(const unsigned char* d, int dLen, unsigned char* sigRet, WOLFSSL_DSA* dsa) { @@ -1628,6 +1688,10 @@ int wolfssl_local_dsa_do_sign(const unsigned char* d, int dLen, return WOLFSSL_FATAL_ERROR; } } + if (((DsaKey*)dsa->internal)->type != DSA_PRIVATE) { + WOLFSSL_MSG("No DSA private key"); + return WOLFSSL_FATAL_ERROR; + } WC_ALLOC_VAR_EX(tmpRng, WC_RNG, 1, NULL, DYNAMIC_TYPE_RNG, return WOLFSSL_FATAL_ERROR); @@ -1647,6 +1711,7 @@ int wolfssl_local_dsa_do_sign(const unsigned char* d, int dLen, return WOLFSSL_FATAL_ERROR; } + dLen = dsa_digest_len(dsa, dLen); if (rng) { #ifdef HAVE_SELFTEST /* FIPS 186-4 4.2, as wc_DsaSign_ex() does below. wc_DsaSign() reads @@ -1694,8 +1759,8 @@ WOLFSSL_DSA_SIG* wolfSSL_DSA_do_sign_ex(const unsigned char* digest, int inLen, WOLFSSL_DSA* dsa) { byte sigBin[DSA_MAX_SIG_SIZE]; - const byte *tmp = sigBin; - int sigLen; + WOLFSSL_DSA_SIG* sig; + int halfSz; WOLFSSL_ENTER("wolfSSL_DSA_do_sign_ex"); @@ -1714,14 +1779,24 @@ WOLFSSL_DSA_SIG* wolfSSL_DSA_do_sign_ex(const unsigned char* digest, return NULL; } - sigLen = mp_unsigned_bin_size(&((DsaKey*)dsa->internal)->q); - if (sigLen <= 0) { + halfSz = mp_unsigned_bin_size(&((DsaKey*)dsa->internal)->q); + if (halfSz <= 0 || halfSz > DSA_MAX_HALF_SIZE) { WOLFSSL_MSG("mp_unsigned_bin_size error"); return NULL; } - /* 2 * sigLen for the two points r and s */ - return wolfSSL_d2i_DSA_SIG(NULL, &tmp, 2 * sigLen); + /* Raw signature is r then s, each the size of q. */ + if ((sig = wolfSSL_DSA_SIG_new_bn()) == NULL) + return NULL; + if (mp_read_unsigned_bin((mp_int*)sig->r->internal, sigBin, + (word32)halfSz) != MP_OKAY || + mp_read_unsigned_bin((mp_int*)sig->s->internal, sigBin + halfSz, + (word32)halfSz) != MP_OKAY) { + WOLFSSL_MSG("mp_read_unsigned_bin error"); + wolfSSL_DSA_SIG_free(sig); + return NULL; + } + return sig; } #endif @@ -1747,6 +1822,7 @@ int wolfssl_local_dsa_do_verify(const unsigned char* d, int dLen, unsigned char* } } + dLen = dsa_digest_len(dsa, dLen); #ifdef HAVE_SELFTEST /* FIPS 186-4 4.2, as wc_DsaVerify_ex() does below. wc_DsaVerify() reads * exactly WC_SHA_DIGEST_SIZE bytes, so it can only serve the digests that @@ -1790,6 +1866,32 @@ int wolfSSL_DSA_bits(const WOLFSSL_DSA *d) return wolfSSL_BN_num_bits(d->p); } +/* Maximum size of a DER encoded DSA signature: r = s = q. + * + * @param [in] dsa DSA key. + * @return Size in bytes on success. + * @return -1 when q is not set. + */ +int wolfSSL_DSA_size(const WOLFSSL_DSA *dsa) +{ + int qBits; + int intSz; + + WOLFSSL_ENTER("wolfSSL_DSA_size"); + + if ((dsa == NULL) || (dsa->q == NULL)) { + return WOLFSSL_FATAL_ERROR; + } + qBits = wolfSSL_BN_num_bits(dsa->q); + if (qBits <= 0) { + return WOLFSSL_FATAL_ERROR; + } + /* INTEGER of q: one more byte when the top bit is set. */ + intSz = qBits / WOLFSSL_BIT_SIZE + 1; + intSz += 1 + (int)SetLength((word32)intSz, NULL); + return 1 + (int)SetLength((word32)(2 * intSz), NULL) + 2 * intSz; +} + #ifndef HAVE_SELFTEST int wolfSSL_DSA_do_verify_ex(const unsigned char* digest, int digest_len, WOLFSSL_DSA_SIG* sig, WOLFSSL_DSA* dsa) @@ -1835,7 +1937,7 @@ int wolfSSL_DSA_do_verify_ex(const unsigned char* digest, int digest_len, /* read r */ /* front pad with zeros */ - if ((sz = wolfSSL_BN_num_bytes(sig->r)) < 0 || sz > DSA_MAX_HALF_SIZE) + if ((sz = wolfSSL_BN_num_bytes(sig->r)) < 0 || sz > qSz) return 0; while (sz++ < qSz) *sigBinPtr++ = 0; @@ -1847,7 +1949,7 @@ int wolfSSL_DSA_do_verify_ex(const unsigned char* digest, int digest_len, /* read s */ /* front pad with zeros */ - if ((sz = wolfSSL_BN_num_bytes(sig->s)) < 0 || sz > DSA_MAX_HALF_SIZE) + if ((sz = wolfSSL_BN_num_bytes(sig->s)) < 0 || sz > qSz) return 0; while (sz++ < qSz) *sigBinPtr++ = 0; @@ -2874,7 +2976,7 @@ void wolfSSL_DH_free(WOLFSSL_DH* dh) } /* Dispose of any allocated BNs. */ - wolfSSL_BN_free(dh->priv_key); + wolfSSL_BN_clear_free(dh->priv_key); wolfSSL_BN_free(dh->pub_key); wolfSSL_BN_free(dh->g); wolfSSL_BN_free(dh->p); @@ -4837,7 +4939,7 @@ int wolfSSL_DH_generate_key(WOLFSSL_DH* dh) if (ret == 1) { /* Dispose of old public and private keys. */ wolfSSL_BN_free(dh->pub_key); - wolfSSL_BN_free(dh->priv_key); + wolfSSL_BN_clear_free(dh->priv_key); /* Allocate new public and private keys. */ dh->pub_key = wolfSSL_BN_new(); diff --git a/src/pk_ec.c b/src/pk_ec.c index 91da8ed6fb5..83add5c450b 100644 --- a/src/pk_ec.c +++ b/src/pk_ec.c @@ -3140,7 +3140,7 @@ void wolfSSL_EC_KEY_free(WOLFSSL_EC_KEY *key) wolfSSL_RefFree(&key->ref); /* Dispose of private key. */ - wolfSSL_BN_free(key->priv_key); + wolfSSL_BN_clear_free(key->priv_key); wolfSSL_EC_POINT_free(key->pub_key); wolfSSL_EC_GROUP_free(key->group); if (key->internal != NULL) { @@ -3696,6 +3696,8 @@ int wolfSSL_EC_KEY_LoadDer_ex(WOLFSSL_EC_KEY* key, const unsigned char* derBuf, if (res == 1) { /* Load into internal EC key based on key type option. */ if (opt == WOLFSSL_EC_KEY_LOAD_PRIVATE) { + /* Decode with any PKCS#8 header, which holds the curve. */ + idx = 0; ret = wc_EccPrivateKeyDecode(derBuf, &idx, (ecc_key*)key->internal, (word32)derSz); } @@ -4672,7 +4674,7 @@ int wolfSSL_EC_KEY_set_private_key(WOLFSSL_EC_KEY *key, if (ret == 1) { /* Free key if previously set. */ if (key->priv_key != NULL) { - wolfSSL_BN_free(key->priv_key); + wolfSSL_BN_clear_free(key->priv_key); } /* Duplicate the BN passed in. */ @@ -4686,7 +4688,7 @@ int wolfSSL_EC_KEY_set_private_key(WOLFSSL_EC_KEY *key, if ((ret == 1) && (SetECKeyInternal(key) != 1)) { WOLFSSL_MSG("SetECKeyInternal failed"); /* Dispose of new private key on error. */ - wolfSSL_BN_free(key->priv_key); + wolfSSL_BN_clear_free(key->priv_key); key->priv_key = NULL; ret = 0; } @@ -5205,8 +5207,11 @@ WOLFSSL_ECDSA_SIG* wolfSSL_d2i_ECDSA_SIG(WOLFSSL_ECDSA_SIG** sig, * @param [in] sig ECDSA signature object. * @param [in, out] pp On in, reference to buffer in which to place encoding. * On out, reference to buffer after encoding. - * May be NULL or point to NULL in which case no encoding - * is done. + * May be NULL in which case no encoding is done. + * When it points to NULL, with + * WOLFSSL_I2D_ECDSA_SIG_ALLOC it is set to a new buffer + * with the encoding, freed with OPENSSL_free(), and + * stays NULL on error; otherwise no encoding is done. * @return Length of encoding on success. * @return 0 on error. */ @@ -5251,6 +5256,11 @@ int wolfSSL_i2d_ECDSA_SIG(const WOLFSSL_ECDSA_SIG *sig, unsigned char **pp) (mp_int*)sig->s->internal) != MP_OKAY) { /* No bytes encoded. */ len = 0; + if (!update_p) { + /* Free the buffer allocated here. */ + XFREE(*pp, NULL, DYNAMIC_TYPE_OPENSSL); + *pp = NULL; + } } else if (update_p) { /* Update pointer to after encoding. */ diff --git a/src/pk_rsa.c b/src/pk_rsa.c index b029fcc4051..b8abd54dca2 100644 --- a/src/pk_rsa.c +++ b/src/pk_rsa.c @@ -2952,6 +2952,207 @@ int wolfSSL_RSA_verify_PKCS1_PSS(WOLFSSL_RSA *rsa, const unsigned char *mHash, (OPENSSL_ALL || WOLFSSL_ASIO || WOLFSSL_HAPROXY || WOLFSSL_NGINX) */ #endif /* WC_RSA_PSS */ +#ifdef WOLFSSL_RSA_OAEP_COMPAT +/* Get the wolfCrypt hash and MGF of OAEP. As in OpenSSL, no md is SHA-1 and + * no mgf1md is md. + * + * @param [in] md Hash of the label. May be NULL. + * @param [in] mgf1md Hash of MGF1. May be NULL. + * @param [out] hash wolfCrypt hash type. + * @param [out] mgf wolfCrypt MGF. + * @return 1 on success. + * @return 0 when a hash is not supported. + */ +static int rsa_oaep_hash_mgf(const WOLFSSL_EVP_MD* md, + const WOLFSSL_EVP_MD* mgf1md, enum wc_HashType* hash, int* mgf) +{ + int ret = 1; + + *hash = (md != NULL) ? EvpMd2MacType(md) : WC_HASH_TYPE_SHA; + *mgf = wc_hash2mgf((mgf1md != NULL) ? EvpMd2MacType(mgf1md) : *hash); + if ((*hash == WC_HASH_TYPE_NONE) || (*mgf == WC_MGF1NONE)) { + WOLFSSL_MSG("OAEP hash not supported"); + ret = 0; + } + + return ret; +} + +/* Add PKCS#1 OAEP padding to a message. + * RFC 8017, 7.1.1, step 2. + * + * @param [out] to Encoded message of tlen bytes. + * @param [in] tlen Size of the RSA modulus in bytes. + * @param [in] from Message. + * @param [in] flen Length of message in bytes. + * @param [in] param Label. May be NULL when plen is 0. + * @param [in] plen Length of label in bytes. + * @param [in] md Hash of the label. NULL for SHA-1. + * @param [in] mgf1md Hash of MGF1. NULL for md. + * @return 1 on success. + * @return 0 on failure. + */ +int wolfSSL_RSA_padding_add_PKCS1_OAEP_mgf1(unsigned char* to, int tlen, + const unsigned char* from, int flen, const unsigned char* param, int plen, + const WOLFSSL_EVP_MD* md, const WOLFSSL_EVP_MD* mgf1md) +{ + int ret = 1; + WC_RNG* rng = NULL; + enum wc_HashType hash = WC_HASH_TYPE_NONE; + int mgf = WC_MGF1NONE; + + WOLFSSL_ENTER("wolfSSL_RSA_padding_add_PKCS1_OAEP_mgf1"); + + /* wolfCrypt pads blocks up to the size of the largest RSA key. */ + if ((to == NULL) || (tlen <= 0) || (tlen > RSA_MAX_SIZE / 8) || + (flen < 0) || ((from == NULL) && (flen > 0)) || (plen < 0) || + ((param == NULL) && (plen > 0))) { + WOLFSSL_MSG("Bad argument"); + ret = 0; + } + if (ret == 1) { + ret = rsa_oaep_hash_mgf(md, mgf1md, &hash, &mgf); + } + /* Create the global RNG before locking. Creating it takes the lock. */ + if ((ret == 1) && (wolfssl_make_global_rng() == NULL)) { + WOLFSSL_MSG("Failed to make RNG"); + ret = 0; + } + /* Global RNG is shared, lock it while padding. */ + if ((ret == 1) && (wc_LockMutex(&globalRNGMutex) != 0)) { + WOLFSSL_MSG("Bad Lock Mutex rng"); + ret = 0; + } + if (ret == 1) { + /* Get it under the lock. It may have been freed since it was made. */ + rng = wolfssl_get_global_rng(); + if (rng == NULL) { + ret = 0; + } + else if (wc_RsaPad_ex((from != NULL) ? from : to, (word32)flen, to, + (word32)tlen, RSA_BLOCK_TYPE_2, rng, WC_RSA_OAEP_PAD, hash, + mgf, (byte*)param, (word32)plen, 0, tlen * 8, NULL) != 0) { + WOLFSSL_MSG("wc_RsaPad_ex failed"); + ret = 0; + } + wc_UnLockMutex(&globalRNGMutex); + } + + return ret; +} + +/* Add PKCS#1 OAEP padding with SHA-1 and MGF1-SHA-1 to a message. + * + * @param [out] to Encoded message of tlen bytes. + * @param [in] tlen Size of the RSA modulus in bytes. + * @param [in] from Message. + * @param [in] flen Length of message in bytes. + * @param [in] param Label. May be NULL when plen is 0. + * @param [in] plen Length of label in bytes. + * @return 1 on success. + * @return 0 on failure. + */ +int wolfSSL_RSA_padding_add_PKCS1_OAEP(unsigned char* to, int tlen, + const unsigned char* from, int flen, const unsigned char* param, int plen) +{ + WOLFSSL_ENTER("wolfSSL_RSA_padding_add_PKCS1_OAEP"); + + return wolfSSL_RSA_padding_add_PKCS1_OAEP_mgf1(to, tlen, from, flen, param, + plen, NULL, NULL); +} + +/* Check PKCS#1 OAEP padding and get the message. + * RFC 8017, 7.1.2, step 3. + * + * from may lack the leading zero bytes of the encoded message. + * + * @param [out] to Buffer for the message. May be from. + * @param [in] tlen Size of to in bytes. + * @param [in] from Encoded message. + * @param [in] flen Length of encoded message in bytes. + * @param [in] num Size of the RSA modulus in bytes. + * @param [in] param Label. May be NULL when plen is 0. + * @param [in] plen Length of label in bytes. + * @param [in] md Hash of the label. NULL for SHA-1. + * @param [in] mgf1md Hash of MGF1. NULL for md. + * @return Length of the message on success. + * @return -1 on failure. wolfCrypt does not tell an empty message from a + * decoding error, so an empty message also fails. + */ +int wolfSSL_RSA_padding_check_PKCS1_OAEP_mgf1(unsigned char* to, int tlen, + const unsigned char* from, int flen, int num, const unsigned char* param, + int plen, const WOLFSSL_EVP_MD* md, const WOLFSSL_EVP_MD* mgf1md) +{ + int ret = 0; + byte* em = NULL; + byte* msg = NULL; + enum wc_HashType hash = WC_HASH_TYPE_NONE; + int mgf = WC_MGF1NONE; + + WOLFSSL_ENTER("wolfSSL_RSA_padding_check_PKCS1_OAEP_mgf1"); + + /* wolfCrypt decodes blocks up to the size of the largest RSA key. */ + if ((to == NULL) || (tlen < 0) || (from == NULL) || (flen < 0) || + (num <= 0) || (num > RSA_MAX_SIZE / 8) || (flen > num) || + (plen < 0) || ((param == NULL) && (plen > 0))) { + WOLFSSL_MSG("Bad argument"); + ret = WOLFSSL_FATAL_ERROR; + } + if ((ret == 0) && (rsa_oaep_hash_mgf(md, mgf1md, &hash, &mgf) != 1)) { + ret = WOLFSSL_FATAL_ERROR; + } + if (ret == 0) { + em = (byte*)XMALLOC((size_t)num, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (em == NULL) { + ret = WOLFSSL_FATAL_ERROR; + } + } + if (ret == 0) { + /* Put back the leading zero bytes. */ + XMEMSET(em, 0, (size_t)(num - flen)); + XMEMCPY(em + num - flen, from, (size_t)flen); + ret = wc_RsaUnPad_ex(em, (word32)num, &msg, RSA_BLOCK_TYPE_2, + WC_RSA_OAEP_PAD, hash, mgf, (byte*)param, (word32)plen, 0, + num * 8, NULL); + if ((ret <= 0) || (ret > tlen)) { + WOLFSSL_MSG("OAEP decoding failed"); + ret = WOLFSSL_FATAL_ERROR; + } + else { + XMEMCPY(to, msg, (size_t)ret); + } + } + + if (em != NULL) { + ForceZero(em, (word32)num); + XFREE(em, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + return ret; +} + +/* Check PKCS#1 OAEP padding with SHA-1 and MGF1-SHA-1 and get the message. + * + * @param [out] to Buffer for the message. May be from. + * @param [in] tlen Size of to in bytes. + * @param [in] from Encoded message. + * @param [in] flen Length of encoded message in bytes. + * @param [in] num Size of the RSA modulus in bytes. + * @param [in] param Label. May be NULL when plen is 0. + * @param [in] plen Length of label in bytes. + * @return Length of the message on success. + * @return -1 on failure. + */ +int wolfSSL_RSA_padding_check_PKCS1_OAEP(unsigned char* to, int tlen, + const unsigned char* from, int flen, int num, const unsigned char* param, + int plen) +{ + WOLFSSL_ENTER("wolfSSL_RSA_padding_check_PKCS1_OAEP"); + + return wolfSSL_RSA_padding_check_PKCS1_OAEP_mgf1(to, tlen, from, flen, + num, param, plen, NULL, NULL); +} +#endif /* WOLFSSL_RSA_OAEP_COMPAT */ + /* * RSA sign/verify APIs */ diff --git a/src/ssl.c b/src/ssl.c index 3773badb1d9..cb8aae381ba 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -433,11 +433,15 @@ WC_RNG* wolfssl_make_rng(WC_RNG* rng, int* local) * them here, next to the includes, rather than inside the files that need * them. * - * x509GetIssuerFromCM() is defined in src/x509_str.c, which also requires - * NO_CERTS to be undefined. */ + * x509GetIssuerFromCM() and X509StoreCmIsIssuer() are defined in + * src/x509_str.c, which also requires NO_CERTS to be undefined. */ #if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) && !defined(NO_CERTS) static int x509GetIssuerFromCM(WOLFSSL_X509 **issuer, WOLFSSL_CERT_MANAGER* cm, WOLFSSL_X509 *x); +#ifdef KEEP_PEER_CERT +static int X509StoreCmIsIssuer(WOLFSSL_CERT_MANAGER* cm, WOLFSSL_X509* ca, + WOLFSSL_X509* x509); +#endif #endif #define WOLFSSL_SSL_API_CERT_INCLUDED @@ -6147,6 +6151,11 @@ size_t wolfSSL_get_client_random(const WOLFSSL* ssl, unsigned char* out, #ifdef KEEP_PEER_CERT FreePeerCert(ssl); #endif +#ifdef OPENSSL_EXTRA + /* The next connection builds its own verified chain. */ + wolfSSL_sk_X509_pop_free(ssl->verifiedChain, NULL); + ssl->verifiedChain = NULL; +#endif #ifdef WOLFSSL_QUIC wolfSSL_quic_clear(ssl); @@ -8915,6 +8924,45 @@ static void* OSSL_Realloc(void *ptr, size_t size) #endif /* USE_WOLFSSL_MEMORY && !WOLFSSL_DEBUG_MEMORY && * !WOLFSSL_STATIC_MEMORY */ +/* The allocators CRYPTO_get_mem_functions returns when none are set. They + * don't call into wolfSSL's allocator, so a wrapper of them passed to + * CRYPTO_set_mem_functions does not recurse. */ +#if !defined(USE_WOLFSSL_MEMORY) || defined(WOLFSSL_STATIC_MEMORY) + #define OSSL_DEF_MALLOC(s) XMALLOC(s, NULL, DYNAMIC_TYPE_OPENSSL) + #define OSSL_DEF_REALLOC(p, s) XREALLOC(p, s, NULL, DYNAMIC_TYPE_OPENSSL) + #define OSSL_DEF_FREE(p) XFREE(p, NULL, DYNAMIC_TYPE_OPENSSL) +#elif !defined(WOLFSSL_NO_MALLOC) + #define OSSL_DEF_MALLOC(s) malloc(s) /* native heap */ + #define OSSL_DEF_REALLOC(p, s) realloc(p, s) /* native heap */ + #define OSSL_DEF_FREE(p) free(p) /* native heap */ +#else + #define OSSL_DEF_MALLOC(s) ((void)(s), (void*)NULL) + #define OSSL_DEF_REALLOC(p, s) ((void)(p), (void)(s), (void*)NULL) + #define OSSL_DEF_FREE(p) (void)(p) +#endif + +static void* OSSL_DefMalloc(size_t size, const char* file, int line) +{ + (void)file; + (void)line; + return OSSL_DEF_MALLOC(size); +} + +static void* OSSL_DefRealloc(void* ptr, size_t size, const char* file, + int line) +{ + (void)file; + (void)line; + return OSSL_DEF_REALLOC(ptr, size); +} + +static void OSSL_DefFree(void* ptr, const char* file, int line) +{ + (void)file; + (void)line; + OSSL_DEF_FREE(ptr); +} + int wolfSSL_CRYPTO_set_mem_functions( wolfSSL_OSSL_Malloc_cb m, wolfSSL_OSSL_Realloc_cb r, @@ -8950,6 +8998,57 @@ int wolfSSL_CRYPTO_set_mem_functions( #endif } +/* Get the allocators set with CRYPTO_set_mem_functions, as in OpenSSL 3.0. + * + * When none are set, the returned functions use the C library. They can be + * wrapped and the wrappers passed to CRYPTO_set_mem_functions. + * Where that is not supported they allocate as OPENSSL_malloc does. + * + * @param [out] m Malloc function. May be NULL. + * @param [out] r Realloc function. May be NULL. + * @param [out] f Free function. May be NULL. + */ +void wolfSSL_CRYPTO_get_mem_functions( + wolfSSL_OSSL_Malloc_cb* m, + wolfSSL_OSSL_Realloc_cb* r, + wolfSSL_OSSL_Free_cb* f) +{ + wolfSSL_OSSL_Malloc_cb mf = OSSL_DefMalloc; + wolfSSL_OSSL_Realloc_cb rf = OSSL_DefRealloc; + wolfSSL_OSSL_Free_cb ff = OSSL_DefFree; + +#if defined(USE_WOLFSSL_MEMORY) && !defined(WOLFSSL_DEBUG_MEMORY) && \ + !defined(WOLFSSL_STATIC_MEMORY) + if (ossl_malloc != NULL) { + mf = ossl_malloc; + rf = ossl_realloc; + ff = ossl_free; + } +#elif defined(USE_WOLFSSL_MEMORY) && !defined(WOLFSSL_STATIC_MEMORY) + { + wolfSSL_Malloc_cb wmf = NULL; + wolfSSL_Free_cb wff = NULL; + wolfSSL_Realloc_cb wrf = NULL; + + /* CRYPTO_set_mem_functions sets them as wolfSSL's allocators. */ + (void)wolfSSL_GetAllocators(&wmf, &wff, &wrf); + if (wmf != NULL) + mf = (wolfSSL_OSSL_Malloc_cb)wmf; + if (wrf != NULL) + rf = (wolfSSL_OSSL_Realloc_cb)wrf; + if (wff != NULL) + ff = (wolfSSL_OSSL_Free_cb)wff; + } +#endif + + if (m != NULL) + *m = mf; + if (r != NULL) + *r = rf; + if (f != NULL) + *f = ff; +} + int wolfSSL_FIPS_mode(void) { #ifdef HAVE_FIPS diff --git a/src/ssl_api_cert.c b/src/ssl_api_cert.c index 15781db1732..537a6b444cd 100644 --- a/src/ssl_api_cert.c +++ b/src/ssl_api_cert.c @@ -3395,21 +3395,64 @@ WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_set_peer_cert_chain(WOLFSSL* ssl) } #ifdef KEEP_PEER_CERT -/* Get the peer's certificate chain, verified against the store. +/* Verify callback for a chain the handshake verified. As the handshake, it + * accepts the date and CA errors of a cert manager CA where that CA verifies + * the cert below it. Any other error fails. + * + * @param [in] ok 1 when the cert at the error depth passed its checks. + * @param [in] ctx X509 store context. + * @return 1 when verification is to continue, 0 to fail. + */ +int VerifiedChainCb(int ok, WOLFSSL_X509_STORE_CTX* ctx) +{ + if ((!ok) && (ctx->error_depth > 0)) { + switch (ctx->error) { + case WOLFSSL_X509_V_ERR_CERT_NOT_YET_VALID: + case WOLFSSL_X509_V_ERR_CERT_HAS_EXPIRED: + case WOLFSSL_X509_V_ERR_INVALID_CA: + case WOLFSSL_X509_V_ERR_KEYUSAGE_NO_CERTSIGN: + ok = X509StoreCmIsIssuer(ctx->store->cm, + wolfSSL_sk_X509_value(ctx->chain, ctx->error_depth), + wolfSSL_sk_X509_value(ctx->chain, ctx->error_depth - 1)); + break; + default: + break; + } + } + + return ok; +} + +/* Returns 1 when the verified chain kept on ssl is of the peer's cert. */ +static int VerifiedChainIsPeer(const WOLFSSL* ssl) +{ + WOLFSSL_X509* x = wolfSSL_sk_X509_value(ssl->verifiedChain, 0); + const WOLFSSL_X509_CHAIN* peer = &ssl->session->chain; + + return (x != NULL) && (x->derCert != NULL) && (peer->count > 0) && + ((int)x->derCert->length == peer->certs[0].length) && + (XMEMCMP(x->derCert->buffer, peer->certs[0].buffer, + x->derCert->length) == 0); +} + +/* Get the peer's chain as verified, from its cert to the trust anchor. * - * Implemented in a similar way to ngx_ssl_ocsp_validate() when - * SSL_get0_verified_chain is not available. The chain is stored on the SSL/TLS - * object and disposed of with it, so the caller must not free it. + * Built with wolfSSL_X509_verify_cert() once per peer cert and kept on ssl + * until a new peer chain or wolfSSL_clear(), as OpenSSL keeps the chain of the + * handshake. After a full handshake that verified the peer, VerifiedChainCb() + * applies; else every check does. Without WOLFSSL_SIGNER_DER_CERT a CA of the + * cert manager cannot go on the chain. * * @param [in, out] ssl SSL/TLS object. Declared const, but the verified * chain is stored into it. - * @return Stack of verified certificates on success. + * @return Stack of verified certificates on success. Owned by ssl. * @return NULL when ssl or its context is NULL, no peer certificate was kept, * the chain cannot be built, or verification fails. */ WOLF_STACK_OF(WOLFSSL_X509) *wolfSSL_get0_verified_chain(const WOLFSSL *ssl) { WOLF_STACK_OF(WOLFSSL_X509)* chain = NULL; + WOLF_STACK_OF(WOLFSSL_X509)* peerChain = NULL; WOLFSSL_X509_STORE_CTX* storeCtx = NULL; WOLFSSL_X509* peerCert = NULL; int err = 0; @@ -3421,6 +3464,9 @@ WOLF_STACK_OF(WOLFSSL_X509) *wolfSSL_get0_verified_chain(const WOLFSSL *ssl) WOLFSSL_MSG("Bad parameter"); err = 1; } + else if (VerifiedChainIsPeer(ssl)) { + return ssl->verifiedChain; + } if (!err) { /* Owned by ssl, so not freed here. */ @@ -3432,19 +3478,12 @@ WOLF_STACK_OF(WOLFSSL_X509) *wolfSSL_get0_verified_chain(const WOLFSSL *ssl) } if (!err) { - chain = CreatePeerCertChain((WOLFSSL*)ssl, 1); - if (chain == NULL) { + /* The peer's certificate first, then its chain and the CA chain. */ + peerChain = CreatePeerCertChain((WOLFSSL*)ssl, 1); + if (peerChain == NULL) { WOLFSSL_MSG("wolfSSL_get_peer_cert_chain error"); err = 1; } - else { - /* Replace any chain kept from a previous call. */ - if (ssl->verifiedChain != NULL) { - wolfSSL_sk_X509_pop_free(ssl->verifiedChain, NULL); - } - /* This is Free'd when ssl is Free'd */ - ((WOLFSSL*)ssl)->verifiedChain = chain; - } } if (!err) { @@ -3456,23 +3495,41 @@ WOLF_STACK_OF(WOLFSSL_X509) *wolfSSL_get0_verified_chain(const WOLFSSL *ssl) } if (!err) { - if (wolfSSL_X509_STORE_CTX_init(storeCtx, SSL_STORE(ssl), peerCert, - chain) != WOLFSSL_SUCCESS) { + if (wolfSSL_X509_STORE_CTX_init(storeCtx, SSL_STORE(ssl), + wolfSSL_sk_X509_value(peerChain, 0), peerChain) != + WOLFSSL_SUCCESS) { WOLFSSL_MSG("wolfSSL_X509_STORE_CTX_init error"); err = 1; } - else if (wolfSSL_X509_verify_cert(storeCtx) <= 0) { + } + + if (!err) { + /* A full handshake verified the peer: no error, not even one a + * verify callback accepted. */ + if ((!ssl->options.verifyNone) && + (ssl->peerVerifyRet == WOLFSSL_X509_V_OK) && + (!wolfSSL_session_reused((WOLFSSL*)ssl))) { + wolfSSL_X509_STORE_CTX_set_verify_cb(storeCtx, VerifiedChainCb); + } + if (wolfSSL_X509_verify_cert(storeCtx) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("wolfSSL_X509_verify_cert error"); err = 1; } } - wolfSSL_X509_STORE_CTX_free(storeCtx); - if (err) { - /* The chain stays owned by the object; report failure only. */ - chain = NULL; + if (!err) { + /* Take the chain built, leaf to trust anchor. */ + chain = storeCtx->chain; + storeCtx->chain = NULL; + /* Replace a chain of an earlier peer. */ + wolfSSL_sk_X509_pop_free(ssl->verifiedChain, NULL); + /* This is Free'd when ssl is Free'd */ + ((WOLFSSL*)ssl)->verifiedChain = chain; } + wolfSSL_X509_STORE_CTX_free(storeCtx); + wolfSSL_sk_X509_pop_free(peerChain, NULL); + return chain; } #endif /* KEEP_PEER_CERT */ diff --git a/src/ssl_asn1.c b/src/ssl_asn1.c index 1b4390b26d0..ccb578c935f 100644 --- a/src/ssl_asn1.c +++ b/src/ssl_asn1.c @@ -1040,58 +1040,88 @@ void wolfSSL_ASN1_INTEGER_free(WOLFSSL_ASN1_INTEGER* in) XFREE(in, NULL, DYNAMIC_TYPE_OPENSSL); } -/* Get the length of the raw integer value bytes, stripping the DER tag/length - * header if present. Required for OpenSSL compatibility where ASN1_INTEGER is - * typedef'd to ASN1_STRING and callers use ASN1_STRING_length() on integers. +/* Get the value of the INTEGER as OpenSSL holds it: the magnitude without the + * DER header and leading zero octets. Data without a DER header is the value + * (WOLFSSL_QT / WOLFSSL_HAPROXY format). + * + * @param [in] ai ASN.1 INTEGER object. + * @param [out] len Length of the value in bytes. + * @return Pointer to the value on success. + * @return NULL when ai is NULL or has no data. + */ +static const unsigned char* wolfssl_asn1_integer_value( + const WOLFSSL_ASN1_INTEGER* ai, int* len) +{ + const unsigned char* data = NULL; + word32 idx = 1; + int derLen = 0; + + *len = 0; + if ((ai != NULL) && (ai->data != NULL) && (ai->length > 0)) { + data = ai->data; + *len = ai->length; + if ((data[0] == ASN_INTEGER) && + (GetLength(data, &idx, &derLen, (word32)ai->length) >= 0) && + (idx + (word32)derLen == (word32)ai->length)) { + data += idx; + *len = derLen; + } + while ((*len > 1) && (data[0] == 0x00)) { + data++; + (*len)--; + } + } + + return data; +} + +/* Get the length of the value of the INTEGER, as ASN1_STRING_length() on an + * ASN1_INTEGER in OpenSSL. * * @param [in] ai ASN.1 INTEGER object. - * @return Length of the raw integer value on success. - * @return 0 when ai is NULL or data is invalid. + * @return Length of the value on success. + * @return 0 when ai is NULL or has no data. */ int wolfSSL_ASN1_INTEGER_get_length(const WOLFSSL_ASN1_INTEGER* ai) { - if (ai == NULL || ai->data == NULL || ai->length <= 0) { - return 0; - } - if (ai->data[0] == ASN_INTEGER) { - word32 idx = 1; - int len = 0; - if (GetLength(ai->data, &idx, &len, (word32)ai->length) >= 0 && - idx + (word32)len == (word32)ai->length) { - return len; - } - } - /* WOLFSSL_QT / WOLFSSL_HAPROXY format: raw bytes without DER header, - * or data that coincidentally starts with 0x02 but whose header+value - * boundaries do not span exactly ai->length. */ - return ai->length; + int len; + + (void)wolfssl_asn1_integer_value(ai, &len); + return len; } -/* Get a pointer to the raw integer value bytes, skipping the DER tag/length - * header if present. Required for OpenSSL compatibility where ASN1_INTEGER is - * typedef'd to ASN1_STRING and callers use ASN1_STRING_get0_data() on integers. +/* Get the value of the INTEGER, as ASN1_STRING_get0_data() on an ASN1_INTEGER + * in OpenSSL: the magnitude, big-endian. The sign is in the type. * * @param [in] ai ASN.1 INTEGER object. - * @return Pointer to the raw integer value bytes on success. - * @return NULL when ai is NULL or data is invalid. + * @return Pointer to the value on success. + * @return NULL when ai is NULL or has no data. */ const unsigned char* wolfSSL_ASN1_INTEGER_get0_data(const WOLFSSL_ASN1_INTEGER* ai) { - if (ai == NULL || ai->data == NULL || ai->length <= 0) { - return NULL; - } - if (ai->data[0] == ASN_INTEGER) { - word32 idx = 1; - int len = 0; - if (GetLength(ai->data, &idx, &len, (word32)ai->length) >= 0 && - idx + (word32)len == (word32)ai->length) { - return ai->data + idx; - } + int len; + + return wolfssl_asn1_integer_value(ai, &len); +} + +/* Get the type of the INTEGER, as ASN1_STRING_type() on an ASN1_INTEGER in + * OpenSSL. The sign is in the negative flag, as for the other INTEGER APIs. + * + * @param [in] ai ASN.1 INTEGER object. + * @return WOLFSSL_V_ASN1_NEG_INTEGER when negative. + * @return WOLFSSL_V_ASN1_INTEGER when not negative. + * @return 0 when ai is NULL. + */ +int wolfSSL_ASN1_INTEGER_get_type(const WOLFSSL_ASN1_INTEGER* ai) +{ + int type = 0; + + if (ai != NULL) { + type = ai->negative ? WOLFSSL_V_ASN1_NEG_INTEGER : + WOLFSSL_V_ASN1_INTEGER; } - /* WOLFSSL_QT / WOLFSSL_HAPROXY format: raw bytes without DER header, - * or data that coincidentally starts with 0x02 but whose header+value - * boundaries do not span exactly ai->length. */ - return ai->data; + + return type; } #if defined(OPENSSL_EXTRA) @@ -1261,6 +1291,7 @@ WOLFSSL_ASN1_INTEGER* wolfSSL_ASN1_INTEGER_dup(const WOLFSSL_ASN1_INTEGER* src) } else { XMEMCPY(dst->data, src->data, (size_t)src->length); + dst->length = src->length; } } @@ -1300,13 +1331,20 @@ int wolfSSL_ASN1_INTEGER_cmp(const WOLFSSL_ASN1_INTEGER* a, ret = 1; } else { + /* Compare the magnitudes from the accessors: data may hold the DER + * encoding or only the content. */ + const unsigned char* aData = wolfSSL_ASN1_INTEGER_get0_data(a); + const unsigned char* bData = wolfSSL_ASN1_INTEGER_get0_data(b); + int aLen = wolfSSL_ASN1_INTEGER_get_length(a); + int bLen = wolfSSL_ASN1_INTEGER_get_length(b); + /* Check for difference in length. */ - if (a->length != b->length) { - ret = a->length - b->length; + if (aLen != bLen) { + ret = aLen - bLen; } - else { + else if (aLen > 0) { /* Compare data given they are the same length. */ - ret = XMEMCMP(a->data, b->data, (size_t)a->length); + ret = XMEMCMP(aData, bData, (size_t)aLen); } /* Reverse comparison result when both negative. */ if (a->negative) { @@ -1361,7 +1399,7 @@ static int wolfssl_asn1_int_twos_compl(byte* data, int length, byte* neg) } else { if (neg != NULL) { - *neg = data[idx] & 0x80; + *neg = (data[idx] & 0x80) ? 1 : 0; } if ((neg == NULL) || (*neg != 0)) { wolfssl_twos_compl(data + idx, length - (int)idx); @@ -1504,6 +1542,13 @@ WOLFSSL_ASN1_INTEGER* wolfSSL_d2i_ASN1_INTEGER(WOLFSSL_ASN1_INTEGER** a, WOLFSSL_MSG("ASN.1 length too large."); err = 1; } + /* DER has no redundant leading octet. OpenSSL rejects one. */ + if ((!err) && (len > 1) && + ((((*in)[idx] == 0x00) && (((*in)[idx + 1] & 0x80) == 0)) || + (((*in)[idx] == 0xff) && (((*in)[idx + 1] & 0x80) != 0)))) { + WOLFSSL_MSG("ASN.1 INTEGER not minimal."); + err = 1; + } /* Allocate a new ASN.1 INTEGER object. */ if ((!err) && ((ret = wolfSSL_ASN1_INTEGER_new()) == NULL)) { err = 1; @@ -1714,6 +1759,11 @@ int wolfSSL_i2a_ASN1_INTEGER(WOLFSSL_BIO *bp, const WOLFSSL_ASN1_INTEGER *a) err = 1; } } + /* Write the magnitude, without the DER zero octet, as OpenSSL. */ + while ((!err) && (len > 1) && (a->data[idx] == 0x00)) { + idx++; + len--; + } /* Keep encoding and writing while no error and bytes in data. */ while ((!err) && (idx < (word32)a->length)) { @@ -6300,6 +6350,19 @@ int wc_OBJ_sn2nid(const char *sn) WOLFSSL_ENTER("wolfSSL_OBJ_cmp"); if (a && b && a->obj && b->obj) { + /* An object made from a NID that has no OID encoding here, as for + * name attribute types, is only the tag and a zero length: + * compare NIDs. */ + if (a->objSz <= 2 || b->objSz <= 2) { + int nidA = wolfSSL_OBJ_obj2nid(a); + int nidB = wolfSSL_OBJ_obj2nid(b); + + if (nidA > 0 && nidB > 0) { + if (nidA == nidB) + return 0; + return (nidA < nidB) ? -1 : 1; + } + } if (a->objSz == b->objSz) { return XMEMCMP(a->obj, b->obj, a->objSz); } diff --git a/src/ssl_certman.c b/src/ssl_certman.c index 0946251320b..9a8bf9627ee 100644 --- a/src/ssl_certman.c +++ b/src/ssl_certman.c @@ -518,15 +518,6 @@ int wolfSSL_CertManagerUnloadTypeCerts( return ret; } -#if defined(OPENSSL_EXTRA) -static int wolfSSL_CertManagerUnloadTempIntermediateCerts( - WOLFSSL_CERT_MANAGER* cm) -{ - WOLFSSL_ENTER("wolfSSL_CertManagerUnloadTempIntermediateCerts"); - return wolfSSL_CertManagerUnloadTypeCerts(cm, WOLFSSL_TEMP_CA); -} -#endif - int wolfSSL_CertManagerUnloadIntermediateCerts( WOLFSSL_CERT_MANAGER* cm) { @@ -961,7 +952,7 @@ int CM_VerifyBuffer_ex(WOLFSSL_CERT_MANAGER* cm, const unsigned char* buff, if (cm->crlEnabled && ((ret == 0) || (ret == WC_NO_ERR_TRACE(ASN_BEFORE_DATE_E)) || (ret == WC_NO_ERR_TRACE(ASN_AFTER_DATE_E)))) { - crlRet = CheckCertCRLFromCm(cm, cm->crl, cert); + crlRet = CheckCertCRLFromCm(cm, cm->crl, cert, NULL, NULL); if (crlRet != 0) { WOLFSSL_MSG("CheckCertCRL failed"); } @@ -2145,7 +2136,7 @@ int wolfSSL_CertManagerCheckCRL(WOLFSSL_CERT_MANAGER* cm, /* A date error is returned only after the parse completed, * so still answer the revocation question that was asked. */ ret = cm_crl_merge(ret, - CheckCertCRLFromCm(cm, cm->crl, cert)); + CheckCertCRLFromCm(cm, cm->crl, cert, NULL, NULL)); } /* Dispose of dynamically allocated memory. */ @@ -3221,6 +3212,179 @@ int AddSigner(WOLFSSL_CERT_MANAGER* cm, Signer *s) return 0; } +#ifndef NO_RSA +/* Returns the size in bytes of the modulus of an RSA public key, 0 when it + * does not decode. */ +static word32 CAKeyRsaSize(const byte* pubKey, word32 pubKeySz) +{ + const byte* n = NULL; + word32 nSz = 0; + word32 idx = 0; + + if (wc_RsaPublicKeyDecode_ex(pubKey, &idx, pubKeySz, &n, &nSz, NULL, + NULL) != 0) { + return 0; + } + while (nSz > 0 && *n == 0) { + n++; + nSz--; + } + return nSz; +} +#endif /* !NO_RSA */ + +#ifdef HAVE_ECC +/* Returns the size in bytes of the curve of an ECC public key, 0 when it + * does not decode. */ +static word32 CAKeyEccSize(const byte* pubKey, word32 pubKeySz, void* heap) +{ + word32 sz = 0; + word32 idx = 0; + WC_DECLARE_VAR(key, ecc_key, 1, 0); + + WC_ALLOC_VAR_EX(key, ecc_key, 1, heap, DYNAMIC_TYPE_ECC, return 0); + if (wc_ecc_init_ex(key, heap, INVALID_DEVID) == 0) { + if (wc_EccPublicKeyDecode(pubKey, &idx, key, pubKeySz) == 0) { + sz = (word32)wc_ecc_size(key); + } + wc_ecc_free(key); + } + WC_FREE_VAR_EX(key, heap, DYNAMIC_TYPE_ECC); + return sz; +} +#endif /* HAVE_ECC */ + +/* Checks a CA's key against the cert manager's minimum key sizes, in bytes: + * of the modulus for RSA, of the curve for ECC. pubKey is the key as a + * DecodedCert stores it. + * Returns 0, or a key size error when the key is too small. */ +int CheckCAKeySize(WOLFSSL_CERT_MANAGER* cm, word32 keyOID, + const byte* pubKey, word32 pubKeySize) +{ + int ret = 0; + word32 keySz; + + (void)pubKey; + (void)pubKeySize; + (void)keySz; + + switch (keyOID) { + #ifndef NO_RSA + #ifdef WC_RSA_PSS + case RSAPSSk: + #endif + case RSAk: + keySz = CAKeyRsaSize(pubKey, pubKeySize); + if (cm->minRsaKeySz < 0 || keySz < (word32)cm->minRsaKeySz) { + ret = RSA_KEY_SIZE_E; + WOLFSSL_MSG_CERT_LOG("\tCA RSA key size error"); + WOLFSSL_MSG_CERT_EX("\tCA RSA key size = %d; " + "minRsaKeySz = %d", keySz, cm->minRsaKeySz); + } + break; + #endif /* !NO_RSA */ + #ifdef HAVE_ECC + case ECDSAk: + keySz = CAKeyEccSize(pubKey, pubKeySize, cm->heap); + if (cm->minEccKeySz < 0 || keySz < (word32)cm->minEccKeySz) { + ret = ECC_KEY_SIZE_E; + WOLFSSL_MSG_CERT_LOG("\tCA ECC key size error"); + WOLFSSL_MSG_CERT_EX("\tCA ECC key size = %d; " + "minEccKeySz = %d", keySz, cm->minEccKeySz); + } + break; + #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + case ED25519k: + if (cm->minEccKeySz < 0 || + ED25519_KEY_SIZE < (word16)cm->minEccKeySz) { + ret = ECC_KEY_SIZE_E; + WOLFSSL_MSG("\tCA ECC key size error"); + } + break; + #endif /* HAVE_ED25519 */ + #ifdef HAVE_ED448 + case ED448k: + if (cm->minEccKeySz < 0 || + ED448_KEY_SIZE < (word16)cm->minEccKeySz) { + ret = ECC_KEY_SIZE_E; + WOLFSSL_MSG("\tCA ECC key size error"); + } + break; + #endif /* HAVE_ED448 */ + #if defined(HAVE_FALCON) + case FALCON_LEVEL1k: + if (cm->minFalconKeySz < 0 || + FALCON_LEVEL1_KEY_SIZE < (word16)cm->minFalconKeySz) { + ret = FALCON_KEY_SIZE_E; + WOLFSSL_MSG("\tCA Falcon level 1 key size error"); + } + break; + case FALCON_LEVEL5k: + if (cm->minFalconKeySz < 0 || + FALCON_LEVEL5_KEY_SIZE < (word16)cm->minFalconKeySz) { + ret = FALCON_KEY_SIZE_E; + WOLFSSL_MSG("\tCA Falcon level 5 key size error"); + } + break; + #endif /* HAVE_FALCON */ + #if defined(WOLFSSL_HAVE_MLDSA) + #ifdef WOLFSSL_MLDSA_FIPS204_DRAFT + case DILITHIUM_LEVEL2k: + if (cm->minMlDsaKeySz < 0 || + WC_MLDSA_44_KEY_SIZE < (word16)cm->minMlDsaKeySz) { + ret = MLDSA_KEY_SIZE_E; + WOLFSSL_MSG("\tCA ML-DSA level 2 key size error"); + } + break; + case DILITHIUM_LEVEL3k: + if (cm->minMlDsaKeySz < 0 || + WC_MLDSA_65_KEY_SIZE < (word16)cm->minMlDsaKeySz) { + ret = MLDSA_KEY_SIZE_E; + WOLFSSL_MSG("\tCA ML-DSA level 3 key size error"); + } + break; + case DILITHIUM_LEVEL5k: + if (cm->minMlDsaKeySz < 0 || + WC_MLDSA_87_KEY_SIZE < (word16)cm->minMlDsaKeySz) { + ret = MLDSA_KEY_SIZE_E; + WOLFSSL_MSG("\tCA ML-DSA level 5 key size error"); + } + break; + #endif /* WOLFSSL_MLDSA_FIPS204_DRAFT */ + case ML_DSA_44k: + if (cm->minMlDsaKeySz < 0 || + WC_MLDSA_44_KEY_SIZE < (word16)cm->minMlDsaKeySz) { + ret = MLDSA_KEY_SIZE_E; + WOLFSSL_MSG("\tCA ML-DSA level 2 key size error"); + } + break; + case ML_DSA_65k: + if (cm->minMlDsaKeySz < 0 || + WC_MLDSA_65_KEY_SIZE < (word16)cm->minMlDsaKeySz) { + ret = MLDSA_KEY_SIZE_E; + WOLFSSL_MSG("\tCA ML-DSA level 3 key size error"); + } + break; + case ML_DSA_87k: + if (cm->minMlDsaKeySz < 0 || + WC_MLDSA_87_KEY_SIZE < (word16)cm->minMlDsaKeySz) { + ret = MLDSA_KEY_SIZE_E; + WOLFSSL_MSG("\tCA ML-DSA level 5 key size error"); + } + break; + #endif /* WOLFSSL_HAVE_MLDSA */ + + default: + WOLFSSL_MSG("\tNo key size check done on CA"); + break; /* no size check if key type is not in switch */ + } + + (void)cm; + (void)pubKeySize; + return ret; +} + /* owns der, internal now uses too */ /* type flag ids from user or from chain received during verify don't allow chain ones to be added w/o isCA extension */ @@ -3294,119 +3458,8 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify) /* check CA key size */ if (verify && (ret == 0 )) { - switch (cert->keyOID) { - #ifndef NO_RSA - #ifdef WC_RSA_PSS - case RSAPSSk: - #endif - case RSAk: - if (cm->minRsaKeySz < 0 || - cert->pubKeySize < (word16)cm->minRsaKeySz) { - ret = RSA_KEY_SIZE_E; - WOLFSSL_MSG_CERT_LOG("\tCA RSA key size error"); - WOLFSSL_MSG_CERT_EX("\tCA RSA pubKeySize = %d; " - "minRsaKeySz = %d", - cert->pubKeySize, cm->minRsaKeySz); - } - break; - #endif /* !NO_RSA */ - #ifdef HAVE_ECC - case ECDSAk: - if (cm->minEccKeySz < 0 || - cert->pubKeySize < (word16)cm->minEccKeySz) { - ret = ECC_KEY_SIZE_E; - WOLFSSL_MSG_CERT_LOG("\tCA ECC key size error"); - WOLFSSL_MSG_CERT_EX("\tCA ECC pubKeySize = %d; " - "minEccKeySz = %d", - cert->pubKeySize, cm->minEccKeySz); - } - break; - #endif /* HAVE_ECC */ - #ifdef HAVE_ED25519 - case ED25519k: - if (cm->minEccKeySz < 0 || - ED25519_KEY_SIZE < (word16)cm->minEccKeySz) { - ret = ECC_KEY_SIZE_E; - WOLFSSL_MSG("\tCA ECC key size error"); - } - break; - #endif /* HAVE_ED25519 */ - #ifdef HAVE_ED448 - case ED448k: - if (cm->minEccKeySz < 0 || - ED448_KEY_SIZE < (word16)cm->minEccKeySz) { - ret = ECC_KEY_SIZE_E; - WOLFSSL_MSG("\tCA ECC key size error"); - } - break; - #endif /* HAVE_ED448 */ - #if defined(HAVE_FALCON) - case FALCON_LEVEL1k: - if (cm->minFalconKeySz < 0 || - FALCON_LEVEL1_KEY_SIZE < (word16)cm->minFalconKeySz) { - ret = FALCON_KEY_SIZE_E; - WOLFSSL_MSG("\tCA Falcon level 1 key size error"); - } - break; - case FALCON_LEVEL5k: - if (cm->minFalconKeySz < 0 || - FALCON_LEVEL5_KEY_SIZE < (word16)cm->minFalconKeySz) { - ret = FALCON_KEY_SIZE_E; - WOLFSSL_MSG("\tCA Falcon level 5 key size error"); - } - break; - #endif /* HAVE_FALCON */ - #if defined(WOLFSSL_HAVE_MLDSA) - #ifdef WOLFSSL_MLDSA_FIPS204_DRAFT - case DILITHIUM_LEVEL2k: - if (cm->minMlDsaKeySz < 0 || - WC_MLDSA_44_KEY_SIZE < (word16)cm->minMlDsaKeySz) { - ret = MLDSA_KEY_SIZE_E; - WOLFSSL_MSG("\tCA ML-DSA level 2 key size error"); - } - break; - case DILITHIUM_LEVEL3k: - if (cm->minMlDsaKeySz < 0 || - WC_MLDSA_65_KEY_SIZE < (word16)cm->minMlDsaKeySz) { - ret = MLDSA_KEY_SIZE_E; - WOLFSSL_MSG("\tCA ML-DSA level 3 key size error"); - } - break; - case DILITHIUM_LEVEL5k: - if (cm->minMlDsaKeySz < 0 || - WC_MLDSA_87_KEY_SIZE < (word16)cm->minMlDsaKeySz) { - ret = MLDSA_KEY_SIZE_E; - WOLFSSL_MSG("\tCA ML-DSA level 5 key size error"); - } - break; - #endif /* WOLFSSL_MLDSA_FIPS204_DRAFT */ - case ML_DSA_44k: - if (cm->minMlDsaKeySz < 0 || - WC_MLDSA_44_KEY_SIZE < (word16)cm->minMlDsaKeySz) { - ret = MLDSA_KEY_SIZE_E; - WOLFSSL_MSG("\tCA ML-DSA level 2 key size error"); - } - break; - case ML_DSA_65k: - if (cm->minMlDsaKeySz < 0 || - WC_MLDSA_65_KEY_SIZE < (word16)cm->minMlDsaKeySz) { - ret = MLDSA_KEY_SIZE_E; - WOLFSSL_MSG("\tCA ML-DSA level 3 key size error"); - } - break; - case ML_DSA_87k: - if (cm->minMlDsaKeySz < 0 || - WC_MLDSA_87_KEY_SIZE < (word16)cm->minMlDsaKeySz) { - ret = MLDSA_KEY_SIZE_E; - WOLFSSL_MSG("\tCA ML-DSA level 5 key size error"); - } - break; - #endif /* WOLFSSL_HAVE_MLDSA */ - - default: - WOLFSSL_MSG("\tNo key size check done on CA"); - break; /* no size check if key type is not in switch */ - } + ret = CheckCAKeySize(cm, cert->keyOID, cert->publicKey, + cert->pubKeySize); } if (ret == 0 && cert->isCA == 0 && type != WOLFSSL_USER_CA && diff --git a/src/ssl_err.c b/src/ssl_err.c index 07ad469119b..bcce19e891e 100644 --- a/src/ssl_err.c +++ b/src/ssl_err.c @@ -193,6 +193,61 @@ void wolfSSL_ERR_print_errors_cb (int (*cb)(const char *str, size_t len, { /* handled internally */ } + + /* First library number given to the application, as in OpenSSL. */ + #define WOLFSSL_ERR_LIB_FIRST_DYNAMIC 128 + + /* Get a new error library number for the application. + * + * @return Library number. + */ + int wolfSSL_ERR_get_next_error_library(void) + { + #if !defined(SINGLE_THREADED) && defined(WOLFSSL_ATOMIC_OPS) && \ + defined(WOLFSSL_ATOMIC_INITIALIZER) + static wolfSSL_Atomic_Int errLibNext = + WOLFSSL_ATOMIC_INITIALIZER(WOLFSSL_ERR_LIB_FIRST_DYNAMIC); + + WOLFSSL_ENTER("wolfSSL_ERR_get_next_error_library"); + return (int)wolfSSL_Atomic_Int_FetchAdd(&errLibNext, 1); + #else + static int errLibNext = WOLFSSL_ERR_LIB_FIRST_DYNAMIC; + + WOLFSSL_ENTER("wolfSSL_ERR_get_next_error_library"); + return errLibNext++; + #endif + } + + /* Register error strings of a library. + * + * wolfSSL has no string tables for application libraries: errors of these + * libraries are not put in the error queue. For OpenSSL compatibility. + * + * @param [in] lib Library number. + * @param [in] str Strings. Not used. + * @return 1 on success. + */ + int wolfSSL_ERR_load_strings(int lib, WOLFSSL_ERR_STRING_DATA* str) + { + WOLFSSL_ENTER("wolfSSL_ERR_load_strings"); + (void)lib; + (void)str; + return 1; + } + + /* Remove error strings of a library. For OpenSSL compatibility. + * + * @param [in] lib Library number. + * @param [in] str Strings. Not used. + * @return 1 on success. + */ + int wolfSSL_ERR_unload_strings(int lib, WOLFSSL_ERR_STRING_DATA* str) + { + WOLFSSL_ENTER("wolfSSL_ERR_unload_strings"); + (void)lib; + (void)str; + return 1; + } #endif #if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE) || \ @@ -296,7 +351,9 @@ void wolfSSL_ERR_print_errors_cb (int (*cb)(const char *str, size_t len, /* Add an error to the error queue. * - * @param [in] lib Library the error occurred in. Not used. + * @param [in] lib Library the error occurred in. Errors of application + * libraries, see wolfSSL_ERR_get_next_error_library(), + * are not queued. * @param [in] fun System function the error occurred in. WOLFSSL_SYS_*. * @param [in] err Error value. * @param [in] file Name of file the error occurred in. @@ -307,6 +364,12 @@ void wolfSSL_ERR_print_errors_cb (int (*cb)(const char *str, size_t len, { WOLFSSL_ENTER("wolfSSL_ERR_put_error"); + #ifdef OPENSSL_EXTRA + if (lib >= WOLFSSL_ERR_LIB_FIRST_DYNAMIC) { + /* Reason of an application library: no string to show. */ + return; + } + #endif #if !defined(DEBUG_WOLFSSL) && !defined(OPENSSL_EXTRA) (void)fun; (void)err; diff --git a/src/ssl_p7p12.c b/src/ssl_p7p12.c index d2bc45fd99d..9642c481051 100644 --- a/src/ssl_p7p12.c +++ b/src/ssl_p7p12.c @@ -1921,6 +1921,73 @@ WC_PKCS12* wolfSSL_PKCS12_create(char* pass, char* name, WOLFSSL_EVP_PKEY* pkey, } +/* Get a BMPString as ASCII, the low byte of each character. + * + * @param [in] in BMPString, UCS-2 big endian. + * @param [in] inSz Length of in in bytes. + * @param [out] out Buffer for ASCII. NULL to get the length. + * @return Length of ASCII string on success. + * @return -1 when in has an odd length or a character that is not ASCII. + */ +static int wolfssl_bmp_to_ascii(const byte* in, word32 inSz, byte* out) +{ + word32 i; + + if ((inSz % 2) != 0) { + return WOLFSSL_FATAL_ERROR; + } + for (i = 0; i < inSz; i += 2) { + if ((in[i] != 0) || (in[i + 1] >= 0x80)) { + return WOLFSSL_FATAL_ERROR; + } + if (out != NULL) { + out[i / 2] = in[i + 1]; + } + } + + return (int)(inSz / 2); +} + +/* Keep the friendlyName and the localKeyId of the PKCS#12 bag of the cert, as + * OpenSSL does with X509_alias_set1 and X509_keyid_set1. + * A friendlyName that is not ASCII is left out. */ +static int wolfssl_x509_set_pkcs12_attrs(WOLFSSL_X509* x509, + const byte* name, word32 nameSz, const byte* keyId, word32 keyIdSz) +{ + int ret = 1; + int len; + + if (name != NULL) { + len = wolfssl_bmp_to_ascii(name, nameSz, NULL); + if (len >= 0) { + x509->alias = (byte*)XMALLOC((size_t)len + 1, x509->heap, + DYNAMIC_TYPE_X509_EXT); + if (x509->alias == NULL) { + ret = 0; + } + else { + (void)wolfssl_bmp_to_ascii(name, nameSz, x509->alias); + x509->alias[len] = '\0'; + x509->aliasSz = len; + } + } + } + if ((ret == 1) && (keyId != NULL)) { + x509->keyid = (byte*)XMALLOC((size_t)keyIdSz + 1, x509->heap, + DYNAMIC_TYPE_X509_EXT); + if (x509->keyid == NULL) { + ret = 0; + } + else { + XMEMCPY(x509->keyid, keyId, keyIdSz); + x509->keyid[keyIdSz] = '\0'; + x509->keyidSz = (int)keyIdSz; + } + } + + return ret; +} + /* return WOLFSSL_SUCCESS on success, WOLFSSL_FAILURE on failure */ int wolfSSL_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, WOLFSSL_EVP_PKEY** pkey, WOLFSSL_X509** cert, @@ -1932,6 +1999,10 @@ int wolfSSL_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, word32 certDataSz; byte* pk = NULL; word32 pkSz; + byte* name = NULL; + word32 nameSz = 0; + byte* keyId = NULL; + word32 keyIdSz = 0; WC_DerCertList* certList = NULL; WC_DECLARE_VAR(DeCert, DecodedCert, 1, 0); @@ -1949,14 +2020,8 @@ int wolfSSL_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, heap = wc_PKCS12_GetHeap(pkcs12); - if (ca == NULL) { - ret = wc_PKCS12_parse(pkcs12, psw, &pk, &pkSz, &certData, &certDataSz, - NULL); - } - else { - ret = wc_PKCS12_parse(pkcs12, psw, &pk, &pkSz, &certData, &certDataSz, - &certList); - } + ret = wc_PKCS12_parse_ex2(pkcs12, psw, &pk, &pkSz, &certData, &certDataSz, + (ca == NULL) ? NULL : &certList, 0, &name, &nameSz, &keyId, &keyIdSz); if (ret < 0) { WOLFSSL_LEAVE("wolfSSL_PKCS12_parse", ret); return WOLFSSL_FAILURE; @@ -1967,6 +2032,8 @@ int wolfSSL_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, DYNAMIC_TYPE_DCERT); if (DeCert == NULL) { WOLFSSL_MSG("out of memory"); + XFREE(name, heap, DYNAMIC_TYPE_PKCS); + XFREE(keyId, heap, DYNAMIC_TYPE_PKCS); return WOLFSSL_FAILURE; } #endif @@ -2090,6 +2157,16 @@ int wolfSSL_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, } FreeDecodedCert(DeCert); XFREE(certData, heap, DYNAMIC_TYPE_PKCS); + if (wolfssl_x509_set_pkcs12_attrs(*cert, name, nameSz, keyId, + keyIdSz) != 1) { + XFREE(pk, heap, DYNAMIC_TYPE_PUBLIC_KEY); + if (ca != NULL) { + wolfSSL_sk_X509_pop_free(*ca, NULL); *ca = NULL; + } + wolfSSL_X509_free(*cert); *cert = NULL; + ret = WOLFSSL_FAILURE; + goto out; + } } @@ -2150,6 +2227,8 @@ int wolfSSL_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, out: + XFREE(name, heap, DYNAMIC_TYPE_PKCS); + XFREE(keyId, heap, DYNAMIC_TYPE_PKCS); WC_FREE_VAR_EX(DeCert, heap, DYNAMIC_TYPE_DCERT); return ret; diff --git a/src/ssl_sk.c b/src/ssl_sk.c index 15370830e61..630a6fa4570 100644 --- a/src/ssl_sk.c +++ b/src/ssl_sk.c @@ -756,6 +756,7 @@ int wolfSSL_sk_insert(WOLFSSL_STACK *stack, const void *data, int idx) node->type = stack->type; #ifdef OPENSSL_ALL node->hash_fn = stack->hash_fn; + node->comp = stack->comp; #endif /* Put data into new node. */ wolfssl_sk_node_set_data(node, stack->type, data); @@ -815,6 +816,113 @@ void* wolfSSL_sk_delete(WOLFSSL_STACK* stack, int idx) return wolfSSL_sk_pop_node(stack, idx); } +/* Remove the first node that holds the data pointer and return the data. + * + * @param [in, out] stack Stack of nodes with data. + * @param [in] data Data to find. + * @return data when found and removed. + * @return NULL when stack or data is NULL or data is not in the stack. + */ +void* wolfSSL_sk_delete_ptr(WOLFSSL_STACK* stack, const void* data) +{ + WOLFSSL_STACK* node; + int idx = 0; + + WOLFSSL_ENTER("wolfSSL_sk_delete_ptr"); + + /* Cipher stacks hold copies, not pointers. */ + if ((stack == NULL) || (data == NULL) || + (stack->type == STACK_TYPE_CIPHER)) { + return NULL; + } + + for (node = stack; (node != NULL) && ((unsigned long)idx < stack->num); + node = node->next) { + if (node->data.generic == data) { + return wolfSSL_sk_pop_node(stack, idx); + } + idx++; + } + + return NULL; +} + +#ifdef OPENSSL_ALL +/* Set the comparator used by sort. + * + * Set on every node as a removed first node is replaced by the next one. + * + * @param [in, out] stack Stack of data. + * @param [in] cb Comparator. May be NULL. + * @return Previous comparator. + * @return NULL when stack is NULL or no comparator was set. + */ +wolf_sk_compare_cb wolfSSL_sk_set_cmp_func(WOLFSSL_STACK* stack, + wolf_sk_compare_cb cb) +{ + wolf_sk_compare_cb old = NULL; + + WOLFSSL_ENTER("wolfSSL_sk_set_cmp_func"); + + if (stack != NULL) { + old = stack->comp; + } + for (; stack != NULL; stack = stack->next) { + stack->comp = cb; + } + + return old; +} + +/* Sort the data in the stack with the stack's comparator. + * + * Stable insertion sort: the first node starts as the sorted part and each + * following node's data is moved into place. Nodes stay, data moves. + * Cipher stacks hold their data in the node and are not sorted. + * + * @param [in, out] stack Stack of data. + */ +void wolfSSL_sk_sort(WOLFSSL_STACK* stack) +{ + WOLFSSL_STACK* cur; + WOLFSSL_STACK* pos; + void* data; + void* next; + unsigned long hash; + unsigned long nextHash; + + WOLFSSL_ENTER("wolfSSL_sk_sort"); + + if ((stack == NULL) || (stack->comp == NULL) || + (stack->type == STACK_TYPE_CIPHER)) { + return; + } + + for (cur = stack->next; cur != NULL; cur = cur->next) { + /* Find the first entry greater than cur. */ + for (pos = stack; pos != cur; pos = pos->next) { + if (stack->comp((const void* const*)&cur->data.generic, + (const void* const*)&pos->data.generic) < 0) { + break; + } + } + /* Move cur's data and hash there and shift the rest up. */ + data = cur->data.generic; + hash = cur->hash; + for (; pos != cur; pos = pos->next) { + next = pos->data.generic; + nextHash = pos->hash; + pos->data.generic = data; + pos->hash = hash; + data = next; + hash = nextHash; + } + cur->data.generic = data; + cur->hash = hash; + } +} +#endif /* OPENSSL_ALL */ + /* Pop off data from the stack. Checks that the type matches the stack type. * * This is an internal API. diff --git a/src/x509.c b/src/x509.c index 39ea4847773..b780a3c3b62 100644 --- a/src/x509.c +++ b/src/x509.c @@ -2218,8 +2218,10 @@ void* wolfSSL_X509V3_EXT_d2i(WOLFSSL_X509_EXTENSION* ext) WOLFSSL_MSG("Failed to malloc ASN1_STRING"); break; } - ret = wolfSSL_ASN1_STRING_set(newString, cert->extSubjKeyId, - cert->extSubjKeyIdSz); + /* The identifier itself. extSubjKeyId holds a hash of it when + * it is not KEYID_SIZE bytes long. */ + ret = wolfSSL_ASN1_STRING_set(newString, cert->extSubjKeyIdSrc, + (int)cert->extSubjKeyIdSz); if (ret != WOLFSSL_SUCCESS) { WOLFSSL_MSG("ASN1_STRING_set() failed"); wolfSSL_ASN1_STRING_free(newString); @@ -4314,6 +4316,11 @@ char* wolfSSL_X509_NAME_oneline(WOLFSSL_X509_NAME* name, char* in, int sz) WOLFSSL_ENTER("wolfSSL_X509_NAME_oneline"); + /* An empty name gives an empty string, as OpenSSL. */ + if (in != NULL && sz > 0) { + in[0] = '\0'; + } + if (name == NULL) { WOLFSSL_MSG("WOLFSSL_X509_NAME pointer was NULL"); return NULL; @@ -4365,20 +4372,22 @@ static unsigned long X509NameHash(WOLFSSL_X509_NAME* name, return 0; } - if (name->sz == 0) { - WOLFSSL_ERROR_MSG("Nothing to hash in WOLFSSL_X509_NAME"); - return 0; + if (name->sz == 0 || wolfSSL_X509_NAME_entry_count(name) == 0) { + /* Empty name: hash of an empty encoding, as OpenSSL. */ + size = 0; } + else { + size = wolfSSL_i2d_X509_NAME_canon(name, &canonName); - size = wolfSSL_i2d_X509_NAME_canon(name, &canonName); - - if (size <= 0 || canonName == NULL) { - WOLFSSL_ERROR_MSG("wolfSSL_i2d_X509_NAME_canon error"); - return 0; + if (size <= 0 || canonName == NULL) { + WOLFSSL_ERROR_MSG("wolfSSL_i2d_X509_NAME_canon error"); + return 0; + } } - rc = wc_Hash(hashType, (const byte*)canonName, (word32)size, digest, - sizeof(digest)); + rc = wc_Hash(hashType, + (canonName != NULL) ? (const byte*)canonName : (const byte*)"", + (word32)size, digest, sizeof(digest)); if (rc == 0) { hash = (((unsigned long)digest[3] << 24) | @@ -5249,9 +5258,11 @@ void wolfSSL_sk_X509_CRL_pop_free(WOLF_STACK_OF(WOLFSSL_X509_CRL)* sk, wolfSSL_sk_pop_free(sk, (wolfSSL_sk_freefunc)f); } +/* Free the stack only, not the CRLs, as OpenSSL does. */ void wolfSSL_sk_X509_CRL_free(WOLF_STACK_OF(WOLFSSL_X509_CRL)* sk) { - wolfSSL_sk_X509_CRL_pop_free(sk, NULL); + WOLFSSL_ENTER("wolfSSL_sk_X509_CRL_free"); + wolfSSL_sk_free(sk); } /* return number of elements on success 0 on fail */ @@ -7382,6 +7393,36 @@ int wolfSSL_X509_cmp(const WOLFSSL_X509 *a, const WOLFSSL_X509 *b) return ret; } + + /* Get the alias of the cert: the friendlyName of its PKCS#12 bag. + * Returns the UTF-8 alias or NULL when the cert has none. */ + unsigned char* wolfSSL_X509_alias_get0(WOLFSSL_X509* x509, int* len) + { + WOLFSSL_ENTER("wolfSSL_X509_alias_get0"); + + if ((x509 == NULL) || (x509->alias == NULL)) { + return NULL; + } + if (len != NULL) { + *len = x509->aliasSz; + } + return x509->alias; + } + + /* Get the key id of the cert: the localKeyId of its PKCS#12 bag. + * Returns the key id or NULL when the cert has none. */ + unsigned char* wolfSSL_X509_keyid_get0(WOLFSSL_X509* x509, int* len) + { + WOLFSSL_ENTER("wolfSSL_X509_keyid_get0"); + + if ((x509 == NULL) || (x509->keyid == NULL)) { + return NULL; + } + if (len != NULL) { + *len = x509->keyidSz; + } + return x509->keyid; + } #endif /* OPENSSL_EXTRA */ #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) || \ @@ -9474,6 +9515,18 @@ int wolfSSL_X509_LOOKUP_ctrl(WOLFSSL_X509_LOOKUP *ctx, int cmd, case WOLFSSL_X509_L_ADD_DIR: /* store directory location to use it later */ #if !defined(NO_WOLFSSL_DIR) + if (argc == NULL && argl == WOLFSSL_FILETYPE_DEFAULT) { + /* Default dir: $SSL_CERT_DIR, as OpenSSL. There is no + * built-in one, so add nothing without it. */ + #ifdef XGETENV + argc = XGETENV("SSL_CERT_DIR"); + #endif + argl = WOLFSSL_FILETYPE_PEM; + if (argc == NULL || *argc == '\0') { + lret = WOLFSSL_SUCCESS; + break; + } + } lret = x509AddCertDir(ctx->dirs, argc, argl); #else (void)x509AddCertDir; @@ -9552,27 +9605,75 @@ static int loadX509orX509REQFromBio(WOLFSSL_BIO* bio, WOLFSSL_X509* x509, return ret; } +#endif /* !NO_BIO */ +#endif /* WOLFSSL_CERT_GEN */ -/* Converts the X509 to DER format and outputs it into bio. +#ifndef NO_BIO +/* Writes the DER encoding of the X509 or X509_REQ to bio. + * + * The stored encoding is written. Encoding the fields again can reorder or + * drop extensions and attributes, which breaks the signature. As in OpenSSL + * 3.0, the setters of a certificate leave that encoding until it is signed + * again, while those of a request encode the request again. * * bio is the structure to hold output DER - * x509 certificate to create DER from + * x509 certificate or request to write + * req if set then x509 is a request + * + * returns WOLFSSL_SUCCESS on success + */ +static int writeX509orX509REQDer(WOLFSSL_BIO* bio, WOLFSSL_X509* x509, + int req) +{ + const unsigned char* der; + int derSz = 0; + + if (bio == NULL || x509 == NULL) { + return WOLFSSL_FAILURE; + } + + der = wolfSSL_X509_get_der(x509, &derSz); + if (der == NULL || derSz <= 0) { + #ifdef WOLFSSL_CERT_GEN + /* No stored encoding: make one from the fields. */ + return loadX509orX509REQFromBio(bio, x509, req); + #else + (void)req; + return WOLFSSL_FAILURE; + #endif + } + + if (wolfSSL_BIO_write(bio, der, derSz) != derSz) { + return WOLFSSL_FAILURE; + } + + return WOLFSSL_SUCCESS; +} + +/* Writes the DER encoding of the X509 to bio, as i2d_X509() does. * * returns WOLFSSL_SUCCESS on success */ int wolfSSL_i2d_X509_bio(WOLFSSL_BIO* bio, WOLFSSL_X509* x509) { - return loadX509orX509REQFromBio(bio, x509, 0); + WOLFSSL_ENTER("wolfSSL_i2d_X509_bio"); + + return writeX509orX509REQDer(bio, x509, 0); } #ifdef WOLFSSL_CERT_REQ +/* Writes the DER encoding of the X509_REQ to bio. + * + * returns WOLFSSL_SUCCESS on success + */ int wolfSSL_i2d_X509_REQ_bio(WOLFSSL_BIO* bio, WOLFSSL_X509* x509) { - return loadX509orX509REQFromBio(bio, x509, 1); + WOLFSSL_ENTER("wolfSSL_i2d_X509_REQ_bio"); + + return writeX509orX509REQDer(bio, x509, 1); } #endif /* WOLFSSL_CERT_REQ */ #endif /* !NO_BIO */ -#endif /* WOLFSSL_CERT_GEN */ /* Converts an internal structure to a DER buffer * @@ -9757,10 +9858,21 @@ static WOLFSSL_X509* d2i_X509orX509REQ_bio(WOLFSSL_BIO* bio, if (localX509 == NULL) { WOLFSSL_MSG("wolfSSL_X509_d2i error"); XFREE(mem, NULL, DYNAMIC_TYPE_OPENSSL); + /* What was read does not decode: as OpenSSL, free the object passed + * in. */ + if (x509 != NULL) { + wolfSSL_X509_free(*x509); + *x509 = NULL; + } return NULL; } if (x509 != NULL) { + /* Free the object passed in and put the new one there. OpenSSL + * decodes into it instead. */ + if (*x509 != NULL && *x509 != localX509) { + wolfSSL_X509_free(*x509); + } *x509 = localX509; } @@ -9784,34 +9896,62 @@ WOLFSSL_X509* wolfSSL_d2i_X509_REQ_bio(WOLFSSL_BIO* bio, WOLFSSL_X509** x509) #endif /* OPENSSL_EXTRA */ #ifdef OPENSSL_EXTRA -/* Use the public key to verify the signature. Note: this only verifies - * the certificate signature. - * returns WOLFSSL_SUCCESS on successful signature verification */ -static int verifyX509orX509REQ(WOLFSSL_X509* x509, WOLFSSL_EVP_PKEY* pkey, - int req) +/* Public key to verify a signature with. */ +typedef struct X509VerifyKey { + const byte* pubKey; + int pubKeySz; + int type; + byte* pubDer; /* public key of a private key, freed by caller */ +#if defined(HAVE_ED25519) && defined(HAVE_ED25519_KEY_EXPORT) + byte edPubKey[ED25519_PUB_KEY_SIZE]; +#endif +#if defined(HAVE_ED448) && defined(HAVE_ED448_KEY_EXPORT) + byte ed448PubKey[ED448_PUB_KEY_SIZE]; +#endif +} X509VerifyKey; + +/* Returns 1 when pkey is an RSA, EC or DSA key with its private part, whose + * cached DER is then the private key, otherwise 0. */ +static int X509PkeyIsPrivate(WOLFSSL_EVP_PKEY* pkey) +{ +#ifndef NO_RSA + if (pkey->type == WC_EVP_PKEY_RSA) { + return pkey->rsa != NULL && pkey->rsa->internal != NULL && + ((RsaKey*)pkey->rsa->internal)->type == RSA_PRIVATE; + } +#endif +#ifdef HAVE_ECC + if (pkey->type == WC_EVP_PKEY_EC) { + return pkey->ecc != NULL && pkey->ecc->internal != NULL && + (((ecc_key*)pkey->ecc->internal)->type == ECC_PRIVATEKEY || + ((ecc_key*)pkey->ecc->internal)->type == ECC_PRIVATEKEY_ONLY); + } +#endif +#ifndef NO_DSA + if (pkey->type == WC_EVP_PKEY_DSA) { + return pkey->dsa != NULL && pkey->dsa->internal != NULL && + ((DsaKey*)pkey->dsa->internal)->type == DSA_PRIVATE; + } +#endif + (void)pkey; + return 0; +} + +/* Get the public key and key type of pkey to verify a signature with. + * returns 0 on success */ +static int X509GetVerifyKey(WOLFSSL_EVP_PKEY* pkey, X509VerifyKey* key) { - int ret; - const byte* der; - int derSz = 0; int type; const byte* pubKey; int pubKeySz; #if defined(HAVE_ED25519) && defined(HAVE_ED25519_KEY_EXPORT) - byte edPubKey[ED25519_PUB_KEY_SIZE]; - word32 edPubKeySz = (word32)sizeof(edPubKey); + word32 edPubKeySz = (word32)sizeof(key->edPubKey); +#endif +#if defined(HAVE_ED448) && defined(HAVE_ED448_KEY_EXPORT) + word32 ed448PubKeySz = (word32)sizeof(key->ed448PubKey); #endif - (void)req; - - if (x509 == NULL || pkey == NULL) { - return WOLFSSL_FATAL_ERROR; - } - - der = wolfSSL_X509_get_der(x509, &derSz); - if (der == NULL) { - WOLFSSL_MSG("Error getting WOLFSSL_X509 DER"); - return WOLFSSL_FATAL_ERROR; - } + key->pubDer = NULL; /* Most key types verify against the cached public-key DER. */ pubKey = (const byte*)pkey->pkey.ptr; @@ -9845,30 +9985,102 @@ static int verifyX509orX509REQ(WOLFSSL_X509* x509, WOLFSSL_EVP_PKEY* pkey, * pkey->pkey.ptr holds a PKCS#8 private blob (or nothing), so * export the public key from the ed25519_key instead. */ if (pkey->ed25519 == NULL || - wc_ed25519_export_public(pkey->ed25519, edPubKey, + wc_ed25519_export_public(pkey->ed25519, key->edPubKey, &edPubKeySz) != 0) { WOLFSSL_MSG("Unable to export Ed25519 public key"); return WOLFSSL_FATAL_ERROR; } - pubKey = edPubKey; + pubKey = key->edPubKey; pubKeySz = (int)edPubKeySz; type = ED25519k; break; #endif + #if defined(HAVE_ED448) && defined(HAVE_ED448_KEY_EXPORT) + case WC_EVP_PKEY_ED448: + /* As Ed25519: the raw public key of the ed448_key, made from + * the private key when it was decoded without one */ + if (pkey->ed448 == NULL || + (wc_ed448_export_public(pkey->ed448, key->ed448PubKey, + &ed448PubKeySz) != 0 && + wc_ed448_make_public(pkey->ed448, key->ed448PubKey, + (word32)sizeof(key->ed448PubKey)) != 0)) { + WOLFSSL_MSG("Unable to export Ed448 public key"); + return WOLFSSL_FATAL_ERROR; + } + pubKey = key->ed448PubKey; + pubKeySz = (int)sizeof(key->ed448PubKey); + type = ED448k; + break; + #endif default: WOLFSSL_MSG("Unknown pkey key type"); return WOLFSSL_FATAL_ERROR; } + /* As OpenSSL, a private key verifies with its public part. When that + * cannot be encoded, as for DSA, the signature cannot be checked. */ + if (X509PkeyIsPrivate(pkey)) { + byte* der; + + pubKeySz = wolfSSL_i2d_PUBKEY(pkey, NULL); + if (pubKeySz <= 0) { + WOLFSSL_MSG("Unable to get the public key of a private key"); + return WOLFSSL_FATAL_ERROR; + } + key->pubDer = (byte*)XMALLOC((size_t)pubKeySz, pkey->heap, + DYNAMIC_TYPE_PUBLIC_KEY); + der = key->pubDer; + if (der == NULL || wolfSSL_i2d_PUBKEY(pkey, &der) != pubKeySz) { + XFREE(key->pubDer, pkey->heap, DYNAMIC_TYPE_PUBLIC_KEY); + key->pubDer = NULL; + return WOLFSSL_FATAL_ERROR; + } + pubKey = key->pubDer; + } + + key->pubKey = pubKey; + key->pubKeySz = pubKeySz; + key->type = type; + return 0; +} + +/* Use the public key to verify the signature. Note: this only verifies + * the certificate signature. + * returns WOLFSSL_SUCCESS on successful signature verification */ +static int verifyX509orX509REQ(WOLFSSL_X509* x509, WOLFSSL_EVP_PKEY* pkey, + int req) +{ + int ret; + const byte* der; + int derSz = 0; + X509VerifyKey key; + + (void)req; + + if (x509 == NULL || pkey == NULL) { + return WOLFSSL_FATAL_ERROR; + } + + der = wolfSSL_X509_get_der(x509, &derSz); + if (der == NULL) { + WOLFSSL_MSG("Error getting WOLFSSL_X509 DER"); + return WOLFSSL_FATAL_ERROR; + } + + if (X509GetVerifyKey(pkey, &key) != 0) { + return WOLFSSL_FATAL_ERROR; + } + #ifdef WOLFSSL_CERT_REQ if (req) ret = CheckCSRSignaturePubKey(der, (word32)derSz, x509->heap, - (unsigned char*)pubKey, pubKeySz, type); + (unsigned char*)key.pubKey, key.pubKeySz, key.type); else #endif ret = CheckCertSignaturePubKey(der, (word32)derSz, x509->heap, - (unsigned char*)pubKey, pubKeySz, type); + (unsigned char*)key.pubKey, key.pubKeySz, key.type); + XFREE(key.pubDer, pkey->heap, DYNAMIC_TYPE_PUBLIC_KEY); if (ret == 0) { return WOLFSSL_SUCCESS; } @@ -10147,13 +10359,22 @@ WOLFSSL_X509_CRL *wolfSSL_d2i_X509_CRL_bio(WOLFSSL_BIO *bp, der = (byte*)XMALLOC(derSz, 0, DYNAMIC_TYPE_DER); if (der != NULL) { if (wolfSSL_BIO_read(bp, der, derSz) == derSz) { - crl = wolfSSL_d2i_X509_CRL(x, der, derSz); + crl = wolfSSL_d2i_X509_CRL(NULL, der, derSz); } } } XFREE(der, 0, DYNAMIC_TYPE_DER); + /* Free the object passed in and put the new one there. OpenSSL decodes + * into it instead. */ + if (crl != NULL && x != NULL) { + if (*x != NULL && *x != crl) { + wolfSSL_X509_CRL_free(*x); + } + *x = crl; + } + return crl; } #endif @@ -11122,15 +11343,73 @@ int wolfSSL_X509_CRL_set_nextUpdate(WOLFSSL_X509_CRL* crl, return WOLFSSL_FAILURE; } -#ifndef NO_WOLFSSL_STUB -int wolfSSL_X509_CRL_verify(WOLFSSL_X509_CRL* crl, WOLFSSL_EVP_PKEY* key) +/* Verify the signature of a CRL with pkey. + * Uses the TBS and signature kept for a CRL that was not verified when it was + * loaded, as with d2i and PEM. A CRL verified on load does not keep them. + * returns 1 when the signature verifies, 0 when it does not and -1 when it + * cannot be checked, as for a key of the wrong type */ +int wolfSSL_X509_CRL_verify(WOLFSSL_X509_CRL* crl, WOLFSSL_EVP_PKEY* pkey) { - (void)crl; - (void)key; - WOLFSSL_STUB("X509_CRL_verify"); - return 0; + int ret; + CRL_Entry* ent; + X509VerifyKey key; + const byte* sigParams = NULL; + word32 sigParamsSz = 0; + WC_DECLARE_VAR(sigCtx, SignatureCtx, 1, 0); + + WOLFSSL_ENTER("wolfSSL_X509_CRL_verify"); + + if (crl == NULL || pkey == NULL || X509GetVerifyKey(pkey, &key) != 0) { + return WOLFSSL_FATAL_ERROR; + } + + WC_ALLOC_VAR_EX(sigCtx, SignatureCtx, 1, crl->heap, DYNAMIC_TYPE_SIGNATURE, + { XFREE(key.pubDer, pkey->heap, DYNAMIC_TYPE_PUBLIC_KEY); + return WOLFSSL_FATAL_ERROR; }); + + if (wc_LockRwLock_Rd(&crl->crlLock) != 0) { + WC_FREE_VAR_EX(sigCtx, crl->heap, DYNAMIC_TYPE_SIGNATURE); + XFREE(key.pubDer, pkey->heap, DYNAMIC_TYPE_PUBLIC_KEY); + return WOLFSSL_FATAL_ERROR; + } + ent = crl->crlList; + if (ent == NULL || ent->toBeSigned == NULL || ent->signature == NULL) { + WOLFSSL_MSG("No TBS and signature kept for the CRL"); + ret = WOLFSSL_FATAL_ERROR; + } + else { + #ifdef WC_RSA_PSS + sigParams = ent->sigParams; + sigParamsSz = ent->sigParamsSz; + #endif + InitSignatureCtx(sigCtx, crl->heap, INVALID_DEVID); + ret = ConfirmSignature(sigCtx, ent->toBeSigned, ent->tbsSz, + key.pubKey, (word32)key.pubKeySz, (word32)key.type, + ent->signature, ent->signatureSz, ent->signatureOID, + sigParams, sigParamsSz, NULL); + FreeSignatureCtx(sigCtx); + if (ret == 0) { + ret = WOLFSSL_SUCCESS; + } + else if (ret == WC_NO_ERR_TRACE(ASN_SIG_OID_E) || + ret == WC_NO_ERR_TRACE(ASN_UNKNOWN_OID_E) || + ret == WC_NO_ERR_TRACE(HASH_TYPE_E) || + ret == WC_NO_ERR_TRACE(NOT_COMPILED_IN) || + ret == WC_NO_ERR_TRACE(MEMORY_E)) { + WOLFSSL_MSG("CRL signature cannot be checked with this key"); + ret = WOLFSSL_FATAL_ERROR; + } + else { + WOLFSSL_MSG("CRL signature did not verify"); + ret = WOLFSSL_FAILURE; + } + } + wc_UnLockRwLock(&crl->crlLock); + + WC_FREE_VAR_EX(sigCtx, crl->heap, DYNAMIC_TYPE_SIGNATURE); + XFREE(key.pubDer, pkey->heap, DYNAMIC_TYPE_PUBLIC_KEY); + return ret; } -#endif /* Encode CRL to DER format in memory. * @@ -11380,8 +11659,10 @@ WOLFSSL_X509_VERIFY_PARAM* wolfSSL_X509_VERIFY_PARAM_new(void) WOLFSSL_X509_VERIFY_PARAM *param = NULL; param = (WOLFSSL_X509_VERIFY_PARAM*)XMALLOC( sizeof(WOLFSSL_X509_VERIFY_PARAM), NULL, DYNAMIC_TYPE_OPENSSL); - if (param != NULL) + if (param != NULL) { XMEMSET(param, 0, sizeof(WOLFSSL_X509_VERIFY_PARAM )); + param->depth = -1; + } return(param); } @@ -11419,6 +11700,18 @@ void wolfSSL_X509_VERIFY_PARAM_set_time(WOLFSSL_X509_VERIFY_PARAM *param, } +/* Sets the maximum number of intermediate CAs that X509_verify_cert() allows. + * -1 means unset. TLS verification does not use it. */ +void wolfSSL_X509_VERIFY_PARAM_set_depth(WOLFSSL_X509_VERIFY_PARAM *param, + int depth) +{ + WOLFSSL_ENTER("wolfSSL_X509_VERIFY_PARAM_set_depth"); + if (param != NULL) { + param->depth = depth; + } +} + + int wolfSSL_X509_VERIFY_PARAM_get_flags(WOLFSSL_X509_VERIFY_PARAM *param) { int ret = 0; @@ -11444,7 +11737,7 @@ int wolfSSL_X509_VERIFY_PARAM_clear_flags(WOLFSSL_X509_VERIFY_PARAM *param, return ret; } -/* note WOLFSSL_X509_VERIFY_PARAM does not record purpose, trust, depth, or +/* note WOLFSSL_X509_VERIFY_PARAM does not record purpose, trust, or * auth_level. */ static const WOLFSSL_X509_VERIFY_PARAM x509_verify_param_builtins[] = { @@ -11455,7 +11748,8 @@ static const WOLFSSL_X509_VERIFY_PARAM x509_verify_param_builtins[] = { 0, /* flags */ "", /* hostname */ 0, /* hostFlags */ - "" /* ipasc */ + "", /* ipasc */ + -1 /* depth */ }, { "ssl_server", /* name */ @@ -11464,7 +11758,8 @@ static const WOLFSSL_X509_VERIFY_PARAM x509_verify_param_builtins[] = { 0, /* flags */ "", /* hostname */ 0, /* hostFlags */ - "" /* ipasc */ + "", /* ipasc */ + -1 /* depth */ } }; @@ -11521,6 +11816,12 @@ int wolfSSL_X509_VERIFY_PARAM_inherit(WOLFSSL_X509_VERIFY_PARAM *to, isOverWrite = (flags & WOLFSSL_VPARAM_OVERWRITE); isDefault = (flags & WOLFSSL_VPARAM_DEFAULT); + /* copy depth if set, -1 is unset */ + if (isOverWrite || + (from->depth != -1 && (to->depth == -1 || isDefault))) { + to->depth = from->depth; + } + /* copy check_time if check time is not set */ if ((to->flags & WOLFSSL_USE_CHECK_TIME) == 0 || isOverWrite) { to->check_time = from->check_time; @@ -11815,13 +12116,23 @@ int wolfSSL_X509_VERIFY_PARAM_set1_ip(WOLFSSL_X509_VERIFY_PARAM* param, return ret; } -#ifndef NO_WOLFSSL_STUB +/* Frees what the object holds and leaves it empty. */ void wolfSSL_X509_OBJECT_free_contents(WOLFSSL_X509_OBJECT* obj) { - (void)obj; - WOLFSSL_STUB("X509_OBJECT_free_contents"); -} + WOLFSSL_ENTER("wolfSSL_X509_OBJECT_free_contents"); + if (obj == NULL) + return; + if (obj->type == WOLFSSL_X509_LU_X509) { + wolfSSL_X509_free(obj->data.x509); + } +#ifdef HAVE_CRL + else if (obj->type == WOLFSSL_X509_LU_CRL) { + wolfSSL_X509_CRL_free(obj->data.crl); + } #endif + obj->type = WOLFSSL_X509_LU_NONE; + obj->data.ptr = NULL; +} #ifndef NO_ASN_TIME int wolfSSL_X509_cmp_current_time(const WOLFSSL_ASN1_TIME* asnTime) @@ -11956,17 +12267,26 @@ static WOLFSSL_X509_REVOKED* RevokedCertToRevoked(RevokedCert* rc, int seq) return NULL; } if (rc->serialSz > 0 && rc->serialSz <= EXTERNAL_SERIAL_SIZE) { - serial->data = (unsigned char*)XMALLOC((size_t)rc->serialSz, NULL, - DYNAMIC_TYPE_OPENSSL); + /* Serials are positive: a high bit needs a zero octet. */ + int pad = (rc->serialNumber[0] & 0x80) ? 1 : 0; + + /* DER encoding: tag, length, content. */ + serial->data = (unsigned char*)XMALLOC( + (size_t)(rc->serialSz + 2 + pad), NULL, DYNAMIC_TYPE_OPENSSL); if (serial->data == NULL) { wolfSSL_ASN1_INTEGER_free(serial); XFREE(rev, NULL, DYNAMIC_TYPE_OPENSSL); return NULL; } - XMEMCPY(serial->data, rc->serialNumber, (size_t)rc->serialSz); - serial->length = rc->serialSz; - serial->dataMax = rc->serialSz; + serial->data[0] = ASN_INTEGER; + serial->data[1] = (byte)(rc->serialSz + pad); + serial->data[2] = 0x00; + XMEMCPY(serial->data + 2 + pad, rc->serialNumber, + (size_t)rc->serialSz); + serial->length = rc->serialSz + 2 + pad; + serial->dataMax = (unsigned int)serial->length; serial->isDynamic = 1; + serial->type = WOLFSSL_V_ASN1_INTEGER; } rev->serialNumber = serial; @@ -12096,6 +12416,7 @@ WOLFSSL_ASN1_INTEGER* wolfSSL_X509_get_serialNumber(WOLFSSL_X509* x509) { WOLFSSL_ASN1_INTEGER* a; int i = 0; + int pad; WOLFSSL_ENTER("wolfSSL_X509_get_serialNumber"); @@ -12116,16 +12437,19 @@ WOLFSSL_ASN1_INTEGER* wolfSSL_X509_get_serialNumber(WOLFSSL_X509* x509) if (a == NULL) return NULL; + /* Serials are positive: a high bit needs a zero octet in DER. */ + pad = ((x509->serialSz > 0) && (x509->serial[0] & 0x80)) ? 1 : 0; + /* Make sure there is space for the data, ASN.1 type and length. */ - if (x509->serialSz > (WOLFSSL_ASN1_INTEGER_MAX - 2)) { + if (x509->serialSz + pad > (WOLFSSL_ASN1_INTEGER_MAX - 2)) { /* dynamically create data buffer, +2 for type and length */ - a->data = (unsigned char*)XMALLOC(x509->serialSz + 2, NULL, + a->data = (unsigned char*)XMALLOC(x509->serialSz + pad + 2, NULL, DYNAMIC_TYPE_OPENSSL); if (a->data == NULL) { wolfSSL_ASN1_INTEGER_free(a); return NULL; } - a->dataMax = (unsigned int)x509->serialSz + 2; + a->dataMax = (unsigned int)(x509->serialSz + pad + 2); a->isDynamic = 1; } else { @@ -12139,10 +12463,13 @@ WOLFSSL_ASN1_INTEGER* wolfSSL_X509_get_serialNumber(WOLFSSL_X509* x509) a->length = x509->serialSz; #else a->data[i++] = ASN_INTEGER; - i += SetLength(x509->serialSz, a->data + i); + i += SetLength(x509->serialSz + pad, a->data + i); + if (pad) + a->data[i++] = 0x00; XMEMCPY(&a->data[i], x509->serial, x509->serialSz); - a->length = x509->serialSz + 2; + a->length = i + x509->serialSz; #endif + a->type = WOLFSSL_V_ASN1_INTEGER; x509->serialNumber = a; @@ -12789,8 +13116,28 @@ int wolfSSL_X509_up_ref(WOLFSSL_X509* x509) WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_X509_chain_up_ref( WOLF_STACK_OF(WOLFSSL_X509)* chain) { - /* wolfSSL_sk_dup takes care of doing a deep copy */ - return wolfSSL_sk_dup(chain); + WOLFSSL_STACK* ret; + WOLFSSL_STACK* node; + WOLFSSL_STACK* fail = NULL; + + /* As OpenSSL: the same certs, each with a new reference. */ + ret = wolfSSL_shallow_sk_dup(chain); + for (node = ret; node != NULL; node = node->next) { + if ((node->data.x509 != NULL) && + (wolfSSL_X509_up_ref(node->data.x509) != WOLFSSL_SUCCESS)) { + fail = node; + break; + } + } + if (fail != NULL) { + for (node = ret; node != fail; node = node->next) { + wolfSSL_X509_free(node->data.x509); + } + wolfSSL_sk_free(ret); + ret = NULL; + } + + return ret; } #endif @@ -13895,6 +14242,11 @@ static int CertFromX509(Cert* cert, WOLFSSL_X509* x509) } totalLen = AddSignature(NULL, ret, NULL, x509->sig.length, x509->sigOID); + if (totalLen <= 0) { + WOLFSSL_MSG("Unable to add signature"); + ret = WOLFSSL_FAILURE; + goto cleanup; + } if (totalLen > *derSz) { WOLFSSL_MSG("Output der buffer too short"); ret = WOLFSSL_FAILURE; @@ -13902,6 +14254,11 @@ static int CertFromX509(Cert* cert, WOLFSSL_X509* x509) } ret = AddSignature(der, ret, x509->sig.buffer, x509->sig.length, x509->sigOID); + if (ret <= 0) { + WOLFSSL_MSG("Unable to add signature"); + ret = WOLFSSL_FAILURE; + goto cleanup; + } } *derSz = ret; @@ -14807,7 +15164,12 @@ static WOLFSSL_X509 *loadX509orX509REQFromPemBio(WOLFSSL_BIO *bp, CERT_TYPE, cb, u); } - if (x != NULL) { + /* Free the object passed in and put the new one there. OpenSSL decodes + * into it instead. Keep it when nothing was read. */ + if (x != NULL && x509 != NULL) { + if (*x != NULL && *x != x509) { + wolfSSL_X509_free(*x); + } *x = x509; } @@ -15810,6 +16172,48 @@ int wolfSSL_write_X509_CRL(WOLFSSL_X509_CRL* crl, const char* path, int type) return ne; } + +#ifdef OPENSSL_EXTRA + /* Duplicate a name entry with copies of its object and value. + * Returns the new entry or NULL on failure. */ + WOLFSSL_X509_NAME_ENTRY* wolfSSL_X509_NAME_ENTRY_dup( + const WOLFSSL_X509_NAME_ENTRY* ne) + { + WOLFSSL_X509_NAME_ENTRY* dupl = NULL; + int err = 0; + + WOLFSSL_ENTER("wolfSSL_X509_NAME_ENTRY_dup"); + + if (ne == NULL) { + return NULL; + } + dupl = wolfSSL_X509_NAME_ENTRY_new(); + if (dupl == NULL) { + return NULL; + } + dupl->nid = ne->nid; + dupl->set = ne->set; + dupl->size = ne->size; + if (ne->object != NULL) { + dupl->object = wolfSSL_ASN1_OBJECT_dup(ne->object); + if (dupl->object == NULL) { + err = 1; + } + } + if ((err == 0) && (ne->value != NULL)) { + dupl->value = wolfSSL_ASN1_STRING_dup(ne->value); + if (dupl->value == NULL) { + err = 1; + } + } + if (err != 0) { + wolfSSL_X509_NAME_ENTRY_free(dupl); + dupl = NULL; + } + + return dupl; + } +#endif /* OPENSSL_EXTRA */ #endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) || \ @@ -16470,6 +16874,9 @@ WOLF_STACK_OF(WOLFSSL_X509_NAME_ENTRY)* wolfSSL_sk_X509_NAME_ENTRY_new( WOLFSSL_STACK* sk = wolfSSL_sk_new_node(NULL); if (sk != NULL) { sk->type = STACK_TYPE_X509_NAME_ENTRY; + #ifdef OPENSSL_ALL + sk->comp = (wolf_sk_compare_cb)cb; + #endif (void)cb; } return sk; @@ -16500,6 +16907,33 @@ void wolfSSL_sk_X509_NAME_ENTRY_free(WOLF_STACK_OF(WOLFSSL_X509_NAME_ENTRY)* sk) wolfSSL_sk_free(sk); } +/* Free the stack and each entry in it with f. */ +void wolfSSL_sk_X509_NAME_ENTRY_pop_free( + WOLF_STACK_OF(WOLFSSL_X509_NAME_ENTRY)* sk, + void (*f)(WOLFSSL_X509_NAME_ENTRY*)) +{ + wolfSSL_sk_pop_free(sk, (wolfSSL_sk_freefunc)f); +} + +#ifdef OPENSSL_ALL +/* Sets the comparator used by sort. Returns the previous one. */ +wolf_sk_X509_NAME_ENTRY_cmp_cb wolfSSL_sk_X509_NAME_ENTRY_set_cmp_func( + WOLF_STACK_OF(WOLFSSL_X509_NAME_ENTRY)* sk, + wolf_sk_X509_NAME_ENTRY_cmp_cb cb) +{ + return (wolf_sk_X509_NAME_ENTRY_cmp_cb)wolfSSL_sk_set_cmp_func(sk, + (wolf_sk_compare_cb)cb); +} + +/* Sorts the entries with the comparator. */ +void wolfSSL_sk_X509_NAME_ENTRY_sort(WOLF_STACK_OF(WOLFSSL_X509_NAME_ENTRY)* sk) +{ + WOLFSSL_ENTER("wolfSSL_sk_X509_NAME_ENTRY_sort"); + + wolfSSL_sk_sort(sk); +} +#endif /* OPENSSL_ALL */ + #endif /* OPENSSL_EXTRA || HAVE_STUNNEL || WOLFSSL_NGINX || HAVE_LIGHTY || WOLFSSL_HAPROXY || WOLFSSL_OPENSSH || HAVE_SBLIM_SFCB */ @@ -17074,19 +17508,7 @@ void wolfSSL_X509_OBJECT_free(WOLFSSL_X509_OBJECT *obj) { WOLFSSL_ENTER("wolfSSL_X509_OBJECT_free"); if (obj != NULL) { - if (obj->type == WOLFSSL_X509_LU_X509) { - wolfSSL_X509_free(obj->data.x509); - } - #ifdef HAVE_CRL - else if (obj->type == WOLFSSL_X509_LU_CRL) { - wolfSSL_X509_CRL_free(obj->data.crl); - } - #endif - else { - /* We don't free as this will point to - * store->cm->crl which we don't own */ - WOLFSSL_MSG("Not free'ing CRL in WOLFSSL_X509_OBJECT"); - } + wolfSSL_X509_OBJECT_free_contents(obj); XFREE(obj, NULL, DYNAMIC_TYPE_OPENSSL); } } @@ -18464,6 +18886,8 @@ void wolfSSL_X509_REQ_free(WOLFSSL_X509* req) wolfSSL_X509_free(req); } +static void regenX509REQDerBuffer(WOLFSSL_X509* x509); + int wolfSSL_X509_REQ_set_version(WOLFSSL_X509 *x, long version) { WOLFSSL_ENTER("wolfSSL_X509_REQ_set_version"); @@ -18471,6 +18895,8 @@ int wolfSSL_X509_REQ_set_version(WOLFSSL_X509 *x, long version) return WOLFSSL_FAILURE; } x->version = (int)version; + /* As OpenSSL, a request that is changed is encoded again */ + regenX509REQDerBuffer(x); return WOLFSSL_SUCCESS; } @@ -18543,44 +18969,42 @@ int wolfSSL_X509_REQ_sign_ctx(WOLFSSL_X509 *req, return WOLFSSL_FAILURE; } -static int regenX509REQDerBuffer(WOLFSSL_X509* x509) +/* Store the encoding of a request whose fields changed. A signed request keeps + * its old signature until it is signed again. An unsigned request has no + * complete encoding, and neither has one that cannot be encoded, as a DSA + * request: then none is kept, so none out of date is written. The change + * stands, as in OpenSSL, which encodes a request when it is written. */ +static void regenX509REQDerBuffer(WOLFSSL_X509* x509) { - int derSz = X509_BUFFER_SZ; - int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE); -#ifndef WOLFSSL_SMALL_STACK - byte der[X509_BUFFER_SZ]; -#else - byte* der; + /* Room for the request info and the largest signature. */ + int derSz = X509_BUFFER_SZ + MAX_SIG_SZ; + DerBuffer* newDer = NULL; + WC_DECLARE_VAR(der, byte, X509_BUFFER_SZ + MAX_SIG_SZ, 0); - der = (byte*)XMALLOC(derSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (!der) { - WOLFSSL_MSG("malloc failed"); - return WOLFSSL_FAILURE; - } +#if !defined(WOLFSSL_NO_CA_NAMES) && defined(OPENSSL_EXTRA) + /* The names are encoded again, not as they were in the old encoding + * or in the names they were set from, and not where they were. */ + ClearX509NameRaw(&x509->issuer); + ClearX509NameRaw(&x509->subject); #endif - - if (wolfssl_x509_make_der(x509, 1, der, &derSz, 0) == WOLFSSL_SUCCESS) { + if (x509->sig.buffer == NULL) { FreeDer(&x509->derCert); - #if !defined(WOLFSSL_NO_CA_NAMES) && defined(OPENSSL_EXTRA) - /* The names are encoded again, not as they were in the old encoding - * or in the names they were set from, and not where they were. */ - ClearX509NameRaw(&x509->issuer); - ClearX509NameRaw(&x509->subject); - #endif - if (AllocDer(&x509->derCert, (word32)derSz, CERT_TYPE, - x509->heap) == 0) { - XMEMCPY(x509->derCert->buffer, der, derSz); - ret = WOLFSSL_SUCCESS; - } - else { - WOLFSSL_MSG("Failed to allocate DER buffer for X509"); - } + return; } - else { + + WC_ALLOC_VAR_EX(der, byte, derSz, NULL, DYNAMIC_TYPE_TMP_BUFFER, + { FreeDer(&x509->derCert); return; }); + + if (wolfssl_x509_make_der(x509, 1, der, &derSz, 1) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("Unable to make DER for X509 REQ"); } + else if (AllocCopyDer(&newDer, der, (word32)derSz, CERT_TYPE, + x509->heap) != 0) { + WOLFSSL_MSG("Failed to allocate DER buffer for X509"); + } + FreeDer(&x509->derCert); + x509->derCert = newDer; WC_FREE_VAR_EX(der, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return ret; } int wolfSSL_X509_REQ_add_extensions(WOLFSSL_X509* req, @@ -18610,7 +19034,8 @@ int wolfSSL_X509_REQ_add_extensions(WOLFSSL_X509* req, ext_sk = ext_sk->next; } - return regenX509REQDerBuffer(req); + regenX509REQDerBuffer(req); + return WOLFSSL_SUCCESS; } int wolfSSL_X509_REQ_add1_attr_by_txt(WOLFSSL_X509 *req, @@ -18763,6 +19188,9 @@ int wolfSSL_X509_REQ_add1_attr_by_NID(WOLFSSL_X509 *req, if (ret != WOLFSSL_SUCCESS) wolfSSL_X509_ATTRIBUTE_free(attr); } + if (ret == WOLFSSL_SUCCESS) { + regenX509REQDerBuffer(req); + } return ret; } @@ -18779,12 +19207,20 @@ WOLFSSL_X509 *wolfSSL_X509_to_X509_REQ(WOLFSSL_X509 *x, int wolfSSL_X509_REQ_set_subject_name(WOLFSSL_X509 *req, WOLFSSL_X509_NAME *name) { - return wolfSSL_X509_set_subject_name(req, name); + if (wolfSSL_X509_set_subject_name(req, name) != WOLFSSL_SUCCESS) { + return WOLFSSL_FAILURE; + } + regenX509REQDerBuffer(req); + return WOLFSSL_SUCCESS; } int wolfSSL_X509_REQ_set_pubkey(WOLFSSL_X509 *req, WOLFSSL_EVP_PKEY *pkey) { - return wolfSSL_X509_set_pubkey(req, pkey); + if (wolfSSL_X509_set_pubkey(req, pkey) != WOLFSSL_SUCCESS) { + return WOLFSSL_FAILURE; + } + regenX509REQDerBuffer(req); + return WOLFSSL_SUCCESS; } #endif /* OPENSSL_ALL && WOLFSSL_CERT_GEN && WOLFSSL_CERT_REQ */ diff --git a/src/x509_str.c b/src/x509_str.c index 3e65d833826..7784bd34dce 100644 --- a/src/x509_str.c +++ b/src/x509_str.c @@ -34,11 +34,13 @@ #ifdef OPENSSL_EXTRA static int X509StoreGetIssuerEx(WOLFSSL_X509 **issuer, WOLFSSL_STACK *certs, WOLFSSL_X509 *x); -static int X509StoreGetIssuerSkip(WOLFSSL_X509 **issuer, - WOLFSSL_STACK *certs, WOLFSSL_X509 *x, - WOLF_STACK_OF(WOLFSSL_X509)* skip); static int X509StoreAddCa(WOLFSSL_X509_STORE* store, WOLFSSL_X509* x509, int type); +static int X509StoreCertInStack(WOLF_STACK_OF(WOLFSSL_X509)* stack, + WOLFSSL_X509* cert); +static int X509StoreCertPartialChainEnabled(WOLFSSL_X509_STORE_CTX* ctx); +static int X509StoreKeySigned(WOLFSSL_X509* ca, WOLFSSL_X509* x, int* err); +static int X509StoreIssued(WOLFSSL_X509* ca, WOLFSSL_X509* x); #endif /* Based on OpenSSL default max depth */ @@ -86,15 +88,12 @@ void wolfSSL_X509_STORE_CTX_free(WOLFSSL_X509_STORE_CTX* ctx) #endif #ifdef OPENSSL_EXTRA - XFREE(ctx->param, ctx->heap, DYNAMIC_TYPE_OPENSSL); + wolfSSL_X509_VERIFY_PARAM_free(ctx->param); ctx->param = NULL; if (ctx->chain != NULL) { wolfSSL_sk_X509_pop_free(ctx->chain, NULL); } - if (ctx->owned != NULL) { - wolfSSL_sk_X509_pop_free(ctx->owned, NULL); - } if (ctx->current_issuer != NULL) { wolfSSL_X509_free(ctx->current_issuer); @@ -215,15 +214,6 @@ int wolfSSL_X509_STORE_CTX_init(WOLFSSL_X509_STORE_CTX* ctx, wolfSSL_sk_X509_pop_free(ctx->chain, NULL); ctx->chain = NULL; } - /* Release the issuers retained by the previous verification and start - * a fresh stack. X509StoreVerifyCert() drops the issuer it decodes - * when this is NULL, so the context must always carry one. */ - wolfSSL_sk_X509_pop_free(ctx->owned, NULL); - ctx->owned = wolfSSL_sk_X509_new_null(); - if (ctx->owned == NULL) { - WOLFSSL_MSG("wolfSSL_X509_STORE_CTX_init failed"); - return WOLFSSL_FAILURE; - } #ifdef SESSION_CERTS ctx->sesChain = NULL; #endif @@ -231,9 +221,6 @@ int wolfSSL_X509_STORE_CTX_init(WOLFSSL_X509_STORE_CTX* ctx, #ifdef HAVE_EX_DATA XMEMSET(&ctx->ex_data, 0, sizeof(ctx->ex_data)); #endif -#if defined(WOLFSSL_APACHE_HTTPD) || defined(OPENSSL_EXTRA) - ctx->depth = WOLFSSL_X509_STORE_DEFAULT_MAX_DEPTH; -#endif ctx->userCtx = NULL; ctx->verify_cb = NULL; @@ -241,16 +228,18 @@ int wolfSSL_X509_STORE_CTX_init(WOLFSSL_X509_STORE_CTX* ctx, ctx->error_depth = 0; ctx->discardSessionCerts = 0; + /* As X509_VERIFY_PARAM_new(), so set0_param() can replace it */ if (ctx->param == NULL) { ctx->param = (WOLFSSL_X509_VERIFY_PARAM*)XMALLOC( sizeof(WOLFSSL_X509_VERIFY_PARAM), - ctx->heap, DYNAMIC_TYPE_OPENSSL); + NULL, DYNAMIC_TYPE_OPENSSL); if (ctx->param == NULL){ WOLFSSL_MSG("wolfSSL_X509_STORE_CTX_init failed"); return WOLFSSL_FAILURE; } } XMEMSET(ctx->param, 0, sizeof(*ctx->param)); + ctx->param->depth = -1; /* Inherit the store's parameters, including the hostname / IP the * caller expects the peer to present. */ @@ -261,6 +250,12 @@ int wolfSSL_X509_STORE_CTX_init(WOLFSSL_X509_STORE_CTX* ctx, return WOLFSSL_FAILURE; } } + /* No depth from the store: use the default, as OpenSSL does */ + if (ctx->param->depth == -1) { + ctx->param->depth = WOLFSSL_X509_STORE_DEFAULT_MAX_DEPTH; + } + /* As OpenSSL's default param */ + ctx->param->flags |= WOLFSSL_TRUSTED_FIRST; return WOLFSSL_SUCCESS; } @@ -274,7 +269,7 @@ void wolfSSL_X509_STORE_CTX_cleanup(WOLFSSL_X509_STORE_CTX* ctx) { if (ctx != NULL) { - XFREE(ctx->param, ctx->heap, DYNAMIC_TYPE_OPENSSL); + wolfSSL_X509_VERIFY_PARAM_free(ctx->param); ctx->param = NULL; wolfSSL_X509_STORE_CTX_init(ctx, NULL, NULL, NULL); @@ -346,7 +341,10 @@ int GetX509Error(int e) case WC_NO_ERR_TRACE(CRL_CERT_REVOKED): return WOLFSSL_X509_V_ERR_CERT_REVOKED; case WC_NO_ERR_TRACE(CRL_MISSING): + case WC_NO_ERR_TRACE(ASN_CRL_NO_SIGNER_E): return WOLFSSL_X509_V_ERR_UNABLE_TO_GET_CRL; + case WC_NO_ERR_TRACE(ASN_CRL_CONFIRM_E): + return WOLFSSL_X509_V_ERR_CRL_SIGNATURE_FAILURE; case WC_NO_ERR_TRACE(EXTKEYUSE_AUTH_E): return WOLFSSL_X509_V_ERR_INVALID_PURPOSE; /* is an internal wolfSSL return code, not an X509_V_* code, so 1 @@ -383,161 +381,146 @@ static void SetupStoreCtxError_ex(WOLFSSL_X509_STORE_CTX* ctx, int ret, wolfSSL_X509_STORE_CTX_set_error_depth(ctx, depth); } -static void SetupStoreCtxError(WOLFSSL_X509_STORE_CTX* ctx, int ret) +#ifndef NO_ASN_TIME +/* The verification time, as OpenSSL's: the param time with + * X509_V_FLAG_USE_CHECK_TIME, none with X509_V_FLAG_NO_CHECK_TIME, else the + * current time, 0. As in wolfCrypt's date checks, a param time of 0 is the + * current time. A custom XVALIDATE_DATE always checks against its own time. + * Returns 0 when dates are not checked, else 1 and the time in *t. */ +static int X509StoreCheckTime(WOLFSSL_X509_STORE_CTX* ctx, time_t* t) { - int depth = 0; - - /* Set error depth */ - if (ctx->chain) - depth = (int)ctx->chain->num; +#ifdef USE_WOLF_VALIDDATE + WOLFSSL_X509_VERIFY_PARAM* param = ctx->param; - SetupStoreCtxError_ex(ctx, ret, depth); + if (param == NULL && ctx->store != NULL) { + param = ctx->store->param; + } + if (param != NULL && (param->flags & WOLFSSL_USE_CHECK_TIME) != 0) { + *t = param->check_time; + return 1; + } + if (param != NULL && (param->flags & WOLFSSL_NO_CHECK_TIME) != 0) { + return 0; + } +#else + (void)ctx; +#endif + *t = 0; + return 1; } -#ifndef NO_ASN_TIME -/* Post certificate validation date handling. This function is called after the - * certificate has been verified by the certificate manager. It then checks if - * X509 store parameters are set for date validation override. - * @param ctx The certificate store context - * @param ret The return value from the certificate manager verify - * @return The return value for the certificate date validation after override - */ -static int X509StoreVerifyCertDate(WOLFSSL_X509_STORE_CTX* ctx, int ret) +/* Checks the validity period of x509 at the verification time. + * Returns WOLFSSL_SUCCESS, ASN_BEFORE_DATE_E or ASN_AFTER_DATE_E. */ +static int X509StoreCheckCertDate(WOLFSSL_X509_STORE_CTX* ctx, + WOLFSSL_X509* x509) { - byte *afterDate = ctx->current_cert->notAfter.data; - byte *beforeDate = ctx->current_cert->notBefore.data; + time_t t; - /* Only override existing date errors or WOLFSSL_SUCCESS. */ - if (ret == WC_NO_ERR_TRACE(ASN_BEFORE_DATE_E) || - ret == WC_NO_ERR_TRACE(ASN_AFTER_DATE_E) || - ret == WC_NO_ERR_TRACE(WOLFSSL_SUCCESS)) { + if (!X509StoreCheckTime(ctx, &t)) { + return WOLFSSL_SUCCESS; + } #ifdef USE_WOLF_VALIDDATE - WOLFSSL_X509_VERIFY_PARAM* param = NULL; - - /* If no external XVALIDATE_DATE was defined then use param for date - validation overrides. */ - if (ctx->param != NULL) { - param = ctx->param; + if (t != 0) { + if (wc_ValidateDateWithTime(x509->notBefore.data, + (byte)x509->notBefore.type, ASN_BEFORE, t, + x509->notBefore.length) < 1) { + return ASN_BEFORE_DATE_E; + } + /* Expired at its notAfter, as OpenSSL's X509_cmp_time() */ + if (wc_ValidateDateWithTime(x509->notAfter.data, + (byte)x509->notAfter.type, ASN_AFTER, t + 1, + x509->notAfter.length) < 1) { + return ASN_AFTER_DATE_E; } - else if (ctx->store != NULL && ctx->store->param != NULL) { - param = ctx->store->param; - } - - if (param != NULL) { - if ((param->flags & WOLFSSL_NO_CHECK_TIME) != 0) { - WOLFSSL_MSG("Overriding date validation WOLFSSL_NO_CHECK_TIME"); - ret = WOLFSSL_SUCCESS; - } - else if ((param->flags & WOLFSSL_USE_CHECK_TIME) != 0 && - (param->check_time != 0)) { - time_t checkTime = param->check_time; - ret = WOLFSSL_SUCCESS; /* override date error and use custom set - time for validating certificate dates */ - WOLFSSL_MSG("Override date validation, WOLFSSL_USE_CHECK_TIME"); - if (wc_ValidateDateWithTime(afterDate, - (byte)ctx->current_cert->notAfter.type, ASN_AFTER, - checkTime, ctx->current_cert->notAfter.length) < 1) { - ret = ASN_AFTER_DATE_E; - } - else if (wc_ValidateDateWithTime(beforeDate, - (byte)ctx->current_cert->notBefore.type, ASN_BEFORE, - checkTime, ctx->current_cert->notBefore.length) < 1) { - ret = ASN_BEFORE_DATE_E; - } - } - #if defined(OPENSSL_ALL) - else { - WOLFSSL_MSG("Using system time for date validation"); - /* use system time for date validation */ - if (wc_ValidateDate(afterDate, - (byte)ctx->current_cert->notAfter.type, ASN_AFTER, - ctx->current_cert->notAfter.length) < 1) { - ret = ASN_AFTER_DATE_E; - } - else if (wc_ValidateDate(beforeDate, - (byte)ctx->current_cert->notBefore.type, ASN_BEFORE, - ctx->current_cert->notBefore.length) < 1) { - ret = ASN_BEFORE_DATE_E; - } - } - #endif - } -#else - if (XVALIDATE_DATE(afterDate, - (byte)ctx->current_cert->notAfter.type, ASN_AFTER, - ctx->current_cert->notAfter.length) < 1) { - ret = ASN_AFTER_DATE_E; - } - else if (XVALIDATE_DATE(beforeDate, - (byte)ctx->current_cert->notBefore.type, ASN_BEFORE, - ctx->current_cert->notBefore.length) < 1) { - ret = ASN_BEFORE_DATE_E; - } -#endif /* USE_WOLF_VALIDDATE */ + return WOLFSSL_SUCCESS; } - - return ret; +#endif + if (XVALIDATE_DATE(x509->notBefore.data, (byte)x509->notBefore.type, + ASN_BEFORE, x509->notBefore.length) < 1) { + return ASN_BEFORE_DATE_E; + } + if (XVALIDATE_DATE(x509->notAfter.data, (byte)x509->notAfter.type, + ASN_AFTER, x509->notAfter.length) < 1) { + return ASN_AFTER_DATE_E; + } + return WOLFSSL_SUCCESS; } + #endif /* NO_ASN_TIME */ #ifdef HAVE_CRL -/* Check ctx->current_cert against the CRLs set with - * X509_STORE_CTX_set0_crls. - * Returns WOLFSSL_SUCCESS if a CRL for the cert's issuer is in the stack and - * the cert is not revoked. Returns CRL_MISSING if the stack has no CRL for - * the issuer. Returns a negative error on revocation or CRL failure. */ -static int X509StoreCheckCtxCrls(WOLFSSL_X509_STORE_CTX* ctx) +/* Check ctx->current_cert against the store's CRLs, signed by issuer and + * current at *checkTime, as CheckCertCRLFromCm() checks them. + * Returns WOLFSSL_SUCCESS or the CRL error. */ +static int X509StoreCheckStoreCrl(WOLFSSL_X509_STORE_CTX* ctx, Signer* issuer, + const time_t* checkTime) { - int ret = WC_NO_ERR_TRACE(CRL_MISSING); - int found = 0; - int dateErr = 0; + int ret; + WC_DECLARE_VAR(cert, DecodedCert, 1, 0); + + WC_ALLOC_VAR_EX(cert, DecodedCert, 1, ctx->heap, DYNAMIC_TYPE_DCERT, + return MEMORY_E); + + InitDecodedCert(cert, ctx->current_cert->derCert->buffer, + ctx->current_cert->derCert->length, ctx->heap); + ret = ParseCertRelative(cert, CERT_TYPE, NO_VERIFY, ctx->store->cm, NULL); + if (ret == 0) { + ret = CheckCertCRLFromCm(ctx->store->cm, ctx->store->cm->crl, cert, + issuer, checkTime); + } + FreeDecodedCert(cert); + WC_FREE_VAR_EX(cert, ctx->heap, DYNAMIC_TYPE_DCERT); + + return (ret == 0) ? WOLFSSL_SUCCESS : ret; +} + +/* As OpenSSL's get_crl_sk(), checks the cert with only the best CRL set with + * X509_STORE_CTX_set0_crls. Returns WOLFSSL_SUCCESS or the CRL error. */ +static int X509StoreCheckCtxCrls(WOLFSSL_X509_STORE_CTX* ctx, Signer* issuer, + const time_t* checkTime) +{ + int ret; int i; int numCrls; + int cur = 0; + WOLFSSL_ASN1_TIME last; + WOLFSSL_X509_CRL* best = NULL; WC_DECLARE_VAR(cert, DecodedCert, 1, 0); numCrls = wolfSSL_sk_X509_CRL_num(ctx->crls); if (numCrls <= 0) - return ret; + return WC_NO_ERR_TRACE(CRL_MISSING); WC_ALLOC_VAR_EX(cert, DecodedCert, 1, ctx->heap, DYNAMIC_TYPE_DCERT, return MEMORY_E); + XMEMSET(&last, 0, sizeof(last)); InitDecodedCert(cert, ctx->current_cert->derCert->buffer, ctx->current_cert->derCert->length, ctx->heap); /* The cert signature is verified by the CertManager. Only the issuer and - * serial info is needed here. */ - if (ParseCertRelative(cert, CERT_TYPE, NO_VERIFY, ctx->store->cm, NULL) - == 0) { - /* Check all CRLs in the stack. A revocation in any of them wins over - * a CRL that does not list the cert, like in the CertManager. */ - for (i = 0; i < numCrls; i++) { - WOLFSSL_X509_CRL* crl = wolfSSL_sk_X509_CRL_value(ctx->crls, i); - if (crl == NULL) - continue; - /* Use the store's cm to verify the CRL. The caller-owned crl is - * not modified. */ - ret = CheckCertCRLFromCm(ctx->store->cm, crl, cert); - if (ret == 0) - found = 1; - else if (ret == WC_NO_ERR_TRACE(CRL_CERT_DATE_ERR)) - dateErr = 1; /* stale CRL, another CRL can still vouch */ - else if (ret != WC_NO_ERR_TRACE(CRL_MISSING)) - break; + * serial info is needed here. A parse error is final, not CRL_MISSING. */ + ret = ParseCertRelative(cert, CERT_TYPE, NO_VERIFY, ctx->store->cm, NULL); + for (i = 0; ret == 0 && i < numCrls; i++) { + WOLFSSL_X509_CRL* crl = wolfSSL_sk_X509_CRL_value(ctx->crls, i); + + if (crl != NULL) { + ret = PickCertCRL(crl, cert, issuer, checkTime, &cur, &last); + if (ret == 1) { + best = crl; + ret = 0; + } } } + if (ret == 0) { + /* The store's cm verifies the CRL. The caller-owned crl is not + * modified. */ + ret = (best == NULL) ? WC_NO_ERR_TRACE(CRL_MISSING) : + CheckCertCRLFromCm(ctx->store->cm, best, cert, issuer, checkTime); + } FreeDecodedCert(cert); WC_FREE_VAR_EX(cert, ctx->heap, DYNAMIC_TYPE_DCERT); - if (ret == 0 || ret == WC_NO_ERR_TRACE(CRL_MISSING) || - ret == WC_NO_ERR_TRACE(CRL_CERT_DATE_ERR)) { - if (found) - ret = WOLFSSL_SUCCESS; - else if (dateErr) - ret = WC_NO_ERR_TRACE(CRL_CERT_DATE_ERR); - else - ret = WC_NO_ERR_TRACE(CRL_MISSING); - } - return ret; + return (ret == 0) ? WOLFSSL_SUCCESS : ret; } #endif /* HAVE_CRL */ @@ -554,6 +537,17 @@ static WOLFSSL_X509_STORE_CTX_verify_cb X509StoreGetVerifyCb( if (ctx == NULL) return NULL; +#if defined(SESSION_CERTS) && defined(KEEP_PEER_CERT) + /* An internal callback, as of SSL_get0_verified_chain, comes first. */ + if (ctx->verify_cb == VerifiedChainCb) + return ctx->verify_cb; +#endif + + /* A CertManager callback, as of an SSL_CTX's store, is used instead. */ + if (ctx->store != NULL && ctx->store->cm != NULL && + ctx->store->cm->verifyCallback != NULL) + return ctx->store->cm->verifyCallback; + if (ctx->verify_cb != NULL) return ctx->verify_cb; @@ -565,179 +559,33 @@ static WOLFSSL_X509_STORE_CTX_verify_cb X509StoreGetVerifyCb( return NULL; } -/* Verify ctx->current_cert against the store. - * - * is an out-parameter, never NULL. It is set to 1 when the - * application's per-context verify callback explicitly rejected a certificate - * the verification itself accepted, and to 0 otherwise. The rejection is - * reported out of band rather than as a return value so that it cannot be - * confused with any of the internal error codes this function passes through. - * - * A caller must stop chain building when it is set: a veto must not be turned - * into a retry with another issuer, and must not be cleared by the - * partial-chain fallback in wolfSSL_X509_verify_cert(). */ -static int X509StoreVerifyCert(WOLFSSL_X509_STORE_CTX* ctx, int* cbRejected, - WOLFSSL_X509_STORE_CTX_verify_cb verifyCb) -{ - int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE); - int crlRet = 0; - int datesChecked = 0; - WOLFSSL_ENTER("X509StoreVerifyCert"); - - *cbRejected = 0; - - if (ctx->current_cert != NULL && ctx->current_cert->derCert != NULL) { - ret = CM_VerifyBuffer_ex(ctx->store->cm, - ctx->current_cert->derCert->buffer, - ctx->current_cert->derCert->length, - WOLFSSL_FILETYPE_ASN1, 0, &crlRet); - datesChecked = (ret == WOLFSSL_SUCCESS) || - (ret == WC_NO_ERR_TRACE(ASN_BEFORE_DATE_E)) || - (ret == WC_NO_ERR_TRACE(ASN_AFTER_DATE_E)); -#ifdef HAVE_CRL - /* The CRLs set with X509_STORE_CTX_set0_crls can revoke a cert the - * CertManager accepted, or supply the CRL its own store lacked. */ - if (ctx->crls != NULL && ctx->store->cm->crlEnabled && datesChecked && - (crlRet == 0 || crlRet == WC_NO_ERR_TRACE(CRL_MISSING))) { - int ctxCrlRet = X509StoreCheckCtxCrls(ctx); - if (ctxCrlRet == WOLFSSL_SUCCESS) { - crlRet = 0; - } - else if (ctxCrlRet != WC_NO_ERR_TRACE(CRL_MISSING)) { - crlRet = ctxCrlRet; - } - } - /* Revocation is reported before the dates, as OpenSSL does. */ - if (crlRet != 0) { - SetupStoreCtxError(ctx, crlRet); - if ((verifyCb == NULL) || (verifyCb(0, ctx) != 1)) { - return crlRet; - } - } -#endif - #ifndef NO_ASN_TIME - /* update return value with any date validation overrides */ - ret = X509StoreVerifyCertDate(ctx, ret); - #endif - SetupStoreCtxError(ctx, ret); - if (verifyCb != NULL) { - /* Snapshot the error so the rejection below can tell one the - * callback recorded itself from one left over from an earlier - * certificate in the chain - SetupStoreCtxError() preserves the - * worst error seen so far, so ctx->error is not necessarily - * WOLFSSL_X509_V_OK on entry even when this certificate - * verified. */ - int preCbError = ctx->error; - - if (verifyCb(ret >= 0 ? 1 : 0, ctx) == 1) { - ret = WOLFSSL_SUCCESS; - } - else if (ret >= 0 && ctx->verify_cb != NULL) { - /* Returning 0 must reject a chain the cert manager accepted. */ - if (ctx->error == preCbError) { - /* Keep an error the callback recorded itself; otherwise - * the rejection has no error to report. */ - wolfSSL_X509_STORE_CTX_set_error(ctx, - WOLFSSL_X509_V_ERR_UNSPECIFIED); - } - *cbRejected = 1; - ret = WOLFSSL_FAILURE; - } - #if !defined(NO_ASN_TIME) && defined(OPENSSL_ALL) - else if (ret >= 0) { - /* A store callback may reject one too, without a veto. */ - ret = WOLFSSL_FATAL_ERROR; - } - #endif - } - } -#if !defined(NO_ASN_TIME) && defined(OPENSSL_ALL) - /* Skipped once the callback has rejected: the decision is already made, - * and re-running the date check would consult the callback a second time, - * which could overturn the rejection. */ - if (*cbRejected == 0 && !datesChecked && ret == WOLFSSL_SUCCESS) { - /* With OpenSSL, we need to check the certificate's date - * after certificate manager verification, - * as it skips date validation when other errors are present. - */ - ret = X509StoreVerifyCertDate(ctx, ret); - SetupStoreCtxError(ctx, ret); - ret = ret == WOLFSSL_SUCCESS ? 1 : 0; - if (verifyCb != NULL) { - if (verifyCb(ret, ctx) == 1) { - ret = WOLFSSL_SUCCESS; - } - else { - ret = -1; - } - } - } -#endif - (void)datesChecked; - return ret; -} - -static int addAllButSelfSigned(WOLF_STACK_OF(WOLFSSL_X509)*to, - WOLF_STACK_OF(WOLFSSL_X509)*from, int *numAdded) -{ - int ret = WOLFSSL_SUCCESS; - int i = 0; - int cnt = 0; - WOLFSSL_X509 *x = NULL; - - for (i = 0; i < wolfSSL_sk_X509_num(from); i++) { - x = wolfSSL_sk_X509_value(from, i); - if (wolfSSL_X509_NAME_cmp(&x->issuer, &x->subject) != 0) { - if (wolfSSL_sk_X509_push(to, x) <= 0) { - ret = WOLFSSL_FAILURE; - goto exit; - } - cnt++; - } - } - -exit: - if (numAdded != NULL) { - *numAdded = cnt; - } - return ret; -} - -static int X509StoreMoveCert(WOLFSSL_STACK *certs_stack, - WOLFSSL_STACK *dest_stack, - WOLFSSL_X509 *cert) { - int i; - - if (certs_stack == NULL || dest_stack == NULL || cert == NULL) - return WOLFSSL_FATAL_ERROR; - - for (i = 0; i < wolfSSL_sk_X509_num(certs_stack); i++) { - if (wolfSSL_sk_X509_value(certs_stack, i) == cert) { - wolfSSL_sk_X509_push(dest_stack, - (WOLFSSL_X509*)wolfSSL_sk_pop_node(certs_stack, i)); - return WOLFSSL_SUCCESS; - } - } - - return WOLFSSL_FAILURE; -} - /* Push x509 onto the ctx chain with its own reference, like OpenSSL. - * The chain owns a reference to each of its certs. */ + * The chain owns a reference to each of its certs. + * Returns WOLFSSL_SUCCESS, MEMORY_E or WOLFSSL_FATAL_ERROR. */ static int X509StoreChainPush(WOLF_STACK_OF(WOLFSSL_X509)* chain, WOLFSSL_X509* x509) { - int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE); + int ret = WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR); if (x509 == NULL || wolfSSL_X509_up_ref(x509) != WOLFSSL_SUCCESS) return ret; ret = wolfSSL_sk_X509_push(chain, x509) > 0 ? WOLFSSL_SUCCESS : - WC_NO_ERR_TRACE(WOLFSSL_FAILURE); + WC_NO_ERR_TRACE(MEMORY_E); if (ret != WOLFSSL_SUCCESS) wolfSSL_X509_free(x509); return ret; } +/* Keeps e, when it is an error, in *err unless one is there: an internal + * error of the chain checks. Returns e. */ +static int X509StoreKeepErr(int* err, int e) +{ + if (err != NULL && *err == 0 && e < 0) { + *err = e; + } + return e; +} + /* Returns 1 if `cert` (by pointer identity) is present in `stack`, else 0. * Used to keep a candidate that already failed verification off the reported * chain. */ @@ -761,25 +609,6 @@ static int X509StoreCertInStack(WOLF_STACK_OF(WOLFSSL_X509)* stack, return 0; } -/* Current certificate failed, but it is possible there is an - * alternative cert with the same subject key which will work. - * Retry until all possible candidate certs are exhausted. - * The temporary CAs of the abandoned path are not removed here: the caller - * drops all of them before it verifies the next link. */ -static void X509VerifyCertSetupRetry(WOLFSSL_X509_STORE_CTX* ctx, - WOLF_STACK_OF(WOLFSSL_X509)* certs, WOLF_STACK_OF(WOLFSSL_X509)* failed, - int* depth, int origDepth) { - WOLFSSL_MSG("X509_verify_cert current cert failed, " - "retrying with other certs."); - X509StoreMoveCert(certs, failed, ctx->current_cert); - ctx->current_cert = wolfSSL_sk_X509_pop(ctx->chain); - /* Release the chain's reference. The cert stays valid through its - * original owner. */ - wolfSSL_X509_free(ctx->current_cert); - if (*depth < origDepth) - *depth += 1; -} - /* Returns 1 if cur and x509 have identical DER encodings, 0 otherwise. */ static int X509DerEquals(WOLFSSL_X509* cur, WOLFSSL_X509* x509) { @@ -793,16 +622,11 @@ static int X509DerEquals(WOLFSSL_X509* cur, WOLFSSL_X509* x509) x509->derCert->length) == 0; } -/* Returns 1 if x509's DER matches an entry in either origTrustedSk (an - * immutable snapshot of the caller's trusted set - store->certs or the - * set0_trusted_stack override - captured before any intermediates were - * injected for this verification call) or in store->trusted. Returns 0 - * otherwise. Used by the X509_V_FLAG_PARTIAL_CHAIN fallback to confirm that - * a chain actually terminates at a caller-trusted certificate. - * NOTE: origTrustedSk is a private snapshot, but store->trusted is read live - * and unlocked here (as it is at the terminal issuer lookup); this mitigation - * is deliberately asymmetric, so a single X509_STORE must not be shared across - * threads verifying concurrently. */ +/* Returns 1 if x509's DER matches an entry in either origTrustedSk (the + * trusted certs of the verification: the trusted stack of the ctx or the + * certs added to the store) or in store->trusted. Returns 0 otherwise. + * NOTE: both are read without a lock, as at the issuer lookups, so an + * X509_STORE must not be changed while it is used to verify. */ static int X509StoreCertIsTrusted(WOLFSSL_X509_STORE* store, WOLFSSL_X509* x509, WOLF_STACK_OF(WOLFSSL_X509)* origTrustedSk) { @@ -831,527 +655,922 @@ static int X509StoreCertIsTrusted(WOLFSSL_X509_STORE* store, return 0; } -/* Enforce the BasicConstraints pathLenConstraint (RFC 5280 sec. 4.2.1.9 and - * the path validation rules in sec. 6.1.4 (l)/(m)) over the certification path - * assembled in ctx->chain. - * - * wolfSSL_X509_verify_cert() authenticates each certificate individually via - * the CertManager, which parses every certificate as CERT_TYPE. The issuer - * pathLen check in ParseCertRelative() is gated on a non-CERT_TYPE certificate - * type (it is reached on the TLS handshake path via CHAIN_CERT_TYPE), so the - * OpenSSL-compatibility path never enforced it. Re-create that check here over - * the completed path so that a CA asserting pathlen:N cannot issue more than N - * subordinate intermediate CAs. - * - * ctx->chain is ordered leaf first (index 0) up to the trust anchor (highest - * index). Walk from the trust anchor down toward the leaf, tracking the - * remaining number of non-self-issued intermediate certificates permitted. - * The budget is only enforced once some CA in the path actually asserts a - * pathLenConstraint; an explicit "haveConstraint" flag tracks that, so every - * value 0..WOLFSSL_MAX_PATH_LEN (the parser's hard cap on pathLenConstraint) - * is a usable budget rather than overloading the cap as a "no constraint" - * sentinel. The leaf (index 0) issues nothing and is therefore not subject to - * the constraint. - * - * Returns WOLFSSL_SUCCESS if the path satisfies every pathLenConstraint, or - * WOLFSSL_FAILURE (with ctx->error set) on the first violation. */ +/* Returns the store whose roots ctx trusts. As in OpenSSL, a trusted stack + * replaces them. */ +static WOLFSSL_X509_STORE* X509StoreRoots(WOLFSSL_X509_STORE_CTX* ctx) +{ + return (ctx->setTrustedSk != NULL) ? NULL : ctx->store; +} + +/* As OpenSSL's check_extensions(): the pathLenConstraint of a CA bounds the + * non-self-issued certs below it, the leaf not counted (RFC 5280 6.1.4 (l) + * and (m)). The error is reported at that CA. + * Returns WOLFSSL_SUCCESS, or WOLFSSL_FAILURE when the verify callback does + * not accept an error. */ static int X509StoreCheckPathLen(WOLFSSL_X509_STORE_CTX* ctx, WOLFSSL_X509_STORE_CTX_verify_cb verifyCb) { int num; int i; - word32 maxPathLen = 0; - byte haveConstraint = 0; - WOLFSSL_X509* anchor; + word32 plen = 0; if (ctx == NULL || ctx->chain == NULL) return WOLFSSL_SUCCESS; num = wolfSSL_sk_X509_num(ctx->chain); - /* A pathLen violation requires at least one intermediate between the leaf - * (index 0) and the trust anchor, i.e. a chain of three or more. */ - if (num < 3) - return WOLFSSL_SUCCESS; + for (i = 1; i < num; i++) { + WOLFSSL_X509* x509 = wolfSSL_sk_X509_value(ctx->chain, i); + + if (x509 == NULL) + continue; + if (i > 1 && x509->isCa && x509->basicConstPlSet && + plen > x509->pathLength) { + ctx->current_cert = x509; + SetupStoreCtxError_ex(ctx, + WOLFSSL_X509_V_ERR_PATH_LENGTH_EXCEEDED, i); + if (verifyCb == NULL || verifyCb(0, ctx) != 1) + return WOLFSSL_FAILURE; + } + if (wolfSSL_X509_NAME_cmp(&x509->issuer, &x509->subject) != 0) + plen++; + } + + return WOLFSSL_SUCCESS; +} + +/* Returns 1 if X509_V_FLAG_PARTIAL_CHAIN is set on the param of ctx, as + * OpenSSL reads it, otherwise 0. Init inherits the store's flags and + * X509_STORE_CTX_set0_param() replaces them. ctx and ctx->store must be + * non-NULL. */ +static int X509StoreCertPartialChainEnabled(WOLFSSL_X509_STORE_CTX* ctx) +{ + WOLFSSL_X509_VERIFY_PARAM* param = ctx->param; + + /* Without a param, the store's, as init would inherit */ + if (param == NULL) { + param = ctx->store->param; + } + return param != NULL && (param->flags & WOLFSSL_PARTIAL_CHAIN) != 0; +} + +/* Returns 1 if x509 can issue certs as OpenSSL's X509_check_ca() decides, + * with keyCertSign, as for a cert above the leaf. keyUsage, if present, must + * allow cert signing and basicConstraints, if present, must say CA. Without + * basicConstraints only the top cert of the chain can be a CA: a v1 + * self-signed cert or one with keyUsage. X509_V_FLAG_X509_STRICT drops that + * exception, as OpenSSL does. */ +static int X509StoreCertIsCa(WOLFSSL_X509_STORE_CTX* ctx, WOLFSSL_X509* x509, + int top) +{ + if (x509->keyUsageSet && (x509->keyUsage & KEYUSE_KEY_CERT_SIGN) == 0) { + return 0; + } + if (x509->basicConstSet) { + return x509->isCa; + } + if (!top || (ctx->param != NULL && + (ctx->param->flags & WOLFSSL_X509_STRICT) != 0)) { + return 0; + } + return x509->keyUsageSet || (x509->version == 1 && + wolfSSL_X509_check_issued(x509, x509) == WOLFSSL_X509_V_OK); +} + +/* Returns 1 if x509, an issuer on the chain, need not be a CA: with + * WOLFSSL_X509_STORE_ALLOW_NON_CA_INTERMEDIATE, an untrusted cert without + * CA:TRUE. Otherwise 0. */ +static int X509StoreNonCaAllowed(WOLFSSL_X509_STORE_CTX* ctx, + WOLFSSL_X509* x509, WOLF_STACK_OF(WOLFSSL_X509)* trustedSk) +{ +#ifdef WOLFSSL_X509_STORE_ALLOW_NON_CA_INTERMEDIATE + return !x509->isCa && X509StoreCertInStack(ctx->ctxIntermediates, x509) && + !X509StoreCertIsTrusted(X509StoreRoots(ctx), x509, trustedSk); +#else + (void)ctx; + (void)x509; + (void)trustedSk; + return 0; +#endif +} + +/* Returns 1 if ca was loaded by the application. As in OpenSSL, whose store + * holds only the certs added to it, a CA cached from a TLS peer's chain is + * not a trust anchor. */ +static int X509StoreCmCaLoaded(const Signer* ca) +{ + return ca != NULL && ca->type != WOLFSSL_CHAIN_CA && + ca->type != WOLFSSL_TEMP_CA; +} + +/* Returns 1 when ret, of ParseCertRelative() with a cert manager or of + * CheckCertSignaturePubKey(), is the result of verifying a cert, a + * signature algorithm not supported included. The cert decoded before, so + * another error is internal, as running out of memory. */ +static int X509StoreVerifyResult(int ret) +{ + return ret == 0 || ret == WC_NO_ERR_TRACE(ASN_NO_SIGNER_E) || + ret == WC_NO_ERR_TRACE(ASN_SELF_SIGNED_E) || + ret == WC_NO_ERR_TRACE(ASN_SIG_CONFIRM_E) || + ret == WC_NO_ERR_TRACE(ASN_SIG_OID_E) || + ret == WC_NO_ERR_TRACE(ASN_SIG_KEY_E) || + ret == WC_NO_ERR_TRACE(ASN_SIG_HASH_E) || + ret == WC_NO_ERR_TRACE(ASN_UNKNOWN_OID_E) || + ret == WC_NO_ERR_TRACE(HASH_TYPE_E) || + ret == WC_NO_ERR_TRACE(NOT_COMPILED_IN) || + ret == WC_NO_ERR_TRACE(BUFFER_E) || + ret == WC_NO_ERR_TRACE(ASN_NAME_INVALID_E) || + ret == WC_NO_ERR_TRACE(ASN_PATHLEN_SIZE_E); +} + +/* Verifies x509, dates aside, with a CA the application loaded into the cert + * manager, which goes in *issuer when it has its DER and its key signed + * x509. Returns 0 or the verify error. An internal error is kept in *err. */ +static int X509StoreCmVerify(WOLFSSL_CERT_MANAGER* cm, WOLFSSL_X509* x509, + WOLFSSL_X509** issuer, int* err) +{ + int ret; + WC_DECLARE_VAR(cert, DecodedCert, 1, 0); + + WC_ALLOC_VAR_EX(cert, DecodedCert, 1, cm->heap, DYNAMIC_TYPE_DCERT, + return X509StoreKeepErr(err, MEMORY_E)); + InitDecodedCert(cert, x509->derCert->buffer, x509->derCert->length, + cm->heap); + ret = ParseCertRelative(cert, CERT_TYPE, VERIFY_SKIP_DATE, cm, NULL); + if (!X509StoreVerifyResult(ret)) { + (void)X509StoreKeepErr(err, ret); + } + /* The CA verified it: as OpenSSL, its name constraints are checked on + * the chain */ + if (ret == WC_NO_ERR_TRACE(ASN_NAME_INVALID_E)) { + ret = 0; + } + if (ret == 0 && !X509StoreCmCaLoaded(cert->ca)) { + ret = WC_NO_ERR_TRACE(ASN_NO_SIGNER_E); + } +#ifdef WOLFSSL_SIGNER_DER_CERT + /* A signer restored from a cert cache has no DER */ + if (ret == 0 && issuer != NULL && cert->ca->derCert != NULL) { + WOLFSSL_X509* ca = NULL; + + if (wolfSSL_X509_d2i_ex(&ca, cert->ca->derCert->buffer, + (int)cert->ca->derCert->length, cm->heap) == NULL) { + (void)X509StoreKeepErr(err, WOLFSSL_FATAL_ERROR); + } + else if (X509StoreKeySigned(ca, x509, err)) { + *issuer = ca; + ca = NULL; + } + wolfSSL_X509_free(ca); + } +#else + (void)issuer; +#endif + FreeDecodedCert(cert); + WC_FREE_VAR_EX(cert, cm->heap, DYNAMIC_TYPE_DCERT); + + return ret; +} + +/* Returns 1 if a CA the application loaded into the cert manager verifies + * x509, dates aside, otherwise 0. An internal error is kept in *err. */ +static int X509StoreCmHasIssuer(WOLFSSL_CERT_MANAGER* cm, WOLFSSL_X509* x509, + int* err) +{ + return X509StoreCmVerify(cm, x509, NULL, err) == 0; +} + +/* Returns 1 if x509 is a self-signed CA the application loaded into the cert + * manager of a store that keeps its CAs only there, as an SSL_CTX's store: the + * CA has its key and, when the CA keeps its DER, the same DER. Otherwise 0. + * An internal error is kept in *err. */ +static int X509StoreCmHasCert(WOLFSSL_X509_STORE_CTX* ctx, WOLFSSL_X509* x509, + int* err) +{ + WOLFSSL_CERT_MANAGER* cm = ctx->store->cm; + int ret; + WC_DECLARE_VAR(cert, DecodedCert, 1, 0); + + if (ctx->setTrustedSk != NULL || ctx->store->trusted != NULL || + x509->derCert == NULL) { + return 0; + } + WC_ALLOC_VAR_EX(cert, DecodedCert, 1, cm->heap, DYNAMIC_TYPE_DCERT, + { (void)X509StoreKeepErr(err, MEMORY_E); return 0; }); + InitDecodedCert(cert, x509->derCert->buffer, x509->derCert->length, + cm->heap); + ret = ParseCertRelative(cert, CERT_TYPE, VERIFY_SKIP_DATE, cm, NULL); + if (!X509StoreVerifyResult(ret)) { + (void)X509StoreKeepErr(err, ret); + } + ret = ret == 0 && X509StoreCmCaLoaded(cert->ca); +#ifdef WOLFSSL_SIGNER_DER_CERT + if (ret && cert->ca != NULL && cert->ca->derCert != NULL) { + ret = cert->ca->derCert->length == x509->derCert->length && + XMEMCMP(cert->ca->derCert->buffer, x509->derCert->buffer, + x509->derCert->length) == 0; + } +#endif + FreeDecodedCert(cert); + WC_FREE_VAR_EX(cert, cm->heap, DYNAMIC_TYPE_DCERT); + + return ret; +} + +#if defined(SESSION_CERTS) && defined(KEEP_PEER_CERT) +/* Returns 1 if ca, above x509 on a chain, is the CA the application loaded + * into the cert manager that verifies x509, dates aside: the same cert, by + * its DER. Otherwise 0. */ +static int X509StoreCmIsIssuer(WOLFSSL_CERT_MANAGER* cm, WOLFSSL_X509* ca, + WOLFSSL_X509* x509) +{ + int err = 0; + int ret = 0; + WOLFSSL_X509* issuer = NULL; - /* The trust anchor (top of chain) is not part of the prospective - * certification path (RFC 5280 sec. 6.1): it does not consume path-length - * budget, and the loop below runs from num-2 down to 1 so the anchor is - * never processed as an intermediate. A self-signed anchor that asserts its - * own pathLenConstraint does still bound the path, matching - * ParseCertRelative()'s trust-anchor handling, so seed the budget from - * it. */ - anchor = wolfSSL_sk_X509_value(ctx->chain, num - 1); - if (anchor != NULL && anchor->isCa && anchor->basicConstPlSet) { - maxPathLen = (word32)anchor->pathLength; - haveConstraint = 1; + if (cm == NULL || ca == NULL || x509 == NULL || x509->derCert == NULL) { + return 0; + } + if (X509StoreCmVerify(cm, x509, &issuer, &err) == 0 && err == 0) { + ret = X509DerEquals(issuer, ca); } + wolfSSL_X509_free(issuer); + + return ret; +} +#endif - for (i = num - 2; i >= 1; i--) { - WOLFSSL_X509* cert = wolfSSL_sk_X509_value(ctx->chain, i); - int selfIssued; +/* As OpenSSL's check_chain_extensions(): every cert above the leaf issues + * the one below it, so it must be a CA that may sign certs. num is the + * number of chain certs to check. + * Returns WOLFSSL_SUCCESS, or WOLFSSL_FAILURE when the verify callback does + * not accept an error. */ +static int X509StoreCheckChainCa(WOLFSSL_X509_STORE_CTX* ctx, + WOLFSSL_X509_STORE_CTX_verify_cb verifyCb, + WOLF_STACK_OF(WOLFSSL_X509)* trustedSk, int num) +{ + int i; + + for (i = 1; i < num; i++) { + WOLFSSL_X509* x509 = wolfSSL_sk_X509_value(ctx->chain, i); - if (cert == NULL) + if (x509 == NULL || X509StoreNonCaAllowed(ctx, x509, trustedSk) || + X509StoreCertIsCa(ctx, x509, i == num - 1)) { continue; + } + ctx->current_cert = x509; + SetupStoreCtxError_ex(ctx, WOLFSSL_X509_V_ERR_INVALID_CA, i); + if (verifyCb == NULL || verifyCb(0, ctx) != 1) { + return WOLFSSL_FAILURE; + } + } + return WOLFSSL_SUCCESS; +} - selfIssued = - (wolfSSL_X509_NAME_cmp(&cert->issuer, &cert->subject) == 0); - - /* RFC 5280 sec. 6.1.4 (l): a non-self-issued *CA* certificate consumes - * one unit of the issuer's remaining path length budget. Gate on isCa - * to match ParseCertRelative() (wolfcrypt/src/asn.c) and the (m) step - * below, so a non-CA intermediate tolerated via verify_cb does not - * trigger a false PATH_LENGTH_EXCEEDED. Only meaningful once a CA above - * has asserted a constraint (haveConstraint). */ - if (!selfIssued && cert->isCa && haveConstraint) { - if (maxPathLen == 0) { - SetupStoreCtxError_ex(ctx, - WOLFSSL_X509_V_ERR_PATH_LENGTH_EXCEEDED, i); - /* Allow an application verify callback to override, matching - * the INVALID_CA handling in wolfSSL_X509_verify_cert(). */ - if (verifyCb != NULL && verifyCb(0, ctx) == 1) { - /* Overridden: keep walking without decrementing (budget is - * already exhausted). */ - continue; - } - return WOLFSSL_FAILURE; +/* As OpenSSL's find_issuer(), picks from certs a cert that issued x, its + * names and key ids matching: the first one valid at the verification time, + * else the one that expires last, as *best when it expires later. Its key + * is not checked. With skipChain, certs on the chain are not picked. + * Failing closed, a cert without its DER is not picked, so that every cert + * on the chain has it and is checked. + * Returns 1 when *best is valid at the verification time, else 0. */ +static int X509StorePickIssuer(WOLFSSL_X509_STORE_CTX* ctx, + WOLF_STACK_OF(WOLFSSL_X509)* certs, WOLFSSL_X509* x, int skipChain, + WOLFSSL_X509** best) +{ + int i; + + for (i = 0; i < wolfSSL_sk_X509_num(certs); i++) { + WOLFSSL_X509* ca = wolfSSL_sk_X509_value(certs, i); + + if (ca == NULL || ca->derCert == NULL || (skipChain && + X509StoreCertInStack(ctx->chain, ca)) || + !X509StoreIssued(ca, x)) { + continue; + } + #ifndef NO_ASN_TIME + if (X509StoreCheckCertDate(ctx, ca) != WOLFSSL_SUCCESS) { + if (*best == NULL || wolfSSL_ASN1_TIME_compare(&ca->notAfter, + &(*best)->notAfter) > 0) { + *best = ca; } - maxPathLen--; + continue; } + #endif + *best = ca; + return 1; + } + return 0; +} + +/* Returns the trusted cert that issued x, as OpenSSL's + * X509_STORE_CTX_get1_issuer() picks it: certs on the chain included. As in + * OpenSSL, a trusted stack replaces the store's trusted certs. */ +static WOLFSSL_X509* X509StoreFindTrusted(WOLFSSL_X509_STORE_CTX* ctx, + WOLFSSL_X509* x) +{ + WOLFSSL_X509* ca = NULL; + + (void)X509StorePickIssuer(ctx, (ctx->setTrustedSk != NULL) ? + ctx->setTrustedSk : ctx->store->added, x, 0, &ca); + return ca; +} + +/* As OpenSSL looks for an alternate chain: the highest untrusted cert below + * the top untrusted one, the numUntrusted certs from the leaf being + * untrusted, that a trusted cert or a CA of the cert manager issued. + * Returns its depth, or -1 when there is none. *alt is that trusted cert, + * NULL for a CA of the cert manager. An internal error is kept in *err. */ +static int X509StoreTrustedAlt(WOLFSSL_X509_STORE_CTX* ctx, int numUntrusted, + WOLFSSL_X509** alt, int* err) +{ + int i; + + for (i = numUntrusted - 2; i >= 0; i--) { + WOLFSSL_X509* x = wolfSSL_sk_X509_value(ctx->chain, i); - /* RFC 5280 sec. 6.1.4 (m): tighten the budget with this CA's own - * pathLenConstraint, if present. The first constraint encountered seeds - * the budget; subsequent ones only ever lower it. */ - if (cert->isCa && cert->basicConstPlSet && - (!haveConstraint || (word32)cert->pathLength < maxPathLen)) { - maxPathLen = (word32)cert->pathLength; - haveConstraint = 1; + *alt = X509StoreFindTrusted(ctx, x); + if (*alt != NULL || (ctx->setTrustedSk == NULL && + X509StoreCmHasIssuer(ctx->store->cm, x, err))) { + return i; } } + *alt = NULL; + return -1; +} +/* As OpenSSL, an internal error is not a verify error: the verify callback + * is not asked and the verification fails, with X509_V_ERR_OUT_OF_MEM when + * memory ran out, else X509_V_ERR_UNSPECIFIED. + * Returns WOLFSSL_FAILURE. */ +static int X509StoreFatal(WOLFSSL_X509_STORE_CTX* ctx, int err) +{ + ctx->error = (err == WC_NO_ERR_TRACE(MEMORY_E) || + err == WC_NO_ERR_TRACE(MEMORY_ERROR)) ? + WOLFSSL_X509_V_ERR_OUT_OF_MEM : WOLFSSL_X509_V_ERR_UNSPECIFIED; + return WOLFSSL_FAILURE; +} + +/* Records err for x at depth and asks the verify callback. + * Returns 1 when the callback accepts the error. */ +static int X509StoreReport(WOLFSSL_X509_STORE_CTX* ctx, + WOLFSSL_X509_STORE_CTX_verify_cb verifyCb, WOLFSSL_X509* x, int err, + int depth) +{ + ctx->current_cert = x; + SetupStoreCtxError_ex(ctx, err, depth); + return verifyCb != NULL && verifyCb(0, ctx) == 1; +} + +/* As OpenSSL's check_auth_level(): the key of each issuer, the trust anchor + * included, must meet the cert manager's minimum CA key size. + * Returns WOLFSSL_SUCCESS, or WOLFSSL_FAILURE when the verify callback does + * not accept an error. */ +static int X509StoreCheckChainKeys(WOLFSSL_X509_STORE_CTX* ctx, + WOLFSSL_X509_STORE_CTX_verify_cb verifyCb, int num) +{ + int i; + + for (i = 1; i < num; i++) { + WOLFSSL_X509* x509 = wolfSSL_sk_X509_value(ctx->chain, i); + + if (x509 != NULL && CheckCAKeySize(ctx->store->cm, + (word32)x509->pubKeyOID, x509->pubKey.buffer, + x509->pubKey.length) != 0 && + !X509StoreReport(ctx, verifyCb, x509, + WOLFSSL_X509_V_ERR_CA_KEY_TOO_SMALL, i)) { + return WOLFSSL_FAILURE; + } + } return WOLFSSL_SUCCESS; } -/* Returns 1 if X509_V_FLAG_PARTIAL_CHAIN is set on ctx or on its store, - * otherwise 0. ctx and ctx->store must be non-NULL. */ -static int X509StoreCertPartialChainEnabled(WOLFSSL_X509_STORE_CTX* ctx) +/* As OpenSSL's internal_verify(), top down. sigFail holds the certs whose + * issuer did not sign them. Returns WOLFSSL_SUCCESS or WOLFSSL_FAILURE. */ +static int X509StoreCheckChainCerts(WOLFSSL_X509_STORE_CTX* ctx, + WOLFSSL_X509_STORE_CTX_verify_cb verifyCb, + WOLF_STACK_OF(WOLFSSL_X509)* trustedSk, int num, int noIssuer, + WOLF_STACK_OF(WOLFSSL_X509)* sigFail) { - /* PARTIAL_CHAIN lets any trusted cert end the path */ - if (ctx->flags & WOLFSSL_PARTIAL_CHAIN) { - return 1; + int i = num - 1; + + if (noIssuer && !X509StoreCertPartialChainEnabled(ctx)) { + if (i > 0) { + i--; + } + else if (!X509StoreReport(ctx, verifyCb, + wolfSSL_sk_X509_value(ctx->chain, 0), + WOLFSSL_X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE, 0)) { + return WOLFSSL_FAILURE; + } } - if (ctx->store->param != NULL && - (ctx->store->param->flags & WOLFSSL_PARTIAL_CHAIN)) { - return 1; + for (; i >= 0; i--) { + WOLFSSL_X509* x509 = wolfSSL_sk_X509_value(ctx->chain, i); + WOLFSSL_X509* up = (i + 1 < num) ? + wolfSSL_sk_X509_value(ctx->chain, i + 1) : NULL; + #ifndef NO_ASN_TIME + int ret; + #endif + + /* RFC 5280 6.1.4 (n): the issuer's keyUsage must allow keyCertSign */ + if (up != NULL && up->keyUsageSet && + (up->keyUsage & KEYUSE_KEY_CERT_SIGN) == 0 && + !X509StoreNonCaAllowed(ctx, up, trustedSk) && + !X509StoreReport(ctx, verifyCb, up, + WOLFSSL_X509_V_ERR_KEYUSAGE_NO_CERTSIGN, i + 1)) { + return WOLFSSL_FAILURE; + } + if (X509StoreCertInStack(sigFail, x509) && + !X509StoreReport(ctx, verifyCb, x509, + WOLFSSL_X509_V_ERR_CERT_SIGNATURE_FAILURE, i)) { + return WOLFSSL_FAILURE; + } + #ifndef NO_ASN_TIME + + if (x509 != NULL) { + ret = X509StoreCheckCertDate(ctx, x509); + if (ret != WOLFSSL_SUCCESS && + !X509StoreReport(ctx, verifyCb, x509, ret, i)) { + return WOLFSSL_FAILURE; + } + } + #endif + ctx->current_cert = x509; + ctx->error_depth = i; + if (verifyCb != NULL && verifyCb(1, ctx) != 1) { + return WOLFSSL_FAILURE; + } + } + return WOLFSSL_SUCCESS; +} + +#ifndef IGNORE_NAME_CONSTRAINTS +/* As OpenSSL's check_name_constraints(): the names of each cert, but a + * self-issued one above the leaf, meet the name constraints of every cert + * above it on the chain, the anchor included. + * Returns WOLFSSL_SUCCESS, or WOLFSSL_FAILURE when the verify callback does + * not accept an error. */ +static int X509StoreCheckChainNames(WOLFSSL_X509_STORE_CTX* ctx, + WOLFSSL_X509_STORE_CTX_verify_cb verifyCb, int num) +{ + int i; + int j; + int ret; + + for (i = num - 1; i >= 0; i--) { + WOLFSSL_X509* x509 = wolfSSL_sk_X509_value(ctx->chain, i); + + if (x509 == NULL || (i > 0 && + wolfSSL_X509_NAME_cmp(&x509->issuer, &x509->subject) == 0)) { + continue; + } + for (j = num - 1; j > i; j--) { + WOLFSSL_X509* ca = wolfSSL_sk_X509_value(ctx->chain, j); + int violation = 0; + + if (ca == NULL || (ca->permittedNames == NULL && + ca->excludedNames == NULL && !ca->nameConstraintCrit)) { + continue; + } + ret = CheckCertNameConstraints(ca->derCert->buffer, + ca->derCert->length, x509->derCert->buffer, + x509->derCert->length, i == 0, ctx->heap, &violation); + if (ret != 0) { + return X509StoreFatal(ctx, ret); + } + if (violation != 0 && !X509StoreReport(ctx, verifyCb, x509, + (violation == NC_VIOLATION_EXCLUDED) ? + WOLFSSL_X509_V_ERR_EXCLUDED_VIOLATION : + (violation == NC_VIOLATION_PERMITTED) ? + WOLFSSL_X509_V_ERR_PERMITTED_VIOLATION : + WOLFSSL_X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE, i)) { + return WOLFSSL_FAILURE; + } + } + } + return WOLFSSL_SUCCESS; +} +#endif /* IGNORE_NAME_CONSTRAINTS */ + +#ifdef HAVE_CRL +/* As OpenSSL's get_crl_delta(), checks the cert with a CRL of up, its issuer, + * of the ctx, else of the store. staleOk and anyKeyUsage accept one out of + * date or without cRLSign. Returns WOLFSSL_SUCCESS or the CRL error. */ +static int X509StoreCheckCertCrls(WOLFSSL_X509_STORE_CTX* ctx, + WOLFSSL_X509* up, int staleOk, int anyKeyUsage) +{ + int ret = WC_NO_ERR_TRACE(CRL_MISSING); + Signer issuer; +#ifndef NO_ASN_TIME + time_t t; + const time_t* checkTime = (!staleOk && X509StoreCheckTime(ctx, &t)) ? + &t : NULL; +#else + const time_t* checkTime = NULL; + + (void)staleOk; +#endif + + XMEMSET(&issuer, 0, sizeof(issuer)); + issuer.publicKey = up->pubKey.buffer; + issuer.pubKeySize = up->pubKey.length; + issuer.keyOID = (word32)up->pubKeyOID; + /* Without the extension any key usage is allowed */ + issuer.keyUsage = (up->keyUsageSet && !anyKeyUsage) ? + up->keyUsage : 0xFFFF; +#ifndef NO_SKID + /* Its subject key id, if any, picks out its CRLs */ + if (up->subjKeyIdSet && up->subjKeyId != NULL && + GetHashId(up->subjKeyId, (int)up->subjKeyIdSz, + issuer.subjectKeyIdHash, + HashIdAlg((word32)up->sigOID)) != 0) { + XMEMSET(issuer.subjectKeyIdHash, 0, + sizeof(issuer.subjectKeyIdHash)); + } +#endif + if (ctx->crls != NULL) { + ret = X509StoreCheckCtxCrls(ctx, &issuer, checkTime); + } + if (ret == WC_NO_ERR_TRACE(CRL_MISSING) && ctx->store->cm->crl != NULL) { + ret = X509StoreCheckStoreCrl(ctx, &issuer, checkTime); + } + return ret; +} +#endif /* HAVE_CRL */ + +/* As OpenSSL's check_revocation(): the leaf, or every cert with check-all. + * Check-all of the cert manager, as TLS, leaves the trust anchor out. + * Returns WOLFSSL_SUCCESS, or WOLFSSL_FAILURE when the verify callback does + * not accept an error. */ +static int X509StoreCheckChainCrls(WOLFSSL_X509_STORE_CTX* ctx, + WOLFSSL_X509_STORE_CTX_verify_cb verifyCb, int num, int noIssuer) +{ + unsigned long flags = (ctx->param != NULL) ? ctx->param->flags : 0; +#ifdef HAVE_CRL + WOLFSSL_CERT_MANAGER* cm = ctx->store->cm; + /* Enabled on the cert manager, or as OpenSSL by the verify param */ + int check = cm->crlEnabled || + (flags & WOLFSSL_X509_V_FLAG_CRL_CHECK) != 0; + int checkAll = (cm->crlEnabled && cm->crlCheckAll) || + (flags & WOLFSSL_X509_V_FLAG_CRL_CHECK_ALL) != 0; +#else + int check = (flags & WOLFSSL_X509_V_FLAG_CRL_CHECK) != 0; + int checkAll = (flags & WOLFSSL_X509_V_FLAG_CRL_CHECK_ALL) != 0; +#endif + int i; + int ret; + + for (i = 0; check && (i == 0 || checkAll) && i < num; i++) { + WOLFSSL_X509* x509 = wolfSSL_sk_X509_value(ctx->chain, i); + WOLFSSL_X509* up = NULL; + + if (i < num - 1) { + up = wolfSSL_sk_X509_value(ctx->chain, i + 1); + } + else if (!noIssuer && i > 0 && + (flags & WOLFSSL_X509_V_FLAG_CRL_CHECK_ALL) == 0) { + break; + } + else if (!noIssuer && X509StoreIssued(x509, x509)) { + /* As OpenSSL, a self-issued top cert has its own CRLs. Another + * has none. */ + up = x509; + } + ctx->current_cert = x509; + ret = WC_NO_ERR_TRACE(CRL_MISSING); + #ifdef HAVE_CRL + if (up != NULL) { + int anyKeyUsage = 0; + + ret = X509StoreCheckCertCrls(ctx, up, 0, 0); + /* As OpenSSL, a CRL of an issuer without cRLSign is reported. + * Once that is accepted, the CRL is used. */ + if (ret == WC_NO_ERR_TRACE(ASN_CRL_NO_SIGNER_E)) { + if (!X509StoreReport(ctx, verifyCb, ctx->current_cert, + WOLFSSL_X509_V_ERR_KEYUSAGE_NO_CRL_SIGN, i)) { + return WOLFSSL_FAILURE; + } + anyKeyUsage = 1; + ret = X509StoreCheckCertCrls(ctx, up, 0, anyKeyUsage); + } + /* As OpenSSL, once its error is accepted a CRL out of date is + * used */ + if (ret == WC_NO_ERR_TRACE(ASN_BEFORE_DATE_E) || + ret == WC_NO_ERR_TRACE(CRL_CERT_DATE_ERR)) { + if (!X509StoreReport(ctx, verifyCb, ctx->current_cert, + (ret == WC_NO_ERR_TRACE(ASN_BEFORE_DATE_E)) ? + WOLFSSL_X509_V_ERR_CRL_NOT_YET_VALID : + WOLFSSL_X509_V_ERR_CRL_HAS_EXPIRED, i)) { + return WOLFSSL_FAILURE; + } + ret = X509StoreCheckCertCrls(ctx, up, 1, anyKeyUsage); + } + } + #else + (void)up; + #endif + /* Any other error is internal */ + if (ret != WOLFSSL_SUCCESS && ret != WC_NO_ERR_TRACE(CRL_MISSING) && + ret != WC_NO_ERR_TRACE(CRL_CERT_REVOKED) && + ret != WC_NO_ERR_TRACE(ASN_CRL_CONFIRM_E)) { + return X509StoreFatal(ctx, ret); + } + /* A CRL that does not verify is not used. Its entries are not + * checked, so failing closed its error is final. */ + if (ret != WOLFSSL_SUCCESS && + (!X509StoreReport(ctx, verifyCb, ctx->current_cert, ret, i) || + ret == WC_NO_ERR_TRACE(ASN_CRL_CONFIRM_E))) { + return WOLFSSL_FAILURE; + } } - return 0; + return WOLFSSL_SUCCESS; } /* Verifies certificate chain using WOLFSSL_X509_STORE_CTX * returns 1 on success or <= 0 on failure. - */ + * Builds and checks the chain as OpenSSL's build_chain() and verify_chain(), + * failing closed: the first issuer found is final, and an alternate chain is + * taken only when its trusted cert is the same cert. A CA of the cert + * manager is trusted and, as in the handshake, needs no issuer there. */ int wolfSSL_X509_verify_cert(WOLFSSL_X509_STORE_CTX* ctx) { - int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE); - int done = 0; - int depth = 0; - int origDepth = 0; - int cbRejected = 0; - WOLFSSL_X509 *issuer = NULL; - WOLFSSL_X509 *orig = NULL; - WOLF_STACK_OF(WOLFSSL_X509)* callerTrusted = NULL; - WOLF_STACK_OF(WOLFSSL_X509)* certsToUse = NULL; - WOLF_STACK_OF(WOLFSSL_X509)* failedCerts = NULL; - WOLF_STACK_OF(WOLFSSL_X509)* origTrustedSk = NULL; + int ret = WOLFSSL_SUCCESS; + int depth; + int num; + int trustedFirst; + int trustedSeen = 0; + int fromTrusted = 0; + int numUntrusted = 1; + int noIssuer = 0; + int cmRet; + int fromCm = 0; + int err = 0; + WOLF_STACK_OF(WOLFSSL_X509)* sigFail = NULL; + WOLFSSL_X509* x; + WOLFSSL_X509* issuer; + WOLFSSL_X509* cmIssuer = NULL; + WOLFSSL_X509* orig; + WOLF_STACK_OF(WOLFSSL_X509)* trustedSk; WOLFSSL_X509_STORE_CTX_verify_cb verifyCb; + WOLFSSL_ENTER("wolfSSL_X509_verify_cert"); - if (ctx == NULL || ctx->store == NULL || ctx->store->cm == NULL - || ctx->current_cert == NULL || ctx->current_cert->derCert == NULL) { + if (ctx == NULL) { + return WOLFSSL_FATAL_ERROR; + } + if (ctx->store == NULL || ctx->store->cm == NULL || + ctx->current_cert == NULL || ctx->current_cert->derCert == NULL) { + ctx->error = WOLFSSL_X509_V_ERR_UNSPECIFIED; return WOLFSSL_FATAL_ERROR; } verifyCb = X509StoreGetVerifyCb(ctx); - - /* Chain building mutates the working stack: caller-supplied intermediates - * are appended and X509VerifyCertSetupRetry moves failed certs out of it. - * store->certs is shared by every connection using this store and - * setTrustedSk is owned by the caller, so build a per-verification shallow - * copy (certsToUse) and leave both untouched. This removes the write-side - * corruption a concurrent verification used to inflict on those stacks, but - * it does NOT make concurrent use of one X509_STORE safe: the dup is itself - * an unlocked read, and store->trusted is still walked live (see the NOTE - * below). A single store must not be shared across threads that verify - * concurrently. - * - * The X509_V_FLAG_PARTIAL_CHAIN fallback needs the set of certs that were - * caller-trusted before any intermediates were injected. Snapshot it from - * certsToUse - the private copy, taken before addAllButSelfSigned() injects - * intermediates - rather than walking the shared stack a second time, so - * the two snapshots are provably identical. Both dups hold borrowed - * references and are shallow-freed at exit. */ - callerTrusted = ctx->store->certs; - if (ctx->setTrustedSk != NULL) { - callerTrusted = ctx->setTrustedSk; - } - - if (callerTrusted != NULL) { - certsToUse = wolfSSL_shallow_sk_dup(callerTrusted); - if (certsToUse != NULL) - origTrustedSk = wolfSSL_shallow_sk_dup(certsToUse); - if (origTrustedSk == NULL) { - ret = WOLFSSL_FAILURE; - goto exit; - } - } - else { - certsToUse = wolfSSL_sk_X509_new_null(); - } - if (certsToUse == NULL) { - ret = WOLFSSL_FAILURE; - goto exit; - } - /* Add the intermediates provided on init to the list of untrusted - * intermediates to be used. */ - ret = addAllButSelfSigned(certsToUse, ctx->ctxIntermediates, NULL); - if (ret != WOLFSSL_SUCCESS) { - goto exit; - } + /* Without a param, the default of init */ + trustedFirst = ctx->param == NULL || + (ctx->param->flags & WOLFSSL_TRUSTED_FIRST) != 0; + trustedSk = (ctx->setTrustedSk != NULL) ? ctx->setTrustedSk : + ctx->store->certs; + depth = (ctx->param != NULL) ? ctx->param->depth : + WOLFSSL_X509_STORE_DEFAULT_MAX_DEPTH; + orig = ctx->current_cert; if (ctx->chain != NULL) { wolfSSL_sk_X509_pop_free(ctx->chain, NULL); } ctx->chain = wolfSSL_sk_X509_new_null(); if (ctx->chain == NULL) { - ret = WOLFSSL_FAILURE; + err = MEMORY_E; goto exit; } - - failedCerts = wolfSSL_sk_X509_new_null(); - if (!failedCerts) { - /* Fail closed: ret is still WOLFSSL_SUCCESS from the checks above, so - * an unset error here would make the function report a verified chain - * after an allocation failure. */ - ret = WOLFSSL_FAILURE; + x = orig; + if (X509StoreKeepErr(&err, X509StoreChainPush(ctx->chain, x)) != + WOLFSSL_SUCCESS) { goto exit; } - /* An explicit negative depth leaves no room for any chain, - * not even a trusted leaf: reject before building one. */ - if (ctx->depth < 0) { - SetupStoreCtxError_ex(ctx, WOLFSSL_X509_V_ERR_CERT_CHAIN_TOO_LONG, 0); + /* A negative depth, unset included, leaves no room for any chain. As + * OpenSSL, the callback is told; failing closed, the error is final. */ + if (depth < 0) { + (void)X509StoreReport(ctx, verifyCb, x, + WOLFSSL_X509_V_ERR_CERT_CHAIN_TOO_LONG, 0); ret = WOLFSSL_FAILURE; goto exit; } - /* The struct is public, so also honor a positive depth written directly - * (no setter). Clamp so the + 1 can't overflow. */ - depth = (ctx->depth < INT_MAX) ? ctx->depth + 1 : INT_MAX; + for (;;) { + /* As OpenSSL, self-signed by names and key ids, key not checked */ + int selfSigned = X509StoreIssued(x, x); + /* As in OpenSSL, a cert found among the trusted certs, or a + * self-signed cert that is the trusted cert picked as its issuer */ + int trusted = fromTrusted || (selfSigned && + X509DerEquals(X509StoreFindTrusted(ctx, x), x)); + WOLFSSL_X509* alt = NULL; + int altDepth = -1; - orig = ctx->current_cert; - origDepth = depth; - while(done == 0 && depth > 0) { - issuer = NULL; + num = wolfSSL_sk_X509_num(ctx->chain); + trustedSeen |= trusted; + /* As in OpenSSL, the self-signature of a trusted cert is not + * checked */ + if (trusted && (selfSigned || X509StoreCertPartialChainEnabled(ctx))) { + break; + } + /* A self-signed CA of the cert manager is a trust anchor */ + if (selfSigned && X509StoreCmHasCert(ctx, x, &err)) { + break; + } - /* Try to find an untrusted issuer first. Skip certs already on the - * path so an issuer cycle (A <- B <- A) ends the search instead of - * running until the depth budget is spent. current_cert is not on - * ctx->chain yet, so a self-issued terminus is still found. */ - ret = X509StoreGetIssuerSkip(&issuer, certsToUse, - ctx->current_cert, ctx->chain); - if (ret == WOLFSSL_SUCCESS) { - if (ctx->current_cert == issuer) { - X509StoreChainPush(ctx->chain, ctx->current_cert); - break; + issuer = NULL; + /* 1 until the cert manager is asked, once, for x */ + cmRet = 1; + fromTrusted = 0; + if (!selfSigned) { + /* The cert manager's CAs are trusted, searched after the trusted + * certs */ + if (trustedSeen || trustedFirst) { + issuer = X509StoreFindTrusted(ctx, x); + fromTrusted = issuer != NULL; + if (issuer == NULL && ctx->setTrustedSk == NULL) { + cmRet = X509StoreCmVerify(ctx->store->cm, x, &cmIssuer, + &err); + } } - - /* We found our issuer in the non-trusted cert list, add it - * to the CM and verify the current cert against it */ - #ifndef WOLFSSL_X509_STORE_ALLOW_NON_CA_INTERMEDIATE - /* RFC 5280 4.2.1.9: reject non-CA issuer. verify_cb may - * suppress the INVALID_CA error to keep building the chain, - * but the leaf signature must still be verified against the - * issuer below - never skip X509StoreVerifyCert. */ - if (!issuer->isCa) { - /* error depth is current depth + 1 */ - SetupStoreCtxError_ex(ctx, WOLFSSL_X509_V_ERR_INVALID_CA, - (ctx->chain) ? (int)(ctx->chain->num + 1) : 1); - if (verifyCb != NULL) { - ret = verifyCb(0, ctx); - if (ret != WOLFSSL_SUCCESS) { - ret = WOLFSSL_FAILURE; - goto exit; - } + if (issuer == NULL && cmRet != 0 && !trustedSeen) { + (void)X509StorePickIssuer(ctx, ctx->ctxIntermediates, x, 1, + &issuer); + if (issuer != NULL) { + numUntrusted++; } - else { - ret = WOLFSSL_FAILURE; - goto exit; + else if (!trustedFirst) { + issuer = X509StoreFindTrusted(ctx, x); + fromTrusted = issuer != NULL; + if (issuer == NULL && ctx->setTrustedSk == NULL) { + cmRet = X509StoreCmVerify(ctx->store->cm, x, + &cmIssuer, &err); + } } } - #endif - /* The CertManager picks the signer itself, by key id or name, from - * everything it holds. Drop the intermediates loaded for the links - * below and for abandoned candidates, so that issuer is the only - * untrusted signer this link can verify against. Otherwise a cert - * signed by one of those would pass here while the path goes on - * with issuer, a same-named cert that never signed it. */ - if (wolfSSL_CertManagerUnloadTempIntermediateCerts(ctx->store->cm) - != WOLFSSL_SUCCESS) { - ret = WOLFSSL_FATAL_ERROR; - goto exit; - } - /* NOTE: this loads the caller-supplied intermediate into the - * shared ctx->store->cm as a WOLFSSL_TEMP_CA, and the unload paths - * drop *all* WOLFSSL_TEMP_CA signers in that CertManager, not only - * the ones added here. This copy removes the working-stack race, - * but two threads running X509_verify_cert() against the same - * X509_STORE still contend on store->cm. Concurrent verification - * on a single shared store therefore remains unsupported; callers - * needing it must use a store per thread. */ - ret = X509StoreAddCa(ctx->store, issuer, WOLFSSL_TEMP_CA); - if (ret != WOLFSSL_SUCCESS) { - X509VerifyCertSetupRetry(ctx, certsToUse, failedCerts, - &depth, origDepth); - continue; - } - ret = X509StoreVerifyCert(ctx, &cbRejected, verifyCb); - if (cbRejected) { - /* The application vetoed this certificate. Stop instead of - * looking for another issuer: the decision is the - * application's and retrying would only ask it again. */ - ret = WOLFSSL_FAILURE; - goto exit; - } - if (ret != WOLFSSL_SUCCESS) { - X509VerifyCertSetupRetry(ctx, certsToUse, failedCerts, - &depth, origDepth); - continue; + } + /* wolfSSL trusts a CA of the cert manager without an issuer there */ + if (err == 0 && fromCm && issuer == NULL && cmRet != 0) { + if (cmRet == 1) { + cmRet = X509StoreCmVerify(ctx->store->cm, x, NULL, &err); } - /* Add it to the current chain and look at the issuer cert next */ - X509StoreChainPush(ctx->chain, ctx->current_cert); - ctx->current_cert = issuer; - } - else if (ret == WC_NO_ERR_TRACE(WOLFSSL_FAILURE)) { - /* Could not find in untrusted list, only place left is - * a trusted CA in the CM. Drop any caller-supplied untrusted - * intermediates that were temporarily loaded into the CertManager - * to authenticate child certificates, so the current certificate - * must verify against a genuinely trusted CA. They must not be - * allowed to anchor the path: otherwise a chain that never reaches - * a configured trust anchor (or whose intermediate signature is - * invalid) would be accepted. */ - if (wolfSSL_CertManagerUnloadTempIntermediateCerts(ctx->store->cm) - != WOLFSSL_SUCCESS) { - /* Could not guarantee the temporary intermediates were - * dropped; fail closed rather than risk verifying the current - * certificate against one. */ - ret = WOLFSSL_FATAL_ERROR; - goto exit; + if (cmRet == WC_NO_ERR_TRACE(ASN_NO_SIGNER_E) || + cmRet == WC_NO_ERR_TRACE(ASN_SELF_SIGNED_E)) { + break; } - ret = X509StoreVerifyCert(ctx, &cbRejected, verifyCb); - if (cbRejected) { - /* An application veto is final. The partial-chain fallback - * below must not accept the chain here and clear ctx->error: - * the certificate verified, the application rejected it. */ - ret = WOLFSSL_FAILURE; + } + if (err != 0) { + goto exit; + } + /* The leaf and the trust anchor do not count against the depth */ + if (!selfSigned && num - 1 > depth) { + (void)X509StoreReport(ctx, verifyCb, x, + WOLFSSL_X509_V_ERR_CERT_CHAIN_TOO_LONG, num - 1); + ret = WOLFSSL_FAILURE; + goto exit; + } + /* A CA of the cert manager is a trusted cert. Without its DER it + * cannot go on the chain: fail closed as without an issuer. */ + fromCm = cmIssuer != NULL; + if (fromCm) { + x = cmIssuer; + cmIssuer = NULL; + (void)X509StoreKeepErr(&err, X509StoreChainPush(ctx->chain, x)); + /* The chain holds x unless err */ + wolfSSL_X509_free(x); + if (err != 0) { goto exit; } - if (ret != WOLFSSL_SUCCESS) { - /* WOLFSSL_PARTIAL_CHAIN may only terminate the chain at a - * certificate the caller actually trusts, so verify that - * ctx->current_cert is itself in the original trust set. */ - if (X509StoreCertPartialChainEnabled(ctx) && - X509StoreCertIsTrusted(ctx->store, ctx->current_cert, - origTrustedSk)) { - X509StoreChainPush(ctx->chain, ctx->current_cert); - /* Clear error set by the failed X509StoreVerifyCert - * attempt; the partial-chain fallback accepted the - * chain at a caller-trusted certificate. */ - ctx->error = 0; - ret = WOLFSSL_SUCCESS; - /* The caller-trusted certificate terminates the path: - * it is the anchor, so stop here rather than falling - * through to the "finish building the chain" push below, - * which would add ctx->current_cert to ctx->chain a - * second time. Mirrors the self-issued terminus break - * above; the depth>0/done==0 success path accepts it. */ - break; - } else { - X509VerifyCertSetupRetry(ctx, certsToUse, failedCerts, - &depth, origDepth); - continue; - } - } - - /* Cert verified, finish building the chain */ - X509StoreChainPush(ctx->chain, ctx->current_cert); - issuer = NULL; - #ifdef WOLFSSL_SIGNER_DER_CERT - x509GetIssuerFromCM(&issuer, ctx->store->cm, ctx->current_cert); - if (issuer != NULL && ctx->owned != NULL) { - wolfSSL_sk_X509_push(ctx->owned, issuer); - } - #else - /* A candidate that already failed verification (moved to - * failedCerts by the retry path) must not terminate the reported - * chain. setTrustedSk / store->trusted are searched by name+AKID, - * not by signature, and setTrustedSk is no longer pruned during - * chain building, so a same-subject cert that was tried and - * rejected can match here. Skip those entries and keep scanning so - * a genuine anchor further down the stack is still found. */ - if (ctx->setTrustedSk == NULL) { - X509StoreGetIssuerSkip(&issuer, - ctx->store->trusted, ctx->current_cert, failedCerts); - } - else { - X509StoreGetIssuerSkip(&issuer, - ctx->setTrustedSk, ctx->current_cert, failedCerts); - } - #endif - if (issuer != NULL) { - X509StoreChainPush(ctx->chain, issuer); - } - - done = 1; + fromTrusted = 1; + continue; } - else { + /* OpenSSL takes a trusted issuer on the chain again, until the chain + * is too long */ + if (issuer != NULL && X509StoreCertInStack(ctx->chain, issuer)) { + (void)X509StoreReport(ctx, verifyCb, x, + WOLFSSL_X509_V_ERR_CERT_CHAIN_TOO_LONG, num - 1); + ret = WOLFSSL_FAILURE; goto exit; } - - depth--; - } - - /* Success requires the path to have reached a configured trust anchor - * (done == 1), to have terminated at a caller-trusted self-signed - * certificate via the break above (done == 0 with depth still > 0), or - * to have spent its depth budget exactly on a trust anchor (below). A - * loop that ran out of its depth budget (depth <= 0) without completing - * must fail with CERT_CHAIN_TOO_LONG unless the cert it stopped on is - * caller-trusted and either self-issued or accepted by - * X509_V_FLAG_PARTIAL_CHAIN: the trust anchor never counts against depth. - * ret may still be WOLFSSL_SUCCESS from the last link, so it cannot be - * relied on here. */ - if (ret == WOLFSSL_SUCCESS && done == 0 && depth <= 0) { - int anchorEndsPath = 0; - - /* A trusted anchor from certsToUse is not an intermediate, so accept - * it here if it ends the path instead of counting it against depth. */ - if (X509StoreCertIsTrusted(ctx->store, ctx->current_cert, - origTrustedSk)) { - /* self-issued anchor: ends the path without a verify */ - if (wolfSSL_X509_check_issued(ctx->current_cert, - ctx->current_cert) == WOLFSSL_X509_V_OK) { - anchorEndsPath = 1; - } - else if (X509StoreCertPartialChainEnabled(ctx)) { - /* verify the anchor so the verify callback sees it and - * can veto it. */ - if (wolfSSL_CertManagerUnloadTempIntermediateCerts( - ctx->store->cm) != WOLFSSL_SUCCESS) { - ret = WOLFSSL_FATAL_ERROR; - goto exit; - } - ret = X509StoreVerifyCert(ctx, &cbRejected, verifyCb); - if (cbRejected) { - ret = WOLFSSL_FAILURE; - goto exit; + if (issuer == NULL) { + altDepth = X509StoreTrustedAlt(ctx, numUntrusted, &alt, &err); + /* Failing closed, OpenSSL's alternate chain is only taken when + * its trusted cert is the untrusted cert above, the same cert */ + if (altDepth >= 0 && X509DerEquals(alt, + wolfSSL_sk_X509_value(ctx->chain, altDepth + 1))) { + while (wolfSSL_sk_X509_num(ctx->chain) > altDepth + 1) { + wolfSSL_X509_free(wolfSSL_sk_X509_pop(ctx->chain)); } - if (ret != WOLFSSL_SUCCESS) { - /* the partial chain is accepted at a caller-trusted - * cert; clear the error from the failed verify */ - ctx->error = 0; + while (wolfSSL_sk_X509_num(sigFail) > 0 && + !X509StoreCertInStack(ctx->chain, + wolfSSL_sk_X509_value(sigFail, + wolfSSL_sk_X509_num(sigFail) - 1))) { + (void)wolfSSL_sk_X509_pop(sigFail); } - anchorEndsPath = 1; + numUntrusted = altDepth + 1; + issuer = alt; + fromTrusted = 1; } } - - if (anchorEndsPath) { - ret = X509StoreChainPush(ctx->chain, ctx->current_cert); + if (err != 0) { + goto exit; } - else { - SetupStoreCtxError_ex(ctx, WOLFSSL_X509_V_ERR_CERT_CHAIN_TOO_LONG, - wolfSSL_sk_X509_num(ctx->chain)); - ret = WOLFSSL_FAILURE; + /* As OpenSSL's last resort, a trusted leaf ends a partial chain + * without a trusted cert */ + if (issuer == NULL && !trustedSeen && altDepth < 0 && + X509StoreCertPartialChainEnabled(ctx) && + X509StoreCertIsTrusted(X509StoreRoots(ctx), orig, + trustedSk)) { + noIssuer = !selfSigned; + break; + } + if (issuer == NULL && selfSigned) { + if (!X509StoreReport(ctx, verifyCb, x, (num == 1) ? + WOLFSSL_X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT : + WOLFSSL_X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN, num - 1) || + altDepth >= 0) { + ret = WOLFSSL_FAILURE; + goto exit; + } + break; + } + if (issuer == NULL) { + if (!X509StoreReport(ctx, verifyCb, x, trusted ? + WOLFSSL_X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT : + WOLFSSL_X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY, + num - 1) || altDepth >= 0) { + ret = WOLFSSL_FAILURE; + goto exit; + } + noIssuer = 1; + break; + } + x = wolfSSL_sk_X509_value(ctx->chain, + wolfSSL_sk_X509_num(ctx->chain) - 1); + /* Its signature failure is reported with the chain's signatures */ + if (!X509StoreCertInStack(sigFail, x) && + !X509StoreKeySigned(issuer, x, &err) && err == 0 && + ((sigFail == NULL && + (sigFail = wolfSSL_sk_X509_new_null()) == NULL) || + wolfSSL_sk_X509_push(sigFail, x) <= 0)) { + err = MEMORY_E; + } + if (err != 0 || X509StoreKeepErr(&err, + X509StoreChainPush(ctx->chain, issuer)) != WOLFSSL_SUCCESS) { + goto exit; } + x = issuer; } + num = wolfSSL_sk_X509_num(ctx->chain); - /* RFC 5280 sec. 6.1.4: the per-certificate CertManager verification above - * does not enforce the issuer's BasicConstraints pathLenConstraint on this - * API path, so check it over the assembled path before reporting success. */ + ret = X509StoreCheckChainCa(ctx, verifyCb, trustedSk, num); if (ret == WOLFSSL_SUCCESS) { ret = X509StoreCheckPathLen(ctx, verifyCb); } + if (ret == WOLFSSL_SUCCESS) { + ret = X509StoreCheckChainKeys(ctx, verifyCb, num); + } - /* Enforce hostname / IP verification from X509_VERIFY_PARAM if set. - * Always check against the leaf (end-entity) certificate, captured in - * orig before the chain-building loop modified ctx->current_cert. - * - * A mismatch is reported to the application verify callback the way - * OpenSSL's check_id_error() does: record error, error_depth and - * current_cert, then call it with ok=0, and let a return of 1 override. - * Without that call a callback installed to inspect or override - * verification errors never sees a hostname or IP mismatch. */ - if (ctx->param != NULL) { - if (ret == WOLFSSL_SUCCESS && ctx->param->hostName[0] != '\0') { - if (wolfSSL_X509_check_host(orig, - ctx->param->hostName, - XSTRLEN(ctx->param->hostName), - ctx->param->hostFlags, NULL) != WOLFSSL_SUCCESS) { - ctx->error = WOLFSSL_X509_V_ERR_HOSTNAME_MISMATCH; - ctx->error_depth = 0; - ctx->current_cert = orig; - if (verifyCb == NULL || verifyCb(0, ctx) != 1) { - ret = WOLFSSL_FAILURE; - } - } - } - if (ret == WOLFSSL_SUCCESS && ctx->param->ipasc[0] != '\0') { - if (wolfSSL_X509_check_ip_asc(orig, - ctx->param->ipasc, - ctx->param->hostFlags) != WOLFSSL_SUCCESS) { - ctx->error = WOLFSSL_X509_V_ERR_IP_ADDRESS_MISMATCH; - ctx->error_depth = 0; - ctx->current_cert = orig; - if (verifyCb == NULL || verifyCb(0, ctx) != 1) { - ret = WOLFSSL_FAILURE; - } - } - } + /* Host and IP of the leaf, reported as OpenSSL's check_id_error() */ + if (ret == WOLFSSL_SUCCESS && ctx->param != NULL && + ctx->param->hostName[0] != '\0' && + wolfSSL_X509_check_host(orig, ctx->param->hostName, + XSTRLEN(ctx->param->hostName), ctx->param->hostFlags, + NULL) != WOLFSSL_SUCCESS && + !X509StoreReport(ctx, verifyCb, orig, + WOLFSSL_X509_V_ERR_HOSTNAME_MISMATCH, 0)) { + ret = WOLFSSL_FAILURE; + } + if (ret == WOLFSSL_SUCCESS && ctx->param != NULL && + ctx->param->ipasc[0] != '\0' && + wolfSSL_X509_check_ip_asc(orig, ctx->param->ipasc, + ctx->param->hostFlags) != WOLFSSL_SUCCESS && + !X509StoreReport(ctx, verifyCb, orig, + WOLFSSL_X509_V_ERR_IP_ADDRESS_MISMATCH, 0)) { + ret = WOLFSSL_FAILURE; } -exit: - /* failedCerts, certsToUse and origTrustedSk hold only borrowed references; - * free the stack nodes, not the certs. All three are per-verification - * stacks (certsToUse/origTrustedSk are shallow dups of the caller's set), - * so none of the caller's own stacks are touched here. */ - wolfSSL_sk_X509_free(failedCerts); - - /* Remove intermediates added to CM. Unconditional: a "did we add one" flag - * is cleared by the same failure paths that leave one resident. Clears all - * TEMP_CAs, so concurrent verifies on one store are unsupported. */ - if (ctx != NULL) { - if (ctx->store != NULL) { - if (wolfSSL_CertManagerUnloadTempIntermediateCerts(ctx->store->cm) - != WOLFSSL_SUCCESS) { - WOLFSSL_MSG("Failed to unload temporary intermediates"); - /* Residue would anchor later verifications. */ - if (ret == WOLFSSL_SUCCESS) - ret = WOLFSSL_FAILURE; - } - } - if (orig != NULL) { - ctx->current_cert = orig; - } + if (ret == WOLFSSL_SUCCESS) { + ret = X509StoreCheckChainCrls(ctx, verifyCb, num, noIssuer); + } + if (ret == WOLFSSL_SUCCESS) { + ret = X509StoreCheckChainCerts(ctx, verifyCb, trustedSk, num, + noIssuer, sigFail); } - wolfSSL_sk_X509_free(certsToUse); - wolfSSL_sk_X509_free(origTrustedSk); +#ifndef IGNORE_NAME_CONSTRAINTS + if (ret == WOLFSSL_SUCCESS) { + ret = X509StoreCheckChainNames(ctx, verifyCb, num); + } +#endif - /* Fail closed on the way out: every failure has to be reportable through - * X509_STORE_CTX_get_error(), or the application is told the chain was - * fine while this function reports failure. Not all of them record one - - * a verify callback that rejects a chain the verification accepted, an - * allocation failure, or a chain-building error that never reached - * SetupStoreCtxError() all leave ctx->error at X509_V_OK. This is a - * deliberate blanket fallback for that whole class; it is applied only - * when nothing more specific was recorded, so an error the callback or - * the verification did set survives untouched. */ +exit: + wolfSSL_X509_free(cmIssuer); + wolfSSL_sk_X509_free(sigFail); + if (err != 0) { + ret = X509StoreFatal(ctx, err); + } + if (orig != NULL) { + ctx->current_cert = orig; + } + /* Every failure must be reportable through X509_STORE_CTX_get_error() */ if (ret != WOLFSSL_SUCCESS && ctx->error == WOLFSSL_X509_V_OK) { ctx->error = WOLFSSL_X509_V_ERR_UNSPECIFIED; } @@ -1470,9 +1689,14 @@ int wolfSSL_X509_STORE_CTX_set_purpose(WOLFSSL_X509_STORE_CTX *ctx, void wolfSSL_X509_STORE_CTX_set_flags(WOLFSSL_X509_STORE_CTX *ctx, unsigned long flags) { - if ((ctx != NULL) && (flags & WOLFSSL_PARTIAL_CHAIN)){ + if (ctx == NULL) { + return; + } + if (flags & WOLFSSL_PARTIAL_CHAIN) { ctx->flags |= WOLFSSL_PARTIAL_CHAIN; } + /* As in OpenSSL, the flags go on the verify param too */ + (void)wolfSSL_X509_VERIFY_PARAM_set_flags(ctx->param, flags); } /* set X509_STORE_CTX ex_data, max idx is MAX_EX_DATA. Return WOLFSSL_SUCCESS @@ -1522,7 +1746,7 @@ void wolfSSL_X509_STORE_CTX_set_depth(WOLFSSL_X509_STORE_CTX* ctx, int depth) { WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_set_depth"); if (ctx != NULL) { - ctx->depth = depth; + wolfSSL_X509_VERIFY_PARAM_set_depth(ctx->param, depth); } } #endif @@ -1686,7 +1910,7 @@ WOLFSSL_STACK* wolfSSL_X509_STORE_CTX_get1_chain(WOLFSSL_X509_STORE_CTX* ctx) } /* create duplicate of ctx chain */ - return wolfSSL_sk_dup(ref); + return wolfSSL_X509_chain_up_ref(ref); } #ifndef NO_WOLFSSL_STUB @@ -1697,18 +1921,75 @@ WOLFSSL_X509_STORE_CTX *wolfSSL_X509_STORE_CTX_get0_parent_ctx( WOLFSSL_STUB("wolfSSL_X509_STORE_CTX_get0_parent_ctx"); return NULL; } +#endif -int wolfSSL_X509_STORE_get_by_subject(WOLFSSL_X509_STORE_CTX* ctx, int idx, - WOLFSSL_X509_NAME* name, WOLFSSL_X509_OBJECT* obj) +/* Returns the first cert in certs with the subject name. */ +static WOLFSSL_X509* X509StoreFindBySubject(WOLFSSL_STACK* certs, + const WOLFSSL_X509_NAME* name) { - (void)ctx; - (void)idx; - (void)name; - (void)obj; - WOLFSSL_STUB("X509_STORE_get_by_subject"); - return 0; + int i; + + for (i = 0; i < wolfSSL_sk_X509_num(certs); i++) { + WOLFSSL_X509* x509 = wolfSSL_sk_X509_value(certs, i); + if ((x509 != NULL) && + (wolfSSL_X509_NAME_cmp(&x509->subject, name) == 0)) { + return x509; + } + } + return NULL; } + +/* Looks up a cert in the store by subject name. CRLs are not looked up. + * Returns 1 and puts a reference in obj when found, 0 otherwise. */ +int wolfSSL_X509_STORE_CTX_get_by_subject(WOLFSSL_X509_STORE_CTX* ctx, + WOLFSSL_X509_LOOKUP_TYPE type, WOLFSSL_X509_NAME* name, + WOLFSSL_X509_OBJECT* obj) +{ + WOLFSSL_X509* x509; +#if defined(WOLFSSL_SIGNER_DER_CERT) && !defined(NO_FILESYSTEM) + WOLF_STACK_OF(WOLFSSL_X509)* sk; +#endif + + WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_get_by_subject"); + + if ((ctx == NULL) || (ctx->store == NULL) || (name == NULL) || + (obj == NULL) || (type != WOLFSSL_X509_LU_X509)) { + return 0; + } + + x509 = X509StoreFindBySubject(ctx->store->trusted, name); + if (x509 == NULL) { + x509 = X509StoreFindBySubject(ctx->store->certs, name); + } + if ((x509 != NULL) && (wolfSSL_X509_up_ref(x509) != WOLFSSL_SUCCESS)) { + return 0; + } +#if defined(WOLFSSL_SIGNER_DER_CERT) && !defined(NO_FILESYSTEM) + /* CAs loaded into the cert manager from files. */ + if (x509 == NULL) { + sk = wolfSSL_X509_STORE_get1_certs(ctx, name); + x509 = wolfSSL_sk_X509_value(sk, 0); + if ((x509 != NULL) && (wolfSSL_X509_up_ref(x509) != WOLFSSL_SUCCESS)) { + x509 = NULL; + } + wolfSSL_sk_X509_pop_free(sk, NULL); + } #endif + if (x509 == NULL) { + return 0; + } + + obj->type = WOLFSSL_X509_LU_X509; + obj->data.x509 = x509; + return 1; +} + +int wolfSSL_X509_STORE_get_by_subject(WOLFSSL_X509_STORE_CTX* ctx, int type, + WOLFSSL_X509_NAME* name, WOLFSSL_X509_OBJECT* obj) +{ + return wolfSSL_X509_STORE_CTX_get_by_subject(ctx, + (WOLFSSL_X509_LOOKUP_TYPE)type, name, obj); +} WOLFSSL_X509_VERIFY_PARAM *wolfSSL_X509_STORE_CTX_get0_param( WOLFSSL_X509_STORE_CTX *ctx) @@ -1719,6 +2000,19 @@ WOLFSSL_X509_VERIFY_PARAM *wolfSSL_X509_STORE_CTX_get0_param( return ctx->param; } +/* Replace the param of ctx, including the values inherited from the store. + * ctx takes ownership of param. A NULL param or the current one keeps the + * current one. */ +void wolfSSL_X509_STORE_CTX_set0_param(WOLFSSL_X509_STORE_CTX *ctx, + WOLFSSL_X509_VERIFY_PARAM *param) +{ + WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_set0_param"); + if (ctx != NULL && param != NULL && param != ctx->param) { + wolfSSL_X509_VERIFY_PARAM_free(ctx->param); + ctx->param = param; + } +} + #endif /* OPENSSL_EXTRA */ #if defined(OPENSSL_EXTRA) && !defined(NO_FILESYSTEM) @@ -1734,6 +2028,8 @@ WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_X509_STORE_get1_certs( WOLFSSL_X509_NAME* certToFilterName = NULL; WOLF_STACK_OF(WOLFSSL_X509)* filteredCerts = NULL; WOLFSSL_X509* filteredCert = NULL; + int i; + int j; WOLFSSL_ENTER("wolfSSL_X509_STORE_get1_certs"); @@ -1757,7 +2053,7 @@ WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_X509_STORE_get1_certs( if (err == 0) { sk = wolfSSL_CertManagerGetCerts(store->cm); - if (sk == NULL) { + if (sk == NULL && wolfSSL_sk_X509_num(store->trusted) <= 0) { err = 1; } } @@ -1784,6 +2080,27 @@ WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_X509_STORE_get1_certs( } } + /* A trusted cert out of date when added is not in the cert manager */ + for (i = 0; err == 0 && i < wolfSSL_sk_X509_num(store->trusted); i++) { + filteredCert = wolfSSL_sk_X509_value(store->trusted, i); + if (wolfSSL_X509_NAME_cmp(&filteredCert->subject, name) != 0) + continue; + for (j = 0; j < wolfSSL_sk_X509_num(filteredCerts); j++) { + if (X509DerEquals(wolfSSL_sk_X509_value(filteredCerts, j), + filteredCert)) + break; + } + if (j < wolfSSL_sk_X509_num(filteredCerts)) + continue; + if (wolfSSL_X509_up_ref(filteredCert) != WOLFSSL_SUCCESS) { + err = 1; + } + else if (wolfSSL_sk_X509_push(filteredCerts, filteredCert) <= 0) { + wolfSSL_X509_free(filteredCert); + err = 1; + } + } + if (err == 1) { if (filteredCerts != NULL) { wolfSSL_sk_X509_pop_free(filteredCerts, NULL); @@ -1822,12 +2139,15 @@ int wolfSSL_X509_STORE_CTX_get1_issuer(WOLFSSL_X509 **issuer, #ifdef WOLFSSL_SIGNER_DER_CERT ret = x509GetIssuerFromCM(issuer, ctx->store->cm, x); -#else + if (ret == WOLFSSL_SUCCESS) { + return ret; + } +#endif + /* A trusted cert out of date when added is not in the cert manager */ ret = X509StoreGetIssuerEx(issuer, ctx->store->trusted, x); if ((ret == WOLFSSL_SUCCESS) && (*issuer != NULL)) { return wolfSSL_X509_up_ref(*issuer); } -#endif return ret; } @@ -1835,12 +2155,33 @@ int wolfSSL_X509_STORE_CTX_get1_issuer(WOLFSSL_X509 **issuer, #ifdef OPENSSL_EXTRA -/* Like X509StoreGetIssuerEx, but candidates present in `skip` are passed over - * and the scan continues, so a rejected same-subject cert does not hide a - * genuine issuer further down the stack. */ -static int X509StoreGetIssuerSkip(WOLFSSL_X509 **issuer, - WOLFSSL_STACK * certs, WOLFSSL_X509 *x, - WOLF_STACK_OF(WOLFSSL_X509)* skip) +/* Returns 1 if the public key of ca verifies the signature of x, else 0. + * An internal error is kept in *err. */ +static int X509StoreKeySigned(WOLFSSL_X509* ca, WOLFSSL_X509* x, int* err) +{ + int ret; + + if (ca->pubKey.buffer == NULL || x->derCert == NULL) { + return 0; + } + ret = CheckCertSignaturePubKey(x->derCert->buffer, x->derCert->length, + x->heap, ca->pubKey.buffer, ca->pubKey.length, (int)ca->pubKeyOID); + if (!X509StoreVerifyResult(ret)) { + (void)X509StoreKeepErr(err, ret); + } + return ret == 0; +} + +/* Returns 1 if ca may issue x, as in OpenSSL's check_issued(): the names + * and key ids match and the key type of ca fits the signature of x. */ +static int X509StoreIssued(WOLFSSL_X509* ca, WOLFSSL_X509* x) +{ + return wolfSSL_X509_check_issued(ca, x) == WOLFSSL_X509_V_OK && + SigOidMatchesKeyOid((word32)x->sigOID, (word32)ca->pubKeyOID); +} + +static int X509StoreGetIssuerEx(WOLFSSL_X509 **issuer, + WOLFSSL_STACK * certs, WOLFSSL_X509 *x) { int i; @@ -1851,9 +2192,7 @@ static int X509StoreGetIssuerSkip(WOLFSSL_X509 **issuer, for (i = 0; i < wolfSSL_sk_X509_num(certs); i++) { WOLFSSL_X509* cand = wolfSSL_sk_X509_value(certs, i); - if (X509StoreCertInStack(skip, cand)) - continue; - if (wolfSSL_X509_check_issued(cand, x) == WOLFSSL_X509_V_OK) { + if (X509StoreIssued(cand, x)) { *issuer = cand; return WOLFSSL_SUCCESS; } @@ -1863,12 +2202,6 @@ static int X509StoreGetIssuerSkip(WOLFSSL_X509 **issuer, return WOLFSSL_FAILURE; } -static int X509StoreGetIssuerEx(WOLFSSL_X509 **issuer, - WOLFSSL_STACK * certs, WOLFSSL_X509 *x) -{ - return X509StoreGetIssuerSkip(issuer, certs, x, NULL); -} - #endif /****************************************************************************** @@ -1914,6 +2247,9 @@ WOLFSSL_X509_STORE* wolfSSL_X509_STORE_new(void) if ((store->trusted = wolfSSL_sk_X509_new_null()) == NULL) goto err_exit; + + if ((store->added = wolfSSL_sk_X509_new_null()) == NULL) + goto err_exit; #endif #ifdef HAVE_CRL @@ -1931,6 +2267,7 @@ WOLFSSL_X509_STORE* wolfSSL_X509_STORE_new(void) goto err_exit; } XMEMSET(store->param, 0, sizeof(WOLFSSL_X509_VERIFY_PARAM)); + store->param->depth = -1; if ((store->lookup.dirs = (WOLFSSL_BY_DIR*)XMALLOC(sizeof(WOLFSSL_BY_DIR), NULL, DYNAMIC_TYPE_OPENSSL)) == NULL) { WOLFSSL_MSG("store->lookup.dir memory allocation error"); @@ -1999,6 +2336,8 @@ void wolfSSL_X509_STORE_free(WOLFSSL_X509_STORE* store) wolfSSL_sk_X509_pop_free(store->trusted, NULL); store->trusted = NULL; } + wolfSSL_sk_X509_free(store->added); + store->added = NULL; #endif #ifdef OPENSSL_ALL if (store->objs != NULL) { @@ -2193,8 +2532,10 @@ static int X509StoreAddCa(WOLFSSL_X509_STORE* store, WOLFSSL_ENTER("X509StoreAddCa"); if (store != NULL && x509 != NULL && x509->derCert != NULL) { - /* Check if NO_CHECK_TIME flag is set - if so, skip date validation */ - if (store->param != NULL && + /* Check if NO_CHECK_TIME flag is set - if so, skip date validation. + * A store of its own keeps a CA out of date out of the cert manager + * also with the flag: TLS would trust it for good. */ + if (store->trusted == NULL && store->param != NULL && (store->param->flags & WOLFSSL_NO_CHECK_TIME) != 0) { verify = VERIFY_SKIP_DATE; } @@ -2233,43 +2574,50 @@ WOLFSSL_LOCAL int X509StorePushCertsToCM(WOLFSSL_X509_STORE* store) if (store == NULL || store->cm == NULL) return WOLFSSL_SUCCESS; - /* Push non-self-signed intermediates from store->certs into the CM. */ - if (store->certs != NULL) { - num = wolfSSL_sk_X509_num(store->certs); + /* Push trusted certs first, while the store is not yet the store of an + * SSL_CTX: their dates are checked. Self-signed CAs are typically already + * in the CM (added during X509_STORE_add_cert), but AddCA handles + * duplicates. */ + if (store->trusted != NULL) { + num = wolfSSL_sk_X509_num(store->trusted); for (i = 0; i < num; i++) { - x509 = wolfSSL_sk_X509_value(store->certs, i); + x509 = wolfSSL_sk_X509_value(store->trusted, i); if (x509 != NULL) { ret = X509StoreAddCa(store, x509, WOLFSSL_USER_CA); - if (ret != WOLFSSL_SUCCESS) { - WOLFSSL_MSG("X509StorePushCertsToCM: failed to add cert"); + /* A cert out of date stays out of the CM and is dropped */ + if (ret != WOLFSSL_SUCCESS && + ret != WC_NO_ERR_TRACE(ASN_BEFORE_DATE_E) && + ret != WC_NO_ERR_TRACE(ASN_AFTER_DATE_E)) { + WOLFSSL_MSG("X509StorePushCertsToCM: failed to add " + "trusted cert"); anyFail = 1; } } } - /* Free and NULL to mark store as CTX-owned. Future add_cert calls - * will go directly to the CertManager. */ - wolfSSL_sk_X509_pop_free(store->certs, NULL); - store->certs = NULL; + wolfSSL_sk_X509_pop_free(store->trusted, NULL); + store->trusted = NULL; } - /* Push trusted certs too. Self-signed CAs are typically already in the CM - * (added during X509_STORE_add_cert), but AddCA handles duplicates. */ - if (store->trusted != NULL) { - num = wolfSSL_sk_X509_num(store->trusted); + /* Push non-self-signed intermediates from store->certs into the CM. */ + if (store->certs != NULL) { + num = wolfSSL_sk_X509_num(store->certs); for (i = 0; i < num; i++) { - x509 = wolfSSL_sk_X509_value(store->trusted, i); + x509 = wolfSSL_sk_X509_value(store->certs, i); if (x509 != NULL) { ret = X509StoreAddCa(store, x509, WOLFSSL_USER_CA); if (ret != WOLFSSL_SUCCESS) { - WOLFSSL_MSG("X509StorePushCertsToCM: failed to add " - "trusted cert"); + WOLFSSL_MSG("X509StorePushCertsToCM: failed to add cert"); anyFail = 1; } } } - wolfSSL_sk_X509_pop_free(store->trusted, NULL); - store->trusted = NULL; + /* Free and NULL to mark store as CTX-owned. Future add_cert calls + * will go directly to the CertManager. */ + wolfSSL_sk_X509_pop_free(store->certs, NULL); + store->certs = NULL; } + wolfSSL_sk_X509_free(store->added); + store->added = NULL; if (anyFail) { return WOLFSSL_FATAL_ERROR; @@ -2289,12 +2637,25 @@ int wolfSSL_X509_STORE_add_cert(WOLFSSL_X509_STORE* store, WOLFSSL_X509* x509) * CA=TRUE */ if (wolfSSL_X509_NAME_cmp(&x509->issuer, &x509->subject) == 0) { result = X509StoreAddCa(store, x509, WOLFSSL_USER_CA); - if (result == WOLFSSL_SUCCESS && store->trusted != NULL) { + /* As OpenSSL, a store of its own takes a cert out of date now. + * It stays out of the cert manager, so TLS does not trust it. + * X509_verify_cert() checks its dates at the verification time. */ + if (store->trusted != NULL && + (result == WC_NO_ERR_TRACE(ASN_BEFORE_DATE_E) || + result == WC_NO_ERR_TRACE(ASN_AFTER_DATE_E))) { + result = WOLFSSL_SUCCESS; + } + /* As OpenSSL, adding a cert already there is a no-op */ + if (result == WOLFSSL_SUCCESS && store->trusted != NULL && + !X509StoreCertIsTrusted(store, x509, NULL)) { result = wolfSSL_X509_up_ref(x509); if (result == WOLFSSL_SUCCESS) { result = wolfSSL_sk_X509_push(store->trusted, x509); if (result > 0) { - result = WOLFSSL_SUCCESS; + /* OpenSSL picks among certs of a name in the order + * they were added. */ + result = (wolfSSL_sk_X509_push(store->added, x509) > 0) + ? WOLFSSL_SUCCESS : WOLFSSL_FATAL_ERROR; } else { result = WOLFSSL_FATAL_ERROR; @@ -2310,7 +2671,8 @@ int wolfSSL_X509_STORE_add_cert(WOLFSSL_X509_STORE* store, WOLFSSL_X509* x509) if (result == WOLFSSL_SUCCESS) { result = wolfSSL_sk_X509_push(store->certs, x509); if (result > 0) { - result = WOLFSSL_SUCCESS; + result = (wolfSSL_sk_X509_push(store->added, x509) > 0) + ? WOLFSSL_SUCCESS : WOLFSSL_FATAL_ERROR; } else { result = WOLFSSL_FATAL_ERROR; @@ -2367,6 +2729,14 @@ int wolfSSL_X509_STORE_set_flags(WOLFSSL_X509_STORE* store, unsigned long flag) if (flag & WOLFSSL_PARTIAL_CHAIN) { store->param->flags |= WOLFSSL_PARTIAL_CHAIN; } + if (flag & WOLFSSL_X509_STRICT) { + store->param->flags |= WOLFSSL_X509_STRICT; + } + /* As OpenSSL, also without HAVE_CRL. Not X509_V_FLAG_NO_CHECK_TIME: on + * the store of an SSL_CTX it lets CAs out of date into the cert + * manager. */ + store->param->flags |= flag & (WOLFSSL_X509_V_FLAG_CRL_CHECK | + WOLFSSL_X509_V_FLAG_CRL_CHECK_ALL); return ret; } @@ -2580,10 +2950,21 @@ int wolfSSL_X509_STORE_set_default_paths(WOLFSSL_X509_STORE *str) WOLFSSL_ENTER("wolfSSL_X509_STORE_set_default_paths"); + if (str == NULL) + return WOLFSSL_FAILURE; + certFile = wc_strdup_ex(XGETENV("SSL_CERT_FILE"), DYNAMIC_TYPE_TMP_BUFFER); certDir = wc_strdup_ex(XGETENV("SSL_CERT_DIR"), DYNAMIC_TYPE_TMP_BUFFER); - ret = wolfSSL_X509_STORE_load_locations(str, certFile, certDir); + /* As OpenSSL: the default locations are optional. There is no built-in + * bundle, and one that does not load is not an error. */ + ret = WOLFSSL_SUCCESS; + if ((certFile != NULL || certDir != NULL) && + wolfSSL_X509_STORE_load_locations(str, certFile, certDir) != + WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Default locations not loaded"); + wolfSSL_ERR_clear_error(); + } XFREE(certFile, NULL, DYNAMIC_TYPE_TMP_BUFFER); XFREE(certDir, NULL, DYNAMIC_TYPE_TMP_BUFFER); @@ -2736,6 +3117,8 @@ WOLF_STACK_OF(WOLFSSL_X509_OBJECT)* wolfSSL_X509_STORE_get0_objects( #if defined(WOLFSSL_SIGNER_DER_CERT) && !defined(NO_FILESYSTEM) WOLFSSL_X509* x509 = NULL; int i = 0; + int j; + int n; #endif WOLFSSL_ENTER("wolfSSL_X509_STORE_get0_objects"); @@ -2767,7 +3150,8 @@ WOLF_STACK_OF(WOLFSSL_X509_OBJECT)* wolfSSL_X509_STORE_get0_objects( #if defined(WOLFSSL_SIGNER_DER_CERT) && !defined(NO_FILESYSTEM) cert_stack = wolfSSL_CertManagerGetCerts(store->cm); - if (cert_stack == NULL && wolfSSL_sk_X509_num(store->certs) > 0) { + if (cert_stack == NULL && (wolfSSL_sk_X509_num(store->certs) > 0 || + wolfSSL_sk_X509_num(store->trusted) > 0)) { cert_stack = wolfSSL_sk_X509_new_null(); if (cert_stack == NULL) { WOLFSSL_MSG("wolfSSL_sk_X509_OBJECT_new error"); @@ -2787,6 +3171,26 @@ WOLF_STACK_OF(WOLFSSL_X509_OBJECT)* wolfSSL_X509_STORE_get0_objects( goto err_cleanup; } } + /* A trusted cert out of date when added is not in the cert manager */ + n = wolfSSL_sk_X509_num(cert_stack); + for (i = 0; i < wolfSSL_sk_X509_num(store->trusted); i++) { + x509 = wolfSSL_sk_X509_value(store->trusted, i); + for (j = 0; j < n; j++) { + if (X509DerEquals(wolfSSL_sk_X509_value(cert_stack, j), x509)) + break; + } + if (j < n) + continue; + if (wolfSSL_X509_up_ref(x509) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("wolfSSL_X509_up_ref error"); + goto err_cleanup; + } + if (wolfSSL_sk_X509_push(cert_stack, x509) <= 0) { + WOLFSSL_MSG("wolfSSL_sk_X509_push error"); + wolfSSL_X509_free(x509); + goto err_cleanup; + } + } for (i = 0; i < wolfSSL_sk_X509_num(cert_stack); i++) { x509 = (WOLFSSL_X509 *)wolfSSL_sk_value(cert_stack, i); obj = wolfSSL_X509_OBJECT_new(); diff --git a/tests/api.c b/tests/api.c index 1d60e540cda..d65a6be154b 100644 --- a/tests/api.c +++ b/tests/api.c @@ -22118,6 +22118,40 @@ static int test_wolfSSL_ERR_put_error(void) return EXPECT_RESULT(); } +static int test_wolfSSL_ERR_load_strings(void) +{ + EXPECT_DECLS; +#if defined(OPENSSL_EXTRA) && !defined(OPENSSL_COEXIST) + static char libName[] = "test lib"; + static char reasonStr[] = "test reason"; + ERR_STRING_DATA lib[2]; + ERR_STRING_DATA reason[2]; + int libNum = 0; + + ExpectIntEQ(ERR_PACK(0x80, 0x1, 0x2), 0x80001002UL); + ExpectIntGE(libNum = ERR_get_next_error_library(), 128); + ExpectIntEQ(ERR_get_next_error_library(), libNum + 1); + + XMEMSET(lib, 0, sizeof(lib)); + XMEMSET(reason, 0, sizeof(reason)); + lib[0].error = ERR_PACK(libNum, 0, 0); + lib[0].string = libName; + reason[0].error = ERR_PACK(libNum, 0, 1); + reason[0].string = reasonStr; + ExpectIntEQ(ERR_load_strings(libNum, lib), 1); + ExpectIntEQ(ERR_load_strings(libNum, reason), 1); + + /* Errors of application libraries are not queued. */ + ERR_clear_error(); + ERR_put_error(libNum, 0, 1, "this file", 1); + ExpectIntEQ(ERR_peek_error(), 0); + + ExpectIntEQ(ERR_unload_strings(libNum, reason), 1); + ExpectIntEQ(ERR_unload_strings(libNum, lib), 1); +#endif + return EXPECT_RESULT(); +} + /* * This is a regression test for a bug where the peek/get error functions were * drawing from the end of the queue rather than the front. @@ -22670,6 +22704,7 @@ static int test_othername_and_SID_ext(void) sid_oid = NULL; ASN1_OCTET_STRING_free(sid_data); X509_REQ_free(x509); + x509 = NULL; EVP_PKEY_free(priv); /* At this point everything used to generate what is in der is cleaned up. @@ -27915,10 +27950,7 @@ static int test_wolfSSL_OCSP_REQ_CTX(void) X509_LU_X509, X509_get_issuer_name(cert))); ExpectNotNull(issuer = X509_OBJECT_get0_X509(x509_obj)); ExpectTrue(wolfSSL_X509_OBJECT_get_type(NULL) == WOLFSSL_X509_LU_NONE); -#ifndef NO_WOLFSSL_STUB - /* Not implemented and not in OpenSSL 1.1.0+ */ - wolfSSL_X509_OBJECT_free_contents(x509_obj); -#endif + wolfSSL_X509_OBJECT_free_contents(NULL); wolfSSL_X509_OBJECT_free(NULL); ExpectNotNull(req = OCSP_REQUEST_new()); @@ -28149,6 +28181,156 @@ static int test_wolfSSL_CRYPTO_memcmp(void) return EXPECT_RESULT(); } +#ifdef OPENSSL_EXTRA +static CRYPTO_malloc_fn test_mem_prev_malloc = NULL; +static CRYPTO_realloc_fn test_mem_prev_realloc = NULL; +static CRYPTO_free_fn test_mem_prev_free = NULL; +static int test_mem_allocs = 0; +static int test_mem_frees = 0; + +static void* test_mem_malloc(size_t sz, const char* file, int line) +{ + test_mem_allocs++; + return test_mem_prev_malloc(sz, file, line); +} + +static void* test_mem_realloc(void* p, size_t sz, const char* file, int line) +{ + if (p == NULL) + test_mem_allocs++; + return test_mem_prev_realloc(p, sz, file, line); +} + +static void test_mem_free(void* p, const char* file, int line) +{ + if (p != NULL) + test_mem_frees++; + test_mem_prev_free(p, file, line); +} + +#if defined(USE_WOLFSSL_MEMORY) && !defined(WOLFSSL_STATIC_MEMORY) && \ + !defined(WOLFSSL_DEBUG_MEMORY) +/* A native wrapper of wolfSSL's allocators that stops a loop. */ +static wolfSSL_Malloc_cb test_mem_native_malloc = NULL; +static wolfSSL_Free_cb test_mem_native_free = NULL; +static wolfSSL_Realloc_cb test_mem_native_realloc = NULL; +static int test_mem_native_depth = 0; +static int test_mem_native_loop = 0; + +static void* test_mem_native_wrap_malloc(size_t sz) +{ + void* p = NULL; + + if (++test_mem_native_depth > 1) + test_mem_native_loop = 1; + else + p = test_mem_native_malloc(sz); + test_mem_native_depth--; + return p; +} + +static void* test_mem_native_wrap_realloc(void* p, size_t sz) +{ + void* q = NULL; + + if (++test_mem_native_depth > 1) + test_mem_native_loop = 1; + else + q = test_mem_native_realloc(p, sz); + test_mem_native_depth--; + return q; +} + +static void test_mem_native_wrap_free(void* p) +{ + if (++test_mem_native_depth > 1) + test_mem_native_loop = 1; + else + test_mem_native_free(p); + test_mem_native_depth--; +} +#endif +#endif + +static int test_wolfSSL_CRYPTO_get_mem_functions(void) +{ + EXPECT_DECLS; +#ifdef OPENSSL_EXTRA + CRYPTO_malloc_fn m = NULL; + CRYPTO_realloc_fn r = NULL; + CRYPTO_free_fn f = NULL; + void* p = NULL; + void* q = NULL; + int ret = 0; +#if defined(USE_WOLFSSL_MEMORY) && !defined(WOLFSSL_STATIC_MEMORY) + X509* x509 = NULL; +#endif + + CRYPTO_get_mem_functions(NULL, NULL, NULL); + CRYPTO_get_mem_functions(&test_mem_prev_malloc, &test_mem_prev_realloc, + &test_mem_prev_free); + ExpectTrue(test_mem_prev_malloc != NULL); + ExpectTrue(test_mem_prev_realloc != NULL); + ExpectTrue(test_mem_prev_free != NULL); + + /* The returned functions can be called directly. */ + if (EXPECT_SUCCESS()) { + ExpectNotNull(p = test_mem_prev_malloc(16, __FILE__, __LINE__)); + ExpectNotNull(q = test_mem_prev_realloc(p, 32, __FILE__, __LINE__)); + if (q != NULL) + p = q; + test_mem_prev_free(p, __FILE__, __LINE__); + p = NULL; + } + + /* Wrap them, allocate through wolfSSL and restore them. */ + if (EXPECT_SUCCESS()) { + ret = CRYPTO_set_mem_functions(test_mem_malloc, test_mem_realloc, + test_mem_free); + } +#if defined(USE_WOLFSSL_MEMORY) && !defined(WOLFSSL_STATIC_MEMORY) + ExpectIntEQ(ret, 1); + CRYPTO_get_mem_functions(&m, &r, &f); + ExpectTrue(m == test_mem_malloc); + ExpectTrue(r == test_mem_realloc); + ExpectTrue(f == test_mem_free); + ExpectNotNull(x509 = X509_new()); + X509_free(x509); + ExpectNotNull(p = OPENSSL_malloc(8)); + OPENSSL_free(p); +#ifndef WOLFSSL_DEBUG_MEMORY + /* Getting them while a native wrapper is installed changes nothing. */ + if (EXPECT_SUCCESS()) { + (void)wolfSSL_GetAllocators(&test_mem_native_malloc, + &test_mem_native_free, &test_mem_native_realloc); + ExpectIntEQ(wolfSSL_SetAllocators(test_mem_native_wrap_malloc, + test_mem_native_wrap_free, test_mem_native_wrap_realloc), 0); + CRYPTO_get_mem_functions(&m, &r, &f); + ExpectIntEQ(wolfSSL_SetAllocators(test_mem_native_malloc, + test_mem_native_free, test_mem_native_realloc), 0); + } + ExpectNotNull(p = OPENSSL_malloc(8)); + OPENSSL_free(p); + ExpectIntEQ(test_mem_native_loop, 0); +#endif + if (ret == 1) { + ret = CRYPTO_set_mem_functions(test_mem_prev_malloc, + test_mem_prev_realloc, test_mem_prev_free); + } + ExpectIntEQ(ret, 1); + ExpectIntGT(test_mem_allocs, 1); + ExpectIntEQ(test_mem_allocs, test_mem_frees); +#else + ExpectIntEQ(ret, 0); +#endif + CRYPTO_get_mem_functions(&m, &r, &f); + ExpectTrue(m == test_mem_prev_malloc); + ExpectTrue(r == test_mem_prev_realloc); + ExpectTrue(f == test_mem_prev_free); +#endif + return EXPECT_RESULT(); +} + /*----------------------------------------------------------------------------* | wolfCrypt ASN *----------------------------------------------------------------------------*/ @@ -31317,7 +31499,6 @@ static int test_sk_X509_CRL_decode(void) ExpectNull(wolfSSL_sk_X509_REVOKED_value(NULL, 0)); } #ifndef NO_WOLFSSL_STUB - ExpectIntEQ(wolfSSL_X509_CRL_verify(NULL, NULL), 0); ExpectIntEQ(X509_OBJECT_set1_X509_CRL(NULL, NULL), 0); ExpectIntEQ(X509_OBJECT_set1_X509(NULL, NULL), 0); #endif @@ -31363,7 +31544,16 @@ static int test_sk_X509_CRL_decode(void) ExpectIntEQ(sk_X509_CRL_num(s), 0); ExpectIntEQ(sk_X509_CRL_push(s, crl), 1); + /* Frees the stack only. */ sk_X509_CRL_free(s); + s = NULL; + ExpectNotNull(X509_CRL_get_issuer(crl)); + ExpectNotNull(s = sk_X509_CRL_new()); + ExpectIntEQ(sk_X509_CRL_push(s, crl), 1); + if (EXPECT_FAIL()) { + X509_CRL_free(crl); + } + sk_X509_CRL_pop_free(s, X509_CRL_free); #endif return EXPECT_RESULT(); } @@ -31456,8 +31646,7 @@ static int test_wolfSSL_X509_CRL_get_REVOKED_after_update(void) ExpectIntEQ(wolfSSL_sk_X509_REVOKED_num(revokedSk), 1); ExpectNotNull(rev = wolfSSL_sk_X509_REVOKED_value(revokedSk, 0)); ExpectNotNull(serial = wolfSSL_X509_REVOKED_get0_serial_number(rev)); - ExpectIntEQ(serial->length, 1); - ExpectIntEQ(serial->data[0], 0x02); + ExpectIntEQ(wolfSSL_ASN1_INTEGER_get(serial), 0x02); wolfSSL_CTX_free(ctx); @@ -47414,6 +47603,7 @@ TEST_CASE testCases[] = { /* Can't memory test as callbacks use Assert. */ TEST_DECL(test_error_queue_per_thread), TEST_DECL(test_wolfSSL_ERR_put_error), + TEST_DECL(test_wolfSSL_ERR_load_strings), TEST_DECL(test_wolfSSL_ERR_get_error_order), TEST_DECL(test_wolfSSL_ERR_GET_REASON_version_mismatch), #ifndef NO_BIO @@ -47476,6 +47666,7 @@ TEST_CASE testCases[] = { #endif TEST_DECL(test_wolfSSL_CRYPTO_memcmp), + TEST_DECL(test_wolfSSL_CRYPTO_get_mem_functions), TEST_DECL(test_wolfSSL_CRYPTO_get_ex_new_index), TEST_DECL(test_CRYPTO_set_dynlock_xxx), TEST_DECL(test_CRYPTO_THREADID_xxx), diff --git a/tests/api/test_certman.c b/tests/api/test_certman.c index 81c8b3573f7..c0d68f1140f 100644 --- a/tests/api/test_certman.c +++ b/tests/api/test_certman.c @@ -626,6 +626,63 @@ int test_wolfSSL_CertManagerLoadCABufferType(void) return EXPECT_RESULT(); } +/* AddCA() checks the RSA modulus and ECC curve size of a CA against the + * minimum key sizes when the CTX verifies peers. */ +int test_wolfSSL_CertManagerCAKeySize(void) +{ + EXPECT_DECLS; +#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && !defined(NO_TLS) && \ + !defined(NO_WOLFSSL_SERVER) + WOLFSSL_CTX* ctx = NULL; + byte* buf = NULL; + size_t sz = 0; + +#if !defined(NO_RSA) && !defined(NO_SHA256) + /* A 2048-bit modulus. */ + ExpectIntEQ(load_file("./certs/ca-cert.der", &buf, &sz), 0); + ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); + wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_PEER, NULL); + ExpectIntEQ(wolfSSL_CTX_SetMinRsaKey_Sz(ctx, 2048), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_CTX_load_verify_buffer(ctx, buf, (long)sz, + WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); + wolfSSL_CTX_free(ctx); + ctx = NULL; + ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); + wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_PEER, NULL); + ExpectIntEQ(wolfSSL_CTX_SetMinRsaKey_Sz(ctx, 2056), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_CTX_load_verify_buffer(ctx, buf, (long)sz, + WOLFSSL_FILETYPE_ASN1), WC_NO_ERR_TRACE(RSA_KEY_SIZE_E)); + wolfSSL_CTX_free(ctx); + ctx = NULL; + XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + buf = NULL; +#endif +#if defined(HAVE_ECC) && !defined(NO_SHA256) && defined(WOLFSSL_SHA384) && \ + (defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 256 + /* P-256 is below a minimum of 384 bits, P-384 is not. */ + ExpectNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); + wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_PEER, NULL); + ExpectIntEQ(wolfSSL_CTX_SetMinEccKey_Sz(ctx, 384), WOLFSSL_SUCCESS); + ExpectIntEQ(load_file("./certs/ca-ecc-cert.der", &buf, &sz), 0); + ExpectIntEQ(wolfSSL_CTX_load_verify_buffer(ctx, buf, (long)sz, + WOLFSSL_FILETYPE_ASN1), WC_NO_ERR_TRACE(ECC_KEY_SIZE_E)); + XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + buf = NULL; + ExpectIntEQ(load_file("./certs/ca-ecc384-cert.der", &buf, &sz), 0); + ExpectIntEQ(wolfSSL_CTX_load_verify_buffer(ctx, buf, (long)sz, + WOLFSSL_FILETYPE_ASN1), WOLFSSL_SUCCESS); + XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + buf = NULL; + wolfSSL_CTX_free(ctx); + ctx = NULL; +#endif + (void)ctx; + (void)buf; + (void)sz; +#endif + return EXPECT_RESULT(); +} + int test_wolfSSL_CertManagerGetCerts(void) { EXPECT_DECLS; diff --git a/tests/api/test_certman.h b/tests/api/test_certman.h index feb9cb687fa..f6a0bcf1979 100644 --- a/tests/api/test_certman.h +++ b/tests/api/test_certman.h @@ -29,6 +29,7 @@ int test_certman_decision_coverage(void); int test_wolfSSL_CertManagerLoadCABuffer(void); int test_wolfSSL_CertManagerLoadCABuffer_ex(void); int test_wolfSSL_CertManagerLoadCABufferType(void); +int test_wolfSSL_CertManagerCAKeySize(void); int test_wolfSSL_CertManagerGetCerts(void); int test_wolfSSL_CertManagerSetVerify(void); int test_wolfSSL_CertManagerNameConstraint(void); @@ -75,6 +76,7 @@ int test_wolfSSL_trust_peer_cert_dates(void); TEST_DECL_GROUP("certman", test_wolfSSL_CertManagerLoadCABuffer), \ TEST_DECL_GROUP("certman", test_wolfSSL_CertManagerLoadCABuffer_ex), \ TEST_DECL_GROUP("certman", test_wolfSSL_CertManagerLoadCABufferType), \ + TEST_DECL_GROUP("certman", test_wolfSSL_CertManagerCAKeySize), \ TEST_DECL_GROUP("certman", test_wolfSSL_CertManagerGetCerts), \ TEST_DECL_GROUP("certman", test_wolfSSL_CertManagerSetVerify), \ TEST_DECL_GROUP("certman", test_wolfSSL_CertManagerNameConstraint), \ diff --git a/tests/api/test_evp_cipher.c b/tests/api/test_evp_cipher.c index 8f0f0f816f1..45812c30619 100644 --- a/tests/api/test_evp_cipher.c +++ b/tests/api/test_evp_cipher.c @@ -251,6 +251,36 @@ int test_wolfSSL_EVP_CIPHER_CTX_set_iv(void) return EXPECT_RESULT(); } +int test_wolfSSL_EVP_CIPHER_CTX_cleanup_wipe(void) +{ + EXPECT_DECLS; +#if defined(OPENSSL_EXTRA) && !defined(NO_DES3) + EVP_CIPHER_CTX* ctx = NULL; + byte key[DES3_KEY_SIZE]; + byte iv[DES_BLOCK_SIZE]; + const byte* p; + size_t i; + byte nonZero = 0; + + XMEMSET(key, 0xa5, sizeof(key)); + XMEMSET(iv, 0, sizeof(iv)); + ExpectNotNull(ctx = EVP_CIPHER_CTX_new()); + ExpectIntEQ(EVP_CipherInit(ctx, EVP_des_ede3_cbc(), key, iv, 1), + WOLFSSL_SUCCESS); + ExpectIntEQ(EVP_CIPHER_CTX_cleanup(ctx), WOLFSSL_SUCCESS); + /* No key schedule left behind. */ + if (ctx != NULL) { + p = (const byte*)&ctx->cipher; + for (i = 0; i < sizeof(ctx->cipher); i++) { + nonZero |= p[i]; + } + } + ExpectIntEQ(nonZero, 0); + EVP_CIPHER_CTX_free(ctx); +#endif + return EXPECT_RESULT(); +} + int test_wolfSSL_EVP_get_cipherbynid(void) { EXPECT_DECLS; diff --git a/tests/api/test_evp_cipher.h b/tests/api/test_evp_cipher.h index 3acc4a4d293..8bc04bcbe22 100644 --- a/tests/api/test_evp_cipher.h +++ b/tests/api/test_evp_cipher.h @@ -28,6 +28,7 @@ int test_wolfSSL_EVP_CIPHER_CTX(void); int test_wolfSSL_EVP_CIPHER_CTX_iv_length(void); int test_wolfSSL_EVP_CIPHER_CTX_key_length(void); int test_wolfSSL_EVP_CIPHER_CTX_set_iv(void); +int test_wolfSSL_EVP_CIPHER_CTX_cleanup_wipe(void); int test_wolfSSL_EVP_get_cipherbynid(void); int test_wolfSSL_EVP_CIPHER_block_size(void); int test_wolfSSL_EVP_CIPHER_iv_length(void); @@ -76,6 +77,7 @@ int test_evp_cipher_update_no_padding_buffered(void); TEST_DECL_GROUP("evp_cipher", test_wolfSSL_EVP_CIPHER_CTX_iv_length), \ TEST_DECL_GROUP("evp_cipher", test_wolfSSL_EVP_CIPHER_CTX_key_length), \ TEST_DECL_GROUP("evp_cipher", test_wolfSSL_EVP_CIPHER_CTX_set_iv), \ + TEST_DECL_GROUP("evp_cipher", test_wolfSSL_EVP_CIPHER_CTX_cleanup_wipe), \ TEST_DECL_GROUP("evp_cipher", test_wolfSSL_EVP_get_cipherbynid), \ TEST_DECL_GROUP("evp_cipher", test_wolfSSL_EVP_CIPHER_block_size), \ TEST_DECL_GROUP("evp_cipher", test_wolfSSL_EVP_CIPHER_iv_length), \ diff --git a/tests/api/test_evp_pkey.c b/tests/api/test_evp_pkey.c index aefd4908b54..bbbbfe27f33 100644 --- a/tests/api/test_evp_pkey.c +++ b/tests/api/test_evp_pkey.c @@ -132,6 +132,28 @@ int test_wolfSSL_EVP_PKEY_base_id(void) #endif return EXPECT_RESULT(); } +int test_wolfSSL_EVP_PKEY_rsa_types(void) +{ + EXPECT_DECLS; +#if defined(OPENSSL_EXTRA) && !defined(NO_RSA) && \ + defined(USE_CERT_BUFFERS_2048) + EVP_PKEY* pkey = NULL; + const unsigned char* in = client_key_der_2048; + + /* Distinct values, so all three can be case labels in one switch. */ + ExpectIntNE(EVP_PKEY_RSA2, EVP_PKEY_RSA); + ExpectIntNE(EVP_PKEY_RSA_PSS, EVP_PKEY_RSA); + ExpectIntNE(EVP_PKEY_RSA2, EVP_PKEY_RSA_PSS); + ExpectIntEQ(EVP_PKEY_RSA_PSS, NID_rsassaPss); + + ExpectNotNull(pkey = d2i_PrivateKey(EVP_PKEY_RSA, NULL, &in, + (long)sizeof_client_key_der_2048)); + ExpectIntEQ(EVP_PKEY_base_id(pkey), EVP_PKEY_RSA); + EVP_PKEY_free(pkey); +#endif + return EXPECT_RESULT(); +} + int test_wolfSSL_EVP_PKEY_id(void) { EXPECT_DECLS; @@ -910,6 +932,172 @@ int test_wolfSSL_EVP_PKEY_set1_get1_DSA(void) return EXPECT_RESULT(); } /* END test_EVP_PKEY_set1_get1_DSA */ +int test_wolfSSL_EVP_PKEY_assign_get1_DSA(void) +{ + EXPECT_DECLS; +#if defined(OPENSSL_ALL) && !defined(NO_DSA) && !defined(HAVE_SELFTEST) && \ + !defined(HAVE_FIPS) && !defined(WC_FIPS_186_5_PLUS) && \ + defined(WOLFSSL_KEY_GEN) && !defined(NO_FILESYSTEM) + DSA* dsa = NULL; + DSA* dsa2 = NULL; + EVP_PKEY* pkey = NULL; + DSA_SIG* sig = NULL; + const BIGNUM* priv = NULL; + unsigned char digest[WC_SHA_DIGEST_SIZE]; + byte der[TWOK_BUF]; + int derSz = 0; + XFILE fp = XBADFILE; + + XMEMSET(digest, 0x5a, sizeof(digest)); + ExpectTrue((fp = XFOPEN("./certs/dsa2048.der", "rb")) != XBADFILE); + ExpectIntGT(derSz = (int)XFREAD(der, 1, sizeof(der), fp), 0); + if (fp != XBADFILE) + XFCLOSE(fp); + + /* Free the pkey before the key returned by get1. */ + ExpectNotNull(dsa = DSA_new()); + ExpectIntEQ(DSA_LoadDer(dsa, der, derSz), 1); + ExpectNotNull(pkey = EVP_PKEY_new()); + ExpectIntEQ(EVP_PKEY_assign_DSA(pkey, dsa), 1); + if (EXPECT_FAIL()) { + DSA_free(dsa); + } + dsa = NULL; + /* get1 returns the key of the pkey with a reference for the caller. */ + ExpectNotNull(dsa2 = EVP_PKEY_get1_DSA(pkey)); + ExpectPtrEq(dsa2, EVP_PKEY_get0_DSA(pkey)); + EVP_PKEY_free(pkey); + pkey = NULL; + DSA_get0_key(dsa2, NULL, &priv); + ExpectNotNull(priv); + ExpectNotNull(sig = DSA_do_sign(digest, (int)sizeof(digest), dsa2)); + ExpectIntEQ(DSA_do_verify(digest, (int)sizeof(digest), sig, dsa2), 1); + DSA_SIG_free(sig); + sig = NULL; + DSA_free(dsa2); + dsa2 = NULL; + + /* Free the key returned by get1 before the pkey. */ + ExpectNotNull(dsa = DSA_new()); + ExpectIntEQ(DSA_LoadDer(dsa, der, derSz), 1); + ExpectNotNull(pkey = EVP_PKEY_new()); + ExpectIntEQ(EVP_PKEY_assign_DSA(pkey, dsa), 1); + if (EXPECT_FAIL()) { + DSA_free(dsa); + } + dsa = NULL; + ExpectNotNull(dsa2 = EVP_PKEY_get1_DSA(pkey)); + ExpectPtrEq(dsa2, EVP_PKEY_get0_DSA(pkey)); + DSA_free(dsa2); + dsa2 = NULL; + ExpectNotNull(sig = DSA_do_sign(digest, (int)sizeof(digest), + EVP_PKEY_get0_DSA(pkey))); + ExpectIntEQ(DSA_do_verify(digest, (int)sizeof(digest), sig, + EVP_PKEY_get0_DSA(pkey)), 1); + DSA_SIG_free(sig); + EVP_PKEY_free(pkey); +#endif + return EXPECT_RESULT(); +} + +int test_wolfSSL_EVP_PKEY_set1_get1_DSA_ref(void) +{ + EXPECT_DECLS; +#if defined(OPENSSL_ALL) && !defined(NO_DSA) && !defined(HAVE_SELFTEST) && \ + !defined(HAVE_FIPS) && !defined(WC_FIPS_186_5_PLUS) && \ + defined(WOLFSSL_KEY_GEN) && !defined(NO_FILESYSTEM) + DSA* dsa = NULL; + DSA* dsa2 = NULL; + DSA* get1 = NULL; + EVP_PKEY* pkey = NULL; + DSA_SIG* sig = NULL; + const unsigned char* p = NULL; + unsigned char digest[WC_SHA_DIGEST_SIZE]; + byte der[TWOK_BUF]; + int derSz = 0; + XFILE fp = XBADFILE; + + XMEMSET(digest, 0x5a, sizeof(digest)); + ExpectTrue((fp = XFOPEN("./certs/dsa2048.der", "rb")) != XBADFILE); + ExpectIntGT(derSz = (int)XFREAD(der, 1, sizeof(der), fp), 0); + if (fp != XBADFILE) + XFCLOSE(fp); + ExpectNotNull(dsa = DSA_new()); + ExpectIntEQ(DSA_LoadDer(dsa, der, derSz), 1); + ExpectNotNull(dsa2 = DSA_new()); + ExpectIntEQ(DSA_LoadDer(dsa2, der, derSz), 1); + ExpectNotNull(pkey = EVP_PKEY_new()); + + /* set1 takes a reference, so the key outlives the caller's one. */ + ExpectIntEQ(EVP_PKEY_set1_DSA(pkey, dsa), 1); + ExpectPtrEq(EVP_PKEY_get0_DSA(pkey), dsa); + DSA_free(dsa); + dsa = NULL; + ExpectNotNull(sig = DSA_do_sign(digest, (int)sizeof(digest), + EVP_PKEY_get0_DSA(pkey))); + ExpectIntEQ(DSA_do_verify(digest, (int)sizeof(digest), sig, + EVP_PKEY_get0_DSA(pkey)), 1); + DSA_SIG_free(sig); + sig = NULL; + + /* get1 after set1 returns the same key. */ + ExpectNotNull(get1 = EVP_PKEY_get1_DSA(pkey)); + ExpectPtrEq(get1, EVP_PKEY_get0_DSA(pkey)); + DSA_free(get1); + get1 = NULL; + + /* set1 with the key the pkey already holds must not free it. */ + ExpectIntEQ(EVP_PKEY_set1_DSA(pkey, EVP_PKEY_get0_DSA(pkey)), 1); + ExpectNotNull(sig = DSA_do_sign(digest, (int)sizeof(digest), + EVP_PKEY_get0_DSA(pkey))); + DSA_SIG_free(sig); + sig = NULL; + + /* Replacing the key drops only the reference the pkey held. */ + ExpectNotNull(get1 = EVP_PKEY_get1_DSA(pkey)); + ExpectIntEQ(EVP_PKEY_set1_DSA(pkey, dsa2), 1); + ExpectPtrEq(EVP_PKEY_get0_DSA(pkey), dsa2); + ExpectNotNull(sig = DSA_do_sign(digest, (int)sizeof(digest), get1)); + ExpectIntEQ(DSA_do_verify(digest, (int)sizeof(digest), sig, get1), 1); + DSA_SIG_free(sig); + sig = NULL; + DSA_free(get1); + get1 = NULL; + DSA_free(dsa2); + dsa2 = NULL; + ExpectNotNull(sig = DSA_do_sign(digest, (int)sizeof(digest), + EVP_PKEY_get0_DSA(pkey))); + DSA_SIG_free(sig); + sig = NULL; + EVP_PKEY_free(pkey); + pkey = NULL; + + /* get1 on a pkey with only the DER decodes the key once and keeps it. + * Decoding always sets the DSA object, so drop it here. */ + p = der; + ExpectNotNull(pkey = d2i_PrivateKey(EVP_PKEY_DSA, NULL, &p, + (long)derSz)); + if (pkey != NULL) { + DSA_free(pkey->dsa); + pkey->dsa = NULL; + pkey->ownDsa = 0; + } + ExpectNotNull(get1 = EVP_PKEY_get1_DSA(pkey)); + ExpectPtrEq(get1, EVP_PKEY_get0_DSA(pkey)); + ExpectNotNull(dsa = EVP_PKEY_get1_DSA(pkey)); + ExpectPtrEq(dsa, get1); + DSA_free(dsa); + dsa = NULL; + EVP_PKEY_free(pkey); + pkey = NULL; + ExpectNotNull(sig = DSA_do_sign(digest, (int)sizeof(digest), get1)); + ExpectIntEQ(DSA_do_verify(digest, (int)sizeof(digest), sig, get1), 1); + DSA_SIG_free(sig); + DSA_free(get1); +#endif + return EXPECT_RESULT(); +} + int test_wolfSSL_EVP_PKEY_set1_get1_EC_KEY(void) { EXPECT_DECLS; @@ -2064,11 +2252,18 @@ int test_wolfSSL_EVP_PKEY_sign_dsa_digest_len(void) WOLFSSL_EVP_MD_CTX* mdCtx = NULL; byte digest[SHA256_DIGEST_LENGTH]; byte other[SHA256_DIGEST_LENGTH]; - byte sig[DSA_MAX_SIG_SIZE]; + /* EVP_PKEY_sign() writes DER, EVP_SignFinal() raw r and s. */ + byte sig[DSA_MAX_SIG_SIZE + 16]; + byte rawSig[DSA_MAX_SIG_SIZE]; byte msg[16]; size_t siglen = sizeof(sig); - unsigned int sigFinalLen = sizeof(sig); + unsigned int sigFinalLen = sizeof(rawSig); SHA256_CTX shaCtx; + DSA_SIG* dsaSig = NULL; + BIGNUM* r = NULL; + BIGNUM* s = NULL; + unsigned char* der = NULL; + int derSz = 0; XMEMSET(msg, 0x33, sizeof(msg)); XMEMSET(digest, 0x5a, sizeof(digest)); @@ -2102,7 +2297,7 @@ int test_wolfSSL_EVP_PKEY_sign_dsa_digest_len(void) ExpectNotNull(mdCtx = EVP_MD_CTX_new()); ExpectIntEQ(EVP_SignInit(mdCtx, EVP_sha256()), WOLFSSL_SUCCESS); ExpectIntEQ(EVP_SignUpdate(mdCtx, msg, sizeof(msg)), WOLFSSL_SUCCESS); - ExpectIntEQ(EVP_SignFinal(mdCtx, sig, &sigFinalLen, pkey), + ExpectIntEQ(EVP_SignFinal(mdCtx, rawSig, &sigFinalLen, pkey), WOLFSSL_SUCCESS); SHA256_Init(&shaCtx); SHA256_Update(&shaCtx, msg, sizeof(msg)); @@ -2110,8 +2305,24 @@ int test_wolfSSL_EVP_PKEY_sign_dsa_digest_len(void) #ifdef WOLFSSL_SMALL_STACK_CACHE wc_Sha256Free((wc_Sha256*)&shaCtx); #endif - ExpectIntEQ(EVP_PKEY_verify(ctxVerify, sig, (size_t)sigFinalLen, digest, + /* EVP_PKEY_verify() takes only the DER encoding. */ + ExpectIntEQ(sigFinalLen, 2 * SHA256_DIGEST_LENGTH); + ExpectNotNull(dsaSig = DSA_SIG_new()); + ExpectNotNull(r = BN_bin2bn(rawSig, SHA256_DIGEST_LENGTH, NULL)); + ExpectNotNull(s = BN_bin2bn(rawSig + SHA256_DIGEST_LENGTH, + SHA256_DIGEST_LENGTH, NULL)); + ExpectIntEQ(DSA_SIG_set0(dsaSig, r, s), 1); + if (EXPECT_SUCCESS()) { + r = NULL; + s = NULL; + } + ExpectIntGT(derSz = i2d_DSA_SIG(dsaSig, &der), 0); + ExpectIntEQ(EVP_PKEY_verify(ctxVerify, der, (size_t)derSz, digest, sizeof(digest)), WOLFSSL_SUCCESS); + XFREE(der, NULL, DYNAMIC_TYPE_ASN1); + BN_free(r); + BN_free(s); + DSA_SIG_free(dsaSig); EVP_MD_CTX_free(mdCtx); EVP_PKEY_CTX_free(ctxVerify); @@ -2122,6 +2333,297 @@ int test_wolfSSL_EVP_PKEY_sign_dsa_digest_len(void) return EXPECT_RESULT(); } +int test_wolfSSL_i2d_PUBKEY_EC_private(void) +{ + EXPECT_DECLS; +#if defined(OPENSSL_EXTRA) && defined(HAVE_ECC) && \ + defined(USE_CERT_BUFFERS_256) && !defined(NO_ECC256) && \ + !defined(NO_ECC_SECP) + /* RFC 5915 ECPrivateKey of a P-256 key without the public key. */ + static const unsigned char privOnly[] = { + 0x30, 0x31, 0x02, 0x01, 0x01, 0x04, 0x20, + 0x51, 0x9b, 0x42, 0x3d, 0x71, 0x5f, 0x8b, 0x58, + 0x1f, 0x4f, 0xa8, 0xee, 0x59, 0xf4, 0x77, 0x1a, + 0x5b, 0x44, 0xc8, 0x13, 0x0b, 0x4e, 0x3e, 0xac, + 0xca, 0x54, 0xa5, 0x6d, 0xda, 0x72, 0xb4, 0x64, + 0xa0, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07 + }; + /* Its public point, x and y. */ + static const unsigned char privOnlyPub[] = { + 0x1c, 0xcb, 0xe9, 0x1c, 0x07, 0x5f, 0xc7, 0xf4, + 0xf0, 0x33, 0xbf, 0xa2, 0x48, 0xdb, 0x8f, 0xcc, + 0xd3, 0x56, 0x5d, 0xe9, 0x4b, 0xbf, 0xb1, 0x2f, + 0x3c, 0x59, 0xff, 0x46, 0xc2, 0x71, 0xbf, 0x83, + 0xce, 0x40, 0x14, 0xc6, 0x88, 0x11, 0xf9, 0xa2, + 0x1a, 0x1f, 0xdb, 0x2c, 0x0e, 0x61, 0x13, 0xe0, + 0x6d, 0xb7, 0xca, 0x93, 0xb7, 0x40, 0x4e, 0x78, + 0xdc, 0x7c, 0xcd, 0x5c, 0xa8, 0x9a, 0x4c, 0xa9 + }; +#ifdef HAVE_ECC_BRAINPOOL + /* PKCS#8 brainpoolP256r1 key: the curve is only in the header. */ + static const unsigned char bpP8[] = { + 0x30, 0x81, 0x88, 0x02, 0x01, 0x00, 0x30, 0x14, 0x06, 0x07, 0x2a, 0x86, + 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x09, 0x2b, 0x24, 0x03, 0x03, 0x02, + 0x08, 0x01, 0x01, 0x07, 0x04, 0x6d, 0x30, 0x6b, 0x02, 0x01, 0x01, 0x04, + 0x20, 0x3a, 0x2f, 0x65, 0x24, 0x08, 0x72, 0x6c, 0x87, 0xa6, 0xb0, 0xe1, + 0x88, 0xac, 0x31, 0x74, 0xd1, 0xc0, 0x41, 0x92, 0xe6, 0xd1, 0x3f, 0x40, + 0xb5, 0x49, 0x7a, 0xa9, 0x0d, 0xe3, 0x58, 0x1e, 0xf4, 0xa1, 0x44, 0x03, + 0x42, 0x00, 0x04, 0x69, 0x46, 0x8e, 0xee, 0x68, 0x80, 0xa4, 0xae, 0x02, + 0x86, 0x6b, 0xc1, 0xef, 0xfe, 0xd1, 0xc6, 0xaa, 0x10, 0x85, 0x5d, 0xbd, + 0xc9, 0x28, 0x88, 0x3e, 0xd1, 0xdd, 0xad, 0xfe, 0x0f, 0x65, 0xc7, 0x2f, + 0xf7, 0xa2, 0x73, 0xd0, 0xe6, 0xae, 0x4e, 0x09, 0x9b, 0x34, 0xf6, 0xfa, + 0x85, 0x97, 0x05, 0xfd, 0xc5, 0xfc, 0x7e, 0x43, 0xfd, 0x24, 0xf4, 0xad, + 0x0e, 0x9d, 0x22, 0x6e, 0xf7, 0x7f, 0xd0 + }; +#endif + EVP_PKEY* pkey = NULL; + EVP_PKEY* pub = NULL; + const unsigned char* p = ecc_key_der_256; + unsigned char* der = NULL; + unsigned char* der2 = NULL; + int derSz = 0; + EC_KEY* ec = NULL; + unsigned char point[65]; +#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) + byte* buf = NULL; + size_t bufSz = 0; +#endif + + /* The SubjectPublicKeyInfo of a private key. */ + ExpectNotNull(pkey = d2i_PrivateKey(EVP_PKEY_EC, NULL, &p, + (long)sizeof_ecc_key_der_256)); + ExpectIntEQ(i2d_PUBKEY(pkey, NULL), (int)sizeof_ecc_key_pub_der_256); + ExpectIntEQ(derSz = i2d_PUBKEY(pkey, &der), + (int)sizeof_ecc_key_pub_der_256); + ExpectBufEQ(der, ecc_key_pub_der_256, sizeof_ecc_key_pub_der_256); + /* The public key reads back. */ + p = der; + ExpectNotNull(pub = d2i_PUBKEY(NULL, &p, derSz)); + ExpectIntEQ(i2d_PUBKEY(pub, &der2), derSz); + ExpectBufEQ(der2, der, derSz); + EVP_PKEY_free(pub); + XFREE(der2, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + der2 = NULL; + + /* The encoding follows the current EC key. */ + ExpectNotNull(ec = EVP_PKEY_get0_EC_KEY(pkey)); + ExpectIntEQ(EC_KEY_generate_key(ec), 1); + ExpectIntEQ(i2d_PUBKEY(pkey, &der2), derSz); + ExpectIntNE(XMEMCMP(der2, der, (size_t)derSz), 0); + ExpectIntEQ(EC_POINT_point2oct(EC_KEY_get0_group(ec), + EC_KEY_get0_public_key(ec), POINT_CONVERSION_UNCOMPRESSED, point, + sizeof(point), NULL), sizeof(point)); + if (EXPECT_SUCCESS()) { + ExpectBufEQ(der2 + derSz - sizeof(point), point, sizeof(point)); + } + XFREE(der2, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + XFREE(der, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + der = NULL; + EVP_PKEY_free(pkey); + pkey = NULL; + + /* The public key is computed when the encoding does not have it. */ + p = privOnly; + ExpectNotNull(pkey = d2i_PrivateKey(EVP_PKEY_EC, NULL, &p, + (long)sizeof(privOnly))); + ExpectIntEQ(derSz = i2d_PUBKEY(pkey, &der), + (int)sizeof_ecc_key_pub_der_256); + ExpectBufEQ(der, ecc_key_pub_der_256, 27); + if (EXPECT_SUCCESS()) { + ExpectBufEQ(der + derSz - sizeof(privOnlyPub), privOnlyPub, + sizeof(privOnlyPub)); + } + XFREE(der, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + der = NULL; + EVP_PKEY_free(pkey); + pkey = NULL; + +#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) + /* PKCS#8: the inner key has no curve parameters. */ + ExpectIntEQ(load_file("./certs/ecc-keyPkcs8.der", &buf, &bufSz), 0); + p = buf; + ExpectNotNull(pkey = d2i_PrivateKey(EVP_PKEY_EC, NULL, &p, + (long)bufSz)); + ExpectIntEQ(i2d_PUBKEY(pkey, &der), (int)sizeof_ecc_key_pub_der_256); + ExpectBufEQ(der, ecc_key_pub_der_256, sizeof_ecc_key_pub_der_256); + XFREE(der, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + der = NULL; + EVP_PKEY_free(pkey); + pkey = NULL; + XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + +#ifdef HAVE_ECC_BRAINPOOL + /* The curve of a PKCS#8 key is taken from the header. */ + p = bpP8; + ExpectNotNull(pkey = d2i_PrivateKey(EVP_PKEY_EC, NULL, &p, + (long)sizeof(bpP8))); + ExpectIntEQ(derSz = i2d_PUBKEY(pkey, &der), 92); + /* Same AlgorithmIdentifier and public point. */ + ExpectBufEQ(der + 2, bpP8 + 6, 22); + if (EXPECT_SUCCESS()) { + ExpectBufEQ(der + derSz - 65, bpP8 + sizeof(bpP8) - 65, 65); + } + XFREE(der, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + EVP_PKEY_free(pkey); +#endif +#endif + return EXPECT_RESULT(); +} + +int test_wolfSSL_EVP_PKEY_sign_verify_dsa_der(void) +{ + EXPECT_DECLS; +#if defined(OPENSSL_EXTRA) && !defined(NO_DSA) && !defined(HAVE_SELFTEST) && \ + defined(WOLFSSL_KEY_GEN) && !defined(NO_SHA256) && \ + defined(USE_CERT_BUFFERS_2048) + /* SHA-256 of "What is easy to do is easy not to do." signed by OpenSSL + * with dsa_key_der_2048. */ + static const unsigned char sigOssl[] = { + 0x30, 0x2c, 0x02, 0x14, 0x29, 0x47, 0x2d, 0xb8, 0x5e, 0xf9, 0x13, 0x8f, + 0xd3, 0x32, 0x70, 0x8e, 0x6b, 0x0b, 0x3d, 0x1f, 0xd2, 0xa5, 0x3c, 0x3c, + 0x02, 0x14, 0x16, 0xb7, 0xed, 0xab, 0x52, 0x90, 0x74, 0xf6, 0x09, 0x6a, + 0x66, 0x70, 0x69, 0xf7, 0x43, 0xd0, 0xdc, 0x87, 0x8b, 0x94, + }; +#if !defined(NO_FILESYSTEM) && (defined(WOLFSSL_QT) || \ + defined(OPENSSL_ALL) || defined(WOLFSSL_OPENSSH)) + /* The same digest signed by OpenSSL with certs/dsa3072.der (256-bit q). */ + static const unsigned char sigOssl256[] = { + 0x30, 0x44, 0x02, 0x20, 0x23, 0x11, 0xc8, 0xeb, 0x07, 0x67, 0xbd, 0xf2, + 0x59, 0xaa, 0x92, 0x28, 0x56, 0x13, 0x8c, 0xee, 0x72, 0x53, 0x8f, 0x01, + 0x1e, 0xf5, 0x7e, 0x8d, 0x32, 0x99, 0xf3, 0x60, 0x05, 0xec, 0xa6, 0x7a, + 0x02, 0x20, 0x04, 0x30, 0x3f, 0x84, 0xeb, 0x64, 0x28, 0xa1, 0x64, 0x30, + 0x34, 0x98, 0x91, 0x34, 0x2d, 0x06, 0x1d, 0xad, 0x93, 0x38, 0x91, 0xfc, + 0xff, 0x3f, 0xd8, 0xfd, 0xb9, 0xb0, 0x2e, 0xd3, 0x9c, 0x66, + }; + unsigned char key[TWOK_BUF]; + int keySz = 0; + XFILE fp = XBADFILE; +#endif + const char* in = "What is easy to do is easy not to do."; + const unsigned char* der = dsa_key_der_2048; + const unsigned char* p = NULL; + unsigned char hash[WC_SHA256_DIGEST_SIZE]; + unsigned char sig[128]; + unsigned char bad[sizeof(sigOssl) + 1]; + unsigned char raw[40]; + size_t sigLen = 0; + EVP_PKEY* pkey = NULL; + EVP_PKEY_CTX* ctx = NULL; + DSA* dsa = NULL; + DSA_SIG* dsaSig = NULL; + + ExpectNotNull(SHA256((const unsigned char*)in, XSTRLEN(in), hash)); + ExpectNotNull(dsa = DSA_new()); + ExpectIntEQ(DSA_LoadDer(dsa, der, (int)sizeof_dsa_key_der_2048), 1); + ExpectNotNull(pkey = EVP_PKEY_new()); + ExpectIntEQ(EVP_PKEY_set1_DSA(pkey, dsa), 1); + + /* Verify a DER signature made by OpenSSL. */ + ExpectNotNull(ctx = EVP_PKEY_CTX_new(pkey, NULL)); + ExpectIntEQ(EVP_PKEY_verify_init(ctx), 1); + ExpectIntEQ(EVP_PKEY_CTX_set_signature_md(ctx, EVP_sha256()), 1); + ExpectIntEQ(EVP_PKEY_verify(ctx, sigOssl, sizeof(sigOssl), hash, + sizeof(hash)), 1); + XMEMCPY(bad, sigOssl, sizeof(sigOssl)); + bad[sizeof(sigOssl) - 1] ^= 0x01; + ExpectIntNE(EVP_PKEY_verify(ctx, bad, sizeof(sigOssl), hash, + sizeof(hash)), 1); + ExpectIntNE(EVP_PKEY_verify(ctx, sigOssl, sizeof(sigOssl) - 1, hash, + sizeof(hash)), 1); + /* Raw r|s is not DER. */ + XMEMCPY(raw, sigOssl + 4, 20); + XMEMCPY(raw + 20, sigOssl + 26, 20); + ExpectIntNE(EVP_PKEY_verify(ctx, raw, sizeof(raw), hash, sizeof(hash)), + 1); + /* r longer than q: r * 256 + 0x5a. */ + bad[0] = 0x30; + bad[1] = 0x2d; + bad[2] = 0x02; + bad[3] = 0x15; + XMEMCPY(bad + 4, sigOssl + 4, 20); + bad[24] = 0x5a; + XMEMCPY(bad + 25, sigOssl + 24, 22); + ExpectIntNE(EVP_PKEY_verify(ctx, bad, sizeof(bad), hash, sizeof(hash)), + 1); + /* s longer than q: s * 256 + 0xa5. */ + XMEMCPY(bad, sigOssl, sizeof(sigOssl)); + bad[1] = 0x2d; + bad[25] = 0x15; + bad[46] = 0xa5; + ExpectIntNE(EVP_PKEY_verify(ctx, bad, sizeof(bad), hash, sizeof(hash)), + 1); + hash[0] ^= 0x01; + ExpectIntNE(EVP_PKEY_verify(ctx, sigOssl, sizeof(sigOssl), hash, + sizeof(hash)), 1); + hash[0] ^= 0x01; + EVP_PKEY_CTX_free(ctx); + ctx = NULL; + + /* Sign: DER of r and s, at most DSA_size() bytes. */ + ExpectNotNull(ctx = EVP_PKEY_CTX_new(pkey, NULL)); + ExpectIntEQ(EVP_PKEY_sign_init(ctx), 1); + ExpectIntEQ(EVP_PKEY_CTX_set_signature_md(ctx, EVP_sha256()), 1); + ExpectIntEQ(EVP_PKEY_sign(ctx, NULL, &sigLen, hash, sizeof(hash)), 1); + ExpectIntEQ((int)sigLen, DSA_size(dsa)); + sigLen = (size_t)DSA_size(dsa) - 1; + ExpectIntNE(EVP_PKEY_sign(ctx, sig, &sigLen, hash, sizeof(hash)), 1); + sigLen = sizeof(sig); + ExpectIntEQ(EVP_PKEY_sign(ctx, sig, &sigLen, hash, sizeof(hash)), 1); + ExpectIntLE((int)sigLen, DSA_size(dsa)); + ExpectIntEQ(sig[0], 0x30); + p = sig; + ExpectNotNull(dsaSig = d2i_DSA_SIG(NULL, &p, (long)sigLen)); + ExpectPtrEq(p, sig + sigLen); + ExpectIntEQ(DSA_do_verify(hash, (int)sizeof(hash), dsaSig, dsa), 1); + DSA_SIG_free(dsaSig); + dsaSig = NULL; + EVP_PKEY_CTX_free(ctx); + ctx = NULL; + + ExpectNotNull(ctx = EVP_PKEY_CTX_new(pkey, NULL)); + ExpectIntEQ(EVP_PKEY_verify_init(ctx), 1); + ExpectIntEQ(EVP_PKEY_verify(ctx, sig, sigLen, hash, sizeof(hash)), 1); + EVP_PKEY_CTX_free(ctx); + ctx = NULL; + EVP_PKEY_free(pkey); + pkey = NULL; + DSA_free(dsa); + dsa = NULL; + +#if !defined(NO_FILESYSTEM) && (defined(WOLFSSL_QT) || \ + defined(OPENSSL_ALL) || defined(WOLFSSL_OPENSSH)) + /* 256-bit q: all of the SHA-256 digest is used. + * d2i_PrivateKey decodes DSA keys only in these builds. */ + ExpectTrue((fp = XFOPEN("./certs/dsa3072.der", "rb")) != XBADFILE); + ExpectIntGT(keySz = (int)XFREAD(key, 1, sizeof(key), fp), 0); + if (fp != XBADFILE) + XFCLOSE(fp); + p = key; + ExpectNotNull(pkey = d2i_PrivateKey(EVP_PKEY_DSA, NULL, &p, keySz)); + ExpectNotNull(dsa = EVP_PKEY_get0_DSA(pkey)); + + ExpectNotNull(ctx = EVP_PKEY_CTX_new(pkey, NULL)); + ExpectIntEQ(EVP_PKEY_verify_init(ctx), 1); + ExpectIntEQ(EVP_PKEY_verify(ctx, sigOssl256, sizeof(sigOssl256), hash, + sizeof(hash)), 1); + EVP_PKEY_CTX_free(ctx); + ctx = NULL; + + ExpectNotNull(ctx = EVP_PKEY_CTX_new(pkey, NULL)); + ExpectIntEQ(EVP_PKEY_sign_init(ctx), 1); + sigLen = sizeof(sig); + ExpectIntEQ(EVP_PKEY_sign(ctx, sig, &sigLen, hash, sizeof(hash)), 1); + p = sig; + ExpectNotNull(dsaSig = d2i_DSA_SIG(NULL, &p, (long)sigLen)); + ExpectIntEQ(DSA_do_verify(hash, (int)sizeof(hash), dsaSig, dsa), 1); + DSA_SIG_free(dsaSig); + EVP_PKEY_CTX_free(ctx); + EVP_PKEY_free(pkey); +#endif +#endif + return EXPECT_RESULT(); +} int test_wolfSSL_EVP_PKEY_sign_verify_ec(void) { EXPECT_DECLS; diff --git a/tests/api/test_evp_pkey.h b/tests/api/test_evp_pkey.h index 6cf395cd426..55fef107ee2 100644 --- a/tests/api/test_evp_pkey.h +++ b/tests/api/test_evp_pkey.h @@ -29,6 +29,7 @@ int test_wolfSSL_EVP_PKEY_CTX_set_rsa_keygen_bits(void); int test_wolfSSL_QT_EVP_PKEY_CTX_free(void); int test_wolfSSL_EVP_PKEY_up_ref(void); int test_wolfSSL_EVP_PKEY_base_id(void); +int test_wolfSSL_EVP_PKEY_rsa_types(void); int test_wolfSSL_EVP_PKEY_id(void); int test_wolfSSL_EVP_MD_pkey_type(void); int test_wolfSSL_EVP_MD_hmac_signing(void); @@ -38,6 +39,8 @@ int test_wolfSSL_EVP_PKEY_hkdf(void); int test_wolfSSL_EVP_PBE_scrypt(void); int test_EVP_PKEY_cmp(void); int test_wolfSSL_EVP_PKEY_set1_get1_DSA(void); +int test_wolfSSL_EVP_PKEY_assign_get1_DSA(void); +int test_wolfSSL_EVP_PKEY_set1_get1_DSA_ref(void); int test_wolfSSL_EVP_PKEY_set1_get1_EC_KEY (void); int test_wolfSSL_EVP_PKEY_get0_EC_KEY(void); int test_wolfSSL_EVP_PKEY_set1_get1_DH (void); @@ -60,6 +63,8 @@ int test_wolfSSL_EVP_SignInit_ex(void); int test_wolfSSL_EVP_PKEY_sign_verify_rsa(void); int test_wolfSSL_EVP_PKEY_sign_verify_dsa(void); int test_wolfSSL_EVP_PKEY_sign_dsa_digest_len(void); +int test_wolfSSL_EVP_PKEY_sign_verify_dsa_der(void); +int test_wolfSSL_i2d_PUBKEY_EC_private(void); int test_wolfSSL_EVP_PKEY_sign_verify_ec(void); int test_wolfSSL_EVP_PKEY_verify_dsa_len(void); int test_wolfSSL_EVP_MD_rsa_signing(void); @@ -91,6 +96,7 @@ int test_wolfSSL_CTX_use_PrivateKey_pkcs8_repopulate(void); TEST_DECL_GROUP("evp_pkey", test_wolfSSL_QT_EVP_PKEY_CTX_free), \ TEST_DECL_GROUP("evp_pkey", test_wolfSSL_EVP_PKEY_up_ref), \ TEST_DECL_GROUP("evp_pkey", test_wolfSSL_EVP_PKEY_base_id), \ + TEST_DECL_GROUP("evp_pkey", test_wolfSSL_EVP_PKEY_rsa_types), \ TEST_DECL_GROUP("evp_pkey", test_wolfSSL_EVP_PKEY_id), \ TEST_DECL_GROUP("evp_pkey", test_wolfSSL_EVP_MD_pkey_type), \ TEST_DECL_GROUP("evp_pkey", test_wolfSSL_EVP_MD_hmac_signing), \ @@ -101,6 +107,8 @@ int test_wolfSSL_CTX_use_PrivateKey_pkcs8_repopulate(void); TEST_DECL_GROUP("evp_pkey", test_wolfSSL_EVP_PBE_scrypt), \ TEST_DECL_GROUP("evp_pkey", test_EVP_PKEY_cmp), \ TEST_DECL_GROUP("evp_pkey", test_wolfSSL_EVP_PKEY_set1_get1_DSA), \ + TEST_DECL_GROUP("evp_pkey", test_wolfSSL_EVP_PKEY_assign_get1_DSA), \ + TEST_DECL_GROUP("evp_pkey", test_wolfSSL_EVP_PKEY_set1_get1_DSA_ref), \ TEST_DECL_GROUP("evp_pkey", test_wolfSSL_EVP_PKEY_set1_get1_EC_KEY), \ TEST_DECL_GROUP("evp_pkey", test_wolfSSL_EVP_PKEY_get0_EC_KEY), \ TEST_DECL_GROUP("evp_pkey", test_wolfSSL_EVP_PKEY_set1_get1_DH), \ @@ -123,6 +131,8 @@ int test_wolfSSL_CTX_use_PrivateKey_pkcs8_repopulate(void); TEST_DECL_GROUP("evp_pkey", test_wolfSSL_EVP_PKEY_sign_verify_rsa), \ TEST_DECL_GROUP("evp_pkey", test_wolfSSL_EVP_PKEY_sign_verify_dsa), \ TEST_DECL_GROUP("evp_pkey", test_wolfSSL_EVP_PKEY_sign_dsa_digest_len), \ + TEST_DECL_GROUP("evp_pkey", test_wolfSSL_EVP_PKEY_sign_verify_dsa_der), \ + TEST_DECL_GROUP("evp_pkey", test_wolfSSL_i2d_PUBKEY_EC_private), \ TEST_DECL_GROUP("evp_pkey", test_wolfSSL_EVP_PKEY_sign_verify_ec), \ TEST_DECL_GROUP("evp_pkey", test_wolfSSL_EVP_PKEY_verify_dsa_len), \ TEST_DECL_GROUP("evp_pkey", test_wolfSSL_EVP_MD_rsa_signing), \ diff --git a/tests/api/test_ossl_asn1.c b/tests/api/test_ossl_asn1.c index 24207f9e171..c45818c9c1f 100644 --- a/tests/api/test_ossl_asn1.c +++ b/tests/api/test_ossl_asn1.c @@ -134,6 +134,8 @@ int test_wolfSSL_ASN1_INTEGER(void) ExpectNotNull(a = d2i_ASN1_INTEGER(NULL, &p, sizeof(longDer))); ExpectPtrNE(p, longDer); ExpectNotNull(dup = wolfSSL_ASN1_INTEGER_dup(a)); + ExpectIntEQ(wolfSSL_ASN1_INTEGER_cmp(dup, a), 0); + ExpectIntEQ(wolfSSL_i2d_ASN1_INTEGER(dup, NULL), (int)sizeof(longDer)); ASN1_INTEGER_free(dup); ASN1_INTEGER_free(a); #endif @@ -168,6 +170,91 @@ int test_wolfSSL_ASN1_INTEGER_cmp(void) ExpectIntEQ(ASN1_INTEGER_set(b, 0x1000), 1); ExpectIntLT(wolfSSL_ASN1_INTEGER_cmp(a, b), 0); ExpectIntGT(wolfSSL_ASN1_INTEGER_cmp(b, a), 0); +#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && !defined(NO_RSA) + /* Equal values compare equal with or without a leading zero byte. + * This serial has the top bit set. */ + { + X509* x509 = NULL; + BIGNUM* bn = NULL; + ASN1_INTEGER* serial = NULL; + ASN1_INTEGER* other = NULL; + + ExpectNotNull(x509 = wolfSSL_X509_load_certificate_file( + "./certs/ocsp/imposter-root-ca-cert.pem", WOLFSSL_FILETYPE_PEM)); + ExpectNotNull(serial = X509_get_serialNumber(x509)); + ExpectNotNull(bn = ASN1_INTEGER_to_BN(serial, NULL)); + ExpectNotNull(other = BN_to_ASN1_INTEGER(bn, NULL)); + ExpectIntEQ(wolfSSL_ASN1_INTEGER_cmp(serial, other), 0); + ExpectIntEQ(wolfSSL_ASN1_INTEGER_cmp(other, serial), 0); + ExpectIntEQ(BN_set_word(bn, 0x80), 1); + ExpectNotNull(BN_to_ASN1_INTEGER(bn, other)); + ExpectIntEQ(ASN1_INTEGER_set(a, 0x80), 1); + ExpectIntEQ(wolfSSL_ASN1_INTEGER_cmp(a, other), 0); + ExpectIntGT(wolfSSL_ASN1_INTEGER_cmp(b, other), 0); + ASN1_INTEGER_free(other); + BN_free(bn); + X509_free(x509); + } +#endif + /* Equal negative values made in different ways compare equal. */ + { + static const unsigned char m128[] = { 0x02, 0x01, 0x80 }; + static const unsigned char m129[] = { 0x02, 0x02, 0xff, 0x7f }; + const unsigned char* p = NULL; + BIGNUM* bn = NULL; + ASN1_INTEGER* c = NULL; + ASN1_INTEGER* d = NULL; + + ExpectIntEQ(ASN1_INTEGER_set(a, -128), 1); + ExpectNotNull(bn = ASN1_INTEGER_to_BN(a, NULL)); + ExpectNotNull(c = BN_to_ASN1_INTEGER(bn, NULL)); + p = m128; + ExpectNotNull(d = d2i_ASN1_INTEGER(NULL, &p, (long)sizeof(m128))); + ExpectIntEQ(wolfSSL_ASN1_INTEGER_cmp(a, c), 0); + ExpectIntEQ(wolfSSL_ASN1_INTEGER_cmp(c, d), 0); + ExpectIntEQ(wolfSSL_ASN1_INTEGER_cmp(d, a), 0); + BN_free(bn); + bn = NULL; + ASN1_INTEGER_free(d); + d = NULL; + + ExpectIntEQ(ASN1_INTEGER_set(b, -129), 1); + ExpectNotNull(bn = ASN1_INTEGER_to_BN(b, NULL)); + ExpectNotNull(BN_to_ASN1_INTEGER(bn, c)); + p = m129; + ExpectNotNull(d = d2i_ASN1_INTEGER(NULL, &p, (long)sizeof(m129))); + ExpectIntEQ(wolfSSL_ASN1_INTEGER_cmp(b, c), 0); + ExpectIntEQ(wolfSSL_ASN1_INTEGER_cmp(b, d), 0); + ExpectIntEQ(wolfSSL_ASN1_INTEGER_cmp(c, d), 0); + ExpectIntLT(wolfSSL_ASN1_INTEGER_cmp(c, a), 0); + ExpectIntGT(wolfSSL_ASN1_INTEGER_cmp(a, d), 0); + BN_free(bn); + ASN1_INTEGER_free(d); + d = NULL; + ASN1_INTEGER_free(c); + c = NULL; + + /* Only the content, as built by hand. */ + ExpectNotNull(c = ASN1_INTEGER_new()); + if (c != NULL) { + c->data[0] = 0x01; + c->data[1] = 0x00; + c->length = 2; + } + ExpectIntEQ(ASN1_INTEGER_set(a, 0x100), 1); + ExpectIntEQ(wolfSSL_ASN1_INTEGER_cmp(c, a), 0); + ExpectIntEQ(ASN1_INTEGER_set(a, 0xff), 1); + ExpectIntGT(wolfSSL_ASN1_INTEGER_cmp(c, a), 0); + ASN1_INTEGER_free(c); + c = NULL; + + /* An empty INTEGER is not 0, as in OpenSSL. */ + ExpectNotNull(c = ASN1_INTEGER_new()); + ExpectIntEQ(ASN1_INTEGER_set(a, 0), 1); + ExpectIntLT(wolfSSL_ASN1_INTEGER_cmp(c, a), 0); + ExpectIntGT(wolfSSL_ASN1_INTEGER_cmp(a, c), 0); + ASN1_INTEGER_free(c); + } ASN1_INTEGER_free(b); ASN1_INTEGER_free(a); @@ -439,6 +526,122 @@ int test_wolfSSL_ASN1_INTEGER_get_set(void) return EXPECT_RESULT(); } +/* ASN1_STRING_length/get0_data on an ASN1_INTEGER give the magnitude, as in + * OpenSSL. */ +int test_wolfSSL_ASN1_INTEGER_STRING(void) +{ + EXPECT_DECLS; +#if defined(OPENSSL_EXTRA) && !defined(NO_ASN) + static const unsigned char p128[] = { 0x02, 0x02, 0x00, 0x80 }; + static const unsigned char m129[] = { 0x02, 0x02, 0xff, 0x7f }; + static const unsigned char v0[] = { 0x00 }; + static const unsigned char v80[] = { 0x80 }; + static const unsigned char v81[] = { 0x81 }; + static const unsigned char v100[] = { 0x01, 0x00 }; + ASN1_INTEGER* a = NULL; + const ASN1_INTEGER* ca = NULL; + BIGNUM* bn = NULL; + const unsigned char* p = NULL; + ASN1_INTEGER* dup = NULL; +#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && defined(HAVE_ECC) + static const unsigned char serial[] = { + 0xe3, 0x81, 0x4b, 0x48, 0xa5, 0x70, 0x61, 0x70 + }; + static const unsigned char serialDer[] = { + 0x02, 0x09, 0x00, 0xe3, 0x81, 0x4b, 0x48, 0xa5, 0x70, 0x61, 0x70 + }; + unsigned char* der = NULL; + X509* x509 = NULL; +#ifndef NO_BIO + BIO* bio = NULL; + char* str = NULL; +#endif +#endif + + ExpectIntEQ(ASN1_STRING_length(ca), 0); + ExpectNull(ASN1_STRING_get0_data(ca)); + ExpectIntEQ(ASN1_STRING_type(ca), 0); + + ExpectNotNull(a = ASN1_INTEGER_new()); + ExpectIntEQ(ASN1_STRING_type(a), V_ASN1_INTEGER); + ExpectIntEQ(ASN1_INTEGER_set(a, 0x80), 1); + ExpectIntEQ(ASN1_STRING_length(a), 1); + ExpectBufEQ(ASN1_STRING_get0_data(a), v80, 1); + ExpectIntEQ(ASN1_STRING_type(a), V_ASN1_INTEGER); + ExpectIntEQ(ASN1_INTEGER_set(a, -128), 1); + ExpectIntEQ(a->type, V_ASN1_NEG_INTEGER); + ExpectIntEQ(ASN1_STRING_length(a), 1); + ExpectBufEQ(ASN1_STRING_get0_data(a), v80, 1); + ExpectIntEQ(ASN1_STRING_type(a), V_ASN1_NEG_INTEGER); + ExpectIntEQ(ASN1_INTEGER_set(a, 0), 1); + ExpectIntEQ(ASN1_STRING_length(a), 1); + ExpectBufEQ(ASN1_STRING_get0_data(a), v0, 1); + ExpectIntEQ(ASN1_STRING_type(a), V_ASN1_INTEGER); + ExpectIntEQ(ASN1_INTEGER_set(a, 256), 1); + ca = a; + ExpectIntEQ(ASN1_STRING_length(ca), 2); + ExpectBufEQ(ASN1_STRING_get0_data(ca), v100, 2); + ExpectIntEQ(ASN1_STRING_type(ca), V_ASN1_INTEGER); + ASN1_INTEGER_free(a); + a = NULL; + + ExpectIntGT(BN_hex2bn(&bn, "-80"), 0); + ExpectNotNull(a = BN_to_ASN1_INTEGER(bn, NULL)); + ExpectIntEQ(a->type, V_ASN1_NEG_INTEGER); + ExpectIntEQ(ASN1_STRING_length(a), 1); + ExpectBufEQ(ASN1_STRING_get0_data(a), v80, 1); + ExpectIntEQ(ASN1_STRING_type(a), V_ASN1_NEG_INTEGER); + ASN1_INTEGER_free(a); + a = NULL; + BN_free(bn); + + p = p128; + ExpectNotNull(a = d2i_ASN1_INTEGER(NULL, &p, (long)sizeof(p128))); + ExpectIntEQ(ASN1_STRING_length(a), 1); + ExpectBufEQ(ASN1_STRING_get0_data(a), v80, 1); + ExpectIntEQ(ASN1_STRING_type(a), V_ASN1_INTEGER); + ASN1_INTEGER_free(a); + a = NULL; + p = m129; + ExpectNotNull(a = d2i_ASN1_INTEGER(NULL, &p, (long)sizeof(m129))); + ExpectIntEQ(a->type, V_ASN1_NEG_INTEGER); + ExpectIntEQ(ASN1_STRING_length(a), 1); + ExpectBufEQ(ASN1_STRING_get0_data(a), v81, 1); + ExpectIntEQ(ASN1_STRING_type(a), V_ASN1_NEG_INTEGER); + ExpectNotNull(dup = wolfSSL_ASN1_INTEGER_dup(a)); + ExpectIntEQ(ASN1_STRING_type(dup), V_ASN1_NEG_INTEGER); + ASN1_INTEGER_free(dup); + ASN1_INTEGER_free(a); + a = NULL; + +#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && defined(HAVE_ECC) + /* The DER serial has a leading zero octet. */ + ExpectNotNull(x509 = X509_load_certificate_file("./certs/test/digsigku.pem", + SSL_FILETYPE_PEM)); + ExpectIntEQ(X509_get_serialNumber(x509)->type, V_ASN1_INTEGER); + ExpectIntEQ(ASN1_STRING_type(X509_get_serialNumber(x509)), + V_ASN1_INTEGER); + ExpectIntEQ(ASN1_STRING_length(X509_get_serialNumber(x509)), + (int)sizeof(serial)); + ExpectBufEQ(ASN1_STRING_get0_data(X509_get_serialNumber(x509)), serial, + sizeof(serial)); + ExpectIntEQ(i2d_ASN1_INTEGER(X509_get_serialNumber(x509), &der), + (int)sizeof(serialDer)); + ExpectBufEQ(der, serialDer, sizeof(serialDer)); + XFREE(der, NULL, DYNAMIC_TYPE_ASN1); +#ifndef NO_BIO + ExpectNotNull(bio = BIO_new(BIO_s_mem())); + ExpectIntEQ(i2a_ASN1_INTEGER(bio, X509_get_serialNumber(x509)), 16); + ExpectIntEQ(BIO_get_mem_data(bio, &str), 16); + ExpectBufEQ(str, "E3814B48A5706170", 16); + BIO_free(bio); +#endif + X509_free(x509); +#endif +#endif + return EXPECT_RESULT(); +} + #if defined(OPENSSL_EXTRA) typedef struct ASN1IntTestVector { const byte* der; @@ -498,6 +701,9 @@ int test_wolfSSL_d2i_ASN1_INTEGER(void) 0xd2, 0x96, 0xdf, 0xd9, 0xd0, 0x4f, 0xad, 0xd7 }; static const byte garbageDer[] = {0xDE, 0xAD, 0xBE, 0xEF}; + /* Not minimal: OpenSSL rejects them. */ + static const byte padZeroDer[] = {0x02, 0x02, 0x00, 0x01}; + static const byte padOnesDer[] = {0x02, 0x02, 0xFF, 0x80}; /* Long-form length with INT_MAX content bytes for overflow testing */ static const byte overflowLenDer[] = {0x02, 0x84, 0x7F, 0xFF, 0xFF, 0xFF}; @@ -530,6 +736,12 @@ int test_wolfSSL_d2i_ASN1_INTEGER(void) p = garbageDer; ExpectNull((a = wolfSSL_d2i_ASN1_INTEGER(&b, &p, sizeof(garbageDer)))); ExpectNull(b); + p = padZeroDer; + ExpectNull((a = wolfSSL_d2i_ASN1_INTEGER(&b, &p, sizeof(padZeroDer)))); + ExpectNull(b); + p = padOnesDer; + ExpectNull((a = wolfSSL_d2i_ASN1_INTEGER(&b, &p, sizeof(padOnesDer)))); + ExpectNull(b); /* Only run on 64-bit systems where the `long` inSz param fits */ if (LONG_MAX >= 0x80000005L) { p = overflowLenDer; @@ -578,6 +790,7 @@ int test_wolfSSL_d2i_ASN1_INTEGER(void) c = NULL; if (testVectors[i].derSz <= sizeof(long)) { + ExpectIntEQ(wolfSSL_ASN1_INTEGER_get(a), testVectors[i].value); ExpectNotNull(c = wolfSSL_ASN1_INTEGER_new()); ExpectIntEQ(wolfSSL_ASN1_INTEGER_set(c, testVectors[i].value), 1); ExpectIntEQ(wolfSSL_ASN1_INTEGER_cmp(a, c), 0); diff --git a/tests/api/test_ossl_asn1.h b/tests/api/test_ossl_asn1.h index 7ae66eb0672..6c96929b93e 100644 --- a/tests/api/test_ossl_asn1.h +++ b/tests/api/test_ossl_asn1.h @@ -29,6 +29,7 @@ int test_wolfSSL_ASN1_INTEGER(void); int test_wolfSSL_ASN1_INTEGER_cmp(void); int test_wolfSSL_ASN1_INTEGER_BN(void); int test_wolfSSL_ASN1_INTEGER_get_set(void); +int test_wolfSSL_ASN1_INTEGER_STRING(void); int test_wolfSSL_d2i_ASN1_INTEGER(void); int test_wolfSSL_a2i_ASN1_INTEGER(void); int test_wolfSSL_i2c_ASN1_INTEGER(void); @@ -68,6 +69,7 @@ int test_ASN1_strings(void); TEST_DECL_GROUP("ossl_asn1_int", test_wolfSSL_ASN1_INTEGER_cmp), \ TEST_DECL_GROUP("ossl_asn1_int", test_wolfSSL_ASN1_INTEGER_BN), \ TEST_DECL_GROUP("ossl_asn1_int", test_wolfSSL_ASN1_INTEGER_get_set), \ + TEST_DECL_GROUP("ossl_asn1_int", test_wolfSSL_ASN1_INTEGER_STRING), \ TEST_DECL_GROUP("ossl_asn1_int", test_wolfSSL_d2i_ASN1_INTEGER), \ TEST_DECL_GROUP("ossl_asn1_int", test_wolfSSL_a2i_ASN1_INTEGER), \ TEST_DECL_GROUP("ossl_asn1_int", test_wolfSSL_i2c_ASN1_INTEGER) diff --git a/tests/api/test_ossl_dsa.c b/tests/api/test_ossl_dsa.c index 826f50b5e10..e396c0f2b2c 100644 --- a/tests/api/test_ossl_dsa.c +++ b/tests/api/test_ossl_dsa.c @@ -51,6 +51,10 @@ int test_DSA_do_sign_verify(void) word32 bytes; byte sigBin[DSA_SIG_SIZE]; int dsacheck; + DSA_SIG* longSig = NULL; + const BIGNUM* r0 = NULL; + const BIGNUM* s0 = NULL; + int i; #ifdef USE_CERT_BUFFERS_1024 byte tmp[ONEK_BUF]; @@ -86,6 +90,32 @@ int test_DSA_do_sign_verify(void) ExpectNotNull(sig = DSA_do_sign(digest, WC_SHA_DIGEST_SIZE, dsa)); ExpectIntEQ(DSA_do_verify(digest, WC_SHA_DIGEST_SIZE, sig, dsa), 1); + /* r and s must be less than q: r * 256 + 1 or s * 256 + 1 fails. */ + if (EXPECT_SUCCESS()) { + DSA_SIG_get0(sig, &r0, &s0); + } + for (i = 0; i < 2; i++) { + BIGNUM* r = NULL; + BIGNUM* s = NULL; + BIGNUM* big = NULL; + + ExpectNotNull(longSig = DSA_SIG_new()); + ExpectNotNull(r = BN_dup(r0)); + ExpectNotNull(s = BN_dup(s0)); + big = (i == 0) ? r : s; + ExpectIntEQ(BN_lshift(big, big, 8), 1); + ExpectIntEQ(BN_add_word(big, 1), 1); + ExpectIntEQ(DSA_SIG_set0(longSig, r, s), 1); + if (EXPECT_FAIL()) { + BN_free(r); + BN_free(s); + } + ExpectIntNE(DSA_do_verify(digest, WC_SHA_DIGEST_SIZE, longSig, dsa), + 1); + DSA_SIG_free(longSig); + longSig = NULL; + } + DSA_SIG_free(sig); DSA_free(dsa); #endif @@ -93,6 +123,48 @@ int test_DSA_do_sign_verify(void) return EXPECT_RESULT(); } +int test_wolfSSL_DSA_size(void) +{ + EXPECT_DECLS; +#if defined(OPENSSL_EXTRA) && !defined(NO_FILESYSTEM) && !defined(NO_DSA) + DSA* dsa = NULL; + byte der[TWOK_BUF]; + int derSz = 0; + XFILE fp = XBADFILE; + + ExpectIntEQ(DSA_size(NULL), -1); + ExpectNotNull(dsa = DSA_new()); + ExpectIntEQ(DSA_size(dsa), -1); + DSA_free(dsa); + dsa = NULL; + + /* q is 160 bits: SEQUENCE of two 21 byte INTEGERs. */ + ExpectTrue((fp = XFOPEN("./certs/dsa2048.der", "rb")) != XBADFILE); + ExpectIntGT(derSz = (int)XFREAD(der, 1, sizeof(der), fp), 0); + if (fp != XBADFILE) { + XFCLOSE(fp); + fp = XBADFILE; + } + ExpectNotNull(dsa = DSA_new()); + ExpectIntEQ(DSA_LoadDer(dsa, der, derSz), 1); + ExpectIntEQ(DSA_size(dsa), 48); + DSA_free(dsa); + dsa = NULL; + + /* q is 256 bits: SEQUENCE of two 33 byte INTEGERs. */ + ExpectTrue((fp = XFOPEN("./certs/dsa-pubkey-2048.der", "rb")) != XBADFILE); + ExpectIntGT(derSz = (int)XFREAD(der, 1, sizeof(der), fp), 0); + if (fp != XBADFILE) + XFCLOSE(fp); + ExpectNotNull(dsa = DSA_new()); + ExpectIntEQ(wolfSSL_DSA_LoadDer_ex(dsa, der, derSz, + WOLFSSL_DSA_LOAD_PUBLIC), 1); + ExpectIntEQ(DSA_size(dsa), 72); + DSA_free(dsa); +#endif + return EXPECT_RESULT(); +} + int test_wolfSSL_DSA_generate_parameters(void) { EXPECT_DECLS; @@ -107,6 +179,160 @@ int test_wolfSSL_DSA_generate_parameters(void) return EXPECT_RESULT(); } +int test_wolfSSL_DSA_do_sign_digest_len(void) +{ + EXPECT_DECLS; +#if !defined(HAVE_SELFTEST) && !defined(HAVE_FIPS) && \ + !defined(WC_FIPS_186_5_PLUS) && defined(OPENSSL_EXTRA) && \ + !defined(NO_FILESYSTEM) && !defined(NO_DSA) + /* OpenSSL signature of the digest below with certs/dsa2048.der. */ + static const unsigned char sigDer[] = { + 0x30, 0x2d, 0x02, 0x14, 0x47, 0xba, 0xa2, 0xa0, 0x80, 0xec, 0xd5, 0xd3, + 0xd4, 0x17, 0xa5, 0xa4, 0xc8, 0xc4, 0xe9, 0x6a, 0xfd, 0x56, 0x37, 0xf4, + 0x02, 0x15, 0x00, 0x86, 0x7f, 0xa1, 0x9c, 0x1e, 0x7b, 0xcc, 0x8b, 0xfa, + 0xb3, 0xc8, 0x47, 0xd8, 0x55, 0xc8, 0x86, 0x31, 0xe1, 0xc7, 0x74 + }; + const unsigned char* p = sigDer; + unsigned char digest[WC_SHA256_DIGEST_SIZE]; + DSA* dsa = NULL; + DSA_SIG* sig = NULL; + byte der[TWOK_BUF]; + int derSz = 0; + XFILE fp = XBADFILE; + + XMEMSET(digest, 0x5a, sizeof(digest)); + ExpectTrue((fp = XFOPEN("./certs/dsa2048.der", "rb")) != XBADFILE); + ExpectIntGT(derSz = (int)XFREAD(der, 1, sizeof(der), fp), 0); + if (fp != XBADFILE) + XFCLOSE(fp); + ExpectNotNull(dsa = DSA_new()); + ExpectIntEQ(DSA_LoadDer(dsa, der, derSz), 1); + + /* q is 160 bits: only the leftmost 20 bytes of the digest are used. */ + ExpectNotNull(sig = d2i_DSA_SIG(NULL, &p, (long)sizeof(sigDer))); + ExpectIntEQ(DSA_do_verify(digest, (int)sizeof(digest), sig, dsa), 1); + ExpectIntEQ(DSA_do_verify(digest, WC_SHA_DIGEST_SIZE, sig, dsa), 1); + DSA_SIG_free(sig); + sig = NULL; + + ExpectNotNull(sig = DSA_do_sign(digest, (int)sizeof(digest), dsa)); + ExpectIntEQ(DSA_do_verify(digest, WC_SHA_DIGEST_SIZE, sig, dsa), 1); + DSA_SIG_free(sig); + DSA_free(dsa); +#endif + return EXPECT_RESULT(); +} + +int test_wolfSSL_DSA_do_sign_q224(void) +{ + EXPECT_DECLS; +#if !defined(HAVE_SELFTEST) && !defined(HAVE_FIPS) && \ + !defined(WC_FIPS_186_5_PLUS) && defined(OPENSSL_EXTRA) && !defined(NO_DSA) + /* DSA key made by OpenSSL: p is 2048 bits, q is 224 bits. */ + static const unsigned char keyDer[] = { + 0x30, 0x82, 0x03, 0x4f, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00, + 0xd2, 0x59, 0xe9, 0xb1, 0xf3, 0xde, 0xae, 0x34, 0xf0, 0x7e, 0x89, 0x81, + 0x28, 0x9c, 0x2a, 0x57, 0x8c, 0x89, 0x73, 0xd9, 0xf8, 0xf2, 0x76, 0x1f, + 0x42, 0x09, 0x0f, 0x55, 0x69, 0xef, 0x71, 0xe1, 0x16, 0xb9, 0x1a, 0x15, + 0x48, 0xa7, 0xd9, 0xbb, 0xdd, 0xa1, 0xfa, 0x9d, 0xa0, 0x1c, 0xaa, 0xb2, + 0x4a, 0xe4, 0xff, 0x89, 0x37, 0xb4, 0x5c, 0xa4, 0xd6, 0x8b, 0x3d, 0xc8, + 0x92, 0x98, 0x80, 0x96, 0x79, 0xaa, 0x7f, 0xf6, 0xa7, 0x88, 0x02, 0xfd, + 0xa9, 0x60, 0x0b, 0x0c, 0x9b, 0xe9, 0x28, 0x7a, 0xa8, 0x72, 0x71, 0xa1, + 0x7a, 0xc4, 0x2a, 0xf5, 0x10, 0xbb, 0x15, 0xc6, 0x29, 0x7a, 0x25, 0x41, + 0x3d, 0x4a, 0xee, 0xf9, 0x59, 0x6d, 0x95, 0xde, 0xbe, 0x4f, 0xce, 0xa7, + 0xdb, 0xd5, 0x73, 0x07, 0xc2, 0x60, 0x12, 0x04, 0xca, 0x7b, 0x45, 0xb8, + 0x33, 0x3f, 0x0c, 0x93, 0x63, 0x58, 0x20, 0x45, 0xd4, 0xac, 0x86, 0x80, + 0xc6, 0x5b, 0xa8, 0xca, 0x47, 0xcd, 0xdb, 0xd9, 0xf8, 0xd7, 0xa8, 0x51, + 0xdd, 0x72, 0x42, 0x22, 0x28, 0x8c, 0x17, 0xe7, 0xd3, 0xa7, 0x1b, 0x82, + 0x8d, 0xaf, 0xdc, 0x92, 0x92, 0xea, 0xc0, 0x7b, 0xee, 0xbe, 0x6e, 0x21, + 0x78, 0xfa, 0x82, 0xb9, 0x8b, 0xc2, 0x1d, 0x14, 0x83, 0x6e, 0x66, 0xfe, + 0xed, 0x4e, 0x3e, 0xb3, 0x46, 0x1c, 0xcf, 0xd4, 0x8e, 0xb6, 0x6c, 0x92, + 0x9a, 0xea, 0xb3, 0xa2, 0xf2, 0xb2, 0xc7, 0xb8, 0x00, 0x61, 0x62, 0xaa, + 0x8c, 0x36, 0x72, 0xa6, 0x2b, 0xaa, 0x8c, 0x37, 0xcd, 0x3e, 0x45, 0xd6, + 0xfe, 0x01, 0x22, 0xc0, 0x7d, 0x65, 0x2c, 0xc0, 0x85, 0x5e, 0x14, 0x58, + 0x4a, 0x4d, 0x57, 0x12, 0xe0, 0xf0, 0x06, 0x2a, 0xbd, 0x23, 0x30, 0x33, + 0x17, 0x30, 0x3d, 0xf6, 0xe8, 0x83, 0x11, 0x65, 0xa1, 0xda, 0x8b, 0x4a, + 0x0c, 0xd9, 0x3e, 0xbf, 0x02, 0x1d, 0x00, 0xf4, 0x7a, 0xde, 0x83, 0x3f, + 0x3e, 0xc6, 0xa1, 0x18, 0xd9, 0x6b, 0xc6, 0x9d, 0x45, 0x05, 0xfb, 0x92, + 0xb2, 0x07, 0xdd, 0xdf, 0x01, 0x98, 0x67, 0x6f, 0xaf, 0xe8, 0x35, 0x02, + 0x82, 0x01, 0x01, 0x00, 0xad, 0xc5, 0x28, 0x1c, 0xfe, 0xfb, 0x29, 0x4f, + 0x6a, 0x00, 0x3b, 0x01, 0xd4, 0x06, 0x6f, 0x3c, 0x3b, 0xb1, 0x1b, 0xeb, + 0x35, 0x24, 0x1d, 0xe8, 0xb9, 0xac, 0x29, 0x9d, 0xbb, 0xf7, 0x33, 0x17, + 0xf6, 0xfa, 0xf3, 0xe9, 0xe2, 0xd2, 0x05, 0xaa, 0x88, 0x6c, 0x42, 0xb8, + 0xa5, 0xdb, 0x40, 0xa2, 0x67, 0x96, 0xad, 0x88, 0x94, 0x06, 0x2e, 0xc4, + 0x99, 0xe5, 0xd1, 0x4a, 0xf4, 0x86, 0x12, 0x60, 0xaf, 0xad, 0x7a, 0x65, + 0x69, 0xc1, 0x15, 0x96, 0xf4, 0xa4, 0x3e, 0x29, 0x77, 0x5d, 0x27, 0xce, + 0xa6, 0x58, 0x70, 0x4d, 0x6f, 0xf2, 0xb3, 0xc5, 0x09, 0x64, 0xd5, 0xe5, + 0x78, 0xb1, 0x08, 0x7d, 0xaa, 0x87, 0xda, 0x67, 0x02, 0xa3, 0xd2, 0x30, + 0xc5, 0xa3, 0xc6, 0x61, 0xfb, 0xa1, 0xa1, 0x31, 0x37, 0x0a, 0x2c, 0x3c, + 0x05, 0x69, 0x55, 0xcb, 0xdf, 0x2c, 0x27, 0xfc, 0x60, 0xd8, 0xd5, 0x10, + 0xd5, 0xb8, 0x2c, 0x9f, 0x33, 0xdb, 0x9d, 0x58, 0x78, 0x5f, 0xb8, 0x56, + 0x7d, 0xd6, 0x83, 0x87, 0xf3, 0xcd, 0x6d, 0x89, 0x01, 0x7a, 0xa0, 0x38, + 0xe2, 0xb1, 0x51, 0x03, 0x25, 0xd2, 0x23, 0x6c, 0x08, 0x95, 0xe4, 0xac, + 0x14, 0xa9, 0xf7, 0x7b, 0xab, 0x50, 0xf8, 0xe7, 0x98, 0x12, 0xd4, 0xb3, + 0xdf, 0x42, 0x5f, 0xec, 0x06, 0x4f, 0x3e, 0xa6, 0x3e, 0x38, 0x73, 0x27, + 0x36, 0xc4, 0x89, 0xef, 0x1e, 0x0e, 0x5e, 0x02, 0xb9, 0x68, 0x4d, 0xd0, + 0xbd, 0x5a, 0x4f, 0xc1, 0x84, 0x90, 0x62, 0xe3, 0xd9, 0xe2, 0x66, 0xcb, + 0xc5, 0x6b, 0xfb, 0xfb, 0xb0, 0xaa, 0x49, 0x51, 0x8a, 0xd3, 0xf0, 0xf9, + 0x4b, 0x44, 0x96, 0xa3, 0x24, 0xa4, 0x94, 0xca, 0xb9, 0xf7, 0x75, 0xde, + 0x0e, 0xa5, 0x7d, 0xee, 0xfe, 0x60, 0x1a, 0x32, 0x7c, 0xa5, 0x13, 0x5e, + 0xa0, 0x52, 0xb3, 0x76, 0x00, 0x37, 0x86, 0xeb, 0x02, 0x82, 0x01, 0x00, + 0x4a, 0xbf, 0x4a, 0xab, 0x69, 0xeb, 0xd2, 0x2d, 0x22, 0x23, 0xcc, 0x14, + 0x8b, 0x0f, 0xf8, 0x64, 0x14, 0x36, 0xae, 0xf7, 0xf2, 0x2a, 0x00, 0x6b, + 0xeb, 0x5e, 0xf4, 0x2b, 0x5e, 0x25, 0x67, 0x5c, 0x67, 0x62, 0x43, 0x2b, + 0x1a, 0x48, 0xff, 0xef, 0x54, 0x2b, 0x49, 0x2b, 0xfb, 0x81, 0xa9, 0xfb, + 0xd5, 0x13, 0x9e, 0x9d, 0xee, 0xf1, 0x94, 0x05, 0xa2, 0x99, 0x47, 0xe4, + 0xfc, 0xdb, 0xed, 0xff, 0x46, 0xae, 0x33, 0x3b, 0xf4, 0x5b, 0xd3, 0xb5, + 0x73, 0xc6, 0xb4, 0x12, 0x99, 0xa4, 0xac, 0xdc, 0xb2, 0x1a, 0xa5, 0xd1, + 0xcb, 0xa7, 0x78, 0xf8, 0x8f, 0x36, 0x02, 0xc4, 0x49, 0xfa, 0x1a, 0x73, + 0x78, 0x0f, 0xf3, 0xab, 0x49, 0x99, 0x96, 0x5f, 0x44, 0x41, 0xd6, 0xe5, + 0xff, 0xfd, 0x9a, 0xcf, 0x56, 0xa2, 0xcf, 0x77, 0x34, 0xed, 0xa4, 0xc1, + 0xd4, 0xbc, 0x3c, 0xcc, 0x75, 0xee, 0x74, 0xbc, 0x38, 0x8e, 0x8c, 0xe4, + 0x8b, 0x64, 0x51, 0xfa, 0xa3, 0xd6, 0x50, 0x5e, 0x26, 0x2f, 0x45, 0x3b, + 0xd4, 0x4b, 0x09, 0x40, 0x63, 0x84, 0xcc, 0xcb, 0x4c, 0xc2, 0x3f, 0x40, + 0x2e, 0xe9, 0x90, 0x6a, 0xda, 0x78, 0xc7, 0x60, 0xc9, 0xbe, 0xb2, 0x42, + 0xed, 0x11, 0xee, 0x91, 0xda, 0x1e, 0xc9, 0x70, 0xb0, 0x89, 0x31, 0x81, + 0x60, 0xc1, 0x03, 0x85, 0x57, 0x29, 0x49, 0x9b, 0x07, 0x06, 0x50, 0x0e, + 0x92, 0xf6, 0x29, 0xc7, 0x45, 0x32, 0x21, 0xd0, 0xd7, 0x20, 0x2f, 0x2f, + 0x05, 0xf1, 0x84, 0x06, 0x82, 0x04, 0x0d, 0xd9, 0x40, 0x0c, 0x3d, 0x03, + 0xa2, 0xda, 0x71, 0xc3, 0x17, 0x04, 0x00, 0x51, 0xdd, 0x5b, 0x54, 0x8f, + 0x1f, 0xfd, 0x56, 0x21, 0x26, 0x1e, 0x22, 0x32, 0xaa, 0x10, 0x6b, 0x97, + 0x42, 0x09, 0xec, 0x09, 0x83, 0xb4, 0x3e, 0x8f, 0x8d, 0x7f, 0x9b, 0x3d, + 0xbf, 0x74, 0x66, 0x89, 0x02, 0x1d, 0x00, 0xc8, 0x5f, 0x91, 0x9a, 0x20, + 0x7f, 0x5f, 0x25, 0xc3, 0xba, 0xe7, 0x4c, 0xf9, 0xe2, 0x44, 0x0e, 0x41, + 0x4d, 0xe5, 0x08, 0xa3, 0xbf, 0x5e, 0x54, 0xf0, 0xc5, 0x05, 0x28 + }; + /* OpenSSL signature of the digest below with keyDer. */ + static const unsigned char sigDer[] = { + 0x30, 0x3e, 0x02, 0x1d, 0x00, 0xd9, 0xd2, 0x9c, 0x09, 0x6d, 0x9c, 0x0b, + 0xae, 0x74, 0xb3, 0xf4, 0x0d, 0x85, 0x2b, 0x1c, 0xdf, 0xb1, 0x2d, 0x93, + 0xd5, 0x32, 0x09, 0xa3, 0x3d, 0xc8, 0xb0, 0x9c, 0x02, 0x02, 0x1d, 0x00, + 0xa6, 0x82, 0x48, 0xed, 0x20, 0xcd, 0x74, 0x17, 0x8d, 0x8a, 0x17, 0x19, + 0x4c, 0x8c, 0xae, 0x01, 0x60, 0x5c, 0xb8, 0x35, 0x11, 0x34, 0x48, 0xac, + 0x30, 0xf6, 0x21, 0x42 + }; + const unsigned char* p = sigDer; + unsigned char digest[WC_SHA256_DIGEST_SIZE]; + DSA* dsa = NULL; + DSA_SIG* sig = NULL; + + XMEMSET(digest, 0x5a, sizeof(digest)); + ExpectNotNull(dsa = DSA_new()); + ExpectIntEQ(DSA_LoadDer(dsa, keyDer, (int)sizeof(keyDer)), 1); + + ExpectNotNull(sig = d2i_DSA_SIG(NULL, &p, (long)sizeof(sigDer))); + ExpectIntEQ(DSA_do_verify(digest, (int)sizeof(digest), sig, dsa), 1); + DSA_SIG_free(sig); + sig = NULL; + + ExpectNotNull(sig = DSA_do_sign(digest, (int)sizeof(digest), dsa)); + ExpectIntEQ(DSA_do_verify(digest, (int)sizeof(digest), sig, dsa), 1); + DSA_SIG_free(sig); + DSA_free(dsa); +#endif + return EXPECT_RESULT(); +} + int test_wolfSSL_DSA_SIG(void) { EXPECT_DECLS; @@ -161,3 +387,71 @@ int test_wolfSSL_DSA_SIG(void) return EXPECT_RESULT(); } +int test_wolfSSL_DSA_public_key(void) +{ + EXPECT_DECLS; +#if !defined(HAVE_SELFTEST) && defined(OPENSSL_EXTRA) && \ + !defined(NO_FILESYSTEM) && !defined(NO_DSA) + DSA* dsa = NULL; + DSA_SIG* sig = NULL; + const BIGNUM* pub = NULL; + const BIGNUM* priv = NULL; + unsigned char digest[WC_SHA_DIGEST_SIZE]; + byte der[TWOK_BUF]; + int derSz = 0; + XFILE fp = XBADFILE; + + XMEMSET(digest, 0x5a, sizeof(digest)); + ExpectTrue((fp = XFOPEN("./certs/dsa-pubkey-2048.der", "rb")) != XBADFILE); + ExpectIntGT(derSz = (int)XFREAD(der, 1, sizeof(der), fp), 0); + if (fp != XBADFILE) + XFCLOSE(fp); + ExpectNotNull(dsa = DSA_new()); + ExpectIntEQ(wolfSSL_DSA_LoadDer_ex(dsa, der, derSz, + WOLFSSL_DSA_LOAD_PUBLIC), 1); + + /* A public key has no private key and can not sign. */ + DSA_get0_key(dsa, &pub, &priv); + ExpectNotNull(pub); + ExpectNull(priv); + ExpectNull(sig = DSA_do_sign(digest, (int)sizeof(digest), dsa)); + DSA_SIG_free(sig); + DSA_free(dsa); +#endif + return EXPECT_RESULT(); +} + +int test_wolfSSL_DSA_up_ref(void) +{ + EXPECT_DECLS; +#if !defined(HAVE_SELFTEST) && !defined(HAVE_FIPS) && \ + !defined(WC_FIPS_186_5_PLUS) && defined(OPENSSL_EXTRA) && \ + !defined(NO_FILESYSTEM) && !defined(NO_DSA) + DSA* dsa = NULL; + DSA_SIG* sig = NULL; + unsigned char digest[WC_SHA_DIGEST_SIZE]; + byte der[TWOK_BUF]; + int derSz = 0; + XFILE fp = XBADFILE; + + ExpectIntEQ(DSA_up_ref(NULL), 0); + + XMEMSET(digest, 0x5a, sizeof(digest)); + ExpectTrue((fp = XFOPEN("./certs/dsa2048.der", "rb")) != XBADFILE); + ExpectIntGT(derSz = (int)XFREAD(der, 1, sizeof(der), fp), 0); + if (fp != XBADFILE) + XFCLOSE(fp); + ExpectNotNull(dsa = DSA_new()); + ExpectIntEQ(DSA_LoadDer(dsa, der, derSz), 1); + ExpectIntEQ(DSA_up_ref(dsa), 1); + if (EXPECT_SUCCESS()) { + /* Releases the reference taken above. The key stays usable. */ + DSA_free(dsa); + } + ExpectNotNull(sig = DSA_do_sign(digest, (int)sizeof(digest), dsa)); + ExpectIntEQ(DSA_do_verify(digest, (int)sizeof(digest), sig, dsa), 1); + DSA_SIG_free(sig); + DSA_free(dsa); +#endif + return EXPECT_RESULT(); +} diff --git a/tests/api/test_ossl_dsa.h b/tests/api/test_ossl_dsa.h index 04cd83d0da2..192dcc00554 100644 --- a/tests/api/test_ossl_dsa.h +++ b/tests/api/test_ossl_dsa.h @@ -25,13 +25,23 @@ #include int test_DSA_do_sign_verify(void); +int test_wolfSSL_DSA_size(void); int test_wolfSSL_DSA_generate_parameters(void); +int test_wolfSSL_DSA_do_sign_digest_len(void); +int test_wolfSSL_DSA_do_sign_q224(void); int test_wolfSSL_DSA_SIG(void); +int test_wolfSSL_DSA_public_key(void); +int test_wolfSSL_DSA_up_ref(void); #define TEST_OSSL_DSA_DECLS \ TEST_DECL_GROUP("ossl_dsa", test_DSA_do_sign_verify), \ + TEST_DECL_GROUP("ossl_dsa", test_wolfSSL_DSA_size), \ TEST_DECL_GROUP("ossl_dsa", test_wolfSSL_DSA_generate_parameters), \ - TEST_DECL_GROUP("ossl_dsa", test_wolfSSL_DSA_SIG) + TEST_DECL_GROUP("ossl_dsa", test_wolfSSL_DSA_do_sign_digest_len), \ + TEST_DECL_GROUP("ossl_dsa", test_wolfSSL_DSA_do_sign_q224), \ + TEST_DECL_GROUP("ossl_dsa", test_wolfSSL_DSA_SIG), \ + TEST_DECL_GROUP("ossl_dsa", test_wolfSSL_DSA_public_key), \ + TEST_DECL_GROUP("ossl_dsa", test_wolfSSL_DSA_up_ref) #endif /* WOLFCRYPT_TEST_OSSL_DSA_H */ diff --git a/tests/api/test_ossl_ec.c b/tests/api/test_ossl_ec.c index 823276ad8cd..fb80275339a 100644 --- a/tests/api/test_ossl_ec.c +++ b/tests/api/test_ossl_ec.c @@ -1208,6 +1208,35 @@ int test_wolfSSL_EC_curve(void) return EXPECT_RESULT(); } +int test_wolfSSL_EC_curve_short_names(void) +{ + EXPECT_DECLS; +#if defined(OPENSSL_EXTRA) && defined(HAVE_ECC) + static const struct { + int nid; + const char* sn; + } curves[] = { + { NID_X9_62_prime192v1, SN_X9_62_prime192v1 }, + { NID_X9_62_prime192v2, SN_X9_62_prime192v2 }, + { NID_X9_62_prime192v3, SN_X9_62_prime192v3 }, + { NID_X9_62_prime239v1, SN_X9_62_prime239v1 }, + { NID_X9_62_prime239v2, SN_X9_62_prime239v2 }, + { NID_X9_62_prime239v3, SN_X9_62_prime239v3 }, + { NID_X9_62_prime256v1, SN_X9_62_prime256v1 }, + { NID_secp224r1, SN_secp224r1 }, + { NID_secp384r1, SN_secp384r1 }, + { NID_secp521r1, SN_secp521r1 }, + }; + size_t i; + + for (i = 0; i < sizeof(curves) / sizeof(curves[0]); i++) { + ExpectStrEQ(OBJ_nid2sn(curves[i].nid), curves[i].sn); + ExpectIntEQ(OBJ_sn2nid(curves[i].sn), curves[i].nid); + } +#endif + return EXPECT_RESULT(); +} + int test_wolfSSL_EC_KEY_dup(void) { EXPECT_DECLS; @@ -1607,13 +1636,17 @@ int test_wolfSSL_ECDSA_SIG(void) ExpectIntEQ(XMEMCMP(sigData, outSig, 8), 0); p = NULL; + ExpectIntEQ(wolfSSL_i2d_ECDSA_SIG(NULL, &p), 0); + ExpectNull(p); ExpectIntEQ(wolfSSL_i2d_ECDSA_SIG(sig, &p), 8); #ifndef WOLFSSL_I2D_ECDSA_SIG_ALLOC + /* Only the length. */ ExpectNull(p); #else + /* A new buffer starting with the encoding, as in OpenSSL. */ ExpectNotNull(p); ExpectIntEQ(XMEMCMP(p, outSig, 8), 0); - XFREE(p, NULL, DYNAMIC_TYPE_OPENSSL); + OPENSSL_free(p); #endif wolfSSL_ECDSA_SIG_free(sig); @@ -1621,6 +1654,67 @@ int test_wolfSSL_ECDSA_SIG(void) return EXPECT_RESULT(); } +#if defined(OPENSSL_EXTRA) && defined(WOLFSSL_I2D_ECDSA_SIG_ALLOC) && \ + defined(USE_WOLFSSL_MEMORY) && !defined(WOLFSSL_NO_MALLOC) && \ + !defined(WOLFSSL_STATIC_MEMORY) && !defined(WOLFSSL_DEBUG_MEMORY) +#define TEST_I2D_ECDSA_SIG_OOM +static wolfSSL_Malloc_cb test_i2d_ecdsa_sig_prev_malloc = NULL; +static int test_i2d_ecdsa_sig_allocs = 0; + +/* Only the first allocation succeeds. */ +static void* test_i2d_ecdsa_sig_malloc(size_t size) +{ + if (test_i2d_ecdsa_sig_allocs++ > 0) + return NULL; + if (test_i2d_ecdsa_sig_prev_malloc != NULL) + return test_i2d_ecdsa_sig_prev_malloc(size); + return malloc(size); +} +#endif + +/* i2d_ECDSA_SIG frees the buffer it allocated when encoding fails. Only math + * libraries that allocate while encoding can fail here. */ +int test_wolfSSL_i2d_ECDSA_SIG_oom(void) +{ + EXPECT_DECLS; +#ifdef TEST_I2D_ECDSA_SIG_OOM + WOLFSSL_ECDSA_SIG* sig = NULL; + const unsigned char* cp = NULL; + unsigned char* p = NULL; + unsigned char sigData[8] = + { 0x30, 0x06, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01 }; + wolfSSL_Malloc_cb prevM = NULL; + wolfSSL_Free_cb prevF = NULL; + wolfSSL_Realloc_cb prevR = NULL; + int len = 0; + + cp = sigData; + ExpectNotNull(sig = wolfSSL_d2i_ECDSA_SIG(NULL, &cp, sizeof(sigData))); + + ExpectIntEQ(wolfSSL_GetAllocators(&prevM, &prevF, &prevR), 0); + test_i2d_ecdsa_sig_prev_malloc = prevM; + test_i2d_ecdsa_sig_allocs = 0; + ExpectIntEQ(wolfSSL_SetAllocators(test_i2d_ecdsa_sig_malloc, prevF, + prevR), 0); + len = wolfSSL_i2d_ECDSA_SIG(sig, &p); + (void)wolfSSL_SetAllocators(prevM, prevF, prevR); + test_i2d_ecdsa_sig_prev_malloc = NULL; + + if (len == 0) { + ExpectNull(p); + } + else { + ExpectIntEQ(len, sizeof(sigData)); + ExpectNotNull(p); + ExpectIntEQ(XMEMCMP(p, sigData, sizeof(sigData)), 0); + } + + OPENSSL_free(p); + wolfSSL_ECDSA_SIG_free(sig); +#endif + return EXPECT_RESULT(); +} + int test_ECDSA_size_sign(void) { EXPECT_DECLS; diff --git a/tests/api/test_ossl_ec.h b/tests/api/test_ossl_ec.h index 52fc422caa1..2e542dcea35 100644 --- a/tests/api/test_ossl_ec.h +++ b/tests/api/test_ossl_ec.h @@ -34,6 +34,7 @@ int test_wolfSSL_SPAKE(void); int test_wolfSSL_EC_KEY_generate(void); int test_EC_i2d(void); int test_wolfSSL_EC_curve(void); +int test_wolfSSL_EC_curve_short_names(void); int test_wolfSSL_EC_KEY_dup(void); int test_wolfSSL_EC_KEY_set_group(void); int test_wolfSSL_EC_KEY_set_conv_form(void); @@ -42,6 +43,7 @@ int test_wolfSSL_EC_KEY_public_key(void); int test_wolfSSL_EC_KEY_print_fp(void); int test_wolfSSL_EC_get_builtin_curves(void); int test_wolfSSL_ECDSA_SIG(void); +int test_wolfSSL_i2d_ECDSA_SIG_oom(void); int test_ECDSA_size_sign(void); int test_ECDSA_do_verify_oversized_sig(void); int test_ECDH_compute_key(void); @@ -58,6 +60,7 @@ int test_wolfSSL_EC_POINT_point2hex_oversized(void); TEST_DECL_GROUP("ossl_ec", test_wolfSSL_EC_KEY_generate), \ TEST_DECL_GROUP("ossl_ec", test_EC_i2d), \ TEST_DECL_GROUP("ossl_ec", test_wolfSSL_EC_curve), \ + TEST_DECL_GROUP("ossl_ec", test_wolfSSL_EC_curve_short_names), \ TEST_DECL_GROUP("ossl_ec", test_wolfSSL_EC_KEY_dup), \ TEST_DECL_GROUP("ossl_ec", test_wolfSSL_EC_KEY_set_group), \ TEST_DECL_GROUP("ossl_ec", test_wolfSSL_EC_KEY_set_conv_form), \ @@ -66,6 +69,7 @@ int test_wolfSSL_EC_POINT_point2hex_oversized(void); TEST_DECL_GROUP("ossl_ec", test_wolfSSL_EC_KEY_print_fp), \ TEST_DECL_GROUP("ossl_ec", test_wolfSSL_EC_get_builtin_curves), \ TEST_DECL_GROUP("ossl_ec", test_wolfSSL_ECDSA_SIG), \ + TEST_DECL_GROUP("ossl_ec", test_wolfSSL_i2d_ECDSA_SIG_oom), \ TEST_DECL_GROUP("ossl_ec", test_ECDSA_size_sign), \ TEST_DECL_GROUP("ossl_ec", test_ECDSA_do_verify_oversized_sig), \ TEST_DECL_GROUP("ossl_ec", test_ECDH_compute_key), \ diff --git a/tests/api/test_ossl_obj.c b/tests/api/test_ossl_obj.c index 178aa9444e5..0f8b9557c13 100644 --- a/tests/api/test_ossl_obj.c +++ b/tests/api/test_ossl_obj.c @@ -259,6 +259,33 @@ int test_wolfSSL_OBJ_cmp(void) ExpectIntEQ(OBJ_cmp(obj, obj), 0); ExpectIntEQ(OBJ_cmp(obj2, obj2), 0); + ASN1_OBJECT_free(obj); + obj = NULL; + ASN1_OBJECT_free(obj2); + obj2 = NULL; + + /* Name attribute types differ. */ + ExpectNotNull(obj = OBJ_nid2obj(NID_commonName)); + ExpectNotNull(obj2 = OBJ_nid2obj(NID_organizationName)); + ExpectIntNE(OBJ_cmp(obj, obj2), 0); + ExpectIntEQ(OBJ_cmp(obj, obj2), -OBJ_cmp(obj2, obj)); + ExpectIntEQ(OBJ_cmp(obj, obj), 0); + ASN1_OBJECT_free(obj2); + obj2 = NULL; + ExpectNotNull(obj2 = OBJ_nid2obj(NID_commonName)); + ExpectIntEQ(OBJ_cmp(obj, obj2), 0); +#if defined(WOLFSSL_CERT_EXT) && defined(WOLFSSL_CERT_GEN) + ASN1_OBJECT_free(obj2); + obj2 = NULL; + ExpectNotNull(obj2 = OBJ_txt2obj("2.5.4.3", 1)); + ExpectIntEQ(OBJ_cmp(obj, obj2), 0); + ExpectIntEQ(OBJ_cmp(obj2, obj), 0); + ASN1_OBJECT_free(obj2); + obj2 = NULL; + ExpectNotNull(obj2 = OBJ_txt2obj("2.5.4.10", 1)); + ExpectIntNE(OBJ_cmp(obj, obj2), 0); +#endif + ASN1_OBJECT_free(obj); ASN1_OBJECT_free(obj2); #endif diff --git a/tests/api/test_ossl_p7p12.c b/tests/api/test_ossl_p7p12.c index 60eca703497..36cd7e03061 100644 --- a/tests/api/test_ossl_p7p12.c +++ b/tests/api/test_ossl_p7p12.c @@ -2048,3 +2048,474 @@ int test_wolfSSL_PKCS12_create_mac(void) #endif return EXPECT_RESULT(); } +int test_wolfSSL_PKCS12_alias_keyid(void) +{ + EXPECT_DECLS; +#if defined(OPENSSL_EXTRA) && defined(HAVE_PKCS12) && !defined(HAVE_FIPS) && \ + !defined(NO_ASN) && !defined(NO_PWDBASED) && defined(HAVE_ECC) && \ + defined(WOLFSSL_AES_256) && defined(HAVE_AES_CBC) && \ + !defined(NO_SHA256) && !defined(NO_HMAC) && !defined(NO_BIO) + /* certs/ecc-key.pem, certs/server-ecc.pem and certs/ca-ecc-cert.pem + * exported by OpenSSL with friendlyName "wolfSSL e-acute euro", CA + * friendlyName "wolfSSL CA" and password "wolfSSL test". */ + static const unsigned char p12Der[] = { + 0x30, 0x82, 0x08, 0x71, 0x02, 0x01, 0x03, 0x30, 0x82, 0x08, 0x27, 0x06, + 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x82, + 0x08, 0x18, 0x04, 0x82, 0x08, 0x14, 0x30, 0x82, 0x08, 0x10, 0x30, 0x82, + 0x06, 0xa2, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, + 0x06, 0xa0, 0x82, 0x06, 0x93, 0x30, 0x82, 0x06, 0x8f, 0x02, 0x01, 0x00, + 0x30, 0x82, 0x06, 0x88, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, + 0x01, 0x07, 0x01, 0x30, 0x57, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x05, 0x0d, 0x30, 0x4a, 0x30, 0x29, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x05, 0x0c, 0x30, 0x1c, 0x04, 0x08, 0xe3, + 0x7a, 0xf6, 0xc3, 0x04, 0x02, 0x3a, 0x27, 0x02, 0x02, 0x08, 0x00, 0x30, + 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x09, 0x05, + 0x00, 0x30, 0x1d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, + 0x01, 0x2a, 0x04, 0x10, 0xfd, 0x28, 0x04, 0xb1, 0xe9, 0xe7, 0x98, 0x9d, + 0x18, 0x42, 0x8f, 0x77, 0xfc, 0x4a, 0xf7, 0xf5, 0x80, 0x82, 0x06, 0x20, + 0x01, 0xf8, 0xc3, 0x28, 0x3e, 0x45, 0x4e, 0x7a, 0xf1, 0x22, 0xa4, 0x7f, + 0xfa, 0x54, 0x72, 0xaa, 0x3c, 0x47, 0x39, 0xd0, 0x01, 0xdc, 0x10, 0x2b, + 0x2c, 0x4c, 0x45, 0xff, 0x7b, 0xd2, 0x20, 0x1e, 0xb4, 0x3a, 0xb1, 0xc4, + 0x9c, 0xa4, 0x07, 0x14, 0x81, 0x4f, 0xdb, 0xd4, 0x58, 0x2b, 0x2d, 0x6c, + 0xfe, 0xec, 0x68, 0x79, 0xc3, 0x15, 0x38, 0x84, 0x26, 0x6f, 0xc9, 0xb9, + 0x7b, 0xbc, 0x91, 0x9e, 0xa9, 0xea, 0xb3, 0x86, 0x13, 0x35, 0xb7, 0x0c, + 0xee, 0xde, 0x4f, 0xb1, 0x9a, 0x41, 0x5b, 0xc9, 0x3c, 0xfe, 0xd0, 0x1a, + 0xf0, 0x13, 0x62, 0xbb, 0xd4, 0x9d, 0xda, 0xca, 0x91, 0xca, 0x7c, 0x16, + 0x46, 0x6b, 0xad, 0x29, 0x76, 0x29, 0x92, 0x70, 0xfd, 0x1f, 0x8d, 0xfb, + 0x55, 0xf6, 0x3d, 0xd6, 0xdd, 0x72, 0x19, 0xb6, 0x7b, 0x52, 0x42, 0x70, + 0xd8, 0x48, 0x6a, 0x70, 0x79, 0x5f, 0xf8, 0x95, 0xef, 0xb9, 0xe0, 0x01, + 0x5b, 0x69, 0xe8, 0xf4, 0xa8, 0x1f, 0xdc, 0x13, 0x95, 0x08, 0xf2, 0x9a, + 0x87, 0xa2, 0x56, 0x0c, 0x69, 0x18, 0x9e, 0xf7, 0x47, 0x17, 0xcf, 0x53, + 0x9d, 0x58, 0x7f, 0x01, 0xf2, 0x03, 0x8c, 0x0f, 0xe9, 0x71, 0x0e, 0x89, + 0x8f, 0x27, 0x62, 0x29, 0x37, 0xdc, 0xd0, 0x2d, 0x31, 0x53, 0x31, 0x0d, + 0x96, 0xd5, 0x82, 0xd4, 0xe9, 0xba, 0xec, 0xe8, 0x55, 0x38, 0xaa, 0xb6, + 0x82, 0x8a, 0xcf, 0x63, 0x6a, 0xb6, 0x15, 0x75, 0x76, 0x77, 0x7e, 0x5b, + 0xae, 0xf2, 0x1d, 0xf8, 0x45, 0x38, 0x67, 0x63, 0x9f, 0x18, 0xb1, 0x85, + 0x65, 0x74, 0x5c, 0xa0, 0x12, 0x6f, 0xed, 0x55, 0xd6, 0x35, 0xbe, 0x8e, + 0x62, 0x57, 0x9f, 0xae, 0x87, 0xee, 0x75, 0x24, 0x6b, 0x21, 0x3b, 0x18, + 0xd6, 0xcc, 0xbe, 0x01, 0x4b, 0x7c, 0x40, 0xfb, 0x35, 0xbc, 0x1e, 0x6d, + 0xfa, 0xc9, 0x2b, 0x35, 0xcd, 0x84, 0xb5, 0x9a, 0x26, 0x11, 0xb2, 0x13, + 0x69, 0x27, 0x4f, 0xf9, 0x08, 0x6d, 0x25, 0x10, 0xfb, 0x88, 0x0c, 0xef, + 0xfb, 0x9e, 0x18, 0x6e, 0x14, 0x2b, 0xe1, 0x4c, 0x14, 0x0f, 0xe8, 0x16, + 0xee, 0x91, 0x1c, 0x79, 0x3a, 0x36, 0x8b, 0x45, 0x3c, 0xdc, 0x53, 0xf5, + 0x60, 0x26, 0xe5, 0xf5, 0x75, 0x32, 0xdd, 0xb0, 0x40, 0x4c, 0x8d, 0xe6, + 0xf3, 0x04, 0x85, 0x89, 0xe6, 0xb0, 0x32, 0xa1, 0x54, 0xc8, 0xe0, 0x48, + 0xfb, 0x57, 0xce, 0xc5, 0xd5, 0xe8, 0xde, 0xc7, 0xfb, 0x1e, 0x21, 0x2d, + 0x87, 0x24, 0x7a, 0xeb, 0x8c, 0x7c, 0x57, 0xb2, 0xcb, 0x37, 0x0e, 0x2e, + 0x06, 0x9a, 0x31, 0x8f, 0x5a, 0x5b, 0x9e, 0xc8, 0x4a, 0xf2, 0x77, 0x58, + 0x42, 0xc5, 0x29, 0x89, 0x11, 0x59, 0x1b, 0xf2, 0xd0, 0xb8, 0x31, 0xee, + 0x01, 0x44, 0x7a, 0x90, 0x76, 0x0f, 0x6d, 0x85, 0xb0, 0xa7, 0x9a, 0x00, + 0x4b, 0xdd, 0x14, 0x22, 0x95, 0x7b, 0x05, 0x19, 0x11, 0xe1, 0xe0, 0xfe, + 0x43, 0x67, 0xb4, 0xd7, 0xc8, 0x87, 0x47, 0x19, 0xfc, 0xd1, 0xe9, 0xc8, + 0xcf, 0xa8, 0x66, 0x0d, 0xd2, 0xd8, 0x64, 0xdc, 0x43, 0xec, 0x74, 0x86, + 0x4f, 0xa6, 0xd7, 0x42, 0x58, 0x35, 0xee, 0x2e, 0xea, 0xb1, 0xad, 0xd1, + 0xc1, 0xa3, 0x4d, 0x99, 0x3f, 0x15, 0x0d, 0x46, 0x78, 0x6a, 0xf9, 0xae, + 0x59, 0x1f, 0x54, 0x8e, 0x90, 0xe6, 0xc9, 0xb7, 0x18, 0x3c, 0x22, 0xa1, + 0x75, 0xa2, 0x11, 0xc0, 0xbe, 0x8d, 0xa4, 0x38, 0x63, 0x6e, 0x62, 0x60, + 0x6b, 0x0b, 0x61, 0x95, 0xe9, 0x30, 0xe5, 0x08, 0x37, 0x21, 0xc7, 0x31, + 0x63, 0x35, 0xd9, 0x7b, 0x87, 0xb8, 0x7d, 0x2c, 0xed, 0x4f, 0x8e, 0xac, + 0xa5, 0xdb, 0xa9, 0x83, 0x5f, 0xc7, 0x8b, 0x7b, 0xf7, 0x08, 0x9e, 0x82, + 0x4b, 0x37, 0x6a, 0x52, 0x6d, 0xc3, 0xbf, 0x4b, 0x81, 0x2d, 0xf9, 0x46, + 0xc4, 0xe6, 0x71, 0x73, 0xb9, 0x3e, 0x7b, 0x7e, 0xc7, 0x13, 0x20, 0xd6, + 0x78, 0xf8, 0xb9, 0x56, 0xa4, 0x06, 0x68, 0x2c, 0x50, 0xf1, 0x07, 0x40, + 0x72, 0x4e, 0xb2, 0x4d, 0xa2, 0x08, 0x31, 0xe2, 0x36, 0xe5, 0xb3, 0x63, + 0x28, 0xd4, 0x99, 0x0d, 0x06, 0x1e, 0x13, 0xba, 0x3f, 0xab, 0xff, 0xab, + 0x69, 0x1b, 0xbc, 0x68, 0xbb, 0xe1, 0xfb, 0x76, 0xf8, 0x97, 0x8a, 0x85, + 0xbe, 0x31, 0x45, 0x4f, 0xb2, 0x6e, 0x18, 0x6e, 0x4a, 0x98, 0x42, 0x7b, + 0x0a, 0x85, 0xc1, 0xba, 0x87, 0xd5, 0xa3, 0xb8, 0xd2, 0x3f, 0xd4, 0x3b, + 0x50, 0x47, 0x54, 0xe8, 0xfd, 0x8b, 0xf6, 0x97, 0x77, 0x0d, 0x6c, 0xe6, + 0x45, 0x71, 0x00, 0x90, 0x03, 0xce, 0xe2, 0x5f, 0xda, 0x27, 0xfb, 0xae, + 0xf9, 0xe8, 0x69, 0x15, 0x10, 0x28, 0x9b, 0x03, 0x4e, 0xf7, 0x67, 0xec, + 0xcc, 0x9d, 0xd9, 0x4b, 0x8d, 0x6f, 0x5b, 0x37, 0xb9, 0x07, 0xae, 0xce, + 0x5a, 0x79, 0xa4, 0xa7, 0xf5, 0x1a, 0x45, 0x83, 0xa2, 0x41, 0xd5, 0x50, + 0xb2, 0xd3, 0xc6, 0x26, 0xd7, 0x92, 0xea, 0xd1, 0x72, 0xb9, 0xc5, 0xd5, + 0x12, 0x27, 0xda, 0x1f, 0x51, 0xc1, 0xe4, 0x09, 0x2a, 0xeb, 0x58, 0x6a, + 0xb2, 0x6d, 0x67, 0xfa, 0x1d, 0x5c, 0x6a, 0x3a, 0xa8, 0x59, 0xae, 0x54, + 0x68, 0xca, 0x60, 0xbe, 0xf8, 0x04, 0x3f, 0xbe, 0x49, 0xc9, 0x8d, 0x10, + 0x20, 0x76, 0xfa, 0x6c, 0x6d, 0x02, 0x9a, 0x5d, 0xd5, 0xef, 0xa2, 0xd2, + 0xfd, 0xfd, 0x23, 0x0c, 0xa9, 0x02, 0x16, 0xdd, 0x1c, 0x08, 0x21, 0x77, + 0x8a, 0xbb, 0xe6, 0xa2, 0x6b, 0xbc, 0x3a, 0x42, 0x5e, 0xf9, 0xf6, 0xc0, + 0x18, 0x5b, 0x74, 0xd3, 0x83, 0x69, 0x04, 0xd5, 0x5f, 0xed, 0x3a, 0xab, + 0x7a, 0xb4, 0xbb, 0x9f, 0x1f, 0xde, 0x78, 0x83, 0xd8, 0x5a, 0xb2, 0xa1, + 0x3f, 0xb2, 0xa2, 0xa3, 0xe2, 0x1c, 0xbf, 0xc0, 0x99, 0x61, 0x98, 0xb7, + 0x0f, 0xd9, 0x04, 0xdc, 0x0b, 0xf9, 0x45, 0xde, 0x51, 0xbb, 0x08, 0xcb, + 0xee, 0x9c, 0xad, 0x07, 0xf3, 0x30, 0xb2, 0x8b, 0xff, 0x65, 0x75, 0xe5, + 0x5b, 0xf6, 0x3b, 0x43, 0xeb, 0x20, 0xb1, 0x2d, 0xe4, 0xe8, 0xf9, 0xd0, + 0x70, 0x7d, 0x84, 0x22, 0xa3, 0x8c, 0x95, 0x5e, 0x6e, 0x30, 0x69, 0x3e, + 0xa0, 0x73, 0xca, 0xe9, 0x7f, 0x7f, 0x6a, 0x55, 0xdd, 0x26, 0xb4, 0xb7, + 0xa7, 0x4c, 0x73, 0x9a, 0x45, 0x3b, 0xab, 0x19, 0xee, 0x1e, 0x59, 0x31, + 0x20, 0x50, 0x27, 0x5f, 0xed, 0x02, 0x9b, 0xd9, 0x82, 0x8f, 0x28, 0x9a, + 0x19, 0x95, 0x4b, 0x28, 0x0a, 0xa6, 0x0e, 0x2c, 0xa8, 0x84, 0x82, 0x26, + 0xbb, 0xc2, 0x89, 0xce, 0xf8, 0x5b, 0xac, 0x82, 0xf7, 0xa0, 0x30, 0x5c, + 0xd4, 0xde, 0x28, 0x74, 0xa9, 0xd9, 0xb3, 0xc6, 0x06, 0xe7, 0xdf, 0x8b, + 0x75, 0x87, 0x6b, 0xc3, 0xbb, 0xad, 0x37, 0x02, 0x60, 0xd4, 0x12, 0x13, + 0x0f, 0x77, 0xc1, 0xb1, 0x09, 0xc2, 0x22, 0x68, 0x45, 0x71, 0xcb, 0x70, + 0xcc, 0xe9, 0x1d, 0x31, 0x87, 0x03, 0x7a, 0xa2, 0x14, 0x33, 0x17, 0x7c, + 0x6c, 0x9b, 0xd6, 0x85, 0x82, 0x2d, 0x53, 0x0d, 0xee, 0x17, 0x33, 0x63, + 0xee, 0x71, 0x45, 0x7c, 0xed, 0x62, 0xba, 0x9d, 0xc6, 0xd8, 0xf9, 0x04, + 0x50, 0x1f, 0x12, 0xcd, 0xe9, 0xea, 0x76, 0x4d, 0xd6, 0x9e, 0x93, 0x1e, + 0xab, 0x15, 0x3f, 0xe5, 0x2a, 0x2c, 0xff, 0x0f, 0xb3, 0xcb, 0xdb, 0x0f, + 0xe0, 0x48, 0xba, 0x51, 0x8d, 0x80, 0x80, 0x54, 0x8d, 0x52, 0xd3, 0xc4, + 0xd5, 0x1a, 0xc8, 0x1b, 0x74, 0xc2, 0x4f, 0xb5, 0xf8, 0xaa, 0xc2, 0xd0, + 0x30, 0x49, 0x0d, 0x10, 0xb6, 0xc3, 0x41, 0x45, 0xcd, 0x52, 0x33, 0x9e, + 0x46, 0xc5, 0x64, 0x22, 0x22, 0x1f, 0x6e, 0xd2, 0x9f, 0x20, 0xf5, 0x4b, + 0xa5, 0x99, 0x89, 0x42, 0x60, 0xb3, 0xbf, 0x29, 0xe6, 0x2a, 0x3f, 0x1c, + 0xc1, 0x38, 0x76, 0x66, 0xe3, 0x52, 0x09, 0x90, 0x08, 0xd0, 0x7a, 0x73, + 0x7e, 0x57, 0x3a, 0xc3, 0x9a, 0x83, 0xa5, 0xe0, 0x4d, 0xb6, 0x5d, 0xb1, + 0x48, 0x34, 0xf7, 0x27, 0x9a, 0xf7, 0x4c, 0x17, 0xd1, 0xda, 0xed, 0x38, + 0x91, 0xf2, 0x53, 0xab, 0x1e, 0xef, 0x42, 0x3b, 0xb8, 0x7a, 0x10, 0x10, + 0x8a, 0xa6, 0x87, 0xd0, 0x26, 0x50, 0x7d, 0x25, 0xf4, 0x7b, 0x33, 0xdc, + 0x03, 0xd4, 0x16, 0x15, 0xfe, 0xb1, 0x26, 0xc9, 0x6e, 0x4f, 0x62, 0xa3, + 0x98, 0xde, 0xcd, 0xfd, 0xa8, 0xb2, 0x36, 0xa2, 0xcb, 0xed, 0x90, 0x59, + 0x58, 0x6b, 0xf6, 0xc3, 0x68, 0x17, 0x2b, 0x98, 0xb9, 0x30, 0xd1, 0x7e, + 0x66, 0x47, 0x95, 0x39, 0x6e, 0xd7, 0xa3, 0x29, 0x5e, 0x8a, 0x1a, 0x65, + 0xe9, 0x88, 0x8a, 0x20, 0x3b, 0x27, 0x80, 0x09, 0x40, 0x3b, 0x66, 0xa9, + 0x40, 0x03, 0xa3, 0x65, 0x67, 0x97, 0x22, 0xa0, 0x31, 0x4f, 0x2c, 0x44, + 0x07, 0x8a, 0x97, 0xf0, 0x8a, 0xd9, 0x63, 0xc2, 0xd5, 0x82, 0xca, 0xc3, + 0x84, 0xff, 0xec, 0xa7, 0x43, 0x9c, 0x51, 0x34, 0xf5, 0xca, 0x8c, 0xeb, + 0xb6, 0x47, 0xdf, 0x6d, 0x2f, 0xdf, 0x9e, 0xe8, 0xf7, 0x1b, 0x6f, 0x28, + 0xff, 0x11, 0x18, 0xb9, 0xb2, 0x96, 0x07, 0xab, 0x6a, 0x4b, 0x14, 0x99, + 0x47, 0xe5, 0x77, 0xd0, 0x76, 0xf9, 0x8e, 0x29, 0x24, 0x0d, 0xa3, 0x3a, + 0x02, 0xaf, 0xa9, 0x89, 0x0e, 0xed, 0xb8, 0xcb, 0xf4, 0xc5, 0xcd, 0x24, + 0x80, 0x32, 0x40, 0x6a, 0x72, 0x4b, 0x7f, 0xf4, 0xef, 0xbd, 0xc7, 0x22, + 0xc6, 0x4f, 0x34, 0xa1, 0x75, 0x95, 0xfd, 0x52, 0x71, 0xa5, 0x67, 0xee, + 0x85, 0x66, 0x6e, 0xb8, 0x25, 0x43, 0x6e, 0x09, 0xc3, 0x45, 0xa0, 0x3f, + 0x8d, 0x55, 0x0e, 0xdc, 0x75, 0xf9, 0x3a, 0xf9, 0x73, 0x6e, 0x76, 0xb1, + 0x66, 0x7c, 0xb6, 0x4a, 0x06, 0xb8, 0x6b, 0xe6, 0xd9, 0x2c, 0xd8, 0xd3, + 0x5e, 0x8b, 0xd7, 0x32, 0x37, 0x05, 0x89, 0xe4, 0x3a, 0xf3, 0x22, 0xa2, + 0x66, 0x15, 0xf7, 0x1b, 0xd3, 0x7d, 0x85, 0x27, 0x44, 0x2f, 0xbf, 0x0c, + 0xa8, 0x8a, 0x1b, 0x6a, 0xca, 0x59, 0xcd, 0x81, 0x02, 0x6c, 0x56, 0xda, + 0x28, 0xd8, 0xb4, 0xa3, 0xb3, 0x73, 0x41, 0x72, 0xa4, 0xa0, 0x0f, 0x88, + 0x5a, 0x31, 0x1b, 0xe9, 0x09, 0x04, 0x2e, 0x51, 0x38, 0x79, 0xdc, 0x2c, + 0x96, 0x71, 0xdf, 0x6f, 0xb1, 0x2d, 0xf8, 0x03, 0x24, 0xe1, 0x87, 0xd8, + 0xcd, 0xcc, 0x9a, 0x32, 0x10, 0x5b, 0xce, 0x98, 0x9d, 0x84, 0x1d, 0x9f, + 0xfd, 0xb6, 0xde, 0xed, 0x53, 0xe6, 0x95, 0xa5, 0xba, 0x4d, 0x1c, 0xbe, + 0x6a, 0x0b, 0x79, 0x04, 0xbb, 0x65, 0xc2, 0x1b, 0x27, 0xf8, 0xca, 0x8a, + 0xf2, 0x92, 0xda, 0xa0, 0x36, 0xc0, 0xcd, 0x47, 0x63, 0xa5, 0x9c, 0x1f, + 0xb0, 0x7d, 0x02, 0x7a, 0x4e, 0x3b, 0x12, 0x93, 0x82, 0xa2, 0xba, 0xde, + 0x0f, 0x05, 0xe2, 0x7e, 0x51, 0x0b, 0x93, 0xae, 0xa0, 0x38, 0xfa, 0x57, + 0x9f, 0xb7, 0xe5, 0x5b, 0xe7, 0x70, 0x35, 0x73, 0xfd, 0x69, 0xbb, 0x02, + 0x36, 0xdc, 0xe6, 0x88, 0xdf, 0xc4, 0x14, 0x53, 0xdb, 0xd5, 0x29, 0x75, + 0xee, 0x7a, 0x43, 0x02, 0xb8, 0x9e, 0xd2, 0xeb, 0x9c, 0x30, 0x17, 0x11, + 0x2c, 0x17, 0x85, 0x29, 0xf0, 0x14, 0x83, 0x40, 0x67, 0x3a, 0xaa, 0x81, + 0xab, 0x51, 0xd4, 0x93, 0xca, 0x71, 0xb6, 0x91, 0x71, 0xfa, 0xd2, 0x85, + 0x0b, 0x37, 0x03, 0x7d, 0x3a, 0xa8, 0xdc, 0xdd, 0x86, 0xf5, 0xaf, 0x68, + 0x83, 0x62, 0x99, 0xd3, 0x08, 0x66, 0x31, 0xc2, 0xb3, 0x9b, 0x5b, 0x16, + 0x79, 0x02, 0x73, 0x08, 0xc2, 0x5e, 0xb2, 0x51, 0x62, 0xde, 0xf2, 0x80, + 0x3f, 0xf9, 0x38, 0x89, 0xd8, 0x54, 0x8f, 0x12, 0x57, 0x6f, 0x63, 0x82, + 0xe8, 0x85, 0x50, 0x76, 0x47, 0xe8, 0xb4, 0x72, 0x30, 0x82, 0x01, 0x66, + 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, + 0x82, 0x01, 0x57, 0x04, 0x82, 0x01, 0x53, 0x30, 0x82, 0x01, 0x4f, 0x30, + 0x82, 0x01, 0x4b, 0x06, 0x0b, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, + 0x0c, 0x0a, 0x01, 0x02, 0xa0, 0x81, 0xef, 0x30, 0x81, 0xec, 0x30, 0x57, + 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x05, 0x0d, 0x30, + 0x4a, 0x30, 0x29, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, + 0x05, 0x0c, 0x30, 0x1c, 0x04, 0x08, 0x02, 0x22, 0x32, 0x6d, 0xb7, 0xe6, + 0x22, 0x27, 0x02, 0x02, 0x08, 0x00, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x09, 0x05, 0x00, 0x30, 0x1d, 0x06, 0x09, + 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x2a, 0x04, 0x10, 0x67, + 0x70, 0x30, 0x70, 0x64, 0x61, 0xc0, 0x8d, 0xe0, 0x4b, 0x29, 0x5c, 0x05, + 0x42, 0x51, 0x55, 0x04, 0x81, 0x90, 0xd9, 0xf6, 0x74, 0x29, 0xd6, 0xb5, + 0xf8, 0x75, 0x65, 0x08, 0x7b, 0x96, 0x19, 0x3d, 0xf3, 0xaf, 0xc9, 0xeb, + 0x5f, 0x5b, 0xdf, 0x7d, 0xc6, 0xe9, 0x8d, 0xdb, 0x0a, 0xe8, 0xda, 0x51, + 0x2c, 0x52, 0xca, 0x8e, 0x2b, 0xb3, 0x81, 0x92, 0x61, 0xaa, 0x11, 0x68, + 0x4d, 0x9b, 0xce, 0xff, 0xdc, 0x7f, 0x0f, 0x43, 0x2b, 0xd7, 0x11, 0x02, + 0xad, 0xd3, 0x2a, 0x4b, 0x56, 0x5e, 0x7e, 0xde, 0x70, 0xa2, 0x42, 0x5d, + 0xa5, 0x07, 0x3f, 0x6a, 0xb9, 0x6a, 0x8f, 0x22, 0xc2, 0x10, 0x16, 0xa5, + 0x97, 0x5b, 0x1c, 0x4d, 0xf3, 0x42, 0xfa, 0x14, 0xd1, 0x5f, 0xd1, 0x22, + 0xcd, 0xfe, 0x2c, 0x2c, 0xf6, 0xc2, 0x23, 0xeb, 0x98, 0x3c, 0xc5, 0xd3, + 0xec, 0xcc, 0x61, 0x32, 0xc0, 0x56, 0xb7, 0xe8, 0x01, 0x7a, 0xd5, 0xdc, + 0x8d, 0x6d, 0x3e, 0xe4, 0x48, 0x45, 0xd3, 0xf0, 0xbe, 0xe6, 0x48, 0x4f, + 0x4b, 0xba, 0x9e, 0xe3, 0xb9, 0x7d, 0xb1, 0xb1, 0x2e, 0x71, 0x91, 0x53, + 0xc9, 0x47, 0x73, 0x58, 0x39, 0xa7, 0x31, 0x4a, 0x30, 0x23, 0x06, 0x09, + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x14, 0x31, 0x16, 0x1e, + 0x14, 0x00, 0x77, 0x00, 0x6f, 0x00, 0x6c, 0x00, 0x66, 0x00, 0x53, 0x00, + 0x53, 0x00, 0x4c, 0x00, 0x20, 0x00, 0xe9, 0x20, 0xac, 0x30, 0x23, 0x06, + 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x15, 0x31, 0x16, + 0x04, 0x14, 0xfe, 0x60, 0x42, 0x8a, 0xbb, 0x29, 0xf4, 0xe4, 0x4d, 0x0f, + 0x8e, 0xba, 0x04, 0xb0, 0xca, 0xf3, 0x48, 0xe0, 0xb3, 0x07, 0x30, 0x41, + 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, + 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20, 0x1b, 0x58, 0x6c, 0xa5, 0x9c, + 0xf4, 0xb8, 0xbd, 0x48, 0x80, 0xb2, 0xd0, 0x6b, 0x5b, 0xfc, 0x54, 0x16, + 0x61, 0x57, 0x10, 0xc0, 0x3d, 0xf3, 0x21, 0x03, 0x5b, 0x2a, 0x3a, 0xf9, + 0x7f, 0x00, 0xc6, 0x04, 0x08, 0xa5, 0x25, 0xff, 0x5c, 0x11, 0xaa, 0xb6, + 0xa6, 0x02, 0x02, 0x08, 0x00, + }; + /* As p12Der with friendlyName "wolfSSL". */ + static const unsigned char p12AsciiDer[] = { + 0x30, 0x82, 0x08, 0x5b, 0x02, 0x01, 0x03, 0x30, 0x82, 0x08, 0x11, 0x06, + 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x82, + 0x08, 0x02, 0x04, 0x82, 0x07, 0xfe, 0x30, 0x82, 0x07, 0xfa, 0x30, 0x82, + 0x06, 0x92, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, + 0x06, 0xa0, 0x82, 0x06, 0x83, 0x30, 0x82, 0x06, 0x7f, 0x02, 0x01, 0x00, + 0x30, 0x82, 0x06, 0x78, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, + 0x01, 0x07, 0x01, 0x30, 0x57, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x05, 0x0d, 0x30, 0x4a, 0x30, 0x29, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x05, 0x0c, 0x30, 0x1c, 0x04, 0x08, 0x1f, + 0xcf, 0xc4, 0xe9, 0xd6, 0xc7, 0x81, 0x1a, 0x02, 0x02, 0x08, 0x00, 0x30, + 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x09, 0x05, + 0x00, 0x30, 0x1d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, + 0x01, 0x2a, 0x04, 0x10, 0xd3, 0xd7, 0x8e, 0xb1, 0x03, 0xed, 0xcc, 0x84, + 0xd7, 0x16, 0xb8, 0xd9, 0xfd, 0xcd, 0x91, 0xa2, 0x80, 0x82, 0x06, 0x10, + 0x4c, 0x8b, 0x28, 0xa6, 0xd3, 0x62, 0xd4, 0xd1, 0xb1, 0xcf, 0x8d, 0x63, + 0x98, 0x5f, 0x7e, 0xec, 0xce, 0x77, 0x8f, 0x77, 0x4e, 0xab, 0x14, 0x54, + 0x0b, 0x9a, 0x23, 0x2a, 0xb9, 0x77, 0x3b, 0xd5, 0x20, 0x29, 0x3e, 0xe8, + 0xa5, 0x8b, 0xc1, 0xe1, 0x3c, 0x8c, 0xd7, 0xd0, 0xd2, 0xf7, 0x19, 0x11, + 0xd7, 0x03, 0xfd, 0xba, 0x9a, 0x10, 0xa8, 0x6a, 0x16, 0x60, 0xd1, 0x27, + 0x46, 0xc2, 0x9a, 0xa1, 0xda, 0xc3, 0x32, 0xba, 0x8e, 0x70, 0x89, 0x0f, + 0x38, 0x28, 0x92, 0x8e, 0x18, 0x1a, 0x0e, 0xa1, 0x3c, 0x5e, 0x50, 0x6a, + 0x1b, 0x3a, 0x50, 0x74, 0x6a, 0xaf, 0xf6, 0x40, 0x83, 0xd2, 0xe9, 0xd0, + 0xc9, 0x0e, 0x35, 0xd1, 0x07, 0x9f, 0xe0, 0xd1, 0x91, 0x62, 0xce, 0x99, + 0x9e, 0xd4, 0x17, 0x6f, 0x8d, 0x10, 0x19, 0x15, 0x86, 0x01, 0x28, 0x13, + 0xe9, 0x13, 0x0c, 0x3f, 0xa9, 0x1a, 0x62, 0x15, 0x08, 0x93, 0x6a, 0x4f, + 0xc4, 0x64, 0x91, 0xd8, 0xb8, 0xe9, 0xe0, 0x53, 0xaf, 0x36, 0x70, 0xcb, + 0xc8, 0xe3, 0x1e, 0x17, 0xfb, 0xa4, 0x39, 0xba, 0xd4, 0x57, 0xa9, 0xea, + 0x64, 0x98, 0x4b, 0x99, 0xb9, 0x16, 0x29, 0x5b, 0xc4, 0xff, 0x7d, 0xc1, + 0x26, 0xd0, 0x49, 0xdc, 0xcc, 0x6d, 0xa5, 0xf9, 0xb6, 0xa3, 0x8a, 0x29, + 0x49, 0x98, 0x58, 0x4e, 0xe8, 0x20, 0x46, 0xd8, 0xc8, 0x7e, 0xe1, 0x89, + 0x3b, 0xa3, 0xb9, 0x91, 0xfc, 0x30, 0x2e, 0x8c, 0xc4, 0x3e, 0x1a, 0x9b, + 0xac, 0x5e, 0x8c, 0x48, 0x59, 0xc7, 0x0d, 0x63, 0x89, 0x81, 0x7f, 0xf0, + 0x9e, 0xc0, 0xb3, 0xb5, 0x6b, 0x6d, 0x35, 0xf6, 0xe7, 0x9b, 0xef, 0x16, + 0x71, 0xd6, 0x8c, 0x68, 0xdc, 0xf5, 0x52, 0xad, 0x8e, 0x14, 0x00, 0x80, + 0x73, 0x67, 0x1d, 0x5a, 0x3d, 0xd3, 0xfa, 0x1f, 0x5e, 0x02, 0x5d, 0x79, + 0x77, 0xfe, 0x74, 0x21, 0x24, 0x7f, 0x27, 0xe7, 0xaf, 0x18, 0xa3, 0x62, + 0xb3, 0x75, 0xf4, 0x8b, 0xa0, 0x9f, 0x55, 0x80, 0xe1, 0x2e, 0x59, 0xd7, + 0xb9, 0x14, 0x2b, 0x9d, 0xfd, 0xfe, 0xf5, 0x04, 0x9b, 0x09, 0xc9, 0x72, + 0xad, 0x53, 0xae, 0x47, 0x4a, 0x20, 0xeb, 0xcd, 0x71, 0xf4, 0x5e, 0xff, + 0x83, 0xab, 0x77, 0x42, 0xbb, 0x03, 0x0d, 0xb9, 0x8c, 0x37, 0x8e, 0xa1, + 0xa1, 0xd4, 0x77, 0xf5, 0xf1, 0x62, 0xa4, 0xae, 0x1a, 0x2c, 0xd9, 0x6d, + 0x89, 0x49, 0xf7, 0x5f, 0x76, 0xda, 0xb4, 0x44, 0xe6, 0x14, 0xe9, 0xfa, + 0x8e, 0xb8, 0x96, 0xe2, 0x8d, 0xb0, 0x2d, 0x4c, 0x63, 0xd8, 0xd6, 0x92, + 0x50, 0xf6, 0x1c, 0x4a, 0xba, 0x4d, 0x40, 0xdf, 0xc1, 0xef, 0xa0, 0xa3, + 0xa4, 0x7f, 0xb8, 0x9f, 0x01, 0x54, 0xf1, 0x45, 0xf9, 0xf1, 0xcc, 0x90, + 0xfa, 0xd2, 0x91, 0x14, 0x43, 0x1e, 0xd6, 0x73, 0x01, 0x76, 0xc1, 0x6f, + 0xd1, 0x50, 0x6f, 0xba, 0xd4, 0xd7, 0x6a, 0xff, 0xfb, 0x67, 0xe8, 0x57, + 0x45, 0x4c, 0xf2, 0x2c, 0x60, 0x43, 0xb4, 0x49, 0xec, 0x39, 0x63, 0xe1, + 0xcf, 0x98, 0x01, 0x78, 0x30, 0xf3, 0x4d, 0x9d, 0xd8, 0x90, 0x68, 0x4c, + 0x7c, 0x2e, 0xf5, 0x38, 0x19, 0x87, 0x6e, 0x9c, 0xbd, 0xb9, 0x51, 0x01, + 0x90, 0x7f, 0x26, 0x7d, 0x4f, 0x50, 0x40, 0x2c, 0xf2, 0xc3, 0x7c, 0x28, + 0x55, 0xd0, 0x79, 0x11, 0x5c, 0x0f, 0xdc, 0xe5, 0xba, 0x35, 0xd8, 0xb3, + 0xf8, 0xdf, 0x66, 0xa8, 0x49, 0xac, 0xeb, 0xf6, 0xa8, 0x5a, 0x93, 0xc6, + 0x03, 0xa1, 0x93, 0x20, 0xb4, 0xcb, 0xf3, 0xbb, 0x99, 0xd0, 0x4a, 0x7c, + 0x58, 0x86, 0x07, 0xe5, 0x63, 0xbc, 0x78, 0xb8, 0xeb, 0xb2, 0x3f, 0xb1, + 0xac, 0xcb, 0xfa, 0x09, 0x81, 0x9f, 0xc3, 0xcb, 0x6f, 0xae, 0x69, 0x8e, + 0xf2, 0x46, 0xa6, 0x2e, 0x54, 0xa7, 0xf1, 0xf8, 0x03, 0x29, 0x97, 0xf2, + 0x51, 0x16, 0x02, 0x91, 0xc5, 0xd5, 0xef, 0x45, 0x79, 0x2a, 0xb4, 0x62, + 0x30, 0xdc, 0x16, 0xea, 0xcd, 0xb8, 0xda, 0xe6, 0x69, 0x53, 0xf3, 0x56, + 0x7a, 0x7c, 0x7f, 0x1a, 0x3e, 0x04, 0x00, 0x46, 0x54, 0xe5, 0x9d, 0xc7, + 0x68, 0x80, 0xb3, 0x7b, 0x97, 0x40, 0xb1, 0x5c, 0x42, 0x90, 0x00, 0xa4, + 0x89, 0x59, 0x1e, 0x19, 0xb1, 0xfd, 0x71, 0xc7, 0x15, 0x36, 0x89, 0xbd, + 0x82, 0xc3, 0xcc, 0x2b, 0xdf, 0x0f, 0x96, 0x73, 0xde, 0x17, 0x01, 0x61, + 0xbc, 0x52, 0x9d, 0x0f, 0x23, 0xee, 0x2a, 0xc4, 0x22, 0x69, 0x6c, 0x80, + 0x2e, 0x54, 0x8c, 0x09, 0xdb, 0x24, 0xa9, 0x29, 0x26, 0x36, 0x2a, 0xf9, + 0xdc, 0x79, 0xcb, 0x51, 0x56, 0x60, 0xaf, 0xc2, 0x77, 0x3c, 0x4e, 0x77, + 0x5b, 0x7d, 0x7c, 0xe1, 0x01, 0xd8, 0x72, 0x2b, 0x9b, 0xe0, 0xa2, 0x5a, + 0x57, 0x6e, 0xf4, 0x00, 0x5c, 0x08, 0x58, 0x35, 0x91, 0x58, 0x4c, 0xbe, + 0x31, 0x78, 0x78, 0xe4, 0xf8, 0x47, 0x73, 0xc6, 0xbe, 0x9c, 0x62, 0x62, + 0xb2, 0x03, 0xc3, 0xa5, 0xbd, 0xf5, 0x97, 0x11, 0x61, 0xb0, 0xf1, 0x2b, + 0x76, 0x38, 0x17, 0x5a, 0x2a, 0xc8, 0xe7, 0x02, 0x7c, 0x34, 0xea, 0x93, + 0x01, 0x12, 0x70, 0xff, 0xc7, 0xa5, 0x7b, 0x66, 0x75, 0x55, 0x43, 0x72, + 0xd6, 0x68, 0x84, 0xfe, 0xba, 0x7e, 0xf0, 0x3f, 0x52, 0x74, 0x59, 0x17, + 0xdd, 0x9a, 0xd3, 0x50, 0xd2, 0x38, 0x7a, 0x22, 0xb8, 0xf8, 0x3b, 0x3f, + 0x3d, 0x01, 0xae, 0x6a, 0x16, 0x1d, 0xb6, 0xa9, 0x64, 0xeb, 0x52, 0x91, + 0x9c, 0x32, 0x54, 0x3e, 0xa1, 0xc6, 0x74, 0x6a, 0x77, 0x7e, 0x43, 0x84, + 0xed, 0x09, 0xcd, 0xa0, 0x51, 0x0d, 0x5c, 0x4c, 0xbc, 0x2b, 0x0a, 0x5a, + 0xa4, 0x6e, 0x96, 0xc6, 0xa0, 0xfd, 0x3b, 0x36, 0x71, 0x43, 0xda, 0x37, + 0xf2, 0xa2, 0x65, 0x5a, 0x74, 0x10, 0x6f, 0xda, 0xb4, 0x09, 0x64, 0x2d, + 0x0f, 0x26, 0x81, 0xc3, 0xb4, 0x67, 0x8d, 0x0d, 0xfe, 0xf2, 0x87, 0xcf, + 0x04, 0x53, 0xfd, 0x1a, 0xa7, 0x92, 0x85, 0x45, 0x60, 0x07, 0x55, 0x22, + 0x7c, 0x01, 0xe4, 0x77, 0xde, 0x43, 0x4b, 0xb5, 0x6e, 0xb5, 0x27, 0xff, + 0x06, 0x97, 0x5c, 0x66, 0x33, 0x54, 0x17, 0xe9, 0xee, 0xdc, 0x0a, 0x3d, + 0xf3, 0xe7, 0x31, 0x23, 0xb2, 0xa7, 0x29, 0x9b, 0x22, 0xc7, 0xb7, 0x6c, + 0xbd, 0x60, 0xbe, 0xc7, 0x6f, 0x4d, 0xa7, 0x80, 0x1c, 0x80, 0xfe, 0xbd, + 0xfe, 0xa1, 0xd5, 0x89, 0xcd, 0x3e, 0xe0, 0xd1, 0x18, 0x03, 0x2d, 0xb2, + 0x60, 0xdd, 0xd0, 0x0d, 0xc3, 0x9e, 0xb0, 0x3b, 0x06, 0x83, 0x8b, 0x24, + 0x05, 0xbc, 0x8f, 0x4f, 0x6d, 0x09, 0x10, 0x04, 0x6b, 0x11, 0x65, 0xfc, + 0x4b, 0x87, 0x91, 0x63, 0x29, 0x0d, 0xcb, 0xae, 0x34, 0x35, 0xf1, 0xee, + 0xaa, 0xc4, 0x5e, 0x81, 0xbd, 0xe7, 0xcc, 0x7c, 0xd9, 0x2e, 0x6c, 0x25, + 0x55, 0x0c, 0x92, 0x2a, 0xc3, 0x62, 0xaa, 0xc9, 0x91, 0x1c, 0x4c, 0xe4, + 0x56, 0xc3, 0xe8, 0x19, 0xe7, 0xb2, 0x0f, 0x78, 0xd4, 0x0b, 0x20, 0x55, + 0xd2, 0x40, 0xb3, 0x76, 0x3f, 0x4a, 0xc9, 0xde, 0x4b, 0xde, 0x36, 0x5b, + 0x81, 0x23, 0x3b, 0x80, 0x83, 0x44, 0x17, 0x03, 0x4c, 0x09, 0xee, 0x76, + 0xd0, 0x07, 0x21, 0x8b, 0xf7, 0x49, 0x16, 0xc7, 0x6e, 0x76, 0xbc, 0xa4, + 0x11, 0xb4, 0x9f, 0x15, 0x43, 0xae, 0xe6, 0xf2, 0xf4, 0x48, 0x7e, 0x0e, + 0x73, 0x8f, 0xfa, 0x2b, 0x5d, 0xa7, 0x02, 0x12, 0xf4, 0x29, 0x25, 0xec, + 0xe5, 0x43, 0x60, 0x4a, 0x8a, 0x89, 0x38, 0xe2, 0xd7, 0x7f, 0x3e, 0x5f, + 0x14, 0x2d, 0x70, 0xd8, 0x34, 0xfd, 0xc5, 0x89, 0x59, 0xd0, 0x27, 0xb0, + 0x0b, 0xa7, 0x23, 0x71, 0xa8, 0x8a, 0xd1, 0xcc, 0x51, 0xe4, 0x1d, 0xd3, + 0x93, 0x77, 0x42, 0x7d, 0x36, 0xdb, 0x53, 0xda, 0x83, 0x42, 0xfa, 0x26, + 0xb5, 0xa6, 0xd8, 0xcd, 0x64, 0xb9, 0x78, 0xdd, 0x14, 0x9d, 0x3d, 0xb4, + 0xd3, 0x88, 0x1f, 0x67, 0x7c, 0xd4, 0xe7, 0xdb, 0xc1, 0xe6, 0x25, 0x24, + 0x93, 0xea, 0xb1, 0x26, 0x0d, 0x33, 0xf2, 0xa0, 0x6e, 0x23, 0x4b, 0xf8, + 0x9a, 0x2d, 0x22, 0x47, 0x09, 0x16, 0xb0, 0x46, 0xb2, 0xdb, 0xe0, 0x43, + 0x49, 0x0f, 0xc6, 0xb4, 0x9c, 0x11, 0x25, 0x9d, 0x53, 0x5e, 0x9a, 0xb0, + 0xd8, 0x5e, 0x94, 0x10, 0x36, 0x3a, 0xb1, 0x10, 0x59, 0x91, 0x6d, 0x70, + 0xd2, 0xa4, 0x9d, 0x36, 0x29, 0x37, 0xf7, 0xc2, 0x1a, 0x66, 0xb5, 0x6f, + 0x96, 0x57, 0x81, 0x50, 0x27, 0x7a, 0x36, 0x4a, 0x61, 0xa1, 0x33, 0x7a, + 0x03, 0x23, 0x0a, 0xb0, 0x1a, 0x1f, 0xd0, 0xaa, 0x1d, 0xc3, 0x82, 0xa3, + 0xe0, 0x08, 0x37, 0x0a, 0xb4, 0x57, 0xc5, 0xc4, 0xd5, 0xce, 0xe3, 0xd6, + 0xd1, 0x90, 0x8b, 0xfb, 0xdc, 0xf0, 0xfe, 0xeb, 0x67, 0x2f, 0x17, 0x89, + 0xe2, 0x25, 0x92, 0x43, 0xd1, 0x22, 0x8a, 0x2d, 0x04, 0xde, 0x3c, 0x04, + 0x48, 0xa1, 0xd3, 0xa6, 0x6f, 0x67, 0x49, 0xb7, 0x20, 0x14, 0xe0, 0xb9, + 0x27, 0xcb, 0xbb, 0xb2, 0xb9, 0xfb, 0xb7, 0x46, 0x6c, 0x41, 0xce, 0x5b, + 0xbf, 0xa2, 0x51, 0x9a, 0x65, 0x1f, 0x0a, 0x6f, 0x08, 0x60, 0x19, 0xdd, + 0x6f, 0x2a, 0xeb, 0xec, 0x5a, 0x23, 0x40, 0x60, 0xce, 0x8b, 0x5c, 0x8c, + 0x7d, 0xd2, 0xca, 0x58, 0x90, 0x5c, 0x6e, 0x80, 0x44, 0x06, 0x55, 0x66, + 0xf6, 0x64, 0x8d, 0x38, 0xff, 0x1a, 0x97, 0xe6, 0x96, 0xd6, 0x57, 0xc2, + 0xbb, 0xeb, 0x91, 0x5c, 0xf0, 0xd1, 0x33, 0x90, 0x08, 0x65, 0x69, 0xdf, + 0xb6, 0x73, 0x09, 0x68, 0x11, 0x11, 0xb4, 0x83, 0xbb, 0xdf, 0x1d, 0x36, + 0x94, 0x30, 0x87, 0xa0, 0x31, 0xca, 0xc0, 0x0f, 0x57, 0x83, 0xaa, 0xd4, + 0x88, 0xf6, 0xcc, 0x91, 0xd1, 0x7f, 0xcc, 0xd7, 0xf4, 0x30, 0x93, 0x16, + 0x70, 0x16, 0x28, 0xb5, 0xe1, 0x23, 0xdb, 0xb7, 0xed, 0x61, 0xc3, 0x2f, + 0xdf, 0xeb, 0x9b, 0x2a, 0x53, 0x81, 0x1b, 0xac, 0xc3, 0x51, 0x6a, 0x69, + 0x18, 0xf4, 0x8f, 0x2c, 0x5e, 0xc7, 0x7a, 0x63, 0xd0, 0x86, 0xe9, 0x8f, + 0x33, 0xbd, 0x1c, 0x33, 0xc2, 0x19, 0x2e, 0x14, 0xd2, 0xb8, 0xbb, 0xf8, + 0xd0, 0xbe, 0xe6, 0x75, 0x0d, 0xea, 0x30, 0x1e, 0xc1, 0x69, 0x6d, 0x8e, + 0x48, 0xf6, 0x10, 0xbc, 0xba, 0x35, 0x6a, 0x2c, 0x4c, 0x87, 0x3d, 0xdb, + 0x5e, 0x2e, 0x11, 0xcd, 0x62, 0x93, 0xe2, 0x0e, 0x20, 0xe8, 0x3c, 0x3e, + 0x9c, 0xea, 0x46, 0xd7, 0x4d, 0xc6, 0x9f, 0xf0, 0x1e, 0xaf, 0xd3, 0xa4, + 0x5f, 0x8f, 0x4b, 0x8d, 0x2a, 0xfa, 0x35, 0xc9, 0xe5, 0x2f, 0x74, 0x91, + 0x78, 0x0a, 0xf6, 0x42, 0x33, 0x49, 0xb2, 0xbf, 0x74, 0xa3, 0x50, 0x63, + 0x9c, 0x19, 0xcd, 0x59, 0xbe, 0x5a, 0x6f, 0xdd, 0xea, 0x1e, 0xcc, 0x69, + 0xaf, 0xfe, 0x02, 0x47, 0xd8, 0xd4, 0xb1, 0x16, 0xab, 0x2b, 0x5b, 0x0e, + 0x72, 0x81, 0x92, 0x96, 0x37, 0x20, 0x4a, 0x43, 0x5b, 0xcb, 0x32, 0x16, + 0x06, 0x99, 0xea, 0x6d, 0x26, 0x85, 0x88, 0x25, 0xa7, 0x0d, 0x67, 0xcd, + 0x57, 0x47, 0x2c, 0x1a, 0x19, 0x22, 0xc9, 0x07, 0xfa, 0x15, 0x8a, 0x11, + 0x89, 0x46, 0xdd, 0xc0, 0x42, 0x88, 0x44, 0xcd, 0xba, 0xd0, 0x73, 0x23, + 0x16, 0x4b, 0x8f, 0xdb, 0xd8, 0xbf, 0x35, 0xe3, 0x00, 0xc3, 0xdc, 0xda, + 0x98, 0x66, 0xe9, 0xb9, 0x08, 0xb4, 0xaa, 0xa2, 0x34, 0xaa, 0x5c, 0xba, + 0xc7, 0x57, 0x44, 0x3f, 0xd4, 0x81, 0xc1, 0x49, 0x84, 0xea, 0xa9, 0x06, + 0x65, 0x88, 0x25, 0xa8, 0xfb, 0x3c, 0xc5, 0x29, 0x31, 0x33, 0x24, 0x45, + 0x6e, 0x65, 0x4c, 0x87, 0x30, 0x82, 0x01, 0x60, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x82, 0x01, 0x51, 0x04, + 0x82, 0x01, 0x4d, 0x30, 0x82, 0x01, 0x49, 0x30, 0x82, 0x01, 0x45, 0x06, + 0x0b, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x0a, 0x01, 0x02, + 0xa0, 0x81, 0xef, 0x30, 0x81, 0xec, 0x30, 0x57, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x05, 0x0d, 0x30, 0x4a, 0x30, 0x29, 0x06, + 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x05, 0x0c, 0x30, 0x1c, + 0x04, 0x08, 0xa1, 0x54, 0x7b, 0xb4, 0x4f, 0x30, 0x2f, 0x11, 0x02, 0x02, + 0x08, 0x00, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, + 0x02, 0x09, 0x05, 0x00, 0x30, 0x1d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, + 0x65, 0x03, 0x04, 0x01, 0x2a, 0x04, 0x10, 0x14, 0x04, 0xc0, 0x75, 0xef, + 0x62, 0x9a, 0x86, 0x86, 0xb8, 0x73, 0x6f, 0x9f, 0x96, 0x89, 0x27, 0x04, + 0x81, 0x90, 0xdf, 0xbf, 0xab, 0xf2, 0x4c, 0x49, 0xcc, 0x98, 0x81, 0xa7, + 0xba, 0x2f, 0x18, 0x42, 0x01, 0x3b, 0xf2, 0xf6, 0x0b, 0xb4, 0xf0, 0x3d, + 0xda, 0x13, 0xe6, 0x92, 0x33, 0xa7, 0x63, 0x50, 0xcc, 0x66, 0xa5, 0xa6, + 0x7d, 0xe6, 0x70, 0x62, 0x4c, 0xf5, 0x09, 0x4f, 0x38, 0x0e, 0x0a, 0xab, + 0x34, 0x26, 0xbf, 0xf1, 0xb3, 0x6f, 0x87, 0x9c, 0x0b, 0x1b, 0xcc, 0x70, + 0x1b, 0xc0, 0x3e, 0x47, 0x38, 0x4e, 0x79, 0x34, 0x3f, 0x76, 0xa4, 0x88, + 0x80, 0x95, 0x2d, 0xd1, 0x3b, 0xfe, 0xca, 0x58, 0x15, 0x35, 0x23, 0x6d, + 0x6e, 0xf8, 0x54, 0x4a, 0x4d, 0x25, 0xbc, 0x62, 0x78, 0x31, 0x82, 0x12, + 0x06, 0x1a, 0x33, 0xd9, 0xf1, 0x48, 0x66, 0xa3, 0xb9, 0x2c, 0x36, 0x0e, + 0x42, 0x0c, 0x07, 0x35, 0x8b, 0xd6, 0x90, 0x3b, 0x24, 0x34, 0x7e, 0x64, + 0x23, 0x8a, 0xb8, 0xbb, 0x91, 0xac, 0x75, 0xb6, 0x11, 0x58, 0x89, 0xb7, + 0x4a, 0x5b, 0x30, 0xb3, 0x24, 0x25, 0x7a, 0x16, 0x96, 0x3c, 0x97, 0x14, + 0x81, 0x9a, 0x31, 0x44, 0x30, 0x1d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x09, 0x14, 0x31, 0x10, 0x1e, 0x0e, 0x00, 0x77, 0x00, + 0x6f, 0x00, 0x6c, 0x00, 0x66, 0x00, 0x53, 0x00, 0x53, 0x00, 0x4c, 0x30, + 0x23, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x15, + 0x31, 0x16, 0x04, 0x14, 0xfe, 0x60, 0x42, 0x8a, 0xbb, 0x29, 0xf4, 0xe4, + 0x4d, 0x0f, 0x8e, 0xba, 0x04, 0xb0, 0xca, 0xf3, 0x48, 0xe0, 0xb3, 0x07, + 0x30, 0x41, 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, + 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20, 0x45, 0xf3, 0x81, + 0xac, 0x56, 0xb3, 0xd8, 0xbb, 0x3d, 0x5e, 0x5b, 0xdc, 0xe6, 0xf5, 0x61, + 0x8a, 0xe0, 0x3b, 0xbc, 0xd7, 0xb1, 0x4b, 0xff, 0xe9, 0x39, 0xd0, 0xa6, + 0x0d, 0x9e, 0x23, 0xda, 0x10, 0x04, 0x08, 0xac, 0xec, 0x08, 0xf8, 0x75, + 0x35, 0xd4, 0xf7, 0x02, 0x02, 0x08, 0x00, + }; + static const unsigned char keyid[] = { + 0xfe, 0x60, 0x42, 0x8a, 0xbb, 0x29, 0xf4, 0xe4, 0x4d, 0x0f, + 0x8e, 0xba, 0x04, 0xb0, 0xca, 0xf3, 0x48, 0xe0, 0xb3, 0x07 + }; + WOLFSSL_BIO* bio = NULL; + WC_PKCS12* pkcs12 = NULL; + WOLFSSL_EVP_PKEY* pkey = NULL; + WOLFSSL_X509* cert = NULL; + WOLFSSL_X509* dup = NULL; + WOLF_STACK_OF(WOLFSSL_X509)* caCerts = NULL; + unsigned char* p = NULL; + int len = 0; + + ExpectNull(X509_alias_get0(NULL, &len)); + ExpectNull(X509_keyid_get0(NULL, &len)); + + ExpectNotNull(bio = BIO_new_mem_buf(p12AsciiDer, + (int)sizeof(p12AsciiDer))); + ExpectNotNull(pkcs12 = d2i_PKCS12_bio(bio, NULL)); + /* The key cert has its own attributes, not those of the CA bag. */ + ExpectIntEQ(PKCS12_parse(pkcs12, "wolfSSL test", &pkey, &cert, + &caCerts), 1); + ExpectIntEQ(sk_X509_num(caCerts), 1); + ExpectNotNull(p = X509_alias_get0(cert, &len)); + ExpectIntEQ(len, 7); + ExpectBufEQ(p, "wolfSSL", 7); + ExpectIntEQ(p[len], 0); + ExpectNotNull(X509_alias_get0(cert, NULL)); + ExpectNotNull(p = X509_keyid_get0(cert, &len)); + ExpectIntEQ(len, (int)sizeof(keyid)); + ExpectBufEQ(p, keyid, sizeof(keyid)); + ExpectIntEQ(p[len], 0); + + /* As in OpenSSL, a copy does not have them. */ + ExpectNotNull(dup = X509_dup(cert)); + ExpectNull(X509_alias_get0(dup, &len)); + ExpectNull(X509_keyid_get0(dup, &len)); + + X509_free(dup); + sk_X509_pop_free(caCerts, X509_free); + X509_free(cert); + EVP_PKEY_free(pkey); + PKCS12_free(pkcs12); + BIO_free(bio); + + /* A friendlyName that is not ASCII is left out. */ + caCerts = NULL; + cert = NULL; + pkey = NULL; + pkcs12 = NULL; + bio = NULL; + ExpectNotNull(bio = BIO_new_mem_buf(p12Der, (int)sizeof(p12Der))); + ExpectNotNull(pkcs12 = d2i_PKCS12_bio(bio, NULL)); + ExpectIntEQ(PKCS12_parse(pkcs12, "wolfSSL test", &pkey, &cert, + &caCerts), 1); + ExpectNull(X509_alias_get0(cert, &len)); + ExpectNotNull(p = X509_keyid_get0(cert, &len)); + ExpectIntEQ(len, (int)sizeof(keyid)); + ExpectBufEQ(p, keyid, sizeof(keyid)); + sk_X509_pop_free(caCerts, X509_free); + X509_free(cert); + EVP_PKEY_free(pkey); + PKCS12_free(pkcs12); + BIO_free(bio); +#if !defined(NO_DES3) && !defined(NO_RSA) && !defined(NO_SHA) && \ + !defined(NO_FILESYSTEM) + { + /* localKeyId only: the SHA-1 of the cert, as OpenSSL makes it. */ + unsigned char srvKeyid[WC_SHA_DIGEST_SIZE]; + unsigned int srvKeyidSz = 0; + WOLF_STACK_OF(WOLFSSL_X509)* ca = NULL; + + cert = NULL; + pkey = NULL; + pkcs12 = NULL; + bio = NULL; + ExpectNotNull(bio = BIO_new_file("./certs/test-servercert.p12", + "rb")); + ExpectNotNull(pkcs12 = d2i_PKCS12_bio(bio, NULL)); + ExpectIntEQ(PKCS12_parse(pkcs12, "wolfSSL test", &pkey, &cert, &ca), + 1); + ExpectNull(X509_alias_get0(cert, &len)); + ExpectIntEQ(X509_digest(cert, EVP_sha1(), srvKeyid, &srvKeyidSz), 1); + ExpectNotNull(p = X509_keyid_get0(cert, &len)); + ExpectIntEQ(len, (int)srvKeyidSz); + ExpectBufEQ(p, srvKeyid, srvKeyidSz); + sk_X509_pop_free(ca, X509_free); + X509_free(cert); + EVP_PKEY_free(pkey); + PKCS12_free(pkcs12); + BIO_free(bio); + } +#endif +#endif + return EXPECT_RESULT(); +} diff --git a/tests/api/test_ossl_p7p12.h b/tests/api/test_ossl_p7p12.h index 1f1e283f528..a35a26eefdd 100644 --- a/tests/api/test_ossl_p7p12.h +++ b/tests/api/test_ossl_p7p12.h @@ -38,6 +38,7 @@ int test_wolfSSL_SMIME_write_PKCS7(void); int test_wolfSSL_PKCS7_verify_nointern(void); int test_wolfSSL_PKCS12(void); int test_wolfSSL_PKCS12_create_mac(void); +int test_wolfSSL_PKCS12_alias_keyid(void); #define TEST_OSSL_PKCS7_DECLS \ TEST_DECL_GROUP("ossl_p7", test_wolfssl_PKCS7), \ @@ -56,9 +57,10 @@ int test_wolfSSL_PKCS12_create_mac(void); TEST_DECL_GROUP("ossl_smime", test_wolfSSL_SMIME_write_PKCS7), \ TEST_DECL_GROUP("ossl_smime", test_wolfSSL_PKCS7_verify_nointern) -#define TEST_OSSL_PKCS12_DECLS \ - TEST_DECL_GROUP("ossl_p12", test_wolfSSL_PKCS12), \ - TEST_DECL_GROUP("ossl_p12", test_wolfSSL_PKCS12_create_mac) +#define TEST_OSSL_PKCS12_DECLS \ + TEST_DECL_GROUP("ossl_p12", test_wolfSSL_PKCS12), \ + TEST_DECL_GROUP("ossl_p12", test_wolfSSL_PKCS12_create_mac), \ + TEST_DECL_GROUP("ossl_p12", test_wolfSSL_PKCS12_alias_keyid) #endif /* WOLFCRYPT_TEST_OSSL_P7P12_H */ diff --git a/tests/api/test_ossl_rsa.c b/tests/api/test_ossl_rsa.c index 7c30e5ce07e..77118d3b2c7 100644 --- a/tests/api/test_ossl_rsa.c +++ b/tests/api/test_ossl_rsa.c @@ -582,6 +582,297 @@ int test_wolfSSL_RSA_padding_add_PKCS1_PSS(void) return EXPECT_RESULT(); } +int test_wolfSSL_RSA_padding_PKCS1_OAEP(void) +{ + EXPECT_DECLS; +#if !defined(NO_RSA) && defined(WOLFSSL_RSA_OAEP_COMPAT) && \ + !defined(WC_NO_RNG) + static const unsigned char msg[16] = { + 'O', 'A', 'E', 'P', ' ', 'l', 'a', 'b', 'e', 'l', ' ', 't', 'e', 's', + 't', '!' + }; + static const unsigned char label[5] = { 'l', 'a', 'b', 'e', 'l' }; + unsigned char em[256] = {0}; + unsigned char out[256] = {0}; + + /* SHA-1 OAEP takes 2 * 20 + 2 bytes. */ + ExpectIntEQ(RSA_padding_add_PKCS1_OAEP(NULL, (int)sizeof(em), msg, + (int)sizeof(msg), NULL, 0), 0); + ExpectIntEQ(RSA_padding_add_PKCS1_OAEP(em, 41, NULL, 0, NULL, 0), 0); + ExpectIntEQ(RSA_padding_add_PKCS1_OAEP(em, 42, NULL, 0, NULL, 0), 1); + ExpectIntEQ(RSA_padding_add_PKCS1_OAEP(em, 57, msg, (int)sizeof(msg), + NULL, 0), 0); + ExpectIntEQ(RSA_padding_add_PKCS1_OAEP(em, 58, msg, (int)sizeof(msg), + NULL, 0), 1); + ExpectIntEQ(RSA_padding_check_PKCS1_OAEP(out, (int)sizeof(out), em, 58, + 58, NULL, 0), (int)sizeof(msg)); + ExpectIntEQ(RSA_padding_add_PKCS1_OAEP(em, (int)sizeof(em), msg, + (int)sizeof(msg), NULL, 1), 0); + ExpectIntEQ(RSA_padding_check_PKCS1_OAEP(NULL, (int)sizeof(out), em, 58, + 58, NULL, 0), -1); + ExpectIntEQ(RSA_padding_check_PKCS1_OAEP(out, (int)sizeof(out), em, 59, + 58, NULL, 0), -1); + + /* With a label. */ + ExpectIntEQ(RSA_padding_add_PKCS1_OAEP(em, (int)sizeof(em), msg, + (int)sizeof(msg), label, (int)sizeof(label)), 1); + ExpectIntEQ(em[0], 0); + ExpectIntEQ(RSA_padding_check_PKCS1_OAEP(out, (int)sizeof(out), em, + (int)sizeof(em), (int)sizeof(em), label, (int)sizeof(label)), + (int)sizeof(msg)); + ExpectBufEQ(out, msg, sizeof(msg)); + /* Leading zero byte removed. */ + ExpectIntEQ(RSA_padding_check_PKCS1_OAEP(out, (int)sizeof(out), em + 1, + (int)sizeof(em) - 1, (int)sizeof(em), label, (int)sizeof(label)), + (int)sizeof(msg)); + ExpectIntEQ(RSA_padding_check_PKCS1_OAEP(out, (int)sizeof(msg) - 1, em, + (int)sizeof(em), (int)sizeof(em), label, (int)sizeof(label)), -1); + ExpectIntEQ(RSA_padding_check_PKCS1_OAEP(out, (int)sizeof(out), em, + (int)sizeof(em), (int)sizeof(em), label, (int)sizeof(label) - 1), -1); + ExpectIntEQ(RSA_padding_check_PKCS1_OAEP(out, (int)sizeof(out), em, + (int)sizeof(em), (int)sizeof(em), NULL, 0), -1); + em[100] ^= 0x01; + ExpectIntEQ(RSA_padding_check_PKCS1_OAEP(out, (int)sizeof(out), em, + (int)sizeof(em), (int)sizeof(em), label, (int)sizeof(label)), -1); + + /* In place. */ + ExpectIntEQ(RSA_padding_add_PKCS1_OAEP(em, (int)sizeof(em), msg, + (int)sizeof(msg), NULL, 0), 1); + ExpectIntEQ(RSA_padding_check_PKCS1_OAEP(em, (int)sizeof(em), em, + (int)sizeof(em), (int)sizeof(em), NULL, 0), (int)sizeof(msg)); + ExpectBufEQ(em, msg, sizeof(msg)); + + /* Each call uses a fresh random seed. */ + ExpectIntEQ(RSA_padding_add_PKCS1_OAEP(em, (int)sizeof(em), msg, + (int)sizeof(msg), NULL, 0), 1); + ExpectIntEQ(RSA_padding_add_PKCS1_OAEP(out, (int)sizeof(out), msg, + (int)sizeof(msg), NULL, 0), 1); + ExpectBufNE(em, out, sizeof(em)); + +#ifdef WC_RSA_NO_PADDING + { + /* msg encrypted by OpenSSL to client_key_der_2048 with the label. */ + static const unsigned char ct[] = { + 0x8f, 0x18, 0x00, 0x4d, 0x31, 0x50, 0xd2, 0x5d, 0x58, 0x47, 0x9a, + 0x97, 0x99, 0x94, 0xd1, 0x3a, 0x97, 0x95, 0x83, 0x5c, 0x45, 0x73, + 0xdf, 0x40, 0x6a, 0x6d, 0xd5, 0x5a, 0x3d, 0xae, 0x93, 0xe1, 0x9f, + 0xa1, 0x97, 0xce, 0xe1, 0xa5, 0xd2, 0x0a, 0xf7, 0x4c, 0x27, 0x5b, + 0x4e, 0xa6, 0xe8, 0x16, 0x01, 0xed, 0x76, 0x60, 0x23, 0xa1, 0xd2, + 0xd7, 0xff, 0xda, 0xb4, 0xc9, 0xd5, 0x7f, 0x47, 0xc1, 0xb1, 0x20, + 0x99, 0x8a, 0x74, 0xde, 0x8c, 0x22, 0x06, 0xd1, 0xe8, 0x4f, 0xf5, + 0x4a, 0xa4, 0xd0, 0xc7, 0xf1, 0x7f, 0x6f, 0x50, 0x10, 0xe8, 0xa0, + 0x2a, 0xce, 0x72, 0xfe, 0x8f, 0xa4, 0x6c, 0xc6, 0x0e, 0x1a, 0x37, + 0x20, 0xfe, 0x6f, 0x8b, 0x9a, 0x22, 0x18, 0x0f, 0x5f, 0x04, 0x95, + 0x0e, 0x7f, 0xec, 0x48, 0xec, 0xcf, 0x0c, 0xe3, 0x45, 0x8f, 0xc6, + 0x49, 0x2c, 0xb9, 0x77, 0xf4, 0x66, 0xf5, 0x23, 0xd1, 0x89, 0x56, + 0x61, 0x1a, 0x23, 0x5d, 0x24, 0x5c, 0xfe, 0x85, 0xf3, 0x66, 0x8a, + 0x18, 0xf0, 0xaf, 0xb0, 0x31, 0x6c, 0xe7, 0x46, 0xb0, 0x98, 0xea, + 0x92, 0x37, 0x88, 0x57, 0x68, 0xb6, 0x80, 0xb5, 0x53, 0x70, 0xca, + 0xe7, 0x55, 0x87, 0xfb, 0x94, 0x71, 0x8d, 0x03, 0x6a, 0x02, 0xa8, + 0xdd, 0x89, 0x58, 0x7e, 0xd1, 0xc5, 0xa6, 0xd3, 0x26, 0xe1, 0x79, + 0xc3, 0xb2, 0x81, 0xf6, 0x08, 0x6b, 0x60, 0xa3, 0x58, 0x2d, 0x8d, + 0x4d, 0xc0, 0xa7, 0xa8, 0xe6, 0x72, 0x2b, 0xa5, 0xdb, 0xdd, 0xc2, + 0x04, 0x13, 0x7a, 0xfe, 0x01, 0xff, 0xa3, 0x40, 0x4d, 0x97, 0xdf, + 0x66, 0x82, 0x71, 0x59, 0x2f, 0xa5, 0xca, 0x6f, 0xd5, 0xf5, 0x79, + 0x14, 0xa2, 0x0e, 0xcb, 0x93, 0x98, 0xdc, 0xeb, 0x45, 0xf8, 0xac, + 0xa3, 0xc3, 0xc6, 0x39, 0xa4, 0x08, 0x76, 0x44, 0xd3, 0x37, 0xbf, + 0x07, 0x18, 0xff, + }; + RSA* rsa = NULL; + const unsigned char* der = client_key_der_2048; + unsigned char ct2[256] = {0}; + + ExpectNotNull(d2i_RSAPrivateKey(&rsa, &der, + sizeof_client_key_der_2048)); + ExpectIntEQ(RSA_private_decrypt((int)sizeof(ct), ct, em, rsa, + RSA_NO_PADDING), (int)sizeof(em)); + ExpectIntEQ(RSA_padding_check_PKCS1_OAEP(out, (int)sizeof(out), em, + (int)sizeof(em), (int)sizeof(em), label, (int)sizeof(label)), + (int)sizeof(msg)); + ExpectBufEQ(out, msg, sizeof(msg)); + + /* Without a label, RSA_PKCS1_OAEP_PADDING decrypts it. */ + ExpectIntEQ(RSA_padding_add_PKCS1_OAEP(em, (int)sizeof(em), msg, + (int)sizeof(msg), NULL, 0), 1); + ExpectIntEQ(RSA_public_encrypt((int)sizeof(em), em, ct2, rsa, + RSA_NO_PADDING), (int)sizeof(ct2)); + ExpectIntEQ(RSA_private_decrypt((int)sizeof(ct2), ct2, out, rsa, + RSA_PKCS1_OAEP_PADDING), (int)sizeof(msg)); + ExpectBufEQ(out, msg, sizeof(msg)); + RSA_free(rsa); + } +#endif +#endif + return EXPECT_RESULT(); +} + +int test_wolfSSL_RSA_padding_PKCS1_OAEP_mgf1(void) +{ + EXPECT_DECLS; +#if !defined(NO_RSA) && defined(WOLFSSL_RSA_OAEP_COMPAT) && \ + !defined(WC_NO_RNG) && !defined(NO_SHA256) + static const unsigned char msg[16] = { + 'O', 'A', 'E', 'P', ' ', 'l', 'a', 'b', 'e', 'l', ' ', 't', 'e', 's', + 't', '!' + }; + static const unsigned char label[5] = { 'l', 'a', 'b', 'e', 'l' }; + unsigned char em[256] = {0}; + unsigned char out[256] = {0}; + + /* NULL hashes are SHA-1, as without _mgf1. */ + ExpectIntEQ(RSA_padding_add_PKCS1_OAEP_mgf1(em, (int)sizeof(em), msg, + (int)sizeof(msg), label, (int)sizeof(label), NULL, NULL), 1); + ExpectIntEQ(RSA_padding_check_PKCS1_OAEP(out, (int)sizeof(out), em, + (int)sizeof(em), (int)sizeof(em), label, (int)sizeof(label)), + (int)sizeof(msg)); + ExpectIntEQ(RSA_padding_check_PKCS1_OAEP_mgf1(out, (int)sizeof(out), em, + (int)sizeof(em), (int)sizeof(em), label, (int)sizeof(label), + EVP_sha1(), EVP_sha1()), (int)sizeof(msg)); + ExpectBufEQ(out, msg, sizeof(msg)); + + /* No MGF1 hash is the label hash. */ + ExpectIntEQ(RSA_padding_add_PKCS1_OAEP_mgf1(em, (int)sizeof(em), msg, + (int)sizeof(msg), NULL, 0, EVP_sha256(), NULL), 1); + ExpectIntEQ(RSA_padding_check_PKCS1_OAEP_mgf1(out, (int)sizeof(out), em, + (int)sizeof(em), (int)sizeof(em), NULL, 0, EVP_sha256(), + EVP_sha256()), (int)sizeof(msg)); + ExpectBufEQ(out, msg, sizeof(msg)); + /* Other hashes fail. */ + ExpectIntEQ(RSA_padding_check_PKCS1_OAEP_mgf1(out, (int)sizeof(out), em, + (int)sizeof(em), (int)sizeof(em), NULL, 0, EVP_sha256(), EVP_sha1()), + -1); + ExpectIntEQ(RSA_padding_check_PKCS1_OAEP_mgf1(out, (int)sizeof(out), em, + (int)sizeof(em), (int)sizeof(em), NULL, 0, EVP_sha1(), EVP_sha256()), + -1); + ExpectIntEQ(RSA_padding_check_PKCS1_OAEP(out, (int)sizeof(out), em, + (int)sizeof(em), (int)sizeof(em), NULL, 0), -1); + + /* SHA-256 OAEP takes 2 * 32 + 2 bytes. */ + ExpectIntEQ(RSA_padding_add_PKCS1_OAEP_mgf1(em, 65, NULL, 0, NULL, 0, + EVP_sha256(), EVP_sha1()), 0); + ExpectIntEQ(RSA_padding_add_PKCS1_OAEP_mgf1(em, 66, NULL, 0, NULL, 0, + EVP_sha256(), EVP_sha1()), 1); + ExpectIntEQ(RSA_padding_add_PKCS1_OAEP_mgf1(em, (int)sizeof(em), msg, + (int)sizeof(msg), NULL, 0, (const EVP_MD*)"no hash", NULL), 0); + ExpectIntEQ(RSA_padding_check_PKCS1_OAEP_mgf1(out, (int)sizeof(out), em, + 66, 66, NULL, 0, EVP_sha256(), (const EVP_MD*)"no hash"), -1); + +#if defined(WOLFSSL_SHA512) && defined(WOLFSSL_SHA384) && \ + defined(WOLFSSL_SHA224) + { + const EVP_MD* mds[4]; + int i; + int j; + + mds[0] = EVP_sha224(); + mds[1] = EVP_sha256(); + mds[2] = EVP_sha384(); + mds[3] = EVP_sha512(); + for (i = 0; i < 4; i++) { + for (j = 0; j < 4; j++) { + ExpectIntEQ(RSA_padding_add_PKCS1_OAEP_mgf1(em, + (int)sizeof(em), msg, (int)sizeof(msg), label, + (int)sizeof(label), mds[i], mds[j]), 1); + ExpectIntEQ(RSA_padding_check_PKCS1_OAEP_mgf1(out, + (int)sizeof(out), em, (int)sizeof(em), (int)sizeof(em), + label, (int)sizeof(label), mds[i], mds[j]), + (int)sizeof(msg)); + ExpectBufEQ(out, msg, sizeof(msg)); + } + } + } +#endif + +#ifdef WC_RSA_NO_PADDING + { + /* msg encrypted by OpenSSL to client_key_der_2048 with OAEP SHA-256, + * MGF1-SHA-1 and the label. */ + static const unsigned char ct[] = { + 0x61, 0x16, 0xd4, 0xb5, 0x9c, 0x43, 0x15, 0x01, 0xd9, 0x99, 0x21, + 0x8f, 0x52, 0xa2, 0xc5, 0x65, 0x23, 0x22, 0xe7, 0x55, 0x32, 0x5f, + 0x25, 0xac, 0xc2, 0xa9, 0x1b, 0xa7, 0x8b, 0x0c, 0x05, 0x86, 0x62, + 0x6c, 0xa8, 0x3c, 0xa4, 0x24, 0x9a, 0x92, 0x53, 0x55, 0x06, 0xc2, + 0xcf, 0x26, 0x71, 0x79, 0xfc, 0x24, 0xf4, 0xd2, 0xc4, 0x99, 0x1f, + 0x65, 0xc8, 0xda, 0xa4, 0xa7, 0xe3, 0xbc, 0x95, 0x3c, 0x85, 0x8d, + 0x24, 0x2f, 0xb3, 0x3c, 0xf9, 0x4f, 0x60, 0x5a, 0xad, 0x7b, 0x64, + 0xe1, 0x4b, 0xc6, 0xe2, 0x69, 0xa3, 0x61, 0x38, 0x52, 0xcb, 0xce, + 0x76, 0x62, 0xe6, 0xaf, 0x06, 0x7f, 0x39, 0xf8, 0x4f, 0x4a, 0x37, + 0x64, 0x37, 0x2b, 0x27, 0x2e, 0xda, 0xed, 0x8b, 0xe5, 0xbf, 0xb2, + 0xb8, 0x90, 0x7f, 0x75, 0x77, 0x0f, 0xed, 0xcb, 0x2d, 0x54, 0xcb, + 0x9c, 0xa8, 0xac, 0xfe, 0x84, 0x65, 0x16, 0xe8, 0x85, 0x81, 0xb5, + 0x7d, 0xff, 0xf8, 0xef, 0x09, 0xe8, 0x51, 0x5b, 0x65, 0x21, 0xfd, + 0xc5, 0xfb, 0xb6, 0xda, 0xfc, 0xae, 0xde, 0x56, 0xae, 0x64, 0x98, + 0xd7, 0xde, 0xe4, 0xe5, 0x60, 0x7d, 0xee, 0x95, 0x47, 0x03, 0xd6, + 0xed, 0x38, 0x3e, 0xf3, 0xe6, 0xfa, 0x28, 0x2b, 0xd7, 0xdb, 0xbc, + 0x6f, 0x21, 0x8e, 0x8d, 0xab, 0x15, 0xda, 0xba, 0x16, 0xe3, 0x53, + 0x79, 0xaf, 0xae, 0x0e, 0x91, 0x5e, 0xe9, 0xec, 0x30, 0x42, 0x35, + 0x47, 0x38, 0x33, 0xd4, 0x05, 0x3e, 0x17, 0x31, 0xec, 0x84, 0x9f, + 0xf2, 0x35, 0x6f, 0xc3, 0xf5, 0xb3, 0x17, 0x02, 0x86, 0xec, 0x74, + 0x25, 0xe5, 0xc0, 0x13, 0x7b, 0x29, 0x52, 0x73, 0xcf, 0x81, 0x8a, + 0x56, 0xca, 0x33, 0x90, 0xba, 0x1f, 0x87, 0xd0, 0x1e, 0x2f, 0x31, + 0xb0, 0xe3, 0x2e, 0xbb, 0x2e, 0x55, 0x35, 0x3e, 0xda, 0xd6, 0x36, + 0xdd, 0x38, 0x49, + }; + RSA* rsa = NULL; + const unsigned char* der = client_key_der_2048; + + ExpectNotNull(d2i_RSAPrivateKey(&rsa, &der, + sizeof_client_key_der_2048)); + ExpectIntEQ(RSA_private_decrypt((int)sizeof(ct), ct, em, rsa, + RSA_NO_PADDING), (int)sizeof(em)); + ExpectIntEQ(RSA_padding_check_PKCS1_OAEP_mgf1(out, (int)sizeof(out), + em, (int)sizeof(em), (int)sizeof(em), label, (int)sizeof(label), + EVP_sha256(), EVP_sha1()), (int)sizeof(msg)); + ExpectBufEQ(out, msg, sizeof(msg)); + #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_256) && \ + defined(WOLFSSL_SHA512) + { + /* msg encrypted by OpenSSL with OAEP SHA3-256 and + * MGF1-SHA-512. */ + static const unsigned char ct3[] = { + 0x74, 0x3f, 0xf3, 0xea, 0x2b, 0x45, 0x01, 0x10, 0x37, 0x0d, + 0xbb, 0x85, 0x95, 0xd7, 0x63, 0x9c, 0x71, 0x8d, 0x2d, 0x37, + 0xc6, 0x09, 0x2a, 0x76, 0x09, 0x76, 0x33, 0x9b, 0xba, 0x45, + 0xed, 0xf6, 0x4c, 0x9e, 0x7d, 0xc4, 0x4a, 0xd9, 0xfc, 0x45, + 0x4b, 0x7b, 0x9d, 0x11, 0xd7, 0x09, 0x96, 0xb4, 0x4d, 0x75, + 0xbc, 0xa5, 0x3c, 0x15, 0x0e, 0xc5, 0xe2, 0xa7, 0xa6, 0xea, + 0x0b, 0x6d, 0xb3, 0x48, 0xf2, 0x27, 0xad, 0x3b, 0x6c, 0xb7, + 0x8e, 0x7e, 0xc5, 0xa9, 0xa5, 0x93, 0xaa, 0x2c, 0xcf, 0x9e, + 0xb0, 0x4c, 0x16, 0x2d, 0x03, 0x31, 0x5b, 0x82, 0x51, 0x7e, + 0x32, 0x43, 0x92, 0x11, 0xa1, 0x9e, 0x01, 0xee, 0xc5, 0xc3, + 0xda, 0xbc, 0x4a, 0xb5, 0xf4, 0xf8, 0x10, 0x55, 0xbf, 0x08, + 0xdb, 0x09, 0xec, 0x51, 0xa0, 0xe5, 0xcd, 0xe6, 0x11, 0x60, + 0x60, 0x65, 0x09, 0x07, 0x0d, 0xe5, 0x19, 0x1c, 0x8d, 0xea, + 0xb2, 0xc1, 0x1a, 0x64, 0x2b, 0x3f, 0xb3, 0x0e, 0x51, 0x25, + 0xe0, 0x6d, 0xe2, 0xcd, 0xce, 0x8c, 0xe3, 0x50, 0x54, 0x1d, + 0x87, 0x27, 0x41, 0x4b, 0xb4, 0xcc, 0xc2, 0x45, 0x47, 0x7a, + 0xfd, 0x5f, 0x4a, 0xf7, 0x67, 0x7b, 0xe9, 0x5d, 0xf4, 0x14, + 0x1a, 0xaf, 0x9c, 0x9e, 0x7d, 0x2f, 0x5f, 0xd3, 0x1b, 0xe5, + 0x63, 0x3f, 0x20, 0x15, 0xed, 0xd8, 0xe2, 0xf0, 0xdb, 0xf2, + 0x9d, 0xf6, 0x86, 0x0e, 0xaa, 0x53, 0x7d, 0x4e, 0xc2, 0xd7, + 0x95, 0x11, 0xbb, 0xff, 0x75, 0x55, 0xcd, 0xb0, 0xda, 0x77, + 0x3a, 0x5c, 0x7a, 0xa8, 0xbf, 0x4d, 0xd1, 0x3e, 0xf6, 0x20, + 0xd9, 0x8d, 0xc9, 0x66, 0xf8, 0x13, 0x6e, 0xbc, 0xc7, 0x82, + 0x35, 0xa5, 0xfc, 0x44, 0xcd, 0x7a, 0x92, 0xd2, 0x90, 0x63, + 0xcf, 0x91, 0x70, 0xe8, 0xb1, 0x8b, 0x2c, 0xe6, 0xbd, 0x2c, + 0x18, 0xf2, 0xc8, 0xc3, 0x31, 0xff, + }; + + ExpectIntEQ(RSA_private_decrypt((int)sizeof(ct3), ct3, em, rsa, + RSA_NO_PADDING), (int)sizeof(em)); + ExpectIntEQ(RSA_padding_check_PKCS1_OAEP_mgf1(out, + (int)sizeof(out), em, (int)sizeof(em), (int)sizeof(em), NULL, + 0, EVP_sha3_256(), EVP_sha512()), (int)sizeof(msg)); + ExpectBufEQ(out, msg, sizeof(msg)); + } + #endif + RSA_free(rsa); + } +#endif +#endif + return EXPECT_RESULT(); +} + int test_wolfSSL_RSA_sign_sha3(void) { EXPECT_DECLS; diff --git a/tests/api/test_ossl_rsa.h b/tests/api/test_ossl_rsa.h index e3b2a186f60..622ad021274 100644 --- a/tests/api/test_ossl_rsa.h +++ b/tests/api/test_ossl_rsa.h @@ -28,6 +28,8 @@ int test_wolfSSL_RSA(void); int test_wolfSSL_RSA_DER(void); int test_wolfSSL_RSA_print(void); int test_wolfSSL_RSA_padding_add_PKCS1_PSS(void); +int test_wolfSSL_RSA_padding_PKCS1_OAEP(void); +int test_wolfSSL_RSA_padding_PKCS1_OAEP_mgf1(void); int test_wolfSSL_RSA_sign_sha3(void); int test_wolfSSL_RSA_get0_key(void); int test_wolfSSL_RSA_meth(void); @@ -53,6 +55,8 @@ int test_wolfSSL_PEM_write_mem_RSAPrivateKey(void); TEST_DECL_GROUP("ossl_rsa", test_wolfSSL_RSA_DER), \ TEST_DECL_GROUP("ossl_rsa", test_wolfSSL_RSA_print), \ TEST_DECL_GROUP("ossl_rsa", test_wolfSSL_RSA_padding_add_PKCS1_PSS), \ + TEST_DECL_GROUP("ossl_rsa", test_wolfSSL_RSA_padding_PKCS1_OAEP), \ + TEST_DECL_GROUP("ossl_rsa", test_wolfSSL_RSA_padding_PKCS1_OAEP_mgf1), \ TEST_DECL_GROUP("ossl_rsa", test_wolfSSL_RSA_sign_sha3), \ TEST_DECL_GROUP("ossl_rsa", test_wolfSSL_RSA_get0_key), \ TEST_DECL_GROUP("ossl_rsa", test_wolfSSL_RSA_meth), \ diff --git a/tests/api/test_ossl_sk.c b/tests/api/test_ossl_sk.c index db7ad9ec66e..e9feca3bbcf 100644 --- a/tests/api/test_ossl_sk.c +++ b/tests/api/test_ossl_sk.c @@ -179,6 +179,148 @@ int test_wolfSSL_sk_delete(void) return EXPECT_RESULT(); } +int test_wolfSSL_sk_delete_ptr(void) +{ + EXPECT_DECLS; +#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) + WOLFSSL_STACK* stack = NULL; + unsigned char data_1[1] = { 1 }; + unsigned char data_2[1] = { 2 }; + unsigned char data_3[1] = { 3 }; + + ExpectNotNull(stack = wolfSSL_sk_new_node(HEAP_HINT)); + + ExpectNull(wolfSSL_sk_delete_ptr(NULL, data_1)); + ExpectNull(wolfSSL_sk_delete_ptr(stack, NULL)); + ExpectNull(wolfSSL_sk_delete_ptr(stack, data_1)); + + ExpectIntEQ(wolfSSL_sk_push(stack, data_1), 1); + ExpectIntEQ(wolfSSL_sk_push(stack, data_2), 2); + ExpectIntEQ(wolfSSL_sk_push(stack, data_3), 3); + ExpectIntEQ(wolfSSL_sk_push(stack, data_2), 4); + + /* Only the first match is removed. */ + ExpectPtrEq(wolfSSL_sk_delete_ptr(stack, data_2), data_2); + ExpectIntEQ(wolfSSL_sk_num(stack), 3); + ExpectPtrEq(wolfSSL_sk_value(stack, 0), data_1); + ExpectPtrEq(wolfSSL_sk_value(stack, 1), data_3); + ExpectPtrEq(wolfSSL_sk_value(stack, 2), data_2); + /* Last, first and only. */ + ExpectPtrEq(wolfSSL_sk_delete_ptr(stack, data_2), data_2); + ExpectNull(wolfSSL_sk_delete_ptr(stack, data_2)); + ExpectPtrEq(wolfSSL_sk_delete_ptr(stack, data_1), data_1); + ExpectPtrEq(wolfSSL_sk_value(stack, 0), data_3); + ExpectPtrEq(wolfSSL_sk_delete_ptr(stack, data_3), data_3); + ExpectIntEQ(wolfSSL_sk_num(stack), 0); + ExpectNull(wolfSSL_sk_delete_ptr(stack, data_3)); + + wolfSSL_sk_free(stack); +#endif + return EXPECT_RESULT(); +} + +int test_wolfSSL_sk_X509_insert_delete_ptr(void) +{ + EXPECT_DECLS; +#if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ + !defined(NO_FILESYSTEM) && !defined(NO_RSA) + WOLF_STACK_OF(WOLFSSL_X509)* certs = NULL; + WOLFSSL_X509* ca = NULL; + WOLFSSL_X509* srv = NULL; + WOLFSSL_X509* cli = NULL; + + ExpectNotNull(ca = wolfSSL_X509_load_certificate_file(caCertFile, + WOLFSSL_FILETYPE_PEM)); + ExpectNotNull(srv = wolfSSL_X509_load_certificate_file(svrCertFile, + WOLFSSL_FILETYPE_PEM)); + ExpectNotNull(cli = wolfSSL_X509_load_certificate_file(cliCertFile, + WOLFSSL_FILETYPE_PEM)); + ExpectNotNull(certs = sk_X509_new_null()); + + ExpectIntLE(sk_X509_insert(NULL, ca, 0), 0); + ExpectIntEQ(sk_X509_insert(certs, ca, 0), 1); + ExpectIntEQ(sk_X509_insert(certs, srv, -1), 2); + /* Key cert goes first. */ + ExpectIntEQ(sk_X509_insert(certs, cli, 0), 3); + ExpectPtrEq(sk_X509_value(certs, 0), cli); + ExpectPtrEq(sk_X509_value(certs, 1), ca); + ExpectPtrEq(sk_X509_value(certs, 2), srv); + + ExpectNull(sk_X509_delete_ptr(NULL, ca)); + ExpectPtrEq(sk_X509_delete_ptr(certs, ca), ca); + ExpectNull(sk_X509_delete_ptr(certs, ca)); + ExpectIntEQ(sk_X509_num(certs), 2); + ExpectPtrEq(sk_X509_value(certs, 0), cli); + ExpectPtrEq(sk_X509_value(certs, 1), srv); + /* Insert in the middle. */ + ExpectIntEQ(sk_X509_insert(certs, ca, 1), 3); + ExpectPtrEq(sk_X509_value(certs, 1), ca); + ExpectPtrEq(sk_X509_value(certs, 2), srv); + + /* Stack only borrows the certs. */ + sk_X509_free(certs); + X509_free(ca); + X509_free(srv); + X509_free(cli); +#endif + return EXPECT_RESULT(); +} + +#ifdef OPENSSL_ALL +static int test_sk_sort_cmp(const void* const* a, const void* const* b) +{ + return (int)**(const unsigned char* const*)a - + (int)**(const unsigned char* const*)b; +} +#endif + +int test_wolfSSL_sk_sort(void) +{ + EXPECT_DECLS; +#ifdef OPENSSL_ALL + WOLFSSL_STACK* stack = NULL; + WOLFSSL_STACK* node; + unsigned char data_3[1] = { 3 }; + unsigned char data_1[1] = { 1 }; + unsigned char data_2[1] = { 2 }; + unsigned char data_1b[1] = { 1 }; + + wolfSSL_sk_sort(NULL); + ExpectTrue(wolfSSL_sk_set_cmp_func(NULL, test_sk_sort_cmp) == NULL); + ExpectNotNull(stack = wolfSSL_sk_new_node(HEAP_HINT)); + wolfSSL_sk_sort(stack); + ExpectIntEQ(wolfSSL_sk_push(stack, data_3), 1); + ExpectIntEQ(wolfSSL_sk_push(stack, data_1), 2); + ExpectIntEQ(wolfSSL_sk_push(stack, data_2), 3); + ExpectIntEQ(wolfSSL_sk_push(stack, data_1b), 4); + + /* No comparator: order kept. */ + wolfSSL_sk_sort(stack); + ExpectPtrEq(wolfSSL_sk_value(stack, 0), data_3); + ExpectPtrEq(wolfSSL_sk_value(stack, 3), data_1b); + + /* Stable, and each hash moves with its data. */ + ExpectTrue(wolfSSL_sk_set_cmp_func(stack, test_sk_sort_cmp) == NULL); + for (node = stack; EXPECT_SUCCESS() && (node != NULL); node = node->next) { + ExpectTrue(node->comp == test_sk_sort_cmp); + node->hash = *(unsigned char*)node->data.generic; + } + wolfSSL_sk_sort(stack); + ExpectIntEQ(wolfSSL_sk_num(stack), 4); + ExpectPtrEq(wolfSSL_sk_value(stack, 0), data_1); + ExpectPtrEq(wolfSSL_sk_value(stack, 1), data_1b); + ExpectPtrEq(wolfSSL_sk_value(stack, 2), data_2); + ExpectPtrEq(wolfSSL_sk_value(stack, 3), data_3); + for (node = stack; EXPECT_SUCCESS() && (node != NULL); node = node->next) { + ExpectIntEQ(node->hash, *(unsigned char*)node->data.generic); + } + ExpectTrue(wolfSSL_sk_set_cmp_func(stack, NULL) == test_sk_sort_cmp); + + wolfSSL_sk_free(stack); +#endif + return EXPECT_RESULT(); +} + int test_wolfSSL_sk_insert(void) { EXPECT_DECLS; @@ -265,6 +407,60 @@ int test_wolfSSL_shallow_sk_dup(void) return EXPECT_RESULT(); } +int test_wolfSSL_X509_chain_up_ref(void) +{ + EXPECT_DECLS; +#if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ + !defined(NO_FILESYSTEM) && !defined(NO_RSA) + WOLF_STACK_OF(WOLFSSL_X509)* chain = NULL; + WOLF_STACK_OF(WOLFSSL_X509)* copy = NULL; + WOLFSSL_X509* ca = NULL; + WOLFSSL_X509* srv = NULL; + WOLFSSL_X509* x509; + unsigned char* der = NULL; + int i; + + ExpectNull(X509_chain_up_ref(NULL)); + ExpectNotNull(ca = wolfSSL_X509_load_certificate_file(caCertFile, + WOLFSSL_FILETYPE_PEM)); + ExpectNotNull(srv = wolfSSL_X509_load_certificate_file(svrCertFile, + WOLFSSL_FILETYPE_PEM)); + ExpectNotNull(chain = sk_X509_new_null()); + ExpectIntEQ(sk_X509_push(chain, srv), 1); + if (EXPECT_FAIL()) + X509_free(srv); + ExpectIntEQ(sk_X509_push(chain, ca), 2); + if (EXPECT_FAIL()) + X509_free(ca); + + /* Same certs in the same order. */ + ExpectNotNull(copy = X509_chain_up_ref(chain)); + ExpectIntEQ(sk_X509_num(copy), 2); + ExpectPtrEq(sk_X509_value(copy, 0), srv); + ExpectPtrEq(sk_X509_value(copy, 1), ca); + + /* The copy holds its own references. */ + sk_X509_pop_free(chain, X509_free); + chain = NULL; + for (i = 0; i < 2; i++) { + x509 = sk_X509_value(copy, i); + ExpectNotNull(X509_get_subject_name(x509)); + ExpectIntGT(i2d_X509(x509, &der), 0); + XFREE(der, NULL, DYNAMIC_TYPE_OPENSSL); + der = NULL; + } + sk_X509_pop_free(copy, X509_free); + + /* An empty chain gives an empty copy. */ + ExpectNotNull(chain = sk_X509_new_null()); + ExpectNotNull(copy = X509_chain_up_ref(chain)); + ExpectIntEQ(sk_X509_num(copy), 0); + sk_X509_pop_free(copy, X509_free); + sk_X509_pop_free(chain, X509_free); +#endif + return EXPECT_RESULT(); +} + int test_wolfSSL_sk_num(void) { EXPECT_DECLS; diff --git a/tests/api/test_ossl_sk.h b/tests/api/test_ossl_sk.h index 3acb4369a5d..dff0a06b064 100644 --- a/tests/api/test_ossl_sk.h +++ b/tests/api/test_ossl_sk.h @@ -30,7 +30,11 @@ int test_wolfSSL_sk_free(void); int test_wolfSSL_sk_push_pop(void); int test_wolfSSL_sk_insert(void); int test_wolfSSL_sk_delete(void); +int test_wolfSSL_sk_delete_ptr(void); +int test_wolfSSL_sk_X509_insert_delete_ptr(void); +int test_wolfSSL_sk_sort(void); int test_wolfSSL_shallow_sk_dup(void); +int test_wolfSSL_X509_chain_up_ref(void); int test_wolfSSL_sk_num(void); int test_wolfSSL_sk_value(void); int test_wolfssl_sk_GENERIC(void); @@ -54,7 +58,12 @@ int test_wolfSSL_CIPHER_current(void); TEST_DECL_GROUP("ossl_sk", test_wolfSSL_sk_push_pop), \ TEST_DECL_GROUP("ossl_sk", test_wolfSSL_sk_insert), \ TEST_DECL_GROUP("ossl_sk", test_wolfSSL_sk_delete), \ + TEST_DECL_GROUP("ossl_sk", test_wolfSSL_sk_delete_ptr), \ + TEST_DECL_GROUP("ossl_sk", \ + test_wolfSSL_sk_X509_insert_delete_ptr), \ + TEST_DECL_GROUP("ossl_sk", test_wolfSSL_sk_sort), \ TEST_DECL_GROUP("ossl_sk", test_wolfSSL_shallow_sk_dup), \ + TEST_DECL_GROUP("ossl_sk", test_wolfSSL_X509_chain_up_ref), \ TEST_DECL_GROUP("ossl_sk", test_wolfSSL_sk_num), \ TEST_DECL_GROUP("ossl_sk", test_wolfSSL_sk_value), \ TEST_DECL_GROUP("ossl_sk", test_wolfssl_sk_GENERIC), \ diff --git a/tests/api/test_ossl_x509.c b/tests/api/test_ossl_x509.c index bfa4b0b6981..8f30e21df24 100644 --- a/tests/api/test_ossl_x509.c +++ b/tests/api/test_ossl_x509.c @@ -306,7 +306,12 @@ int test_wolfSSL_X509_subject_name_hash(void) ExpectNotNull(x509 = X509_new()); ExpectIntEQ(X509_subject_name_hash(NULL), 0); - ExpectIntEQ(X509_subject_name_hash(x509), 0); + /* Empty name: hash of an empty encoding, as OpenSSL. */ +#ifndef NO_SHA + ExpectIntEQ(X509_subject_name_hash(x509), 0xeea339daUL); +#else + ExpectIntEQ(X509_subject_name_hash(x509), 0x42c4b0e3UL); +#endif X509_free(x509); x509 = NULL; @@ -348,7 +353,12 @@ int test_wolfSSL_X509_issuer_name_hash(void) ExpectNotNull(x509 = X509_new()); ExpectIntEQ(X509_issuer_name_hash(NULL), 0); - ExpectIntEQ(X509_issuer_name_hash(x509), 0); + /* Empty name: hash of an empty encoding, as OpenSSL. */ +#ifndef NO_SHA + ExpectIntEQ(X509_issuer_name_hash(x509), 0xeea339daUL); +#else + ExpectIntEQ(X509_issuer_name_hash(x509), 0x42c4b0e3UL); +#endif X509_free(x509); x509 = NULL; diff --git a/tests/api/test_ossl_x509_crypto.c b/tests/api/test_ossl_x509_crypto.c index 230cfaf3938..d90c86a4f50 100644 --- a/tests/api/test_ossl_x509_crypto.c +++ b/tests/api/test_ossl_x509_crypto.c @@ -30,6 +30,9 @@ #include #include +#ifdef OPENSSL_EXTRA + #include +#endif #include #include #include @@ -364,6 +367,379 @@ int test_wolfSSL_X509_verify_mldsa_privkey_pkey(void) return EXPECT_RESULT(); } +#if defined(OPENSSL_EXTRA) && defined(HAVE_CRL) && !defined(NO_FILESYSTEM) && \ + !defined(NO_CERTS) && !defined(NO_RSA) +static int test_X509_CRL_verify_file(const char* crlFile, const char* caFile, + int expected) +{ + EXPECT_DECLS; + WOLFSSL_X509_CRL* crl = NULL; + WOLFSSL_X509* ca = NULL; + WOLFSSL_EVP_PKEY* pkey = NULL; + XFILE fp = XBADFILE; + + ExpectTrue((fp = XFOPEN(crlFile, "rb")) != XBADFILE); + ExpectNotNull(crl = PEM_read_X509_CRL(fp, NULL, NULL, NULL)); + if (fp != XBADFILE) + XFCLOSE(fp); + ExpectNotNull(ca = wolfSSL_X509_load_certificate_file(caFile, + WOLFSSL_FILETYPE_PEM)); + ExpectNotNull(pkey = X509_get_pubkey(ca)); + ExpectIntEQ(X509_CRL_verify(crl, pkey), expected); + + EVP_PKEY_free(pkey); + X509_free(ca); + X509_CRL_free(crl); + return EXPECT_RESULT(); +} +#endif + +int test_wolfSSL_X509_CRL_verify(void) +{ + EXPECT_DECLS; +#if defined(OPENSSL_EXTRA) && defined(HAVE_CRL) && !defined(NO_FILESYSTEM) && \ + !defined(NO_CERTS) && !defined(NO_RSA) + WOLFSSL_X509_CRL* crl = NULL; + WOLFSSL_X509* ca = NULL; + WOLFSSL_EVP_PKEY* pkey = NULL; + byte der[4096]; + int derSz = 0; + XFILE fp = XBADFILE; + + ExpectIntEQ(test_X509_CRL_verify_file("./certs/crl/crl.pem", caCertFile, + 1), TEST_SUCCESS); + ExpectIntEQ(test_X509_CRL_verify_file("./certs/crl/crl.pem", svrCertFile, + 0), TEST_SUCCESS); +#ifdef HAVE_ECC + ExpectIntEQ(test_X509_CRL_verify_file("./certs/crl/caEccCrl.pem", + caEccCertFile, 1), TEST_SUCCESS); + /* Key type does not match the signature. */ + ExpectIntEQ(test_X509_CRL_verify_file("./certs/crl/caEccCrl.pem", + caCertFile, -1), TEST_SUCCESS); +#endif + + ExpectNotNull(ca = wolfSSL_X509_load_certificate_file(caCertFile, + WOLFSSL_FILETYPE_PEM)); + ExpectNotNull(pkey = X509_get_pubkey(ca)); + ExpectIntEQ(X509_CRL_verify(NULL, pkey), -1); + + /* Changed signature. */ + ExpectTrue((fp = XFOPEN("./certs/crl/crl.der", "rb")) != XBADFILE); + ExpectIntGT(derSz = (int)XFREAD(der, 1, sizeof(der), fp), 0); + if (fp != XBADFILE) + XFCLOSE(fp); + if (derSz > 0) + der[derSz - 1] ^= 0x01; + ExpectNotNull(crl = wolfSSL_d2i_X509_CRL(NULL, der, derSz)); + ExpectIntEQ(X509_CRL_verify(crl, NULL), -1); + ExpectIntEQ(X509_CRL_verify(crl, pkey), 0); + X509_CRL_free(crl); + crl = NULL; + + /* Nothing signed yet. */ + ExpectNotNull(crl = X509_CRL_new()); + ExpectIntEQ(X509_CRL_verify(crl, pkey), -1); + X509_CRL_free(crl); + + EVP_PKEY_free(pkey); + X509_free(ca); +#endif + return EXPECT_RESULT(); +} + +#if defined(OPENSSL_EXTRA) && !defined(NO_FILESYSTEM) && !defined(NO_BIO) && \ + !defined(NO_CERTS) +static WOLFSSL_EVP_PKEY* test_x509_verify_privkey_load(const char* file) +{ + WOLFSSL_BIO* bio = wolfSSL_BIO_new_file(file, "rb"); + WOLFSSL_EVP_PKEY* pkey = NULL; + + if (bio != NULL) { + pkey = wolfSSL_PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL); + wolfSSL_BIO_free(bio); + } + return pkey; +} + +/* X509_verify() of certFile and, with crlFile, X509_CRL_verify() with the + * private key in keyFile. */ +static int test_x509_verify_privkey_file(const char* certFile, + const char* crlFile, const char* keyFile, int expected) +{ + EXPECT_DECLS; + WOLFSSL_X509* x509 = NULL; + WOLFSSL_EVP_PKEY* pkey = NULL; +#ifdef HAVE_CRL + WOLFSSL_X509_CRL* crl = NULL; + XFILE fp = XBADFILE; +#endif + + ExpectNotNull(pkey = test_x509_verify_privkey_load(keyFile)); + ExpectNotNull(x509 = wolfSSL_X509_load_certificate_file(certFile, + WOLFSSL_FILETYPE_PEM)); + ExpectIntEQ(wolfSSL_X509_verify(x509, pkey), expected); +#ifdef HAVE_CRL + if (crlFile != NULL) { + ExpectTrue((fp = XFOPEN(crlFile, "rb")) != XBADFILE); + ExpectNotNull(crl = wolfSSL_PEM_read_X509_CRL(fp, NULL, NULL, NULL)); + if (fp != XBADFILE) + XFCLOSE(fp); + ExpectIntEQ(wolfSSL_X509_CRL_verify(crl, pkey), expected); + wolfSSL_X509_CRL_free(crl); + } +#else + (void)crlFile; +#endif + + wolfSSL_X509_free(x509); + wolfSSL_EVP_PKEY_free(pkey); + return EXPECT_RESULT(); +} +#endif + +/* As OpenSSL, a private key verifies with its public part. */ +int test_wolfSSL_X509_verify_privkey(void) +{ + EXPECT_DECLS; +#if defined(OPENSSL_EXTRA) && !defined(NO_FILESYSTEM) && !defined(NO_BIO) && \ + !defined(NO_CERTS) +#if defined(HAVE_ED448) && defined(HAVE_ED448_KEY_EXPORT) && \ + defined(HAVE_ED448_KEY_IMPORT) + WOLFSSL_X509* root = NULL; + WOLFSSL_X509* ca = NULL; + WOLFSSL_EVP_PKEY* pub = NULL; + unsigned char buf[256]; + const unsigned char* p = NULL; + int bufSz = (int)sizeof(buf); +#endif + +#ifndef NO_RSA + ExpectIntEQ(test_x509_verify_privkey_file(caCertFile, + "./certs/crl/crl.pem", "./certs/ca-key.pem", WOLFSSL_SUCCESS), + TEST_SUCCESS); + ExpectIntEQ(test_x509_verify_privkey_file(caCertFile, + "./certs/crl/crl.pem", "./certs/server-key.pem", WOLFSSL_FAILURE), + TEST_SUCCESS); +#endif +#ifdef HAVE_ECC + ExpectIntEQ(test_x509_verify_privkey_file(caEccCertFile, + "./certs/crl/caEccCrl.pem", "./certs/ca-ecc-key.pem", + WOLFSSL_SUCCESS), TEST_SUCCESS); + ExpectIntEQ(test_x509_verify_privkey_file(caEccCertFile, + "./certs/crl/caEccCrl.pem", "./certs/ecc-key.pem", WOLFSSL_FAILURE), + TEST_SUCCESS); +#endif +#if defined(HAVE_ED448) && defined(HAVE_ED448_KEY_EXPORT) && \ + defined(HAVE_ED448_KEY_IMPORT) + ExpectIntEQ(test_x509_verify_privkey_file("./certs/ed448/ca-ed448.pem", + NULL, "./certs/ed448/root-ed448-priv.pem", WOLFSSL_SUCCESS), + TEST_SUCCESS); + ExpectIntEQ(test_x509_verify_privkey_file("./certs/ed448/ca-ed448.pem", + NULL, "./certs/ed448/ca-ed448-priv.pem", WOLFSSL_FAILURE), + TEST_SUCCESS); + /* And with the public key */ + ExpectNotNull(root = wolfSSL_X509_load_certificate_file( + "./certs/ed448/root-ed448.pem", WOLFSSL_FILETYPE_PEM)); + ExpectNotNull(ca = wolfSSL_X509_load_certificate_file( + "./certs/ed448/ca-ed448.pem", WOLFSSL_FILETYPE_PEM)); + ExpectIntEQ(wolfSSL_X509_get_pubkey_buffer(root, buf, &bufSz), + WOLFSSL_SUCCESS); + p = buf; + ExpectNotNull(pub = wolfSSL_d2i_PUBKEY(NULL, &p, bufSz)); + ExpectIntEQ(wolfSSL_X509_verify(ca, pub), WOLFSSL_SUCCESS); + wolfSSL_EVP_PKEY_free(pub); + wolfSSL_X509_free(ca); + wolfSSL_X509_free(root); +#endif +#if !defined(NO_DSA) && !defined(NO_RSA) && \ + (defined(WOLFSSL_QT) || defined(OPENSSL_ALL)) + /* The public part of a DSA key cannot be encoded: not checked. A DSA PEM + * private key is read with WOLFSSL_QT or OPENSSL_ALL. */ + ExpectIntEQ(test_x509_verify_privkey_file(caCertFile, NULL, + "./certs/dsa2048.pem", WOLFSSL_FATAL_ERROR), TEST_SUCCESS); +#endif +#endif + return EXPECT_RESULT(); +} + +int test_wolfSSL_X509_CRL_get_REVOKED_serial(void) +{ + EXPECT_DECLS; +#if defined(OPENSSL_EXTRA) && defined(HAVE_CRL) + /* CRL that revokes serial 0x020105. These bytes also read as the DER + * encoding of 5. */ + static const unsigned char crlDer[] = { + 0x30, 0x81, 0xba, 0x30, 0x63, 0x02, 0x01, 0x01, 0x30, 0x0a, 0x06, 0x08, + 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x1a, 0x31, 0x18, + 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0f, 0x43, 0x52, 0x4c, + 0x20, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x20, 0x74, 0x65, 0x73, 0x74, + 0x17, 0x0d, 0x32, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x32, 0x31, 0x32, 0x35, 0x31, 0x32, 0x30, + 0x38, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x16, 0x30, 0x14, + 0x02, 0x03, 0x02, 0x01, 0x05, 0x17, 0x0d, 0x32, 0x36, 0x30, 0x31, 0x30, + 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x0a, 0x06, 0x08, + 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x47, 0x00, 0x30, + 0x44, 0x02, 0x20, 0x7a, 0xfe, 0xd1, 0xa0, 0x33, 0x2a, 0xff, 0xad, 0x51, + 0x36, 0x78, 0x60, 0x63, 0x46, 0x52, 0x8e, 0x74, 0x2e, 0xf1, 0xe5, 0x72, + 0x5f, 0x0e, 0x81, 0xd9, 0x5c, 0xca, 0x2b, 0xbb, 0x32, 0xb6, 0x80, 0x02, + 0x20, 0x2e, 0xa2, 0x8b, 0x7a, 0x2c, 0x44, 0x3f, 0x2b, 0xee, 0xe4, 0x64, + 0x73, 0x04, 0xea, 0x83, 0x49, 0x62, 0x0c, 0x44, 0xa3, 0x63, 0xc2, 0xfd, + 0xbe, 0x01, 0x7c, 0x5f, 0x31, 0x72, 0x9a, 0xd7, 0x76, + }; +#ifdef WOLFSSL_CERT_GEN + /* Content of a serial built by hand, and its DER */ + static unsigned char highSerial[] = { 0x8a, 0x01 }; + static const unsigned char highDer[] = { 0x02, 0x03, 0x00, 0x8a, 0x01 }; + WOLFSSL_ASN1_INTEGER high; + WOLFSSL_X509_REVOKED highRev; + unsigned char* highOut = NULL; +#endif + WOLFSSL_X509_CRL* crl = NULL; + WOLF_STACK_OF(WOLFSSL_X509_REVOKED)* revs = NULL; + WOLFSSL_X509_REVOKED* rev = NULL; + const WOLFSSL_ASN1_INTEGER* serial = NULL; + WOLFSSL_ASN1_INTEGER* ai = NULL; + WOLFSSL_BIGNUM* bn = NULL; +#ifdef WOLFSSL_CERT_GEN + static const unsigned char p128[] = { 0x02, 0x02, 0x00, 0x80 }; + WOLFSSL_X509_REVOKED add; + unsigned char* der = NULL; +#endif + + ExpectNotNull(crl = wolfSSL_d2i_X509_CRL(NULL, crlDer, + (int)sizeof(crlDer))); + ExpectNotNull(revs = X509_CRL_get_REVOKED(crl)); + ExpectIntEQ(sk_X509_REVOKED_num(revs), 1); + ExpectNotNull(rev = sk_X509_REVOKED_value(revs, 0)); + ExpectNotNull(serial = X509_REVOKED_get0_serialNumber(rev)); + ExpectIntEQ(ASN1_INTEGER_get(serial), 0x020105); + ExpectNotNull(bn = ASN1_INTEGER_to_BN(serial, NULL)); + ExpectIntEQ(BN_get_word(bn), 0x020105); + ExpectNotNull(ai = ASN1_INTEGER_new()); + ExpectIntEQ(ASN1_INTEGER_set(ai, 0x020105), 1); + ExpectIntEQ(ASN1_INTEGER_cmp(serial, ai), 0); + ExpectIntEQ(ASN1_INTEGER_set(ai, 5), 1); + ExpectIntNE(ASN1_INTEGER_cmp(serial, ai), 0); +#ifdef WOLFSSL_CERT_GEN + /* An entry added back keeps its serial. */ + ExpectIntEQ(wolfSSL_X509_CRL_add_revoked(crl, rev), WOLFSSL_SUCCESS); + ExpectNotNull(revs = X509_CRL_get_REVOKED(crl)); + ExpectIntEQ(sk_X509_REVOKED_num(revs), 2); + ExpectNotNull(rev = sk_X509_REVOKED_value(revs, 1)); + ExpectIntEQ(ASN1_INTEGER_get(X509_REVOKED_get0_serialNumber(rev)), + 0x020105); + /* A serial with the top bit set is encoded with a zero octet. */ + XMEMSET(&add, 0, sizeof(add)); + ExpectIntEQ(ASN1_INTEGER_set(ai, 0x80), 1); + add.serialNumber = ai; + ExpectIntEQ(wolfSSL_X509_CRL_add_revoked(crl, &add), WOLFSSL_SUCCESS); + ExpectNotNull(revs = X509_CRL_get_REVOKED(crl)); + ExpectIntEQ(sk_X509_REVOKED_num(revs), 3); + ExpectNotNull(rev = sk_X509_REVOKED_value(revs, 2)); + ExpectIntEQ(i2d_ASN1_INTEGER(X509_REVOKED_get0_serialNumber(rev), &der), + (int)sizeof(p128)); + ExpectBufEQ(der, p128, sizeof(p128)); + XFREE(der, NULL, DYNAMIC_TYPE_ASN1); +#endif + + BN_free(bn); + ASN1_INTEGER_free(ai); + X509_CRL_free(crl); +#ifdef WOLFSSL_CERT_GEN + /* An entry serial with the top bit set is encoded with a zero octet. */ + crl = NULL; + XMEMSET(&high, 0, sizeof(high)); + high.data = highSerial; + high.length = (int)sizeof(highSerial); + XMEMSET(&highRev, 0, sizeof(highRev)); + highRev.serialNumber = &high; + ExpectNotNull(crl = wolfSSL_d2i_X509_CRL(NULL, crlDer, + (int)sizeof(crlDer))); + ExpectIntEQ(wolfSSL_X509_CRL_add_revoked(crl, &highRev), WOLFSSL_SUCCESS); + ExpectNotNull(revs = X509_CRL_get_REVOKED(crl)); + ExpectIntEQ(sk_X509_REVOKED_num(revs), 2); + ExpectNotNull(rev = sk_X509_REVOKED_value(revs, 1)); + ExpectIntEQ(i2d_ASN1_INTEGER(X509_REVOKED_get0_serialNumber(rev), + &highOut), (int)sizeof(highDer)); + ExpectBufEQ(highOut, highDer, sizeof(highDer)); + XFREE(highOut, NULL, DYNAMIC_TYPE_ASN1); + X509_CRL_free(crl); +#endif +#endif + return EXPECT_RESULT(); +} + +/* A cert whose serial has the top bit set is revoked by the entry that + * X509_CRL_add_revoked makes from X509_get_serialNumber. */ +int test_wolfSSL_X509_CRL_add_revoked_serial(void) +{ + EXPECT_DECLS; +#if defined(OPENSSL_EXTRA) && defined(HAVE_CRL) && \ + defined(WOLFSSL_CERT_GEN) && !defined(NO_FILESYSTEM) && \ + !defined(NO_BIO) && !defined(NO_CERTS) && !defined(NO_RSA) + /* 0x8a0102030405060708 */ + static const unsigned char serialDer[] = { + 0x02, 0x0a, 0x00, 0x8a, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 + }; + const unsigned char* p = serialDer; + unsigned char* der = NULL; + int derSz = 0; + WOLFSSL_ASN1_INTEGER* ai = NULL; + WOLFSSL_EVP_PKEY* key = NULL; + WOLFSSL_X509* tmp = NULL; + WOLFSSL_X509* leaf = NULL; + WOLFSSL_X509* ca = NULL; + WOLFSSL_X509_CRL* crl = NULL; + WOLFSSL_X509_STORE* store = NULL; + WOLFSSL_X509_STORE_CTX* ctx = NULL; + WOLFSSL_X509_REVOKED rev; + XFILE fp = XBADFILE; + + /* Issue the server cert again with the serial. */ + ExpectNotNull(ai = d2i_ASN1_INTEGER(NULL, &p, (long)sizeof(serialDer))); + ExpectNotNull(tmp = X509_load_certificate_file(svrCertFile, + SSL_FILETYPE_PEM)); + ExpectIntEQ(X509_set_serialNumber(tmp, ai), WOLFSSL_SUCCESS); + ExpectNotNull(key = test_x509_verify_privkey_load("./certs/ca-key.pem")); + ExpectIntGT(X509_sign(tmp, key, EVP_sha256()), 0); + ExpectIntGT(derSz = i2d_X509(tmp, &der), 0); + p = der; + ExpectNotNull(leaf = d2i_X509(NULL, &p, derSz)); + ExpectIntEQ(ASN1_INTEGER_cmp(X509_get_serialNumber(leaf), ai), 0); + + ExpectTrue((fp = XFOPEN("./certs/crl/crl.pem", "rb")) != XBADFILE); + ExpectNotNull(crl = PEM_read_X509_CRL(fp, NULL, NULL, NULL)); + if (fp != XBADFILE) + XFCLOSE(fp); + XMEMSET(&rev, 0, sizeof(rev)); + rev.serialNumber = X509_get_serialNumber(leaf); + ExpectIntEQ(wolfSSL_X509_CRL_add_revoked(crl, &rev), WOLFSSL_SUCCESS); + + ExpectNotNull(ca = X509_load_certificate_file(caCertFile, + SSL_FILETYPE_PEM)); + ExpectNotNull(store = X509_STORE_new()); + ExpectIntEQ(X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK), + WOLFSSL_SUCCESS); + ExpectIntEQ(X509_STORE_add_cert(store, ca), WOLFSSL_SUCCESS); + ExpectIntEQ(X509_STORE_add_crl(store, crl), WOLFSSL_SUCCESS); + ExpectNotNull(ctx = X509_STORE_CTX_new()); + ExpectIntEQ(X509_STORE_CTX_init(ctx, store, leaf, NULL), WOLFSSL_SUCCESS); + ExpectIntNE(X509_verify_cert(ctx), WOLFSSL_SUCCESS); + ExpectIntEQ(X509_STORE_CTX_get_error(ctx), X509_V_ERR_CERT_REVOKED); + + X509_STORE_CTX_free(ctx); + X509_STORE_free(store); + X509_free(ca); + X509_CRL_free(crl); + X509_free(leaf); + XFREE(der, NULL, DYNAMIC_TYPE_OPENSSL); + X509_free(tmp); + EVP_PKEY_free(key); + ASN1_INTEGER_free(ai); +#endif + return EXPECT_RESULT(); +} + int test_wolfSSL_X509_sign(void) { EXPECT_DECLS; @@ -561,8 +937,12 @@ int test_wolfSSL_X509_sign(void) ExpectIntGT(cnSz = X509_NAME_get_sz(name), 0); ExpectNotNull(cn = (char*)XMALLOC(cnSz, HEAP_HINT, DYNAMIC_TYPE_OPENSSL)); ExpectNull(X509_NAME_oneline(NULL, cn, (int)cnSz)); + ExpectTrue(cn == NULL || cn[0] == '\0'); ExpectPtrEq(X509_NAME_oneline(name, cn, 0), cn); + if (cn != NULL) + cn[0] = 'x'; ExpectPtrEq(X509_NAME_oneline(emptyName, cn, (int)cnSz), cn); + ExpectTrue(cn == NULL || cn[0] == '\0'); ExpectNull(X509_NAME_oneline(emptyName, NULL, 0)); ExpectPtrEq(X509_NAME_oneline(name, cn, (int)cnSz), cn); ExpectIntEQ(0, XSTRNCMP(cn, dCert.subject, XSTRLEN(cn))); diff --git a/tests/api/test_ossl_x509_crypto.h b/tests/api/test_ossl_x509_crypto.h index 68ce053d6b0..0cb0b9b4427 100644 --- a/tests/api/test_ossl_x509_crypto.h +++ b/tests/api/test_ossl_x509_crypto.h @@ -29,6 +29,10 @@ int test_wolfSSL_X509_check_private_key_mldsa(void); int test_wolfSSL_X509_verify(void); int test_wolfSSL_X509_verify_mldsa_cross_level(void); int test_wolfSSL_X509_verify_mldsa_privkey_pkey(void); +int test_wolfSSL_X509_CRL_verify(void); +int test_wolfSSL_X509_verify_privkey(void); +int test_wolfSSL_X509_CRL_get_REVOKED_serial(void); +int test_wolfSSL_X509_CRL_add_revoked_serial(void); int test_wolfSSL_X509_sign(void); int test_wolfSSL_X509_sign2(void); int test_wolfSSL_make_cert(void); @@ -42,6 +46,12 @@ int test_wolfSSL_make_cert(void); test_wolfSSL_X509_verify_mldsa_cross_level), \ TEST_DECL_GROUP("ossl_x509_crypto", \ test_wolfSSL_X509_verify_mldsa_privkey_pkey), \ + TEST_DECL_GROUP("ossl_x509_crypto", test_wolfSSL_X509_CRL_verify), \ + TEST_DECL_GROUP("ossl_x509_crypto", test_wolfSSL_X509_verify_privkey), \ + TEST_DECL_GROUP("ossl_x509_crypto", \ + test_wolfSSL_X509_CRL_get_REVOKED_serial), \ + TEST_DECL_GROUP("ossl_x509_crypto", \ + test_wolfSSL_X509_CRL_add_revoked_serial), \ TEST_DECL_GROUP("ossl_x509_crypto", test_wolfSSL_X509_sign), \ TEST_DECL_GROUP("ossl_x509_crypto", test_wolfSSL_X509_sign2), \ TEST_DECL_GROUP("ossl_x509_crypto", test_wolfSSL_make_cert) diff --git a/tests/api/test_ossl_x509_ext.c b/tests/api/test_ossl_x509_ext.c index af2bedc46e2..3606946435f 100644 --- a/tests/api/test_ossl_x509_ext.c +++ b/tests/api/test_ossl_x509_ext.c @@ -1714,6 +1714,68 @@ int test_wolfSSL_X509V3_EXT(void) return EXPECT_RESULT(); } +int test_wolfSSL_X509V3_EXT_d2i_skid(void) +{ + EXPECT_DECLS; +#if defined(OPENSSL_EXTRA) && defined(HAVE_ECC) + /* Self-signed P-256 cert with the 8 byte subjectKeyIdentifier + * 01:02:03:04:05:06:07:08. */ + static const unsigned char certDer[] = { + 0x30, 0x82, 0x01, 0x66, 0x30, 0x82, 0x01, 0x0C, 0xA0, 0x03, 0x02, 0x01, + 0x02, 0x02, 0x14, 0x15, 0x97, 0xDB, 0x0A, 0x35, 0x44, 0x83, 0x46, 0x36, + 0x38, 0xDF, 0xB6, 0x18, 0x9C, 0x99, 0xED, 0xFC, 0xEE, 0x78, 0x17, 0x30, + 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30, + 0x0F, 0x31, 0x0D, 0x30, 0x0B, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x04, + 0x53, 0x4B, 0x49, 0x38, 0x30, 0x20, 0x17, 0x0D, 0x32, 0x36, 0x31, 0x30, + 0x31, 0x33, 0x31, 0x39, 0x35, 0x34, 0x31, 0x32, 0x5A, 0x18, 0x0F, 0x32, + 0x31, 0x32, 0x36, 0x30, 0x39, 0x31, 0x39, 0x31, 0x39, 0x35, 0x34, 0x31, + 0x32, 0x5A, 0x30, 0x0F, 0x31, 0x0D, 0x30, 0x0B, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x0C, 0x04, 0x53, 0x4B, 0x49, 0x38, 0x30, 0x59, 0x30, 0x13, 0x06, + 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, + 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x22, 0x25, + 0x14, 0x25, 0x6B, 0x70, 0x38, 0xB3, 0x93, 0x5E, 0x18, 0x77, 0x58, 0x35, + 0xCE, 0x42, 0x4A, 0x95, 0xD4, 0xA5, 0xDD, 0x92, 0xB7, 0xC9, 0xEC, 0xF8, + 0xEB, 0x39, 0x5F, 0x44, 0xCB, 0x06, 0x69, 0xD3, 0xE0, 0x26, 0xAF, 0xC3, + 0xF3, 0xC0, 0x07, 0x40, 0xAC, 0x1C, 0x15, 0xEE, 0xBD, 0x5C, 0x15, 0x70, + 0x0A, 0x2A, 0x34, 0xB2, 0xF8, 0xCD, 0x34, 0xEC, 0xAB, 0x82, 0x82, 0x88, + 0x82, 0x81, 0xA3, 0x44, 0x30, 0x42, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, + 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xA7, 0xFC, 0xEC, 0x51, 0x8B, + 0xA3, 0x66, 0x18, 0x6C, 0xB2, 0xB4, 0x7C, 0x31, 0xF6, 0x7A, 0x22, 0x51, + 0xAB, 0x9D, 0xC4, 0x30, 0x11, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x0A, + 0x04, 0x08, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x30, 0x0C, + 0x06, 0x03, 0x55, 0x1D, 0x13, 0x01, 0x01, 0xFF, 0x04, 0x02, 0x30, 0x00, + 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, + 0x03, 0x48, 0x00, 0x30, 0x45, 0x02, 0x20, 0x66, 0x9B, 0x36, 0xE5, 0xA5, + 0x82, 0x34, 0x11, 0xE2, 0x62, 0x94, 0x5E, 0xAE, 0xD6, 0xAD, 0x4B, 0x73, + 0x2E, 0xD1, 0x09, 0x6C, 0x57, 0x76, 0xF7, 0xD6, 0xCC, 0xC0, 0x24, 0x05, + 0x74, 0xD9, 0x14, 0x02, 0x21, 0x00, 0xC3, 0xA8, 0x3B, 0xC6, 0x8D, 0x4D, + 0x58, 0xF0, 0x0B, 0x59, 0xDE, 0x8F, 0x53, 0x59, 0x8C, 0xA9, 0xC3, 0x2A, + 0x8F, 0x6D, 0x6C, 0x09, 0x25, 0xFB, 0x56, 0x1C, 0xBF, 0xD1, 0x35, 0x1B, + 0x8B, 0xC2, + }; + static const unsigned char skid[] = { + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 + }; + WOLFSSL_X509* x509 = NULL; + WOLFSSL_X509_EXTENSION* ext = NULL; + WOLFSSL_ASN1_STRING* str = NULL; + int idx = -1; + + ExpectNotNull(x509 = wolfSSL_X509_d2i(NULL, certDer, + (int)sizeof(certDer))); + ExpectIntGE(idx = wolfSSL_X509_get_ext_by_NID(x509, + NID_subject_key_identifier, -1), 0); + ExpectNotNull(ext = wolfSSL_X509_get_ext(x509, idx)); + ExpectNotNull(str = (WOLFSSL_ASN1_STRING*)wolfSSL_X509V3_EXT_d2i(ext)); + ExpectIntEQ(wolfSSL_ASN1_STRING_length(str), (int)sizeof(skid)); + ExpectBufEQ(wolfSSL_ASN1_STRING_get0_data(str), skid, sizeof(skid)); + + wolfSSL_ASN1_STRING_free(str); + wolfSSL_X509_free(x509); +#endif + return EXPECT_RESULT(); +} + int test_wolfSSL_X509V3_EXT_print(void) { EXPECT_DECLS; diff --git a/tests/api/test_ossl_x509_ext.h b/tests/api/test_ossl_x509_ext.h index a95b34a8050..5bb3ee93e3a 100644 --- a/tests/api/test_ossl_x509_ext.h +++ b/tests/api/test_ossl_x509_ext.h @@ -48,6 +48,7 @@ int test_wolfSSL_X509_get_ext_d2i_basic_constraints(void); int test_wolfSSL_X509V3_EXT_san(void); int test_wolfSSL_X509V3_EXT_aia(void); int test_wolfSSL_X509V3_EXT(void); +int test_wolfSSL_X509V3_EXT_d2i_skid(void); int test_wolfSSL_X509V3_EXT_print(void); int test_wolfSSL_X509_get_ext_d2i_name_constraints(void); int test_wolfSSL_sk_GENERAL_SUBTREE(void); @@ -89,6 +90,7 @@ int test_wolfSSL_X509_set_ext_oid_collision(void); TEST_DECL_GROUP("ossl_x509_ext", test_wolfSSL_X509V3_EXT_san), \ TEST_DECL_GROUP("ossl_x509_ext", test_wolfSSL_X509V3_EXT_aia), \ TEST_DECL_GROUP("ossl_x509_ext", test_wolfSSL_X509V3_EXT), \ + TEST_DECL_GROUP("ossl_x509_ext", test_wolfSSL_X509V3_EXT_d2i_skid), \ TEST_DECL_GROUP("ossl_x509_ext", test_wolfSSL_X509V3_EXT_print), \ TEST_DECL_GROUP("ossl_x509_ext", \ test_wolfSSL_X509_get_ext_d2i_name_constraints), \ diff --git a/tests/api/test_ossl_x509_name.c b/tests/api/test_ossl_x509_name.c index 3b21c0b2f69..5ddc7582dce 100644 --- a/tests/api/test_ossl_x509_name.c +++ b/tests/api/test_ossl_x509_name.c @@ -323,7 +323,8 @@ int test_wolfSSL_X509_NAME_hash(void) ExpectIntEQ(X509_NAME_hash(NULL), 0); ExpectNotNull(name = wolfSSL_X509_NAME_new_ex(NULL)); - ExpectIntEQ(X509_NAME_hash(name), 0); + /* SHA-1 of an empty encoding, as OpenSSL. */ + ExpectIntEQ(X509_NAME_hash(name), 0xeea339daUL); X509_NAME_free(name); ExpectNotNull(bio = BIO_new(BIO_s_file())); @@ -419,6 +420,7 @@ int test_wolfSSL_X509_NAME_print_ex(void) membio = NULL; X509_free(x509); + x509 = NULL; BIO_free(bio); name = NULL; @@ -929,6 +931,179 @@ int test_wolfSSL_X509_NAME_ENTRY(void) return EXPECT_RESULT(); } +#ifdef OPENSSL_ALL +/* Orders entries by the first byte of their value. */ +static int test_name_entry_cmp(const X509_NAME_ENTRY* const* a, + const X509_NAME_ENTRY* const* b) +{ + return (int)ASN1_STRING_get0_data( + X509_NAME_ENTRY_get_data((X509_NAME_ENTRY*)*a))[0] - + (int)ASN1_STRING_get0_data( + X509_NAME_ENTRY_get_data((X509_NAME_ENTRY*)*b))[0]; +} + +static int test_name_entry_cmp_rev(const X509_NAME_ENTRY* const* a, + const X509_NAME_ENTRY* const* b) +{ + return test_name_entry_cmp(b, a); +} +#endif + +int test_wolfSSL_sk_X509_NAME_ENTRY_sort(void) +{ + EXPECT_DECLS; +#ifdef OPENSSL_ALL + static const char* vals[] = { "c1", "a1", "d", "b", "a2", "c2" }; + static const char* sorted[] = { "a1", "a2", "b", "c1", "c2", "d" }; + X509_NAME_ENTRY* ents[6]; + STACK_OF(X509_NAME_ENTRY)* sk = NULL; + X509_NAME_ENTRY* e; + int i; + + XMEMSET(ents, 0, sizeof(ents)); + for (i = 0; i < 6; i++) { + ExpectNotNull(ents[i] = X509_NAME_ENTRY_create_by_txt(NULL, + "commonName", MBSTRING_UTF8, (const byte*)vals[i], + (int)XSTRLEN(vals[i]))); + } + + /* NULL stack, empty stack and no comparator. */ + sk_X509_NAME_ENTRY_sort(NULL); + ExpectTrue(sk_X509_NAME_ENTRY_set_cmp_func(NULL, test_name_entry_cmp) == + NULL); + ExpectNotNull(sk = sk_X509_NAME_ENTRY_new(NULL)); + sk_X509_NAME_ENTRY_sort(sk); + for (i = 0; i < 6; i++) { + ExpectIntGT(sk_X509_NAME_ENTRY_push(sk, ents[i]), 0); + } + sk_X509_NAME_ENTRY_sort(sk); + ExpectPtrEq(sk_X509_NAME_ENTRY_value(sk, 0), ents[0]); + ExpectPtrEq(sk_X509_NAME_ENTRY_value(sk, 5), ents[5]); + + /* Stable sort, equal entries keep their order. */ + ExpectTrue(sk_X509_NAME_ENTRY_set_cmp_func(sk, test_name_entry_cmp) == + NULL); + sk_X509_NAME_ENTRY_sort(sk); + ExpectIntEQ(sk_X509_NAME_ENTRY_num(sk), 6); + for (i = 0; i < 6; i++) { + ExpectNotNull(e = sk_X509_NAME_ENTRY_value(sk, i)); + ExpectIntEQ(XMEMCMP(ASN1_STRING_get0_data(X509_NAME_ENTRY_get_data(e)), + sorted[i], XSTRLEN(sorted[i])), 0); + } + ExpectTrue(sk_X509_NAME_ENTRY_set_cmp_func(sk, test_name_entry_cmp_rev) + == test_name_entry_cmp); + sk_X509_NAME_ENTRY_sort(sk); + ExpectPtrEq(sk_X509_NAME_ENTRY_value(sk, 0), ents[2]); + ExpectPtrEq(sk_X509_NAME_ENTRY_value(sk, 5), ents[4]); + + /* The comparator survives removing the first node. */ + ExpectPtrEq(wolfSSL_sk_delete(sk, 0), ents[2]); + ExpectIntGT(sk_X509_NAME_ENTRY_push(sk, ents[2]), 0); + sk_X509_NAME_ENTRY_sort(sk); + ExpectPtrEq(sk_X509_NAME_ENTRY_value(sk, 0), ents[2]); + sk_X509_NAME_ENTRY_free(sk); + sk = NULL; + + /* Comparator given to new(). */ + ExpectNotNull(sk = sk_X509_NAME_ENTRY_new(test_name_entry_cmp)); + for (i = 0; i < 6; i++) { + ExpectIntGT(sk_X509_NAME_ENTRY_push(sk, ents[5 - i]), 0); + } + sk_X509_NAME_ENTRY_sort(sk); + ExpectPtrEq(sk_X509_NAME_ENTRY_value(sk, 0), ents[4]); + ExpectPtrEq(sk_X509_NAME_ENTRY_value(sk, 5), ents[2]); + sk_X509_NAME_ENTRY_free(sk); + + for (i = 0; i < 6; i++) { + X509_NAME_ENTRY_free(ents[i]); + } +#endif + return EXPECT_RESULT(); +} + +int test_wolfSSL_X509_NAME_ENTRY_dup(void) +{ + EXPECT_DECLS; +#if defined(OPENSSL_EXTRA) && !defined(NO_FILESYSTEM) && !defined(NO_RSA) + X509* x509 = NULL; + X509_NAME* name = NULL; + X509_NAME_ENTRY* ne = NULL; + X509_NAME_ENTRY* dup = NULL; + STACK_OF(X509_NAME_ENTRY)* sk = NULL; + ASN1_STRING* val = NULL; + ASN1_STRING* dupVal = NULL; + int i; + int cnt = 0; + int nid = 0; + + ExpectNull(X509_NAME_ENTRY_dup(NULL)); + ExpectNotNull(x509 = wolfSSL_X509_load_certificate_file(cliCertFile, + WOLFSSL_FILETYPE_PEM)); + ExpectNotNull(name = X509_get_subject_name(x509)); + ExpectIntGT(cnt = X509_NAME_entry_count(name), 0); + + /* Copies of all entries, freed with the stack. */ + ExpectNotNull(sk = sk_X509_NAME_ENTRY_new(NULL)); + for (i = 0; i < cnt; i++) { + ExpectNotNull(ne = X509_NAME_get_entry(name, i)); + ExpectNotNull(dup = X509_NAME_ENTRY_dup(ne)); + ExpectTrue(dup != ne); + ExpectNotNull(val = X509_NAME_ENTRY_get_data(ne)); + ExpectNotNull(dupVal = X509_NAME_ENTRY_get_data(dup)); + ExpectTrue(val != dupVal); + ExpectIntEQ(ASN1_STRING_length(dupVal), ASN1_STRING_length(val)); + ExpectIntEQ(ASN1_STRING_type(dupVal), ASN1_STRING_type(val)); + ExpectIntEQ(XMEMCMP(ASN1_STRING_get0_data(dupVal), + ASN1_STRING_get0_data(val), (size_t)ASN1_STRING_length(val)), 0); + ExpectIntEQ(OBJ_cmp(X509_NAME_ENTRY_get_object(dup), + X509_NAME_ENTRY_get_object(ne)), 0); + ExpectIntEQ(OBJ_obj2nid(X509_NAME_ENTRY_get_object(dup)), + OBJ_obj2nid(X509_NAME_ENTRY_get_object(ne))); + if (EXPECT_SUCCESS() && (sk_X509_NAME_ENTRY_push(sk, dup) > 0)) { + dup = NULL; + } + X509_NAME_ENTRY_free(dup); + dup = NULL; + } + ExpectIntEQ(sk_X509_NAME_ENTRY_num(sk), cnt); + sk_X509_NAME_ENTRY_pop_free(sk, X509_NAME_ENTRY_free); + sk_X509_NAME_ENTRY_pop_free(NULL, X509_NAME_ENTRY_free); + + /* The copy outlives the original. */ + ExpectNotNull(ne = X509_NAME_get_entry(name, 0)); + nid = OBJ_obj2nid(X509_NAME_ENTRY_get_object(ne)); + ExpectNotNull(dup = X509_NAME_ENTRY_dup(ne)); + X509_free(x509); + ExpectNotNull(val = X509_NAME_ENTRY_get_data(dup)); + ExpectIntGT(ASN1_STRING_length(val), 0); + ExpectIntEQ(OBJ_obj2nid(X509_NAME_ENTRY_get_object(dup)), nid); + X509_NAME_ENTRY_free(dup); +#endif + return EXPECT_RESULT(); +} + +int test_wolfSSL_X509_NAME_ENTRY_octet_string(void) +{ + EXPECT_DECLS; +#if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) + X509_NAME_ENTRY* ne = NULL; + ASN1_STRING* val = NULL; + const unsigned char raw[] = { 0x04, 0x03, 0x00, 0xab, 0xcd }; + + /* Same value as OpenSSL. */ + ExpectIntEQ(B_ASN1_OCTET_STRING, 0x0200); + /* Not an MBSTRING_* type: the type is kept as given. */ + ExpectNotNull(ne = X509_NAME_ENTRY_create_by_txt(NULL, "CN", + B_ASN1_OCTET_STRING, raw, (int)sizeof(raw))); + ExpectNotNull(val = X509_NAME_ENTRY_get_data(ne)); + ExpectIntEQ(ASN1_STRING_type(val), B_ASN1_OCTET_STRING); + ExpectIntEQ(ASN1_STRING_length(val), (int)sizeof(raw)); + ExpectIntEQ(XMEMCMP(ASN1_STRING_get0_data(val), raw, sizeof(raw)), 0); + X509_NAME_ENTRY_free(ne); +#endif + return EXPECT_RESULT(); +} + int test_wolfSSL_X509_NAME_ENTRY_get_object(void) { EXPECT_DECLS; diff --git a/tests/api/test_ossl_x509_name.h b/tests/api/test_ossl_x509_name.h index 2e99c65ed88..632159c3dae 100644 --- a/tests/api/test_ossl_x509_name.h +++ b/tests/api/test_ossl_x509_name.h @@ -29,6 +29,9 @@ int test_wolfSSL_X509_NAME(void); int test_wolfSSL_X509_NAME_hash(void); int test_wolfSSL_X509_NAME_print_ex(void); int test_wolfSSL_X509_NAME_ENTRY(void); +int test_wolfSSL_sk_X509_NAME_ENTRY_sort(void); +int test_wolfSSL_X509_NAME_ENTRY_dup(void); +int test_wolfSSL_X509_NAME_ENTRY_octet_string(void); int test_wolfSSL_X509_NAME_ENTRY_get_object(void); int test_wolfSSL_X509_NAME_ENTRY_shared_object(void); @@ -38,6 +41,10 @@ int test_wolfSSL_X509_NAME_ENTRY_shared_object(void); TEST_DECL_GROUP("ossl_x509_name", test_wolfSSL_X509_NAME_hash), \ TEST_DECL_GROUP("ossl_x509_name", test_wolfSSL_X509_NAME_print_ex), \ TEST_DECL_GROUP("ossl_x509_name", test_wolfSSL_X509_NAME_ENTRY), \ + TEST_DECL_GROUP("ossl_x509_name", test_wolfSSL_sk_X509_NAME_ENTRY_sort), \ + TEST_DECL_GROUP("ossl_x509_name", test_wolfSSL_X509_NAME_ENTRY_dup), \ + TEST_DECL_GROUP("ossl_x509_name", \ + test_wolfSSL_X509_NAME_ENTRY_octet_string), \ TEST_DECL_GROUP("ossl_x509_name", \ test_wolfSSL_X509_NAME_ENTRY_get_object), \ TEST_DECL_GROUP("ossl_x509_name", \ diff --git a/tests/api/test_ossl_x509_pk.c b/tests/api/test_ossl_x509_pk.c index e4b7302d7c2..67aa042947a 100644 --- a/tests/api/test_ossl_x509_pk.c +++ b/tests/api/test_ossl_x509_pk.c @@ -328,6 +328,157 @@ int test_wolfSSL_X509_PUBKEY_get(void) return EXPECT_RESULT(); } +#if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && !defined(NO_FILESYSTEM) && \ + (!defined(NO_RSA) || defined(HAVE_ECC)) +static int test_X509_get0_pubkey_file(const char* file) +{ + EXPECT_DECLS; + X509* x509 = NULL; + X509* dup = NULL; + EVP_PKEY* key = NULL; + EVP_PKEY* pkey = NULL; + unsigned char* der = NULL; + unsigned char* der2 = NULL; + int derSz = 0; + + ExpectNotNull(x509 = wolfSSL_X509_load_certificate_file(file, + WOLFSSL_FILETYPE_PEM)); + /* The cert owns the key: the same key every time. */ + ExpectNotNull(key = X509_get0_pubkey(x509)); + ExpectPtrEq(X509_get0_pubkey(x509), key); + /* X509_get_pubkey returns a new reference for the caller to free. */ + ExpectNotNull(pkey = X509_get_pubkey(x509)); + ExpectPtrEq(pkey, key); + ExpectIntGT(derSz = i2d_PUBKEY(key, &der), 0); + ExpectIntEQ(i2d_PUBKEY(pkey, &der2), derSz); + ExpectBufEQ(der2, der, derSz); + XFREE(der2, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + der2 = NULL; + EVP_PKEY_free(pkey); + pkey = NULL; + ExpectPtrEq(X509_get0_pubkey(x509), key); + + /* A copy owns its own key. */ + ExpectNotNull(dup = X509_dup(x509)); + ExpectNotNull(pkey = X509_get0_pubkey(dup)); + ExpectPtrNE(pkey, key); + X509_free(x509); + x509 = NULL; + ExpectIntEQ(i2d_PUBKEY(pkey, &der2), derSz); + ExpectBufEQ(der2, der, derSz); + + XFREE(der2, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + XFREE(der, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + X509_free(dup); + return EXPECT_RESULT(); +} +#endif + +int test_wolfSSL_X509_get0_pubkey_files(void) +{ + EXPECT_DECLS; +#if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && !defined(NO_FILESYSTEM) +#if !defined(NO_RSA) && defined(HAVE_ECC) + X509* x509 = NULL; + X509* ecc = NULL; + EVP_PKEY* key = NULL; + EVP_PKEY* pkey = NULL; + unsigned char* der = NULL; + unsigned char* der2 = NULL; + int derSz = 0; +#endif + + ExpectNull(X509_get0_pubkey(NULL)); +#ifndef NO_RSA + ExpectIntEQ(test_X509_get0_pubkey_file(svrCertFile), TEST_SUCCESS); +#endif +#ifdef HAVE_ECC + ExpectIntEQ(test_X509_get0_pubkey_file(eccCertFile), TEST_SUCCESS); +#endif + +#if !defined(NO_RSA) && defined(HAVE_ECC) + /* Setting a new public key drops the old owned key. */ + ExpectNotNull(x509 = wolfSSL_X509_load_certificate_file(svrCertFile, + WOLFSSL_FILETYPE_PEM)); + ExpectNotNull(ecc = wolfSSL_X509_load_certificate_file(eccCertFile, + WOLFSSL_FILETYPE_PEM)); + ExpectNotNull(pkey = X509_get0_pubkey(x509)); + ExpectIntEQ(EVP_PKEY_base_id(pkey), EVP_PKEY_RSA); + ExpectNotNull(key = X509_get0_pubkey(ecc)); + ExpectIntEQ(X509_set_pubkey(x509, key), WOLFSSL_SUCCESS); + ExpectNotNull(pkey = X509_get0_pubkey(x509)); + ExpectIntEQ(EVP_PKEY_base_id(pkey), EVP_PKEY_EC); + ExpectIntGT(derSz = i2d_PUBKEY(key, &der), 0); + ExpectIntEQ(i2d_PUBKEY(pkey, &der2), derSz); + ExpectBufEQ(der2, der, derSz); + + XFREE(der2, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + XFREE(der, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + X509_free(ecc); + X509_free(x509); +#endif +#endif + return EXPECT_RESULT(); +} + +#if defined(OPENSSL_EXTRA) && defined(KEEP_PEER_CERT) && \ + defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && !defined(NO_RSA) +static EVP_PKEY* test_get0_pubkey_leaf = NULL; +static int test_get0_pubkey_leaf_bad = 0; + +/* Keep the leaf's key from the first call and check it on later calls. */ +static int test_get0_pubkey_verify_cb(int ok, X509_STORE_CTX* store) +{ + X509* cert = X509_STORE_CTX_get_current_cert(store); + + (void)ok; + if (X509_STORE_CTX_get_error_depth(store) == 0) { + if (test_get0_pubkey_leaf == NULL) { + test_get0_pubkey_leaf = X509_get0_pubkey(cert); + } + else if ((EVP_PKEY_bits(test_get0_pubkey_leaf) != 2048) || + (X509_get0_pubkey(cert) != test_get0_pubkey_leaf)) { + test_get0_pubkey_leaf_bad = 1; + } + } + return 1; +} +#endif + +/* The key of the leaf in the verify callback stays valid while the peer cert + * does, as in OpenSSL. */ +int test_wolfSSL_X509_get0_pubkey_peer(void) +{ + EXPECT_DECLS; +#if defined(OPENSSL_EXTRA) && defined(KEEP_PEER_CERT) && \ + defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && !defined(NO_RSA) + WOLFSSL_CTX* ctx_c = NULL; + WOLFSSL_CTX* ctx_s = NULL; + WOLFSSL* ssl_c = NULL; + WOLFSSL* ssl_s = NULL; + struct test_memio_ctx test_ctx; + + XMEMSET(&test_ctx, 0, sizeof(test_ctx)); + test_get0_pubkey_leaf = NULL; + test_get0_pubkey_leaf_bad = 0; + ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s, + wolfSSLv23_client_method, wolfSSLv23_server_method), 0); + /* The leaf is not trusted, so the callback is called on an error. */ + ExpectIntEQ(wolfSSL_CTX_UnloadCAs(ctx_c), WOLFSSL_SUCCESS); + wolfSSL_set_verify(ssl_c, WOLFSSL_VERIFY_PEER, test_get0_pubkey_verify_cb); + ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0); + ExpectNotNull(test_get0_pubkey_leaf); + ExpectIntEQ(test_get0_pubkey_leaf_bad, 0); + ExpectIntEQ(EVP_PKEY_bits(test_get0_pubkey_leaf), 2048); + + wolfSSL_free(ssl_s); + wolfSSL_free(ssl_c); + wolfSSL_CTX_free(ctx_s); + wolfSSL_CTX_free(ctx_c); +#endif + return EXPECT_RESULT(); +} + int test_wolfSSL_X509_set_pubkey(void) { EXPECT_DECLS; diff --git a/tests/api/test_ossl_x509_pk.h b/tests/api/test_ossl_x509_pk.h index c7afb032848..35dcb269120 100644 --- a/tests/api/test_ossl_x509_pk.h +++ b/tests/api/test_ossl_x509_pk.h @@ -30,6 +30,8 @@ int test_wolfSSL_X509_PUBKEY_EC(void); int test_wolfSSL_X509_PUBKEY_DSA(void); int test_wolfSSL_X509_PUBKEY_MLDSA(void); int test_wolfSSL_X509_PUBKEY_get(void); +int test_wolfSSL_X509_get0_pubkey_files(void); +int test_wolfSSL_X509_get0_pubkey_peer(void); int test_wolfSSL_X509_set_pubkey(void); int test_wolfSSL_X509_get0_pubkey(void); int test_wolfSSL_X509_get_pubkey_key_types(void); @@ -45,6 +47,8 @@ int test_wolfSSL_X509_PUBKEY_get0_param_fail(void); TEST_DECL_GROUP("ossl_x509_pk", test_wolfSSL_X509_PUBKEY_get), \ TEST_DECL_GROUP("ossl_x509_pk", test_wolfSSL_X509_set_pubkey), \ TEST_DECL_GROUP("ossl_x509_pk", test_wolfSSL_X509_get0_pubkey), \ + TEST_DECL_GROUP("ossl_x509_pk", test_wolfSSL_X509_get0_pubkey_files), \ + TEST_DECL_GROUP("ossl_x509_pk", test_wolfSSL_X509_get0_pubkey_peer), \ TEST_DECL_GROUP("ossl_x509_pk", test_wolfSSL_X509_get_pubkey_key_types), \ TEST_DECL_GROUP("ossl_x509_pk", test_wolfSSL_X509_get0_pubkey_threads), \ TEST_DECL_GROUP("ossl_x509_pk", test_wolfSSL_X509_PUBKEY_get0_param_fail) diff --git a/tests/api/test_ossl_x509_str.c b/tests/api/test_ossl_x509_str.c index 367f39a76f9..24798cc8b45 100644 --- a/tests/api/test_ossl_x509_str.c +++ b/tests/api/test_ossl_x509_str.c @@ -29,10 +29,12 @@ #endif #include +#include #ifdef OPENSSL_EXTRA #include #include #endif +#include #include #include @@ -87,10 +89,18 @@ int test_wolfSSL_X509_STORE_check_time(void) WOLFSSL_X509_STORE_CTX* ctx = NULL; WOLFSSL_X509* ca = NULL; WOLFSSL_X509* cert = NULL; +#ifdef HAVE_CRL + WOLF_STACK_OF(WOLFSSL_X509_CRL)* crls = NULL; + WOLFSSL_X509_CRL* crl = NULL; + XFILE fp = XBADFILE; +#endif int ret; time_t check_time; const char* srvCertFile = "./certs/server-cert.pem"; const char* expiredCertFile = "./certs/test/expired/expired-cert.pem"; + WOLFSSL_ASN1_TIME* epoch = NULL; + int day = 0; + int sec = 0; /* Set check_time to May 26, 2000 - should fail "not yet valid" check */ ExpectNotNull(store = wolfSSL_X509_STORE_new()); @@ -146,6 +156,26 @@ int test_wolfSSL_X509_STORE_check_time(void) WOLFSSL_SUCCESS); ret = wolfSSL_X509_verify_cert(ctx); ExpectIntEQ(ret, WOLFSSL_SUCCESS); + + /* As OpenSSL's X509_cmp_time(), the CA expires at its notAfter */ + ExpectNotNull(epoch = wolfSSL_ASN1_TIME_new()); + ExpectIntEQ(wolfSSL_ASN1_TIME_set_string(epoch, "19700101000000Z"), + WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_ASN1_TIME_diff(&day, &sec, epoch, + wolfSSL_X509_get_notAfter(ca)), WOLFSSL_SUCCESS); + check_time = (time_t)day * 86400 + sec; + ExpectIntEQ(wolfSSL_X509_STORE_CTX_init(ctx, store, cert, NULL), + WOLFSSL_SUCCESS); + wolfSSL_X509_STORE_CTX_set_time(ctx, 0, check_time - 1); + ExpectIntEQ(wolfSSL_X509_verify_cert(ctx), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_X509_STORE_CTX_init(ctx, store, cert, NULL), + WOLFSSL_SUCCESS); + wolfSSL_X509_STORE_CTX_set_time(ctx, 0, check_time); + ExpectIntNE(wolfSSL_X509_verify_cert(ctx), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_X509_STORE_CTX_get_error(ctx), + WOLFSSL_X509_V_ERR_CERT_HAS_EXPIRED); + ExpectIntEQ(wolfSSL_X509_STORE_CTX_get_error_depth(ctx), 1); + wolfSSL_ASN1_TIME_free(epoch); wolfSSL_X509_STORE_CTX_free(ctx); ctx = NULL; } @@ -156,7 +186,8 @@ int test_wolfSSL_X509_STORE_check_time(void) wolfSSL_X509_free(ca); ca = NULL; - /* A CRL flag must not make verification use check_time */ + /* A CRL flag must not make verification use check_time. As in OpenSSL, + * it turns on CRL checks: the CA's CRL does not list the cert. */ ExpectNotNull(store = wolfSSL_X509_STORE_new()); if (store != NULL) { ExpectNotNull(ca = wolfSSL_X509_load_certificate_file(caCertFile, @@ -173,10 +204,32 @@ int test_wolfSSL_X509_STORE_check_time(void) WOLFSSL_X509_V_FLAG_CRL_CHECK), WOLFSSL_SUCCESS); ExpectIntEQ(ctx->param->flags & WOLFSSL_USE_CHECK_TIME, 0); } +#ifdef HAVE_CRL + ExpectTrue((fp = XFOPEN("./certs/crl/crl.pem", "rb")) != XBADFILE); + ExpectNotNull(crl = wolfSSL_PEM_read_X509_CRL(fp, NULL, NULL, NULL)); + if (fp != XBADFILE) + XFCLOSE(fp); + ExpectNotNull(crls = wolfSSL_sk_X509_CRL_new_null()); + ExpectIntGT(wolfSSL_sk_X509_CRL_push(crls, crl), 0); + wolfSSL_X509_STORE_CTX_set0_crls(ctx, crls); +#endif ret = wolfSSL_X509_verify_cert(ctx); +#ifdef HAVE_CRL ExpectIntEQ(ret, WOLFSSL_SUCCESS); +#else + /* Without HAVE_CRL there is no CRL */ + ExpectIntNE(ret, WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_X509_STORE_CTX_get_error(ctx), + WOLFSSL_X509_V_ERR_UNABLE_TO_GET_CRL); +#endif wolfSSL_X509_STORE_CTX_free(ctx); ctx = NULL; +#ifdef HAVE_CRL + wolfSSL_sk_X509_CRL_free(crls); + crls = NULL; + wolfSSL_X509_CRL_free(crl); + crl = NULL; +#endif } wolfSSL_X509_STORE_free(store); store = NULL; @@ -207,6 +260,13 @@ int test_wolfSSL_X509_STORE_check_time(void) * because time validation is skipped */ ret = wolfSSL_X509_verify_cert(ctx); ExpectIntEQ(ret, WOLFSSL_SUCCESS); + + /* As OpenSSL, X509_V_FLAG_USE_CHECK_TIME wins, also with time 0, the + * current time in wolfSSL */ + ExpectIntEQ(wolfSSL_X509_STORE_CTX_init(ctx, store, cert, NULL), + WOLFSSL_SUCCESS); + wolfSSL_X509_STORE_CTX_set_time(ctx, 0, 0); + ExpectIntNE(wolfSSL_X509_verify_cert(ctx), WOLFSSL_SUCCESS); } wolfSSL_X509_STORE_CTX_free(ctx); ctx = NULL; @@ -388,7 +448,8 @@ int test_wolfSSL_X509_verify_cert_crl_date_override(void) #if defined(OPENSSL_EXTRA) && defined(HAVE_CRL) && !defined(NO_RSA) && \ !defined(NO_FILESYSTEM) && !defined(NO_ASN_TIME) && \ !defined(WOLFSSL_CRL_ALLOW_MISSING_CDP) -static int test_crl_date_cb_waive[2]; +/* The third verdict to waive is set by the test itself. */ +static int test_crl_date_cb_waive[3]; static int test_crl_date_cb_seen[4]; static int test_crl_date_cb_calls; #ifdef OPENSSL_ALL @@ -409,7 +470,8 @@ static int test_crl_date_verify_cb(int ok, X509_STORE_CTX* ctx) test_crl_date_cb_seen[test_crl_date_cb_calls] = err; test_crl_date_cb_calls++; return (err == test_crl_date_cb_waive[0]) || - (err == test_crl_date_cb_waive[1]); + (err == test_crl_date_cb_waive[1]) || + (err == test_crl_date_cb_waive[2]); } static int test_crl_date_verify(X509_STORE* store, X509* cert, int waive0, @@ -502,9 +564,12 @@ int test_wolfSSL_X509_verify_cert_crl_date_callback(void) const int noCrl = WOLFSSL_X509_V_ERR_UNABLE_TO_GET_CRL; const int notYet = WOLFSSL_X509_V_ERR_CERT_NOT_YET_VALID; const int revokedErr = WOLFSSL_X509_V_ERR_CERT_REVOKED; + const int crlNotYet = WOLFSSL_X509_V_ERR_CRL_NOT_YET_VALID; /* Waives no verdict the store reports. */ const int none = -1; + test_crl_date_cb_waive[2] = none; + ExpectNotNull(store = X509_STORE_new()); ExpectNotNull(ca = wolfSSL_X509_load_certificate_file( "./certs/ca-cert.pem", SSL_FILETYPE_PEM)); @@ -526,11 +591,12 @@ int test_wolfSSL_X509_verify_cert_crl_date_callback(void) ExpectIntEQ(test_crl_date_cb_calls, 1); #ifdef OPENSSL_ALL - /* A certificate that verified is passed to the callback once. */ + /* Each certificate that verified is passed to the callback once, the + * trust anchor included, as in OpenSSL. */ ExpectNotNull(plainStore = X509_STORE_new()); ExpectIntEQ(X509_STORE_add_cert(plainStore, ca), SSL_SUCCESS); ExpectIntEQ(test_crl_date_verify(plainStore, cert, none, none, &err), 1); - ExpectIntEQ(test_crl_date_cb_ok_calls, 1); + ExpectIntEQ(test_crl_date_cb_ok_calls, 2); ExpectIntEQ(test_crl_date_cb_calls, 0); /* A store callback can still reject it. */ if (plainStore != NULL) @@ -600,12 +666,13 @@ int test_wolfSSL_X509_verify_cert_crl_date_callback(void) sk_X509_CRL_pop_free(crls, X509_CRL_free); crls = NULL; - /* Waiving the date error still leaves the CRL verdict to reject. */ + /* As with the store callback, revocation is reported first, so + * the date error is what is left to reject. */ ExpectIntEQ(wc_SetTimeCb(test_crl_date_override_time_cb), 0); test_crl_date_cm_cb_waive = 1; test_crl_date_cm_cb_calls = 0; ExpectIntEQ(test_crl_date_verify(ctxStore, cert, 0, 0, &err), 0); - ExpectIntEQ(err, noCrl); + ExpectIntEQ(err, notYet); ExpectIntEQ(test_crl_date_cm_cb_calls, 2); wc_SetTimeCb(NULL); @@ -626,18 +693,21 @@ int test_wolfSSL_X509_verify_cert_crl_date_callback(void) ExpectIntEQ(test_crl_date_cb_seen[0], noCrl); ExpectIntEQ(test_crl_date_cb_seen[1], notYet); + /* As in OpenSSL, the dates of the trust anchor are checked too. */ ExpectIntEQ(test_crl_date_verify(store, cert, noCrl, notYet, &err), 1); ExpectIntEQ(err, notYet); - ExpectIntEQ(test_crl_date_cb_calls, 2); + ExpectIntEQ(test_crl_date_cb_calls, 3); #ifdef OPENSSL_ALL - /* The dates are still checked once a missing issuer is waived. */ + /* The dates are still checked once a missing issuer is waived. As in + * OpenSSL, the leaf signature that cannot be verified is reported too. */ ExpectNotNull(plainStore = X509_STORE_new()); ExpectIntEQ(test_crl_date_verify(plainStore, cert, - WOLFSSL_X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY, none, &err), 0); + WOLFSSL_X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY, + WOLFSSL_X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE, &err), 0); ExpectIntEQ(err, notYet); - ExpectIntEQ(test_crl_date_cb_calls, 2); - ExpectIntEQ(test_crl_date_cb_seen[1], notYet); + ExpectIntEQ(test_crl_date_cb_calls, 3); + ExpectIntEQ(test_crl_date_cb_seen[2], notYet); X509_STORE_free(plainStore); plainStore = NULL; #endif @@ -657,12 +727,17 @@ int test_wolfSSL_X509_verify_cert_crl_date_callback(void) XFCLOSE(fp); ExpectIntEQ(X509_STORE_add_crl(store, crl), SSL_SUCCESS); + /* As in OpenSSL, the CRL is not yet valid either, and that is reported + * first. */ + test_crl_date_cb_waive[2] = crlNotYet; ExpectIntEQ(test_crl_date_verify(store, revoked, revokedErr, notYet, &err), 1); ExpectIntEQ(err, notYet); - ExpectIntEQ(test_crl_date_cb_calls, 2); - ExpectIntEQ(test_crl_date_cb_seen[0], revokedErr); - ExpectIntEQ(test_crl_date_cb_seen[1], notYet); + ExpectIntEQ(test_crl_date_cb_calls, 4); + ExpectIntEQ(test_crl_date_cb_seen[0], crlNotYet); + ExpectIntEQ(test_crl_date_cb_seen[1], revokedErr); + ExpectIntEQ(test_crl_date_cb_seen[2], notYet); + ExpectIntEQ(test_crl_date_cb_seen[3], notYet); /* A CRL set on the context is consulted before the dates as well. */ ExpectTrue((fp = XFOPEN("./certs/crl/crl.revoked", "rb")) != XBADFILE); @@ -684,8 +759,10 @@ int test_wolfSSL_X509_verify_cert_crl_date_callback(void) test_crl_date_cb_calls = 0; ExpectIntNE(X509_verify_cert(storeCtx), SSL_SUCCESS); ExpectIntEQ(X509_STORE_CTX_get_error(storeCtx), revokedErr); - ExpectIntEQ(test_crl_date_cb_calls, 1); + ExpectIntEQ(test_crl_date_cb_calls, 2); + ExpectIntEQ(test_crl_date_cb_seen[0], crlNotYet); X509_STORE_CTX_free(storeCtx); + test_crl_date_cb_waive[2] = none; wc_SetTimeCb(NULL); @@ -737,6 +814,73 @@ static int verify_cb(int ok, X509_STORE_CTX *ctx) } #endif +#if defined(OPENSSL_EXTRA) && defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \ + !defined(NO_RSA) && !defined(NO_TLS) +static WOLFSSL* test_app_data_ssl; +static int test_app_data_calls; +static int test_app_data_bad; + +/* App data starts NULL and is apart from the SSL. */ +static int test_app_data_verify_cb(int ok, X509_STORE_CTX* ctx) +{ + static int data; + int idx = SSL_get_ex_data_X509_STORE_CTX_idx(); + + test_app_data_calls++; + if ((test_app_data_calls == 1) && + (X509_STORE_CTX_get_app_data(ctx) != NULL)) { + test_app_data_bad = 1; + } +#ifdef HAVE_EX_DATA + if ((X509_STORE_CTX_set_app_data(ctx, &data) != WOLFSSL_SUCCESS) || + (X509_STORE_CTX_get_app_data(ctx) != &data) || + (X509_STORE_CTX_get_ex_data(ctx, idx) != test_app_data_ssl)) { + test_app_data_bad = 1; + } +#else + (void)idx; + if ((X509_STORE_CTX_set_app_data(ctx, &data) != + WC_NO_ERR_TRACE(WOLFSSL_FAILURE)) || + (X509_STORE_CTX_get_app_data(ctx) != NULL)) { + test_app_data_bad = 1; + } +#endif + return ok; +} + +static int test_X509_STORE_CTX_app_data_tls(void) +{ + EXPECT_DECLS; + WOLFSSL_CTX* ctx_c = NULL; + WOLFSSL_CTX* ctx_s = NULL; + WOLFSSL* ssl_c = NULL; + WOLFSSL* ssl_s = NULL; + struct test_memio_ctx test_ctx; + + XMEMSET(&test_ctx, 0, sizeof(test_ctx)); +#ifndef WOLFSSL_NO_TLS12 + ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s, + wolfTLSv1_2_client_method, wolfTLSv1_2_server_method), 0); +#else + ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s, + wolfTLSv1_3_client_method, wolfTLSv1_3_server_method), 0); +#endif + test_app_data_ssl = ssl_c; + test_app_data_calls = 0; + test_app_data_bad = 0; + wolfSSL_set_verify(ssl_c, WOLFSSL_VERIFY_PEER, test_app_data_verify_cb); + ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0); + ExpectIntGT(test_app_data_calls, 0); + ExpectIntEQ(test_app_data_bad, 0); + + wolfSSL_free(ssl_s); + wolfSSL_free(ssl_c); + wolfSSL_CTX_free(ctx_s); + wolfSSL_CTX_free(ctx_c); + return EXPECT_RESULT(); +} +#endif + int test_wolfSSL_X509_STORE_CTX(void) { EXPECT_DECLS; @@ -841,6 +985,36 @@ int test_wolfSSL_X509_STORE_CTX(void) ctx = NULL; } + /* test X509_STORE_CTX_get/set_app_data */ + { + int tmpData = 7; + ExpectNotNull(ctx = X509_STORE_CTX_new()); + ExpectNull(X509_STORE_CTX_get_app_data(ctx)); + #ifdef HAVE_EX_DATA + ExpectIntEQ(X509_STORE_CTX_set_app_data(ctx, &tmpData), + WOLFSSL_SUCCESS); + ExpectPtrEq(X509_STORE_CTX_get_app_data(ctx), &tmpData); + ExpectNull(X509_STORE_CTX_get_ex_data(ctx, 0)); + /* init and cleanup clear it */ + ExpectIntEQ(X509_STORE_CTX_init(ctx, NULL, NULL, NULL), + WOLFSSL_SUCCESS); + ExpectNull(X509_STORE_CTX_get_app_data(ctx)); + ExpectIntEQ(X509_STORE_CTX_set_app_data(ctx, &tmpData), + WOLFSSL_SUCCESS); + X509_STORE_CTX_cleanup(ctx); + ExpectNull(X509_STORE_CTX_get_app_data(ctx)); + #else + ExpectIntEQ(X509_STORE_CTX_set_app_data(ctx, &tmpData), + WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); + ExpectNull(X509_STORE_CTX_get_app_data(ctx)); + #endif + X509_STORE_CTX_free(ctx); + ctx = NULL; + } +#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && !defined(NO_TLS) + ExpectIntEQ(test_X509_STORE_CTX_app_data_tls(), TEST_SUCCESS); +#endif + /* test X509_STORE_get/set_ex_data */ { int i = 0, tmpData = 99; @@ -906,6 +1080,7 @@ static int test_wolfSSL_X509_STORE_CTX_ex1(X509_STORE_test_data *testData) X509_STORE* store = NULL; X509_STORE_CTX* ctx = NULL; STACK_OF(X509)* chain = NULL; + STACK_OF(X509)* chain1 = NULL; int i = 0; /* Test case 1, add X509 certs to store and verify */ @@ -922,6 +1097,13 @@ static int test_wolfSSL_X509_STORE_CTX_ex1(X509_STORE_test_data *testData) ExpectIntEQ(X509_cmp(sk_X509_value(chain, i), sk_X509_value(testData->expectedChain, i)), 0); } + /* get1_chain references the same certs. */ + ExpectNotNull(chain1 = X509_STORE_CTX_get1_chain(ctx)); + ExpectIntEQ(sk_X509_num(chain1), sk_X509_num(chain)); + for (i = 0; i < sk_X509_num(chain1); i++) { + ExpectPtrEq(sk_X509_value(chain1, i), sk_X509_value(chain, i)); + } + sk_X509_pop_free(chain1, X509_free); X509_STORE_CTX_free(ctx); X509_STORE_free(store); return EXPECT_RESULT(); @@ -1194,6 +1376,9 @@ static int test_wolfSSL_X509_STORE_CTX_ex10(X509_STORE_test_data *testData) /* Fails because chain is incomplete */ ExpectIntNE(X509_verify_cert(ctx), 1); ExpectIntEQ(X509_STORE_set_flags(store, X509_V_FLAG_PARTIAL_CHAIN), 1); + /* As in OpenSSL, init takes the store's flags */ + ExpectIntNE(X509_verify_cert(ctx), 1); + ExpectIntEQ(X509_STORE_CTX_init(ctx, store, testData->x509Leaf, NULL), 1); /* Partial chain now OK */ ExpectIntEQ(X509_verify_cert(ctx), 1); ExpectNotNull(chain = X509_STORE_CTX_get_chain(ctx)); @@ -1374,21 +1559,17 @@ static int test_wolfSSL_X509_STORE_CTX_ex_partial_chain_cb_reject( STACK_OF(X509)* trusted = NULL; /* A per-context verify callback that rejects a certificate must not be - * overruled by the partial-chain terminus. The store trusts the root, so - * the intermediate the chain ends at verifies successfully - only the - * callback rejects it. The callback's veto is what makes - * X509StoreVerifyCert fail, and the WOLFSSL_PARTIAL_CHAIN fallback would - * then accept the chain at that same (caller-trusted) certificate and - * clear ctx->error, reporting X509_V_OK for a chain the application - * refused. */ + * overruled by the partial-chain terminus. The chain ends at the trusted + * intermediate, which verifies successfully - only the callback rejects + * it, when signalled success at its depth. A WOLFSSL_PARTIAL_CHAIN + * fallback must not accept the chain at that same (caller-trusted) + * certificate and clear ctx->error, reporting X509_V_OK for a chain the + * application refused. */ ExpectNotNull(store = X509_STORE_new()); ExpectIntEQ(X509_STORE_add_cert(store, testData->x509Ca), 1); /* Trust the two intermediates through the ctx override instead of the - * store, so the chain runs out of issuers at x509CaInt while the root - * that signed it is still a trusted CA in the CertManager. That is what - * makes the last X509StoreVerifyCert() succeed, leaving the callback as - * the only reason for the failure. */ + * store. */ ExpectNotNull(trusted = sk_X509_new_null()); ExpectIntGT(sk_X509_push(trusted, testData->x509CaInt2), 0); ExpectIntGT(sk_X509_push(trusted, testData->x509CaInt), 0); @@ -1397,8 +1578,10 @@ static int test_wolfSSL_X509_STORE_CTX_ex_partial_chain_cb_reject( ExpectIntEQ(X509_STORE_CTX_init(ctx, store, testData->x509Leaf, NULL), 1); X509_STORE_CTX_trusted_stack(ctx, trusted); X509_STORE_CTX_set_flags(ctx, X509_V_FLAG_PARTIAL_CHAIN); - /* After init, which clears any callback already on the context. */ - partialChainRejectCert = testData->x509CaInt; + /* After init, which clears any callback already on the context. + * With X509_V_FLAG_PARTIAL_CHAIN the chain ends at the first trusted + * cert, x509CaInt2, as in OpenSSL: x509CaInt is never seen. */ + partialChainRejectCert = testData->x509CaInt2; partialChainRejectSeen = 0; X509_STORE_CTX_set_verify_cb(ctx, partial_chain_reject_cb); @@ -2352,10 +2535,9 @@ static int test_untrusted_inter_depth_exhaustion(X509* leafDeep, X509* inter, ExpectIntEQ(X509_STORE_CTX_init(ctx, store, leafDeep, untrusted), 1); X509_STORE_CTX_set_depth(ctx, INT_MAX); ExpectIntEQ(X509_verify_cert(ctx), 1); - /* a positive depth written directly (no setter) is still honored */ + /* a positive depth set after init is honored */ ExpectIntEQ(X509_STORE_CTX_init(ctx, store, leafDeep, untrusted), 1); - if (ctx != NULL) - ctx->depth = 1; + X509_STORE_CTX_set_depth(ctx, 1); ExpectIntEQ(X509_verify_cert(ctx), 0); ExpectIntEQ(X509_STORE_CTX_get_error(ctx), X509_V_ERR_CERT_CHAIN_TOO_LONG); @@ -2463,7 +2645,12 @@ static int test_untrusted_inter_depth_trusted_stack(X509* leaf, X509* inter, X509_STORE_CTX_set_flags(ctx, X509_V_FLAG_PARTIAL_CHAIN); X509_STORE_CTX_set_depth(ctx, 0); ExpectIntEQ(X509_verify_cert(ctx), 1); - /* fresh ctx below: init does not clear the ctx-level flag */ + /* As in OpenSSL, init drops it */ + ExpectIntEQ(X509_STORE_CTX_init(ctx, store, leaf, NULL), 1); + X509_STORE_CTX_set_depth(ctx, 0); + ExpectIntEQ(X509_verify_cert(ctx), 0); + ExpectIntEQ(X509_STORE_CTX_get_error(ctx), + X509_V_ERR_CERT_CHAIN_TOO_LONG); X509_STORE_CTX_free(ctx); ctx = NULL; @@ -2586,12 +2773,10 @@ static int test_untrusted_inter_trusted_stack_cleanup(X509* leaf, X509* inter, } /* Trusted-stack counterpart of test_untrusted_inter_store_stack_unchanged: the - * caller's set0_trusted_stack must not be mutated - not even reordered - by the - * retry path. Put the tampered candidate ahead of root in the trusted stack so - * the verifier hits it first and takes X509VerifyCertSetupRetry (which moves - * failed candidates around on the internal copy), supply the genuine int-ca via - * the untrusted stack, then assert the trusted stack's exact contents and order - * after both a succeeding and a failing verification. */ + * caller's set0_trusted_stack must not be mutated - not even reordered - by + * X509_verify_cert(). Put the tampered candidate ahead of root in the trusted + * stack and the genuine int-ca in the untrusted stack, then assert the trusted + * stack's exact contents and order after each verification. */ static int test_untrusted_inter_trusted_stack_unchanged(X509* leaf, X509* inter, X509* tamperedInter, X509* root) { @@ -2603,18 +2788,19 @@ static int test_untrusted_inter_trusted_stack_unchanged(X509* leaf, X509* inter, ExpectNotNull(store = X509_STORE_new()); ExpectNotNull(trusted = sk_X509_new_null()); - /* Tampered candidate ahead of root forces the retry path over the trusted - * stack. */ + /* Tampered candidate ahead of root: it is found first. */ ExpectIntGT(sk_X509_push(trusted, tamperedInter), 0); ExpectIntGT(sk_X509_push(trusted, root), 0); - /* Succeeding verification: genuine int-ca arrives via the untrusted stack. */ + /* Genuine int-ca via the untrusted stack. The tampered cert is found + * first and is final: wolfSSL fails closed. OpenSSL rejects too, root did + * not sign it. */ ExpectNotNull(untrusted = sk_X509_new_null()); ExpectIntGT(sk_X509_push(untrusted, inter), 0); ExpectNotNull(ctx = X509_STORE_CTX_new()); ExpectIntEQ(X509_STORE_CTX_init(ctx, store, leaf, untrusted), 1); X509_STORE_CTX_trusted_stack(ctx, trusted); - ExpectIntEQ(X509_verify_cert(ctx), 1); + ExpectIntEQ(X509_verify_cert(ctx), 0); X509_STORE_CTX_free(ctx); ctx = NULL; @@ -2642,16 +2828,11 @@ static int test_untrusted_inter_trusted_stack_unchanged(X509* leaf, X509* inter, } /* One mixed-candidate verification: leaf with both the tampered intermediate - * (broken outer signature, same subject as int-ca) and the genuine int-ca in - * the untrusted stack, in the given push order. The chain must verify - the - * verifier tries the candidates and recovers via X509VerifyCertSetupRetry when - * it hits the tampered one first. Only the return value is asserted: when the - * tampered candidate is tried first wolfSSL intentionally preserves its error - * code even though the chain recovers (see the "worst-seen error must persist" - * behaviour exercised by test_X509_STORE_InvalidCa), so the error after success - * is order-dependent and not asserted here. */ + * (broken outer signature, same subject and key as int-ca) and the genuine + * int-ca in the untrusted stack, in the given push order. The first one is + * the issuer: the chain verifies as expected only with int-ca first. */ static int untrusted_inter_retry_one(X509_STORE* store, X509* leaf, - X509* first, X509* second) + X509* first, X509* second, int expected) { EXPECT_DECLS; X509_STORE_CTX* ctx = NULL; @@ -2662,21 +2843,18 @@ static int untrusted_inter_retry_one(X509_STORE* store, X509* leaf, ExpectIntGT(sk_X509_push(mixed, second), 0); ExpectNotNull(ctx = X509_STORE_CTX_new()); ExpectIntEQ(X509_STORE_CTX_init(ctx, store, leaf, mixed), 1); - ExpectIntEQ(X509_verify_cert(ctx), 1); + ExpectIntEQ(X509_verify_cert(ctx), expected); X509_STORE_CTX_free(ctx); sk_X509_free(mixed); return EXPECT_RESULT(); } -/* Retry path: when several caller-supplied candidates share a subject, the - * verifier tries one, fails, and retries with another - * (X509VerifyCertSetupRetry), moving entries through an internal "failed" list. - * Exercise BOTH push orderings so that, whichever order the verifier enumerates - * same-subject candidates, at least one ordering forces it to hit the tampered - * candidate first and recover. Then prove the store is left clean: a later +/* Same-subject candidates in the untrusted stack: the first issuer found is + * final, as in OpenSSL. With the tampered cert first the chain fails; with + * int-ca first it verifies. Then prove the store is left clean: a later * verification on the same store with only the tampered intermediate must fail * (no genuine int-ca left behind), and one with the genuine intermediate must - * still succeed. */ + * still succeed. The name is kept from when another candidate was tried. */ static int test_untrusted_inter_retry(X509* leaf, X509* inter, X509* tamperedInter, X509* root) { @@ -2689,13 +2867,16 @@ static int test_untrusted_inter_retry(X509* leaf, X509* inter, ExpectNotNull(store = X509_STORE_new()); ExpectIntEQ(X509_STORE_add_cert(store, root), 1); - /* Both orderings verify and report X509_V_OK. */ - ExpectIntEQ(untrusted_inter_retry_one(store, leaf, tamperedInter, inter), 1); - ExpectIntEQ(untrusted_inter_retry_one(store, leaf, inter, tamperedInter), 1); + /* The first issuer found is final: with the tampered cert first, + * wolfSSL fails closed. OpenSSL rejects too, root did not sign it. */ + ExpectIntEQ(untrusted_inter_retry_one(store, leaf, tamperedInter, inter, + 0), 1); + ExpectIntEQ(untrusted_inter_retry_one(store, leaf, inter, tamperedInter, + 1), 1); /* Reuse the SAME store with only the tampered intermediate: must fail. If - * a retry above left the genuine int-ca behind in the store, this would - * wrongly succeed. */ + * a verification above left the genuine int-ca behind in the store, this + * would wrongly succeed. */ ExpectNotNull(badOnly = sk_X509_new_null()); ExpectIntGT(sk_X509_push(badOnly, tamperedInter), 0); ExpectNotNull(ctx = X509_STORE_CTX_new()); @@ -2706,7 +2887,7 @@ static int test_untrusted_inter_retry(X509* leaf, X509* inter, ctx = NULL; /* Reuse the SAME store with the genuine intermediate: must still succeed, - * proving the retry left no stale state that breaks later verifications. */ + * proving the verifications above left no stale state. */ ExpectNotNull(goodOnly = sk_X509_new_null()); ExpectIntGT(sk_X509_push(goodOnly, inter), 0); ExpectNotNull(ctx = X509_STORE_CTX_new()); @@ -2722,10 +2903,8 @@ static int test_untrusted_inter_retry(X509* leaf, X509* inter, } /* A first-link signature failure must not leave the caller-supplied issuer - * loaded in the store's CertManager. X509_verify_cert() adds it as a - * WOLFSSL_TEMP_CA before checking the child; if the check fails the anchor has - * to go with it. The compat verifier drops TEMP_CAs before its own trust - * check, so residue is only visible through another user of the same + * loaded in the store's CertManager: X509_verify_cert() loads no temporary + * CAs. Residue would only be visible through another user of the same * CertManager - signer lookups there do not filter on type. */ static int test_untrusted_inter_no_temp_ca_residue(X509* leaf, X509* inter, X509* root) @@ -2775,15 +2954,12 @@ static int test_untrusted_inter_no_temp_ca_residue(X509* leaf, X509* inter, return EXPECT_RESULT(); } -/* Retry-path chain integrity: a tampered same-subject candidate tried and - * rejected before the genuine intermediate succeeds must not appear in the - * reported chain. Drive the retry path (tampered candidate ahead of the - * genuine one), then confirm X509_STORE_CTX_get0_chain() contains the genuine - * intermediate and never the rejected sibling. Certs are compared by content - * (X509_cmp) since the chain need not hold the caller's pointers. - * NOTE: this exercises the retry/failedCerts machinery via the untrusted - * stack. The terminal-anchor failedCerts guard is covered separately by - * test_untrusted_inter_terminal_anchor_rejected(). */ +/* Reported chain with the tampered sibling ahead of int-ca in the untrusted + * stack: the tampered cert is the leaf's issuer and is final, so the chain + * holds it and never int-ca, as in OpenSSL (leaf, tampered, root). Certs are + * compared by content (X509_cmp) since the chain need not hold the caller's + * pointers. The name is kept from when the sibling was rejected and int-ca + * tried. */ static int test_untrusted_inter_chain_excludes_rejected(X509* leaf, X509* inter, X509* tamperedInter, X509* root) { @@ -2799,16 +2975,16 @@ static int test_untrusted_inter_chain_excludes_rejected(X509* leaf, X509* inter, ExpectNotNull(store = X509_STORE_new()); ExpectIntEQ(X509_STORE_add_cert(store, root), 1); - /* Tampered candidate first forces the verifier to try and reject it, - * moving it into the internal failedCerts list, before recovering with the - * genuine intermediate. */ + /* Tampered candidate first. */ ExpectNotNull(mixed = sk_X509_new_null()); ExpectIntGT(sk_X509_push(mixed, tamperedInter), 0); ExpectIntGT(sk_X509_push(mixed, inter), 0); ExpectNotNull(ctx = X509_STORE_CTX_new()); ExpectIntEQ(X509_STORE_CTX_init(ctx, store, leaf, mixed), 1); - ExpectIntEQ(X509_verify_cert(ctx), 1); + /* The tampered cert is found first and is final: wolfSSL fails closed + * and the genuine int-ca is not tried. OpenSSL rejects too. */ + ExpectIntEQ(X509_verify_cert(ctx), 0); ExpectNotNull(chain = X509_STORE_CTX_get0_chain(ctx)); for (i = 0; i < sk_X509_num(chain); i++) { @@ -2818,8 +2994,8 @@ static int test_untrusted_inter_chain_excludes_rejected(X509* leaf, X509* inter, if (c != NULL && X509_cmp(c, tamperedInter) == 0) foundTampered = 1; } - ExpectIntEQ(foundInter, 1); - ExpectIntEQ(foundTampered, 0); + ExpectIntEQ(foundInter, 0); + ExpectIntEQ(foundTampered, 1); X509_STORE_CTX_free(ctx); X509_STORE_free(store); @@ -2828,17 +3004,12 @@ static int test_untrusted_inter_chain_excludes_rejected(X509* leaf, X509* inter, } #ifndef NO_TLS -/* Terminal-anchor variant of the above: drive the failedCerts guard on the - * issuer looked up after the CertManager verification succeeds. - * - * The anchors live in the CertManager (loaded from file) rather than on - * store->certs, so the terminal lookup consults set0_trusted_stack. That - * stack holds only the tampered intermediate, which is a same-subject sibling - * of the genuine one: the verifier tries it as the leaf's issuer, fails to - * verify it against the root, and moves it to failedCerts. The leaf then - * verifies directly against the CertManager copy of int-ca, and the terminal - * X509StoreGetIssuerEx() finds the tampered cert again by name+AKID. Without - * the guard it would be pushed onto the reported chain. */ +/* A trusted stack replaces the store's CAs, as in OpenSSL. root and int-ca + * are only in the CertManager (SSL_CTX_set_cert_store() moves store->certs + * there); the trusted stack holds only the tampered sibling of int-ca. It is + * the leaf's trusted issuer and nothing trusted issues it, so verification + * fails with UNABLE_TO_GET_ISSUER_CERT at depth 1 and the chain holds it. + * The name is kept from when the sibling was rejected. */ static int test_untrusted_inter_terminal_anchor_rejected(X509* leaf, X509* inter, X509* tamperedInter, X509* root) { @@ -2853,8 +3024,8 @@ static int test_untrusted_inter_terminal_anchor_rejected(X509* leaf, int storeOwned = 0; /* SSL_CTX_set_cert_store() pushes store->certs into the CertManager and - * detaches the stack, so int-ca becomes a CM anchor and the terminal - * lookup has to fall back to the caller's trusted stack. */ + * detaches the stack, so int-ca is only a CM CA, which the trusted stack + * replaces. */ #ifndef NO_WOLFSSL_SERVER ExpectNotNull(sslCtx = SSL_CTX_new(wolfSSLv23_server_method())); #else @@ -2875,7 +3046,12 @@ static int test_untrusted_inter_terminal_anchor_rejected(X509* leaf, ExpectIntEQ(X509_STORE_CTX_init(ctx, store, leaf, NULL), 1); X509_STORE_CTX_trusted_stack(ctx, trusted); - ExpectIntEQ(X509_verify_cert(ctx), 1); + /* As in OpenSSL, the trusted stack replaces the CAs of the store: the + * tampered cert is the only trusted issuer and root did not sign it. */ + ExpectIntEQ(X509_verify_cert(ctx), 0); + ExpectIntEQ(X509_STORE_CTX_get_error(ctx), + X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT); + ExpectIntEQ(X509_STORE_CTX_get_error_depth(ctx), 1); ExpectNotNull(chain = X509_STORE_CTX_get0_chain(ctx)); for (i = 0; i < sk_X509_num(chain); i++) { @@ -2883,7 +3059,7 @@ static int test_untrusted_inter_terminal_anchor_rejected(X509* leaf, if (c != NULL && X509_cmp(c, tamperedInter) == 0) foundTampered = 1; } - ExpectIntEQ(foundTampered, 0); + ExpectIntEQ(foundTampered, 1); X509_STORE_CTX_free(ctx); sk_X509_free(trusted); @@ -2896,12 +3072,9 @@ static int test_untrusted_inter_terminal_anchor_rejected(X509* leaf, #endif /* NO_TLS */ /* The store's cert stack is shared by every X509_STORE_CTX (and every SSL - * connection) using the store, so verification must not modify it. Chain - * building appends caller-supplied intermediates and moves failed retry - * candidates around on an internal copy only. Put a tampered candidate on - * store->certs ahead of the genuine one so the verifier takes the retry path - * (which used to reorder the stack), then assert the stack's exact contents - * and order after both a succeeding and a failing verification. */ + * connection) using the store, so verification must not modify it. Put a + * tampered candidate on store->certs ahead of inter2, then assert the stack's + * exact contents and order after each verification. */ static int test_untrusted_inter_store_stack_unchanged(X509* leaf, X509* inter, X509* tamperedInter, X509* inter2, X509* root) { @@ -2917,15 +3090,14 @@ static int test_untrusted_inter_store_stack_unchanged(X509* leaf, X509* inter, ExpectIntEQ(X509_STORE_add_cert(store, inter2), 1); ExpectIntEQ(sk_X509_num(store->certs), 2); - /* Succeeding verification: the tampered candidate is hit first and the - * genuine intermediate arrives via the untrusted stack, forcing a retry. - * Only the return value is asserted; the error code after a recovered - * retry is order-dependent (worst-seen error persists). */ + /* Genuine int-ca via the untrusted stack. The tampered cert of the store + * is found first and is final: wolfSSL fails closed. OpenSSL rejects + * too, root did not sign it. */ ExpectNotNull(untrusted = sk_X509_new_null()); ExpectIntGT(sk_X509_push(untrusted, inter), 0); ExpectNotNull(ctx = X509_STORE_CTX_new()); ExpectIntEQ(X509_STORE_CTX_init(ctx, store, leaf, untrusted), 1); - ExpectIntEQ(X509_verify_cert(ctx), 1); + ExpectIntEQ(X509_verify_cert(ctx), 0); X509_STORE_CTX_free(ctx); ctx = NULL; @@ -3078,336 +3250,1006 @@ int test_X509_verify_cert_untrusted_inter(void) return EXPECT_RESULT(); } -#if defined(OPENSSL_EXTRA) && !defined(NO_RSA) && !defined(NO_CERTS) && \ - defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_EXT) && \ - !defined(NO_SHA256) && defined(USE_CERT_BUFFERS_2048) && \ - !defined(NO_ASN_TIME) && !defined(ALLOW_INVALID_CERTSIGN) -/* Build a CA:TRUE certificate signed by the 2048-bit test root, or self-signed - * with subjKey when selfSigned is set (caKey may then be NULL). cn NULL copies - * the root's subject. keyUsage NULL omits the KeyUsage extension. */ -static int gen_ca_int_keyusage(byte* out, int outMax, RsaKey* subjKey, - RsaKey* caKey, WC_RNG* rng, const char* cn, const char* keyUsage, - int selfSigned) -{ - Cert cert; - - if (wc_InitCert(&cert) != 0) - return -1; - cert.isCA = 1; - cert.sigType = CTC_SHA256wRSA; - XSTRNCPY(cert.subject.country, "US", CTC_NAME_SIZE - 1); - XSTRNCPY(cert.subject.org, "wolfSSL_test", CTC_NAME_SIZE - 1); - if (cn != NULL) - XSTRNCPY(cert.subject.commonName, cn, CTC_NAME_SIZE - 1); - else if (wc_SetSubjectBuffer(&cert, ca_cert_der_2048, - (int)sizeof_ca_cert_der_2048) != 0) - return -1; - if (wc_SetSubjectKeyIdFromPublicKey(&cert, subjKey, NULL) != 0) - return -1; - if (!selfSigned && wc_SetAuthKeyIdFromCert(&cert, ca_cert_der_2048, - (int)sizeof_ca_cert_der_2048) != 0) - return -1; - if (keyUsage != NULL && wc_SetKeyUsage(&cert, keyUsage) != 0) - return -1; - /* A self-signed certificate names no issuer; the subject stands in. */ - if (!selfSigned && wc_SetIssuerBuffer(&cert, ca_cert_der_2048, - (int)sizeof_ca_cert_der_2048) != 0) - return -1; - if (wc_MakeCert(&cert, out, (word32)outMax, subjKey, NULL, rng) < 0) - return -1; - return wc_SignCert(cert.bodySz, cert.sigType, out, (word32)outMax, - selfSigned ? subjKey : caKey, NULL, rng); -} - -/* Build a leaf signed by the given intermediate (its DER + private key). */ -static int gen_leaf_under_int(byte* out, int outMax, RsaKey* leafKey, - const byte* issuerDer, int issuerDerSz, RsaKey* issuerKey, WC_RNG* rng, - const char* cn) -{ - Cert cert; - - if (wc_InitCert(&cert) != 0) - return -1; - cert.isCA = 0; - cert.sigType = CTC_SHA256wRSA; - XSTRNCPY(cert.subject.country, "US", CTC_NAME_SIZE - 1); - XSTRNCPY(cert.subject.org, "wolfSSL_test", CTC_NAME_SIZE - 1); - XSTRNCPY(cert.subject.commonName, cn, CTC_NAME_SIZE - 1); - if (wc_SetSubjectKeyIdFromPublicKey(&cert, leafKey, NULL) != 0) - return -1; - if (wc_SetAuthKeyIdFromCert(&cert, issuerDer, issuerDerSz) != 0) - return -1; - if (wc_SetKeyUsage(&cert, "digitalSignature") != 0) - return -1; - if (wc_SetIssuerBuffer(&cert, issuerDer, issuerDerSz) != 0) - return -1; - if (wc_MakeCert(&cert, out, (word32)outMax, leafKey, NULL, rng) < 0) - return -1; - return wc_SignCert(cert.bodySz, cert.sigType, out, (word32)outMax, - issuerKey, NULL, rng); -} - -/* Verify "leaf <- intermediate <- root(ca-cert)" where the intermediate is - * supplied only as an untrusted candidate. Returns the X509_verify_cert() - * result (1 verified, 0 rejected) via *verifyRet. */ -static int run_int_keyusage_case(const byte* intDer, int intSz, - const byte* leafDer, int leafSz, X509* root, int* verifyRet) +/* Depth from X509_VERIFY_PARAM, set as xmlsec does. leaf-deep <- int-ca2 <- + * int-ca <- root has two intermediates: depth 1 is too small, 2 is enough. */ +int test_wolfSSL_X509_VERIFY_PARAM_set_depth(void) { EXPECT_DECLS; +#if defined(OPENSSL_EXTRA) && !defined(NO_RSA) && !defined(NO_CERTS) && \ + !defined(NO_FILESYSTEM) + X509* leaf = NULL; X509* inter = NULL; - X509* leaf = NULL; + X509* inter2 = NULL; + X509* root = NULL; + STACK_OF(X509)* untrusted = NULL; X509_STORE* store = NULL; X509_STORE_CTX* ctx = NULL; - STACK_OF(X509)* untrusted = NULL; - const byte* p; + X509_VERIFY_PARAM* vpm = NULL; + X509_VERIFY_PARAM* vpm2 = NULL; +#if !defined(NO_TLS) && !defined(NO_WOLFSSL_CLIENT) + SSL_CTX* sslCtx = NULL; + SSL* ssl = NULL; +#endif - p = intDer; - ExpectNotNull(inter = d2i_X509(NULL, &p, intSz)); - p = leafDer; - ExpectNotNull(leaf = d2i_X509(NULL, &p, leafSz)); - ExpectNotNull(store = X509_STORE_new()); - ExpectIntEQ(X509_STORE_add_cert(store, root), 1); + ExpectNotNull(leaf = X509_load_certificate_file( + "./certs/intermediate/untrusted_anchor/leaf-deep-cert.pem", + SSL_FILETYPE_PEM)); + ExpectNotNull(inter = X509_load_certificate_file( + "./certs/intermediate/untrusted_anchor/int-ca-cert.pem", + SSL_FILETYPE_PEM)); + ExpectNotNull(inter2 = X509_load_certificate_file( + "./certs/intermediate/untrusted_anchor/int-ca2-cert.pem", + SSL_FILETYPE_PEM)); + ExpectNotNull(root = X509_load_certificate_file( + "./certs/intermediate/untrusted_anchor/root-ca-cert.pem", + SSL_FILETYPE_PEM)); ExpectNotNull(untrusted = sk_X509_new_null()); ExpectIntGT(sk_X509_push(untrusted, inter), 0); + ExpectIntGT(sk_X509_push(untrusted, inter2), 0); + ExpectNotNull(store = X509_STORE_new()); + ExpectIntEQ(X509_STORE_add_cert(store, root), 1); ExpectNotNull(ctx = X509_STORE_CTX_new()); + ExpectNotNull(vpm = X509_VERIFY_PARAM_new()); + + /* A param without a depth does not limit the chain */ + ExpectIntEQ(X509_STORE_CTX_init(ctx, store, leaf, untrusted), 1); + ExpectIntEQ(X509_verify_cert(ctx), 1); + ExpectIntEQ(X509_STORE_set1_param(store, vpm), 1); + /* A builtin leaves the depth unset. ssl_server fits the leaf's EKU. */ + ExpectIntEQ(X509_VERIFY_PARAM_set1(X509_STORE_get0_param(store), + X509_VERIFY_PARAM_lookup("ssl_server")), 1); +#if !defined(NO_TLS) && !defined(NO_WOLFSSL_CLIENT) + ExpectNotNull(sslCtx = SSL_CTX_new(wolfSSLv23_client_method())); + ExpectNotNull(ssl = SSL_new(sslCtx)); + ExpectIntEQ(X509_STORE_set1_param(store, SSL_CTX_get0_param(sslCtx)), 1); + ExpectIntEQ(X509_STORE_set1_param(store, SSL_get0_param(ssl)), 1); + ExpectIntEQ(X509_STORE_set1_param(store, + X509_STORE_get0_param(SSL_CTX_get_cert_store(sslCtx))), 1); +#endif + ExpectIntEQ(X509_STORE_CTX_init(ctx, store, leaf, untrusted), 1); + ExpectIntEQ(X509_verify_cert(ctx), 1); + + /* The context inherits the store depth */ + X509_VERIFY_PARAM_set_depth(vpm, 1); + ExpectIntEQ(X509_STORE_set1_param(store, vpm), 1); + ExpectIntEQ(X509_STORE_CTX_init(ctx, store, leaf, untrusted), 1); + ExpectIntEQ(X509_verify_cert(ctx), 0); + ExpectIntEQ(X509_STORE_CTX_get_error(ctx), X509_V_ERR_CERT_CHAIN_TOO_LONG); + X509_VERIFY_PARAM_set_depth(vpm, 2); + ExpectIntEQ(X509_STORE_set1_param(store, vpm), 1); ExpectIntEQ(X509_STORE_CTX_init(ctx, store, leaf, untrusted), 1); - if (verifyRet != NULL) - *verifyRet = X509_verify_cert(ctx); + ExpectIntEQ(X509_verify_cert(ctx), 1); + + /* set0_param() replaces the inherited param: depth 1 fails here */ + ExpectIntEQ(X509_STORE_CTX_init(ctx, store, leaf, untrusted), 1); + ExpectNotNull(vpm2 = X509_VERIFY_PARAM_new()); + X509_VERIFY_PARAM_set_depth(vpm2, 1); + X509_STORE_CTX_set0_param(ctx, vpm2); + vpm2 = NULL; + ExpectIntEQ(X509_verify_cert(ctx), 0); + ExpectIntEQ(X509_STORE_CTX_get_error(ctx), X509_V_ERR_CERT_CHAIN_TOO_LONG); + /* A negative depth rejects every chain. Only -1 is unset, so the store + * passes on -2, and -1 left in the context's param rejects too. */ + X509_VERIFY_PARAM_set_depth(vpm, -2); + ExpectIntEQ(X509_STORE_set1_param(store, vpm), 1); + ExpectIntEQ(X509_STORE_CTX_init(ctx, store, leaf, untrusted), 1); + ExpectIntEQ(X509_verify_cert(ctx), 0); + ExpectIntEQ(X509_STORE_CTX_get_error(ctx), X509_V_ERR_CERT_CHAIN_TOO_LONG); + ExpectIntEQ(X509_STORE_CTX_init(ctx, store, leaf, untrusted), 1); + X509_VERIFY_PARAM_set_depth(X509_STORE_CTX_get0_param(ctx), -1); + ExpectIntEQ(X509_verify_cert(ctx), 0); + ExpectIntEQ(X509_STORE_CTX_get_error(ctx), X509_V_ERR_CERT_CHAIN_TOO_LONG); + + /* With a store depth of 1, a later depth of 2 is honored */ + X509_VERIFY_PARAM_set_depth(vpm, 1); + ExpectIntEQ(X509_STORE_set1_param(store, vpm), 1); + ExpectIntEQ(X509_STORE_CTX_init(ctx, store, leaf, untrusted), 1); + ExpectNotNull(vpm2 = X509_VERIFY_PARAM_new()); + X509_VERIFY_PARAM_set_depth(vpm2, 2); + X509_STORE_CTX_set0_param(ctx, vpm2); + vpm2 = NULL; + ExpectIntEQ(X509_verify_cert(ctx), 1); + /* cleanup frees the param, the next init inherits depth 1 again */ + X509_STORE_CTX_cleanup(ctx); + ExpectIntEQ(X509_STORE_CTX_init(ctx, store, leaf, untrusted), 1); + ExpectIntEQ(X509_verify_cert(ctx), 0); + ExpectIntEQ(X509_STORE_CTX_get_error(ctx), X509_V_ERR_CERT_CHAIN_TOO_LONG); + ExpectIntEQ(X509_STORE_CTX_init(ctx, store, leaf, untrusted), 1); + X509_VERIFY_PARAM_set_depth(X509_STORE_CTX_get0_param(ctx), 2); + ExpectIntEQ(X509_verify_cert(ctx), 1); + ExpectIntEQ(X509_STORE_CTX_init(ctx, store, leaf, untrusted), 1); + X509_STORE_CTX_set_depth(ctx, 2); + ExpectIntEQ(X509_verify_cert(ctx), 1); + /* the last setter wins */ + ExpectIntEQ(X509_STORE_CTX_init(ctx, store, leaf, untrusted), 1); + X509_STORE_CTX_set_depth(ctx, 1); + X509_VERIFY_PARAM_set_depth(X509_STORE_CTX_get0_param(ctx), 2); + ExpectIntEQ(X509_verify_cert(ctx), 1); + + /* A param without a depth rejects every chain, as in OpenSSL. A second + * set0_param() frees the first, NULL or the current one keeps it and + * X509_STORE_CTX_free() frees the last. */ + ExpectIntEQ(X509_STORE_CTX_init(ctx, store, leaf, untrusted), 1); + ExpectNotNull(vpm2 = X509_VERIFY_PARAM_new()); + X509_STORE_CTX_set0_param(ctx, vpm2); + vpm2 = NULL; + ExpectIntEQ(X509_verify_cert(ctx), 0); + ExpectIntEQ(X509_STORE_CTX_get_error(ctx), X509_V_ERR_CERT_CHAIN_TOO_LONG); + ExpectIntEQ(X509_STORE_CTX_init(ctx, store, leaf, untrusted), 1); + ExpectNotNull(vpm2 = X509_VERIFY_PARAM_new()); + X509_VERIFY_PARAM_set_depth(vpm2, 2); + X509_STORE_CTX_set0_param(ctx, vpm2); + X509_STORE_CTX_set0_param(ctx, NULL); + X509_STORE_CTX_set0_param(ctx, vpm2); + X509_STORE_CTX_set0_param(NULL, NULL); + X509_VERIFY_PARAM_set_depth(NULL, 2); + ExpectPtrEq(X509_STORE_CTX_get0_param(ctx), vpm2); + ExpectIntEQ(X509_verify_cert(ctx), 1); + X509_STORE_CTX_free(ctx); + X509_VERIFY_PARAM_free(vpm); +#if !defined(NO_TLS) && !defined(NO_WOLFSSL_CLIENT) + SSL_free(ssl); + SSL_CTX_free(sslCtx); +#endif X509_STORE_free(store); sk_X509_free(untrusted); X509_free(leaf); X509_free(inter); + X509_free(inter2); + X509_free(root); +#endif /* OPENSSL_EXTRA && !NO_RSA && !NO_CERTS && !NO_FILESYSTEM */ return EXPECT_RESULT(); } -/* Verify leafDer with caDer trusted only through the context, so that path - * building can reach the anchor only as a temporary CA. Partial chains are - * allowed so an anchor that is not self-signed can end the path. */ -static int run_selfsigned_anchor_case(const byte* caDer, int caSz, - const byte* leafDer, int leafSz, int* verifyRet) +#if defined(OPENSSL_EXTRA) && !defined(NO_RSA) && !defined(NO_CERTS) && \ + !defined(NO_FILESYSTEM) +static int test_X509_verify_cert_accept_cb(int ok, X509_STORE_CTX* ctx) +{ + (void)ok; + (void)ctx; + return 1; +} +#endif + +/* An X509 made in memory has no DER. Failing closed, it is never an issuer, + * trusted or not, so every cert on the chain is checked. As in OpenSSL, the + * leaf then has no issuer. */ +int test_X509_verify_cert_no_der(void) { EXPECT_DECLS; - X509* ca = NULL; +#if defined(OPENSSL_EXTRA) && !defined(NO_RSA) && !defined(NO_CERTS) && \ + !defined(NO_FILESYSTEM) + X509* ca = NULL; + X509* inter = NULL; X509* leaf = NULL; + X509* leaf2 = NULL; + X509* fake = NULL; + X509* fakeInter = NULL; + STACK_OF(X509)* sk = NULL; + STACK_OF(X509)* untrusted = NULL; X509_STORE* store = NULL; X509_STORE_CTX* ctx = NULL; - STACK_OF(X509)* trusted = NULL; - const byte* p; +#ifdef HAVE_CRL + X509_CRL* crl = NULL; + XFILE fp = XBADFILE; +#endif - p = caDer; - ExpectNotNull(ca = d2i_X509(NULL, &p, caSz)); - p = leafDer; - ExpectNotNull(leaf = d2i_X509(NULL, &p, leafSz)); + ExpectNotNull(ca = X509_load_certificate_file("./certs/ca-cert.pem", + SSL_FILETYPE_PEM)); + ExpectNotNull(inter = X509_load_certificate_file( + "./certs/intermediate/ca-int-cert.pem", SSL_FILETYPE_PEM)); + ExpectNotNull(leaf = X509_load_certificate_file("./certs/server-cert.pem", + SSL_FILETYPE_PEM)); + ExpectNotNull(leaf2 = X509_load_certificate_file( + "./certs/intermediate/ca-int2-cert.pem", SSL_FILETYPE_PEM)); + /* The names and key of ca-cert and ca-int, without DER */ + ExpectNotNull(fake = X509_new()); + ExpectIntEQ(X509_set_subject_name(fake, X509_get_subject_name(ca)), 1); + ExpectIntEQ(X509_set_issuer_name(fake, X509_get_subject_name(ca)), 1); + ExpectIntEQ(X509_set_pubkey(fake, X509_get0_pubkey(ca)), 1); + ExpectNotNull(fakeInter = X509_new()); + ExpectIntEQ(X509_set_subject_name(fakeInter, + X509_get_subject_name(inter)), 1); + ExpectIntEQ(X509_set_issuer_name(fakeInter, + X509_get_issuer_name(inter)), 1); + ExpectIntEQ(X509_set_pubkey(fakeInter, X509_get0_pubkey(inter)), 1); + + /* A trusted stack cert with PARTIAL_CHAIN would end the chain */ + ExpectNotNull(sk = sk_X509_new_null()); + ExpectIntGT(sk_X509_push(sk, fake), 0); ExpectNotNull(store = X509_STORE_new()); ExpectNotNull(ctx = X509_STORE_CTX_new()); ExpectIntEQ(X509_STORE_CTX_init(ctx, store, leaf, NULL), 1); - ExpectNotNull(trusted = sk_X509_new_null()); - ExpectIntGT(sk_X509_push(trusted, ca), 0); - X509_STORE_CTX_trusted_stack(ctx, trusted); + X509_STORE_CTX_trusted_stack(ctx, sk); X509_STORE_CTX_set_flags(ctx, X509_V_FLAG_PARTIAL_CHAIN); - if (verifyRet != NULL) - *verifyRet = X509_verify_cert(ctx); + ExpectIntEQ(X509_verify_cert(ctx), 0); + ExpectIntEQ(X509_STORE_CTX_get_error(ctx), + X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY); + ExpectIntEQ(X509_STORE_CTX_get_error_depth(ctx), 0); + /* Nor is it verified: the error is not X509_V_OK */ + ExpectIntEQ(X509_STORE_CTX_init(ctx, store, fake, NULL), 1); + ExpectIntEQ(X509_verify_cert(ctx), WOLFSSL_FATAL_ERROR); + ExpectIntEQ(X509_STORE_CTX_get_error(ctx), X509_V_ERR_UNSPECIFIED); + + /* An untrusted one below a trusted root, every CRL checked. The + * callback accepts each error: 20, 3 and 21 at depth 0. */ + ExpectNotNull(untrusted = sk_X509_new_null()); + ExpectIntGT(sk_X509_push(untrusted, fakeInter), 0); + ExpectIntEQ(X509_STORE_add_cert(store, ca), 1); +#ifdef HAVE_CRL + ExpectTrue((fp = XFOPEN("./certs/crl/crl.pem", "rb")) != XBADFILE); + ExpectNotNull(crl = PEM_read_X509_CRL(fp, NULL, NULL, NULL)); + if (fp != XBADFILE) + XFCLOSE(fp); + ExpectIntEQ(X509_STORE_add_crl(store, crl), 1); +#endif + ExpectIntEQ(X509_STORE_CTX_init(ctx, store, leaf2, untrusted), 1); + X509_STORE_CTX_set_flags(ctx, X509_V_FLAG_CRL_CHECK | + X509_V_FLAG_CRL_CHECK_ALL); + X509_STORE_CTX_set_verify_cb(ctx, test_X509_verify_cert_accept_cb); + ExpectIntEQ(X509_verify_cert(ctx), 1); + ExpectIntEQ(X509_STORE_CTX_get_error(ctx), + X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE); + ExpectIntEQ(X509_STORE_CTX_get_error_depth(ctx), 0); + ExpectIntEQ(sk_X509_num(X509_STORE_CTX_get0_chain(ctx)), 1); + X509_STORE_CTX_free(ctx); X509_STORE_free(store); - sk_X509_free(trusted); - X509_free(leaf); +#ifdef HAVE_CRL + X509_CRL_free(crl); +#endif + sk_X509_free(sk); + sk_X509_free(untrusted); + X509_free(fake); + X509_free(fakeInter); X509_free(ca); + X509_free(inter); + X509_free(leaf); + X509_free(leaf2); +#endif return EXPECT_RESULT(); } -#endif -/* Regression: a chain-supplied (untrusted) intermediate that is CA:TRUE but - * whose KeyUsage extension does NOT assert keyCertSign must NOT be usable to - * sign the leaf - RFC 5280 4.2.1.3. Previously such an intermediate, added as - * a temporary CA during path building, was accepted as a signing CA. - * - * Conversely, an intermediate with NO KeyUsage extension implies all usages - * (including keyCertSign) and must still verify - the fix must not over-reject - * those. */ -int test_X509_verify_cert_ca_no_keycertsign(void) +#if defined(OPENSSL_EXTRA) && defined(HAVE_CRL) && !defined(NO_RSA) && \ + !defined(NO_CERTS) && !defined(NO_FILESYSTEM) && !defined(NO_ASN_TIME) +static int test_crl_time_accept; /* the callback accepts CRL date errors */ +static int test_crl_time_errs; /* CRL date errors the callback saw */ + +/* Accepts the date errors of certs, and of CRLs with test_crl_time_accept */ +static int test_crl_time_cb(int ok, X509_STORE_CTX* ctx) { - EXPECT_DECLS; -#if defined(OPENSSL_EXTRA) && !defined(NO_RSA) && !defined(NO_CERTS) && \ - defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_EXT) && \ - !defined(NO_SHA256) && defined(USE_CERT_BUFFERS_2048) && \ - !defined(NO_ASN_TIME) && !defined(ALLOW_INVALID_CERTSIGN) - /* ALLOW_INVALID_CERTSIGN disables the keyCertSign enforcement that Case 1 - * relies on, so the test is only meaningful when it is not defined. */ - WC_RNG rng; - RsaKey caKey, intKey, leafKey; - int rngI = 0, caI = 0, intI = 0, leafI = 0; - word32 idx; - byte* intDer = NULL; - byte* leafDer = NULL; - int intSz = 0, leafSz = 0; - int verifyRet = -1; - const byte* p; - X509* root = NULL; + int err = X509_STORE_CTX_get_error(ctx); - intDer = (byte*)XMALLOC(FOURK_BUF, NULL, DYNAMIC_TYPE_TMP_BUFFER); - leafDer = (byte*)XMALLOC(FOURK_BUF, NULL, DYNAMIC_TYPE_TMP_BUFFER); - ExpectNotNull(intDer); - ExpectNotNull(leafDer); + if (!ok && (err == X509_V_ERR_CRL_NOT_YET_VALID || + err == X509_V_ERR_CRL_HAS_EXPIRED)) { + test_crl_time_errs++; + return test_crl_time_accept; + } + return ok || err == X509_V_ERR_CERT_NOT_YET_VALID || + err == X509_V_ERR_CERT_HAS_EXPIRED; +} - ExpectIntEQ(wc_InitRng(&rng), 0); - if (EXPECT_SUCCESS()) rngI = 1; - ExpectIntEQ(wc_InitRsaKey(&caKey, NULL), 0); - if (EXPECT_SUCCESS()) caI = 1; - idx = 0; - ExpectIntEQ(wc_RsaPrivateKeyDecode(ca_key_der_2048, &idx, &caKey, - sizeof_ca_key_der_2048), 0); - ExpectIntEQ(wc_InitRsaKey(&intKey, NULL), 0); - if (EXPECT_SUCCESS()) intI = 1; - idx = 0; - ExpectIntEQ(wc_RsaPrivateKeyDecode(server_key_der_2048, &idx, &intKey, - sizeof_server_key_der_2048), 0); - ExpectIntEQ(wc_InitRsaKey(&leafKey, NULL), 0); - if (EXPECT_SUCCESS()) leafI = 1; - idx = 0; - ExpectIntEQ(wc_RsaPrivateKeyDecode(client_key_der_2048, &idx, &leafKey, - sizeof_client_key_der_2048), 0); +/* The time of asn1Time in *t */ +static int test_crl_time_get(const ASN1_TIME* asn1Time, time_t* t) +{ + ASN1_TIME* epoch = ASN1_TIME_adj(NULL, 0, 0, 0); + int day = 0; + int sec = 0; + int ret = epoch != NULL && + ASN1_TIME_diff(&day, &sec, epoch, asn1Time) == 1; + + *t = (time_t)day * 86400 + sec; + ASN1_TIME_free(epoch); + return ret; +} - p = ca_cert_der_2048; - ExpectNotNull(root = d2i_X509(NULL, &p, (int)sizeof_ca_cert_der_2048)); +/* X509_verify_cert() of leaf with the trusted ca and crl, of the store or, + * with toCtx, of the ctx, CRL_CHECK and flags on the ctx at time t. The error + * is put in *err. */ +static int test_crl_time_run(X509* ca, X509* leaf, X509_CRL* crl, int toCtx, + time_t t, unsigned long flags, int* err) +{ + X509_STORE* store = X509_STORE_new(); + X509_STORE_CTX* ctx = X509_STORE_CTX_new(); + STACK_OF(X509_CRL)* crls = sk_X509_CRL_new_null(); + int ret = -1; + + if (store != NULL && ctx != NULL && crls != NULL && + X509_STORE_add_cert(store, ca) == 1 && + (toCtx ? sk_X509_CRL_push(crls, crl) > 0 : + X509_STORE_add_crl(store, crl) == 1) && + X509_STORE_CTX_init(ctx, store, leaf, NULL) == 1) { + if (toCtx) + X509_STORE_CTX_set0_crls(ctx, crls); + X509_STORE_CTX_set_flags(ctx, X509_V_FLAG_CRL_CHECK | flags); + X509_STORE_CTX_set_time(ctx, 0, t); + X509_STORE_CTX_set_verify_cb(ctx, test_crl_time_cb); + test_crl_time_errs = 0; + ret = X509_verify_cert(ctx); + *err = X509_STORE_CTX_get_error(ctx); + } + X509_STORE_CTX_free(ctx); + X509_STORE_free(store); + sk_X509_CRL_free(crls); + return ret; +} +#endif - /* Case 1: intermediate CA WITHOUT keyCertSign -> verification must fail. */ - ExpectIntGT((intSz = gen_ca_int_keyusage(intDer, FOURK_BUF, &intKey, &caKey, - &rng, "No keyCertSign Intermediate", "digitalSignature", 0)), 0); - ExpectIntGT((leafSz = gen_leaf_under_int(leafDer, FOURK_BUF, &leafKey, - intDer, intSz, &intKey, &rng, "Leaf under bad int")), 0); - verifyRet = -1; - ExpectIntEQ(run_int_keyusage_case(intDer, intSz, leafDer, leafSz, root, - &verifyRet), 1); - ExpectIntNE(verifyRet, 1); +/* As OpenSSL's check_crl_time(), a CRL of the store or of the ctx is current + * from its thisUpdate to its nextUpdate at the verification time: else 11 or + * 12, once accepted the CRL is used. X509_V_FLAG_USE_CHECK_TIME wins over + * X509_V_FLAG_NO_CHECK_TIME. The times are taken from the CRL. */ +int test_X509_verify_cert_crl_time(void) +{ + EXPECT_DECLS; +#if defined(OPENSSL_EXTRA) && defined(HAVE_CRL) && !defined(NO_RSA) && \ + !defined(NO_CERTS) && !defined(NO_FILESYSTEM) && !defined(NO_ASN_TIME) + X509* ca = NULL; + X509* leaf = NULL; + X509* revoked = NULL; + X509_CRL* crl = NULL; + XFILE fp = XBADFILE; + time_t thisUpdate = 0; + time_t nextUpdate = 0; + int toCtx; + int err = 0; - /* Case 2: intermediate CA with NO KeyUsage extension -> must verify. */ - ExpectIntGT((intSz = gen_ca_int_keyusage(intDer, FOURK_BUF, &intKey, &caKey, - &rng, "No KeyUsage Intermediate", NULL, 0)), 0); - ExpectIntGT((leafSz = gen_leaf_under_int(leafDer, FOURK_BUF, &leafKey, - intDer, intSz, &intKey, &rng, "Leaf under noKU int")), 0); - verifyRet = -1; - ExpectIntEQ(run_int_keyusage_case(intDer, intSz, leafDer, leafSz, root, - &verifyRet), 1); - ExpectIntEQ(verifyRet, 1); + ExpectNotNull(ca = X509_load_certificate_file("./certs/ca-cert.pem", + SSL_FILETYPE_PEM)); + ExpectNotNull(leaf = X509_load_certificate_file("./certs/server-cert.pem", + SSL_FILETYPE_PEM)); + ExpectNotNull(revoked = X509_load_certificate_file( + "./certs/server-revoked-cert.pem", SSL_FILETYPE_PEM)); + ExpectTrue((fp = XFOPEN("./certs/crl/crl.pem", "rb")) != XBADFILE); + ExpectNotNull(crl = PEM_read_X509_CRL(fp, NULL, NULL, NULL)); + if (fp != XBADFILE) + XFCLOSE(fp); + ExpectIntEQ(test_crl_time_get(X509_CRL_get0_lastUpdate(crl), + &thisUpdate), 1); + ExpectIntEQ(test_crl_time_get(X509_CRL_get0_nextUpdate(crl), + &nextUpdate), 1); + ExpectTrue(thisUpdate + 1 < nextUpdate - 1); + + for (toCtx = 0; toCtx <= 1 && EXPECT_SUCCESS(); toCtx++) { + test_crl_time_accept = 0; + ExpectIntEQ(test_crl_time_run(ca, leaf, crl, toCtx, thisUpdate + 1, + 0, &err), 1); + ExpectIntEQ(test_crl_time_errs, 0); + ExpectIntEQ(test_crl_time_run(ca, leaf, crl, toCtx, nextUpdate - 1, + 0, &err), 1); + ExpectIntEQ(test_crl_time_errs, 0); + ExpectIntEQ(test_crl_time_run(ca, leaf, crl, toCtx, thisUpdate - 1, + 0, &err), 0); + ExpectIntEQ(err, X509_V_ERR_CRL_NOT_YET_VALID); + ExpectIntEQ(test_crl_time_run(ca, leaf, crl, toCtx, nextUpdate + 1, + 0, &err), 0); + ExpectIntEQ(err, X509_V_ERR_CRL_HAS_EXPIRED); + /* As OpenSSL's X509_cmp_time(), current at its thisUpdate, expired + * at its nextUpdate */ + ExpectIntEQ(test_crl_time_run(ca, leaf, crl, toCtx, thisUpdate, 0, + &err), 1); + ExpectIntEQ(test_crl_time_run(ca, leaf, crl, toCtx, nextUpdate, 0, + &err), 0); + ExpectIntEQ(err, X509_V_ERR_CRL_HAS_EXPIRED); + ExpectIntEQ(test_crl_time_run(ca, leaf, crl, toCtx, nextUpdate + 1, + X509_V_FLAG_NO_CHECK_TIME, &err), 0); + ExpectIntEQ(err, X509_V_ERR_CRL_HAS_EXPIRED); + + test_crl_time_accept = 1; + ExpectIntEQ(test_crl_time_run(ca, leaf, crl, toCtx, nextUpdate + 1, + 0, &err), 1); + ExpectIntEQ(test_crl_time_errs, 1); + ExpectIntEQ(test_crl_time_run(ca, revoked, crl, toCtx, + thisUpdate - 1, 0, &err), 0); + ExpectIntEQ(err, X509_V_ERR_CERT_REVOKED); + ExpectIntEQ(test_crl_time_errs, 1); + ExpectIntEQ(test_crl_time_run(ca, revoked, crl, toCtx, + nextUpdate + 1, 0, &err), 0); + ExpectIntEQ(err, X509_V_ERR_CERT_REVOKED); + ExpectIntEQ(test_crl_time_errs, 1); + } - X509_free(root); - if (rngI) wc_FreeRng(&rng); - if (caI) wc_FreeRsaKey(&caKey); - if (intI) wc_FreeRsaKey(&intKey); - if (leafI) wc_FreeRsaKey(&leafKey); - XFREE(intDer, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(leafDer, NULL, DYNAMIC_TYPE_TMP_BUFFER); + X509_CRL_free(crl); + X509_free(ca); + X509_free(leaf); + X509_free(revoked); #endif return EXPECT_RESULT(); } -/* A self-signed trust anchor stays usable when its KeyUsage extension omits - * keyCertSign. A self-issued key rollover certificate signed by the root is not - * self-signed, so it needs keyCertSign to act as a trust anchor. - * - * @return TEST_SUCCESS on success. - */ -int test_X509_verify_cert_selfsigned_anchor_no_keycertsign(void) +/* A CRL loaded after its CA is verified then and keeps no signature. As in + * OpenSSL, it is used for the certs of that CA: loaded with + * X509_STORE_load_locations(), X509_LOOKUP_load_file() or, into an SSL_CTX, + * wolfSSL_CTX_LoadCRLFile(). */ +int test_X509_verify_cert_crl_loaded(void) { EXPECT_DECLS; -#if defined(OPENSSL_EXTRA) && !defined(NO_RSA) && !defined(NO_CERTS) && \ - defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_EXT) && \ - !defined(NO_SHA256) && defined(USE_CERT_BUFFERS_2048) && \ - !defined(NO_ASN_TIME) && !defined(ALLOW_INVALID_CERTSIGN) - static const struct { - int selfSigned; /* else a rollover signed by the test root */ - const char* keyUsage; - int expectVerify; /* expected X509_verify_cert() result */ - } cases[] = { - { 1, "digitalSignature", 1 }, - { 0, "digitalSignature", 0 }, - { 0, "digitalSignature,keyCertSign", 1 }, - }; - WC_RNG rng; - RsaKey rootKey, caKey, leafKey; - int rngI = 0, rootI = 0, caI = 0, leafI = 0; - word32 idx; - byte* caDer = NULL; - byte* leafDer = NULL; - DecodedCert* dc = NULL; - int caSz = 0, leafSz = 0; - int verifyRet; - size_t i; - - caDer = (byte*)XMALLOC(FOURK_BUF, NULL, DYNAMIC_TYPE_TMP_BUFFER); - leafDer = (byte*)XMALLOC(FOURK_BUF, NULL, DYNAMIC_TYPE_TMP_BUFFER); - dc = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, - DYNAMIC_TYPE_DCERT); - ExpectNotNull(caDer); - ExpectNotNull(leafDer); - ExpectNotNull(dc); +#if defined(OPENSSL_EXTRA) && defined(HAVE_CRL) && !defined(NO_RSA) && \ + !defined(NO_CERTS) && !defined(NO_FILESYSTEM) && \ + !defined(NO_WOLFSSL_DIR) && defined(WOLFSSL_PEM_TO_DER) + const char* crlFile = "./certs/crl/crl.pem"; + X509* ca = NULL; + X509* leaf = NULL; + X509* revoked = NULL; + X509_STORE* store = NULL; + X509_STORE_CTX* ctx = NULL; +#if !defined(NO_TLS) && !defined(NO_WOLFSSL_CLIENT) + SSL_CTX* sslCtx = NULL; +#endif + int i; - ExpectIntEQ(wc_InitRng(&rng), 0); - if (EXPECT_SUCCESS()) rngI = 1; - ExpectIntEQ(wc_InitRsaKey(&rootKey, NULL), 0); - if (EXPECT_SUCCESS()) rootI = 1; - idx = 0; - ExpectIntEQ(wc_RsaPrivateKeyDecode(ca_key_der_2048, &idx, &rootKey, - sizeof_ca_key_der_2048), 0); - ExpectIntEQ(wc_InitRsaKey(&caKey, NULL), 0); - if (EXPECT_SUCCESS()) caI = 1; - idx = 0; - ExpectIntEQ(wc_RsaPrivateKeyDecode(server_key_der_2048, &idx, &caKey, - sizeof_server_key_der_2048), 0); - ExpectIntEQ(wc_InitRsaKey(&leafKey, NULL), 0); - if (EXPECT_SUCCESS()) leafI = 1; - idx = 0; - ExpectIntEQ(wc_RsaPrivateKeyDecode(client_key_der_2048, &idx, &leafKey, - sizeof_client_key_der_2048), 0); + ExpectNotNull(ca = X509_load_certificate_file("./certs/ca-cert.pem", + SSL_FILETYPE_PEM)); + ExpectNotNull(leaf = X509_load_certificate_file("./certs/server-cert.pem", + SSL_FILETYPE_PEM)); + ExpectNotNull(revoked = X509_load_certificate_file( + "./certs/server-revoked-cert.pem", SSL_FILETYPE_PEM)); + for (i = 0; i < 3 && EXPECT_SUCCESS(); i++) { + if (i < 2) { + ExpectNotNull(store = X509_STORE_new()); + ExpectIntEQ(X509_STORE_add_cert(store, ca), 1); + } + if (i == 0) { + ExpectIntEQ(X509_STORE_load_locations(store, crlFile, NULL), 1); + } + else if (i == 1) { + ExpectIntEQ(X509_LOOKUP_load_file(X509_STORE_add_lookup(store, + X509_LOOKUP_file()), crlFile, X509_FILETYPE_PEM), 1); + } + else { + /* A CA of an SSL_CTX goes on the chain only with its DER */ + #if !defined(NO_TLS) && !defined(NO_WOLFSSL_CLIENT) && \ + defined(WOLFSSL_SIGNER_DER_CERT) + ExpectNotNull(sslCtx = SSL_CTX_new(SSLv23_client_method())); + ExpectIntEQ(SSL_CTX_load_verify_locations(sslCtx, + "./certs/ca-cert.pem", NULL), 1); + ExpectIntEQ(wolfSSL_CTX_EnableCRL(sslCtx, 0), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_CTX_LoadCRLFile(sslCtx, crlFile, + WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); + ExpectNotNull(store = SSL_CTX_get_cert_store(sslCtx)); + #else + break; + #endif + } - for (i = 0; i < XELEM_CNT(cases) && EXPECT_SUCCESS(); i++) { - ExpectIntGT((caSz = gen_ca_int_keyusage(caDer, FOURK_BUF, &caKey, - &rootKey, &rng, cases[i].selfSigned ? "Self Signed Anchor" : NULL, - cases[i].keyUsage, cases[i].selfSigned)), 0); - /* A plain parse sets selfSigned only for the self-signed anchor. */ - wc_InitDecodedCert(dc, caDer, (word32)caSz, NULL); - ExpectIntEQ(wc_ParseCert(dc, CA_TYPE, NO_VERIFY, NULL), 0); - ExpectIntEQ(dc->selfIssued, 1); - ExpectIntEQ(dc->selfSigned, cases[i].selfSigned); - wc_FreeDecodedCert(dc); - ExpectIntGT((leafSz = gen_leaf_under_int(leafDer, FOURK_BUF, &leafKey, - caDer, caSz, &caKey, &rng, "Leaf under anchor")), 0); - verifyRet = -1; - ExpectIntEQ(run_selfsigned_anchor_case(caDer, caSz, leafDer, leafSz, - &verifyRet), 1); - ExpectIntEQ(verifyRet, cases[i].expectVerify); + ExpectNotNull(ctx = X509_STORE_CTX_new()); + ExpectIntEQ(X509_STORE_CTX_init(ctx, store, leaf, NULL), 1); + X509_STORE_CTX_set_flags(ctx, X509_V_FLAG_CRL_CHECK); + ExpectIntEQ(X509_verify_cert(ctx), 1); + ExpectIntEQ(X509_STORE_CTX_init(ctx, store, revoked, NULL), 1); + X509_STORE_CTX_set_flags(ctx, X509_V_FLAG_CRL_CHECK); + ExpectIntEQ(X509_verify_cert(ctx), 0); + ExpectIntEQ(X509_STORE_CTX_get_error(ctx), X509_V_ERR_CERT_REVOKED); + X509_STORE_CTX_free(ctx); + ctx = NULL; + #if !defined(NO_TLS) && !defined(NO_WOLFSSL_CLIENT) + if (sslCtx != NULL) { + SSL_CTX_free(sslCtx); + sslCtx = NULL; + store = NULL; + } + #endif + X509_STORE_free(store); + store = NULL; } - if (rngI) wc_FreeRng(&rng); - if (rootI) wc_FreeRsaKey(&rootKey); - if (caI) wc_FreeRsaKey(&caKey); - if (leafI) wc_FreeRsaKey(&leafKey); - XFREE(caDer, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(leafDer, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(dc, NULL, DYNAMIC_TYPE_DCERT); + X509_free(ca); + X509_free(leaf); + X509_free(revoked); #endif return EXPECT_RESULT(); } -#if defined(OPENSSL_EXTRA) && !defined(NO_RSA) && !defined(NO_CERTS) && \ - defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_EXT) && \ - !defined(NO_SHA256) && defined(USE_CERT_BUFFERS_2048) && \ - !defined(NO_ASN_TIME) -/* Build a certificate for key, signed with signKey, from bare common names. - * issuerCn NULL names the 2048-bit test root. skid and akid fill a key id with - * that byte, 0 omits the extension. */ -static X509* gen_named_cert(const char* subjCn, const char* issuerCn, int isCA, - byte skid, byte akid, RsaKey* key, RsaKey* signKey, WC_RNG* rng) +/* An intermediate CA of an SSL_CTX, without its issuer there, is the trust + * anchor. As TLS, the CRL check-all of the cert manager leaves it out, so the + * chain the handshake verified is returned. The leaf is still checked. + * X509_V_FLAG_CRL_CHECK_ALL checks the anchor: no CRL, as OpenSSL with + * X509_V_FLAG_PARTIAL_CHAIN. */ +int test_X509_verify_cert_crl_cm_anchor(void) { - Cert cert; - X509* x509 = NULL; - byte* der = NULL; - const byte* p; - int derSz = -1; - - if (wc_InitCert(&cert) != 0) - return NULL; + EXPECT_DECLS; +#if defined(OPENSSL_EXTRA) && defined(HAVE_CRL) && !defined(NO_RSA) && \ + !defined(NO_CERTS) && !defined(NO_FILESYSTEM) && !defined(NO_TLS) && \ + !defined(NO_WOLFSSL_CLIENT) && defined(WOLFSSL_PEM_TO_DER) && \ + defined(WOLFSSL_SIGNER_DER_CERT) + const char* caFile = "./certs/intermediate/ca-int2-cert.pem"; + const char* crlFile = "./certs/crl/ca-int2.pem"; + X509* leaf = NULL; + SSL_CTX* sslCtx = NULL; + X509_STORE_CTX* ctx = NULL; +#if defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) && \ + defined(WOLFSSL_ALT_CERT_CHAINS) && defined(SESSION_CERTS) && \ + defined(KEEP_PEER_CERT) + test_ssl_memio_ctx test_ctx; + STACK_OF(X509)* chain = NULL; +#endif + + ExpectNotNull(leaf = X509_load_certificate_file( + "./certs/intermediate/server-int-cert.pem", SSL_FILETYPE_PEM)); + ExpectNotNull(sslCtx = SSL_CTX_new(SSLv23_client_method())); + ExpectIntEQ(SSL_CTX_load_verify_locations(sslCtx, caFile, NULL), 1); + ExpectIntEQ(wolfSSL_CTX_EnableCRL(sslCtx, WOLFSSL_CRL_CHECKALL), + WOLFSSL_SUCCESS); + ExpectNotNull(ctx = X509_STORE_CTX_new()); + ExpectIntEQ(X509_STORE_CTX_init(ctx, SSL_CTX_get_cert_store(sslCtx), leaf, + NULL), 1); + ExpectIntEQ(X509_verify_cert(ctx), 0); + ExpectIntEQ(X509_STORE_CTX_get_error(ctx), X509_V_ERR_UNABLE_TO_GET_CRL); + ExpectIntEQ(X509_STORE_CTX_get_error_depth(ctx), 0); + ExpectIntEQ(wolfSSL_CTX_LoadCRLFile(sslCtx, crlFile, + WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); + ExpectIntEQ(X509_STORE_CTX_init(ctx, SSL_CTX_get_cert_store(sslCtx), leaf, + NULL), 1); + ExpectIntEQ(X509_verify_cert(ctx), 1); + ExpectIntEQ(sk_X509_num(X509_STORE_CTX_get0_chain(ctx)), 2); + ExpectIntEQ(X509_STORE_CTX_init(ctx, SSL_CTX_get_cert_store(sslCtx), leaf, + NULL), 1); + X509_STORE_CTX_set_flags(ctx, X509_V_FLAG_CRL_CHECK | + X509_V_FLAG_CRL_CHECK_ALL); + ExpectIntEQ(X509_verify_cert(ctx), 0); + ExpectIntEQ(X509_STORE_CTX_get_error(ctx), X509_V_ERR_UNABLE_TO_GET_CRL); + ExpectIntEQ(X509_STORE_CTX_get_error_depth(ctx), 1); + X509_STORE_CTX_free(ctx); + SSL_CTX_free(sslCtx); + X509_free(leaf); + +#if defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) && \ + defined(WOLFSSL_ALT_CERT_CHAINS) && defined(SESSION_CERTS) && \ + defined(KEEP_PEER_CERT) + /* The server sends the anchor too: only then does TLS leave it out */ + XMEMSET(&test_ctx, 0, sizeof(test_ctx)); + test_ctx.c_cb.caPemFile = caFile; + test_ctx.c_cb.crlPemFile = crlFile; + test_ctx.s_cb.certPemFile = "./certs/intermediate/server-chain-short.pem"; + test_ctx.s_cb.keyPemFile = "./certs/server-key.pem"; + ExpectIntEQ(test_ssl_memio_setup(&test_ctx), TEST_SUCCESS); + ExpectIntEQ(test_ssl_memio_do_handshake(&test_ctx, 10, NULL), + TEST_SUCCESS); + ExpectNotNull(chain = SSL_get0_verified_chain(test_ctx.c_ssl)); + ExpectIntEQ(sk_X509_num(chain), 2); + test_ssl_memio_cleanup(&test_ctx); +#endif +#endif + return EXPECT_RESULT(); +} + +#if defined(OPENSSL_EXTRA) && !defined(NO_RSA) && !defined(NO_CERTS) && \ + !defined(NO_FILESYSTEM) +static int test_internal_err_calls; /* calls of the verify callback */ + +static int test_internal_err_cb(int ok, X509_STORE_CTX* ctx) +{ + (void)ok; + (void)ctx; + test_internal_err_calls++; + return 1; +} + +/* Verifies leaf with the CA of store and returns X509_verify_cert() */ +static int test_internal_err_run(X509_STORE* store, X509* leaf, int* err) +{ + EXPECT_DECLS; + X509_STORE_CTX* ctx = NULL; + int ret = -1; + + test_internal_err_calls = 0; + ExpectNotNull(ctx = X509_STORE_CTX_new()); + ExpectIntEQ(X509_STORE_CTX_init(ctx, store, leaf, NULL), 1); + X509_STORE_CTX_set_verify_cb(ctx, test_internal_err_cb); + if (EXPECT_SUCCESS()) { + ret = X509_verify_cert(ctx); + *err = X509_STORE_CTX_get_error(ctx); + } + X509_STORE_CTX_free(ctx); + return ret; +} +#endif + +/* An internal error fails the verification with X509_V_ERR_UNSPECIFIED and + * the verify callback is not asked. The DER of the leaf is broken after it + * decoded, so checking its signature fails to parse it, with a cert of the + * store and with a CA of an SSL_CTX. */ +int test_X509_verify_cert_internal_err(void) +{ + EXPECT_DECLS; +#if defined(OPENSSL_EXTRA) && !defined(NO_RSA) && !defined(NO_CERTS) && \ + !defined(NO_FILESYSTEM) + X509* ca = NULL; + X509* leaf = NULL; + X509_STORE* store = NULL; +#if !defined(NO_TLS) && !defined(NO_WOLFSSL_CLIENT) + SSL_CTX* sslCtx = NULL; +#endif + int err = 0; + + ExpectNotNull(ca = X509_load_certificate_file("./certs/ca-cert.pem", + SSL_FILETYPE_PEM)); + ExpectNotNull(leaf = X509_load_certificate_file("./certs/server-cert.pem", + SSL_FILETYPE_PEM)); + ExpectNotNull(store = X509_STORE_new()); + ExpectIntEQ(X509_STORE_add_cert(store, ca), 1); + ExpectIntEQ(test_internal_err_run(store, leaf, &err), 1); + ExpectIntEQ(err, X509_V_OK); + ExpectIntEQ(test_internal_err_calls, 2); + + /* The outer SEQUENCE of the leaf becomes a SET */ + ExpectTrue(leaf != NULL && leaf->derCert != NULL && + leaf->derCert->buffer[0] == (ASN_SEQUENCE | ASN_CONSTRUCTED)); + if (EXPECT_SUCCESS()) { + leaf->derCert->buffer[0] = ASN_SET | ASN_CONSTRUCTED; + } + ExpectIntEQ(test_internal_err_run(store, leaf, &err), 0); + ExpectIntEQ(err, X509_V_ERR_UNSPECIFIED); + ExpectIntEQ(test_internal_err_calls, 0); +#if !defined(NO_TLS) && !defined(NO_WOLFSSL_CLIENT) + ExpectNotNull(sslCtx = SSL_CTX_new(SSLv23_client_method())); + ExpectIntEQ(SSL_CTX_load_verify_locations(sslCtx, "./certs/ca-cert.pem", + NULL), 1); + ExpectIntEQ(test_internal_err_run(SSL_CTX_get_cert_store(sslCtx), leaf, + &err), 0); + ExpectIntEQ(err, X509_V_ERR_UNSPECIFIED); + ExpectIntEQ(test_internal_err_calls, 0); +#endif + if (EXPECT_SUCCESS()) { + leaf->derCert->buffer[0] = ASN_SEQUENCE | ASN_CONSTRUCTED; + } + +#if !defined(NO_TLS) && !defined(NO_WOLFSSL_CLIENT) + SSL_CTX_free(sslCtx); +#endif + X509_STORE_free(store); + X509_free(ca); + X509_free(leaf); +#endif + return EXPECT_RESULT(); +} + +#if defined(OPENSSL_EXTRA) && !defined(NO_RSA) && !defined(NO_CERTS) && \ + defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_EXT) && \ + !defined(NO_SHA256) && defined(USE_CERT_BUFFERS_2048) && \ + !defined(NO_ASN_TIME) && !defined(ALLOW_INVALID_CERTSIGN) +/* Build a CA:TRUE certificate signed by the 2048-bit test root, or self-signed + * with subjKey when selfSigned is set (caKey may then be NULL). cn NULL copies + * the root's subject. keyUsage NULL omits the KeyUsage extension. */ +static int gen_ca_int_keyusage(byte* out, int outMax, RsaKey* subjKey, + RsaKey* caKey, WC_RNG* rng, const char* cn, const char* keyUsage, + int selfSigned) +{ + Cert cert; + + if (wc_InitCert(&cert) != 0) + return -1; + cert.isCA = 1; + cert.sigType = CTC_SHA256wRSA; + XSTRNCPY(cert.subject.country, "US", CTC_NAME_SIZE - 1); + XSTRNCPY(cert.subject.org, "wolfSSL_test", CTC_NAME_SIZE - 1); + if (cn != NULL) + XSTRNCPY(cert.subject.commonName, cn, CTC_NAME_SIZE - 1); + else if (wc_SetSubjectBuffer(&cert, ca_cert_der_2048, + (int)sizeof_ca_cert_der_2048) != 0) + return -1; + if (wc_SetSubjectKeyIdFromPublicKey(&cert, subjKey, NULL) != 0) + return -1; + if (!selfSigned && wc_SetAuthKeyIdFromCert(&cert, ca_cert_der_2048, + (int)sizeof_ca_cert_der_2048) != 0) + return -1; + if (keyUsage != NULL && wc_SetKeyUsage(&cert, keyUsage) != 0) + return -1; + /* A self-signed certificate names no issuer; the subject stands in. */ + if (!selfSigned && wc_SetIssuerBuffer(&cert, ca_cert_der_2048, + (int)sizeof_ca_cert_der_2048) != 0) + return -1; + if (wc_MakeCert(&cert, out, (word32)outMax, subjKey, NULL, rng) < 0) + return -1; + return wc_SignCert(cert.bodySz, cert.sigType, out, (word32)outMax, + selfSigned ? subjKey : caKey, NULL, rng); +} + +/* Build a leaf signed by the given intermediate (its DER + private key). */ +static int gen_leaf_under_int(byte* out, int outMax, RsaKey* leafKey, + const byte* issuerDer, int issuerDerSz, RsaKey* issuerKey, WC_RNG* rng, + const char* cn) +{ + Cert cert; + + if (wc_InitCert(&cert) != 0) + return -1; + cert.isCA = 0; + cert.sigType = CTC_SHA256wRSA; + XSTRNCPY(cert.subject.country, "US", CTC_NAME_SIZE - 1); + XSTRNCPY(cert.subject.org, "wolfSSL_test", CTC_NAME_SIZE - 1); + XSTRNCPY(cert.subject.commonName, cn, CTC_NAME_SIZE - 1); + if (wc_SetSubjectKeyIdFromPublicKey(&cert, leafKey, NULL) != 0) + return -1; + if (wc_SetAuthKeyIdFromCert(&cert, issuerDer, issuerDerSz) != 0) + return -1; + if (wc_SetKeyUsage(&cert, "digitalSignature") != 0) + return -1; + if (wc_SetIssuerBuffer(&cert, issuerDer, issuerDerSz) != 0) + return -1; + if (wc_MakeCert(&cert, out, (word32)outMax, leafKey, NULL, rng) < 0) + return -1; + return wc_SignCert(cert.bodySz, cert.sigType, out, (word32)outMax, + issuerKey, NULL, rng); +} + +/* Verify "leaf <- intermediate <- root(ca-cert)" where the intermediate is + * supplied only as an untrusted candidate. Returns the X509_verify_cert() + * result (1 verified, 0 rejected) via *verifyRet, and the error and its depth + * via *verifyErr and *verifyDepth. */ +static int run_int_keyusage_case(const byte* intDer, int intSz, + const byte* leafDer, int leafSz, X509* root, int* verifyRet, + int* verifyErr, int* verifyDepth) +{ + EXPECT_DECLS; + X509* inter = NULL; + X509* leaf = NULL; + X509_STORE* store = NULL; + X509_STORE_CTX* ctx = NULL; + STACK_OF(X509)* untrusted = NULL; + const byte* p; + + p = intDer; + ExpectNotNull(inter = d2i_X509(NULL, &p, intSz)); + p = leafDer; + ExpectNotNull(leaf = d2i_X509(NULL, &p, leafSz)); + ExpectNotNull(store = X509_STORE_new()); + ExpectIntEQ(X509_STORE_add_cert(store, root), 1); + ExpectNotNull(untrusted = sk_X509_new_null()); + ExpectIntGT(sk_X509_push(untrusted, inter), 0); + ExpectNotNull(ctx = X509_STORE_CTX_new()); + ExpectIntEQ(X509_STORE_CTX_init(ctx, store, leaf, untrusted), 1); + *verifyRet = X509_verify_cert(ctx); + *verifyErr = X509_STORE_CTX_get_error(ctx); + *verifyDepth = X509_STORE_CTX_get_error_depth(ctx); + X509_STORE_CTX_free(ctx); + X509_STORE_free(store); + sk_X509_free(untrusted); + X509_free(leaf); + X509_free(inter); + return EXPECT_RESULT(); +} + +/* Verify leafDer with caDer trusted only through the context, so that path + * building can reach the anchor only as a temporary CA. Partial chains are + * allowed so an anchor that is not self-signed can end the path. Returns the + * X509_verify_cert() result, the error and its depth through the pointers. */ +static int run_selfsigned_anchor_case(const byte* caDer, int caSz, + const byte* leafDer, int leafSz, int* verifyRet, int* verifyErr, + int* verifyDepth) +{ + EXPECT_DECLS; + X509* ca = NULL; + X509* leaf = NULL; + X509_STORE* store = NULL; + X509_STORE_CTX* ctx = NULL; + STACK_OF(X509)* trusted = NULL; + const byte* p; + + p = caDer; + ExpectNotNull(ca = d2i_X509(NULL, &p, caSz)); + p = leafDer; + ExpectNotNull(leaf = d2i_X509(NULL, &p, leafSz)); + ExpectNotNull(store = X509_STORE_new()); + ExpectNotNull(ctx = X509_STORE_CTX_new()); + ExpectIntEQ(X509_STORE_CTX_init(ctx, store, leaf, NULL), 1); + ExpectNotNull(trusted = sk_X509_new_null()); + ExpectIntGT(sk_X509_push(trusted, ca), 0); + X509_STORE_CTX_trusted_stack(ctx, trusted); + X509_STORE_CTX_set_flags(ctx, X509_V_FLAG_PARTIAL_CHAIN); + *verifyRet = X509_verify_cert(ctx); + *verifyErr = X509_STORE_CTX_get_error(ctx); + *verifyDepth = X509_STORE_CTX_get_error_depth(ctx); + X509_STORE_CTX_free(ctx); + X509_STORE_free(store); + sk_X509_free(trusted); + X509_free(leaf); + X509_free(ca); + return EXPECT_RESULT(); +} +#endif + +/* Regression: a chain-supplied (untrusted) intermediate that is CA:TRUE but + * whose KeyUsage extension does NOT assert keyCertSign must NOT be usable to + * sign the leaf - RFC 5280 4.2.1.3. Previously such an intermediate, added as + * a temporary CA during path building, was accepted as a signing CA. + * + * Conversely, an intermediate with NO KeyUsage extension implies all usages + * (including keyCertSign) and must still verify - the fix must not over-reject + * those. */ +int test_X509_verify_cert_ca_no_keycertsign(void) +{ + EXPECT_DECLS; +#if defined(OPENSSL_EXTRA) && !defined(NO_RSA) && !defined(NO_CERTS) && \ + defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_EXT) && \ + !defined(NO_SHA256) && defined(USE_CERT_BUFFERS_2048) && \ + !defined(NO_ASN_TIME) && !defined(ALLOW_INVALID_CERTSIGN) + /* ALLOW_INVALID_CERTSIGN disables the keyCertSign enforcement that Case 1 + * relies on, so the test is only meaningful when it is not defined. */ + WC_RNG rng; + RsaKey caKey, intKey, leafKey; + int rngI = 0, caI = 0, intI = 0, leafI = 0; + word32 idx; + byte* intDer = NULL; + byte* leafDer = NULL; + int intSz = 0, leafSz = 0; + int verifyRet = -1; + int verifyErr = 0, verifyDepth = 0; + const byte* p; + X509* root = NULL; + + intDer = (byte*)XMALLOC(FOURK_BUF, NULL, DYNAMIC_TYPE_TMP_BUFFER); + leafDer = (byte*)XMALLOC(FOURK_BUF, NULL, DYNAMIC_TYPE_TMP_BUFFER); + ExpectNotNull(intDer); + ExpectNotNull(leafDer); + + ExpectIntEQ(wc_InitRng(&rng), 0); + if (EXPECT_SUCCESS()) rngI = 1; + ExpectIntEQ(wc_InitRsaKey(&caKey, NULL), 0); + if (EXPECT_SUCCESS()) caI = 1; + idx = 0; + ExpectIntEQ(wc_RsaPrivateKeyDecode(ca_key_der_2048, &idx, &caKey, + sizeof_ca_key_der_2048), 0); + ExpectIntEQ(wc_InitRsaKey(&intKey, NULL), 0); + if (EXPECT_SUCCESS()) intI = 1; + idx = 0; + ExpectIntEQ(wc_RsaPrivateKeyDecode(server_key_der_2048, &idx, &intKey, + sizeof_server_key_der_2048), 0); + ExpectIntEQ(wc_InitRsaKey(&leafKey, NULL), 0); + if (EXPECT_SUCCESS()) leafI = 1; + idx = 0; + ExpectIntEQ(wc_RsaPrivateKeyDecode(client_key_der_2048, &idx, &leafKey, + sizeof_client_key_der_2048), 0); + + p = ca_cert_der_2048; + ExpectNotNull(root = d2i_X509(NULL, &p, (int)sizeof_ca_cert_der_2048)); + + /* Case 1: intermediate CA WITHOUT keyCertSign -> verification must fail. */ + ExpectIntGT((intSz = gen_ca_int_keyusage(intDer, FOURK_BUF, &intKey, &caKey, + &rng, "No keyCertSign Intermediate", "digitalSignature", 0)), 0); + ExpectIntGT((leafSz = gen_leaf_under_int(leafDer, FOURK_BUF, &leafKey, + intDer, intSz, &intKey, &rng, "Leaf under bad int")), 0); + verifyRet = -1; + ExpectIntEQ(run_int_keyusage_case(intDer, intSz, leafDer, leafSz, root, + &verifyRet, &verifyErr, &verifyDepth), 1); + ExpectIntNE(verifyRet, 1); + ExpectIntEQ(verifyErr, X509_V_ERR_INVALID_CA); + ExpectIntEQ(verifyDepth, 1); + + /* Case 2: intermediate CA with NO KeyUsage extension -> must verify. */ + ExpectIntGT((intSz = gen_ca_int_keyusage(intDer, FOURK_BUF, &intKey, &caKey, + &rng, "No KeyUsage Intermediate", NULL, 0)), 0); + ExpectIntGT((leafSz = gen_leaf_under_int(leafDer, FOURK_BUF, &leafKey, + intDer, intSz, &intKey, &rng, "Leaf under noKU int")), 0); + verifyRet = -1; + ExpectIntEQ(run_int_keyusage_case(intDer, intSz, leafDer, leafSz, root, + &verifyRet, &verifyErr, &verifyDepth), 1); + ExpectIntEQ(verifyRet, 1); + + X509_free(root); + if (rngI) wc_FreeRng(&rng); + if (caI) wc_FreeRsaKey(&caKey); + if (intI) wc_FreeRsaKey(&intKey); + if (leafI) wc_FreeRsaKey(&leafKey); + XFREE(intDer, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(leafDer, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return EXPECT_RESULT(); +} + +/* As in OpenSSL, a trust anchor whose KeyUsage extension omits keyCertSign + * cannot issue certificates, also when it is self-signed. A self-issued key + * rollover certificate signed by the root acts as a trust anchor with + * keyCertSign. + * + * @return TEST_SUCCESS on success. + */ +int test_X509_verify_cert_selfsigned_anchor_no_keycertsign(void) +{ + EXPECT_DECLS; +#if defined(OPENSSL_EXTRA) && !defined(NO_RSA) && !defined(NO_CERTS) && \ + defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_EXT) && \ + !defined(NO_SHA256) && defined(USE_CERT_BUFFERS_2048) && \ + !defined(NO_ASN_TIME) && !defined(ALLOW_INVALID_CERTSIGN) + static const struct { + int selfSigned; /* else a rollover signed by the test root */ + const char* keyUsage; + int expectVerify; /* expected X509_verify_cert() result */ + int expectErr; /* expected error */ + } cases[] = { + { 1, "digitalSignature", 0, X509_V_ERR_INVALID_CA }, + { 0, "digitalSignature", 0, X509_V_ERR_INVALID_CA }, + { 0, "digitalSignature,keyCertSign", 1, X509_V_OK }, + }; + WC_RNG rng; + RsaKey rootKey, caKey, leafKey; + int rngI = 0, rootI = 0, caI = 0, leafI = 0; + word32 idx; + byte* caDer = NULL; + byte* leafDer = NULL; + DecodedCert* dc = NULL; + int caSz = 0, leafSz = 0; + int verifyRet; + int verifyErr = 0, verifyDepth = 0; + size_t i; + + caDer = (byte*)XMALLOC(FOURK_BUF, NULL, DYNAMIC_TYPE_TMP_BUFFER); + leafDer = (byte*)XMALLOC(FOURK_BUF, NULL, DYNAMIC_TYPE_TMP_BUFFER); + dc = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, + DYNAMIC_TYPE_DCERT); + ExpectNotNull(caDer); + ExpectNotNull(leafDer); + ExpectNotNull(dc); + + ExpectIntEQ(wc_InitRng(&rng), 0); + if (EXPECT_SUCCESS()) rngI = 1; + ExpectIntEQ(wc_InitRsaKey(&rootKey, NULL), 0); + if (EXPECT_SUCCESS()) rootI = 1; + idx = 0; + ExpectIntEQ(wc_RsaPrivateKeyDecode(ca_key_der_2048, &idx, &rootKey, + sizeof_ca_key_der_2048), 0); + ExpectIntEQ(wc_InitRsaKey(&caKey, NULL), 0); + if (EXPECT_SUCCESS()) caI = 1; + idx = 0; + ExpectIntEQ(wc_RsaPrivateKeyDecode(server_key_der_2048, &idx, &caKey, + sizeof_server_key_der_2048), 0); + ExpectIntEQ(wc_InitRsaKey(&leafKey, NULL), 0); + if (EXPECT_SUCCESS()) leafI = 1; + idx = 0; + ExpectIntEQ(wc_RsaPrivateKeyDecode(client_key_der_2048, &idx, &leafKey, + sizeof_client_key_der_2048), 0); + + for (i = 0; i < XELEM_CNT(cases) && EXPECT_SUCCESS(); i++) { + ExpectIntGT((caSz = gen_ca_int_keyusage(caDer, FOURK_BUF, &caKey, + &rootKey, &rng, cases[i].selfSigned ? "Self Signed Anchor" : NULL, + cases[i].keyUsage, cases[i].selfSigned)), 0); + /* A plain parse sets selfSigned only for the self-signed anchor. */ + wc_InitDecodedCert(dc, caDer, (word32)caSz, NULL); + ExpectIntEQ(wc_ParseCert(dc, CA_TYPE, NO_VERIFY, NULL), 0); + ExpectIntEQ(dc->selfIssued, 1); + ExpectIntEQ(dc->selfSigned, cases[i].selfSigned); + wc_FreeDecodedCert(dc); + ExpectIntGT((leafSz = gen_leaf_under_int(leafDer, FOURK_BUF, &leafKey, + caDer, caSz, &caKey, &rng, "Leaf under anchor")), 0); + verifyRet = -1; + ExpectIntEQ(run_selfsigned_anchor_case(caDer, caSz, leafDer, leafSz, + &verifyRet, &verifyErr, &verifyDepth), 1); + ExpectIntEQ(verifyRet, cases[i].expectVerify); + ExpectIntEQ(verifyErr, cases[i].expectErr); + if (cases[i].expectVerify == 0) + ExpectIntEQ(verifyDepth, 1); + } + + if (rngI) wc_FreeRng(&rng); + if (rootI) wc_FreeRsaKey(&rootKey); + if (caI) wc_FreeRsaKey(&caKey); + if (leafI) wc_FreeRsaKey(&leafKey); + XFREE(caDer, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(leafDer, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(dc, NULL, DYNAMIC_TYPE_DCERT); +#endif + return EXPECT_RESULT(); +} + +#if defined(OPENSSL_EXTRA) && !defined(NO_RSA) && !defined(NO_CERTS) && \ + defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_EXT) && \ + !defined(NO_SHA256) && defined(USE_CERT_BUFFERS_2048) && \ + !defined(NO_ASN_TIME) +/* Build a certificate for key, signed with signKey, from bare common names. + * issuerCn NULL names the 2048-bit test root. skid and akid fill a key id with + * that byte, 0 omits the extension. */ +static X509* gen_named_cert(const char* subjCn, const char* issuerCn, int isCA, + byte skid, byte akid, RsaKey* key, RsaKey* signKey, WC_RNG* rng) +{ + Cert cert; + X509* x509 = NULL; + byte* der = NULL; + const byte* p; + int derSz = -1; + + if (wc_InitCert(&cert) != 0) + return NULL; cert.isCA = isCA; cert.sigType = CTC_SHA256wRSA; cert.selfSigned = 0; @@ -3419,160 +4261,2714 @@ static X509* gen_named_cert(const char* subjCn, const char* issuerCn, int isCA, #ifdef WOLFSSL_CERT_GEN_CACHE wc_SetCert_Free(&cert); /* release DecodedCert from wc_SetIssuerBuffer */ #endif - return NULL; + return NULL; + } + if (skid != 0) { + XMEMSET(cert.skid, skid, KEYID_SIZE); + cert.skidSz = KEYID_SIZE; + } + if (akid != 0) { + XMEMSET(cert.akid, akid, KEYID_SIZE); + cert.akidSz = KEYID_SIZE; + } + + der = (byte*)XMALLOC(FOURK_BUF, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (der != NULL && wc_MakeCert(&cert, der, FOURK_BUF, key, NULL, rng) > 0) + derSz = wc_SignCert(cert.bodySz, cert.sigType, der, FOURK_BUF, signKey, + NULL, rng); + if (derSz > 0) { + p = der; + x509 = d2i_X509(NULL, &p, derSz); + } + XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#ifdef WOLFSSL_CERT_GEN_CACHE + wc_SetCert_Free(&cert); /* release DecodedCert from wc_SetIssuerBuffer */ +#endif + return x509; +} +#endif + +/* X509_verify_cert() loads each candidate issuer into the CertManager as a + * temporary CA, and the CertManager picks the signer on its own from all it + * holds. An untrusted CA loaded for a link below, or for a path that was + * abandoned, must be gone when the next link is verified: otherwise a + * certificate signed by it passes while the path goes on with a same-named + * genuine intermediate that leads to the root. + * + * The attacker knows the genuine intermediate's certificate and holds none of + * its keys. Every forged path must be rejected. */ +int test_X509_verify_cert_stale_temp_ca(void) +{ + EXPECT_DECLS; +#if defined(OPENSSL_EXTRA) && !defined(NO_RSA) && !defined(NO_CERTS) && \ + defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_EXT) && \ + !defined(NO_SHA256) && defined(USE_CERT_BUFFERS_2048) && \ + !defined(NO_ASN_TIME) + enum { K_ROOT, K_INT, K_ATK, K_CNT }; + enum { C_INT, C_HONEST, C_FORGED, C_LOOP_TWIN, C_LOOP_UP, C_BARE_TWIN, + C_DECOY, C_FORGED_B, C_TWIN_A, C_TWIN_B, C_UP, C_UP_OTHER, C_CNT }; + static const struct { + const char* subj; + const char* issuer; /* NULL is the test root */ + int isCA; + byte skid; + byte akid; + int key; + int signKey; + } certs[C_CNT] = { + /* The genuine intermediate and a leaf it issued. */ + { "Issuing CA", NULL, 1, 0x03, 0, K_INT, K_ROOT }, + { "honest", "Issuing CA", 0, 0, 0x03, K_ATK, K_INT }, + /* Signed by the attacker in the intermediate's name. */ + { "forged", "Issuing CA", 0, 0, 0, K_ATK, K_ATK }, + /* Two CAs that issued each other, one named like the intermediate. */ + { "Issuing CA", "Upper CA", 1, 0x0b, 0, K_ATK, K_ATK }, + { "Upper CA", "Issuing CA", 1, 0x16, 0, K_ATK, K_ATK }, + /* No subject key id, and not signed by the issuer it names. */ + { "Issuing CA", "Decoy CA", 1, 0, 0, K_ATK, K_ATK }, + { "Decoy CA", "Nowhere", 1, 0x16, 0, K_INT, K_ATK }, + /* Twin A verifies under Upper CA, which names twin B as its issuer but + * is not signed by it. The other Upper CA did not sign twin A. */ + { "forged", "Issuing CA", 0, 0x16, 0, K_ATK, K_ATK }, + { "Issuing CA", "Upper CA", 1, 0x0b, 0, K_ATK, K_INT }, + { "Issuing CA", "Nowhere", 1, 0x16, 0, K_ATK, K_ROOT }, + { "Upper CA", "Issuing CA", 1, 0x21, 0x16, K_INT, K_ROOT }, + { "Upper CA", "Nowhere", 1, 0x2c, 0, K_ATK, K_ROOT }, + }; + static const struct { + int leaf; + int untrusted[6]; /* in push order, ends with -1 */ + int expectVerify; /* expected X509_verify_cert() result */ + } cases[] = { + { C_HONEST, { C_INT, -1 }, 1 }, + { C_FORGED, { C_INT, -1 }, 0 }, + /* Left from a link below: no link fails on the way up. */ + { C_FORGED, { C_LOOP_TWIN, C_LOOP_UP, C_INT, -1 }, 0 }, + /* Left from an abandoned path: the certificate that failed. */ + { C_FORGED, { C_BARE_TWIN, C_DECOY, C_INT, -1 }, 0 }, + /* Left from an abandoned path: the issuer it failed against. */ + { C_FORGED_B, { C_TWIN_A, C_INT, C_TWIN_B, C_UP, C_UP_OTHER, -1 }, 0 }, + }; + WC_RNG rng; + RsaKey keys[K_CNT]; + int rngI = 0; + int keysI = 0; + word32 idx; + X509* x509[C_CNT]; + X509* root = NULL; + X509_STORE* store = NULL; + X509_STORE_CTX* ctx = NULL; + STACK_OF(X509)* untrusted = NULL; + const byte* p; + size_t i; + int j; + + XMEMSET(x509, 0, sizeof(x509)); + + ExpectIntEQ(wc_InitRng(&rng), 0); + if (EXPECT_SUCCESS()) rngI = 1; + for (j = 0; j < K_CNT; j++) { + ExpectIntEQ(wc_InitRsaKey(&keys[j], NULL), 0); + if (EXPECT_SUCCESS()) keysI = j + 1; + } + idx = 0; + ExpectIntEQ(wc_RsaPrivateKeyDecode(ca_key_der_2048, &idx, &keys[K_ROOT], + sizeof_ca_key_der_2048), 0); + idx = 0; + ExpectIntEQ(wc_RsaPrivateKeyDecode(server_key_der_2048, &idx, &keys[K_INT], + sizeof_server_key_der_2048), 0); + idx = 0; + ExpectIntEQ(wc_RsaPrivateKeyDecode(client_key_der_2048, &idx, &keys[K_ATK], + sizeof_client_key_der_2048), 0); + + p = ca_cert_der_2048; + ExpectNotNull(root = d2i_X509(NULL, &p, (int)sizeof_ca_cert_der_2048)); + for (j = 0; j < C_CNT; j++) { + ExpectNotNull(x509[j] = gen_named_cert(certs[j].subj, certs[j].issuer, + certs[j].isCA, certs[j].skid, certs[j].akid, &keys[certs[j].key], + &keys[certs[j].signKey], &rng)); + } + + for (i = 0; i < XELEM_CNT(cases) && EXPECT_SUCCESS(); i++) { + ExpectNotNull(store = X509_STORE_new()); + ExpectIntEQ(X509_STORE_add_cert(store, root), 1); + ExpectNotNull(untrusted = sk_X509_new_null()); + for (j = 0; cases[i].untrusted[j] >= 0; j++) { + ExpectIntGT(sk_X509_push(untrusted, x509[cases[i].untrusted[j]]), + 0); + } + ExpectNotNull(ctx = X509_STORE_CTX_new()); + ExpectIntEQ(X509_STORE_CTX_init(ctx, store, x509[cases[i].leaf], + untrusted), 1); + ExpectIntEQ(X509_verify_cert(ctx), cases[i].expectVerify); + X509_STORE_CTX_free(ctx); + ctx = NULL; + X509_STORE_free(store); + store = NULL; + sk_X509_free(untrusted); + untrusted = NULL; + } + + for (j = 0; j < C_CNT; j++) + X509_free(x509[j]); + X509_free(root); + while (keysI > 0) + wc_FreeRsaKey(&keys[--keysI]); + if (rngI) wc_FreeRng(&rng); +#endif + return EXPECT_RESULT(); +} + +#if defined(OPENSSL_EXTRA) && !defined(NO_RSA) && !defined(NO_CERTS) && \ + !defined(NO_FILESYSTEM) +/* See certs/intermediate/trust_anchor/gen_certs.sh and gen_dated_certs.sh */ +#define TA_CERT_DIR "./certs/intermediate/trust_anchor/" +#if defined(HAVE_CRL) && defined(WOLFSSL_CERT_GEN) && \ + !defined(NO_ASN_TIME) && !defined(NO_STDIO_FILESYSTEM) +/* CRLs are generated */ +#define X509_VFY_GEN_CRLS +#endif + +/* Verify errors */ +#define VE_OK X509_V_OK +#define VE_ISSUER X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT +#define VE_NOCRL X509_V_ERR_UNABLE_TO_GET_CRL +#define VE_CRLSIG X509_V_ERR_CRL_SIGNATURE_FAILURE +#define VE_SIG X509_V_ERR_CERT_SIGNATURE_FAILURE +#define VE_NOTYET X509_V_ERR_CERT_NOT_YET_VALID +#define VE_EXPIRED X509_V_ERR_CERT_HAS_EXPIRED +#define VE_SELF0 X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT +#define VE_SELF X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN +#define VE_LOCAL X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY +#define VE_LEAFSIG X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE +#define VE_LONG X509_V_ERR_CERT_CHAIN_TOO_LONG +#define VE_REVOKED X509_V_ERR_CERT_REVOKED +#define VE_CA X509_V_ERR_INVALID_CA +#define VE_CERTSIGN X509_V_ERR_KEYUSAGE_NO_CERTSIGN +#define VE_KEYSIZE X509_V_ERR_CA_KEY_TOO_SMALL +#define VE_NCPERM X509_V_ERR_PERMITTED_VIOLATION +#define VE_NCEXCL X509_V_ERR_EXCLUDED_VIOLATION +#define VE_PATHLEN X509_V_ERR_PATH_LENGTH_EXCEEDED +#define VE_CRLEXP X509_V_ERR_CRL_HAS_EXPIRED +#define VE_CRLNYV X509_V_ERR_CRL_NOT_YET_VALID +#define VE_CRLKU X509_V_ERR_KEYUSAGE_NO_CRL_SIGN + +/* Options of a case */ +#define VO_XMLSEC 0x00001 /* a new param, as xmlsec: no TRUSTED_FIRST */ +#define VO_PARTIAL 0x00002 /* X509_V_FLAG_PARTIAL_CHAIN */ +#define VO_STRICT 0x00004 /* X509_V_FLAG_X509_STRICT */ +#define VO_NOTIME 0x00008 /* X509_V_FLAG_NO_CHECK_TIME */ +#define VO_S_STRICT 0x00010 /* X509_V_FLAG_X509_STRICT on the store */ +#define VO_S_NOTIME 0x00020 /* X509_V_FLAG_NO_CHECK_TIME on the store */ +#define VO_CRL 0x00040 /* X509_V_FLAG_CRL_CHECK on the store */ +#define VO_CRL_ALL 0x000C0 /* and X509_V_FLAG_CRL_CHECK_ALL */ +#define VO_FILE 0x00100 /* trusted certs by X509_STORE_load_locations */ +#define VO_LOOKUP 0x00200 /* by X509_LOOKUP_load_file */ +#define VO_SSLCTX 0x00400 /* by SSL_CTX_load_verify_locations */ +#define VO_ADD1999 0x00800 /* trusted certs added in 1999 */ +#define VO_MINRSA 0x01000 /* a minimum RSA CA key of 4096 bits */ +#define VO_DEPTH0 0x02000 /* X509_STORE_CTX_set_depth(ctx, 0) */ +#define VO_DEPTH1 0x04000 /* X509_STORE_CTX_set_depth(ctx, 1) */ +#define VO_MINECC 0x08000 /* a minimum ECC CA key of 384 bits */ +#define VO_T2005 0x10000 /* verification time 2005 */ +#define VO_T2015 0x20000 /* 2015 */ +#define VO_T2025 0x30000 /* 2025 */ +#define VO_TIME 0x30000 +#define VO_S_PARTIAL 0x40000 /* X509_V_FLAG_PARTIAL_CHAIN on the store */ +#define VO_C_CRL 0x80000 /* X509_V_FLAG_CRL_CHECK on the ctx */ +#define VO_C_CRL_ALL 0x180000 /* and X509_V_FLAG_CRL_CHECK_ALL */ + +/* The verify callback logs every error and accepts these */ +#define VA_ISSUER 0x01 /* VE_ISSUER */ +#define VA_LOCAL 0x02 /* VE_LOCAL */ +#define VA_SELF 0x04 /* VE_SELF0 and VE_SELF */ +#define VA_DATES 0x08 /* VE_NOTYET and VE_EXPIRED */ +#define VA_CA 0x10 /* VE_CA */ +#define VA_KEYSIZE 0x20 /* VE_KEYSIZE */ +#define VA_NOCRL 0x40 /* VE_NOCRL */ +#define VA_CRLKU 0x100 /* VE_CRLKU */ +#define VA_CRLEXP 0x200 /* VE_CRLEXP */ +#define VA_ALL 0x80 /* any */ + +/* A verification. Certs are named by file: TA_CERT_DIR -cert.pem or + * an alias of x509VfyFiles; "#2" is another copy of it. CRLs alike, + * with -crl.pem; "+" is given with X509_STORE_CTX_set0_crls(). */ +typedef struct x509_vfy_case { + const char* name; + const char* trusted; /* store certs, in the order added */ + const char* stack; /* X509_STORE_CTX_trusted_stack() */ + const char* untrusted; + const char* leaf; + const char* crls; + int opts; /* VO_* */ + int cb; /* VA_*, 0: no verify callback */ + int ret; /* of X509_verify_cert() */ + int err; + int depth; /* of err, unless VE_OK */ + const char* chain; /* leaf first, NULL: not checked */ + int cbLog[6]; /* errors and depths the callback saw */ +} x509_vfy_case; + +static const x509_vfy_case x509VfyCases[] = { + /* Every issuer, untrusted or trusted, meets the cert manager's minimum + * CA key size. All keys are 2048 bits. OpenSSL has no minimum for CAs + * only: at auth level 3 it first reports + * X509_V_ERR_EE_KEY_TOO_SMALL for the leaf, then the same errors. */ + { "key_size: 2048 bits", + "ca", NULL, "int1 int2", "server-int", NULL, + 0, 0, 1, VE_OK, 0, NULL, { 0 } }, + { "key_size: 4096 bits minimum", + "ca", NULL, "int1 int2", "server-int", NULL, + VO_MINRSA, 0, 0, VE_KEYSIZE, 1, NULL, { 0 } }, + { "key_size: callback accepts each issuer, the anchor too", + "ca", NULL, "int1 int2", "server-int", NULL, + VO_MINRSA, VA_KEYSIZE, 1, VE_KEYSIZE, 0, NULL, + { VE_KEYSIZE, 1, VE_KEYSIZE, 2, VE_KEYSIZE, 3 } }, +#ifdef HAVE_ECC + /* The size of an ECC key is that of its curve. All keys are P-256. */ + { "key_size: P-256", + "ca-ecc", NULL, "int1-ecc int2-ecc", "server-int-ecc", NULL, + 0, 0, 1, VE_OK, 0, NULL, { 0 } }, + { "key_size: 384 bits ECC minimum", + "ca-ecc", NULL, "int1-ecc int2-ecc", "server-int-ecc", NULL, + VO_MINECC, 0, 0, VE_KEYSIZE, 1, NULL, { 0 } }, +#endif + + /* A self-signed cert ends the chain. self-copy has the name and key of + * the trusted self, which verifies it, but only a trusted cert itself + * ends the chain. */ + { "selfsigned_copy: trusted", + "self", NULL, NULL, "self", NULL, + 0, 0, 1, VE_OK, 0, NULL, { 0 } }, + { "selfsigned_copy: copy", + "self", NULL, NULL, "self-copy", NULL, + 0, 0, 0, VE_SELF0, 0, NULL, { 0 } }, + { "selfsigned_copy: callback accepts copy", + "self", NULL, NULL, "self-copy", NULL, + 0, VA_ALL, 1, VE_SELF0, 0, "self-copy", { VE_SELF0, 0 } }, + { "selfsigned_copy: copy, partial chain", + "self", NULL, NULL, "self-copy", NULL, + VO_PARTIAL, 0, 0, VE_SELF0, 0, NULL, { 0 } }, + /* As in OpenSSL, the first trusted cert of the name, self, is taken: the + * copy is a mimic of it. Added first, the copy is taken. */ + { "selfsigned_copy: copy trusted too", + "self self-copy", NULL, NULL, "self-copy", NULL, + 0, 0, 0, VE_SELF0, 0, NULL, { 0 } }, + { "selfsigned_copy: copy trusted first", + "self-copy self", NULL, NULL, "self-copy", NULL, + 0, 0, 1, VE_OK, 0, NULL, { 0 } }, + { "selfsigned_copy: copy, trusted stack", + NULL, "self", NULL, "self-copy", NULL, + 0, 0, 0, VE_SELF0, 0, NULL, { 0 } }, + { "selfsigned_copy: trusted stack", + NULL, "self", NULL, "self", NULL, + 0, 0, 1, VE_OK, 0, NULL, { 0 } }, + { "selfsigned_copy: copy, store file", + "self", NULL, NULL, "self-copy", NULL, + VO_FILE, 0, 0, VE_SELF0, 0, NULL, { 0 } }, + { "selfsigned_copy: store file", + "self", NULL, NULL, "self", NULL, + VO_FILE, 0, 1, VE_OK, 0, NULL, { 0 } }, +#if defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM) + { "selfsigned_copy: copy, lookup file", + "self", NULL, NULL, "self-copy", NULL, + VO_LOOKUP, 0, 0, VE_SELF0, 0, NULL, { 0 } }, + { "selfsigned_copy: lookup file", + "self", NULL, NULL, "self", NULL, + VO_LOOKUP, 0, 1, VE_OK, 0, NULL, { 0 } }, +#endif +#if !defined(NO_TLS) && !defined(NO_WOLFSSL_CLIENT) + /* An SSL_CTX keeps its CAs in the cert manager only */ + { "selfsigned_copy: SSL_CTX", + "self", NULL, NULL, "self", NULL, + VO_SSLCTX, 0, 1, VE_OK, 0, NULL, { 0 } }, +#endif + + /* A trusted cert is a root only when self-signed. link has the name of + * root and its own key, and root issued it: it is self-issued, but its + * authority key id names root's key. */ + { "selfissued_anchor: link", + "link", NULL, NULL, "leaf", NULL, + 0, 0, 0, VE_ISSUER, 1, NULL, { 0 } }, + { "selfissued_anchor: callback accepts link", + "link", NULL, NULL, "leaf", NULL, + 0, VA_ALL, 1, VE_ISSUER, 0, "leaf link", { VE_ISSUER, 1 } }, + { "selfissued_anchor: link, partial chain", + "link", NULL, NULL, "leaf", NULL, + VO_PARTIAL, 0, 1, VE_OK, 0, NULL, { 0 } }, + { "selfissued_anchor: link without aki is self-signed", + "link-noaki", NULL, NULL, "leaf", NULL, + 0, 0, 1, VE_OK, 0, NULL, { 0 } }, + { "selfissued_anchor: link and root", + "link root", NULL, NULL, "leaf", NULL, + 0, 0, 1, VE_OK, 0, "leaf link root", { 0 } }, + /* link is not the anchor: it counts against the depth */ + { "selfissued_anchor: link and root, depth 0", + "link root", NULL, NULL, "leaf", NULL, + VO_DEPTH0, 0, 0, VE_LONG, 1, NULL, { 0 } }, + { "selfissued_anchor: link and root, depth 1", + "link root", NULL, NULL, "leaf", NULL, + VO_DEPTH1, 0, 1, VE_OK, 0, NULL, { 0 } }, + { "selfissued_anchor: link, store file", + "link", NULL, NULL, "leaf", NULL, + VO_FILE, 0, 0, VE_ISSUER, 1, NULL, { 0 } }, + { "selfissued_anchor: link and root, store file", + "link root", NULL, NULL, "leaf", NULL, + VO_FILE, 0, 1, VE_OK, 0, NULL, { 0 } }, +#if defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM) + { "selfissued_anchor: link, lookup file", + "link", NULL, NULL, "leaf", NULL, + VO_LOOKUP, 0, 0, VE_ISSUER, 1, NULL, { 0 } }, + { "selfissued_anchor: link and root, lookup file", + "link root", NULL, NULL, "leaf", NULL, + VO_LOOKUP, 0, 1, VE_OK, 0, NULL, { 0 } }, +#endif +#if !defined(NO_TLS) && !defined(NO_WOLFSSL_CLIENT) && \ + defined(WOLFSSL_SIGNER_DER_CERT) + /* A CA of an SSL_CTX is a trusted cert, the chain goes on to its + * issuer there */ + { "selfissued_anchor: root and link, SSL_CTX", + "root link", NULL, NULL, "leaf", NULL, + VO_SSLCTX, 0, 1, VE_OK, 0, "leaf link root", { 0 } }, + { "selfissued_anchor: link, SSL_CTX", + "link", NULL, NULL, "leaf", NULL, + VO_SSLCTX, 0, 0, VE_ISSUER, 1, NULL, { 0 } }, +#endif + + /* Every cert above the leaf is a CA that may sign certs, a trusted one + * too. Without basicConstraints only a v1 self-signed root is one, + * unless X509_V_FLAG_X509_STRICT is set. With that flag OpenSSL first + * reports that v1-root-leaf has no authority key id: + * X509_V_ERR_MISSING_AUTHORITY_KEY_IDENTIFIER at depth 0. */ + { "trusted_ca: CA:FALSE root", + "notca-root nobc-root v1-root", NULL, NULL, "notca-root-leaf", NULL, + 0, 0, 0, VE_CA, 1, NULL, { 0 } }, + { "trusted_ca: callback accepts CA:FALSE root", + "notca-root nobc-root v1-root", NULL, NULL, "notca-root-leaf", NULL, + 0, VA_ALL, 1, VE_CA, 0, "notca-root-leaf notca-root", { VE_CA, 1 } }, + { "trusted_ca: CA:FALSE root, a stack without it", + "notca-root nobc-root v1-root", "v1-root", NULL, "notca-root-leaf", + NULL, 0, 0, 0, VE_LOCAL, 0, NULL, { 0 } }, + /* The stack's leaf ends the chain: the store's root is not on it */ + { "trusted_ca: leaf in a stack, partial chain", + "notca-root nobc-root v1-root", "notca-root-leaf", NULL, + "notca-root-leaf", NULL, + VO_PARTIAL, 0, 1, VE_OK, 0, "notca-root-leaf", { 0 } }, + { "trusted_ca: CA:FALSE root as the leaf", + "notca-root nobc-root v1-root", NULL, NULL, "notca-root", NULL, + 0, 0, 1, VE_OK, 0, NULL, { 0 } }, + { "trusted_ca: copy of a stack cert", + NULL, "notca-root", NULL, "notca-root#2", NULL, + 0, 0, 1, VE_OK, 0, "notca-root", { 0 } }, + { "trusted_ca: v3 root without basicConstraints", + "notca-root nobc-root v1-root", NULL, NULL, "nobc-root-leaf", NULL, + 0, 0, 0, VE_CA, 1, NULL, { 0 } }, + { "trusted_ca: callback accepts v3 root without basicConstraints", + "notca-root nobc-root v1-root", NULL, NULL, "nobc-root-leaf", NULL, + 0, VA_ALL, 1, VE_CA, 0, "nobc-root-leaf nobc-root", { VE_CA, 1 } }, + { "trusted_ca: v1 root", + "notca-root nobc-root v1-root", NULL, NULL, "v1-root-leaf", NULL, + 0, 0, 1, VE_OK, 0, NULL, { 0 } }, + { "trusted_ca: v1 root, strict", + "notca-root nobc-root v1-root", NULL, NULL, "v1-root-leaf", NULL, + VO_STRICT, 0, 0, VE_CA, 1, NULL, { 0 } }, + { "trusted_ca: v1 root in a stack", + NULL, "notca-root v1-root", NULL, "v1-root-leaf", NULL, + 0, 0, 1, VE_OK, 0, NULL, { 0 } }, + { "trusted_ca: v1 root in a stack, strict", + NULL, "notca-root v1-root", NULL, "v1-root-leaf", NULL, + VO_STRICT, 0, 0, VE_CA, 1, NULL, { 0 } }, + { "trusted_ca: v1 root, strict store", + "notca-root nobc-root v1-root", NULL, NULL, "v1-root-leaf", NULL, + VO_S_STRICT, 0, 0, VE_CA, 1, NULL, { 0 } }, +#ifndef WOLFSSL_X509_STORE_ALLOW_NON_CA_INTERMEDIATE + /* An untrusted CA:FALSE intermediate is reported as itself, then its + * keyUsage without keyCertSign */ + { "trusted_ca: CA:FALSE intermediate", + "nca-ca", NULL, "nca-int", "nca-leaf", NULL, + VO_FILE, VA_ALL, 1, VE_CERTSIGN, 0, "nca-leaf nca-int nca-ca", + { VE_CA, 1, VE_CERTSIGN, 1 } }, + /* The leaf signature is still checked after that */ + { "trusted_ca: CA:FALSE intermediate, bad leaf signature", + "nca-ca", NULL, "nca-int", "nca-leaf-badsig", NULL, + VO_FILE, VA_ALL, 1, VE_SIG, 0, "nca-leaf-badsig nca-int nca-ca", + { VE_CA, 1, VE_CERTSIGN, 1, VE_SIG, 0 } }, +#else + /* An untrusted CA:FALSE intermediate is allowed */ + { "trusted_ca: CA:FALSE intermediate allowed", + "nca-ca", NULL, "nca-int", "nca-leaf", NULL, + VO_FILE, VA_ALL, 1, VE_OK, 0, "nca-leaf nca-int nca-ca", { 0 } }, + { "trusted_ca: CA:FALSE intermediate allowed, bad leaf signature", + "nca-ca", NULL, "nca-int", "nca-leaf-badsig", NULL, + VO_FILE, VA_ALL, 1, VE_SIG, 0, "nca-leaf-badsig nca-int nca-ca", + { VE_SIG, 0 } }, +#endif + + /* With X509_V_FLAG_TRUSTED_FIRST, the default, a trusted root that + * issues a cert ends the chain, also when an untrusted cross-signed copy + * of it issues it too. cross-root is dated-root issued by expired-root. + * Without the flag the untrusted certs come first. */ + { "trusted_first: trusted root first", + "dated-root expired-root", NULL, "dated-int cross-root", + "dated-int-leaf", NULL, + 0, 0, 1, VE_OK, 0, "dated-int-leaf dated-int dated-root", { 0 } }, +#ifndef NO_ASN_TIME + { "trusted_first: untrusted first", + "dated-root expired-root", NULL, "dated-int cross-root", + "dated-int-leaf", NULL, + VO_XMLSEC, 0, 0, VE_EXPIRED, 3, NULL, { 0 } }, + /* dated-root-late is not valid in 2015, expired-root is */ + { "trusted_first: late root", + "dated-root-late expired-root", NULL, "dated-int cross-root", + "dated-int-leaf", NULL, + VO_T2015, 0, 0, VE_NOTYET, 2, NULL, { 0 } }, + { "trusted_first: late root, untrusted first", + "dated-root-late expired-root", NULL, "dated-int cross-root", + "dated-int-leaf", NULL, + VO_XMLSEC | VO_T2015, 0, 1, VE_OK, 0, + "dated-int-leaf dated-int cross-root expired-root", { 0 } }, + /* A trusted cert valid at the verification time comes first, also + * before a trusted root */ + { "trusted_first: trusted cross-root valid in 2015", + "dated-root-late expired-root cross-root", NULL, + "dated-int cross-root", "dated-int-leaf", NULL, + VO_T2015, 0, 1, VE_OK, 0, + "dated-int-leaf dated-int cross-root expired-root", { 0 } }, + + /* Without X509_V_FLAG_TRUSTED_FIRST the issuer of an untrusted cert + * comes from the untrusted certs first, then from the trusted certs, one + * valid at the verification time first. Above a trusted cert only a + * trusted cert issues, with the flag too. */ + { "untrusted_first: trusted root valid in 2015", + "dated-root expired-root cross-root-late", NULL, "dated-int", + "dated-int-leaf", NULL, + VO_XMLSEC | VO_T2015, 0, 1, VE_OK, 0, + "dated-int-leaf dated-int dated-root", { 0 } }, + { "untrusted_first: no untrusted issuer of a trusted cert", + "dated-root expired-root dated-int", NULL, "cross-root", + "dated-int-leaf", NULL, + VO_XMLSEC, 0, 1, VE_OK, 0, "dated-int-leaf dated-int dated-root", + { 0 } }, + { "untrusted_first: no untrusted issuer of a trusted cert, no root", + "expired-root dated-int", NULL, "cross-root", "dated-int-leaf", NULL, + VO_XMLSEC | VO_T2015, 0, 0, VE_ISSUER, 1, NULL, { 0 } }, + { "untrusted_first: no root, trusted first", + "expired-root dated-int", NULL, "cross-root", "dated-int-leaf", NULL, + VO_T2015, 0, 0, VE_ISSUER, 1, NULL, { 0 } }, + { "untrusted_first: trusted cross-root valid in 2015", + "dated-root-late expired-root cross-root", NULL, "dated-int", + "dated-int-leaf", NULL, + VO_XMLSEC | VO_T2015, 0, 1, VE_OK, 0, + "dated-int-leaf dated-int cross-root expired-root", { 0 } }, + + /* Without X509_V_FLAG_TRUSTED_FIRST the untrusted certs are searched in + * their order, self-signed ones included */ + { "untrusted_order: copy of the root first", + "dated-root expired-root", NULL, "dated-int dated-root#2 cross-root", + "dated-int-leaf", NULL, + VO_XMLSEC, 0, 1, VE_OK, 0, "dated-int-leaf dated-int dated-root", + { 0 } }, + { "untrusted_order: cross-root first", + "dated-root expired-root", NULL, "dated-int cross-root dated-root#2", + "dated-int-leaf", NULL, + VO_XMLSEC, 0, 0, VE_EXPIRED, 3, NULL, { 0 } }, + + /* alt-end, issued by a cert not given, is above the untrusted twins of + * alt-int, which alt-root issued. OpenSSL goes on from the trusted + * alt-int and verifies. wolfSSL fails closed: the twin is the issuer and + * alt-end above it has none. */ + { "dead_end: twin out of date", + "alt-end alt-int alt-root", NULL, "alt-old-int", "alt-int-leaf", NULL, + VO_XMLSEC, 0, 0, VE_ISSUER, 2, NULL, { 0 } }, + { "dead_end: twin not a CA", + "alt-end alt-int alt-root", NULL, "alt-notca-int", "alt-int-leaf", + NULL, VO_XMLSEC, 0, 0, VE_ISSUER, 2, NULL, { 0 } }, + /* OpenSSL: VE_NOTYET at depth 1 on its chain through alt-int, which + * the callback accepts. The missing issuer is final as a trusted cert + * issued the leaf. */ + { "dead_end: alt-int not valid yet", + "alt-end alt-int alt-root", NULL, "alt-end-int", "alt-int-leaf", NULL, + VO_XMLSEC | VO_T2015, VA_ALL, 0, VE_ISSUER, 2, + "alt-int-leaf alt-end-int alt-end", { VE_ISSUER, 2 } }, + /* OpenSSL: VE_CA at depth 1 on its chain through the trusted twin */ + { "dead_end: trusted twin not a CA", + "alt-notca-int alt-end", NULL, "alt-end-int", "alt-int-leaf", NULL, + VO_XMLSEC, VA_ISSUER | VA_LOCAL, 0, VE_ISSUER, 2, NULL, + { VE_ISSUER, 2 } }, +#endif + + /* A trusted self-signed root ends the chain. noaki-root has no authority + * key id, so by name noaki-root-link, a trusted CA it issued, could + * issue it too. */ + { "noaki_root: root ends the chain", + NULL, "noaki-root-link noaki-root", NULL, "noaki-root-leaf", NULL, + 0, VA_ALL, 1, VE_OK, 0, "noaki-root-leaf noaki-root", { 0 } }, + + /* A cert is verified with the issuer chosen for it only. The cert + * manager finds forge-fake-int by name before forge-int. */ + { "forged_issuer: forge-int", + "forge-root", NULL, NULL, "forge-int", NULL, + 0, 0, 1, VE_OK, 0, NULL, { 0 } }, + { "forged_issuer: bad sub first", + "forge-root", NULL, "forge-bad-sub forge-sub forge-int forge-fake-int", + "forge-sub-leaf", NULL, + 0, 0, 0, VE_LOCAL, 2, NULL, { 0 } }, + { "forged_issuer: fake int", + "forge-root", NULL, "forge-fake-int forge-q forge-int", + "forge-fake-int-leaf", NULL, + 0, 0, 0, VE_SIG, 2, NULL, { 0 } }, + + /* The issuer chosen for a cert must have signed it. notca-twin has the + * name of notca-root, which signed the leaf, but not its key. Without a + * subject key id it issues the leaf by name. */ + { "wrong_signer: trusted notca-root first", + "root notca-root", NULL, "notca-twin", "notca-root-leaf", NULL, + 0, 0, 0, VE_CA, 1, NULL, { 0 } }, + /* The untrusted twin is taken by name: VE_SIG at depth 0 */ + { "wrong_signer: untrusted first", + "root notca-root", NULL, "notca-twin", "notca-root-leaf", NULL, + VO_XMLSEC, 0, 0, VE_SIG, 0, "notca-root-leaf notca-twin root", + { 0 } }, + { "wrong_signer: only a stack issues", + "notca-root", "root", "notca-twin", "notca-root-leaf", NULL, + 0, 0, 0, VE_SIG, 0, NULL, { 0 } }, + +#ifndef NO_ASN_TIME + /* A callback that rejects an error of a trusted cert ends the + * verification. The trusted wrongca-int names wrongca as its issuer, + * whose key did not sign it. Its untrusted twin wrongca-old-int, out of + * date, has no issuer. OpenSSL: VE_SIG at depth 1 through the trusted + * twin. wolfSSL fails closed on the missing issuer. */ + { "trusted_cert_error: no root", + "wrongca-int wrongca", NULL, "wrongca-old-int", "wrongca-int-leaf", + NULL, VO_XMLSEC, VA_ISSUER | VA_LOCAL, 0, VE_LOCAL, 1, NULL, + { VE_LOCAL, 1 } }, + { "trusted_cert_error: root", + "wrongca-int wrongca wrongca-root", NULL, "wrongca-old-int", + "wrongca-int-leaf", NULL, + VO_XMLSEC, VA_ISSUER | VA_LOCAL, 0, VE_LOCAL, 1, NULL, + { VE_LOCAL, 1 } }, +#endif + + /* With a trusted stack, trusted certs come only from the stack. The + * store's dated-root has the name and key of the stack's cross-root but + * does not issue it, nor dated-int in a stack, nor any other cert. */ + { "trusted_stack_only: stack cert without issuer", + "dated-root", "cross-root", NULL, "dated-int", NULL, + 0, 0, 0, VE_ISSUER, 1, NULL, { 0 } }, + { "trusted_stack_only: leaf", + "dated-root", "cross-root", "dated-int", "dated-int-leaf", NULL, + 0, 0, 0, VE_ISSUER, 2, NULL, { 0 } }, + { "trusted_stack_only: dated-int in the stack", + "dated-root", "dated-int", NULL, "dated-int-leaf", NULL, + 0, 0, 0, VE_ISSUER, 1, NULL, { 0 } }, + { "trusted_stack_only: callback accepts, the chain ends there", + "dated-root", "dated-int", NULL, "dated-int-leaf", NULL, + 0, VA_ALL, 1, VE_ISSUER, 0, "dated-int-leaf dated-int", + { VE_ISSUER, 1 } }, + { "trusted_stack_only: partial chain", + "dated-root", "cross-root", "dated-int", "dated-int-leaf", NULL, + VO_PARTIAL, 0, 1, VE_OK, 0, NULL, { 0 } }, + { "trusted_stack_only: store CA does not issue the leaf", + "dated-root", "expired-root", NULL, "dated-int", NULL, + 0, 0, 0, VE_LOCAL, 0, NULL, { 0 } }, + { "trusted_stack_only: store CA does not issue an untrusted cert", + "dated-root", "expired-root", "dated-int", "dated-int-leaf", NULL, + 0, 0, 0, VE_LOCAL, 1, NULL, { 0 } }, + /* The top of a partial chain: its dates are not checked */ + { "trusted_stack_only: expired stack cert", + "dated-root", "expired-int", NULL, "dated-int-leaf", NULL, + 0, 0, 0, VE_ISSUER, 1, NULL, { 0 } }, + { "trusted_stack_only: callback accepts expired stack cert", + "dated-root", "expired-int", NULL, "dated-int-leaf", NULL, + 0, VA_ALL, 1, VE_ISSUER, 0, NULL, { VE_ISSUER, 1 } }, + { "trusted_stack_only: store root not trusted", + "dated-root", "expired-int", NULL, "dated-root", NULL, + 0, 0, 0, VE_SELF0, 0, NULL, { 0 } }, + { "trusted_stack_only: store root not trusted, partial chain", + "dated-root", "expired-int", NULL, "dated-root", NULL, + VO_PARTIAL, 0, 0, VE_SELF0, 0, NULL, { 0 } }, + +#ifdef HAVE_CRL + /* With X509_V_FLAG_CRL_CHECK_ALL the CRL of a stack cert that no stack + * cert issues cannot be checked: its issuer is not on the chain. + * Accepting the missing issuer does not accept that. */ + { "trusted_stack_crl: missing issuer accepted", + "ca", "int1", NULL, "int2", "ca-int-crl", + VO_CRL_ALL, VA_ISSUER | VA_LOCAL, 0, VE_NOCRL, 1, NULL, + { VE_ISSUER, 1, VE_NOCRL, 1 } }, + { "trusted_stack_crl: callback accepts both", + "ca", "int1", NULL, "int2", "ca-int-crl", + VO_CRL_ALL, VA_ALL, 1, VE_NOCRL, 0, "int2 int1", + { VE_ISSUER, 1, VE_NOCRL, 1 } }, + { "trusted_stack_crl: partial chain", + "ca", "int1", NULL, "int2", "ca-int-crl", + VO_CRL_ALL | VO_PARTIAL, 0, 0, VE_NOCRL, 1, NULL, { 0 } }, +#endif + + /* A trusted root of the name of a cert's issuer issues it when the key + * ids do not tell otherwise, also when its key did not sign it. + * expired-root-nokid has expired-root's name, a new key, no key ids. */ + { "nokid_issuer: wrong key", + "expired-root-nokid", NULL, NULL, "expired-root-leaf", NULL, + 0, 0, 0, VE_SIG, 0, NULL, { 0 } }, + { "nokid_issuer: callback accepts", + "expired-root-nokid", NULL, NULL, "expired-root-leaf", NULL, + 0, VA_ALL, 1, VE_SIG, 0, "expired-root-leaf expired-root-nokid", + { VE_SIG, 0 } }, + +#ifdef HAVE_ECC + /* An issuer has a key of the type of the cert's signature. ec-name-root, + * an EC root without key ids, has the name of the RSA link, which issued + * the leaf. */ + { "keytype_issuer: EC root of the name", + "ec-name-root", NULL, NULL, "leaf", NULL, + 0, 0, 0, VE_LOCAL, 0, NULL, { 0 } }, + { "keytype_issuer: callback accepts", + "ec-name-root", NULL, NULL, "leaf", NULL, + 0, VA_ALL, 1, VE_LEAFSIG, 0, "leaf", + { VE_LOCAL, 0, VE_LEAFSIG, 0 } }, +#endif + +#ifndef NO_ASN_TIME + /* The dates of every cert of the chain are checked at the verification + * time, the trust anchor too. expired-root is valid from 2010 to 2019, + * the leaf it issued from 2000 to 2049. */ + { "anchor_dates: no check time on the store", + "expired-root", NULL, NULL, "expired-root-leaf", NULL, + VO_S_NOTIME, 0, 1, VE_OK, 0, NULL, { 0 } }, + { "anchor_dates: expired root", + "expired-root", NULL, NULL, "expired-root-leaf", NULL, + 0, 0, 0, VE_EXPIRED, 1, NULL, { 0 } }, + { "anchor_dates: 2015", + "expired-root", NULL, NULL, "expired-root-leaf", NULL, + VO_T2015, 0, 1, VE_OK, 0, NULL, { 0 } }, + { "anchor_dates: 2005", + "expired-root", NULL, NULL, "expired-root-leaf", NULL, + VO_T2005, 0, 0, VE_NOTYET, 1, NULL, { 0 } }, + /* The verification time wins over X509_V_FLAG_NO_CHECK_TIME */ + { "anchor_dates: 2025 and no check time", + "expired-root", NULL, NULL, "expired-root-leaf", NULL, + VO_T2025 | VO_NOTIME, 0, 0, VE_EXPIRED, 1, NULL, { 0 } }, + { "anchor_dates: no check time", + "expired-root", NULL, NULL, "expired-root-leaf", NULL, + VO_NOTIME, 0, 1, VE_OK, 0, NULL, { 0 } }, + { "anchor_dates: callback accepts", + "expired-root", NULL, NULL, "expired-root-leaf", NULL, + 0, VA_ALL, 1, VE_EXPIRED, 0, "expired-root-leaf expired-root", + { VE_EXPIRED, 1 } }, + /* A trusted leaf is checked once, as the current cert */ + { "anchor_dates: trusted leaf", + "expired-root", NULL, NULL, "expired-root", NULL, + 0, VA_ALL, 1, VE_EXPIRED, 0, "expired-root", { VE_EXPIRED, 0 } }, + { "anchor_dates: copy of a stack cert", + NULL, "expired-root", NULL, "expired-root#2", NULL, + 0, VA_ALL, 1, VE_EXPIRED, 0, "expired-root", { VE_EXPIRED, 0 } }, + /* With X509_V_FLAG_PARTIAL_CHAIN the first trusted cert ends the chain. + * The root above it is not checked. */ + { "anchor_dates: trusted intermediate", + "expired-root expired-root-int", NULL, NULL, "expired-root-int-leaf", + NULL, 0, 0, 0, VE_EXPIRED, 2, NULL, { 0 } }, + { "anchor_dates: trusted intermediate, partial chain", + "expired-root expired-root-int", NULL, NULL, "expired-root-int-leaf", + NULL, VO_PARTIAL, 0, 1, VE_OK, 0, NULL, { 0 } }, + /* A cert above that trusted cert is not on the chain. Its date error + * does not end the verification: cross-root-late issues the trusted + * dated-int and is valid from 2020. */ + { "anchor_dates: late cert above", + "expired-root expired-root-int dated-int", NULL, "cross-root-late", + "dated-int-leaf", NULL, + VO_T2015, 0, 0, VE_ISSUER, 1, NULL, { 0 } }, + { "anchor_dates: late cert above, partial chain", + "expired-root expired-root-int dated-int", NULL, "cross-root-late", + "dated-int-leaf", NULL, + VO_T2015 | VO_PARTIAL, 0, 1, VE_OK, 0, "dated-int-leaf dated-int", + { 0 } }, + /* The store is not used with a trusted stack. With the leaf in the + * stack, the partial chain ends below the store's dated-root-late, not + * valid in 2015. */ + { "anchor_dates: stack cert as the leaf", + "dated-root-late", "dated-int", NULL, "dated-int", NULL, + VO_T2015 | VO_PARTIAL, 0, 1, VE_OK, 0, "dated-int", { 0 } }, + /* As in OpenSSL, the leaf ends the partial chain only when no issuer + * is found: the untrusted dated-int is put on it */ + { "anchor_dates: stack cert as the leaf, untrusted issuer", + "dated-root-late", "dated-int-leaf", "dated-int", "dated-int-leaf", + NULL, VO_T2015 | VO_PARTIAL, 0, 1, VE_OK, 0, + "dated-int-leaf dated-int", { 0 } }, + + /* The ctx param inherits the store's X509_V_FLAG_PARTIAL_CHAIN. As in + * OpenSSL, a new param, as xmlsec sets, does not have it. */ + { "partial_chain: store flag", + "int2", NULL, NULL, "server-int", NULL, + VO_S_PARTIAL, 0, 1, VE_OK, 0, "server-int int2", { 0 } }, + { "partial_chain: store flag, new param", + "int2", NULL, NULL, "server-int", NULL, + VO_S_PARTIAL | VO_XMLSEC, 0, 0, VE_ISSUER, 1, NULL, { 0 } }, + { "partial_chain: new param with the flag", + "int2", NULL, NULL, "server-int", NULL, + VO_PARTIAL | VO_XMLSEC, 0, 1, VE_OK, 0, "server-int int2", { 0 } }, + + /* As OpenSSL, the callback is told of a chain too long. Failing closed, + * the error is final: once it is accepted, OpenSSL reports VE_LOCAL at + * depth 1 and verifies. */ + { "depth: callback told", + "ca", NULL, "int1 int2", "server-int", NULL, + VO_DEPTH0, VA_ISSUER, 0, VE_LONG, 1, NULL, { VE_LONG, 1 } }, + { "depth: callback accepts", + "ca", NULL, "int1 int2", "server-int", NULL, + VO_DEPTH0, VA_ALL, 0, VE_LONG, 1, NULL, { VE_LONG, 1 } }, + + /* X509_V_FLAG_CRL_CHECK(_ALL) on the ctx without CRLs, also without + * HAVE_CRL: each cert checked has no CRL */ + { "crl_none: CRL_CHECK on the ctx", + "ca", NULL, NULL, "server", NULL, + VO_C_CRL, 0, 0, VE_NOCRL, 0, NULL, { 0 } }, + { "crl_none: CRL_CHECK on the ctx, callback accepts", + "ca", NULL, NULL, "server", NULL, + VO_C_CRL, VA_NOCRL, 1, VE_NOCRL, 0, NULL, { VE_NOCRL, 0 } }, + { "crl_none: CRL_CHECK_ALL on the ctx, partial chain", + "int2", NULL, NULL, "server-int", NULL, + VO_C_CRL_ALL | VO_PARTIAL, VA_NOCRL, 1, VE_NOCRL, 0, NULL, + { VE_NOCRL, 0, VE_NOCRL, 1 } }, + /* As OpenSSL, a self-signed anchor has its own CRLs */ + { "crl_none: CRL_CHECK_ALL on the ctx, anchor", + "ca", NULL, NULL, "server", NULL, + VO_C_CRL_ALL, VA_NOCRL, 1, VE_NOCRL, 0, NULL, + { VE_NOCRL, 0, VE_NOCRL, 1 } }, + { "crl_none: CRL_CHECK on the ctx, the anchor alone", + "ca", NULL, NULL, "ca", NULL, + VO_C_CRL, 0, 0, VE_NOCRL, 0, NULL, { 0 } }, + +#ifdef HAVE_CRL + /* The store's CRLs are checked for a cert out of date now but valid at + * the verification time. dated-root-crl revokes expired-int. */ + { "crl_dates: no CRL check", + "dated-root", NULL, NULL, "expired-int", NULL, + VO_T2015, 0, 1, VE_OK, 0, NULL, { 0 } }, + { "crl_dates: no CRL", + "dated-root", NULL, NULL, "expired-int", NULL, + VO_T2015 | VO_CRL, 0, 0, VE_NOCRL, 0, NULL, { 0 } }, + { "crl_dates: revoked", + "dated-root", NULL, NULL, "expired-int", "dated-root", + VO_T2015 | VO_CRL, 0, 0, VE_REVOKED, 0, NULL, { 0 } }, + /* Out of date now: revoked first, then the date error */ + { "crl_dates: dates accepted", + "dated-root", NULL, NULL, "expired-int", "dated-root", + VO_CRL, VA_DATES, 0, VE_REVOKED, 0, NULL, { VE_REVOKED, 0 } }, + { "crl_dates: callback accepts", + "dated-root", NULL, NULL, "expired-int", "dated-root", + VO_CRL, VA_ALL, 1, VE_EXPIRED, 0, NULL, + { VE_REVOKED, 0, VE_EXPIRED, 0 } }, + { "crl_dates: CRL of X509_STORE_CTX_set0_crls", + "dated-root", NULL, NULL, "expired-int", "dated-root-empty +dated-root", + VO_CRL, VA_DATES, 0, VE_REVOKED, 0, NULL, { VE_REVOKED, 0 } }, + /* As in OpenSSL, the flag on the ctx turns on the check */ + { "crl_dates: CRL_CHECK on the ctx, revoked", + "dated-root", NULL, NULL, "expired-int", "+dated-root", + VO_T2015 | VO_C_CRL, 0, 0, VE_REVOKED, 0, NULL, { 0 } }, + { "crl_dates: CRL_CHECK on the ctx, no CRL", + "dated-root", NULL, NULL, "expired-int", NULL, + VO_T2015 | VO_C_CRL, 0, 0, VE_NOCRL, 0, NULL, { 0 } }, + { "crl_dates: CRL_CHECK on the ctx, xmlsec param, revoked", + "dated-root", NULL, NULL, "expired-int", "+dated-root", + VO_XMLSEC | VO_T2015 | VO_C_CRL, 0, 0, VE_REVOKED, 0, NULL, { 0 } }, + { "crl_dates: CRL_CHECK on the ctx, not revoked", + "dated-root", NULL, NULL, "expired-int", "+dated-root-empty", + VO_T2015 | VO_C_CRL_ALL, 0, 1, VE_OK, 0, NULL, { 0 } }, + /* A CRL whose signature does not verify is not used: its error is + * final. Once the callback accepts it, OpenSSL takes its entries: + * VE_REVOKED, accepted. */ + { "crl_dates: bad CRL signature", + "dated-root", NULL, NULL, "expired-int", "+dated-root-badsig", + VO_T2015 | VO_CRL, 0, 0, VE_CRLSIG, 0, NULL, { 0 } }, + { "crl_dates: bad CRL signature, callback accepts", + "dated-root", NULL, NULL, "expired-int", "+dated-root-badsig", + VO_T2015 | VO_CRL, VA_ALL, 0, VE_CRLSIG, 0, NULL, { VE_CRLSIG, 0 } }, +#endif +#ifdef X509_VFY_GEN_CRLS + /* A stale CRL is reported. As in OpenSSL, once that is accepted its + * entries are still checked. A current CRL of the ctx is used over a + * stale one of the store. ca-stale and ca-revoked list server. */ + { "crl_stale: stale CRL", + "ca", NULL, NULL, "server", "ca-stale", + VO_CRL, 0, 0, VE_CRLEXP, 0, NULL, { 0 } }, + { "crl_stale: stale CRL, callback accepts it", + "ca", NULL, NULL, "server", "ca-stale", + VO_CRL, VA_CRLEXP, 0, VE_REVOKED, 0, NULL, + { VE_CRLEXP, 0, VE_REVOKED, 0 } }, + { "crl_stale: stale CRL without the cert, callback accepts it", + "ca", NULL, NULL, "server", "ca-stale-empty", + VO_CRL, VA_CRLEXP, 1, VE_CRLEXP, 0, NULL, { VE_CRLEXP, 0 } }, + { "crl_stale: current CRL of the ctx", + "ca", NULL, NULL, "server", "ca-stale-empty +ca-revoked", + VO_CRL, VA_CRLEXP, 0, VE_REVOKED, 0, NULL, { VE_REVOKED, 0 } }, + { "crl_stale: current CRL of the ctx without the cert", + "ca", NULL, NULL, "server", "ca-stale +ca-empty", + VO_CRL, 0, 1, VE_OK, 0, NULL, { 0 } }, + /* X509_V_FLAG_NO_CHECK_TIME skips the dates of CRLs too */ + { "crl_stale: stale CRL, no time check", + "ca", NULL, NULL, "server", "ca-stale", + VO_CRL | VO_NOTIME, 0, 0, VE_REVOKED, 0, NULL, { 0 } }, + { "crl_stale: stale CRL without the cert, no time check", + "ca", NULL, NULL, "server", "ca-stale-empty", + VO_CRL | VO_NOTIME, 0, 1, VE_OK, 0, NULL, { 0 } }, + { "crl_stale: stale CRL of the ctx, no time check on the store", + "ca", NULL, NULL, "server", "+ca-stale", + VO_C_CRL | VO_S_NOTIME, 0, 0, VE_REVOKED, 0, NULL, { 0 } }, + /* As OpenSSL, the dates of a CRL before its signature */ + { "crl_stale: stale CRL with a bad signature", + "ca", NULL, NULL, "server", "ca-stale-empty-badsig", + VO_CRL, 0, 0, VE_CRLEXP, 0, NULL, { 0 } }, + { "crl_stale: stale CRL with a bad signature, callback accepts it", + "ca", NULL, NULL, "server", "ca-stale-empty-badsig", + VO_CRL, VA_CRLEXP, 0, VE_CRLSIG, 0, NULL, + { VE_CRLEXP, 0, VE_CRLSIG, 0 } }, + /* As OpenSSL, the CRLs of the ctx are used over the store's, which are + * not looked at */ + { "crl_stale: current CRL of the ctx, the store's revokes", + "ca", NULL, NULL, "server", "ca-revoked +ca-empty", + VO_CRL, 0, 1, VE_OK, 0, NULL, { 0 } }, + { "crl_stale: current CRL of the ctx, the store's does not verify", + "ca", NULL, NULL, "server", "ca-empty-badsig +ca-empty", + VO_CRL, 0, 1, VE_OK, 0, NULL, { 0 } }, + { "crl_stale: stale CRL of the ctx, the store's revokes", + "ca", NULL, NULL, "server", "ca-revoked +ca-stale-empty", + VO_CRL, VA_CRLEXP, 1, VE_CRLEXP, 0, NULL, { VE_CRLEXP, 0 } }, + { "crl_stale: CRL of the store not yet valid", + "ca", NULL, NULL, "server", "ca-nyv-empty", + VO_CRL, 0, 0, VE_CRLNYV, 0, NULL, { 0 } }, + { "crl_stale: CRL of the store not yet valid, current one of the ctx", + "ca", NULL, NULL, "server", "ca-nyv-empty +ca-empty", + VO_CRL, 0, 1, VE_OK, 0, NULL, { 0 } }, + /* Not yet valid over expired, as OpenSSL takes the CRL of the latest + * thisUpdate */ + { "crl_stale: CRLs of the ctx expired and not yet valid", + "ca", NULL, NULL, "server", "+ca-stale-empty +ca-nyv-empty", + VO_CRL, 0, 0, VE_CRLNYV, 0, NULL, { 0 } }, + { "crl_stale: CRLs of the ctx not yet valid and expired", + "ca", NULL, NULL, "server", "+ca-nyv-empty +ca-stale-empty", + VO_CRL, 0, 0, VE_CRLNYV, 0, NULL, { 0 } }, + + /* As OpenSSL's get_crl_sk(), only the best CRL is checked: a current + * one, then the latest. ca-otherkey has the name of ca, no AKID and + * another key: its signature fails. The -old CRLs are a day older. */ + { "crl_pick: older CRL of another key", + "ca", NULL, NULL, "server", "ca-otherkey-old ca-empty", + VO_CRL, 0, 1, VE_OK, 0, NULL, { 0 } }, + { "crl_pick: older CRL of another key, added last", + "ca", NULL, NULL, "server", "ca-empty ca-otherkey-old", + VO_CRL, 0, 1, VE_OK, 0, NULL, { 0 } }, + { "crl_pick: newer CRL of another key", + "ca", NULL, NULL, "server", "ca-otherkey ca-empty-old", + VO_CRL, 0, 0, VE_CRLSIG, 0, NULL, { 0 } }, + { "crl_pick: newer CRL of another key, added last", + "ca", NULL, NULL, "server", "ca-empty-old ca-otherkey", + VO_CRL, 0, 0, VE_CRLSIG, 0, NULL, { 0 } }, + { "crl_pick: older CRL of another key, ctx", + "ca", NULL, NULL, "server", "+ca-otherkey-old +ca-empty", + VO_C_CRL, 0, 1, VE_OK, 0, NULL, { 0 } }, + { "crl_pick: older CRL of another key, ctx, last", + "ca", NULL, NULL, "server", "+ca-empty +ca-otherkey-old", + VO_C_CRL, 0, 1, VE_OK, 0, NULL, { 0 } }, + { "crl_pick: newer CRL of another key, ctx", + "ca", NULL, NULL, "server", "+ca-otherkey +ca-empty-old", + VO_C_CRL, 0, 0, VE_CRLSIG, 0, NULL, { 0 } }, + { "crl_pick: newer CRL of another key, ctx, last", + "ca", NULL, NULL, "server", "+ca-empty-old +ca-otherkey", + VO_C_CRL, 0, 0, VE_CRLSIG, 0, NULL, { 0 } }, + { "crl_pick: current CRL over a newer one not yet valid", + "ca", NULL, NULL, "server", "ca-revoked ca-nyv-empty", + VO_CRL, 0, 0, VE_REVOKED, 0, NULL, { 0 } }, + { "crl_pick: current CRL over a newer one not yet valid, ctx", + "ca", NULL, NULL, "server", "+ca-nyv-empty +ca-revoked", + VO_C_CRL, 0, 0, VE_REVOKED, 0, NULL, { 0 } }, + { "crl_pick: same thisUpdate, the first", + "ca", NULL, NULL, "server", "ca-revoked ca-empty", + VO_CRL, 0, 0, VE_REVOKED, 0, NULL, { 0 } }, + { "crl_pick: same thisUpdate, the first, other order", + "ca", NULL, NULL, "server", "ca-empty ca-revoked", + VO_CRL, 0, 1, VE_OK, 0, NULL, { 0 } }, + { "crl_pick: same thisUpdate, the first, ctx", + "ca", NULL, NULL, "server", "+ca-revoked +ca-empty", + VO_C_CRL, 0, 0, VE_REVOKED, 0, NULL, { 0 } }, + { "crl_pick: same thisUpdate, the first, ctx, other order", + "ca", NULL, NULL, "server", "+ca-empty +ca-revoked", + VO_C_CRL, 0, 1, VE_OK, 0, NULL, { 0 } }, + + /* As OpenSSL, a self-signed anchor has its own CRLs: checked with + * X509_V_FLAG_CRL_CHECK_ALL, or as the leaf. ca-self lists ca. */ + { "crl_anchor: anchor revoked", + "ca", NULL, NULL, "server", "ca-self", + VO_CRL_ALL, 0, 0, VE_REVOKED, 1, NULL, { 0 } }, + { "crl_anchor: anchor revoked, CRL_CHECK_ALL on the ctx", + "ca", NULL, NULL, "server", "+ca-self", + VO_C_CRL_ALL, 0, 0, VE_REVOKED, 1, NULL, { 0 } }, + { "crl_anchor: anchor revoked, only the leaf checked", + "ca", NULL, NULL, "server", "ca-self", + VO_CRL, 0, 1, VE_OK, 0, NULL, { 0 } }, + { "crl_anchor: anchor revoked, the leaf", + "ca", NULL, NULL, "ca", "ca-self", + VO_CRL, 0, 0, VE_REVOKED, 0, NULL, { 0 } }, + { "crl_anchor: anchor not revoked", + "ca", NULL, NULL, "server", "ca-empty", + VO_CRL_ALL, 0, 1, VE_OK, 0, NULL, { 0 } }, +#endif + + /* The error is reported at the CA whose path length is exceeded: + * pl0-int, of pathlen:0, issued the CA pl0-sub */ + { "path_len: trusted CA", + "ca pl0-int", NULL, "pl0-sub", "pl0-leaf", NULL, + 0, 0, 0, VE_PATHLEN, 2, NULL, { 0 } }, + { "path_len: untrusted CA", + "ca", NULL, "pl0-int pl0-sub", "pl0-leaf", NULL, + 0, 0, 0, VE_PATHLEN, 2, NULL, { 0 } }, + { "path_len: callback accepts", + "ca", NULL, "pl0-int pl0-sub", "pl0-leaf", NULL, + 0, VA_ALL, 1, VE_PATHLEN, 0, "pl0-leaf pl0-sub pl0-int ca", + { VE_PATHLEN, 2 } }, + { "path_len: partial chain", + "pl0-int", NULL, "pl0-sub", "pl0-leaf", NULL, + VO_PARTIAL, VA_ALL, 1, VE_PATHLEN, 0, "pl0-leaf pl0-sub pl0-int", + { VE_PATHLEN, 2 } }, + +#if !defined(NO_TLS) && !defined(NO_WOLFSSL_CLIENT) +#ifdef WOLFSSL_SIGNER_DER_CERT + /* With X509_V_FLAG_TRUSTED_FIRST the trusted dated-int of an SSL_CTX is + * taken over an untrusted twin out of date, then its issuer there */ + { "ctx_store_twin: only the root trusted", + "dated-root", NULL, "expired-int", "dated-int-leaf", NULL, + VO_SSLCTX, 0, 0, VE_EXPIRED, 1, NULL, { 0 } }, + { "ctx_store_twin: trusted twin", + "dated-root dated-int", NULL, "expired-int", "dated-int-leaf", NULL, + VO_SSLCTX, 0, 1, VE_OK, 0, + "dated-int-leaf dated-int dated-root", { 0 } }, + { "ctx_store_twin: trusted twin, 2005", + "dated-root dated-int", NULL, "expired-int", "dated-int-leaf", NULL, + VO_SSLCTX | VO_T2005, 0, 1, VE_OK, 0, + "dated-int-leaf dated-int dated-root", { 0 } }, + { "ctx_store_twin: trusted twin, 2015", + "dated-root dated-int", NULL, "expired-int", "dated-int-leaf", NULL, + VO_SSLCTX | VO_T2015, 0, 1, VE_OK, 0, + "dated-int-leaf dated-int dated-root", { 0 } }, + { "ctx_store_twin: untrusted first", + "dated-root dated-int", NULL, "expired-int", "dated-int-leaf", NULL, + VO_SSLCTX | VO_XMLSEC, 0, 0, VE_EXPIRED, 1, NULL, { 0 } }, + /* A CA of an SSL_CTX is a trusted cert: it goes on the chain, then its + * issuer there, each checked as in a store: pl0-int, of pathlen:0, may + * not issue the CA pl0-sub, and a CA:FALSE root may not issue */ + { "ctx_store_ca: path length", + "ca pl0-int", NULL, "pl0-sub", "pl0-leaf", NULL, + VO_SSLCTX, 0, 0, VE_PATHLEN, 2, NULL, { 0 } }, + { "ctx_store_ca: path length, callback accepts", + "ca pl0-int", NULL, "pl0-sub", "pl0-leaf", NULL, + VO_SSLCTX, VA_ALL, 1, VE_PATHLEN, 0, NULL, { VE_PATHLEN, 2 } }, + { "ctx_store_ca: CA:FALSE root", + "notca-root", NULL, NULL, "notca-root-leaf", NULL, + VO_SSLCTX, 0, 0, VE_CA, 1, NULL, { 0 } }, + { "ctx_store_ca: path length of the root of a trusted CA", + "ca pl0-sub pl0-int", NULL, NULL, "pl0-leaf", NULL, + VO_SSLCTX, 0, 0, VE_PATHLEN, 2, NULL, { 0 } }, + { "ctx_store_ca: expired root of a trusted CA", + "expired-root expired-root-int", NULL, NULL, "expired-root-int-leaf", + NULL, VO_SSLCTX, 0, 0, VE_EXPIRED, 2, NULL, { 0 } }, + { "ctx_store_ca: root of a trusted CA, 2015", + "expired-root expired-root-int", NULL, NULL, "expired-root-int-leaf", + NULL, VO_SSLCTX | VO_T2015, 0, 1, VE_OK, 0, + "expired-root-int-leaf expired-root-int expired-root", { 0 } }, +#ifdef HAVE_CRL + { "ctx_store_ca: root revokes a trusted CA", + "dated-root expired-int", NULL, NULL, "dated-int-leaf", + "dated-root int", VO_SSLCTX | VO_T2015 | VO_CRL_ALL, 0, 0, + VE_REVOKED, 1, NULL, { 0 } }, +#endif + /* wolfSSL trusts a CA of an SSL_CTX without its issuer there, as its + * handshake does. OpenSSL: VE_ISSUER at depth 2. */ + { "ctx_store_ca: CA without its root", + "int1", NULL, "int2", "server-int", NULL, + VO_SSLCTX, 0, 1, VE_OK, 0, "server-int int2 int1", { 0 } }, + /* That CA is the trust anchor: it does not count against the depth, + * as the anchor of a partial chain in OpenSSL. OpenSSL, without the + * root: VE_LONG at depth 1 and 2 where these verify. */ + { "ctx_store_ca: CA without its root, depth 0", + "int2", NULL, NULL, "server-int", NULL, + VO_SSLCTX | VO_DEPTH0, 0, 1, VE_OK, 0, "server-int int2", { 0 } }, + { "ctx_store_ca: CA without its root, intermediate, depth 0", + "int1", NULL, "int2", "server-int", NULL, + VO_SSLCTX | VO_DEPTH0, 0, 0, VE_LONG, 1, NULL, { 0 } }, + { "ctx_store_ca: CA without its root, intermediate, depth 1", + "int1", NULL, "int2", "server-int", NULL, + VO_SSLCTX | VO_DEPTH1, 0, 1, VE_OK, 0, "server-int int2 int1", + { 0 } }, +#else + /* Without its DER a CA of an SSL_CTX cannot go on the chain: the cert + * it issued has no issuer */ + { "ctx_store_ca: CA without DER", + "ca pl0-int", NULL, "pl0-sub", "pl0-leaf", NULL, + VO_SSLCTX, 0, 0, VE_LOCAL, 1, NULL, { 0 } }, +#endif +#endif + + /* An untrusted intermediate is date checked when verified, at the + * verification time, and one valid then is chosen first. expired-int is + * valid from 2010 to 2019, dated-int is the same CA valid until 2049. */ + { "untrusted_dates: expired", + "dated-root", NULL, "expired-int", "dated-int-leaf", NULL, + 0, 0, 0, VE_EXPIRED, 1, NULL, { 0 } }, + { "untrusted_dates: 2015", + "dated-root", NULL, "expired-int", "dated-int-leaf", NULL, + VO_T2015, 0, 1, VE_OK, 0, NULL, { 0 } }, + { "untrusted_dates: callback accepts", + "dated-root", NULL, "expired-int", "dated-int-leaf", NULL, + 0, VA_ALL, 1, VE_EXPIRED, 0, "dated-int-leaf expired-int dated-root", + { VE_EXPIRED, 1 } }, +#ifdef HAVE_CRL + /* The store's CRLs are checked for it too, dated-root-crl revokes it */ + { "untrusted_dates: revoked", + "dated-root", NULL, "expired-int", "dated-int-leaf", "dated-root int", + VO_T2015 | VO_CRL_ALL, 0, 0, VE_REVOKED, 1, NULL, { 0 } }, + { "untrusted_dates: callback accepts revoked", + "dated-root", NULL, "expired-int", "dated-int-leaf", "dated-root int", + VO_T2015 | VO_CRL_ALL, VA_ALL, 1, VE_REVOKED, 0, + "dated-int-leaf expired-int dated-root", { VE_REVOKED, 1 } }, + /* Out of date now: revoked first, then the date error */ + { "untrusted_dates: revoked, dates accepted", + "dated-root", NULL, "expired-int", "dated-int-leaf", "dated-root int", + VO_CRL_ALL, VA_DATES, 0, VE_REVOKED, 1, NULL, { VE_REVOKED, 1 } }, + { "untrusted_dates: callback accepts revoked and expired", + "dated-root", NULL, "expired-int", "dated-int-leaf", "dated-root int", + VO_CRL_ALL, VA_ALL, 1, VE_EXPIRED, 0, NULL, + { VE_REVOKED, 1, VE_EXPIRED, 1 } }, +#endif + { "untrusted_dates: valid twin chosen", + "dated-root", NULL, "expired-int dated-int", "dated-int-leaf", NULL, + 0, 0, 1, VE_OK, 0, "dated-int-leaf dated-int dated-root", { 0 } }, + /* With X509_V_FLAG_TRUSTED_FIRST a trusted issuer is taken first, also + * one out of date */ + { "untrusted_dates: trusted twin out of date", + "dated-root expired-int", NULL, "expired-int dated-int", + "dated-int-leaf", NULL, + 0, 0, 0, VE_EXPIRED, 1, NULL, { 0 } }, + { "untrusted_dates: trusted twin out of date, 2015", + "dated-root expired-int", NULL, "expired-int dated-int", + "dated-int-leaf", NULL, + VO_T2015, 0, 1, VE_OK, 0, NULL, { 0 } }, + { "untrusted_dates: trusted twin out of date, untrusted first", + "dated-root expired-int", NULL, "expired-int dated-int", + "dated-int-leaf", NULL, + VO_XMLSEC, 0, 1, VE_OK, 0, "dated-int-leaf dated-int dated-root", + { 0 } }, + /* The top of a partial chain is not date checked */ + { "untrusted_dates: top of a partial chain", + NULL, NULL, "expired-int", "dated-int-leaf", NULL, + 0, VA_LOCAL, 1, VE_LOCAL, 0, NULL, { VE_LOCAL, 1 } }, + /* Unless it is a lone leaf */ + { "untrusted_dates: lone leaf", + NULL, NULL, NULL, "expired-int", NULL, + 0, VA_ALL, 1, VE_EXPIRED, 0, "expired-int", + { VE_LOCAL, 0, VE_LEAFSIG, 0, VE_EXPIRED, 0 } }, + /* With an untrusted issuer above it, it is date checked. A rejection is + * final. */ + { "untrusted_dates: untrusted issuer above", + NULL, NULL, "expired-int cross-root", "dated-int-leaf", NULL, + 0, VA_LOCAL, 0, VE_EXPIRED, 1, NULL, + { VE_LOCAL, 2, VE_EXPIRED, 1 } }, + /* Also with a trusted issuer above that the cert manager does not find: + * badkid-int names nokid-root by a key id that does not match */ + { "untrusted_dates: trusted issuer by name", + "nokid-root", NULL, "badkid-int", "badkid-int-leaf", NULL, + 0, VA_LOCAL, 0, VE_EXPIRED, 1, NULL, { VE_EXPIRED, 1 } }, + { "untrusted_dates: trusted issuer by name, 2015", + "nokid-root", NULL, "badkid-int", "badkid-int-leaf", NULL, + VO_T2015, VA_LOCAL, 1, VE_OK, 0, + "badkid-int-leaf badkid-int nokid-root", { 0 } }, + { "untrusted_dates: top of a partial chain, partial chain flag", + NULL, NULL, "expired-int", "dated-int-leaf", NULL, + VO_PARTIAL, VA_LOCAL, 0, VE_EXPIRED, 1, NULL, + { VE_LOCAL, 1, VE_EXPIRED, 1 } }, + /* A trusted one that ends a partial chain */ + { "untrusted_dates: trusted, partial chain", + "expired-int", NULL, NULL, "dated-int-leaf", NULL, + VO_PARTIAL, 0, 0, VE_EXPIRED, 1, NULL, { 0 } }, + { "untrusted_dates: trusted, partial chain, 2015", + "expired-int", NULL, NULL, "dated-int-leaf", NULL, + VO_PARTIAL | VO_T2015, 0, 1, VE_OK, 0, NULL, { 0 } }, + { "untrusted_dates: trusted with its root, partial chain", + "expired-int dated-root", NULL, NULL, "dated-int-leaf", NULL, + VO_PARTIAL, 0, 0, VE_EXPIRED, 1, NULL, { 0 } }, + /* Also when the depth limit ends the chain at it */ + { "untrusted_dates: trusted with its root, partial chain, depth 0", + "expired-int dated-root", NULL, NULL, "dated-int-leaf", NULL, + VO_PARTIAL | VO_DEPTH0, 0, 0, VE_EXPIRED, 1, NULL, { 0 } }, + + /* A store of its own takes a trusted cert that is out of date. Its dates + * are checked at the verification time. */ + { "add_cert_expired: expired root", + "expired-root", NULL, NULL, "expired-root-leaf", NULL, + 0, 0, 0, VE_EXPIRED, 1, NULL, { 0 } }, + { "add_cert_expired: 2005", + "expired-root", NULL, NULL, "expired-root-leaf", NULL, + VO_T2005, 0, 0, VE_NOTYET, 1, NULL, { 0 } }, + { "add_cert_expired: 2015", + "expired-root", NULL, NULL, "expired-root-leaf", NULL, + VO_T2015, 0, 1, VE_OK, 0, NULL, { 0 } }, + { "add_cert_expired: callback accepts", + "expired-root", NULL, NULL, "expired-root-leaf", NULL, + 0, VA_ALL, 1, VE_EXPIRED, 0, NULL, { VE_EXPIRED, 1 } }, + /* A valid root of the same name with a new key does not hide it. Nor is + * it the anchor of a leaf it did not sign: renewed-root signed + * renewed-root-leaf and is valid from 2020. Both orders. In 2015 + * expired-root, valid then, is taken by name for renewed-root-leaf: + * VE_SIG at depth 0. */ + { "add_cert_expired: renewed root first", + "renewed-root expired-root", NULL, NULL, "expired-root-leaf", NULL, + VO_T2015, 0, 1, VE_OK, 0, NULL, { 0 } }, + { "add_cert_expired: renewed root first, renewed leaf", + "renewed-root expired-root", NULL, NULL, "renewed-root-leaf", NULL, + 0, 0, 1, VE_OK, 0, NULL, { 0 } }, + { "add_cert_expired: renewed root first, renewed leaf, 2015", + "renewed-root expired-root", NULL, NULL, "renewed-root-leaf", NULL, + VO_T2015, 0, 0, VE_SIG, 0, "renewed-root-leaf expired-root", { 0 } }, + { "add_cert_expired: renewed root last", + "expired-root renewed-root", NULL, NULL, "expired-root-leaf", NULL, + VO_T2015, 0, 1, VE_OK, 0, NULL, { 0 } }, + { "add_cert_expired: renewed root last, renewed leaf", + "expired-root renewed-root", NULL, NULL, "renewed-root-leaf", NULL, + 0, 0, 1, VE_OK, 0, NULL, { 0 } }, + { "add_cert_expired: renewed root last, renewed leaf, 2015", + "expired-root renewed-root", NULL, NULL, "renewed-root-leaf", NULL, + VO_T2015, 0, 0, VE_SIG, 0, "renewed-root-leaf expired-root", { 0 } }, + /* A root not yet valid when added anchors a chain once valid */ + { "add_cert_expired: root added in 1999", + "dated-root", NULL, NULL, "dated-int", NULL, + VO_ADD1999, 0, 1, VE_OK, 0, NULL, { 0 } }, + /* A trusted root comes before an untrusted cross-signed copy of it */ + { "add_cert_expired: trusted root before cross-root", + "dated-root expired-root", NULL, "dated-int cross-root", + "dated-int-leaf", NULL, + 0, 0, 1, VE_OK, 0, "dated-int-leaf dated-int dated-root", { 0 } }, + /* Of two roots with the same name and key, the anchor is the one valid + * at the verification time: dated-root-late is valid from 2020 */ + { "add_cert_expired: late twin of the root", + "dated-root-late dated-root", NULL, "dated-int", "dated-int-leaf", + NULL, VO_T2015, 0, 1, VE_OK, 0, + "dated-int-leaf dated-int dated-root", { 0 } }, + /* With a trusted stack the store's certs are not used */ + { "add_cert_expired: stack without the root", + "expired-root", "expired-root-int", NULL, "expired-root-int-leaf", + NULL, 0, 0, 0, VE_ISSUER, 1, NULL, { 0 } }, + { "add_cert_expired: stack without the root, 2015", + "expired-root", "expired-root-int", NULL, "expired-root-int-leaf", + NULL, VO_T2015, 0, 0, VE_ISSUER, 1, NULL, { 0 } }, + /* Nor does it end a chain whose missing issuer the callback accepts */ + { "add_cert_expired: stack without the root, callback accepts", + "expired-root", "expired-root-int", NULL, "expired-root-int-leaf", + NULL, 0, VA_ALL, 1, VE_ISSUER, 0, + "expired-root-int-leaf expired-root-int", { VE_ISSUER, 1 } }, + /* Nor does a root of the missing issuer's name with another key: + * renewed-root did not sign cross-root. It is not valid in 2015 either. */ + { "add_cert_expired: renewed root not the issuer", + "renewed-root", NULL, "dated-int cross-root", "dated-int-leaf", NULL, + VO_T2015, VA_ALL, 1, VE_LOCAL, 0, + "dated-int-leaf dated-int cross-root", { VE_LOCAL, 2 } }, + /* Nor for a lone leaf, whose signature is then reported unverified */ + { "add_cert_expired: renewed root, lone leaf", + "renewed-root", NULL, NULL, "expired-root-leaf", NULL, + VO_T2015, VA_ALL, 1, VE_LEAFSIG, 0, "expired-root-leaf", + { VE_LOCAL, 0, VE_LEAFSIG, 0 } }, + { "add_cert_expired: renewed root, lone leaf, missing issuer accepted", + "renewed-root", NULL, NULL, "expired-root-leaf", NULL, + VO_T2015, VA_LOCAL, 0, VE_LEAFSIG, 0, NULL, + { VE_LOCAL, 0, VE_LEAFSIG, 0 } }, + /* With X509_V_FLAG_PARTIAL_CHAIN the first trusted cert ends the chain. + * The root above it is not used. */ + { "add_cert_expired: trusted intermediate", + "expired-root expired-root-int", NULL, NULL, "expired-root-int-leaf", + NULL, 0, 0, 0, VE_EXPIRED, 2, NULL, { 0 } }, + { "add_cert_expired: trusted intermediate in a stack", + NULL, "expired-root-int expired-root", NULL, "expired-root-int-leaf", + NULL, 0, 0, 0, VE_EXPIRED, 2, NULL, { 0 } }, + { "add_cert_expired: trusted intermediate, partial chain", + "expired-root expired-root-int", NULL, NULL, "expired-root-int-leaf", + NULL, VO_PARTIAL, 0, 1, VE_OK, 0, + "expired-root-int-leaf expired-root-int", { 0 } }, + { "add_cert_expired: trusted intermediate in a stack, partial chain", + NULL, "expired-root-int expired-root", NULL, "expired-root-int-leaf", + NULL, VO_PARTIAL, 0, 1, VE_OK, 0, NULL, { 0 } }, + { "add_cert_expired: renewed root not the issuer, partial chain", + "renewed-root", NULL, "dated-int cross-root", "dated-int-leaf", NULL, + VO_T2015 | VO_PARTIAL, VA_ALL, 1, VE_LOCAL, 0, + "dated-int-leaf dated-int cross-root", { VE_LOCAL, 2 } }, + + /* An untrusted self-signed cert issues a cert that no other cert + * issues. It ends the chain as VE_SELF. */ + { "untrusted_root: self-signed in the chain", + NULL, NULL, "dated-root", "dated-int", NULL, + 0, 0, 0, VE_SELF, 1, NULL, { 0 } }, + { "untrusted_root: missing issuer accepted", + NULL, NULL, "dated-root", "dated-int", NULL, + 0, VA_LOCAL, 0, VE_SELF, 1, NULL, { VE_SELF, 1 } }, + { "untrusted_root: callback accepts", + NULL, NULL, "dated-root", "dated-int", NULL, + 0, VA_SELF | VA_ISSUER | VA_LOCAL, 1, VE_SELF, 0, + "dated-int dated-root", { VE_SELF, 1 } }, + { "untrusted_root: untrusted first", + NULL, NULL, "dated-root", "dated-int", NULL, + VO_XMLSEC, 0, 0, VE_SELF, 1, NULL, { 0 } }, + { "untrusted_root: partial chain", + NULL, NULL, "dated-root", "dated-int", NULL, + VO_PARTIAL, 0, 0, VE_SELF, 1, NULL, { 0 } }, + { "untrusted_root: trusted", + "dated-root", NULL, "dated-root", "dated-int", NULL, + 0, 0, 1, VE_OK, 0, "dated-int dated-root", { 0 } }, + /* A trusted leaf ends a partial chain without a trusted cert, as + * OpenSSL's last resort, also above a self-signed cert */ + { "untrusted_root: trusted leaf", + "dated-int", NULL, "dated-root", "dated-int", NULL, + 0, 0, 0, VE_SELF, 1, NULL, { 0 } }, + { "untrusted_root: trusted leaf, partial chain", + "dated-int", NULL, "dated-root", "dated-int", NULL, + VO_PARTIAL, 0, 1, VE_OK, 0, "dated-int dated-root", { 0 } }, + + /* A trusted self-issued cert that is not self-signed is not a root. + * expired-root-link has expired-root's name and a new key. The chain + * goes on to expired-root, out of date now, and its dates are checked at + * the verification time. */ + { "selfissued_dates: link as the leaf", + "expired-root", NULL, NULL, "expired-root-link", NULL, + 0, 0, 0, VE_EXPIRED, 1, "expired-root-link expired-root", { 0 } }, + { "selfissued_dates: link as the leaf, 2005", + "expired-root", NULL, NULL, "expired-root-link", NULL, + VO_T2005, 0, 0, VE_NOTYET, 1, NULL, { 0 } }, + { "selfissued_dates: link as the leaf, 2015", + "expired-root", NULL, NULL, "expired-root-link", NULL, + VO_T2015, 0, 1, VE_OK, 0, "expired-root-link expired-root", { 0 } }, + { "selfissued_dates: link trusted, 2015", + "expired-root expired-root-link", NULL, NULL, + "expired-root-link-leaf", NULL, + VO_T2015, 0, 1, VE_OK, 0, + "expired-root-link-leaf expired-root-link expired-root", { 0 } }, + { "selfissued_dates: link trusted", + "expired-root expired-root-link", NULL, NULL, + "expired-root-link-leaf", NULL, + 0, 0, 0, VE_EXPIRED, 2, NULL, { 0 } }, + /* A valid root of the name without key ids did not sign the link. It is + * taken by name as it is valid now: VE_SIG at depth 1. */ + { "selfissued_dates: valid nokid twin of the root", + "expired-root expired-root-link expired-root-nokid", NULL, NULL, + "expired-root-link-leaf", NULL, + 0, 0, 0, VE_SIG, 1, + "expired-root-link-leaf expired-root-link expired-root-nokid", + { 0 } }, + { "selfissued_dates: valid nokid twin of the root, 2015", + "expired-root expired-root-link expired-root-nokid", NULL, NULL, + "expired-root-link-leaf", NULL, + VO_T2015, 0, 1, VE_OK, 0, + "expired-root-link-leaf expired-root-link expired-root", { 0 } }, + /* Alone, the link out of date ends a partial chain the callback + * accepts. Its dates are not checked then. */ + { "selfissued_dates: old link alone", + "expired-root-old-link", NULL, NULL, "expired-root-link-leaf", NULL, + 0, VA_ALL, 1, VE_ISSUER, 0, NULL, { VE_ISSUER, 1 } }, +#endif + +#if defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_EXT) && \ + !defined(NO_SHA256) && defined(USE_CERT_BUFFERS_2048) && \ + !defined(IGNORE_NAME_CONSTRAINTS) + /* The names of every cert meet the name constraints of the certs above + * it, the anchor's too: nc-ca permits only the email addresses of + * .wolfssl.com */ + { "name_constraints: email permitted", + "nc-ca", NULL, NULL, "nc-leaf", NULL, + 0, 0, 1, VE_OK, 0, "nc-leaf nc-ca", { 0 } }, + { "name_constraints: email not permitted", + "nc-ca", NULL, NULL, "nc-leaf-bad", NULL, + 0, 0, 0, VE_NCPERM, 0, NULL, { 0 } }, + { "name_constraints: callback accepts", + "nc-ca", NULL, NULL, "nc-leaf-bad", NULL, + 0, VA_ALL, 1, VE_NCPERM, 0, "nc-leaf-bad nc-ca", { VE_NCPERM, 0 } }, +#if !defined(NO_TLS) && !defined(NO_WOLFSSL_CLIENT) && \ + defined(WOLFSSL_SIGNER_DER_CERT) + { "name_constraints: CA of an SSL_CTX", + "nc-ca", NULL, NULL, "nc-leaf-bad", NULL, + VO_SSLCTX, VA_ALL, 1, VE_NCPERM, 0, "nc-leaf-bad nc-ca", + { VE_NCPERM, 0 } }, +#endif + /* The CN of the leaf, CA or not, meets the DNS constraints when it has + * no dNSName SAN: ncdns-ca permits .example.com but .blocked.example.com */ + { "name_constraints: CA leaf CN permitted", + "ncdns-ca", NULL, NULL, "ncdns-leaf", NULL, + 0, 0, 1, VE_OK, 0, "ncdns-leaf ncdns-ca", { 0 } }, + { "name_constraints: CA leaf CN not permitted", + "ncdns-ca", NULL, NULL, "ncdns-leaf-bad", NULL, + 0, 0, 0, VE_NCPERM, 0, NULL, { 0 } }, + { "name_constraints: CA leaf CN excluded", + "ncdns-ca", NULL, NULL, "ncdns-leaf-excl", NULL, + 0, 0, 0, VE_NCEXCL, 0, NULL, { 0 } }, +#endif + +#if defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_EXT) && \ + !defined(NO_SHA256) && defined(USE_CERT_BUFFERS_2048) && \ + !defined(NO_ASN_TIME) && !defined(ALLOW_INVALID_CERTSIGN) + /* Without X509_V_FLAG_TRUSTED_FIRST the untrusted twin-bad, a CA without + * keyCertSign, issues the leaf. twin-good is the same CA, trusted, with + * keyCertSign. Once the callback accepts VE_CA, VE_CERTSIGN is reported + * at depth 1, so a callback that accepts VE_CA only rejects. */ + { "no_keycertsign: callback accepts", + "ca twin-good", NULL, "twin-bad", "twin-leaf", NULL, + VO_XMLSEC, VA_ALL, 1, VE_CERTSIGN, 0, "twin-leaf twin-bad ca", + { VE_CA, 1, VE_CERTSIGN, 1 } }, + { "no_keycertsign: callback accepts VE_CA only", + "ca twin-good", NULL, "twin-bad", "twin-leaf", NULL, + VO_XMLSEC, VA_CA, 0, VE_CERTSIGN, 1, "twin-leaf twin-bad ca", + { VE_CA, 1, VE_CERTSIGN, 1 } }, +#ifdef X509_VFY_GEN_CRLS + /* nocrlsign has keyUsage keyCertSign only. Its CRL nocrlsign-revoked, + * listing nocrlsign-leaf, is reported. As in OpenSSL, once that is + * accepted, the CRL is used. */ + { "crl_sign: issuer without cRLSign", + "ca", NULL, "nocrlsign", "nocrlsign-leaf", "+nocrlsign-revoked", + VO_C_CRL, 0, 0, VE_CRLKU, 0, NULL, { 0 } }, + { "crl_sign: callback accepts a missing CRL", + "ca", NULL, "nocrlsign", "nocrlsign-leaf", "+nocrlsign-revoked", + VO_C_CRL, VA_NOCRL, 0, VE_CRLKU, 0, NULL, { VE_CRLKU, 0 } }, + { "crl_sign: callback accepts it", + "ca", NULL, "nocrlsign", "nocrlsign-leaf", "+nocrlsign-revoked", + VO_C_CRL, VA_CRLKU, 0, VE_REVOKED, 0, NULL, + { VE_CRLKU, 0, VE_REVOKED, 0 } }, + { "crl_sign: callback accepts it, store CRLs", + "ca", NULL, "nocrlsign", "nocrlsign-leaf", "ca-empty nocrlsign-revoked", + VO_CRL_ALL, VA_CRLKU, 0, VE_REVOKED, 0, NULL, + { VE_CRLKU, 0, VE_REVOKED, 0 } }, + /* As OpenSSL's check_crl(), cRLSign before the CRL dates */ + { "crl_sign: stale CRL", + "ca", NULL, "nocrlsign", "nocrlsign-leaf", "+nocrlsign-stale-empty", + VO_C_CRL, 0, 0, VE_CRLKU, 0, NULL, { 0 } }, + { "crl_sign: stale CRL, callback accepts both, store CRLs", + "ca", NULL, "nocrlsign", "nocrlsign-leaf", + "ca-empty nocrlsign-stale-empty", + VO_CRL_ALL, VA_CRLKU | VA_CRLEXP, 1, VE_CRLEXP, 0, NULL, + { VE_CRLKU, 0, VE_CRLEXP, 0 } }, + { "crl_sign: stale CRL, callback accepts both", + "ca", NULL, "nocrlsign", "nocrlsign-leaf", "+nocrlsign-stale-empty", + VO_C_CRL, VA_CRLKU | VA_CRLEXP, 1, VE_CRLEXP, 0, NULL, + { VE_CRLKU, 0, VE_CRLEXP, 0 } }, +#endif + /* pl0-notca is not a CA. As in OpenSSL, it counts against the path + * length of pl0-ca, of pathlen:0, also once its VE_CA is accepted. */ +#ifndef WOLFSSL_X509_STORE_ALLOW_NON_CA_INTERMEDIATE + { "path_len: not a CA, callback accepts VE_CA", + "ca", NULL, "pl0-ca pl0-notca", "pl0-notca-leaf", NULL, + 0, VA_CA, 0, VE_PATHLEN, 2, NULL, { VE_CA, 1, VE_PATHLEN, 2 } }, +#else + { "path_len: not a CA", + "ca", NULL, "pl0-ca pl0-notca", "pl0-notca-leaf", NULL, + 0, 0, 0, VE_PATHLEN, 2, NULL, { 0 } }, +#endif +#endif +}; + +/* Files of the names not in TA_CERT_DIR */ +static const struct { + const char* name; + const char* file; +} x509VfyFiles[] = { + { "ca", "./certs/ca-cert.pem" }, + { "int1", "./certs/intermediate/ca-int-cert.pem" }, + { "int2", "./certs/intermediate/ca-int2-cert.pem" }, + { "server-int", "./certs/intermediate/server-int-cert.pem" }, + { "server", "./certs/server-cert.pem" }, + { "ca-ecc", "./certs/ca-ecc-cert.pem" }, + { "int1-ecc", "./certs/intermediate/ca-int-ecc-cert.pem" }, + { "int2-ecc", "./certs/intermediate/ca-int2-ecc-cert.pem" }, + { "server-int-ecc", "./certs/intermediate/server-int-ecc-cert.pem" }, + { "nca-ca", "./certs/intermediate/ca_false_intermediate/test_ca.pem" }, + { "nca-int", + "./certs/intermediate/ca_false_intermediate/test_int_not_cacert.pem" }, + { "nca-leaf", + "./certs/intermediate/ca_false_intermediate/test_sign_bynoca_srv.pem" }, + { "ca-int-crl", "./certs/crl/ca-int.pem" }, + { "nc-ca", "./certs/test/cert-ext-nc.pem" }, + { "ncdns-ca", "./certs/test/cert-ext-ncmulti.pem" }, + { "pl0-int", "./certs/test-pathlen/chainF-ICA2-pathlen0.pem" }, + { "pl0-sub", "./certs/test-pathlen/chainF-ICA1-pathlen1.pem" }, + { "pl0-leaf", "./certs/test-pathlen/chainF-entity.pem" } +}; + +/* The certs by name, loaded once */ +#define X509_VFY_NAME_SZ 32 +static struct { + char name[X509_VFY_NAME_SZ]; + X509* x509; +} x509VfyCerts[96]; +static int x509VfyCertsNum = 0; + +/* What the verify callback saw */ +static int x509VfyAccept; +static struct { + int err; + int depth; + X509* cert; +} x509VfyLog[4]; +static int x509VfyLogNum; + +/* Copies the next space separated name of *list to name. Returns 0 when + * there is none. */ +static int x509_vfy_next(const char** list, char* name) +{ + const char* p = *list; + int n = 0; + + if (p == NULL) + return 0; + while (*p == ' ') + p++; + while (*p != '\0' && *p != ' ' && n < X509_VFY_NAME_SZ - 1) + name[n++] = *p++; + name[n] = '\0'; + *list = p; + return n > 0; +} + +/* Writes the file of a cert or CRL name to path */ +static void x509_vfy_path(const char* name, const char* suffix, char* path, + int pathSz) +{ + char base[X509_VFY_NAME_SZ]; + size_t i; + int n = 0; + + while (name[n] != '\0' && name[n] != '#' && n < X509_VFY_NAME_SZ - 1) { + base[n] = name[n]; + n++; + } + base[n] = '\0'; + for (i = 0; i < XELEM_CNT(x509VfyFiles); i++) { + if (XSTRCMP(base, x509VfyFiles[i].name) == 0) { + XSNPRINTF(path, (size_t)pathSz, "%s", x509VfyFiles[i].file); + return; + } + } + XSNPRINTF(path, (size_t)pathSz, "%s%s%s", TA_CERT_DIR, base, suffix); +} + +/* Keeps x509 under name */ +static int x509_vfy_keep(const char* name, X509* x509) +{ + if (x509 == NULL || x509VfyCertsNum == (int)XELEM_CNT(x509VfyCerts)) + return 0; + XSTRNCPY(x509VfyCerts[x509VfyCertsNum].name, name, X509_VFY_NAME_SZ - 1); + x509VfyCerts[x509VfyCertsNum].name[X509_VFY_NAME_SZ - 1] = '\0'; + x509VfyCerts[x509VfyCertsNum].x509 = x509; + x509VfyCertsNum++; + return 1; +} + +/* The cert of name, loaded on first use. NULL on failure. */ +static X509* x509_vfy_cert(const char* name) +{ + char path[160]; + X509* x509; + int i; + + for (i = 0; i < x509VfyCertsNum; i++) { + if (XSTRCMP(x509VfyCerts[i].name, name) == 0) + return x509VfyCerts[i].x509; + } + x509_vfy_path(name, "-cert.pem", path, (int)sizeof(path)); + x509 = X509_load_certificate_file(path, SSL_FILETYPE_PEM); + if (!x509_vfy_keep(name, x509)) { + X509_free(x509); + x509 = NULL; + } + return x509; +} + +#ifdef X509_VFY_GEN_CRLS +/* Generated CRLs by name, as DER */ +static struct { + char name[X509_VFY_NAME_SZ]; + unsigned char* der; + int derSz; +} x509VfyCrls[12]; +static int x509VfyCrlsNum = 0; + +/* A new copy of the generated CRL of name, NULL when there is none */ +static X509_CRL* x509_vfy_gen_crl(const char* name) +{ + const unsigned char* p; + int i; + + for (i = 0; i < x509VfyCrlsNum; i++) { + if (XSTRCMP(x509VfyCrls[i].name, name) == 0) { + p = x509VfyCrls[i].der; + return d2i_X509_CRL(NULL, &p, x509VfyCrls[i].derSz); + } + } + return NULL; +} +#endif + +static void x509_vfy_free_certs(void) +{ + int i; + + for (i = 0; i < x509VfyCertsNum; i++) + X509_free(x509VfyCerts[i].x509); + x509VfyCertsNum = 0; +#ifdef X509_VFY_GEN_CRLS + for (i = 0; i < x509VfyCrlsNum; i++) + XFREE(x509VfyCrls[i].der, NULL, DYNAMIC_TYPE_OPENSSL); + x509VfyCrlsNum = 0; +#endif +} + +/* Pushes the certs of list on sk. Returns 1 on success. */ +static int x509_vfy_push(STACK_OF(X509)* sk, const char* list) +{ + char name[X509_VFY_NAME_SZ]; + X509* x509; + + while (x509_vfy_next(&list, name)) { + if ((x509 = x509_vfy_cert(name)) == NULL || + sk_X509_push(sk, x509) <= 0) + return 0; + } + return 1; +} + +/* Returns 1 when sk holds the certs of list in order: the same objects when + * same is set, else equal ones. */ +static int x509_vfy_match(STACK_OF(X509)* sk, const char* list, int same) +{ + char name[X509_VFY_NAME_SZ]; + X509* x509; + X509* x509Sk; + int i = 0; + + while (x509_vfy_next(&list, name)) { + if (i >= sk_X509_num(sk) || (x509 = x509_vfy_cert(name)) == NULL) + return 0; + x509Sk = sk_X509_value(sk, i); + if (same ? (x509Sk != x509) : (X509_cmp(x509Sk, x509) != 0)) + return 0; + i++; + } + return i == sk_X509_num(sk); +} + +static int x509_vfy_cb(int ok, X509_STORE_CTX* ctx) +{ + int err = X509_STORE_CTX_get_error(ctx); + + if (!ok) { + if (x509VfyLogNum < (int)XELEM_CNT(x509VfyLog)) { + x509VfyLog[x509VfyLogNum].err = err; + x509VfyLog[x509VfyLogNum].depth = + X509_STORE_CTX_get_error_depth(ctx); + x509VfyLog[x509VfyLogNum].cert = + X509_STORE_CTX_get_current_cert(ctx); + } + x509VfyLogNum++; + ok = (x509VfyAccept & VA_ALL) || + ((x509VfyAccept & VA_ISSUER) && err == VE_ISSUER) || + ((x509VfyAccept & VA_LOCAL) && err == VE_LOCAL) || + ((x509VfyAccept & VA_SELF) && + (err == VE_SELF0 || err == VE_SELF)) || + ((x509VfyAccept & VA_DATES) && + (err == VE_NOTYET || err == VE_EXPIRED)) || + ((x509VfyAccept & VA_CA) && err == VE_CA) || + ((x509VfyAccept & VA_KEYSIZE) && err == VE_KEYSIZE) || + ((x509VfyAccept & VA_NOCRL) && err == VE_NOCRL) || + ((x509VfyAccept & VA_CRLKU) && err == VE_CRLKU) || + ((x509VfyAccept & VA_CRLEXP) && err == VE_CRLEXP); + } + return ok; +} + +#ifndef NO_ASN_TIME +/* The current time in 1999, before the dated certs */ +static time_t x509_vfy_time_1999(time_t* t) +{ + time_t now = (time_t)915148800; + + if (t != NULL) + *t = now; + return now; +} +#endif + +/* nca-leaf with a broken signature, as nca-leaf-badsig */ +static int x509_vfy_gen_badsig(void) +{ + X509* x509 = x509_vfy_cert("nca-leaf"); + X509* bad = NULL; + unsigned char* der = NULL; + const unsigned char* p; + int derSz; + + if (x509 != NULL && (derSz = i2d_X509(x509, &der)) > 0) { + der[derSz - 1] ^= 0x01; + p = der; + bad = d2i_X509(NULL, &p, derSz); + } + XFREE(der, NULL, DYNAMIC_TYPE_OPENSSL); + if (!x509_vfy_keep("nca-leaf-badsig", bad)) { + X509_free(bad); + return 0; + } + return 1; +} + +#if defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_EXT) && \ + !defined(NO_SHA256) && defined(USE_CERT_BUFFERS_2048) && \ + ((!defined(NO_ASN_TIME) && !defined(ALLOW_INVALID_CERTSIGN)) || \ + !defined(IGNORE_NAME_CONSTRAINTS)) +/* Keeps the DER cert of der under name */ +static int x509_vfy_keep_der(const char* name, const byte* der, int derSz) +{ + X509* x509; + + if (derSz <= 0) + return 0; + x509 = d2i_X509(NULL, &der, derSz); + if (!x509_vfy_keep(name, x509)) { + X509_free(x509); + return 0; + } + return 1; +} +#endif + +#if defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_EXT) && \ + !defined(NO_SHA256) && defined(USE_CERT_BUFFERS_2048) && \ + !defined(NO_ASN_TIME) && !defined(ALLOW_INVALID_CERTSIGN) +/* Twin CAs of one name and key issued by ca-cert: twin-good with + * keyCertSign, twin-bad without. twin-bad issued twin-leaf. Also pl0-ca, of + * pathlen:0, issued by ca-cert, pl0-notca, not a CA, issued by it, and + * pl0-notca-leaf. nocrlsign, issued by ca-cert, may sign certs but not + * CRLs; it issued nocrlsign-leaf. */ +static int x509_vfy_gen_twins(void) +{ + EXPECT_DECLS; + WC_RNG rng; + RsaKey caKey, intKey, leafKey; + int rngI = 0, caI = 0, intI = 0, leafI = 0; + word32 idx; + byte* der = NULL; + byte* leafDer = NULL; + int sz = 0; + Cert cert; + + ExpectNotNull(der = (byte*)XMALLOC(FOURK_BUF, NULL, + DYNAMIC_TYPE_TMP_BUFFER)); + ExpectNotNull(leafDer = (byte*)XMALLOC(FOURK_BUF, NULL, + DYNAMIC_TYPE_TMP_BUFFER)); + ExpectIntEQ(wc_InitRng(&rng), 0); + if (EXPECT_SUCCESS()) rngI = 1; + ExpectIntEQ(wc_InitRsaKey(&caKey, NULL), 0); + if (EXPECT_SUCCESS()) caI = 1; + idx = 0; + ExpectIntEQ(wc_RsaPrivateKeyDecode(ca_key_der_2048, &idx, &caKey, + sizeof_ca_key_der_2048), 0); + ExpectIntEQ(wc_InitRsaKey(&intKey, NULL), 0); + if (EXPECT_SUCCESS()) intI = 1; + idx = 0; + ExpectIntEQ(wc_RsaPrivateKeyDecode(server_key_der_2048, &idx, &intKey, + sizeof_server_key_der_2048), 0); + ExpectIntEQ(wc_InitRsaKey(&leafKey, NULL), 0); + if (EXPECT_SUCCESS()) leafI = 1; + idx = 0; + ExpectIntEQ(wc_RsaPrivateKeyDecode(client_key_der_2048, &idx, &leafKey, + sizeof_client_key_der_2048), 0); + + if (EXPECT_SUCCESS()) { + sz = gen_ca_int_keyusage(der, FOURK_BUF, &intKey, &caKey, &rng, + "Twin Intermediate", "keyCertSign,cRLSign", 0); + } + ExpectIntEQ(x509_vfy_keep_der("twin-good", der, sz), 1); + if (EXPECT_SUCCESS()) { + sz = gen_ca_int_keyusage(der, FOURK_BUF, &intKey, &caKey, &rng, + "Twin Intermediate", "digitalSignature", 0); + } + ExpectIntEQ(x509_vfy_keep_der("twin-bad", der, sz), 1); + if (EXPECT_SUCCESS()) { + sz = gen_leaf_under_int(leafDer, FOURK_BUF, &leafKey, der, sz, + &intKey, &rng, "Leaf under twins"); + } + ExpectIntEQ(x509_vfy_keep_der("twin-leaf", leafDer, sz), 1); + + ExpectIntEQ(wc_InitCert(&cert), 0); + cert.isCA = 1; + cert.pathLen = 0; + cert.pathLenSet = 1; + cert.sigType = CTC_SHA256wRSA; + XSTRNCPY(cert.subject.commonName, "Pathlen 0 CA", CTC_NAME_SIZE - 1); + ExpectIntEQ(wc_SetSubjectKeyIdFromPublicKey(&cert, &intKey, NULL), 0); + ExpectIntEQ(wc_SetAuthKeyIdFromCert(&cert, ca_cert_der_2048, + (int)sizeof_ca_cert_der_2048), 0); + ExpectIntEQ(wc_SetIssuerBuffer(&cert, ca_cert_der_2048, + (int)sizeof_ca_cert_der_2048), 0); + ExpectIntGT(wc_MakeCert(&cert, der, FOURK_BUF, &intKey, NULL, &rng), 0); + if (EXPECT_SUCCESS()) { + sz = wc_SignCert(cert.bodySz, cert.sigType, der, FOURK_BUF, &caKey, + NULL, &rng); + } + ExpectIntEQ(x509_vfy_keep_der("pl0-ca", der, sz), 1); + if (EXPECT_SUCCESS()) { + sz = gen_leaf_under_int(leafDer, FOURK_BUF, &leafKey, der, sz, + &intKey, &rng, "Not a CA"); + } + ExpectIntEQ(x509_vfy_keep_der("pl0-notca", leafDer, sz), 1); + if (EXPECT_SUCCESS()) { + sz = gen_leaf_under_int(der, FOURK_BUF, &caKey, leafDer, sz, + &leafKey, &rng, "Leaf of not a CA"); + } + ExpectIntEQ(x509_vfy_keep_der("pl0-notca-leaf", der, sz), 1); + + if (EXPECT_SUCCESS()) { + sz = gen_ca_int_keyusage(der, FOURK_BUF, &intKey, &caKey, &rng, + "No CRL Sign CA", "keyCertSign", 0); + } + ExpectIntEQ(x509_vfy_keep_der("nocrlsign", der, sz), 1); + if (EXPECT_SUCCESS()) { + sz = gen_leaf_under_int(leafDer, FOURK_BUF, &leafKey, der, sz, + &intKey, &rng, "Leaf of no CRL Sign CA"); + } + ExpectIntEQ(x509_vfy_keep_der("nocrlsign-leaf", leafDer, sz), 1); + + if (rngI) wc_FreeRng(&rng); + if (caI) wc_FreeRsaKey(&caKey); + if (intI) wc_FreeRsaKey(&intKey); + if (leafI) wc_FreeRsaKey(&leafKey); + XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(leafDer, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return EXPECT_RESULT(); +} +#endif + +#if defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_EXT) && \ + !defined(NO_SHA256) && defined(USE_CERT_BUFFERS_2048) && \ + !defined(IGNORE_NAME_CONSTRAINTS) +/* Leaves of nc-ca, which permits only the email addresses of .wolfssl.com: + * nc-leaf with one, nc-leaf-bad with another. Leaves of ncdns-ca, CAs with a + * CN and no SAN: ncdns-leaf in .example.com, ncdns-leaf-bad outside it, + * ncdns-leaf-excl in the excluded .blocked.example.com. */ +static int x509_vfy_gen_nc(void) +{ + EXPECT_DECLS; + static const struct { + const char* name; + const char* ca; + int isCA; + const char* cn; + const char* email; + } leaves[] = { + { "nc-leaf", "nc-ca", 0, "NC Leaf", + "leaf@info.wolfssl.com" }, + { "nc-leaf-bad", "nc-ca", 0, "NC Leaf", + "leaf@info.example.com" }, + { "ncdns-leaf", "ncdns-ca", 1, "www.example.com", "" }, + { "ncdns-leaf-bad", "ncdns-ca", 1, "www.bank.com", "" }, + { "ncdns-leaf-excl", "ncdns-ca", 1, "www.blocked.example.com", "" } + }; + WC_RNG rng; + RsaKey caKey, leafKey; + int rngI = 0, caI = 0, leafI = 0; + word32 idx; + byte* der = NULL; + X509* ca = NULL; + const byte* caDer = NULL; + int caDerSz = 0; + Cert cert; + int sz = 0; + int i; + + ExpectNotNull(der = (byte*)XMALLOC(FOURK_BUF, NULL, + DYNAMIC_TYPE_TMP_BUFFER)); + ExpectIntEQ(wc_InitRng(&rng), 0); + if (EXPECT_SUCCESS()) rngI = 1; + ExpectIntEQ(wc_InitRsaKey(&caKey, NULL), 0); + if (EXPECT_SUCCESS()) caI = 1; + idx = 0; + ExpectIntEQ(wc_RsaPrivateKeyDecode(server_key_der_2048, &idx, &caKey, + sizeof_server_key_der_2048), 0); + ExpectIntEQ(wc_InitRsaKey(&leafKey, NULL), 0); + if (EXPECT_SUCCESS()) leafI = 1; + idx = 0; + ExpectIntEQ(wc_RsaPrivateKeyDecode(client_key_der_2048, &idx, &leafKey, + sizeof_client_key_der_2048), 0); + + for (i = 0; i < (int)XELEM_CNT(leaves) && EXPECT_SUCCESS(); i++) { + ExpectNotNull(ca = x509_vfy_cert(leaves[i].ca)); + ExpectNotNull(caDer = wolfSSL_X509_get_der(ca, &caDerSz)); + ExpectIntEQ(wc_InitCert(&cert), 0); + cert.isCA = leaves[i].isCA; + cert.sigType = CTC_SHA256wRSA; + XSTRNCPY(cert.subject.country, "US", CTC_NAME_SIZE - 1); + XSTRNCPY(cert.subject.commonName, leaves[i].cn, CTC_NAME_SIZE - 1); + XSTRNCPY(cert.subject.email, leaves[i].email, CTC_NAME_SIZE - 1); + ExpectIntEQ(wc_SetAuthKeyIdFromCert(&cert, caDer, caDerSz), 0); + ExpectIntEQ(wc_SetIssuerBuffer(&cert, caDer, caDerSz), 0); + ExpectIntGT(wc_MakeCert(&cert, der, FOURK_BUF, &leafKey, NULL, &rng), + 0); + if (EXPECT_SUCCESS()) { + sz = wc_SignCert(cert.bodySz, cert.sigType, der, FOURK_BUF, + &caKey, NULL, &rng); + } + ExpectIntEQ(x509_vfy_keep_der(leaves[i].name, der, sz), 1); + } + + if (rngI) wc_FreeRng(&rng); + if (caI) wc_FreeRsaKey(&caKey); + if (leafI) wc_FreeRsaKey(&leafKey); + XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return EXPECT_RESULT(); +} +#endif + +/* Adds the trusted certs of c to store */ +static int x509_vfy_add_trusted(const x509_vfy_case* c, X509_STORE* store, + SSL_CTX* sslCtx) +{ + EXPECT_DECLS; + const char* list = c->trusted; + char name[X509_VFY_NAME_SZ]; + char path[160]; + X509_LOOKUP* lookup = NULL; + + (void)sslCtx; + while (EXPECT_SUCCESS() && x509_vfy_next(&list, name)) { + x509_vfy_path(name, "-cert.pem", path, (int)sizeof(path)); + if (c->opts & VO_FILE) { + ExpectIntEQ(X509_STORE_load_locations(store, path, NULL), 1); + } +#if defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM) + else if (c->opts & VO_LOOKUP) { + if (lookup == NULL) { + ExpectNotNull(lookup = X509_STORE_add_lookup(store, + X509_LOOKUP_file())); + } + ExpectIntEQ(X509_LOOKUP_load_file(lookup, path, + X509_FILETYPE_PEM), 1); + } +#endif +#if !defined(NO_TLS) && !defined(NO_WOLFSSL_CLIENT) + else if (c->opts & VO_SSLCTX) { + ExpectIntEQ(SSL_CTX_load_verify_locations(sslCtx, path, NULL), + 1); + } +#endif + else { + ExpectIntEQ(X509_STORE_add_cert(store, x509_vfy_cert(name)), 1); + } + } + (void)lookup; + return EXPECT_RESULT(); +} + +#ifdef HAVE_CRL +/* Breaks the signature of *crl */ +static int x509_vfy_crl_badsig(X509_CRL** crl) +{ + X509_CRL* bad = NULL; + unsigned char* der = NULL; + const unsigned char* p; + int derSz; + + if ((derSz = i2d_X509_CRL(*crl, &der)) > 0) { + der[derSz - 1] ^= 0x01; + p = der; + bad = d2i_X509_CRL(NULL, &p, derSz); + } + XFREE(der, NULL, DYNAMIC_TYPE_OPENSSL); + if (bad == NULL) + return 0; + X509_CRL_free(*crl); + *crl = bad; + return 1; +} + +/* Adds the CRLs of c to store or, with a '+', to *crls. "-badsig" is + * the CRL of name with a broken signature. */ +static int x509_vfy_add_crls(const x509_vfy_case* c, X509_STORE* store, + STACK_OF(X509_CRL)** crls) +{ + EXPECT_DECLS; + const char* list = c->crls; + char name[X509_VFY_NAME_SZ]; + char path[160]; + XFILE fp = XBADFILE; + X509_CRL* crl = NULL; + int toCtx; + int badSig; + size_t len; + + while (EXPECT_SUCCESS() && x509_vfy_next(&list, name)) { + toCtx = (name[0] == '+'); + len = XSTRLEN(name); + badSig = len > 7 && XSTRCMP(name + len - 7, "-badsig") == 0; + if (badSig) + name[len - 7] = '\0'; + #ifdef X509_VFY_GEN_CRLS + crl = x509_vfy_gen_crl(name + toCtx); + #endif + if (crl == NULL) { + x509_vfy_path(name + toCtx, "-crl.pem", path, (int)sizeof(path)); + ExpectTrue((fp = XFOPEN(path, "rb")) != XBADFILE); + ExpectNotNull(crl = PEM_read_X509_CRL(fp, NULL, NULL, NULL)); + if (fp != XBADFILE) { + XFCLOSE(fp); + fp = XBADFILE; + } + } + if (badSig) { + ExpectIntEQ(x509_vfy_crl_badsig(&crl), 1); + } + if (!toCtx) { + ExpectIntEQ(X509_STORE_add_crl(store, crl), 1); + } + else { + if (*crls == NULL) { + ExpectNotNull(*crls = sk_X509_CRL_new_null()); + } + ExpectIntGT(sk_X509_CRL_push(*crls, crl), 0); + if (EXPECT_SUCCESS()) + crl = NULL; + } + X509_CRL_free(crl); + crl = NULL; } - if (skid != 0) { - XMEMSET(cert.skid, skid, KEYID_SIZE); - cert.skidSz = KEYID_SIZE; + return EXPECT_RESULT(); +} +#endif + +/* Runs the verification of c and checks its results */ +static int x509_vfy_run(const x509_vfy_case* c) +{ + EXPECT_DECLS; + X509* leaf = NULL; + X509_STORE* store = NULL; + X509_STORE_CTX* ctx = NULL; + X509_VERIFY_PARAM* vpm = NULL; + STACK_OF(X509)* untrusted = NULL; + STACK_OF(X509)* trusted = NULL; + STACK_OF(X509)* chain = NULL; +#ifdef HAVE_CRL + STACK_OF(X509_CRL)* crls = NULL; +#endif + SSL_CTX* sslCtx = NULL; + unsigned long flags = 0; + time_t t = 0; + int i; + int n; + + if (c->opts & VO_SSLCTX) { +#if !defined(NO_TLS) && !defined(NO_WOLFSSL_CLIENT) + ExpectNotNull(sslCtx = SSL_CTX_new(wolfSSLv23_client_method())); + /* As OpenSSL, load CAs unverified */ + SSL_CTX_set_verify(sslCtx, SSL_VERIFY_NONE, NULL); + ExpectNotNull(store = SSL_CTX_get_cert_store(sslCtx)); +#endif } - if (akid != 0) { - XMEMSET(cert.akid, akid, KEYID_SIZE); - cert.akidSz = KEYID_SIZE; + else { + ExpectNotNull(store = X509_STORE_new()); + } + if (c->opts & VO_S_NOTIME) { + ExpectIntEQ(X509_VERIFY_PARAM_set_flags(X509_STORE_get0_param(store), + X509_V_FLAG_NO_CHECK_TIME), 1); + } + if (c->opts & VO_S_STRICT) + flags |= X509_V_FLAG_X509_STRICT; + if (c->opts & VO_S_PARTIAL) + flags |= X509_V_FLAG_PARTIAL_CHAIN; + if (c->opts & VO_CRL) + flags |= X509_V_FLAG_CRL_CHECK; + if ((c->opts & VO_CRL_ALL) == VO_CRL_ALL) + flags |= X509_V_FLAG_CRL_CHECK_ALL; + if (flags != 0) { + ExpectIntEQ(X509_STORE_set_flags(store, flags), 1); + } +#ifndef NO_ASN_TIME + if (c->opts & VO_ADD1999) { + ExpectIntEQ(wc_SetTimeCb(x509_vfy_time_1999), 0); + } +#endif + if (c->trusted != NULL) { + ExpectIntEQ(x509_vfy_add_trusted(c, store, sslCtx), TEST_SUCCESS); + } +#ifndef NO_ASN_TIME + if (c->opts & VO_ADD1999) + wc_SetTimeCb(NULL); +#endif + if ((c->opts & VO_MINRSA) && store != NULL) + store->cm->minRsaKeySz = 4096 / 8; + if ((c->opts & VO_MINECC) && store != NULL) + store->cm->minEccKeySz = 384 / 8; +#ifdef HAVE_CRL + if (c->crls != NULL) { + ExpectIntEQ(x509_vfy_add_crls(c, store, &crls), TEST_SUCCESS); + } +#else + ExpectNull(c->crls); +#endif + if (c->untrusted != NULL) { + ExpectNotNull(untrusted = sk_X509_new_null()); + ExpectIntEQ(x509_vfy_push(untrusted, c->untrusted), 1); + } + if (c->stack != NULL) { + ExpectNotNull(trusted = sk_X509_new_null()); + ExpectIntEQ(x509_vfy_push(trusted, c->stack), 1); } - der = (byte*)XMALLOC(FOURK_BUF, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (der != NULL && wc_MakeCert(&cert, der, FOURK_BUF, key, NULL, rng) > 0) - derSz = wc_SignCert(cert.bodySz, cert.sigType, der, FOURK_BUF, signKey, - NULL, rng); - if (derSz > 0) { - p = der; - x509 = d2i_X509(NULL, &p, derSz); + ExpectNotNull(leaf = x509_vfy_cert(c->leaf)); + ExpectNotNull(ctx = X509_STORE_CTX_new()); + ExpectIntEQ(X509_STORE_CTX_init(ctx, store, leaf, untrusted), 1); + if (EXPECT_SUCCESS()) { + if (trusted != NULL) + X509_STORE_CTX_trusted_stack(ctx, trusted); + switch (c->opts & VO_TIME) { + case VO_T2005: t = (time_t)1104537600; break; + case VO_T2015: t = (time_t)1420070400; break; + case VO_T2025: t = (time_t)1735689600; break; + default: break; + } + if (c->opts & VO_XMLSEC) { + ExpectNotNull(vpm = X509_VERIFY_PARAM_new()); + if (vpm != NULL) { + X509_VERIFY_PARAM_set_depth(vpm, 9); + if (t != 0) + X509_VERIFY_PARAM_set_time(vpm, t); + X509_STORE_CTX_set0_param(ctx, vpm); + } + } + else if (t != 0) { + X509_STORE_CTX_set_time(ctx, 0, t); + } + flags = 0; + if (c->opts & VO_PARTIAL) + flags |= X509_V_FLAG_PARTIAL_CHAIN; + if (c->opts & VO_STRICT) + flags |= X509_V_FLAG_X509_STRICT; + if (c->opts & VO_NOTIME) + flags |= X509_V_FLAG_NO_CHECK_TIME; + if (c->opts & VO_C_CRL) + flags |= X509_V_FLAG_CRL_CHECK; + if ((c->opts & VO_C_CRL_ALL) == VO_C_CRL_ALL) + flags |= X509_V_FLAG_CRL_CHECK_ALL; + if (flags != 0) + X509_STORE_CTX_set_flags(ctx, flags); + if (c->opts & VO_DEPTH0) + X509_STORE_CTX_set_depth(ctx, 0); + if (c->opts & VO_DEPTH1) + X509_STORE_CTX_set_depth(ctx, 1); +#ifdef HAVE_CRL + if (crls != NULL) { + X509_STORE_CTX_set0_crls(ctx, crls); + } +#endif + x509VfyAccept = c->cb; + x509VfyLogNum = 0; + if (c->cb != 0) + X509_STORE_CTX_set_verify_cb(ctx, x509_vfy_cb); + } + + ExpectIntEQ(X509_verify_cert(ctx), c->ret); + ExpectIntEQ(X509_STORE_CTX_get_error(ctx), c->err); + if (c->err != VE_OK) { + ExpectIntEQ(X509_STORE_CTX_get_error_depth(ctx), c->depth); + } + if (EXPECT_SUCCESS()) + chain = X509_STORE_CTX_get0_chain(ctx); + if (c->chain != NULL) { + ExpectNotNull(chain); + ExpectIntEQ(x509_vfy_match(chain, c->chain, 0), 1); + } + if (c->cb != 0) { + for (n = 0; n < 3 && c->cbLog[2 * n] != 0; n++) { + ExpectIntLT(n, x509VfyLogNum); + ExpectIntEQ(x509VfyLog[n].err, c->cbLog[2 * n]); + ExpectIntEQ(x509VfyLog[n].depth, c->cbLog[2 * n + 1]); + } + ExpectIntEQ(x509VfyLogNum, n); + /* The current cert of each error is the cert at its depth */ + for (i = 0; i < n && chain != NULL && EXPECT_SUCCESS(); i++) { + if (x509VfyLog[i].depth < sk_X509_num(chain)) { + ExpectIntEQ(X509_cmp(x509VfyLog[i].cert, + sk_X509_value(chain, x509VfyLog[i].depth)), 0); + } + } + } + /* The caller's stacks are left as they were */ + if (untrusted != NULL) { + ExpectIntEQ(x509_vfy_match(untrusted, c->untrusted, 1), 1); + } + if (trusted != NULL) { + ExpectIntEQ(x509_vfy_match(trusted, c->stack, 1), 1); + } + + X509_STORE_CTX_free(ctx); +#if !defined(NO_TLS) && !defined(NO_WOLFSSL_CLIENT) + if (sslCtx != NULL) + SSL_CTX_free(sslCtx); + else +#endif + X509_STORE_free(store); + sk_X509_free(untrusted); + sk_X509_free(trusted); +#ifdef HAVE_CRL + sk_X509_CRL_pop_free(crls, X509_CRL_free); +#endif + return EXPECT_RESULT(); +} +#endif + +#ifdef X509_VFY_GEN_CRLS +/* CRLs of ca: ca-stale and ca-stale-empty out of date for a month, + * ca-revoked, ca-empty and ca-self current, ca-nyv-empty valid in a month. + * ca-stale and ca-revoked list server, ca-self lists ca. ca-empty-old is a + * day older than ca-empty. ca-otherkey and ca-otherkey-old, a day older, are + * signed with another key. The current ones have the same thisUpdate. + * nocrlsign-revoked of nocrlsign lists nocrlsign-leaf. nocrlsign-stale-empty + * is out of date for a month. */ +static int x509_vfy_gen_crls(void) +{ + EXPECT_DECLS; + static const struct { + const char* name; + const char* issuer; + const char* key; /* of the issuer */ + int days; /* from now to the next update */ + const char* revoked; /* NULL: none */ + } crls[] = { + { "ca-stale", "ca", "./certs/ca-key.pem", -30, "server" }, + { "ca-stale-empty", "ca", "./certs/ca-key.pem", -30, NULL }, + { "ca-revoked", "ca", "./certs/ca-key.pem", 30, "server" }, + { "ca-empty", "ca", "./certs/ca-key.pem", 30, NULL }, + { "ca-nyv-empty", "ca", "./certs/ca-key.pem", 60, NULL }, + { "ca-self", "ca", "./certs/ca-key.pem", 30, "ca" }, + { "ca-empty-old", "ca", "./certs/ca-key.pem", 29, NULL }, + { "ca-otherkey", "ca", "./certs/server-key.pem", 30, NULL }, + { "ca-otherkey-old", "ca", "./certs/server-key.pem", 29, NULL }, + #if defined(WOLFSSL_CERT_EXT) && !defined(NO_SHA256) && \ + defined(USE_CERT_BUFFERS_2048) && !defined(ALLOW_INVALID_CERTSIGN) + { "nocrlsign-revoked", "nocrlsign", "./certs/server-key.pem", 30, + "nocrlsign-leaf" }, + { "nocrlsign-stale-empty", "nocrlsign", "./certs/server-key.pem", -30, + NULL } + #endif + }; + EVP_PKEY* key = NULL; + X509_CRL* crl = NULL; + ASN1_TIME t; + XFILE fp = XBADFILE; + const unsigned char* der = NULL; + int derSz = 0; + time_t now = XTIME(NULL); + size_t i; + + for (i = 0; i < XELEM_CNT(crls) && EXPECT_SUCCESS(); i++) { + ExpectTrue((fp = XFOPEN(crls[i].key, "rb")) != XBADFILE); + if (fp != XBADFILE) { + ExpectNotNull(key = PEM_read_PrivateKey(fp, NULL, NULL, NULL)); + XFCLOSE(fp); + } + ExpectNotNull(crl = wolfSSL_X509_CRL_new()); + ExpectIntEQ(wolfSSL_X509_CRL_set_issuer_name(crl, + X509_get_subject_name(x509_vfy_cert(crls[i].issuer))), + WOLFSSL_SUCCESS); + XMEMSET(&t, 0, sizeof(t)); + ExpectNotNull(ASN1_TIME_adj(&t, now, crls[i].days - 30, 0)); + ExpectIntEQ(wolfSSL_X509_CRL_set_lastUpdate(crl, &t), + WOLFSSL_SUCCESS); + ExpectNotNull(ASN1_TIME_adj(&t, now, crls[i].days, 0)); + ExpectIntEQ(wolfSSL_X509_CRL_set_nextUpdate(crl, &t), + WOLFSSL_SUCCESS); + if (crls[i].revoked != NULL) { + ExpectNotNull(der = wolfSSL_X509_get_der( + x509_vfy_cert(crls[i].revoked), &derSz)); + ExpectIntEQ(wolfSSL_X509_CRL_add_revoked_cert(crl, der, derSz), + WOLFSSL_SUCCESS); + } + ExpectIntEQ(wolfSSL_X509_CRL_sign(crl, key, wolfSSL_EVP_sha256()), + WOLFSSL_SUCCESS); + if (EXPECT_SUCCESS()) { + XSTRNCPY(x509VfyCrls[i].name, crls[i].name, + X509_VFY_NAME_SZ - 1); + x509VfyCrls[i].der = NULL; + x509VfyCrls[i].derSz = i2d_X509_CRL(crl, &x509VfyCrls[i].der); + x509VfyCrlsNum = (int)i + 1; + } + ExpectIntGT(x509VfyCrls[i].derSz, 0); + X509_CRL_free(crl); + crl = NULL; + EVP_PKEY_free(key); + key = NULL; + } + return EXPECT_RESULT(); +} +#endif + +/* X509_verify_cert() on the chains of x509VfyCases, each compared with + * OpenSSL 3.0. A comment tells where OpenSSL gives another result. */ +int test_X509_verify_cert_chains(void) +{ + EXPECT_DECLS; +#if defined(OPENSSL_EXTRA) && !defined(NO_RSA) && !defined(NO_CERTS) && \ + !defined(NO_FILESYSTEM) + X509_STORE* store = NULL; + X509_STORE_CTX* ctx = NULL; + size_t i; + int failed = 0; + + ExpectIntEQ(x509_vfy_gen_badsig(), 1); +#if defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_EXT) && \ + !defined(NO_SHA256) && defined(USE_CERT_BUFFERS_2048) && \ + !defined(NO_ASN_TIME) && !defined(ALLOW_INVALID_CERTSIGN) + ExpectIntEQ(x509_vfy_gen_twins(), TEST_SUCCESS); +#endif +#if defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_EXT) && \ + !defined(NO_SHA256) && defined(USE_CERT_BUFFERS_2048) && \ + !defined(IGNORE_NAME_CONSTRAINTS) + ExpectIntEQ(x509_vfy_gen_nc(), TEST_SUCCESS); +#endif +#ifdef X509_VFY_GEN_CRLS + ExpectIntEQ(x509_vfy_gen_crls(), TEST_SUCCESS); +#endif + + /* A context has X509_V_FLAG_TRUSTED_FIRST: VO_XMLSEC replaces its + * param */ + ExpectNotNull(store = X509_STORE_new()); + ExpectNotNull(ctx = X509_STORE_CTX_new()); + ExpectIntEQ(X509_STORE_CTX_init(ctx, store, x509_vfy_cert("leaf"), NULL), + 1); + ExpectIntNE(X509_VERIFY_PARAM_get_flags(X509_STORE_CTX_get0_param(ctx)) & + X509_V_FLAG_TRUSTED_FIRST, 0); + X509_STORE_CTX_free(ctx); + X509_STORE_free(store); + + for (i = 0; i < XELEM_CNT(x509VfyCases) && EXPECT_SUCCESS(); i++) { + if (x509_vfy_run(&x509VfyCases[i]) != TEST_SUCCESS) { + fprintf(stderr, "X509_verify_cert() case %d failed: %s\n", + (int)i, x509VfyCases[i].name); + failed++; + } + } + ExpectIntEQ(failed, 0); + x509_vfy_free_certs(); +#endif + return EXPECT_RESULT(); +} + +#if defined(OPENSSL_EXTRA) && !defined(NO_RSA) && !defined(NO_CERTS) && \ + !defined(NO_FILESYSTEM) && defined(USE_WOLFSSL_MEMORY) && \ + !defined(WOLFSSL_STATIC_MEMORY) && !defined(WOLFSSL_NO_MALLOC) && \ + !defined(WOLFSSL_DEBUG_MEMORY) +#define TEST_X509_VERIFY_CERT_OOM +static wolfSSL_Malloc_cb x509VfyOomMalloc = NULL; +static wolfSSL_Realloc_cb x509VfyOomRealloc = NULL; +static int x509VfyOomNum = 0; +static int x509VfyOomAt = 0; + +/* Fails allocation number x509VfyOomAt */ +static void* x509_vfy_oom_malloc(size_t size) +{ + if (++x509VfyOomNum == x509VfyOomAt) + return NULL; + if (x509VfyOomMalloc != NULL) + return x509VfyOomMalloc(size); + return malloc(size); +} + +static void* x509_vfy_oom_realloc(void* ptr, size_t size) +{ + if (++x509VfyOomNum == x509VfyOomAt) + return NULL; + if (x509VfyOomRealloc != NULL) + return x509VfyOomRealloc(ptr, size); + return realloc(ptr, size); +} + +/* Returns 1 when verifying a signature with the RSA key of ca allocates */ +static int x509_vfy_oom_rsa_allocs(X509* ca, wolfSSL_Free_cb freeCb) +{ + RsaKey* key = NULL; + byte sig[256]; + byte* out = NULL; + word32 idx = 0; + int ret = 0; + + key = (RsaKey*)XMALLOC(sizeof(RsaKey), NULL, DYNAMIC_TYPE_RSA); + if (key != NULL && wc_InitRsaKey(key, NULL) == 0) { + if (wc_RsaPublicKeyDecode(ca->pubKey.buffer, &idx, key, + ca->pubKey.length) == 0 && + wc_RsaEncryptSize(key) == (int)sizeof(sig)) { + XMEMSET(sig, 1, sizeof(sig)); + sig[0] = 0; + x509VfyOomNum = 0; + x509VfyOomAt = 0; + if (wolfSSL_SetAllocators(x509_vfy_oom_malloc, freeCb, + x509_vfy_oom_realloc) == 0) { + (void)wc_RsaSSL_VerifyInline(sig, sizeof(sig), &out, key); + (void)wolfSSL_SetAllocators(x509VfyOomMalloc, freeCb, + x509VfyOomRealloc); + ret = x509VfyOomNum > 0; + } + } + wc_FreeRsaKey(key); + } + XFREE(key, NULL, DYNAMIC_TYPE_RSA); + return ret; +} +#endif + +/* X509_verify_cert() rejects whichever allocation fails: a chain without a + * trusted issuer, a chain through a CA of an SSL_CTX of pathlen:0, a cert + * that a CRL of X509_STORE_CTX_set0_crls revokes while a CRL of the store + * does not, and an expired self-signed CA of an SSL_CTX. A callback that + * accepts every error cannot accept a failed allocation, and some is + * reported as X509_V_ERR_OUT_OF_MEM. Where verifying an RSA signature + * allocates, a failure there is a bad signature, as in OpenSSL: then only + * that a failing chain still fails without a callback is checked. */ +int test_X509_verify_cert_oom(void) +{ + EXPECT_DECLS; +#ifdef TEST_X509_VERIFY_CERT_OOM + static const struct { + const char* leaf; + const char* untrusted; /* NULL: none */ + const char* sslCtxCa; /* with ca-cert, the CAs of an SSL_CTX */ + const char* storeCrl; + const char* ctxCrl; + int err; + } cases[] = { + { "./certs/intermediate/server-int-cert.pem", NULL, NULL, NULL, NULL, + X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY }, + #if !defined(NO_TLS) && !defined(NO_WOLFSSL_CLIENT) && \ + defined(WOLFSSL_SIGNER_DER_CERT) + { "./certs/test-pathlen/chainF-entity.pem", + "./certs/test-pathlen/chainF-ICA1-pathlen1.pem", + "./certs/test-pathlen/chainF-ICA2-pathlen0.pem", NULL, NULL, + X509_V_ERR_PATH_LENGTH_EXCEEDED }, + #endif + #ifdef HAVE_CRL + { "./certs/server-cert.pem", NULL, NULL, + "./certs/crl/extra-crls/ca-int-cert-revoked.pem", + "./certs/crl/extra-crls/general-server-crl.pem", + X509_V_ERR_CERT_REVOKED }, + #endif + #if !defined(NO_TLS) && !defined(NO_WOLFSSL_CLIENT) && \ + defined(WOLFSSL_SIGNER_DER_CERT) + { TA_CERT_DIR "expired-root-cert.pem", NULL, + TA_CERT_DIR "expired-root-cert.pem", NULL, NULL, + X509_V_ERR_CERT_HAS_EXPIRED }, + #endif + }; + X509_STORE* store = NULL; + X509_STORE_CTX* ctx = NULL; + X509* ca = NULL; + X509* leaf = NULL; + X509* inter = NULL; + STACK_OF(X509)* untrusted = NULL; +#if !defined(NO_TLS) && !defined(NO_WOLFSSL_CLIENT) + SSL_CTX* sslCtx = NULL; +#endif +#ifdef HAVE_CRL + X509_CRL* crl = NULL; + STACK_OF(X509_CRL)* crls = NULL; + XFILE fp = XBADFILE; +#endif + wolfSSL_Free_cb prevF = NULL; + int allocs; + int acceptAll; + int ret; + int err; + int baseErr = 0; + int baseLogNum = 0; + int baseLog[2 * 4]; /* x509VfyLog without a failure: errors, depths */ + int same; + int rsaAllocs = 0; + int outOfMem; + int i; + int n; + size_t c; + + ExpectNotNull(ca = X509_load_certificate_file("./certs/ca-cert.pem", + SSL_FILETYPE_PEM)); + ExpectIntEQ(wolfSSL_GetAllocators(&x509VfyOomMalloc, &prevF, + &x509VfyOomRealloc), 0); + if (EXPECT_SUCCESS()) + rsaAllocs = x509_vfy_oom_rsa_allocs(ca, prevF); + for (c = 0; c < XELEM_CNT(cases) && EXPECT_SUCCESS(); c++) { + ExpectNotNull(leaf = X509_load_certificate_file(cases[c].leaf, + SSL_FILETYPE_PEM)); + if (cases[c].untrusted != NULL) { + ExpectNotNull(inter = X509_load_certificate_file( + cases[c].untrusted, SSL_FILETYPE_PEM)); + ExpectNotNull(untrusted = sk_X509_new_null()); + ExpectIntGT(sk_X509_push(untrusted, inter), 0); + } + #if !defined(NO_TLS) && !defined(NO_WOLFSSL_CLIENT) + if (cases[c].sslCtxCa != NULL) { + ExpectNotNull(sslCtx = SSL_CTX_new(wolfSSLv23_client_method())); + SSL_CTX_set_verify(sslCtx, SSL_VERIFY_NONE, NULL); + ExpectIntEQ(SSL_CTX_load_verify_locations(sslCtx, + "./certs/ca-cert.pem", NULL), 1); + ExpectIntEQ(SSL_CTX_load_verify_locations(sslCtx, + cases[c].sslCtxCa, NULL), 1); + ExpectNotNull(store = SSL_CTX_get_cert_store(sslCtx)); + } + else + #endif + { + ExpectNotNull(store = X509_STORE_new()); + ExpectIntEQ(X509_STORE_add_cert(store, ca), 1); + } + #ifdef HAVE_CRL + if (cases[c].storeCrl != NULL) { + ExpectTrue((fp = XFOPEN(cases[c].storeCrl, "rb")) != XBADFILE); + ExpectNotNull(crl = PEM_read_X509_CRL(fp, NULL, NULL, NULL)); + if (fp != XBADFILE) + XFCLOSE(fp); + ExpectIntEQ(X509_STORE_add_crl(store, crl), 1); + X509_CRL_free(crl); + crl = NULL; + } + if (cases[c].ctxCrl != NULL) { + ExpectTrue((fp = XFOPEN(cases[c].ctxCrl, "rb")) != XBADFILE); + ExpectNotNull(crl = PEM_read_X509_CRL(fp, NULL, NULL, NULL)); + if (fp != XBADFILE) + XFCLOSE(fp); + ExpectNotNull(crls = sk_X509_CRL_new_null()); + ExpectIntGT(sk_X509_CRL_push(crls, crl), 0); + } + #endif + /* First without a failure, to count the allocations. A callback + * that accepts every error is not asked about a failed allocation, + * as OpenSSL: X509_V_ERR_OUT_OF_MEM, or X509_V_ERR_UNSPECIFIED + * where it is not known. */ + for (acceptAll = 0; acceptAll <= 1 && EXPECT_SUCCESS(); acceptAll++) { + allocs = 0; + outOfMem = 0; + for (i = 0; i <= allocs && EXPECT_SUCCESS(); i++) { + ExpectNotNull(ctx = X509_STORE_CTX_new()); + ExpectIntEQ(X509_STORE_CTX_init(ctx, store, leaf, untrusted), + 1); + #ifdef HAVE_CRL + if (crls != NULL) + X509_STORE_CTX_set0_crls(ctx, crls); + #endif + x509VfyAccept = VA_ALL; + x509VfyLogNum = 0; + if (acceptAll) + X509_STORE_CTX_set_verify_cb(ctx, x509_vfy_cb); + x509VfyOomNum = 0; + x509VfyOomAt = i; + ExpectIntEQ(wolfSSL_SetAllocators(x509_vfy_oom_malloc, prevF, + x509_vfy_oom_realloc), 0); + ret = X509_verify_cert(ctx); + (void)wolfSSL_SetAllocators(x509VfyOomMalloc, prevF, + x509VfyOomRealloc); + err = X509_STORE_CTX_get_error(ctx); + if (i == 0) { + allocs = x509VfyOomNum; + if (!acceptAll) + ExpectIntEQ(err, cases[c].err); + ExpectIntEQ(ret, acceptAll); + baseErr = err; + baseLogNum = x509VfyLogNum; + for (n = 0; n < (int)XELEM_CNT(x509VfyLog); n++) { + baseLog[2 * n] = x509VfyLog[n].err; + baseLog[2 * n + 1] = x509VfyLog[n].depth; + } + } + else { + /* Without effect, or internal: the callback saw only + * errors it sees without a failure */ + same = x509VfyLogNum <= baseLogNum; + for (n = 0; same && n < x509VfyLogNum && + n < (int)XELEM_CNT(x509VfyLog); n++) { + same = x509VfyLog[n].err == baseLog[2 * n] && + x509VfyLog[n].depth == baseLog[2 * n + 1]; + } + if (ret == 1) { + same = acceptAll && (rsaAllocs || (same && + err == baseErr && x509VfyLogNum == baseLogNum)); + } + else if (err != X509_V_ERR_OUT_OF_MEM && + err != X509_V_ERR_UNSPECIFIED) { + same = rsaAllocs || + (same && !acceptAll && err == baseErr); + } + if (!same) { + fprintf(stderr, "X509_verify_cert() of %s with " + "allocation %d failing: %d, error %d\n", + cases[c].leaf, i, ret, err); + } + ExpectTrue(same); + outOfMem |= (err == X509_V_ERR_OUT_OF_MEM); + } + X509_STORE_CTX_free(ctx); + ctx = NULL; + } + ExpectIntGT(allocs, 0); + /* Some failed allocation is reported as such */ + ExpectTrue(outOfMem); + } + #ifdef HAVE_CRL + sk_X509_CRL_pop_free(crls, X509_CRL_free); + crls = NULL; + #endif + #if !defined(NO_TLS) && !defined(NO_WOLFSSL_CLIENT) + if (sslCtx != NULL) { + SSL_CTX_free(sslCtx); + sslCtx = NULL; + store = NULL; + } + #endif + X509_STORE_free(store); + store = NULL; + sk_X509_pop_free(untrusted, X509_free); + untrusted = NULL; + X509_free(leaf); + leaf = NULL; } - XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#ifdef WOLFSSL_CERT_GEN_CACHE - wc_SetCert_Free(&cert); /* release DecodedCert from wc_SetIssuerBuffer */ + X509_free(ca); #endif - return x509; + return EXPECT_RESULT(); } -#endif -/* X509_verify_cert() loads each candidate issuer into the CertManager as a - * temporary CA, and the CertManager picks the signer on its own from all it - * holds. An untrusted CA loaded for a link below, or for a path that was - * abandoned, must be gone when the next link is verified: otherwise a - * certificate signed by it passes while the path goes on with a same-named - * genuine intermediate that leads to the root. - * - * The attacker knows the genuine intermediate's certificate and holds none of - * its keys. Every forged path must be rejected. */ -int test_X509_verify_cert_stale_temp_ca(void) +/* A store of its own takes a trusted cert that is out of date, as in + * OpenSSL (the add_cert_expired cases of x509VfyCases). The cert stays out + * of the cert manager, so TLS does not trust it. */ +int test_X509_STORE_add_cert_expired(void) { EXPECT_DECLS; #if defined(OPENSSL_EXTRA) && !defined(NO_RSA) && !defined(NO_CERTS) && \ - defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_EXT) && \ - !defined(NO_SHA256) && defined(USE_CERT_BUFFERS_2048) && \ - !defined(NO_ASN_TIME) - enum { K_ROOT, K_INT, K_ATK, K_CNT }; - enum { C_INT, C_HONEST, C_FORGED, C_LOOP_TWIN, C_LOOP_UP, C_BARE_TWIN, - C_DECOY, C_FORGED_B, C_TWIN_A, C_TWIN_B, C_UP, C_UP_OTHER, C_CNT }; - static const struct { - const char* subj; - const char* issuer; /* NULL is the test root */ - int isCA; - byte skid; - byte akid; - int key; - int signKey; - } certs[C_CNT] = { - /* The genuine intermediate and a leaf it issued. */ - { "Issuing CA", NULL, 1, 0x03, 0, K_INT, K_ROOT }, - { "honest", "Issuing CA", 0, 0, 0x03, K_ATK, K_INT }, - /* Signed by the attacker in the intermediate's name. */ - { "forged", "Issuing CA", 0, 0, 0, K_ATK, K_ATK }, - /* Two CAs that issued each other, one named like the intermediate. */ - { "Issuing CA", "Upper CA", 1, 0x0b, 0, K_ATK, K_ATK }, - { "Upper CA", "Issuing CA", 1, 0x16, 0, K_ATK, K_ATK }, - /* No subject key id, and not signed by the issuer it names. */ - { "Issuing CA", "Decoy CA", 1, 0, 0, K_ATK, K_ATK }, - { "Decoy CA", "Nowhere", 1, 0x16, 0, K_INT, K_ATK }, - /* Twin A verifies under Upper CA, which names twin B as its issuer but - * is not signed by it. The other Upper CA did not sign twin A. */ - { "forged", "Issuing CA", 0, 0x16, 0, K_ATK, K_ATK }, - { "Issuing CA", "Upper CA", 1, 0x0b, 0, K_ATK, K_INT }, - { "Issuing CA", "Nowhere", 1, 0x16, 0, K_ATK, K_ROOT }, - { "Upper CA", "Issuing CA", 1, 0x21, 0x16, K_INT, K_ROOT }, - { "Upper CA", "Nowhere", 1, 0x2c, 0, K_ATK, K_ROOT }, - }; - static const struct { - int leaf; - int untrusted[6]; /* in push order, ends with -1 */ - int expectVerify; /* expected X509_verify_cert() result */ - } cases[] = { - { C_HONEST, { C_INT, -1 }, 1 }, - { C_FORGED, { C_INT, -1 }, 0 }, - /* Left from a link below: no link fails on the way up. */ - { C_FORGED, { C_LOOP_TWIN, C_LOOP_UP, C_INT, -1 }, 0 }, - /* Left from an abandoned path: the certificate that failed. */ - { C_FORGED, { C_BARE_TWIN, C_DECOY, C_INT, -1 }, 0 }, - /* Left from an abandoned path: the issuer it failed against. */ - { C_FORGED_B, { C_TWIN_A, C_INT, C_TWIN_B, C_UP, C_UP_OTHER, -1 }, 0 }, - }; - WC_RNG rng; - RsaKey keys[K_CNT]; - int rngI = 0; - int keysI = 0; - word32 idx; - X509* x509[C_CNT]; + !defined(NO_FILESYSTEM) && !defined(NO_ASN_TIME) + const char* leafFile = TA_CERT_DIR "expired-root-leaf-cert.pem"; X509* root = NULL; + X509* renewed = NULL; + X509* leaf = NULL; + X509* issuer = NULL; X509_STORE* store = NULL; + X509_STORE* store2 = NULL; X509_STORE_CTX* ctx = NULL; - STACK_OF(X509)* untrusted = NULL; - const byte* p; - size_t i; - int j; +#if defined(WOLFSSL_SIGNER_DER_CERT) + STACK_OF(X509)* certs = NULL; +#endif +#if defined(OPENSSL_ALL) && defined(WOLFSSL_SIGNER_DER_CERT) + STACK_OF(X509_OBJECT)* objs = NULL; + int i; +#endif +#if !defined(NO_TLS) && !defined(NO_WOLFSSL_CLIENT) + SSL_CTX* sslCtx = NULL; + X509* datedRoot = NULL; + X509* expiredInt = NULL; +#endif - XMEMSET(x509, 0, sizeof(x509)); + ExpectNotNull(root = X509_load_certificate_file( + TA_CERT_DIR "expired-root-cert.pem", SSL_FILETYPE_PEM)); + ExpectNotNull(renewed = X509_load_certificate_file( + TA_CERT_DIR "renewed-root-cert.pem", SSL_FILETYPE_PEM)); + ExpectNotNull(leaf = X509_load_certificate_file(leafFile, + SSL_FILETYPE_PEM)); + ExpectNotNull(store = X509_STORE_new()); + ExpectIntEQ(X509_STORE_add_cert(store, root), 1); + ExpectIntEQ(wolfSSL_CertManagerVerify(store->cm, leafFile, + SSL_FILETYPE_PEM), WC_NO_ERR_TRACE(ASN_NO_SIGNER_E)); + /* Adding it again keeps one copy */ + ExpectIntEQ(X509_STORE_add_cert(store, root), 1); + ExpectIntEQ(sk_X509_num(store->trusted), 1); - ExpectIntEQ(wc_InitRng(&rng), 0); - if (EXPECT_SUCCESS()) rngI = 1; - for (j = 0; j < K_CNT; j++) { - ExpectIntEQ(wc_InitRsaKey(&keys[j], NULL), 0); - if (EXPECT_SUCCESS()) keysI = j + 1; - } - idx = 0; - ExpectIntEQ(wc_RsaPrivateKeyDecode(ca_key_der_2048, &idx, &keys[K_ROOT], - sizeof_ca_key_der_2048), 0); - idx = 0; - ExpectIntEQ(wc_RsaPrivateKeyDecode(server_key_der_2048, &idx, &keys[K_INT], - sizeof_server_key_der_2048), 0); - idx = 0; - ExpectIntEQ(wc_RsaPrivateKeyDecode(client_key_der_2048, &idx, &keys[K_ATK], - sizeof_client_key_der_2048), 0); + /* Verifying with it does not put it in the cert manager */ + ExpectNotNull(ctx = X509_STORE_CTX_new()); + ExpectIntEQ(X509_STORE_CTX_init(ctx, store, leaf, NULL), 1); + X509_STORE_CTX_set_time(ctx, 0, (time_t)1420070400); + ExpectIntEQ(X509_verify_cert(ctx), 1); + ExpectIntEQ(wolfSSL_CertManagerVerify(store->cm, leafFile, + SSL_FILETYPE_PEM), WC_NO_ERR_TRACE(ASN_NO_SIGNER_E)); + /* The issuer lookups find it */ + ExpectIntEQ(X509_STORE_CTX_init(ctx, store, leaf, NULL), 1); + ExpectIntEQ(X509_STORE_CTX_get1_issuer(&issuer, ctx, leaf), 1); + ExpectIntEQ(X509_cmp(issuer, root), 0); + X509_free(issuer); +#if defined(WOLFSSL_SIGNER_DER_CERT) + ExpectNotNull(certs = X509_STORE_get1_certs(ctx, + X509_get_subject_name(root))); + ExpectIntEQ(sk_X509_num(certs), 1); + sk_X509_pop_free(certs, X509_free); +#endif +#if defined(OPENSSL_ALL) && defined(WOLFSSL_SIGNER_DER_CERT) + ExpectNotNull(objs = X509_STORE_get0_objects(store)); + ExpectIntEQ(sk_X509_OBJECT_num(objs), 1); + ExpectIntEQ(X509_cmp(X509_OBJECT_get0_X509( + (X509_OBJECT*)sk_X509_OBJECT_value(objs, 0)), root), 0); +#endif - p = ca_cert_der_2048; - ExpectNotNull(root = d2i_X509(NULL, &p, (int)sizeof_ca_cert_der_2048)); - for (j = 0; j < C_CNT; j++) { - ExpectNotNull(x509[j] = gen_named_cert(certs[j].subj, certs[j].issuer, - certs[j].isCA, certs[j].skid, certs[j].akid, &keys[certs[j].key], - &keys[certs[j].signKey], &rng)); + /* Nor with X509_V_FLAG_NO_CHECK_TIME */ + ExpectNotNull(store2 = X509_STORE_new()); + ExpectIntEQ(X509_VERIFY_PARAM_set_flags(X509_STORE_get0_param(store2), + X509_V_FLAG_NO_CHECK_TIME), 1); + ExpectIntEQ(X509_STORE_add_cert(store2, root), 1); + ExpectIntEQ(wolfSSL_CertManagerVerify(store2->cm, leafFile, + SSL_FILETYPE_PEM), WC_NO_ERR_TRACE(ASN_NO_SIGNER_E)); + X509_STORE_free(store2); + store2 = NULL; + +#if defined(OPENSSL_ALL) && defined(WOLFSSL_SIGNER_DER_CERT) + /* A valid root of the same name with a new key does not hide it */ + for (i = 0; i < 2; i++) { + ExpectNotNull(store2 = X509_STORE_new()); + ExpectIntEQ(X509_STORE_add_cert(store2, (i == 0) ? renewed : root), + 1); + ExpectIntEQ(X509_STORE_add_cert(store2, (i == 0) ? root : renewed), + 1); + ExpectNotNull(objs = X509_STORE_get0_objects(store2)); + ExpectIntEQ(sk_X509_OBJECT_num(objs), 2); + X509_STORE_free(store2); + store2 = NULL; } +#endif - for (i = 0; i < XELEM_CNT(cases) && EXPECT_SUCCESS(); i++) { - ExpectNotNull(store = X509_STORE_new()); - ExpectIntEQ(X509_STORE_add_cert(store, root), 1); - ExpectNotNull(untrusted = sk_X509_new_null()); - for (j = 0; cases[i].untrusted[j] >= 0; j++) { - ExpectIntGT(sk_X509_push(untrusted, x509[cases[i].untrusted[j]]), - 0); - } - ExpectNotNull(ctx = X509_STORE_CTX_new()); - ExpectIntEQ(X509_STORE_CTX_init(ctx, store, x509[cases[i].leaf], - untrusted), 1); - ExpectIntEQ(X509_verify_cert(ctx), cases[i].expectVerify); - X509_STORE_CTX_free(ctx); - ctx = NULL; - X509_STORE_free(store); +#if !defined(NO_TLS) && !defined(NO_WOLFSSL_CLIENT) + /* The store of an SSL_CTX still refuses it */ + ExpectNotNull(datedRoot = X509_load_certificate_file( + TA_CERT_DIR "dated-root-cert.pem", SSL_FILETYPE_PEM)); + ExpectNotNull(expiredInt = X509_load_certificate_file( + TA_CERT_DIR "expired-int-cert.pem", SSL_FILETYPE_PEM)); + ExpectNotNull(sslCtx = SSL_CTX_new(wolfSSLv23_client_method())); + ExpectIntEQ(X509_STORE_add_cert(SSL_CTX_get_cert_store(sslCtx), root), + WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)); + ExpectIntEQ(X509_STORE_set_flags(SSL_CTX_get_cert_store(sslCtx), + X509_V_FLAG_NO_CHECK_TIME), 1); + ExpectIntEQ(X509_STORE_add_cert(SSL_CTX_get_cert_store(sslCtx), root), + WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)); + /* Nor does an SSL_CTX trust it when given the store. The intermediates + * of the store go in as before. */ + ExpectIntEQ(X509_STORE_add_cert(store, datedRoot), 1); + ExpectIntEQ(X509_STORE_add_cert(store, expiredInt), 1); + ExpectIntEQ(X509_VERIFY_PARAM_set_flags(X509_STORE_get0_param(store), + X509_V_FLAG_NO_CHECK_TIME), 1); + SSL_CTX_set_cert_store(sslCtx, store); + if (SSL_CTX_get_cert_store(sslCtx) == store) { store = NULL; - sk_X509_free(untrusted); - untrusted = NULL; } + ExpectIntEQ(wolfSSL_CertManagerVerify(wolfSSL_CTX_GetCertManager(sslCtx), + leafFile, SSL_FILETYPE_PEM), WC_NO_ERR_TRACE(ASN_NO_SIGNER_E)); + ExpectIntEQ(wolfSSL_CertManagerVerify(wolfSSL_CTX_GetCertManager(sslCtx), + TA_CERT_DIR "dated-int-leaf-cert.pem", SSL_FILETYPE_PEM), + WOLFSSL_SUCCESS); + SSL_CTX_free(sslCtx); + X509_free(datedRoot); + X509_free(expiredInt); +#endif - for (j = 0; j < C_CNT; j++) - X509_free(x509[j]); + X509_STORE_CTX_free(ctx); + X509_STORE_free(store); X509_free(root); - while (keysI > 0) - wc_FreeRsaKey(&keys[--keysI]); - if (rngI) wc_FreeRng(&rng); + X509_free(renewed); + X509_free(leaf); #endif return EXPECT_RESULT(); } @@ -3683,10 +7079,10 @@ int test_X509_STORE_untrusted(void) * properly */ ExpectIntEQ(test_X509_STORE_untrusted_certs(untrusted3, 1, 0, 1), TEST_SUCCESS); - /* Still needs properly loaded CA, while including it in untrusted - * list is not an error, it also doesn't count for verify */ + /* Still needs properly loaded CA. As in OpenSSL, the untrusted root + * ends the chain and is reported. */ ExpectIntEQ(test_X509_STORE_untrusted_certs(untrusted3, 0, - X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY, 0), + X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN, 0), TEST_SUCCESS); /* Succeeds because path to loaded CA is available. */ ExpectIntEQ(test_X509_STORE_untrusted_certs(untrusted4, 1, 0, 1), @@ -3698,6 +7094,7 @@ int test_X509_STORE_untrusted(void) #if defined(OPENSSL_EXTRA) && !defined(NO_RSA) && !defined(NO_FILESYSTEM) && \ !defined(WOLFSSL_X509_STORE_ALLOW_NON_CA_INTERMEDIATE) +static int first_errcode; static int last_errcode; static int last_errdepth; @@ -3705,6 +7102,8 @@ static int X509Callback(int ok, X509_STORE_CTX *ctx) { if (!ok) { + if (first_errcode == 0) + first_errcode = X509_STORE_CTX_get_error(ctx); last_errcode = X509_STORE_CTX_get_error(ctx); last_errdepth = X509_STORE_CTX_get_error_depth(ctx); } @@ -3729,6 +7128,7 @@ int test_X509_STORE_InvalidCa(void) X509* cert = NULL; STACK_OF(X509)* untrusted = NULL; + first_errcode = 0; last_errcode = 0; last_errdepth = 0; @@ -3756,12 +7156,15 @@ int test_X509_STORE_InvalidCa(void) ExpectIntEQ(X509_STORE_CTX_init(ctx, str, cert, untrusted), 1); ExpectIntEQ(X509_verify_cert(ctx), 1); - ExpectIntEQ(last_errcode, X509_V_ERR_INVALID_CA); + ExpectIntEQ(first_errcode, X509_V_ERR_INVALID_CA); + /* As in OpenSSL, its keyUsage without keyCertSign is reported next */ + ExpectIntEQ(last_errcode, X509_V_ERR_KEYUSAGE_NO_CERTSIGN); (void)last_errdepth; /* Defense in depth: ctx->error must not be clobbered back to X509_V_OK * by the later successful verification of the intermediate against the * trusted root. The worst-seen error must persist. */ - ExpectIntEQ(X509_STORE_CTX_get_error(ctx), X509_V_ERR_INVALID_CA); + ExpectIntEQ(X509_STORE_CTX_get_error(ctx), + X509_V_ERR_KEYUSAGE_NO_CERTSIGN); X509_free(cert); X509_STORE_free(str); @@ -3790,6 +7193,7 @@ int test_X509_STORE_InvalidCa_CtxCallback(void) X509* cert = NULL; STACK_OF(X509)* untrusted = NULL; + first_errcode = 0; last_errcode = 0; last_errdepth = 0; @@ -3819,9 +7223,12 @@ int test_X509_STORE_InvalidCa_CtxCallback(void) /* The callback overrides the CA:FALSE issuer, so verification succeeds... */ ExpectIntEQ(X509_verify_cert(ctx), 1); /* ...and it must actually have been handed the INVALID_CA error. */ - ExpectIntEQ(last_errcode, X509_V_ERR_INVALID_CA); + ExpectIntEQ(first_errcode, X509_V_ERR_INVALID_CA); + /* As in OpenSSL, its keyUsage without keyCertSign is reported next */ + ExpectIntEQ(last_errcode, X509_V_ERR_KEYUSAGE_NO_CERTSIGN); (void)last_errdepth; - ExpectIntEQ(X509_STORE_CTX_get_error(ctx), X509_V_ERR_INVALID_CA); + ExpectIntEQ(X509_STORE_CTX_get_error(ctx), + X509_V_ERR_KEYUSAGE_NO_CERTSIGN); X509_free(cert); X509_STORE_free(str); @@ -4002,22 +7409,29 @@ int test_wolfSSL_X509_STORE_set_flags(void) !defined(NO_FILESYSTEM) && !defined(NO_RSA) X509_STORE* store = NULL; X509* x509 = NULL; -#ifdef HAVE_CRL + X509_STORE_CTX* ctx = NULL; X509_STORE_CTX* storeCtx = NULL; X509* ca = NULL; int err = 0; -#endif /* The CRL flags must not share bits with the other verify flags */ ExpectIntEQ((X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL) & (X509_V_FLAG_USE_CHECK_TIME | X509_V_FLAG_NO_CHECK_TIME | - X509_V_FLAG_PARTIAL_CHAIN), 0); + X509_V_FLAG_PARTIAL_CHAIN | X509_V_FLAG_X509_STRICT), 0); ExpectNotNull((store = wolfSSL_X509_STORE_new())); ExpectNotNull((x509 = wolfSSL_X509_load_certificate_file(svrCertFile, WOLFSSL_FILETYPE_PEM))); ExpectIntEQ(X509_STORE_add_cert(store, x509), WOLFSSL_SUCCESS); + /* As in OpenSSL, the flags go on the verify param */ + ExpectNotNull(ctx = X509_STORE_CTX_new()); + ExpectIntEQ(X509_STORE_CTX_init(ctx, store, x509, NULL), WOLFSSL_SUCCESS); + X509_STORE_CTX_set_flags(ctx, X509_V_FLAG_X509_STRICT); + ExpectIntNE(X509_VERIFY_PARAM_get_flags(X509_STORE_CTX_get0_param(ctx)) & + X509_V_FLAG_X509_STRICT, 0); + X509_STORE_CTX_free(ctx); + #ifdef HAVE_CRL ExpectIntEQ(X509_STORE_set_flags(store, WOLFSSL_CRL_CHECKALL), WOLFSSL_SUCCESS); @@ -4030,19 +7444,29 @@ int test_wolfSSL_X509_STORE_set_flags(void) WC_NO_ERR_TRACE(NOT_COMPILED_IN)); ExpectIntEQ(X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK), WC_NO_ERR_TRACE(NOT_COMPILED_IN)); + ExpectIntEQ(X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK_ALL), + WC_NO_ERR_TRACE(NOT_COMPILED_IN)); #endif + /* As OpenSSL, the CRL flags go on the param, also without HAVE_CRL */ + ExpectIntEQ(X509_VERIFY_PARAM_get_flags(X509_STORE_get0_param(store)) & + (X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL), + X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL); wolfSSL_X509_STORE_free(store); store = NULL; -#ifdef HAVE_CRL /* X509_V_FLAG_CRL_CHECK turns on CRL checks. No CRL is loaded. */ ExpectNotNull((store = wolfSSL_X509_STORE_new())); ExpectNotNull((ca = wolfSSL_X509_load_certificate_file(caCertFile, WOLFSSL_FILETYPE_PEM))); ExpectIntEQ(X509_STORE_add_cert(store, ca), WOLFSSL_SUCCESS); +#ifdef HAVE_CRL ExpectIntEQ(X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK), WOLFSSL_SUCCESS); +#else + ExpectIntEQ(X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK), + WC_NO_ERR_TRACE(NOT_COMPILED_IN)); +#endif ExpectNotNull((storeCtx = X509_STORE_CTX_new())); ExpectIntEQ(X509_STORE_CTX_init(storeCtx, store, x509, NULL), WOLFSSL_SUCCESS); @@ -4053,7 +7477,6 @@ int test_wolfSSL_X509_STORE_set_flags(void) X509_STORE_CTX_free(storeCtx); wolfSSL_X509_free(ca); wolfSSL_X509_STORE_free(store); -#endif wolfSSL_X509_free(x509); #endif /* defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && @@ -4210,6 +7633,16 @@ int test_wolfSSL_X509_STORE_load_locations(void) ExpectIntEQ(wolfSSL_CertManagerLoadCA(store->cm, ca_file, NULL), WOLFSSL_SUCCESS); + /* The default dir is optional. */ + { + X509_LOOKUP* lookup = NULL; + + ExpectNotNull(lookup = X509_STORE_add_lookup(store, + X509_LOOKUP_hash_dir())); + ExpectIntEQ(X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT), + WOLFSSL_SUCCESS); + } + /* Test bad arguments */ ExpectIntEQ(X509_STORE_load_locations(NULL, ca_file, NULL), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); @@ -4247,6 +7680,16 @@ int test_wolfSSL_X509_STORE_load_locations(void) ExpectIntEQ(setenv("SSL_CERT_FILE", client_pem_file, 1), 0); ExpectIntEQ(setenv("SSL_CERT_DIR", certs_path, 1), 0); ExpectIntEQ(X509_STORE_set_default_paths(store), WOLFSSL_SUCCESS); + /* Default locations are optional, as with OpenSSL. */ + ExpectIntEQ(X509_STORE_set_default_paths(NULL), + WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); + ExpectIntEQ(unsetenv("SSL_CERT_FILE"), 0); + ExpectIntEQ(unsetenv("SSL_CERT_DIR"), 0); + ExpectIntEQ(X509_STORE_set_default_paths(store), WOLFSSL_SUCCESS); + ExpectIntEQ(setenv("SSL_CERT_DIR", bad_path, 1), 0); + ExpectIntEQ(X509_STORE_set_default_paths(store), WOLFSSL_SUCCESS); + ExpectIntEQ(setenv("SSL_CERT_FILE", client_pem_file, 1), 0); + ExpectIntEQ(setenv("SSL_CERT_DIR", certs_path, 1), 0); #endif #if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE) @@ -4472,6 +7915,103 @@ int test_wolfSSL_X509_STORE_get1_certs(void) return EXPECT_RESULT(); } +int test_wolfSSL_X509_STORE_CTX_get_by_subject(void) +{ + EXPECT_DECLS; +#if defined(OPENSSL_ALL) && !defined(NO_FILESYSTEM) && !defined(NO_RSA) + X509_STORE_CTX* ctx = NULL; + X509_STORE* store = NULL; + X509* ca = NULL; + X509* svr = NULL; + X509* cli = NULL; + X509_OBJECT* obj = NULL; + + ExpectNotNull(ca = X509_load_certificate_file(caCertFile, + SSL_FILETYPE_PEM)); + ExpectNotNull(svr = X509_load_certificate_file(svrCertFile, + SSL_FILETYPE_PEM)); + ExpectNotNull(cli = X509_load_certificate_file(cliCertFile, + SSL_FILETYPE_PEM)); + ExpectNotNull(ctx = X509_STORE_CTX_new()); + ExpectNotNull(store = X509_STORE_new()); + ExpectNotNull(obj = X509_OBJECT_new()); + + /* Errors */ + ExpectIntEQ(X509_STORE_CTX_get_by_subject(NULL, X509_LU_X509, + X509_get_subject_name(ca), obj), 0); + ExpectIntEQ(X509_STORE_CTX_get_by_subject(ctx, X509_LU_X509, + X509_get_subject_name(ca), obj), 0); + + /* Trusted self-signed cert and untrusted intermediate. */ + ExpectIntEQ(X509_STORE_add_cert(store, ca), 1); + ExpectIntEQ(X509_STORE_add_cert(store, svr), 1); + ExpectIntEQ(X509_STORE_CTX_init(ctx, store, NULL, NULL), 1); + ExpectIntEQ(X509_STORE_CTX_get_by_subject(ctx, X509_LU_X509, NULL, obj), + 0); + ExpectIntEQ(X509_STORE_CTX_get_by_subject(ctx, X509_LU_X509, + X509_get_subject_name(ca), NULL), 0); + ExpectIntEQ(X509_STORE_CTX_get_by_subject(ctx, X509_LU_CRL, + X509_get_subject_name(ca), obj), 0); + ExpectIntEQ(X509_STORE_CTX_get_by_subject(ctx, X509_LU_X509, + X509_get_subject_name(cli), obj), 0); + ExpectTrue(X509_OBJECT_get_type(obj) == X509_LU_NONE); + + ExpectIntEQ(X509_STORE_CTX_get_by_subject(ctx, X509_LU_X509, + X509_get_subject_name(ca), obj), 1); + ExpectTrue(X509_OBJECT_get_type(obj) == X509_LU_X509); + ExpectPtrEq(X509_OBJECT_get0_X509(obj), ca); + X509_OBJECT_free(obj); + obj = NULL; + + /* free_contents releases the reference and empties the object */ + ExpectNotNull(obj = X509_OBJECT_new()); + ExpectIntEQ(X509_STORE_CTX_get_by_subject(ctx, X509_LU_X509, + X509_get_subject_name(ca), obj), 1); + X509_OBJECT_free_contents(obj); + ExpectTrue(X509_OBJECT_get_type(obj) == X509_LU_NONE); + ExpectNull(X509_OBJECT_get0_X509(obj)); + X509_OBJECT_free_contents(obj); + X509_OBJECT_free(obj); + obj = NULL; + + ExpectNotNull(obj = X509_OBJECT_new()); + ExpectIntEQ(X509_STORE_get_by_subject(ctx, X509_LU_X509, + X509_get_subject_name(svr), obj), 1); + ExpectPtrEq(X509_OBJECT_get0_X509(obj), svr); + X509_STORE_CTX_cleanup(ctx); + X509_STORE_free(store); + store = NULL; + X509_free(svr); + svr = NULL; + + /* The object holds the last reference to the cert. */ + ExpectIntEQ(X509_check_issued(ca, X509_OBJECT_get0_X509(obj)), X509_V_OK); + X509_OBJECT_free(obj); + obj = NULL; + +#ifdef WOLFSSL_SIGNER_DER_CERT + /* CA loaded from a file into the cert manager. */ + ExpectNotNull(store = X509_STORE_new()); + ExpectIntEQ(X509_STORE_load_locations(store, caCertFile, NULL), 1); + ExpectIntEQ(X509_STORE_CTX_init(ctx, store, NULL, NULL), 1); + ExpectNotNull(obj = X509_OBJECT_new()); + ExpectIntEQ(X509_STORE_CTX_get_by_subject(ctx, X509_LU_X509, + X509_get_subject_name(ca), obj), 1); + ExpectIntEQ(X509_cmp(X509_OBJECT_get0_X509(obj), ca), 0); + X509_STORE_CTX_cleanup(ctx); + X509_STORE_free(store); + ExpectNotNull(X509_get_subject_name(X509_OBJECT_get0_X509(obj))); +#endif + + X509_OBJECT_free(obj); + X509_STORE_CTX_free(ctx); + X509_free(cli); + X509_free(svr); + X509_free(ca); +#endif + return EXPECT_RESULT(); +} + #if defined(HAVE_SSL_MEMIO_TESTS_DEPENDENCIES) && \ defined(WOLFSSL_LOCAL_X509_STORE) && \ (defined(OPENSSL_ALL) || defined(WOLFSSL_QT)) && defined(HAVE_CRL) @@ -5027,7 +8567,12 @@ int test_wolfSSL_CTX_set_cert_store(void) if (EXPECT_SUCCESS()) { ExpectIntEQ(X509_STORE_CTX_init(storeCtx, SSL_CTX_get_cert_store(ctx), svrCert, NULL), SSL_SUCCESS); + #ifdef WOLFSSL_SIGNER_DER_CERT ExpectIntEQ(X509_verify_cert(storeCtx), SSL_SUCCESS); + #else + /* Without their DER the CAs cannot go on the chain */ + ExpectIntNE(X509_verify_cert(storeCtx), SSL_SUCCESS); + #endif } X509_STORE_CTX_free(storeCtx); @@ -5083,3 +8628,62 @@ int test_wolfSSL_CTX_set_cert_store(void) return EXPECT_RESULT(); } +#if defined(OPENSSL_EXTRA) && defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \ + !defined(NO_RSA) && !defined(NO_FILESYSTEM) +static int test_X509_verify_cert_tls_cached_ca_cb(int ok, X509_STORE_CTX* ctx) +{ + int err = X509_STORE_CTX_get_error(ctx); + + return ok || err == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY || + err == WC_NO_ERR_TRACE(ASN_NO_SIGNER_E); +} +#endif + +/* A CA that TLS cached from a peer's chain, after the verify callback waived + * its missing issuer, is not a trust anchor for X509_verify_cert() on the + * SSL_CTX's store. OpenSSL never adds the peer's certs to the store. */ +int test_X509_verify_cert_tls_cached_ca(void) +{ + EXPECT_DECLS; +#if defined(OPENSSL_EXTRA) && defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && \ + !defined(NO_RSA) && !defined(NO_FILESYSTEM) + WOLFSSL_CTX* ctx_c = NULL; + WOLFSSL_CTX* ctx_s = NULL; + WOLFSSL* ssl_c = NULL; + WOLFSSL* ssl_s = NULL; + struct test_memio_ctx test_ctx; + X509_STORE_CTX* storeCtx = NULL; + X509* leaf = NULL; + + XMEMSET(&test_ctx, 0, sizeof(test_ctx)); + ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s, + wolfSSLv23_client_method, wolfSSLv23_server_method), 0); + /* The client trusts no CA of the server's chain. */ + ExpectIntEQ(wolfSSL_CTX_UnloadCAs(ctx_c), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_use_certificate_chain_file(ssl_s, + "./certs/intermediate/server-chain.pem"), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_use_PrivateKey_file(ssl_s, "./certs/server-key.pem", + WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); + wolfSSL_set_verify(ssl_c, WOLFSSL_VERIFY_PEER, + test_X509_verify_cert_tls_cached_ca_cb); + ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0); + + /* Issued by an intermediate of the server's chain */ + ExpectNotNull(leaf = X509_load_certificate_file( + "./certs/intermediate/client-int-cert.pem", SSL_FILETYPE_PEM)); + ExpectNotNull(storeCtx = X509_STORE_CTX_new()); + ExpectIntEQ(X509_STORE_CTX_init(storeCtx, SSL_CTX_get_cert_store(ctx_c), + leaf, NULL), 1); + ExpectIntNE(X509_verify_cert(storeCtx), 1); + ExpectIntEQ(X509_STORE_CTX_get_error(storeCtx), + X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY); + + X509_STORE_CTX_free(storeCtx); + X509_free(leaf); + wolfSSL_free(ssl_s); + wolfSSL_free(ssl_c); + wolfSSL_CTX_free(ctx_s); + wolfSSL_CTX_free(ctx_c); +#endif + return EXPECT_RESULT(); +} diff --git a/tests/api/test_ossl_x509_str.h b/tests/api/test_ossl_x509_str.h index d69340dd8cd..758398a6917 100644 --- a/tests/api/test_ossl_x509_str.h +++ b/tests/api/test_ossl_x509_str.h @@ -39,9 +39,19 @@ int test_wolfSSL_X509_verify_cert_pathlen_anchor(void); int test_wolfSSL_X509_STORE_CTX_verify_cb(void); int test_wolfSSL_X509_STORE_CTX_verify_cb_check_id(void); int test_X509_verify_cert_untrusted_inter(void); +int test_wolfSSL_X509_VERIFY_PARAM_set_depth(void); +int test_X509_verify_cert_no_der(void); +int test_X509_verify_cert_crl_time(void); +int test_X509_verify_cert_crl_loaded(void); +int test_X509_verify_cert_crl_cm_anchor(void); +int test_X509_verify_cert_internal_err(void); int test_X509_verify_cert_ca_no_keycertsign(void); int test_X509_verify_cert_selfsigned_anchor_no_keycertsign(void); int test_X509_verify_cert_stale_temp_ca(void); +int test_X509_verify_cert_chains(void); +int test_X509_verify_cert_oom(void); +int test_X509_verify_cert_tls_cached_ca(void); +int test_X509_STORE_add_cert_expired(void); int test_X509_STORE_untrusted(void); int test_X509_STORE_InvalidCa(void); int test_X509_STORE_InvalidCa_CtxCallback(void); @@ -55,6 +65,7 @@ int test_wolfSSL_X509_STORE_load_locations(void); int test_X509_STORE_get0_objects(void); int test_X509_STORE_get0_objects_borrowed_crl(void); int test_wolfSSL_X509_STORE_get1_certs(void); +int test_wolfSSL_X509_STORE_CTX_get_by_subject(void); int test_wolfSSL_X509_STORE_set_get_crl(void); int test_wolfSSL_X509_STORE_CTX_set0_crls(void); int test_wolfSSL_X509_STORE_add_crl_oom(void); @@ -89,11 +100,22 @@ int test_wolfSSL_CTX_set_cert_store(void); TEST_DECL_GROUP("ossl_x509_store", \ test_wolfSSL_X509_STORE_CTX_verify_cb_check_id), \ TEST_DECL_GROUP("ossl_x509_store", test_X509_verify_cert_untrusted_inter), \ + TEST_DECL_GROUP("ossl_x509_store", \ + test_wolfSSL_X509_VERIFY_PARAM_set_depth), \ + TEST_DECL_GROUP("ossl_x509_store", test_X509_verify_cert_no_der), \ + TEST_DECL_GROUP("ossl_x509_store", test_X509_verify_cert_crl_time), \ + TEST_DECL_GROUP("ossl_x509_store", test_X509_verify_cert_crl_loaded), \ + TEST_DECL_GROUP("ossl_x509_store", test_X509_verify_cert_crl_cm_anchor), \ + TEST_DECL_GROUP("ossl_x509_store", test_X509_verify_cert_internal_err), \ TEST_DECL_GROUP("ossl_x509_store", \ test_X509_verify_cert_ca_no_keycertsign), \ TEST_DECL_GROUP("ossl_x509_store", \ test_X509_verify_cert_selfsigned_anchor_no_keycertsign), \ TEST_DECL_GROUP("ossl_x509_store", test_X509_verify_cert_stale_temp_ca), \ + TEST_DECL_GROUP("ossl_x509_store", test_X509_verify_cert_chains), \ + TEST_DECL_GROUP("ossl_x509_store", test_X509_verify_cert_oom), \ + TEST_DECL_GROUP("ossl_x509_store", test_X509_verify_cert_tls_cached_ca), \ + TEST_DECL_GROUP("ossl_x509_store", test_X509_STORE_add_cert_expired), \ TEST_DECL_GROUP("ossl_x509_store", test_X509_STORE_untrusted), \ TEST_DECL_GROUP("ossl_x509_store", test_X509_STORE_InvalidCa), \ TEST_DECL_GROUP("ossl_x509_store", test_X509_STORE_InvalidCa_CtxCallback), \ @@ -112,6 +134,8 @@ int test_wolfSSL_CTX_set_cert_store(void); TEST_DECL_GROUP("ossl_x509_store", \ test_X509_STORE_get0_objects_borrowed_crl), \ TEST_DECL_GROUP("ossl_x509_store", test_wolfSSL_X509_STORE_get1_certs), \ + TEST_DECL_GROUP("ossl_x509_store", \ + test_wolfSSL_X509_STORE_CTX_get_by_subject), \ TEST_DECL_GROUP("ossl_x509_store", test_wolfSSL_X509_STORE_set_get_crl), \ TEST_DECL_GROUP("ossl_x509_store", \ test_wolfSSL_X509_STORE_CTX_set0_crls), \ diff --git a/tests/api/test_ssl_cert.c b/tests/api/test_ssl_cert.c index 4ff30806b8b..3805dc404d5 100644 --- a/tests/api/test_ssl_cert.c +++ b/tests/api/test_ssl_cert.c @@ -1077,6 +1077,20 @@ int test_wolfSSL_set_peer_cert_chain(void) return EXPECT_RESULT(); } +#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(SESSION_CERTS) && \ + defined(OPENSSL_EXTRA) && defined(KEEP_PEER_CERT) && \ + !defined(WOLFSSL_NO_TLS12) && !defined(NO_RSA) && !defined(NO_TLS) +static int test_verified_chain_cm_calls = 0; + +/* CertManager verify callback that counts calls and rejects any error. */ +static int test_verified_chain_cm_cb(int ok, WOLFSSL_X509_STORE_CTX* store) +{ + (void)store; + test_verified_chain_cm_calls++; + return ok; +} +#endif + /* Test getting the verified certificate chain. * * @return TEST_SUCCESS on success. @@ -1091,6 +1105,11 @@ int test_wolfSSL_get0_verified_chain(void) WOLFSSL *ssl_c = NULL, *ssl_s = NULL; struct test_memio_ctx test_ctx; WOLF_STACK_OF(WOLFSSL_X509)* chain = NULL; +#ifdef WOLFSSL_SIGNER_DER_CERT + WOLFSSL_X509_STORE_CTX* storeCtx = NULL; + WOLFSSL_X509* peer = NULL; + int calls = 0; +#endif ExpectNull(wolfSSL_get0_verified_chain(NULL)); @@ -1101,20 +1120,78 @@ int test_wolfSSL_get0_verified_chain(void) /* Without a peer certificate there is nothing to verify. */ ExpectNull(wolfSSL_get0_verified_chain(ssl_c)); + /* The app's CertManager callback is not used to build the chain. */ + test_verified_chain_cm_calls = 0; + wolfSSL_CertManagerSetVerify(wolfSSL_CTX_GetCertManager(ctx_c), + test_verified_chain_cm_cb); + wolfSSL_set_verify(ssl_c, WOLFSSL_VERIFY_PEER, NULL); ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0); +#ifdef WOLFSSL_SIGNER_DER_CERT + calls = test_verified_chain_cm_calls; /* The server's chain verifies against the CA the client loaded. */ ExpectNotNull(chain = wolfSSL_get0_verified_chain(ssl_c)); ExpectIntGT(wolfSSL_sk_X509_num(chain), 0); + ExpectIntEQ(test_verified_chain_cm_calls, calls); + wolfSSL_CertManagerSetVerify(wolfSSL_CTX_GetCertManager(ctx_c), NULL); if (ssl_c != NULL) { ExpectPtrEq(ssl_c->verifiedChain, chain); } - /* Called again the previous chain is released and a new one stored. */ - ExpectNotNull(chain = wolfSSL_get0_verified_chain(ssl_c)); + /* Called again, the same chain is returned, as by OpenSSL. */ + ExpectPtrEq(wolfSSL_get0_verified_chain(ssl_c), chain); if (ssl_c != NULL) { ExpectPtrEq(ssl_c->verifiedChain, chain); } + /* Built once: without the CA it does not verify, but is still there. */ + ExpectIntEQ(wolfSSL_CTX_UnloadCAs(ctx_c), WOLFSSL_SUCCESS); + ExpectNotNull(storeCtx = wolfSSL_X509_STORE_CTX_new()); + ExpectIntEQ(wolfSSL_X509_STORE_CTX_init(storeCtx, + wolfSSL_CTX_get_cert_store(ctx_c), wolfSSL_sk_X509_value(chain, 0), + NULL), WOLFSSL_SUCCESS); + ExpectIntNE(wolfSSL_X509_verify_cert(storeCtx), WOLFSSL_SUCCESS); + wolfSSL_X509_STORE_CTX_free(storeCtx); + ExpectPtrEq(wolfSSL_get0_verified_chain(ssl_c), chain); + ExpectIntEQ(wolfSSL_CTX_load_verify_locations(ctx_c, caCertFile, NULL), + WOLFSSL_SUCCESS); + + /* Dropped by wolfSSL_clear() and by a new peer chain. */ + ExpectIntEQ(wolfSSL_clear(ssl_c), WOLFSSL_SUCCESS); + if (ssl_c != NULL) { + ExpectNull(ssl_c->verifiedChain); + } + ExpectNotNull(wolfSSL_get0_verified_chain(ssl_c)); + wolfSSL_free(ssl_s); + ssl_s = NULL; + wolfSSL_CTX_free(ctx_s); + ctx_s = NULL; + XMEMSET(&test_ctx, 0, sizeof(test_ctx)); + ExpectNotNull(ctx_s = wolfSSL_CTX_new(wolfTLSv1_2_server_method())); + ExpectIntEQ(wolfSSL_CTX_set_session_cache_mode(ctx_s, + WOLFSSL_SESS_CACHE_OFF), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_CTX_use_certificate_chain_file(ctx_s, + "./certs/intermediate/server-chain.pem"), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_CTX_use_PrivateKey_file(ctx_s, svrKeyFile, + WOLFSSL_FILETYPE_PEM), WOLFSSL_SUCCESS); + wolfSSL_SetIORecv(ctx_s, test_memio_read_cb); + wolfSSL_SetIOSend(ctx_s, test_memio_write_cb); + ExpectIntEQ(test_memio_setup(&test_ctx, NULL, &ctx_s, NULL, &ssl_s, + NULL, wolfTLSv1_2_server_method), 0); + ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0); + ExpectIntEQ(wolfSSL_session_reused(ssl_c), 0); + if (ssl_c != NULL) { + ExpectNull(ssl_c->verifiedChain); + } + ExpectNotNull(chain = wolfSSL_get0_verified_chain(ssl_c)); + ExpectIntEQ(wolfSSL_sk_X509_num(chain), 4); + ExpectNotNull(peer = wolfSSL_get_peer_certificate(ssl_c)); + ExpectIntEQ(wolfSSL_X509_cmp(wolfSSL_sk_X509_value(chain, 0), peer), 0); + wolfSSL_X509_free(peer); +#else + /* Without its DER that CA cannot go on the chain. */ + ExpectNull(chain = wolfSSL_get0_verified_chain(ssl_c)); +#endif + wolfSSL_free(ssl_s); wolfSSL_free(ssl_c); wolfSSL_CTX_free(ctx_s); @@ -4484,9 +4561,14 @@ static int test_chain_slot_case_run(const test_chain_slot_case* tc, /* A certificate too large for its slot must not let the one behind it take * its index, which is what this getter reads as the peer. */ +#ifdef WOLFSSL_SIGNER_DER_CERT ExpectNotNull(sk = wolfSSL_get0_verified_chain(ssl)); ExpectIntEQ(test_chain_is_cert(wolfSSL_sk_X509_value(sk, 0), leafDer, leafSz), 1); +#else + /* Without its DER the CA cannot go on the chain. */ + ExpectNull(wolfSSL_get0_verified_chain(ssl)); +#endif ExpectIntEQ(wolfSSL_get_chain_count(wolfSSL_get_peer_chain(ssl)), 2); @@ -4565,6 +4647,205 @@ static int test_chain_slot_case_run(const test_chain_slot_case* tc, return EXPECT_RESULT(); } +#if !defined(NO_FILESYSTEM) && defined(WOLFSSL_SIGNER_DER_CERT) +/* Build a CA cert of key with the validity period of the cert datesDer: + * issued by issuerDer with issuerKey or, without issuerDer, self-signed. + * Returns the DER length, or < 0 on failure. */ +static int test_verified_chain_gen_ca(byte* out, int outMax, RsaKey* key, + const byte* issuerDer, int issuerDerSz, RsaKey* issuerKey, WC_RNG* rng, + const char* cn, const byte* datesDer, int datesDerSz) +{ + Cert cert; + int ret; + + if (wc_InitCert(&cert) != 0) { + return WOLFSSL_FATAL_ERROR; + } + cert.isCA = 1; + cert.sigType = CTC_SHA256wRSA; + XSTRNCPY(cert.subject.country, "US", CTC_NAME_SIZE - 1); + XSTRNCPY(cert.subject.org, "wolfSSL_test", CTC_NAME_SIZE - 1); + XSTRNCPY(cert.subject.commonName, cn, CTC_NAME_SIZE - 1); + ret = wc_SetDatesBuffer(&cert, datesDer, datesDerSz); + if (ret == 0) + ret = wc_SetSubjectKeyIdFromPublicKey(&cert, key, NULL); + if (ret == 0) + ret = wc_SetKeyUsage(&cert, "keyCertSign,cRLSign"); + if (ret == 0 && issuerDer == NULL) { + ret = wc_MakeSelfCert(&cert, out, (word32)outMax, key, rng); + } + else if (ret == 0) { + ret = wc_SetAuthKeyIdFromCert(&cert, issuerDer, issuerDerSz); + if (ret == 0) + ret = wc_SetIssuerBuffer(&cert, issuerDer, issuerDerSz); + if (ret == 0) + ret = wc_MakeCert(&cert, out, (word32)outMax, key, NULL, rng); + if (ret >= 0) + ret = wc_SignCert(cert.bodySz, cert.sigType, out, (word32)outMax, + issuerKey, NULL, rng); + } +#ifdef WOLFSSL_CERT_GEN_CACHE + wc_SetCert_Free(&cert); +#endif + + return ret; +} + +/* How the handshake of test_verified_chain_run() verifies the peer. */ +#define TEST_VCHAIN_NONE 0 /* not at all */ +#define TEST_VCHAIN_PEER 1 /* verified */ +#define TEST_VCHAIN_HOST 2 /* a verify callback accepts a host name error */ +#define TEST_VCHAIN_RESUME 3 /* verified, then resumed */ +#define TEST_VCHAIN_KEYSZ 4 /* verified, then CA keys must be 4096 bits */ + +static int test_verified_chain_accept(int ok, WOLFSSL_X509_STORE_CTX* store) +{ + (void)ok; + (void)store; + return 1; +} + +/* Check the verified chain of ssl: none when num is 0, else num certs, the + * peer's, issuerDer and ca-cert. */ +static int test_verified_chain_check(WOLFSSL* ssl, int num, + const byte* issuerDer, int issuerSz) +{ + EXPECT_DECLS; + WOLF_STACK_OF(WOLFSSL_X509)* sk = NULL; + WOLFSSL_X509* peer = NULL; + + sk = wolfSSL_get0_verified_chain(ssl); + if (num == 0) { + ExpectNull(sk); + } + else { + ExpectNotNull(peer = wolfSSL_get_peer_certificate(ssl)); + ExpectIntEQ(wolfSSL_sk_X509_num(sk), num); + ExpectIntEQ(wolfSSL_X509_cmp(wolfSSL_sk_X509_value(sk, 0), peer), 0); + ExpectIntEQ(test_chain_is_cert(wolfSSL_sk_X509_value(sk, 1), + issuerDer, issuerSz), 1); + if (num > 2) { + ExpectIntEQ(test_chain_is_cert(wolfSSL_sk_X509_value(sk, 2), + ca_cert_der_2048, (int)sizeof_ca_cert_der_2048), 1); + } + /* As OpenSSL, the same chain again */ + ExpectPtrEq(wolfSSL_get0_verified_chain(ssl), sk); + } + wolfSSL_X509_free(peer); + + return EXPECT_RESULT(); +} + +/* A handshake to a client that loads ca1 and ca2, when set, into its cert + * manager with their date errors allowed, or that verifies with store. The + * server sends peerDer. The handshake checks neither the dates of a CA of the + * cert manager nor that it is a CA; X509_verify_cert() does, failing with err + * at depth 1. The verified chain is checked as test_verified_chain_check() + * does, with num 0 when the handshake does not verify the peer. */ +static int test_verified_chain_run(const byte* ca1, int ca1Sz, + const byte* ca2, int ca2Sz, WOLFSSL_X509_STORE* store, + const byte* peerDer, int peerSz, const byte* issuerDer, int issuerSz, + int mode, int err, int num) +{ + EXPECT_DECLS; + WOLFSSL_CTX* ctx_c = NULL; + WOLFSSL_CTX* ctx_s = NULL; + WOLFSSL* ssl_c = NULL; + WOLFSSL* ssl_s = NULL; + struct test_memio_ctx test_ctx; + WOLFSSL_X509_STORE_CTX* storeCtx = NULL; + WOLFSSL_X509* peer = NULL; + WOLFSSL_SESSION* sess = NULL; +#ifndef WOLFSSL_NO_TLS12 + method_provider method_c = wolfTLSv1_2_client_method; + method_provider method_s = wolfTLSv1_2_server_method; +#else + method_provider method_c = wolfTLSv1_3_client_method; + method_provider method_s = wolfTLSv1_3_server_method; +#endif + + XMEMSET(&test_ctx, 0, sizeof(test_ctx)); + ExpectNotNull(ctx_c = wolfSSL_CTX_new(method_c())); + if (ctx_c != NULL) { + wolfSSL_SetIORecv(ctx_c, test_memio_read_cb); + wolfSSL_SetIOSend(ctx_c, test_memio_write_cb); + } + if (ca1 != NULL) { + ExpectIntEQ(wolfSSL_CTX_load_verify_buffer_ex(ctx_c, ca1, ca1Sz, + WOLFSSL_FILETYPE_ASN1, 0, WOLFSSL_LOAD_FLAG_DATE_ERR_OKAY), + WOLFSSL_SUCCESS); + } + if (ca2 != NULL) { + ExpectIntEQ(wolfSSL_CTX_load_verify_buffer_ex(ctx_c, ca2, ca2Sz, + WOLFSSL_FILETYPE_ASN1, 0, WOLFSSL_LOAD_FLAG_DATE_ERR_OKAY), + WOLFSSL_SUCCESS); + } + ExpectIntEQ(test_memio_setup_ex(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s, + method_c, method_s, NULL, 0, (byte*)peerDer, peerSz, + (byte*)client_key_der_2048, (int)sizeof_client_key_der_2048), 0); + if (store != NULL) { + ExpectIntEQ(wolfSSL_set1_verify_cert_store(ssl_c, store), + WOLFSSL_SUCCESS); + } + if (mode == TEST_VCHAIN_HOST) { + ExpectIntEQ(wolfSSL_X509_VERIFY_PARAM_set1_host( + wolfSSL_get0_param(ssl_c), "wrong.example.com", 0), + WOLFSSL_SUCCESS); + } + wolfSSL_set_verify(ssl_c, (mode == TEST_VCHAIN_NONE) ? + WOLFSSL_VERIFY_NONE : WOLFSSL_VERIFY_PEER, + (mode == TEST_VCHAIN_HOST) ? test_verified_chain_accept : NULL); + ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0); + ExpectIntEQ(wolfSSL_get_verify_result(ssl_c), (mode == TEST_VCHAIN_HOST) ? + WOLFSSL_X509_V_ERR_HOSTNAME_MISMATCH : WOLFSSL_X509_V_OK); + if (mode == TEST_VCHAIN_KEYSZ) { + ExpectIntEQ(wolfSSL_CTX_SetMinRsaKey_Sz(ctx_c, 4096), + WOLFSSL_SUCCESS); + } + + ExpectNotNull(peer = wolfSSL_get_peer_certificate(ssl_c)); + ExpectNotNull(storeCtx = wolfSSL_X509_STORE_CTX_new()); + ExpectIntEQ(wolfSSL_X509_STORE_CTX_init(storeCtx, (store != NULL) ? store : + wolfSSL_CTX_get_cert_store(ctx_c), peer, NULL), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_X509_verify_cert(storeCtx), WOLFSSL_FAILURE); + ExpectIntEQ(wolfSSL_X509_STORE_CTX_get_error(storeCtx), err); + ExpectIntEQ(wolfSSL_X509_STORE_CTX_get_error_depth(storeCtx), 1); + + ExpectIntEQ(test_verified_chain_check(ssl_c, + (mode == TEST_VCHAIN_PEER || mode == TEST_VCHAIN_RESUME) ? num : 0, + issuerDer, issuerSz), TEST_SUCCESS); + + if (mode == TEST_VCHAIN_RESUME) { + /* Resumed, the peer is not verified again: every check applies */ + ExpectNotNull(sess = wolfSSL_get1_session(ssl_c)); + wolfSSL_free(ssl_c); + ssl_c = NULL; + wolfSSL_free(ssl_s); + ssl_s = NULL; + XMEMSET(&test_ctx, 0, sizeof(test_ctx)); + ExpectIntEQ(test_memio_setup_ex(&test_ctx, &ctx_c, &ctx_s, &ssl_c, + &ssl_s, method_c, method_s, NULL, 0, (byte*)peerDer, peerSz, + (byte*)client_key_der_2048, (int)sizeof_client_key_der_2048), 0); + wolfSSL_set_verify(ssl_c, WOLFSSL_VERIFY_PEER, NULL); + ExpectIntEQ(wolfSSL_set_session(ssl_c, sess), WOLFSSL_SUCCESS); + ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0); + ExpectIntEQ(wolfSSL_session_reused(ssl_c), 1); + ExpectIntEQ(wolfSSL_get_verify_result(ssl_c), WOLFSSL_X509_V_OK); + ExpectIntEQ(test_verified_chain_check(ssl_c, 0, NULL, 0), + TEST_SUCCESS); + } + + wolfSSL_SESSION_free(sess); + wolfSSL_X509_STORE_CTX_free(storeCtx); + wolfSSL_X509_free(peer); + wolfSSL_free(ssl_s); + wolfSSL_free(ssl_c); + wolfSSL_CTX_free(ctx_s); + wolfSSL_CTX_free(ctx_c); + + return EXPECT_RESULT(); +} +#endif /* !NO_FILESYSTEM && WOLFSSL_SIGNER_DER_CERT */ #endif /* session chain slot test dependencies */ /* Test that a certificate too large for a session chain slot does not let the @@ -4678,6 +4959,180 @@ int test_wolfSSL_session_chain_oversized_cert(void) #endif return EXPECT_RESULT(); } + +/* Test that the verified chain is the one the handshake verified, also when + * X509_verify_cert() rejects a CA of the cert manager that has expired or is + * not a CA, the trust anchor or not. Only those errors of only such a CA, and + * only after a full handshake that verified the peer, are not failed. + * + * @return TEST_SUCCESS on success. + */ +int test_wolfSSL_get0_verified_chain_anchor(void) +{ + EXPECT_DECLS; +#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && !defined(NO_RSA) && \ + !defined(NO_TLS) && !defined(NO_SHA256) && !defined(NO_ASN_TIME) && \ + defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_EXT) && \ + defined(WOLFSSL_ALT_NAMES) && defined(USE_CERT_BUFFERS_2048) && \ + defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) && \ + defined(KEEP_PEER_CERT) && !defined(IGNORE_KEY_EXTENSIONS) && \ + (!defined(WOLFSSL_NO_TLS12) || defined(WOLFSSL_TLS13)) && \ + !defined(NO_FILESYSTEM) && defined(WOLFSSL_SIGNER_DER_CERT) + WC_RNG rng; + RsaKey caKey; + RsaKey interKey; + RsaKey leafKey; + WOLFSSL_X509* expired = NULL; + WOLFSSL_X509* x509 = NULL; + WOLFSSL_X509_STORE* store = NULL; + const byte* expiredDer = NULL; + const byte* caDer = ca_cert_der_2048; + int caSz = (int)sizeof_ca_cert_der_2048; + byte* anchorDer = NULL; + byte* interDer = NULL; + byte* leafDer = NULL; + byte* chainDer = NULL; + int expiredSz = 0; + int anchorSz = 0; + int interSz = 0; + int leafSz = 0; + int rngInit = 0; + int caInit = 0; + int interInit = 0; + int leafInit = 0; + word32 idx; + + ExpectNotNull(anchorDer = (byte*)XMALLOC(TEST_CHAIN_BUF_SZ, NULL, + DYNAMIC_TYPE_TMP_BUFFER)); + ExpectNotNull(interDer = (byte*)XMALLOC(TEST_CHAIN_BUF_SZ, NULL, + DYNAMIC_TYPE_TMP_BUFFER)); + ExpectNotNull(leafDer = (byte*)XMALLOC(TEST_CHAIN_BUF_SZ, NULL, + DYNAMIC_TYPE_TMP_BUFFER)); + ExpectNotNull(chainDer = (byte*)XMALLOC(2 * TEST_CHAIN_BUF_SZ, NULL, + DYNAMIC_TYPE_TMP_BUFFER)); + ExpectIntEQ(wc_InitRng(&rng), 0); + if (EXPECT_SUCCESS()) rngInit = 1; + ExpectIntEQ(wc_InitRsaKey(&caKey, NULL), 0); + if (EXPECT_SUCCESS()) caInit = 1; + idx = 0; + ExpectIntEQ(wc_RsaPrivateKeyDecode(ca_key_der_2048, &idx, &caKey, + (word32)sizeof_ca_key_der_2048), 0); + ExpectIntEQ(wc_InitRsaKey(&interKey, NULL), 0); + if (EXPECT_SUCCESS()) interInit = 1; + idx = 0; + ExpectIntEQ(wc_RsaPrivateKeyDecode(server_key_der_2048, &idx, &interKey, + (word32)sizeof_server_key_der_2048), 0); + ExpectIntEQ(wc_InitRsaKey(&leafKey, NULL), 0); + if (EXPECT_SUCCESS()) leafInit = 1; + idx = 0; + ExpectIntEQ(wc_RsaPrivateKeyDecode(client_key_der_2048, &idx, &leafKey, + (word32)sizeof_client_key_der_2048), 0); + + /* A CA that expired in 2018 */ + ExpectNotNull(expired = wolfSSL_X509_load_certificate_file( + "./certs/test/expired/expired-ca.der", WOLFSSL_FILETYPE_ASN1)); + ExpectNotNull(expiredDer = wolfSSL_X509_get_der(expired, &expiredSz)); + + /* The trust anchor expired */ + ExpectIntGT((anchorSz = test_verified_chain_gen_ca(anchorDer, + TEST_CHAIN_BUF_SZ, &caKey, NULL, 0, NULL, &rng, "Expired Anchor", + expiredDer, expiredSz)), 0); + ExpectIntGT((leafSz = test_chain_gen_cert(leafDer, TEST_CHAIN_BUF_SZ, + &leafKey, anchorDer, anchorSz, &caKey, &rng, "Expired Anchor Leaf", 0, + 0)), 0); + ExpectIntEQ(test_verified_chain_run(anchorDer, anchorSz, NULL, 0, NULL, + leafDer, leafSz, anchorDer, anchorSz, TEST_VCHAIN_PEER, + WOLFSSL_X509_V_ERR_CERT_HAS_EXPIRED, 2), TEST_SUCCESS); + ExpectIntEQ(test_verified_chain_run(anchorDer, anchorSz, NULL, 0, NULL, + leafDer, leafSz, anchorDer, anchorSz, TEST_VCHAIN_NONE, + WOLFSSL_X509_V_ERR_CERT_HAS_EXPIRED, 2), TEST_SUCCESS); + ExpectIntEQ(test_verified_chain_run(anchorDer, anchorSz, NULL, 0, NULL, + leafDer, leafSz, anchorDer, anchorSz, TEST_VCHAIN_HOST, + WOLFSSL_X509_V_ERR_CERT_HAS_EXPIRED, 2), TEST_SUCCESS); +#if !defined(WOLFSSL_NO_TLS12) && !defined(NO_SESSION_CACHE) + ExpectIntEQ(test_verified_chain_run(anchorDer, anchorSz, NULL, 0, NULL, + leafDer, leafSz, anchorDer, anchorSz, TEST_VCHAIN_RESUME, + WOLFSSL_X509_V_ERR_CERT_HAS_EXPIRED, 2), TEST_SUCCESS); +#endif + + /* An intermediate that expired, below ca-cert */ + ExpectIntGT((interSz = test_verified_chain_gen_ca(interDer, + TEST_CHAIN_BUF_SZ, &interKey, caDer, caSz, &caKey, &rng, + "Expired Int", expiredDer, expiredSz)), 0); + ExpectIntGT((leafSz = test_chain_gen_cert(leafDer, TEST_CHAIN_BUF_SZ, + &leafKey, interDer, interSz, &interKey, &rng, "Expired Int Leaf", 0, + 0)), 0); + ExpectIntEQ(test_verified_chain_run(caDer, caSz, interDer, interSz, NULL, + leafDer, leafSz, interDer, interSz, TEST_VCHAIN_PEER, + WOLFSSL_X509_V_ERR_CERT_HAS_EXPIRED, 3), TEST_SUCCESS); + + /* A cert that is not a CA, issued by ca-cert, alone and below it */ + ExpectIntGT((anchorSz = test_chain_gen_cert(anchorDer, TEST_CHAIN_BUF_SZ, + &interKey, caDer, caSz, &caKey, &rng, "Not CA Anchor", 0, 0)), 0); + ExpectIntGT((leafSz = test_chain_gen_cert(leafDer, TEST_CHAIN_BUF_SZ, + &leafKey, anchorDer, anchorSz, &interKey, &rng, "Not CA Anchor Leaf", + 0, 0)), 0); + ExpectIntEQ(test_verified_chain_run(anchorDer, anchorSz, NULL, 0, NULL, + leafDer, leafSz, anchorDer, anchorSz, TEST_VCHAIN_PEER, + WOLFSSL_X509_V_ERR_INVALID_CA, 2), TEST_SUCCESS); + ExpectIntEQ(test_verified_chain_run(anchorDer, anchorSz, NULL, 0, NULL, + leafDer, leafSz, anchorDer, anchorSz, TEST_VCHAIN_NONE, + WOLFSSL_X509_V_ERR_INVALID_CA, 2), TEST_SUCCESS); + ExpectIntEQ(test_verified_chain_run(caDer, caSz, anchorDer, anchorSz, + NULL, leafDer, leafSz, anchorDer, anchorSz, TEST_VCHAIN_PEER, + WOLFSSL_X509_V_ERR_INVALID_CA, 3), TEST_SUCCESS); + + /* Any other error of such a CA fails: a key that is now too small */ + ExpectIntGT((interSz = test_chain_gen_cert(interDer, TEST_CHAIN_BUF_SZ, + &interKey, caDer, caSz, &caKey, &rng, "Valid Int", 1, 0)), 0); + ExpectIntGT((leafSz = test_chain_gen_cert(leafDer, TEST_CHAIN_BUF_SZ, + &leafKey, interDer, interSz, &interKey, &rng, "Valid Int Leaf", 0, + 0)), 0); + ExpectIntEQ(test_verified_chain_run(caDer, caSz, interDer, interSz, NULL, + leafDer, leafSz, interDer, interSz, TEST_VCHAIN_KEYSZ, + WOLFSSL_X509_V_ERR_CA_KEY_TOO_SMALL, 0), TEST_SUCCESS); + + /* An expired intermediate that only a store of its own trusts, outside + * its cert manager, while the peer sends a valid one of the same name + * and key that ca-cert issued */ + ExpectIntGT((interSz = test_verified_chain_gen_ca(interDer, + TEST_CHAIN_BUF_SZ, &interKey, caDer, caSz, &caKey, &rng, "Store Int", + expiredDer, expiredSz)), 0); + ExpectIntGT((anchorSz = test_chain_gen_cert(anchorDer, TEST_CHAIN_BUF_SZ, + &interKey, caDer, caSz, &caKey, &rng, "Store Int", 1, 0)), 0); + ExpectIntGT((leafSz = test_chain_gen_cert(leafDer, TEST_CHAIN_BUF_SZ, + &leafKey, anchorDer, anchorSz, &interKey, &rng, "Store Int Leaf", 0, + 0)), 0); + if (EXPECT_SUCCESS()) { + XMEMCPY(chainDer, leafDer, (size_t)leafSz); + XMEMCPY(chainDer + leafSz, anchorDer, (size_t)anchorSz); + } + ExpectNotNull(store = wolfSSL_X509_STORE_new()); + ExpectNotNull(x509 = wolfSSL_X509_d2i(NULL, caDer, caSz)); + ExpectIntEQ(wolfSSL_X509_STORE_add_cert(store, x509), WOLFSSL_SUCCESS); + wolfSSL_X509_free(x509); + x509 = NULL; + ExpectNotNull(x509 = wolfSSL_X509_d2i(NULL, interDer, interSz)); + ExpectIntEQ(wolfSSL_X509_STORE_add_cert(store, x509), WOLFSSL_SUCCESS); + wolfSSL_X509_free(x509); + x509 = NULL; + ExpectIntEQ(test_verified_chain_run(NULL, 0, NULL, 0, store, chainDer, + leafSz + anchorSz, NULL, 0, TEST_VCHAIN_PEER, + WOLFSSL_X509_V_ERR_CERT_HAS_EXPIRED, 0), TEST_SUCCESS); + + wolfSSL_X509_STORE_free(store); + wolfSSL_X509_free(expired); + if (rngInit) wc_FreeRng(&rng); + if (caInit) wc_FreeRsaKey(&caKey); + if (interInit) wc_FreeRsaKey(&interKey); + if (leafInit) wc_FreeRsaKey(&leafKey); + XFREE(anchorDer, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(interDer, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(leafDer, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(chainDer, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return EXPECT_RESULT(); +} #if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && !defined(NO_RSA) && \ !defined(NO_TLS) && !defined(NO_SHA256) && !defined(NO_ASN_TIME) && \ defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_EXT) && \ diff --git a/tests/api/test_ssl_cert.h b/tests/api/test_ssl_cert.h index 952e007321e..2b54d458daf 100644 --- a/tests/api/test_ssl_cert.h +++ b/tests/api/test_ssl_cert.h @@ -50,6 +50,7 @@ int test_wolfSSL_cert_setup_cb_ret(void); int test_wolfSSL_get_peer_cert_chain(void); int test_wolfSSL_set_peer_cert_chain(void); int test_wolfSSL_get0_verified_chain(void); +int test_wolfSSL_get0_verified_chain_anchor(void); int test_wolfSSL_CA_list_add(void); int test_wolfSSL_CA_list_get(void); int test_wolfSSL_load_client_CA_file(void); @@ -99,6 +100,8 @@ int test_wolfSSL_SESSION_get0_peer_full_chain(void); TEST_DECL_GROUP("ssl_cert", test_wolfSSL_get_peer_cert_chain), \ TEST_DECL_GROUP("ssl_cert", test_wolfSSL_set_peer_cert_chain), \ TEST_DECL_GROUP("ssl_cert", test_wolfSSL_get0_verified_chain), \ + TEST_DECL_GROUP("ssl_cert", \ + test_wolfSSL_get0_verified_chain_anchor), \ TEST_DECL_GROUP("ssl_cert", test_wolfSSL_CA_list_add), \ TEST_DECL_GROUP("ssl_cert", test_wolfSSL_CA_list_get), \ TEST_DECL_GROUP("ssl_cert", test_wolfSSL_load_client_CA_file), \ diff --git a/tests/api/test_tls.c b/tests/api/test_tls.c index b8b8b29b46c..a6414567f73 100644 --- a/tests/api/test_tls.c +++ b/tests/api/test_tls.c @@ -763,6 +763,48 @@ int test_tls_check_domain_name_single_label(void) return EXPECT_RESULT(); } +/* As in OpenSSL, the X509_STRICT and NO_CHECK_TIME flags of a connection do + * not reach the store of its SSL_CTX. */ +int test_tls_param_flags_not_on_store(void) +{ + EXPECT_DECLS; +#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(OPENSSL_EXTRA) && \ + !defined(NO_RSA) && !defined(NO_CERTS) && !defined(NO_FILESYSTEM) && \ + !defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER) && \ + !defined(NO_SHA256) && !defined(NO_ASN_TIME) + WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL; + WOLFSSL *ssl_c = NULL, *ssl_s = NULL; + struct test_memio_ctx test_ctx; + WOLFSSL_X509_STORE* store = NULL; + WOLFSSL_X509* expired = NULL; + unsigned long flags = WOLFSSL_NO_CHECK_TIME | WOLFSSL_X509_STRICT; + + XMEMSET(&test_ctx, 0, sizeof(test_ctx)); + ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s, + wolfSSLv23_client_method, wolfSSLv23_server_method), 0); + wolfSSL_set_verify(ssl_c, WOLFSSL_VERIFY_PEER, NULL); + ExpectIntEQ(wolfSSL_X509_VERIFY_PARAM_set_flags(wolfSSL_get0_param(ssl_c), + flags), WOLFSSL_SUCCESS); + ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0); + + ExpectNotNull(store = wolfSSL_CTX_get_cert_store(ctx_c)); + ExpectIntEQ(wolfSSL_X509_VERIFY_PARAM_get_flags( + wolfSSL_X509_STORE_get0_param(store)) & flags, 0); + /* An expired CA still does not become a signer */ + ExpectNotNull(expired = wolfSSL_X509_load_certificate_file( + "./certs/test/expired/expired-ca.pem", WOLFSSL_FILETYPE_PEM)); + ExpectIntNE(wolfSSL_X509_STORE_add_cert(store, expired), + WOLFSSL_SUCCESS); + + wolfSSL_X509_free(expired); + wolfSSL_free(ssl_c); + wolfSSL_free(ssl_s); + wolfSSL_CTX_free(ctx_c); + wolfSSL_CTX_free(ctx_s); +#endif + return EXPECT_RESULT(); +} + /* One macro per group test_tls_get_peer_tmp_key() can exercise, so that the * helper below is never compiled without a caller. */ #if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(OPENSSL_EXTRA) && \ diff --git a/tests/api/test_tls.h b/tests/api/test_tls.h index 0c5a30b1ef4..af7c666fbda 100644 --- a/tests/api/test_tls.h +++ b/tests/api/test_tls.h @@ -132,6 +132,7 @@ int test_wolfSSL_get_shared_ciphers(void); int test_tls12_aesgcm_record_nonce_unique(void); int test_tls_param_flags_crl_check(void); int test_tls_hmac_inner_cid_decision_coverage(void); +int test_tls_param_flags_not_on_store(void); #define TEST_TLS_DECLS \ TEST_DECL_GROUP("tls", test_utils_memio_move_message), \ @@ -235,6 +236,7 @@ int test_tls_hmac_inner_cid_decision_coverage(void); TEST_DECL_GROUP("tls", test_wolfSSL_get_shared_ciphers), \ TEST_DECL_GROUP("tls", test_tls12_aesgcm_record_nonce_unique), \ TEST_DECL_GROUP("tls", test_tls_param_flags_crl_check), \ + TEST_DECL_GROUP("tls", test_tls_param_flags_not_on_store), \ TEST_DECL_GROUP("tls", test_dhe_psk_max_premaster), \ TEST_DECL_GROUP("tls", test_tls12_chain_verify_cb), \ TEST_DECL_GROUP("tls", test_tls12_chain_verify_cb_server), \ diff --git a/tests/api/test_x509.c b/tests/api/test_x509.c index 85df3aba4bc..46077df7bb2 100644 --- a/tests/api/test_x509.c +++ b/tests/api/test_x509.c @@ -840,6 +840,9 @@ int test_x509_CertFromX509_akid_overflow(void) unsigned char* akid_val = NULL; WOLFSSL_X509* x = NULL; WOLFSSL_BIO* bio = NULL; + WOLFSSL_EVP_PKEY* pkey = NULL; + const unsigned char* keyDer = ecc_key_der_256; + char* bioData = NULL; #ifdef WOLFSSL_SMALL_STACK buf = (unsigned char*)XMALLOC(16384, NULL, DYNAMIC_TYPE_TMP_BUFFER); @@ -1038,13 +1041,21 @@ int test_x509_CertFromX509_akid_overflow(void) x = wolfSSL_X509_d2i(NULL, buf, (int)pos); ExpectNotNull(x); - /* Attempt re-encode via i2d_X509_bio -- must fail gracefully, not - * overflow. Before the fix this would write ~4000 bytes past the - * end of cert->akid[]. */ + /* i2d_X509_bio writes the parsed DER, it does not re-encode. */ bio = wolfSSL_BIO_new(wolfSSL_BIO_s_mem()); ExpectNotNull(bio); - ExpectIntEQ(wolfSSL_i2d_X509_bio(bio, x), 0); + ExpectIntEQ(wolfSSL_i2d_X509_bio(bio, x), 1); + ExpectIntEQ(wolfSSL_BIO_get_mem_data(bio, &bioData), (int)pos); + ExpectBufEQ(bioData, buf, pos); + + /* Attempt re-encode via X509_sign -- must fail gracefully, not + * overflow. Before the fix this would write ~4000 bytes past the + * end of cert->akid[]. */ + ExpectNotNull(pkey = wolfSSL_d2i_PrivateKey(WC_EVP_PKEY_EC, NULL, &keyDer, + (long)sizeof_ecc_key_der_256)); + ExpectIntEQ(wolfSSL_X509_sign(x, pkey, wolfSSL_EVP_sha256()), 0); + wolfSSL_EVP_PKEY_free(pkey); wolfSSL_BIO_free(bio); wolfSSL_X509_free(x); XFREE(akid_val, NULL, DYNAMIC_TYPE_TMP_BUFFER); @@ -1134,6 +1145,9 @@ int test_x509_ReqCertFromX509_skid_overflow(void) WOLFSSL_X509* req = NULL; WOLFSSL_BIO* bio = NULL; + WOLFSSL_EVP_PKEY* pkey = NULL; + const unsigned char* keyDer = ecc_key_der_256; + char* bioData = NULL; /* Step 1: Parse the crafted CSR -- this should succeed (the parser * dynamically allocates subjKeyId to the parsed size). */ @@ -1141,13 +1155,23 @@ int test_x509_ReqCertFromX509_skid_overflow(void) (int)sizeof(crafted_csr_der)); ExpectNotNull(req); - /* Step 2: Attempt to re-encode. Before the fix, this triggered a - * heap buffer overflow in ReqCertFromX509() writing 64 bytes into - * cert->skid[32]. With the fix, it must return failure. */ + /* i2d_X509_REQ_bio writes the parsed DER, it does not re-encode. */ bio = wolfSSL_BIO_new(wolfSSL_BIO_s_mem()); ExpectNotNull(bio); - ExpectIntNE(wolfSSL_i2d_X509_REQ_bio(bio, req), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_i2d_X509_REQ_bio(bio, req), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_BIO_get_mem_data(bio, &bioData), + (int)sizeof(crafted_csr_der)); + ExpectBufEQ(bioData, crafted_csr_der, sizeof(crafted_csr_der)); + + /* Step 2: Attempt to re-encode via X509_REQ_sign. Before the fix, this + * triggered a heap buffer overflow in ReqCertFromX509() writing 64 bytes + * into cert->skid[32]. With the fix, it must return failure. */ + ExpectNotNull(pkey = wolfSSL_d2i_PrivateKey(WC_EVP_PKEY_EC, NULL, &keyDer, + (long)sizeof_ecc_key_der_256)); + ExpectIntNE(wolfSSL_X509_REQ_sign(req, pkey, wolfSSL_EVP_sha256()), + WOLFSSL_SUCCESS); + wolfSSL_EVP_PKEY_free(pkey); wolfSSL_BIO_free(bio); wolfSSL_X509_free(req); #endif @@ -1485,3 +1509,438 @@ int test_x509_decision_coverage(void) #endif return EXPECT_RESULT(); } + +/* Test that i2d_X509_REQ() writes a parsed request as it was read and writes + * nothing for a request that was never signed. */ +int test_x509_REQ_i2d_stored_der(void) +{ + EXPECT_DECLS; +#if defined(WOLFSSL_CERT_REQ) && defined(WOLFSSL_CERT_GEN) && \ + defined(WOLFSSL_CERT_EXT) && !defined(NO_BIO) && \ + (defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)) && \ + !defined(NO_FILESYSTEM) && !defined(NO_RSA) && defined(HAVE_ECC) + const char* csrFiles[] = { + "./certs/csr.attr.der", + "./certs/csr.ext.der", + "./certs/csr.signed.der", + #ifndef NO_DSA + "./certs/csr.dsa.der", + #endif + }; + byte buf[1024]; + int bufSz = 0; + XFILE f = XBADFILE; + WOLFSSL_X509* req = NULL; + WOLFSSL_X509* parsed = NULL; + WOLFSSL_X509_NAME* name = NULL; + WOLFSSL_X509_EXTENSION* ext = NULL; + WOLF_STACK_OF(WOLFSSL_X509_EXTENSION)* exts = NULL; + WOLFSSL_EVP_PKEY* priv = NULL; + WOLFSSL_EVP_PKEY* pub = NULL; + const unsigned char* ecPriv = ecc_clikey_der_256; + const unsigned char* ecPub = ecc_clikeypub_der_256; + unsigned char* der = NULL; + int derSz = 0; + size_t i; + + for (i = 0; i < sizeof(csrFiles) / sizeof(csrFiles[0]); i++) { + ExpectTrue((f = XFOPEN(csrFiles[i], "rb")) != XBADFILE); + ExpectIntGT(bufSz = (int)XFREAD(buf, 1, sizeof(buf), f), 0); + if (f != XBADFILE) { + XFCLOSE(f); + f = XBADFILE; + } + ExpectNotNull(req = wolfSSL_X509_REQ_d2i(NULL, buf, bufSz)); + ExpectIntEQ(derSz = wolfSSL_i2d_X509_REQ(req, &der), bufSz); + ExpectBufEQ(der, buf, bufSz); + XFREE(der, NULL, DYNAMIC_TYPE_OPENSSL); + der = NULL; + wolfSSL_X509_free(req); + req = NULL; + } + + ExpectNotNull(priv = wolfSSL_d2i_PrivateKey(WC_EVP_PKEY_EC, NULL, &ecPriv, + (long)sizeof_ecc_clikey_der_256)); + ExpectNotNull(pub = wolfSSL_d2i_PUBKEY(NULL, &ecPub, + (long)sizeof_ecc_clikeypub_der_256)); + ExpectNotNull(req = wolfSSL_X509_REQ_new()); + ExpectNotNull(name = wolfSSL_X509_NAME_new()); + ExpectIntEQ(wolfSSL_X509_NAME_add_entry_by_txt(name, "commonName", + MBSTRING_UTF8, (const byte*)"Test", 4, -1, 0), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_X509_REQ_set_subject_name(req, name), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_X509_REQ_set_pubkey(req, pub), WOLFSSL_SUCCESS); + ExpectNotNull(ext = wolfSSL_X509V3_EXT_nconf_nid(NULL, NULL, + WC_NID_key_usage, "digitalSignature")); + ExpectNotNull(exts = wolfSSL_sk_X509_EXTENSION_new_null()); + ExpectIntEQ(wolfSSL_sk_X509_EXTENSION_push(exts, ext), 1); + if (EXPECT_FAIL()) { + wolfSSL_X509_EXTENSION_free(ext); + } + ExpectIntEQ(wolfSSL_X509_REQ_add_extensions(req, exts), WOLFSSL_SUCCESS); + + /* Not signed yet. */ + ExpectNull(wolfSSL_X509_get_der(req, &derSz)); + ExpectIntLE(wolfSSL_i2d_X509_REQ(req, &der), 0); + ExpectNull(der); + + ExpectIntEQ(wolfSSL_X509_REQ_sign(req, priv, wolfSSL_EVP_sha256()), + WOLFSSL_SUCCESS); + ExpectIntGT(derSz = wolfSSL_i2d_X509_REQ(req, &der), 0); + ExpectNotNull(parsed = wolfSSL_X509_REQ_d2i(NULL, der, derSz)); + ExpectIntEQ(wolfSSL_X509_REQ_verify(parsed, pub), WOLFSSL_SUCCESS); + if (parsed != NULL) { + ExpectIntEQ(parsed->keyUsageSet, 1); + ExpectIntEQ(parsed->keyUsage, KEYUSE_DIGITAL_SIG); + } + + wolfSSL_X509_free(parsed); + XFREE(der, NULL, DYNAMIC_TYPE_OPENSSL); + wolfSSL_sk_X509_EXTENSION_pop_free(exts, wolfSSL_X509_EXTENSION_free); + wolfSSL_X509_NAME_free(name); + wolfSSL_X509_free(req); + wolfSSL_EVP_PKEY_free(pub); + wolfSSL_EVP_PKEY_free(priv); +#endif + return EXPECT_RESULT(); +} + +/* Test that X509_REQ_add_extensions() on a parsed request stores the whole + * request, with the new extension and the old signature. */ +int test_x509_REQ_add_extensions_parsed(void) +{ + EXPECT_DECLS; +#if defined(WOLFSSL_CERT_REQ) && defined(WOLFSSL_CERT_GEN) && \ + defined(WOLFSSL_CERT_EXT) && defined(WOLFSSL_ALT_NAMES) && \ + !defined(NO_BIO) && (defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)) && \ + !defined(NO_FILESYSTEM) && !defined(NO_RSA) + byte buf[1024]; + int bufSz = 0; + XFILE f = XBADFILE; + WOLFSSL_X509* req = NULL; + WOLFSSL_X509* parsed = NULL; + WOLFSSL_X509_EXTENSION* ext = NULL; + WOLF_STACK_OF(WOLFSSL_X509_EXTENSION)* exts = NULL; + WOLF_STACK_OF(WOLFSSL_X509_EXTENSION)* reqExts = NULL; + WOLFSSL_EVP_PKEY* pub = NULL; + const unsigned char* der = NULL; + int derSz = 0; + unsigned char* out = NULL; + + /* Has subjectAltName and keyUsage. */ + ExpectTrue((f = XFOPEN("./certs/csr.ext.der", "rb")) != XBADFILE); + ExpectIntGT(bufSz = (int)XFREAD(buf, 1, sizeof(buf), f), 0); + if (f != XBADFILE) { + XFCLOSE(f); + } + ExpectNotNull(req = wolfSSL_X509_REQ_d2i(NULL, buf, bufSz)); + ExpectNotNull(pub = wolfSSL_X509_get_pubkey(req)); + ExpectIntEQ(wolfSSL_X509_REQ_verify(req, pub), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_X509_get_ext_count(req), 2); + + ExpectNotNull(ext = wolfSSL_X509V3_EXT_nconf_nid(NULL, NULL, + WC_NID_ext_key_usage, "serverAuth")); + ExpectNotNull(exts = wolfSSL_sk_X509_EXTENSION_new_null()); + ExpectIntEQ(wolfSSL_sk_X509_EXTENSION_push(exts, ext), 1); + if (EXPECT_FAIL()) { + wolfSSL_X509_EXTENSION_free(ext); + } + ExpectIntEQ(wolfSSL_X509_REQ_add_extensions(req, exts), WOLFSSL_SUCCESS); + + ExpectIntEQ(wolfSSL_X509_get_ext_count(req), 3); + ExpectNotNull(reqExts = (WOLF_STACK_OF(WOLFSSL_X509_EXTENSION)*) + wolfSSL_X509_REQ_get_extensions(req)); + ExpectIntEQ(wolfSSL_sk_X509_EXTENSION_num(reqExts), 3); + + /* The stored encoding is the whole request. */ + ExpectNotNull(der = wolfSSL_X509_get_der(req, &derSz)); + ExpectNotNull(parsed = wolfSSL_X509_REQ_d2i(NULL, der, derSz)); + ExpectIntEQ(wolfSSL_X509_get_ext_count(parsed), 3); + ExpectIntGE(wolfSSL_X509_get_ext_by_NID(parsed, WC_NID_ext_key_usage, -1), + 0); + ExpectIntEQ(wolfSSL_i2d_X509_REQ(req, &out), derSz); + ExpectBufEQ(out, der, derSz); + + /* The old signature does not cover the new extension. */ + ExpectIntNE(wolfSSL_X509_REQ_verify(req, pub), WOLFSSL_SUCCESS); + + XFREE(out, NULL, DYNAMIC_TYPE_OPENSSL); + wolfSSL_X509_free(parsed); + wolfSSL_sk_X509_EXTENSION_pop_free(reqExts, wolfSSL_X509_EXTENSION_free); + wolfSSL_sk_X509_EXTENSION_pop_free(exts, wolfSSL_X509_EXTENSION_free); + wolfSSL_EVP_PKEY_free(pub); + wolfSSL_X509_free(req); +#endif + return EXPECT_RESULT(); +} + +/* Test that a signed request changed by X509_REQ_add_extensions() verifies + * again once it is signed again. */ +int test_x509_REQ_add_extensions_resign(void) +{ + EXPECT_DECLS; +#if defined(WOLFSSL_CERT_REQ) && defined(WOLFSSL_CERT_GEN) && \ + defined(WOLFSSL_CERT_EXT) && !defined(NO_BIO) && \ + (defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)) && !defined(NO_RSA) + WOLFSSL_X509* req = NULL; + WOLFSSL_X509* parsed = NULL; + WOLFSSL_X509_NAME* name = NULL; + WOLFSSL_X509_EXTENSION* ext = NULL; + WOLF_STACK_OF(WOLFSSL_X509_EXTENSION)* exts = NULL; + WOLFSSL_EVP_PKEY* priv = NULL; + WOLFSSL_EVP_PKEY* pub = NULL; + const unsigned char* rsaPriv = client_key_der_2048; + const unsigned char* rsaPub = client_keypub_der_2048; + unsigned char* der = NULL; + int derSz = 0; + + ExpectNotNull(priv = wolfSSL_d2i_PrivateKey(WC_EVP_PKEY_RSA, NULL, + &rsaPriv, (long)sizeof_client_key_der_2048)); + ExpectNotNull(pub = wolfSSL_d2i_PUBKEY(NULL, &rsaPub, + (long)sizeof_client_keypub_der_2048)); + ExpectNotNull(req = wolfSSL_X509_REQ_new()); + ExpectNotNull(name = wolfSSL_X509_NAME_new()); + ExpectIntEQ(wolfSSL_X509_NAME_add_entry_by_txt(name, "commonName", + MBSTRING_UTF8, (const byte*)"Test", 4, -1, 0), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_X509_REQ_set_subject_name(req, name), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_X509_REQ_set_pubkey(req, pub), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_X509_REQ_sign(req, priv, wolfSSL_EVP_sha256()), + WOLFSSL_SUCCESS); + ExpectIntGT(derSz = wolfSSL_i2d_X509_REQ(req, &der), 0); + ExpectNotNull(parsed = wolfSSL_X509_REQ_d2i(NULL, der, derSz)); + ExpectIntEQ(wolfSSL_X509_REQ_verify(parsed, pub), WOLFSSL_SUCCESS); + + ExpectNotNull(ext = wolfSSL_X509V3_EXT_nconf_nid(NULL, NULL, + WC_NID_ext_key_usage, "serverAuth")); + ExpectNotNull(exts = wolfSSL_sk_X509_EXTENSION_new_null()); + ExpectIntEQ(wolfSSL_sk_X509_EXTENSION_push(exts, ext), 1); + if (EXPECT_FAIL()) { + wolfSSL_X509_EXTENSION_free(ext); + } + ExpectIntEQ(wolfSSL_X509_REQ_add_extensions(parsed, exts), + WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_X509_get_ext_count(parsed), 1); + ExpectIntNE(wolfSSL_X509_REQ_verify(parsed, pub), WOLFSSL_SUCCESS); + + ExpectIntEQ(wolfSSL_X509_REQ_sign(parsed, priv, wolfSSL_EVP_sha256()), + WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_X509_get_ext_count(parsed), 1); + ExpectIntEQ(wolfSSL_X509_REQ_verify(parsed, pub), WOLFSSL_SUCCESS); + + wolfSSL_X509_free(parsed); + XFREE(der, NULL, DYNAMIC_TYPE_OPENSSL); + wolfSSL_sk_X509_EXTENSION_pop_free(exts, wolfSSL_X509_EXTENSION_free); + wolfSSL_X509_NAME_free(name); + wolfSSL_X509_free(req); + wolfSSL_EVP_PKEY_free(pub); + wolfSSL_EVP_PKEY_free(priv); +#endif + return EXPECT_RESULT(); +} + +/* Test that a request changed by a setter is encoded again, with its old + * signature, as in OpenSSL, while a certificate keeps its stored encoding + * until it is signed again, as in OpenSSL 3.0. */ +int test_x509_REQ_setters_reencode(void) +{ + EXPECT_DECLS; +#if defined(WOLFSSL_CERT_REQ) && defined(WOLFSSL_CERT_GEN) && \ + !defined(NO_BIO) && (defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)) && \ + !defined(NO_FILESYSTEM) && !defined(NO_RSA) + WOLFSSL_X509* req = NULL; + WOLFSSL_X509* x509 = NULL; + WOLFSSL_X509* parsed = NULL; + WOLFSSL_X509_NAME* name = NULL; + WOLFSSL_X509_NAME* same = NULL; + WOLFSSL_EVP_PKEY* pub = NULL; + WOLFSSL_EVP_PKEY* newPub = NULL; + WOLFSSL_BIO* bio = NULL; + XFILE f = XBADFILE; + byte fileDer[1024]; + int fileSz = 0; + WOLFSSL_EVP_PKEY* parsedPub = NULL; + unsigned char* keyA = NULL; + unsigned char* keyB = NULL; + int keySz = 0; + unsigned char* der = NULL; + int derSz = 0; + char cn[64]; + int i; + + ExpectNotNull(name = wolfSSL_X509_NAME_new()); + ExpectIntEQ(wolfSSL_X509_NAME_add_entry_by_txt(name, "commonName", + MBSTRING_UTF8, (const byte*)"changed", -1, -1, 0), WOLFSSL_SUCCESS); + + for (i = 0; i < 2; i++) { + ExpectNotNull(bio = wolfSSL_BIO_new_file("./certs/csr.signed.der", + "rb")); + ExpectNotNull(req = wolfSSL_d2i_X509_REQ_bio(bio, NULL)); + wolfSSL_BIO_free(bio); + bio = NULL; + ExpectNotNull(pub = wolfSSL_X509_get_pubkey(req)); + ExpectIntEQ(wolfSSL_X509_REQ_verify(req, pub), WOLFSSL_SUCCESS); + if (i == 0) { + ExpectIntEQ(wolfSSL_X509_REQ_set_subject_name(req, name), + WOLFSSL_SUCCESS); + } + else { + ExpectIntEQ(wolfSSL_X509_REQ_add1_attr_by_NID(req, + WC_NID_pkcs9_challengePassword, WOLFSSL_MBSTRING_ASC, + (const unsigned char*)"password", -1), WOLFSSL_SUCCESS); + } + /* The old signature no longer verifies */ + ExpectIntNE(wolfSSL_X509_REQ_verify(req, pub), WOLFSSL_SUCCESS); + + ExpectNotNull(bio = wolfSSL_BIO_new(wolfSSL_BIO_s_mem())); + ExpectIntEQ(wolfSSL_i2d_X509_REQ_bio(bio, req), WOLFSSL_SUCCESS); + ExpectNotNull(parsed = wolfSSL_d2i_X509_REQ_bio(bio, NULL)); + if (i == 0) { + ExpectIntGT(wolfSSL_X509_NAME_get_text_by_NID( + wolfSSL_X509_get_subject_name(parsed), WC_NID_commonName, cn, + (int)sizeof(cn)), 0); + ExpectStrEQ(cn, "changed"); + } + else { + if (parsed != NULL) { + ExpectStrEQ(parsed->challengePw, "password"); + } + #ifdef OPENSSL_ALL + /* Only then are the attributes of a parsed request kept */ + ExpectIntGE(wolfSSL_X509_REQ_get_attr_by_NID(parsed, + WC_NID_pkcs9_challengePassword, -1), 0); + #endif + } + wolfSSL_X509_free(parsed); + parsed = NULL; + wolfSSL_BIO_free(bio); + bio = NULL; + wolfSSL_EVP_PKEY_free(pub); + pub = NULL; + wolfSSL_X509_free(req); + req = NULL; + } + + /* As OpenSSL, the version is the value of its field, and a field set to + * what it holds leaves the request as it was */ + ExpectTrue((f = XFOPEN("./certs/csr.signed.der", "rb")) != XBADFILE); + ExpectIntGT(fileSz = (int)XFREAD(fileDer, 1, sizeof(fileDer), f), 0); + if (f != XBADFILE) { + XFCLOSE(f); + } + ExpectNotNull(req = wolfSSL_X509_REQ_d2i(NULL, fileDer, fileSz)); + ExpectIntEQ(wolfSSL_X509_REQ_get_version(req), 0); + ExpectNotNull(same = wolfSSL_X509_NAME_dup( + wolfSSL_X509_get_subject_name(req))); + ExpectIntEQ(wolfSSL_X509_REQ_set_subject_name(req, same), WOLFSSL_SUCCESS); + ExpectNotNull(pub = wolfSSL_X509_get_pubkey(req)); + ExpectIntEQ(wolfSSL_X509_REQ_set_pubkey(req, pub), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_X509_REQ_set_version(req, 0), WOLFSSL_SUCCESS); + ExpectIntEQ(derSz = wolfSSL_i2d_X509_REQ(req, &der), fileSz); + ExpectBufEQ(der, fileDer, fileSz); + ExpectIntEQ(wolfSSL_X509_REQ_verify(req, pub), WOLFSSL_SUCCESS); + XFREE(der, NULL, DYNAMIC_TYPE_OPENSSL); + der = NULL; + + /* Another version and key are encoded */ + ExpectNotNull(x509 = wolfSSL_X509_load_certificate_file(svrCertFile, + WOLFSSL_FILETYPE_PEM)); + ExpectNotNull(newPub = wolfSSL_X509_get_pubkey(x509)); + ExpectIntEQ(wolfSSL_X509_REQ_set_version(req, 1), WOLFSSL_SUCCESS); + ExpectIntGT(derSz = wolfSSL_i2d_X509_REQ(req, &der), 0); + ExpectNotNull(parsed = wolfSSL_X509_REQ_d2i(NULL, der, derSz)); + ExpectIntEQ(wolfSSL_X509_REQ_get_version(parsed), 1); + XFREE(der, NULL, DYNAMIC_TYPE_OPENSSL); + der = NULL; + wolfSSL_X509_free(parsed); + parsed = NULL; + ExpectIntEQ(wolfSSL_X509_REQ_set_pubkey(req, newPub), WOLFSSL_SUCCESS); + ExpectIntGT(derSz = wolfSSL_i2d_X509_REQ(req, &der), 0); + ExpectNotNull(parsed = wolfSSL_X509_REQ_d2i(NULL, der, derSz)); + ExpectNotNull(parsedPub = wolfSSL_X509_get_pubkey(parsed)); + ExpectIntGT(keySz = wolfSSL_i2d_PUBKEY(parsedPub, &keyA), 0); + ExpectIntEQ(wolfSSL_i2d_PUBKEY(newPub, &keyB), keySz); + ExpectBufEQ(keyA, keyB, keySz); + XFREE(keyA, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + XFREE(keyB, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + XFREE(der, NULL, DYNAMIC_TYPE_OPENSSL); + der = NULL; + wolfSSL_EVP_PKEY_free(parsedPub); + wolfSSL_X509_free(parsed); + parsed = NULL; + wolfSSL_EVP_PKEY_free(newPub); + wolfSSL_EVP_PKEY_free(pub); + wolfSSL_X509_NAME_free(same); + wolfSSL_X509_free(req); + req = NULL; + +#ifndef NO_DSA + /* A DSA request cannot be encoded again: the change stands and no + * encoding out of date is kept */ + ExpectNotNull(bio = wolfSSL_BIO_new_file("./certs/csr.dsa.der", "rb")); + ExpectNotNull(req = wolfSSL_d2i_X509_REQ_bio(bio, NULL)); + wolfSSL_BIO_free(bio); + bio = NULL; + ExpectNotNull(wolfSSL_X509_get_der(req, &derSz)); + ExpectIntEQ(wolfSSL_X509_REQ_set_subject_name(req, name), WOLFSSL_SUCCESS); + ExpectNull(wolfSSL_X509_get_der(req, &derSz)); + ExpectNotNull(bio = wolfSSL_BIO_new(wolfSSL_BIO_s_mem())); + ExpectIntEQ(wolfSSL_i2d_X509_REQ_bio(bio, req), WOLFSSL_FAILURE); + wolfSSL_BIO_free(bio); + bio = NULL; + wolfSSL_X509_free(req); + req = NULL; +#endif + + ExpectNotNull(bio = wolfSSL_BIO_new(wolfSSL_BIO_s_mem())); + ExpectIntEQ(wolfSSL_X509_set_subject_name(x509, name), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_i2d_X509_bio(bio, x509), WOLFSSL_SUCCESS); + ExpectNotNull(parsed = wolfSSL_d2i_X509_bio(bio, NULL)); + ExpectIntGT(wolfSSL_X509_NAME_get_text_by_NID( + wolfSSL_X509_get_subject_name(parsed), WC_NID_commonName, cn, + (int)sizeof(cn)), 0); + ExpectStrEQ(cn, "www.wolfssl.com"); + + wolfSSL_X509_free(parsed); + wolfSSL_BIO_free(bio); + wolfSSL_X509_free(x509); + wolfSSL_X509_NAME_free(name); +#endif + return EXPECT_RESULT(); +} + +/* Test that d2i_X509_bio() replaces the object passed in and, as OpenSSL, + * frees it when what it read does not decode. */ +int test_x509_d2i_bio_reuse(void) +{ + EXPECT_DECLS; +#if (defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)) && !defined(NO_BIO) && \ + !defined(NO_FILESYSTEM) && !defined(NO_RSA) + static const byte bad[] = { 0x30, 0x04, 0x02, 0x01, 0x01, 0x05 }; + WOLFSSL_X509* x509 = NULL; + WOLFSSL_X509* ret = NULL; + WOLFSSL_BIO* bio = NULL; + + ExpectNotNull(x509 = wolfSSL_X509_load_certificate_file(svrCertFile, + WOLFSSL_FILETYPE_PEM)); + ExpectNotNull(bio = wolfSSL_BIO_new_file("./certs/ca-cert.der", "rb")); + ExpectNotNull(ret = wolfSSL_d2i_X509_bio(bio, &x509)); + ExpectPtrEq(ret, x509); + wolfSSL_BIO_free(bio); + bio = NULL; + + ExpectNotNull(bio = wolfSSL_BIO_new_mem_buf(bad, (int)sizeof(bad))); + ExpectNull(wolfSSL_d2i_X509_bio(bio, &x509)); + ExpectNull(x509); + wolfSSL_BIO_free(bio); + bio = NULL; + + /* Nothing read: kept */ + ExpectNotNull(x509 = wolfSSL_X509_load_certificate_file(svrCertFile, + WOLFSSL_FILETYPE_PEM)); + ExpectNotNull(bio = wolfSSL_BIO_new(wolfSSL_BIO_s_mem())); + ExpectNull(wolfSSL_d2i_X509_bio(bio, &x509)); + ExpectNotNull(x509); + wolfSSL_BIO_free(bio); + wolfSSL_X509_free(x509); +#endif + return EXPECT_RESULT(); +} diff --git a/tests/api/test_x509.h b/tests/api/test_x509.h index d475b120a38..32277035ba4 100644 --- a/tests/api/test_x509.h +++ b/tests/api/test_x509.h @@ -35,6 +35,11 @@ int test_x509_ReqCertFromX509_skid_boundary(void); int test_x509_ReqCertFromX509_ext_critical(void); int test_x509_REQ_sign_mldsa(void); int test_x509_decision_coverage(void); +int test_x509_REQ_i2d_stored_der(void); +int test_x509_REQ_add_extensions_parsed(void); +int test_x509_REQ_add_extensions_resign(void); +int test_x509_REQ_setters_reencode(void); +int test_x509_d2i_bio_reuse(void); #define TEST_X509_DECLS \ TEST_DECL_GROUP("x509", test_x509_rfc2818_verification_callback), \ @@ -48,7 +53,12 @@ int test_x509_decision_coverage(void); TEST_DECL_GROUP("x509", test_x509_ReqCertFromX509_skid_overflow), \ TEST_DECL_GROUP("x509", test_x509_ReqCertFromX509_skid_boundary), \ TEST_DECL_GROUP("x509", test_x509_ReqCertFromX509_ext_critical), \ - TEST_DECL_GROUP("x509", test_x509_REQ_sign_mldsa), \ - TEST_DECL_GROUP("x509", test_x509_decision_coverage) + TEST_DECL_GROUP("x509", test_x509_REQ_sign_mldsa), \ + TEST_DECL_GROUP("x509", test_x509_decision_coverage), \ + TEST_DECL_GROUP("x509", test_x509_REQ_i2d_stored_der), \ + TEST_DECL_GROUP("x509", test_x509_REQ_add_extensions_parsed), \ + TEST_DECL_GROUP("x509", test_x509_REQ_add_extensions_resign), \ + TEST_DECL_GROUP("x509", test_x509_REQ_setters_reencode), \ + TEST_DECL_GROUP("x509", test_x509_d2i_bio_reuse) #endif /* WOLFCRYPT_TEST_X509_H */ diff --git a/tests/unit-mcdc/test_crl_whitebox.c b/tests/unit-mcdc/test_crl_whitebox.c index 3ee20d4f938..79f38c058be 100644 --- a/tests/unit-mcdc/test_crl_whitebox.c +++ b/tests/unit-mcdc/test_crl_whitebox.c @@ -90,13 +90,13 @@ static void wb_check_cert_crl_ex(WOLFSSL_CERT_MANAGER* cm) XMEMSET(issuerHash, 0x22, sizeof(issuerHash)); WB_NOTE(CheckCertCRLCm(cm->crl, issuerHash, NULL, (int)sizeof(serial), - hash, NULL, 0, NULL, cm, 1)); + hash, NULL, 0, NULL, cm, 1, NULL, NULL)); WB_NOTE(CheckCertCRLCm(cm->crl, issuerHash, NULL, (int)sizeof(serial), - NULL, NULL, 0, NULL, cm, 1)); + NULL, NULL, 0, NULL, cm, 1, NULL, NULL)); WB_NOTE(CheckCertCRLCm(cm->crl, issuerHash, serial, 0, - NULL, NULL, 0, NULL, cm, 1)); + NULL, NULL, 0, NULL, cm, 1, NULL, NULL)); WB_NOTE(CheckCertCRLCm(cm->crl, issuerHash, serial, (int)sizeof(serial), - NULL, NULL, 0, NULL, cm, 1)); + NULL, NULL, 0, NULL, cm, 1, NULL, NULL)); } @@ -154,14 +154,14 @@ static void wb_missing_crl_callbacks(WOLFSSL_CERT_MANAGER* cm) /* 1. cm NULL: operand 0 false for both decisions. */ WB_NOTE(CheckCertCRLCm(cm->crl, issuerHash, serial, (int)sizeof(serial), NULL, (const byte*)url, (int)XSTRLEN(url), NULL, - NULL, 1)); + NULL, 1, NULL, NULL)); /* 2. real cm, no callbacks: operand 0 true, operand 1 false. */ cm->cbMissingCRL = NULL; cm->crlCb = NULL; WB_NOTE(CheckCertCRLCm(cm->crl, issuerHash, serial, (int)sizeof(serial), NULL, (const byte*)url, (int)XSTRLEN(url), NULL, - cm, 1)); + cm, 1, NULL, NULL)); /* 3. both callbacks installed, error cb returns 0: takes :668 TRUE (the * partner that gives operands 0 and 1 their pairs) and :686 to its third @@ -171,14 +171,14 @@ static void wb_missing_crl_callbacks(WOLFSSL_CERT_MANAGER* cm) g_crlCbResult = 0; WB_NOTE(CheckCertCRLCm(cm->crl, issuerHash, serial, (int)sizeof(serial), NULL, (const byte*)url, (int)XSTRLEN(url), NULL, - cm, 1)); + cm, 1, NULL, NULL)); /* 4. error cb returns non-zero: :686 operand 2 true, decision TRUE, which * is the override-the-CRL-error path. */ g_crlCbResult = 1; WB_NOTE(CheckCertCRLCm(cm->crl, issuerHash, serial, (int)sizeof(serial), NULL, (const byte*)url, (int)XSTRLEN(url), NULL, - cm, 1)); + cm, 1, NULL, NULL)); /* 5. a url longer than the 256-byte stack buffer takes the "CRL url too * long" arm of the copy guard inside the :668 body, which the short url @@ -189,7 +189,8 @@ static void wb_missing_crl_callbacks(WOLFSSL_CERT_MANAGER* cm) longUrl[sizeof(longUrl) - 1] = '\0'; WB_NOTE(CheckCertCRLCm(cm->crl, issuerHash, serial, (int)sizeof(serial), NULL, (const byte*)longUrl, - (int)sizeof(longUrl) - 1, NULL, cm, 1)); + (int)sizeof(longUrl) - 1, NULL, cm, 1, NULL, + NULL)); } cm->cbMissingCRL = NULL; diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 46090474893..699bd8b3de8 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -18304,7 +18304,7 @@ static int DecodeDsaAsn1Sig(const byte* sig, word32 sigSz, byte* sigCpy, /* The certificate's signatureAlgorithm (sigOID) must match the issuer's * key type (keyOID). sigOID picks the pre-hash; keyOID picks the * verifier. They need to agree or the verifier gets the wrong input. */ -static int SigOidMatchesKeyOid(word32 sigOID, word32 keyOID) +int SigOidMatchesKeyOid(word32 sigOID, word32 keyOID) { switch (keyOID) { #ifndef NO_RSA @@ -21046,6 +21046,63 @@ static int ConfirmNameConstraints(Signer* signer, DecodedCert* cert) return 1; } +/* Checks the names of cert against the name constraints of caCert, as for a + * cert below caCert in a chain, leaf when it ends it. *violation is 0 when + * they are met, else NC_VIOLATION_EXCLUDED, NC_VIOLATION_PERMITTED or, for a + * critical constraint of a form that is not supported, + * NC_VIOLATION_UNSUPPORTED. + * Returns 0, or an error when a cert cannot be parsed. */ +int CheckCertNameConstraints(const byte* caCert, word32 caCertSz, + const byte* cert, word32 certSz, int leaf, void* heap, int* violation) +{ + int ret = WC_NO_ERR_TRACE(MEMORY_E); + Signer signer; + WC_DECLARE_VAR(ca, DecodedCert, 1, heap); + WC_DECLARE_VAR(dc, DecodedCert, 1, heap); + + *violation = 0; + WC_ALLOC_VAR_EX(ca, DecodedCert, 1, heap, DYNAMIC_TYPE_DCERT, goto end); + InitDecodedCert(ca, caCert, caCertSz, heap); + WC_ALLOC_VAR_EX(dc, DecodedCert, 1, heap, DYNAMIC_TYPE_DCERT, goto end); + InitDecodedCert(dc, cert, certSz, heap); + ret = ParseCertRelative(ca, CA_TYPE, NO_VERIFY, NULL, NULL); + if (ret == 0) { + ret = ParseCertRelative(dc, CERT_TYPE, NO_VERIFY, NULL, NULL); + } + if (ret != 0) { + goto end; + } + /* As OpenSSL, the CN of the leaf is checked, CA or not */ + if (leaf) + dc->isCA = 0; + XMEMSET(&signer, 0, sizeof(signer)); + signer.excludedNames = ca->excludedNames; + if (!ConfirmNameConstraints(&signer, dc)) { + *violation = NC_VIOLATION_EXCLUDED; + } + else { + signer.permittedNames = ca->permittedNames; + if (!ConfirmNameConstraints(&signer, dc)) { + *violation = NC_VIOLATION_PERMITTED; + } + else { + signer.extNameConstraintCrit = ca->extNameConstraintCrit; + signer.extNameConstraintHasUnsupported = + ca->extNameConstraintHasUnsupported; + if (!ConfirmNameConstraints(&signer, dc)) { + *violation = NC_VIOLATION_UNSUPPORTED; + } + } + } +end: + /* ca and dc are each NULL or initialised */ + FreeDecodedCert(dc); + FreeDecodedCert(ca); + WC_FREE_VAR_EX(dc, heap, DYNAMIC_TYPE_DCERT); + WC_FREE_VAR_EX(ca, heap, DYNAMIC_TYPE_DCERT); + return ret; +} + #endif /* IGNORE_NAME_CONSTRAINTS */ #ifdef WOLFSSL_ASN_TEMPLATE @@ -39581,6 +39638,8 @@ int VerifyCRL_Signature(SignatureCtx* sigCtx, const byte* toBeSigned, word32 signatureOID, const byte* sigParams, int sigParamsSz, Signer *ca, void* heap) { + int ret; + /* try to confirm/verify signature */ /* Enforced by default (RFC 5280 4.2.1.3 / 5.2: a CRL issuer MUST assert * cRLSign). IGNORE_KEY_EXTENSIONS is a deliberate, RFC-non-conformant @@ -39594,12 +39653,17 @@ int VerifyCRL_Signature(SignatureCtx* sigCtx, const byte* toBeSigned, #endif /* IGNORE_KEY_EXTENSIONS */ InitSignatureCtx(sigCtx, heap, INVALID_DEVID); - if (ConfirmSignature(sigCtx, toBeSigned, tbsSz, ca->publicKey, + ret = ConfirmSignature(sigCtx, toBeSigned, tbsSz, ca->publicKey, ca->pubKeySize, ca->keyOID, signature, sigSz, - signatureOID, sigParams, (word32)sigParamsSz, NULL) != 0) { + signatureOID, sigParams, (word32)sigParamsSz, NULL); + if (ret != 0) { WOLFSSL_MSG("CRL Confirm signature failed"); - WOLFSSL_ERROR_VERBOSE(ASN_CRL_CONFIRM_E); - return ASN_CRL_CONFIRM_E; + /* Running out of memory is not a bad signature */ + if (ret != WC_NO_ERR_TRACE(MEMORY_E)) { + ret = ASN_CRL_CONFIRM_E; + } + WOLFSSL_ERROR_VERBOSE(ret); + return ret; } return 0; diff --git a/wolfcrypt/src/evp.c b/wolfcrypt/src/evp.c index f60e4d59517..4faeaf2a55e 100644 --- a/wolfcrypt/src/evp.c +++ b/wolfcrypt/src/evp.c @@ -495,6 +495,7 @@ void wolfSSL_EVP_CIPHER_CTX_free(WOLFSSL_EVP_CIPHER_CTX *ctx) if (ctx) { WOLFSSL_ENTER("wolfSSL_EVP_CIPHER_CTX_free"); wolfSSL_EVP_CIPHER_CTX_cleanup(ctx); + ForceZero(ctx, sizeof(*ctx)); XFREE(ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER); } } @@ -3502,36 +3503,41 @@ int wolfSSL_EVP_PKEY_sign(WOLFSSL_EVP_PKEY_CTX *ctx, unsigned char *sig, } #endif /* !NO_RSA */ -#ifndef NO_DSA +#if !defined(NO_DSA) && !defined(HAVE_SELFTEST) case WC_EVP_PKEY_DSA: { int bytes; int ret; + WOLFSSL_DSA_SIG* dsaSig; if (!ctx->pkey->dsa) return WOLFSSL_FAILURE; - bytes = wolfSSL_BN_num_bytes(ctx->pkey->dsa->q); - if (bytes == WC_NO_ERR_TRACE(WOLFSSL_FAILURE)) + if (!ctx->pkey->dsa->exSet && + SetDsaExternal(ctx->pkey->dsa) != WOLFSSL_SUCCESS) + return WOLFSSL_FAILURE; + /* DER encoding of r and s, as in OpenSSL. */ + bytes = wolfSSL_DSA_size(ctx->pkey->dsa); + if (bytes <= 0) return WOLFSSL_FAILURE; - bytes *= 2; if (!sig) { *siglen = (size_t)bytes; return WOLFSSL_SUCCESS; } if ((int)*siglen < bytes) return WOLFSSL_FAILURE; - /* wolfssl_local_dsa_do_sign() takes the length as an int, and wolfCrypt + /* wolfSSL_DSA_do_sign_ex() takes the length as an int, and wolfCrypt * rejects anything longer than this anyway. */ if (tbslen > WC_MAX_DIGEST_SIZE) return WOLFSSL_FAILURE; - ret = wolfssl_local_dsa_do_sign(tbs, (int)tbslen, sig, ctx->pkey->dsa); - /* wolfssl_local_dsa_do_sign() can return WOLFSSL_FATAL_ERROR */ - if (ret != WOLFSSL_SUCCESS) - return ret; - if (bytes == WC_NO_ERR_TRACE(WOLFSSL_FAILURE)) + dsaSig = wolfSSL_DSA_do_sign_ex(tbs, (int)tbslen, ctx->pkey->dsa); + if (dsaSig == NULL) + return WOLFSSL_FAILURE; + ret = wolfSSL_i2d_DSA_SIG(dsaSig, &sig); + wolfSSL_DSA_SIG_free(dsaSig); + if (ret <= 0) return WOLFSSL_FAILURE; - *siglen = (size_t)bytes; + *siglen = (size_t)ret; return WOLFSSL_SUCCESS; } -#endif /* NO_DSA */ +#endif /* !NO_DSA && !HAVE_SELFTEST */ #ifdef HAVE_ECC case WC_EVP_PKEY_EC: { @@ -3644,25 +3650,36 @@ int wolfSSL_EVP_PKEY_verify(WOLFSSL_EVP_PKEY_CTX *ctx, const unsigned char *sig, ctx->padding, wolfSSL_EVP_MD_type(ctx->mgf1_md), ctx->saltlen); #endif /* !NO_RSA */ -#ifndef NO_DSA +#if !defined(NO_DSA) && !defined(HAVE_SELFTEST) case WC_EVP_PKEY_DSA: { - int dsacheck = 0; - int bytes; - if (!ctx->pkey->dsa || tbslen < WC_SHA_DIGEST_SIZE) - return WOLFSSL_FAILURE; - bytes = wolfSSL_BN_num_bytes(ctx->pkey->dsa->q); - if (bytes <= 0 || siglen < (size_t)bytes * 2) + int ret; + const unsigned char* p = sig; + unsigned char* der = NULL; + WOLFSSL_DSA_SIG* dsaSig; + if (!ctx->pkey->dsa) return WOLFSSL_FAILURE; - /* wolfssl_local_dsa_do_verify() takes the length as an int, and wolfCrypt + /* wolfSSL_DSA_do_verify_ex() takes the length as an int, and wolfCrypt * rejects anything longer than this anyway. */ if (tbslen > WC_MAX_DIGEST_SIZE) return WOLFSSL_FAILURE; - if (wolfssl_local_dsa_do_verify(tbs, (int)tbslen, (unsigned char *)sig, - ctx->pkey->dsa, &dsacheck) != WOLFSSL_SUCCESS || dsacheck != 1) + dsaSig = wolfSSL_d2i_DSA_SIG(NULL, &p, (long)siglen); + if (dsaSig == NULL) return WOLFSSL_FAILURE; - return WOLFSSL_SUCCESS; + /* Only the DER encoding of r and s, as in OpenSSL. */ + ret = wolfSSL_i2d_DSA_SIG(dsaSig, &der); + if ((ret > 0) && ((size_t)ret == siglen) && + (XMEMCMP(der, sig, (size_t)ret) == 0)) { + ret = wolfSSL_DSA_do_verify_ex(tbs, (int)tbslen, dsaSig, + ctx->pkey->dsa); + } + else { + ret = 0; + } + XFREE(der, NULL, DYNAMIC_TYPE_ASN1); + wolfSSL_DSA_SIG_free(dsaSig); + return (ret == 1) ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE; } -#endif /* NO_DSA */ +#endif /* !NO_DSA && !HAVE_SELFTEST */ #ifdef HAVE_ECC case WC_EVP_PKEY_EC: { @@ -7090,6 +7107,8 @@ void wolfSSL_EVP_init(void) WOLFSSL_ENTER("wolfSSL_EVP_CIPHER_CTX_cleanup"); if (ctx) { wolfSSL_EVP_CIPHER_CTX_cleanup_cipher(ctx); + /* Key schedules of all ciphers, DES included. */ + ForceZero(&ctx->cipher, sizeof(ctx->cipher)); ctx->cipherType = WOLFSSL_EVP_CIPH_TYPE_INIT; /* not yet initialized */ #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) if (ctx->key) { @@ -9675,7 +9694,7 @@ int wolfSSL_EVP_PKEY_set1_RSA(WOLFSSL_EVP_PKEY *pkey, WOLFSSL_RSA *key) #endif /* !NO_RSA */ #if !defined (NO_DSA) && !defined(HAVE_SELFTEST) && defined(WOLFSSL_KEY_GEN) -/* with set1 functions the pkey struct does not own the DSA structure +/* with set1 functions the pkey struct takes a reference to the DSA structure * * returns WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on failure */ @@ -9689,9 +9708,14 @@ int wolfSSL_EVP_PKEY_set1_DSA(WOLFSSL_EVP_PKEY *pkey, WOLFSSL_DSA *key) WOLFSSL_ENTER("wolfSSL_EVP_PKEY_set1_DSA"); if((pkey == NULL) || (key == NULL))return WOLFSSL_FAILURE; + /* Take the reference first: key may be the one the pkey holds. */ + if (wolfSSL_DSA_up_ref(key) != 1) { + WOLFSSL_MSG("wolfSSL_DSA_up_ref failed"); + return WOLFSSL_FAILURE; + } clearEVPPkeyKeys(pkey); pkey->dsa = key; - pkey->ownDsa = 0; /* pkey does not own DSA */ + pkey->ownDsa = 1; /* pkey holds a reference */ pkey->type = WC_EVP_PKEY_DSA; if (key->inSet == 0) { if (SetDsaInternal(key) != WOLFSSL_SUCCESS) { @@ -9731,6 +9755,16 @@ int wolfSSL_EVP_PKEY_set1_DSA(WOLFSSL_EVP_PKEY *pkey, WOLFSSL_DSA *key) return WOLFSSL_FAILURE; } + /* Drop the encoding of a key held before. */ + if (pkey->pkey.ptr != NULL) { + if (pkey->pkey_sz > 0) { + ForceZero(pkey->pkey.ptr, (word32)pkey->pkey_sz); + } + XFREE(pkey->pkey.ptr, pkey->heap, DYNAMIC_TYPE_DER); + pkey->pkey_sz = 0; + } + /* The new encoding has no PKCS#8 header. */ + pkey->pkcs8HeaderSz = 0; pkey->pkey.ptr = (char*)XMALLOC((size_t)derSz, pkey->heap, DYNAMIC_TYPE_DER); if (pkey->pkey.ptr == NULL) { @@ -9753,6 +9787,9 @@ WOLFSSL_DSA* wolfSSL_EVP_PKEY_get0_DSA(struct WOLFSSL_EVP_PKEY *pkey) return pkey->dsa; } +/* Returns the DSA key of the pkey with its reference count incremented. + * The caller frees it with wolfSSL_DSA_free(). + */ WOLFSSL_DSA* wolfSSL_EVP_PKEY_get1_DSA(WOLFSSL_EVP_PKEY* key) { WOLFSSL_DSA* local; @@ -9763,14 +9800,18 @@ WOLFSSL_DSA* wolfSSL_EVP_PKEY_get1_DSA(WOLFSSL_EVP_PKEY* key) WOLFSSL_MSG("Bad function argument"); return NULL; } - - local = wolfSSL_DSA_new(); - if (local == NULL) { - WOLFSSL_MSG("Error creating a new WOLFSSL_DSA structure"); + if (key->type != WC_EVP_PKEY_DSA) { + WOLFSSL_MSG("WOLFSSL_EVP_PKEY does not hold a DSA key"); return NULL; } - if (key->type == WC_EVP_PKEY_DSA) { + if (key->dsa == NULL) { + /* Decode the stored DER and keep the key on the pkey. */ + local = wolfSSL_DSA_new(); + if (local == NULL) { + WOLFSSL_MSG("Error creating a new WOLFSSL_DSA structure"); + return NULL; + } if (wolfSSL_DSA_LoadDer(local, (const unsigned char*)key->pkey.ptr, key->pkey_sz) != WOLFSSL_SUCCESS) { /* now try public key */ @@ -9778,16 +9819,18 @@ WOLFSSL_DSA* wolfSSL_EVP_PKEY_get1_DSA(WOLFSSL_EVP_PKEY* key) (const unsigned char*)key->pkey.ptr, key->pkey_sz, WOLFSSL_DSA_LOAD_PUBLIC) != WOLFSSL_SUCCESS) { wolfSSL_DSA_free(local); - local = NULL; + return NULL; } } + key->dsa = local; + key->ownDsa = 1; } - else { - WOLFSSL_MSG("WOLFSSL_EVP_PKEY does not hold a DSA key"); - wolfSSL_DSA_free(local); - local = NULL; + + if (wolfSSL_DSA_up_ref(key->dsa) != 1) { + WOLFSSL_MSG("wolfSSL_DSA_up_ref failed"); + return NULL; } - return local; + return key->dsa; } #endif /* !NO_DSA && !HAVE_SELFTEST && WOLFSSL_KEY_GEN */ diff --git a/wolfcrypt/src/evp_pk.c b/wolfcrypt/src/evp_pk.c index 32290ae00cf..10c2e77c7ec 100644 --- a/wolfcrypt/src/evp_pk.c +++ b/wolfcrypt/src/evp_pk.c @@ -2645,116 +2645,90 @@ int wolfSSL_i2d_PrivateKey_bio(WOLFSSL_BIO* bio, WOLFSSL_EVP_PKEY* key) #ifdef HAVE_ECC /* Encode EC key as public key DER. * - * @param [in] key WOLFSSL_EVP_KEY object to encode. * @param [in] ec WOLFSSL_EC_KEY object to encode. * @param [out] der Buffer with DER encoding of EC public key. * @return Public key DER encoding size on success. * @return WOLFSSL_FATAL_ERROR when dynamic memory allocation fails. * @return WOLFSSL_FATAL_ERROR when encoding fails. */ -static int wolfssl_i_i2d_ecpublickey(const WOLFSSL_EVP_PKEY* key, - const WOLFSSL_EC_KEY *ec, unsigned char **der) +static int wolfssl_i_i2d_ecpublickey(const WOLFSSL_EC_KEY *ec, + unsigned char **der) { - word32 pub_derSz = 0; - int ret; - unsigned char *local_der = NULL; - word32 local_derSz = 0; - unsigned char *pub_der = NULL; - ecc_key *eccKey = NULL; - word32 inOutIdx = 0; - - /* We need to get the DER, then convert it to a public key. But what we get - * might be a buffered private key so we need to decode it and then encode - * the public part. */ - ret = wolfssl_i_evp_pkey_get_der(key, &local_der); - if (ret <= 0) { - /* In this case, there was no buffered DER at all. This could be the - * case where the key that was passed in was generated. So now we - * have to create the local DER. */ - local_derSz = (word32)wolfSSL_i2d_ECPrivateKey(ec, &local_der); - if (local_derSz == 0) { - ret = WOLFSSL_FATAL_ERROR; - } - } else { - local_derSz = (word32)ret; - ret = 0; - } - - if (ret == 0) { - eccKey = (ecc_key *)XMALLOC(sizeof(*eccKey), NULL, DYNAMIC_TYPE_ECC); - if (eccKey == NULL) { - WOLFSSL_MSG("Failed to allocate key buffer."); - ret = WOLFSSL_FATAL_ERROR; - } - } + int ret = 0; + int sz = 0; + ecc_key* eccKey = NULL; + ecc_key* pubKey = NULL; - /* Initialize a wolfCrypt ECC key. */ - if (ret == 0) { - ret = wc_ecc_init(eccKey); - } - if (ret == 0) { - /* Decode the DER data with wolfCrypt ECC key. */ - ret = wc_EccPublicKeyDecode(local_der, &inOutIdx, eccKey, local_derSz); - if (ret < 0) { - /* We now try again as x.963 [point type][x][opt y]. */ - ret = wc_ecc_import_x963(local_der, local_derSz, eccKey); - } + if ((ec == NULL) || (ec->internal == NULL)) { + ret = WOLFSSL_FATAL_ERROR; } - - if (ret == 0) { - /* Get the size of the encoding of the public key DER. */ - pub_derSz = (word32)wc_EccPublicKeyDerSize(eccKey, 1); - if ((int)pub_derSz <= 0) { - ret = WOLFSSL_FATAL_ERROR; - } + /* Sync the internal key with the EC key. */ + if ((ret == 0) && (!ec->inSet) && + (SetECKeyInternal((WOLFSSL_EC_KEY*)ec) != 1)) { + ret = WOLFSSL_FATAL_ERROR; } - if (ret == 0) { - /* Allocate memory for public key DER encoding. */ - pub_der = (unsigned char*)XMALLOC(pub_derSz, NULL, - DYNAMIC_TYPE_PUBLIC_KEY); - if (pub_der == NULL) { - WOLFSSL_MSG("Failed to allocate output buffer."); - ret = WOLFSSL_FATAL_ERROR; + eccKey = (ecc_key*)ec->internal; + if (eccKey->type == ECC_PRIVATEKEY_ONLY) { + /* Compute the public point into a separate key. */ + pubKey = (ecc_key*)XMALLOC(sizeof(*pubKey), NULL, + DYNAMIC_TYPE_ECC); + if (pubKey == NULL) { + ret = WOLFSSL_FATAL_ERROR; + } + else if (wc_ecc_init(pubKey) != 0) { + XFREE(pubKey, NULL, DYNAMIC_TYPE_ECC); + pubKey = NULL; + ret = WOLFSSL_FATAL_ERROR; + } + else { + pubKey->idx = eccKey->idx; + pubKey->dp = eccKey->dp; + if (wc_ecc_make_pub(eccKey, &pubKey->pubkey) != 0) { + ret = WOLFSSL_FATAL_ERROR; + } + pubKey->type = ECC_PUBLICKEY; + eccKey = pubKey; + } } } if (ret == 0) { - /* Encode public key as DER. */ - pub_derSz = (word32)wc_EccPublicKeyToDer(eccKey, pub_der, pub_derSz, 1); - if ((int)pub_derSz <= 0) { + sz = wc_EccPublicKeyDerSize(eccKey, 1); + if (sz <= 0) { ret = WOLFSSL_FATAL_ERROR; } } - - /* This block is for actually returning the DER of the public key */ if ((ret == 0) && (der != NULL)) { int bufferPassedIn = ((*der) != NULL); + unsigned char* buf = *der; + if (!bufferPassedIn) { - *der = (unsigned char*)XMALLOC(pub_derSz, NULL, + buf = (unsigned char*)XMALLOC((size_t)sz, NULL, DYNAMIC_TYPE_PUBLIC_KEY); - if (*der == NULL) { - WOLFSSL_MSG("Failed to allocate output buffer."); + if (buf == NULL) { ret = WOLFSSL_FATAL_ERROR; } } + if ((ret == 0) && + (wc_EccPublicKeyToDer(eccKey, buf, (word32)sz, 1) != sz)) { + ret = WOLFSSL_FATAL_ERROR; + } if (ret == 0) { - XMEMCPY(*der, pub_der, pub_derSz); - if (bufferPassedIn) { - *der += pub_derSz; - } + *der = bufferPassedIn ? buf + sz : buf; + } + else if (!bufferPassedIn) { + XFREE(buf, NULL, DYNAMIC_TYPE_PUBLIC_KEY); } } - /* Dispose of allocated objects. */ - XFREE(pub_der, NULL, DYNAMIC_TYPE_PUBLIC_KEY); - XFREE(local_der, NULL, DYNAMIC_TYPE_OPENSSL); - wc_ecc_free(eccKey); - XFREE(eccKey, NULL, DYNAMIC_TYPE_ECC); + if (pubKey != NULL) { + wc_ecc_free(pubKey); + XFREE(pubKey, NULL, DYNAMIC_TYPE_ECC); + } - /* Return error or the size of the DER encoded public key. */ if (ret == 0) { - ret = (int)pub_derSz; + ret = sz; } return ret; } @@ -2964,7 +2938,7 @@ int wolfSSL_i2d_PublicKey(const WOLFSSL_EVP_PKEY *key, unsigned char **der) #endif #ifdef HAVE_ECC case WC_EVP_PKEY_EC: - return wolfssl_i_i2d_ecpublickey(key, key->ecc, der); + return wolfssl_i_i2d_ecpublickey(key->ecc, der); #endif #if defined(HAVE_ED25519) && defined(HAVE_ED25519_KEY_EXPORT) /* Emit a SubjectPublicKeyInfo (withAlg=1) rather than the bare key: diff --git a/wolfcrypt/src/pkcs12.c b/wolfcrypt/src/pkcs12.c index d2ac234bc70..ac3a5497cd4 100644 --- a/wolfcrypt/src/pkcs12.c +++ b/wolfcrypt/src/pkcs12.c @@ -60,6 +60,11 @@ static const byte WC_PKCS12_KeyBag_OID[] = {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x0c, 0x0a, 0x01, 0x01}; static const byte WC_PKCS12_ShroudedKeyBag_OID[] = {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x0c, 0x0a, 0x01, 0x02}; +/* PKCS#9 friendlyName and localKeyId bag attributes */ +static const byte WC_PKCS12_FriendlyName_OID[] = + {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x14}; +static const byte WC_PKCS12_LocalKeyId_OID[] = + {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x15}; typedef struct ContentInfo { @@ -1342,6 +1347,126 @@ static int PKCS12_CoalesceOctetStrings(WC_PKCS12* pkcs12, byte* data, } #endif +/* friendlyName and localKeyId bag attributes of a cert */ +typedef struct Pkcs12CertAttrs { + const byte* cert; + byte* friendlyName; + word32 friendlyNameSz; + byte* localKeyId; + word32 localKeyIdSz; + struct Pkcs12CertAttrs* next; +} Pkcs12CertAttrs; + +static void PKCS12_FreeCertAttrs(Pkcs12CertAttrs* attrs, void* heap) +{ + while (attrs != NULL) { + Pkcs12CertAttrs* next = attrs->next; + XFREE(attrs->friendlyName, heap, DYNAMIC_TYPE_PKCS); + XFREE(attrs->localKeyId, heap, DYNAMIC_TYPE_PKCS); + XFREE(attrs, heap, DYNAMIC_TYPE_PKCS); + attrs = next; + } + (void)heap; +} + +/* Copy the value of an attribute when it has the expected tag. */ +static int PKCS12_CopyAttrValue(const byte* data, word32 idx, word32 maxIdx, + byte expTag, byte** out, word32* outSz, void* heap) +{ + int ret = 0; + int len = 0; + byte tag = 0; + + if ((*out != NULL) || (GetASNTag(data, &idx, &tag, maxIdx) < 0) || + (tag != expTag) || (GetLength(data, &idx, &len, maxIdx) < 0)) { + /* Not used: a second attribute or another type. */ + return 0; + } + *out = (byte*)XMALLOC((size_t)len + 1, heap, DYNAMIC_TYPE_PKCS); + if (*out == NULL) { + ret = MEMORY_E; + } + else { + XMEMCPY(*out, data + idx, (size_t)len); + *outSz = (word32)len; + } + (void)heap; + return ret; +} + +/* Get the friendlyName and localKeyId bag attributes of a cert. + * PKCS#12 (RFC 7292), 4.2: SafeBag bagAttributes SET OF PKCS12Attribute. + * Bad attributes are skipped as other attributes are. + * + * data : decoded content + * idx : index of the attributes after the bag value + * bagEnd : index of the end of the bag + * cert : cert of the bag + * list : list of the attributes of the certs, the new entry is added + */ +static int PKCS12_GetCertAttrs(const byte* data, word32 idx, word32 bagEnd, + const byte* cert, Pkcs12CertAttrs** list, void* heap) +{ + int ret = 0; + int len = 0; + int oidSz = 0; + word32 setEnd; + word32 attrEnd; + word32 oidIdx; + Pkcs12CertAttrs* attrs; + + if ((idx >= bagEnd) || (GetSet(data, &idx, &len, bagEnd) < 0)) { + return 0; + } + setEnd = idx + (word32)len; + + attrs = (Pkcs12CertAttrs*)XMALLOC(sizeof(Pkcs12CertAttrs), heap, + DYNAMIC_TYPE_PKCS); + if (attrs == NULL) { + return MEMORY_E; + } + XMEMSET(attrs, 0, sizeof(Pkcs12CertAttrs)); + attrs->cert = cert; + + while ((ret == 0) && (idx < setEnd)) { + if (GetSequence(data, &idx, &len, setEnd) < 0) { + break; + } + attrEnd = idx + (word32)len; + if (GetASNObjectId(data, &idx, &oidSz, attrEnd) < 0) { + break; + } + oidIdx = idx; + idx += (word32)oidSz; + /* The first of the attribute values is used. */ + if (GetSet(data, &idx, &len, attrEnd) >= 0) { + if ((oidSz == (int)sizeof(WC_PKCS12_FriendlyName_OID)) && + (XMEMCMP(data + oidIdx, WC_PKCS12_FriendlyName_OID, + sizeof(WC_PKCS12_FriendlyName_OID)) == 0)) { + ret = PKCS12_CopyAttrValue(data, idx, attrEnd, ASN_BMPSTRING, + &attrs->friendlyName, &attrs->friendlyNameSz, heap); + } + else if ((oidSz == (int)sizeof(WC_PKCS12_LocalKeyId_OID)) && + (XMEMCMP(data + oidIdx, WC_PKCS12_LocalKeyId_OID, + sizeof(WC_PKCS12_LocalKeyId_OID)) == 0)) { + ret = PKCS12_CopyAttrValue(data, idx, attrEnd, + ASN_OCTET_STRING, &attrs->localKeyId, + &attrs->localKeyIdSz, heap); + } + } + idx = attrEnd; + } + + if (ret != 0) { + PKCS12_FreeCertAttrs(attrs, heap); + } + else { + attrs->next = *list; + *list = attrs; + } + return ret; +} + /* return 0 on success and negative on failure. * By side effect returns private key, cert, and optionally ca. * Parses and decodes the parts of PKCS12 @@ -1379,10 +1504,28 @@ int wc_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, int wc_PKCS12_parse_ex(WC_PKCS12* pkcs12, const char* psw, byte** pkey, word32* pkeySz, byte** cert, word32* certSz, WC_DerCertList** ca, int keepKeyHeader) +{ + return wc_PKCS12_parse_ex2(pkcs12, psw, pkey, pkeySz, cert, certSz, ca, + keepKeyHeader, NULL, NULL, NULL, NULL); +} + +/* As wc_PKCS12_parse_ex, and also returns the bag attributes of cert. + * + * friendlyName : optional BMPString of the friendlyName returned, NULL + * when cert has none + * localKeyId : optional localKeyId returned, NULL when cert has none + */ +int wc_PKCS12_parse_ex2(WC_PKCS12* pkcs12, const char* psw, + byte** pkey, word32* pkeySz, byte** cert, word32* certSz, + WC_DerCertList** ca, int keepKeyHeader, + byte** friendlyName, word32* friendlyNameSz, + byte** localKeyId, word32* localKeyIdSz) { ContentInfo* ci = NULL; WC_DerCertList* certList = NULL; WC_DerCertList* tailList = NULL; + Pkcs12CertAttrs* attrs = NULL; + int wantAttrs = (friendlyName != NULL) || (localKeyId != NULL); byte* buf = NULL; word32 bufSz = 0; word32 i, oid; @@ -1405,6 +1548,14 @@ int wc_PKCS12_parse_ex(WC_PKCS12* pkcs12, const char* psw, *pkey = NULL; if (ca != NULL) *ca = NULL; + if (friendlyName != NULL) { + *friendlyName = NULL; + *friendlyNameSz = 0; + } + if (localKeyId != NULL) { + *localKeyId = NULL; + *localKeyIdSz = 0; + } /* if there is sign data then verify the MAC */ if (pkcs12->signData != NULL ) { @@ -1785,6 +1936,14 @@ int wc_PKCS12_parse_ex(WC_PKCS12* pkcs12, const char* psw, /* on to next */ idx += (word32)size; + + if (wantAttrs) { + ret = PKCS12_GetCertAttrs(data, idx, (word32)bagSz, + node->buffer, &attrs, pkcs12->heap); + if (ret != 0) { + goto exit_pk12par; + } + } } break; @@ -1829,6 +1988,26 @@ int wc_PKCS12_parse_ex(WC_PKCS12* pkcs12, const char* psw, if (ret < 0) goto exit_pk12par; } + if (*cert != NULL) { + Pkcs12CertAttrs* cur; + + for (cur = attrs; cur != NULL; cur = cur->next) { + if (cur->cert != *cert) { + continue; + } + if (friendlyName != NULL) { + *friendlyName = cur->friendlyName; + *friendlyNameSz = cur->friendlyNameSz; + cur->friendlyName = NULL; + } + if (localKeyId != NULL) { + *localKeyId = cur->localKeyId; + *localKeyIdSz = cur->localKeyIdSz; + cur->localKeyId = NULL; + } + break; + } + } /* if ca arg provided return certList, otherwise free it */ if (ca != NULL) { @@ -1859,6 +2038,7 @@ int wc_PKCS12_parse_ex(WC_PKCS12* pkcs12, const char* psw, wc_FreeCertList(certList, pkcs12->heap); } + PKCS12_FreeCertAttrs(attrs, pkcs12->heap); return ret; } diff --git a/wolfssl/crl.h b/wolfssl/crl.h index 0a1c72d7d5e..af28519af5f 100644 --- a/wolfssl/crl.h +++ b/wolfssl/crl.h @@ -49,7 +49,13 @@ WOLFSSL_LOCAL int CheckCertCRL_ex(WOLFSSL_CRL* crl, byte* issuerHash, byte* serial, int serialSz, byte* serialHash, const byte* extCrlInfo, int extCrlInfoSz, void* issuerName); WOLFSSL_LOCAL int CheckCertCRLFromCm(WOLFSSL_CERT_MANAGER* cm, - WOLFSSL_CRL* crl, DecodedCert* cert); + WOLFSSL_CRL* crl, DecodedCert* cert, Signer* issuer, + const time_t* checkTime); +#ifdef OPENSSL_EXTRA +WOLFSSL_LOCAL int PickCertCRL(WOLFSSL_CRL* crl, DecodedCert* cert, + Signer* issuer, const time_t* checkTime, int* cur, + WOLFSSL_ASN1_TIME* last); +#endif #ifdef HAVE_CRL_UPDATE_CB WOLFSSL_LOCAL int GetCRLInfo(WOLFSSL_CRL* crl, CrlInfo* info, const byte* buff, long sz, int type); diff --git a/wolfssl/internal.h b/wolfssl/internal.h index d0aa5473165..d088837de44 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -3052,6 +3052,10 @@ WOLFSSL_LOCAL void CleanupStoreCtxCallback(WOLFSSL_X509_STORE_CTX* store, WOLFSSL_LOCAL int X509StoreLoadCertBuffer(WOLFSSL_X509_STORE *str, byte *buf, word32 bufLen, int type); WOLFSSL_LOCAL int X509StorePushCertsToCM(WOLFSSL_X509_STORE* store); +#if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) && \ + defined(KEEP_PEER_CERT) +WOLFSSL_LOCAL int VerifiedChainCb(int ok, WOLFSSL_X509_STORE_CTX* ctx); +#endif #endif /* !defined NO_CERTS */ /* wolfSSL Sock Addr */ @@ -5037,6 +5041,8 @@ int ProcessOldClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, WOLFSSL_LOCAL int AddSigner(WOLFSSL_CERT_MANAGER* cm, Signer *s); WOLFSSL_LOCAL int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify); + WOLFSSL_LOCAL int CheckCAKeySize(WOLFSSL_CERT_MANAGER* cm, word32 keyOID, + const byte* pubKey, word32 pubKeySize); WOLFSSL_LOCAL int RemoveCA(WOLFSSL_CERT_MANAGER* cm, byte* hash, int type); WOLFSSL_LOCAL int SetCAType(WOLFSSL_CERT_MANAGER* cm, byte* hash, int type); WOLFSSL_LOCAL @@ -6262,6 +6268,7 @@ struct WOLFSSL_STACK { #if defined(OPENSSL_ALL) wolf_sk_hash_cb hash_fn; unsigned long hash; + wolf_sk_compare_cb comp; /* used by sort */ #endif union { @@ -6366,6 +6373,13 @@ struct WOLFSSL_X509 { #endif /* WOLFSSL_QT || OPENSSL_ALL */ #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) WOLFSSL_ASN1_INTEGER* serialNumber; /* Stores SN from wolfSSL_X509_get_serialNumber */ +#endif +#ifdef OPENSSL_EXTRA + /* friendlyName, as UTF-8, and localKeyId from a PKCS#12 bag */ + byte* alias; + int aliasSz; + byte* keyid; + int keyidSz; #endif WOLFSSL_ASN1_TIME notBefore; WOLFSSL_ASN1_TIME notAfter; diff --git a/wolfssl/openssl/asn1.h b/wolfssl/openssl/asn1.h index 17746ae4289..51d48c6e721 100644 --- a/wolfssl/openssl/asn1.h +++ b/wolfssl/openssl/asn1.h @@ -30,7 +30,6 @@ #define ASN1_STRING_new wolfSSL_ASN1_STRING_new #define ASN1_STRING_type_new wolfSSL_ASN1_STRING_type_new -#define ASN1_STRING_type wolfSSL_ASN1_STRING_type #define ASN1_STRING_set wolfSSL_ASN1_STRING_set #define ASN1_OCTET_STRING_set wolfSSL_ASN1_STRING_set #define ASN1_STRING_free wolfSSL_ASN1_STRING_free @@ -87,6 +86,8 @@ #define V_ASN1_CONSTRUCTED WOLFSSL_V_ASN1_CONSTRUCTED +#define B_ASN1_OCTET_STRING WOLFSSL_B_ASN1_OCTET_STRING + #define ASN1_STRING_FLAG_BITS_LEFT WOLFSSL_ASN1_STRING_FLAG_BITS_LEFT #define ASN1_STRING_FLAG_NDEF WOLFSSL_ASN1_STRING_FLAG_NDEF #define ASN1_STRING_FLAG_CONT WOLFSSL_ASN1_STRING_FLAG_CONT diff --git a/wolfssl/openssl/compat_types.h b/wolfssl/openssl/compat_types.h index 9bddc31a530..2ca5f6b9b44 100644 --- a/wolfssl/openssl/compat_types.h +++ b/wolfssl/openssl/compat_types.h @@ -66,5 +66,7 @@ typedef WOLFSSL_EVP_PKEY_CTX EVP_PKEY_CTX; #endif /* !OPENSSL_COEXIST && (OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL) */ typedef unsigned long (*wolf_sk_hash_cb) (const void *v); +typedef int (*wolf_sk_compare_cb) (const void* const* a, + const void* const* b); #endif /* !WOLFSSL_OPENSSL_COMPAT_TYPES_H_ */ diff --git a/wolfssl/openssl/crypto.h b/wolfssl/openssl/crypto.h index cef908f1539..d8391d43aa6 100644 --- a/wolfssl/openssl/crypto.h +++ b/wolfssl/openssl/crypto.h @@ -113,6 +113,11 @@ WOLFSSL_API int wolfSSL_OPENSSL_init_crypto(word64 opts, const WOLFSSL_INIT_SETT /* this function was used to set the default malloc, free, and realloc */ #define CRYPTO_malloc_init() 0 /* CRYPTO_malloc_init is not needed */ +#define CRYPTO_malloc_fn wolfSSL_OSSL_Malloc_cb +#define CRYPTO_realloc_fn wolfSSL_OSSL_Realloc_cb +#define CRYPTO_free_fn wolfSSL_OSSL_Free_cb +#define CRYPTO_get_mem_functions wolfSSL_CRYPTO_get_mem_functions + #define OPENSSL_free wolfSSL_OPENSSL_free #define OPENSSL_malloc wolfSSL_OPENSSL_malloc #define OPENSSL_hexchar2int wolfSSL_OPENSSL_hexchar2int diff --git a/wolfssl/openssl/dsa.h b/wolfssl/openssl/dsa.h index 4d7263dcb39..96e02e10516 100644 --- a/wolfssl/openssl/dsa.h +++ b/wolfssl/openssl/dsa.h @@ -51,11 +51,13 @@ struct WOLFSSL_DSA { void* internal; /* our Dsa Key */ char inSet; /* internal set from external ? */ char exSet; /* external set from internal ? */ + wolfSSL_Ref ref; /* Reference count information. */ }; WOLFSSL_API WOLFSSL_DSA* wolfSSL_DSA_new(void); WOLFSSL_API void wolfSSL_DSA_free(WOLFSSL_DSA* dsa); +WOLFSSL_API int wolfSSL_DSA_up_ref(WOLFSSL_DSA* dsa); #if !defined(NO_FILESYSTEM) && !defined(NO_STDIO_FILESYSTEM) WOLFSSL_API int wolfSSL_DSA_print_fp(XFILE fp, WOLFSSL_DSA* dsa, int indent); #endif /* !NO_FILESYSTEM && NO_STDIO_FILESYSTEM */ @@ -96,6 +98,7 @@ WOLFSSL_API int wolfSSL_DSA_do_verify( const unsigned char* d, unsigned char* sig, WOLFSSL_DSA* dsa, int *dsacheck); WOLFSSL_API int wolfSSL_DSA_bits(const WOLFSSL_DSA *d); +WOLFSSL_API int wolfSSL_DSA_size(const WOLFSSL_DSA *dsa); WOLFSSL_API WOLFSSL_DSA_SIG* wolfSSL_DSA_SIG_new(void); WOLFSSL_API void wolfSSL_DSA_SIG_free(WOLFSSL_DSA_SIG *sig); @@ -131,12 +134,14 @@ typedef WOLFSSL_DSA DSA; #define DSA_new wolfSSL_DSA_new #define DSA_free wolfSSL_DSA_free +#define DSA_up_ref wolfSSL_DSA_up_ref #define DSA_print_fp wolfSSL_DSA_print_fp #define DSA_LoadDer wolfSSL_DSA_LoadDer #define DSA_generate_key wolfSSL_DSA_generate_key #define DSA_generate_parameters wolfSSL_DSA_generate_parameters #define DSA_generate_parameters_ex wolfSSL_DSA_generate_parameters_ex +#define DSA_size wolfSSL_DSA_size #define DSA_get0_pqg wolfSSL_DSA_get0_pqg #define DSA_set0_pqg wolfSSL_DSA_set0_pqg #define DSA_get0_key wolfSSL_DSA_get0_key diff --git a/wolfssl/openssl/ec.h b/wolfssl/openssl/ec.h index 95e32972fa4..3d50c8be8b4 100644 --- a/wolfssl/openssl/ec.h +++ b/wolfssl/openssl/ec.h @@ -124,6 +124,18 @@ enum { #define NID_brainpoolP320r1 WC_NID_brainpoolP320r1 #define NID_brainpoolP384r1 WC_NID_brainpoolP384r1 #define NID_brainpoolP512r1 WC_NID_brainpoolP512r1 + +/* Short names of the curves, as OBJ_nid2sn() returns them */ +#define SN_X9_62_prime192v1 "prime192v1" +#define SN_X9_62_prime192v2 "prime192v2" +#define SN_X9_62_prime192v3 "prime192v3" +#define SN_X9_62_prime239v1 "prime239v1" +#define SN_X9_62_prime239v2 "prime239v2" +#define SN_X9_62_prime239v3 "prime239v3" +#define SN_X9_62_prime256v1 "prime256v1" +#define SN_secp224r1 "secp224r1" +#define SN_secp384r1 "secp384r1" +#define SN_secp521r1 "secp521r1" #endif #ifdef HAVE_ED448 diff --git a/wolfssl/openssl/err.h b/wolfssl/openssl/err.h index 9c3b0b1c5bf..e8522e77903 100644 --- a/wolfssl/openssl/err.h +++ b/wolfssl/openssl/err.h @@ -59,6 +59,14 @@ /* err.h for openssl */ #define ERR_load_ERR_strings wolfSSL_ERR_load_ERR_strings +#define ERR_get_next_error_library wolfSSL_ERR_get_next_error_library +#define ERR_load_strings wolfSSL_ERR_load_strings +#define ERR_unload_strings wolfSSL_ERR_unload_strings +#define ERR_STRING_DATA WOLFSSL_ERR_STRING_DATA +#define ERR_PACK(l, f, r) \ + ((((unsigned long)(l) & 0xFFUL) << 24) | \ + (((unsigned long)(f) & 0xFFFUL) << 12) | \ + ((unsigned long)(r) & 0xFFFUL)) #define ERR_load_crypto_strings wolfSSL_ERR_load_crypto_strings #define ERR_load_CRYPTO_strings wolfSSL_ERR_load_crypto_strings #define ERR_peek_last_error wolfSSL_ERR_peek_last_error diff --git a/wolfssl/openssl/evp.h b/wolfssl/openssl/evp.h index f55728b41df..b5ad2c0e328 100644 --- a/wolfssl/openssl/evp.h +++ b/wolfssl/openssl/evp.h @@ -443,6 +443,10 @@ enum { WC_EVP_PKEY_RSA = 16, WC_EVP_PKEY_DSA = 17, WC_EVP_PKEY_EC = 18, + /* OpenSSL RSA key types. wolfSSL never creates keys of these types; + * they exist so code that switches on them compiles. */ + WC_EVP_PKEY_RSA2 = 19, + WC_EVP_PKEY_RSA_PSS = WC_NID_rsassaPss, WC_AES_128_GCM_TYPE = 21, WC_AES_192_GCM_TYPE = 22, WC_AES_256_GCM_TYPE = 23, @@ -522,6 +526,8 @@ enum { #define EVP_PKEY_RSA WC_EVP_PKEY_RSA #define EVP_PKEY_DSA WC_EVP_PKEY_DSA #define EVP_PKEY_EC WC_EVP_PKEY_EC +#define EVP_PKEY_RSA2 WC_EVP_PKEY_RSA2 +#define EVP_PKEY_RSA_PSS WC_EVP_PKEY_RSA_PSS #define AES_128_GCM_TYPE WC_AES_128_GCM_TYPE #define AES_192_GCM_TYPE WC_AES_192_GCM_TYPE #define AES_256_GCM_TYPE WC_AES_256_GCM_TYPE diff --git a/wolfssl/openssl/rsa.h b/wolfssl/openssl/rsa.h index 0c28c4427b9..d7bea15e47d 100644 --- a/wolfssl/openssl/rsa.h +++ b/wolfssl/openssl/rsa.h @@ -177,6 +177,27 @@ WOLFSSL_LOCAL int wolfSSL_RSA_verify_mgf(int hashAlg, int mgf1Hash, int saltLen); WOLFSSL_API int wolfSSL_RSA_public_decrypt(int flen, const unsigned char* from, unsigned char* to, WOLFSSL_RSA* rsa, int padding); +#if defined(OPENSSL_EXTRA) && !defined(WC_NO_RSA_OAEP) && \ + !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0)) \ + && !defined(WOLFSSL_RSA_PUBLIC_ONLY) && !defined(WOLFSSL_RSA_VERIFY_ONLY) + /* RSA_padding_add_PKCS1_OAEP and RSA_padding_check_PKCS1_OAEP */ + #define WOLFSSL_RSA_OAEP_COMPAT +#endif +#ifdef WOLFSSL_RSA_OAEP_COMPAT +WOLFSSL_API int wolfSSL_RSA_padding_add_PKCS1_OAEP(unsigned char* to, int tlen, + const unsigned char* from, int flen, const unsigned char* param, int plen); +WOLFSSL_API int wolfSSL_RSA_padding_add_PKCS1_OAEP_mgf1(unsigned char* to, + int tlen, const unsigned char* from, int flen, const unsigned char* param, + int plen, const WOLFSSL_EVP_MD* md, const WOLFSSL_EVP_MD* mgf1md); +/* An empty message fails, as wolfCrypt reports it as a decoding error. */ +WOLFSSL_API int wolfSSL_RSA_padding_check_PKCS1_OAEP(unsigned char* to, + int tlen, const unsigned char* from, int flen, int num, + const unsigned char* param, int plen); +WOLFSSL_API int wolfSSL_RSA_padding_check_PKCS1_OAEP_mgf1(unsigned char* to, + int tlen, const unsigned char* from, int flen, int num, + const unsigned char* param, int plen, const WOLFSSL_EVP_MD* md, + const WOLFSSL_EVP_MD* mgf1md); +#endif WOLFSSL_API int wolfSSL_RSA_GenAdd(WOLFSSL_RSA* rsa); WOLFSSL_API int wolfSSL_RSA_LoadDer(WOLFSSL_RSA* rsa, const unsigned char* derBuf, int derSz); @@ -275,6 +296,15 @@ WOLFSSL_API int wolfSSL_RSA_set_ex_data_with_cleanup( #define RSA_get0_key wolfSSL_RSA_get0_key +#ifdef WOLFSSL_RSA_OAEP_COMPAT +#define RSA_padding_add_PKCS1_OAEP wolfSSL_RSA_padding_add_PKCS1_OAEP +#define RSA_padding_check_PKCS1_OAEP wolfSSL_RSA_padding_check_PKCS1_OAEP +#define RSA_padding_add_PKCS1_OAEP_mgf1 \ + wolfSSL_RSA_padding_add_PKCS1_OAEP_mgf1 +#define RSA_padding_check_PKCS1_OAEP_mgf1 \ + wolfSSL_RSA_padding_check_PKCS1_OAEP_mgf1 +#endif + #define RSA_F4 WOLFSSL_RSA_F4 #define OPENSSL_RSA_MAX_MODULUS_BITS RSA_MAX_SIZE diff --git a/wolfssl/openssl/ssl.h b/wolfssl/openssl/ssl.h index fa669e3c618..e4af2c5f48e 100644 --- a/wolfssl/openssl/ssl.h +++ b/wolfssl/openssl/ssl.h @@ -656,6 +656,8 @@ typedef STACK_OF(ACCESS_DESCRIPTION) AUTHORITY_INFO_ACCESS; #define X509_add1_ext_i2d wolfSSL_X509_add1_ext_i2d #define X509_delete_ext wolfSSL_X509_delete_ext #define X509_get0_subject_key_id wolfSSL_X509_get0_subject_key_id +#define X509_alias_get0 wolfSSL_X509_alias_get0 +#define X509_keyid_get0 wolfSSL_X509_keyid_get0 #define X509_EXTENSION_get_object wolfSSL_X509_EXTENSION_get_object #define X509_EXTENSION_get_data wolfSSL_X509_EXTENSION_get_data @@ -672,6 +674,9 @@ typedef STACK_OF(ACCESS_DESCRIPTION) AUTHORITY_INFO_ACCESS; #define sk_X509_dup wolfSSL_shallow_sk_dup #define sk_X509_delete(sk, i) \ ((WOLFSSL_X509*)wolfSSL_sk_delete((sk), (i))) +#define sk_X509_delete_ptr(sk, x) \ + ((WOLFSSL_X509*)wolfSSL_sk_delete_ptr((sk), (x))) +#define sk_X509_insert(sk, x, i) wolfSSL_sk_insert((sk), (x), (i)) #define sk_X509_free wolfSSL_sk_X509_free #define X509_chain_up_ref wolfSSL_X509_chain_up_ref @@ -720,6 +725,7 @@ typedef STACK_OF(ACCESS_DESCRIPTION) AUTHORITY_INFO_ACCESS; #define X509_NAME_cmp wolfSSL_X509_NAME_cmp #define X509_NAME_ENTRY_new wolfSSL_X509_NAME_ENTRY_new #define X509_NAME_ENTRY_free wolfSSL_X509_NAME_ENTRY_free +#define X509_NAME_ENTRY_dup wolfSSL_X509_NAME_ENTRY_dup #define X509_NAME_ENTRY_create_by_NID wolfSSL_X509_NAME_ENTRY_create_by_NID #define X509_NAME_ENTRY_create_by_txt wolfSSL_X509_NAME_ENTRY_create_by_txt #define X509_NAME_add_entry wolfSSL_X509_NAME_add_entry @@ -766,6 +772,9 @@ typedef WOLFSSL_X509_NAME_ENTRY X509_NAME_ENTRY; #define sk_X509_NAME_ENTRY_num wolfSSL_sk_X509_NAME_ENTRY_num #define sk_X509_NAME_ENTRY_value wolfSSL_sk_X509_NAME_ENTRY_value #define sk_X509_NAME_ENTRY_free wolfSSL_sk_X509_NAME_ENTRY_free +#define sk_X509_NAME_ENTRY_pop_free wolfSSL_sk_X509_NAME_ENTRY_pop_free +#define sk_X509_NAME_ENTRY_set_cmp_func wolfSSL_sk_X509_NAME_ENTRY_set_cmp_func +#define sk_X509_NAME_ENTRY_sort wolfSSL_sk_X509_NAME_ENTRY_sort #define X509_V_FLAG_CRL_CHECK WOLFSSL_X509_V_FLAG_CRL_CHECK #define X509_V_FLAG_CRL_CHECK_ALL WOLFSSL_X509_V_FLAG_CRL_CHECK_ALL @@ -805,6 +814,16 @@ typedef WOLFSSL_X509_NAME_ENTRY X509_NAME_ENTRY; #define X509_STORE_CTX_set_error_depth wolfSSL_X509_STORE_CTX_set_error_depth #define X509_STORE_CTX_get_ex_data wolfSSL_X509_STORE_CTX_get_ex_data #define X509_STORE_CTX_set_ex_data wolfSSL_X509_STORE_CTX_set_ex_data +#ifdef OPENSSL_EXTRA +/* wolfSSL keeps the SSL at index 0 in a TLS verify callback. */ +#define WOLFSSL_X509_STORE_CTX_APP_DATA_IDX 1 +#define X509_STORE_CTX_set_app_data(ctx, data) \ + wolfSSL_X509_STORE_CTX_set_ex_data((ctx), \ + WOLFSSL_X509_STORE_CTX_APP_DATA_IDX, (data)) +#define X509_STORE_CTX_get_app_data(ctx) \ + wolfSSL_X509_STORE_CTX_get_ex_data((ctx), \ + WOLFSSL_X509_STORE_CTX_APP_DATA_IDX) +#endif #define X509_STORE_CTX_set_depth wolfSSL_X509_STORE_CTX_set_depth #define X509_STORE_CTX_verify_cb WOLFSSL_X509_STORE_CTX_verify_cb #define X509_STORE_CTX_get0_current_issuer \ @@ -833,6 +852,7 @@ wolfSSL_X509_STORE_set_verify_cb((WOLFSSL_X509_STORE *)(s), (WOLFSSL_X509_STORE_ #define X509_STORE_set_flags wolfSSL_X509_STORE_set_flags #define X509_STORE_get1_certs wolfSSL_X509_STORE_get1_certs #define X509_STORE_get_by_subject wolfSSL_X509_STORE_get_by_subject +#define X509_STORE_CTX_get_by_subject wolfSSL_X509_STORE_CTX_get_by_subject #define X509_STORE_set_ex_data wolfSSL_X509_STORE_set_ex_data #define X509_STORE_get_ex_data wolfSSL_X509_STORE_get_ex_data #define X509_STORE_get0_param wolfSSL_X509_STORE_get0_param @@ -840,10 +860,12 @@ wolfSSL_X509_STORE_set_verify_cb((WOLFSSL_X509_STORE *)(s), (WOLFSSL_X509_STORE_ #define X509_STORE_CTX_get1_issuer wolfSSL_X509_STORE_CTX_get1_issuer #define X509_STORE_CTX_set_time wolfSSL_X509_STORE_CTX_set_time #define X509_STORE_CTX_get0_param wolfSSL_X509_STORE_CTX_get0_param +#define X509_STORE_CTX_set0_param wolfSSL_X509_STORE_CTX_set0_param #define X509_VERIFY_PARAM_new wolfSSL_X509_VERIFY_PARAM_new #define X509_VERIFY_PARAM_free wolfSSL_X509_VERIFY_PARAM_free #define X509_VERIFY_PARAM_set_flags wolfSSL_X509_VERIFY_PARAM_set_flags #define X509_VERIFY_PARAM_set_time wolfSSL_X509_VERIFY_PARAM_set_time +#define X509_VERIFY_PARAM_set_depth wolfSSL_X509_VERIFY_PARAM_set_depth #define X509_VERIFY_PARAM_get_flags wolfSSL_X509_VERIFY_PARAM_get_flags #define X509_VERIFY_PARAM_clear_flags wolfSSL_X509_VERIFY_PARAM_clear_flags #define X509_VERIFY_PARAM_set_hostflags wolfSSL_X509_VERIFY_PARAM_set_hostflags @@ -1074,8 +1096,8 @@ wolfSSL_X509_STORE_set_verify_cb((WOLFSSL_X509_STORE *)(s), (WOLFSSL_X509_STORE_ #define ASN1_OCTET_STRING_cmp wolfSSL_ASN1_STRING_cmp #define ASN1_STRING_data wolfSSL_ASN1_STRING_data /* In OpenSSL, ASN1_INTEGER is a typedef alias of ASN1_STRING (same struct), - * so ASN1_STRING_length/get0_data work on ASN1_INTEGER* as well. - * In wolfSSL they are distinct structs, so dispatch by type using _Generic. */ + * so ASN1_STRING_length/get0_data/type work on ASN1_INTEGER* as well. + * In wolfSSL they are distinct structs, so dispatch by type. */ #if !defined(__cplusplus) && defined(__STDC_VERSION__) && \ __STDC_VERSION__ >= 201112L #define ASN1_STRING_length(x) \ @@ -1090,9 +1112,42 @@ wolfSSL_X509_STORE_set_verify_cb((WOLFSSL_X509_STORE *)(s), (WOLFSSL_X509_STORE_ const WOLFSSL_ASN1_INTEGER*: wolfSSL_ASN1_INTEGER_get0_data, \ default: wolfSSL_ASN1_STRING_get0_data \ )(x) +#define ASN1_STRING_type(x) \ + _Generic((x), \ + WOLFSSL_ASN1_INTEGER*: wolfSSL_ASN1_INTEGER_get_type, \ + const WOLFSSL_ASN1_INTEGER*: wolfSSL_ASN1_INTEGER_get_type, \ + default: wolfSSL_ASN1_STRING_type \ + )(x) +#elif !defined(__cplusplus) && (defined(__GNUC__) || defined(__clang__)) +/* Before C11. The call not taken gets a NULL of its parameter type, so x is + * still type checked and evaluated once. As with _Generic, these are + * function-like macros: for a function pointer use + * wolfSSL_ASN1_STRING_length or wolfSSL_ASN1_INTEGER_get_length. */ +#define WOLFSSL_ASN1_IS_INTEGER(x) \ + (__builtin_types_compatible_p(__typeof__(x), WOLFSSL_ASN1_INTEGER*) || \ + __builtin_types_compatible_p(__typeof__(x), const WOLFSSL_ASN1_INTEGER*)) +#define WOLFSSL_ASN1_INTEGER_ARG(x) \ + __builtin_choose_expr(WOLFSSL_ASN1_IS_INTEGER(x), (x), \ + (const WOLFSSL_ASN1_INTEGER*)0) +#define WOLFSSL_ASN1_STRING_ARG(x) \ + __builtin_choose_expr(WOLFSSL_ASN1_IS_INTEGER(x), \ + (const WOLFSSL_ASN1_STRING*)0, (x)) +#define ASN1_STRING_length(x) \ + __builtin_choose_expr(WOLFSSL_ASN1_IS_INTEGER(x), \ + wolfSSL_ASN1_INTEGER_get_length(WOLFSSL_ASN1_INTEGER_ARG(x)), \ + wolfSSL_ASN1_STRING_length(WOLFSSL_ASN1_STRING_ARG(x))) +#define ASN1_STRING_get0_data(x) \ + __builtin_choose_expr(WOLFSSL_ASN1_IS_INTEGER(x), \ + wolfSSL_ASN1_INTEGER_get0_data(WOLFSSL_ASN1_INTEGER_ARG(x)), \ + wolfSSL_ASN1_STRING_get0_data(WOLFSSL_ASN1_STRING_ARG(x))) +#define ASN1_STRING_type(x) \ + __builtin_choose_expr(WOLFSSL_ASN1_IS_INTEGER(x), \ + wolfSSL_ASN1_INTEGER_get_type(WOLFSSL_ASN1_INTEGER_ARG(x)), \ + wolfSSL_ASN1_STRING_type(WOLFSSL_ASN1_STRING_ARG(x))) #else #define ASN1_STRING_get0_data wolfSSL_ASN1_STRING_get0_data #define ASN1_STRING_length wolfSSL_ASN1_STRING_length +#define ASN1_STRING_type wolfSSL_ASN1_STRING_type #endif #define ASN1_STRING_to_UTF8 wolfSSL_ASN1_STRING_to_UTF8 #define ASN1_UNIVERSALSTRING_to_string wolfSSL_ASN1_UNIVERSALSTRING_to_string @@ -1320,6 +1375,8 @@ typedef wolfSSL_custom_ext_parse_cb custom_ext_parse_cb; #define sk_value wolfSSL_sk_value #define sk_ASN1_OBJECT_value wolfSSL_sk_value #define OPENSSL_sk_value wolfSSL_sk_value +#define OPENSSL_sk_set_cmp_func wolfSSL_sk_set_cmp_func +#define OPENSSL_sk_sort wolfSSL_sk_sort #define d2i_PKCS12_bio wolfSSL_d2i_PKCS12_bio #define d2i_PKCS12_fp wolfSSL_d2i_PKCS12_fp diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index ad14fcf5ab4..9d0cf6d447a 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -410,6 +410,9 @@ typedef int (*WOLFSSL_X509_STORE_CTX_check_crl_cb)(WOLFSSL_X509_STORE_CTX *, #define WOLFSSL_V_ASN1_CONSTRUCTED 0x20 +/* Type bit of an OCTET STRING, as in OpenSSL */ +#define WOLFSSL_B_ASN1_OCTET_STRING 0x0200 + #define WOLFSSL_ASN1_STRING_FLAG_BITS_LEFT 0x008 #define WOLFSSL_ASN1_STRING_FLAG_NDEF 0x010 #define WOLFSSL_ASN1_STRING_FLAG_CONT 0x020 @@ -711,10 +714,6 @@ struct WOLFSSL_X509_STORE_CTX { char* domain; /* subject CN domain name */ #ifdef HAVE_EX_DATA WOLFSSL_CRYPTO_EX_DATA ex_data; /* external data */ -#endif -#if defined(WOLFSSL_APACHE_HTTPD) || defined(OPENSSL_EXTRA) - int depth; /* used in X509_STORE_CTX_*_depth: defaults - to WOLFSSL_X509_STORE_DEFAULT_MAX_DEPTH */ #endif void* userCtx; /* user ctx */ int error; /* current error */ @@ -727,7 +726,6 @@ struct WOLFSSL_X509_STORE_CTX { int flags; #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) - WOLF_STACK_OF(WOLFSSL_X509)* owned; /* Certs owned by this CTX */ WOLF_STACK_OF(WOLFSSL_X509)* ctxIntermediates; /* Intermediates specified * on store ctx init */ WOLF_STACK_OF(WOLFSSL_X509)* setTrustedSk;/* A trusted stack override @@ -901,6 +899,7 @@ struct WOLFSSL_X509_STORE { WOLF_STACK_OF(WOLFSSL_X509)* trusted; WOLF_STACK_OF(WOLFSSL_X509)* owned; word32 numAdded; /* Unused, retained for ABI */ + WOLF_STACK_OF(WOLFSSL_X509)* added; /* certs and trusted, as added */ }; #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) @@ -929,6 +928,7 @@ struct WOLFSSL_X509_VERIFY_PARAM { char hostName[WOLFSSL_HOST_NAME_MAX]; unsigned int hostFlags; char ipasc[WOLFSSL_MAX_IPSTR]; + int depth; /* max intermediate CAs, -1 when unset */ }; #endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */ @@ -2134,6 +2134,12 @@ WOLFSSL_API int wolfSSL_sk_push(WOLFSSL_STACK *st, const void *data); WOLFSSL_API int wolfSSL_sk_insert(WOLFSSL_STACK *sk, const void *data, int idx); WOLFSSL_API void* wolfSSL_sk_pop(WOLFSSL_STACK* sk); WOLFSSL_API void* wolfSSL_sk_delete(WOLFSSL_STACK* sk, int idx); +WOLFSSL_API void* wolfSSL_sk_delete_ptr(WOLFSSL_STACK* sk, const void* data); +#ifdef OPENSSL_ALL +WOLFSSL_API wolf_sk_compare_cb wolfSSL_sk_set_cmp_func(WOLFSSL_STACK* sk, + wolf_sk_compare_cb cb); +WOLFSSL_API void wolfSSL_sk_sort(WOLFSSL_STACK* sk); +#endif #endif #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) || \ defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || defined(OPENSSL_ALL) @@ -2500,6 +2506,12 @@ WOLFSSL_API unsigned char* wolfSSL_X509_get_subjectKeyID( WOLFSSL_X509* x509, unsigned char* dst, int* dstLen); WOLFSSL_API const WOLFSSL_ASN1_STRING *wolfSSL_X509_get0_subject_key_id( WOLFSSL_X509 *x509); +#ifdef OPENSSL_EXTRA +WOLFSSL_API unsigned char* wolfSSL_X509_alias_get0(WOLFSSL_X509* x509, + int* len); +WOLFSSL_API unsigned char* wolfSSL_X509_keyid_get0(WOLFSSL_X509* x509, + int* len); +#endif WOLFSSL_API int wolfSSL_X509_verify(WOLFSSL_X509* x509, WOLFSSL_EVP_PKEY* pkey); #ifdef WOLFSSL_CERT_REQ @@ -2571,6 +2583,7 @@ WOLFSSL_API int wolfSSL_ASN1_STRING_length(const WOLFSSL_ASN1_STRING* asn); WOLFSSL_API int wolfSSL_ASN1_INTEGER_get_length(const WOLFSSL_ASN1_INTEGER* ai); WOLFSSL_API const unsigned char* wolfSSL_ASN1_INTEGER_get0_data( const WOLFSSL_ASN1_INTEGER* ai); +WOLFSSL_API int wolfSSL_ASN1_INTEGER_get_type(const WOLFSSL_ASN1_INTEGER* ai); WOLFSSL_API int wolfSSL_ASN1_STRING_copy(WOLFSSL_ASN1_STRING* dst, const WOLFSSL_ASN1_STRING* src); /* NOTE: a single WOLFSSL_X509_STORE must not be shared across threads that @@ -2606,9 +2619,14 @@ WOLFSSL_API WOLFSSL_X509_STORE_CTX *wolfSSL_X509_STORE_CTX_get0_parent_ctx( WOLFSSL_API int wolfSSL_X509_STORE_set_flags(WOLFSSL_X509_STORE* store, unsigned long flag); WOLFSSL_API int wolfSSL_X509_STORE_get_by_subject(WOLFSSL_X509_STORE_CTX* ctx, - int idx, WOLFSSL_X509_NAME* name, WOLFSSL_X509_OBJECT* obj); + int type, WOLFSSL_X509_NAME* name, WOLFSSL_X509_OBJECT* obj); +WOLFSSL_API int wolfSSL_X509_STORE_CTX_get_by_subject( + WOLFSSL_X509_STORE_CTX* ctx, WOLFSSL_X509_LOOKUP_TYPE type, + WOLFSSL_X509_NAME* name, WOLFSSL_X509_OBJECT* obj); WOLFSSL_API WOLFSSL_X509_VERIFY_PARAM *wolfSSL_X509_STORE_CTX_get0_param( WOLFSSL_X509_STORE_CTX *ctx); +WOLFSSL_API void wolfSSL_X509_STORE_CTX_set0_param(WOLFSSL_X509_STORE_CTX *ctx, + WOLFSSL_X509_VERIFY_PARAM *param); WOLFSSL_API int wolfSSL_X509_STORE_CTX_init(WOLFSSL_X509_STORE_CTX* ctx, WOLFSSL_X509_STORE* store, WOLFSSL_X509* x509, WOLF_STACK_OF(WOLFSSL_X509)*); WOLFSSL_API void wolfSSL_X509_STORE_CTX_cleanup(WOLFSSL_X509_STORE_CTX* ctx); @@ -2686,6 +2704,8 @@ WOLFSSL_API int wolfSSL_X509_VERIFY_PARAM_set_flags(WOLFSSL_X509_VERIFY_PARAM *p unsigned long flags); WOLFSSL_API void wolfSSL_X509_VERIFY_PARAM_set_time( WOLFSSL_X509_VERIFY_PARAM *param, time_t t); +WOLFSSL_API void wolfSSL_X509_VERIFY_PARAM_set_depth( + WOLFSSL_X509_VERIFY_PARAM *param, int depth); WOLFSSL_API int wolfSSL_X509_VERIFY_PARAM_get_flags(WOLFSSL_X509_VERIFY_PARAM *param); WOLFSSL_API int wolfSSL_X509_VERIFY_PARAM_clear_flags(WOLFSSL_X509_VERIFY_PARAM *param, unsigned long flags); @@ -2956,14 +2976,19 @@ WOLFSSL_API long wolfSSL_get_default_read_buffer_len(const WOLFSSL* ssl); enum { WOLFSSL_X509_V_OK = 0, WOLFSSL_X509_V_ERR_UNSPECIFIED = 1, + WOLFSSL_X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT = 2, WOLFSSL_X509_V_ERR_UNABLE_TO_GET_CRL = 3, WOLFSSL_X509_V_ERR_CERT_SIGNATURE_FAILURE = 7, + WOLFSSL_X509_V_ERR_CRL_SIGNATURE_FAILURE = 8, WOLFSSL_X509_V_ERR_CERT_NOT_YET_VALID = 9, WOLFSSL_X509_V_ERR_CERT_HAS_EXPIRED = 10, + WOLFSSL_X509_V_ERR_CRL_NOT_YET_VALID = 11, WOLFSSL_X509_V_ERR_CRL_HAS_EXPIRED = 12, WOLFSSL_X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD = 13, WOLFSSL_X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD = 14, + WOLFSSL_X509_V_ERR_OUT_OF_MEM = 17, WOLFSSL_X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT = 18, + WOLFSSL_X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN = 19, WOLFSSL_X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY = 20, WOLFSSL_X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE = 21, WOLFSSL_X509_V_ERR_CERT_CHAIN_TOO_LONG = 22, @@ -2972,9 +2997,15 @@ enum { WOLFSSL_X509_V_ERR_INVALID_PURPOSE = 26, WOLFSSL_X509_V_ERR_CERT_REJECTED = 28, WOLFSSL_X509_V_ERR_SUBJECT_ISSUER_MISMATCH = 29, + WOLFSSL_X509_V_ERR_KEYUSAGE_NO_CERTSIGN = 32, + WOLFSSL_X509_V_ERR_KEYUSAGE_NO_CRL_SIGN = 35, + WOLFSSL_X509_V_ERR_PERMITTED_VIOLATION = 47, + WOLFSSL_X509_V_ERR_EXCLUDED_VIOLATION = 48, + WOLFSSL_X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE = 51, WOLFSSL_X509_V_ERR_APPLICATION_VERIFICATION = 50, WOLFSSL_X509_V_ERR_HOSTNAME_MISMATCH = 62, WOLFSSL_X509_V_ERR_IP_ADDRESS_MISMATCH = 64, + WOLFSSL_X509_V_ERR_CA_KEY_TOO_SMALL = 67, WOLFSSL_X509_V_ERR_INVALID_CA = 79, WC_OSSL_V509_V_ERR_MAX = 80, /* 95 matches OpenSSL's X509_V_ERR_RPK_UNTRUSTED (OpenSSL 3.2+). It is @@ -3574,6 +3605,21 @@ WOLFSSL_API unsigned long wolfSSL_ERR_get_error_line_data(const char** file, int WOLFSSL_API unsigned long wolfSSL_ERR_get_error(void); WOLFSSL_API void wolfSSL_ERR_clear_error(void); +#ifdef OPENSSL_EXTRA +/* Error string of an error library registered by the application. */ +typedef struct WOLFSSL_ERR_STRING_DATA { + unsigned long error; + const char* string; +} WOLFSSL_ERR_STRING_DATA; + +/* wolfSSL_ERR_put_error() does not queue errors of these libraries. */ +WOLFSSL_API int wolfSSL_ERR_get_next_error_library(void); +WOLFSSL_API int wolfSSL_ERR_load_strings(int lib, + WOLFSSL_ERR_STRING_DATA* str); +WOLFSSL_API int wolfSSL_ERR_unload_strings(int lib, + WOLFSSL_ERR_STRING_DATA* str); +#endif + WOLFSSL_API int wolfSSL_RAND_status(void); WOLFSSL_API int wolfSSL_RAND_pseudo_bytes(unsigned char* buf, int num); @@ -5834,6 +5880,10 @@ WOLFSSL_API int wolfSSL_X509_NAME_ENTRY_set(const WOLFSSL_X509_NAME_ENTRY *ne); || defined(OPENSSL_EXTRA_X509_SMALL) WOLFSSL_API void wolfSSL_X509_NAME_ENTRY_free(WOLFSSL_X509_NAME_ENTRY* ne); WOLFSSL_API WOLFSSL_X509_NAME_ENTRY* wolfSSL_X509_NAME_ENTRY_new(void); +#ifdef OPENSSL_EXTRA +WOLFSSL_API WOLFSSL_X509_NAME_ENTRY* wolfSSL_X509_NAME_ENTRY_dup( + const WOLFSSL_X509_NAME_ENTRY* ne); +#endif #ifndef wolfSSL_X509_NAME_free WOLFSSL_API void wolfSSL_X509_NAME_free(WOLFSSL_X509_NAME* name); #endif @@ -5950,6 +6000,10 @@ WOLFSSL_API int wolfSSL_CRYPTO_set_mem_functions( wolfSSL_OSSL_Malloc_cb m, wolfSSL_OSSL_Realloc_cb r, wolfSSL_OSSL_Free_cb f); +WOLFSSL_API void wolfSSL_CRYPTO_get_mem_functions( + wolfSSL_OSSL_Malloc_cb* m, + wolfSSL_OSSL_Realloc_cb* r, + wolfSSL_OSSL_Free_cb* f); WOLFSSL_API int wolfSSL_CRYPTO_set_mem_ex_functions(void *(*m) (size_t, const char *, int), void *(*r) (void *, size_t, const char *, int), void (*f) (void *)); @@ -6038,6 +6092,19 @@ WOLFSSL_API WOLFSSL_X509_NAME_ENTRY* wolfSSL_sk_X509_NAME_ENTRY_value(const WOLF_STACK_OF(WOLFSSL_X509_NAME_ENTRY)* sk, int i); WOLFSSL_API int wolfSSL_sk_X509_NAME_ENTRY_num(const WOLF_STACK_OF(WOLFSSL_X509_NAME_ENTRY)* sk); WOLFSSL_API void wolfSSL_sk_X509_NAME_ENTRY_free(WOLF_STACK_OF(WOLFSSL_X509_NAME_ENTRY)* sk); +WOLFSSL_API void wolfSSL_sk_X509_NAME_ENTRY_pop_free( + WOLF_STACK_OF(WOLFSSL_X509_NAME_ENTRY)* sk, + void (*f)(WOLFSSL_X509_NAME_ENTRY*)); +#ifdef OPENSSL_ALL +typedef WOLF_SK_COMPARE_CB(WOLFSSL_X509_NAME_ENTRY, + wolf_sk_X509_NAME_ENTRY_cmp_cb); +WOLFSSL_API wolf_sk_X509_NAME_ENTRY_cmp_cb + wolfSSL_sk_X509_NAME_ENTRY_set_cmp_func( + WOLF_STACK_OF(WOLFSSL_X509_NAME_ENTRY)* sk, + wolf_sk_X509_NAME_ENTRY_cmp_cb cb); +WOLFSSL_API void wolfSSL_sk_X509_NAME_ENTRY_sort( + WOLF_STACK_OF(WOLFSSL_X509_NAME_ENTRY)* sk); +#endif WOLFSSL_API int wolfSSL_sk_X509_OBJECT_num(const WOLF_STACK_OF(WOLFSSL_X509_OBJECT) *s); diff --git a/wolfssl/test.h b/wolfssl/test.h index d89a48cfa60..5222a24f27c 100644 --- a/wolfssl/test.h +++ b/wolfssl/test.h @@ -2762,7 +2762,7 @@ static WC_INLINE int myVerify(int preverify, WOLFSSL_X509_STORE_CTX* store) #if defined(OPENSSL_EXTRA) && defined(SHOW_CERTS) && !defined(NO_FILESYSTEM) \ && !defined(OPENSSL_COEXIST) /* avoid printing duplicate certs */ - if (store->depth == 1) { + if (store->error_depth == 0) { int i; /* retrieve x509 certs and display them on stdout */ sk = wolfSSL_X509_STORE_GetCerts(store); diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index 29cd5d62759..50fdf10fd59 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -2612,8 +2612,20 @@ WOLFSSL_LOCAL int EncodePolicyOID(byte *out, word32 *outSz, WOLFSSL_TEST_VIS int DecodeExtensionType(const byte* input, word32 length, word32 oid, byte critical, DecodedCert* cert, int *isUnknownExt); +WOLFSSL_LOCAL int SigOidMatchesKeyOid(word32 sigOID, word32 keyOID); WOLFSSL_LOCAL int CheckCertSignaturePubKey(const byte* cert, word32 certSz, void* heap, const byte* pubKey, word32 pubKeySz, int pubKeyOID); +#ifndef IGNORE_NAME_CONSTRAINTS +/* Name constraint violations of CheckCertNameConstraints() */ +enum { + NC_VIOLATION_EXCLUDED = 1, + NC_VIOLATION_PERMITTED = 2, + NC_VIOLATION_UNSUPPORTED = 3 +}; +WOLFSSL_LOCAL int CheckCertNameConstraints(const byte* caCert, + word32 caCertSz, const byte* cert, word32 certSz, int leaf, void* heap, + int* violation); +#endif #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_SMALL_CERT_VERIFY) WOLFSSL_API int wc_CheckCertSignature(const byte* cert, word32 certSz, void* heap, diff --git a/wolfssl/wolfcrypt/pkcs12.h b/wolfssl/wolfcrypt/pkcs12.h index 4ebd1713770..73c17d282a6 100644 --- a/wolfssl/wolfcrypt/pkcs12.h +++ b/wolfssl/wolfcrypt/pkcs12.h @@ -58,6 +58,11 @@ WOLFSSL_API int wc_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, WOLFSSL_API int wc_PKCS12_parse_ex(WC_PKCS12* pkcs12, const char* psw, byte** pkey, word32* pkeySz, byte** cert, word32* certSz, WC_DerCertList** ca, int keepKeyHeader); +WOLFSSL_LOCAL int wc_PKCS12_parse_ex2(WC_PKCS12* pkcs12, const char* psw, + byte** pkey, word32* pkeySz, byte** cert, word32* certSz, + WC_DerCertList** ca, int keepKeyHeader, + byte** friendlyName, word32* friendlyNameSz, + byte** localKeyId, word32* localKeyIdSz); WOLFSSL_LOCAL int wc_PKCS12_verify_ex(WC_PKCS12* pkcs12, const byte* psw, word32 pswSz); WOLFSSL_API WC_PKCS12* wc_PKCS12_create(char* pass, word32 passSz, diff --git a/wolfssl/wolfcrypt/settings.h b/wolfssl/wolfcrypt/settings.h index 6564f4aa52a..62b4512ef1b 100644 --- a/wolfssl/wolfcrypt/settings.h +++ b/wolfssl/wolfcrypt/settings.h @@ -5251,10 +5251,11 @@ blinding by defining WC_BLINDING_NO_RNG_ACKNOWLEDGE_WEAKNESS." #define WOLFSSL_COPY_KEY #endif -/* X509_STORE_get0_objects() can only enumerate a store's certificates when the - * CA table keeps their DER. Costs one DER copy per loaded CA, so it stays - * optional; define WOLFSSL_NO_SIGNER_DER_CERT to opt back out. */ -#if defined(OPENSSL_ALL) && !defined(WOLFSSL_NO_SIGNER_DER_CERT) +/* X509_verify_cert() can only put a CA of the cert manager on the chain and + * check it, and X509_STORE_get0_objects() can only enumerate a store's + * certificates, when the CA table keeps their DER. Costs one DER copy per + * loaded CA; define WOLFSSL_NO_SIGNER_DER_CERT to opt back out. */ +#if defined(OPENSSL_EXTRA) && !defined(WOLFSSL_NO_SIGNER_DER_CERT) #undef WOLFSSL_SIGNER_DER_CERT #define WOLFSSL_SIGNER_DER_CERT #endif