From f83f62e1bff0c2aedc32e67fe369ba923c5b104a Mon Sep 17 00:00:00 2001 From: JustOff Date: Sat, 9 Jun 2018 15:11:22 +0300 Subject: Update NSS to 3.36.4-RTM --- security/nss/TAG-INFO | 1 + .../abi-check/expected-report-libnspr4.so.txt | 8 - .../abi-check/expected-report-libssl3.so.txt | 29 +- .../nss/automation/abi-check/previous-nss-release | 2 +- security/nss/automation/buildbot-slave/build.sh | 45 +- security/nss/automation/release/nspr-version.txt | 2 +- security/nss/automation/saw/bmul.cry | 8 + security/nss/automation/saw/bmul.saw | 26 + security/nss/automation/saw/chacha20.cry | 357 ++++ security/nss/automation/saw/chacha20.saw | 40 + security/nss/automation/saw/poly1305-hacl.saw | 38 + security/nss/automation/saw/poly1305.cry | 336 +++ security/nss/automation/saw/poly1305.saw | 47 + .../automation/taskcluster/docker-hacl/Dockerfile | 4 +- .../automation/taskcluster/docker-saw/Dockerfile | 46 + .../taskcluster/docker-saw/LLVMgold.so.zip | Bin 0 -> 13558285 bytes .../taskcluster/docker-saw/bin/checkout.sh | 15 + .../nss/automation/taskcluster/docker/setup.sh | 22 +- .../nss/automation/taskcluster/graph/src/extend.js | 125 +- .../taskcluster/graph/src/image_builder.js | 2 +- .../nss/automation/taskcluster/graph/src/queue.js | 5 +- .../automation/taskcluster/graph/src/try_syntax.js | 5 +- .../automation/taskcluster/scripts/check_abi.sh | 172 ++ .../nss/automation/taskcluster/scripts/run_saw.sh | 9 + .../taskcluster/scripts/run_scan_build.sh | 2 +- security/nss/build.sh | 1 + security/nss/cmd/certcgi/HOWTO.txt | 137 -- security/nss/cmd/certcgi/Makefile | 48 - security/nss/cmd/certcgi/ca.html | 19 - security/nss/cmd/certcgi/ca_form.html | 357 ---- security/nss/cmd/certcgi/certcgi.c | 2245 -------------------- security/nss/cmd/certcgi/certcgi.gyp | 33 - security/nss/cmd/certcgi/index.html | 789 ------- security/nss/cmd/certcgi/main.html | 76 - security/nss/cmd/certcgi/manifest.mn | 22 - security/nss/cmd/certcgi/nscp_ext_form.html | 84 - security/nss/cmd/certcgi/stnd_ext_form.html | 219 -- security/nss/cmd/certutil/certutil.c | 2 +- security/nss/cmd/manifest.mn | 1 - security/nss/cmd/signtool/sign.c | 58 +- security/nss/coreconf/config.gypi | 5 + security/nss/cpputil/scoped_ptrs.h | 10 + security/nss/cpputil/tls_parser.h | 1 + security/nss/doc/certutil.xml | 6 +- security/nss/gtests/der_gtest/der_gtest.gyp | 3 + security/nss/gtests/der_gtest/manifest.mn | 1 + .../nss/gtests/der_gtest/p12_import_unittest.cc | 251 +++ security/nss/gtests/nss_bogo_shim/config.json | 64 + .../nss/gtests/ssl_gtest/bloomfilter_unittest.cc | 2 +- security/nss/gtests/ssl_gtest/libssl_internals.c | 4 - security/nss/gtests/ssl_gtest/libssl_internals.h | 1 - security/nss/gtests/ssl_gtest/ssl_0rtt_unittest.cc | 80 +- .../nss/gtests/ssl_gtest/ssl_agent_unittest.cc | 5 +- security/nss/gtests/ssl_gtest/ssl_auth_unittest.cc | 176 +- .../nss/gtests/ssl_gtest/ssl_cert_ext_unittest.cc | 10 +- .../gtests/ssl_gtest/ssl_ciphersuite_unittest.cc | 12 +- .../nss/gtests/ssl_gtest/ssl_custext_unittest.cc | 25 +- .../nss/gtests/ssl_gtest/ssl_damage_unittest.cc | 24 +- security/nss/gtests/ssl_gtest/ssl_dhe_unittest.cc | 82 +- security/nss/gtests/ssl_gtest/ssl_drop_unittest.cc | 78 +- security/nss/gtests/ssl_gtest/ssl_ecdh_unittest.cc | 64 +- .../nss/gtests/ssl_gtest/ssl_extension_unittest.cc | 222 +- .../nss/gtests/ssl_gtest/ssl_fragment_unittest.cc | 4 +- security/nss/gtests/ssl_gtest/ssl_fuzz_unittest.cc | 45 +- security/nss/gtests/ssl_gtest/ssl_hrr_unittest.cc | 91 +- .../nss/gtests/ssl_gtest/ssl_keylog_unittest.cc | 4 +- .../nss/gtests/ssl_gtest/ssl_loopback_unittest.cc | 77 +- .../nss/gtests/ssl_gtest/ssl_record_unittest.cc | 14 +- .../gtests/ssl_gtest/ssl_resumption_unittest.cc | 276 ++- security/nss/gtests/ssl_gtest/ssl_skip_unittest.cc | 94 +- .../nss/gtests/ssl_gtest/ssl_staticrsa_unittest.cc | 24 +- .../gtests/ssl_gtest/ssl_tls13compat_unittest.cc | 68 +- .../ssl_gtest/ssl_v2_client_hello_unittest.cc | 8 +- .../nss/gtests/ssl_gtest/ssl_version_unittest.cc | 39 +- .../gtests/ssl_gtest/ssl_versionpolicy_unittest.cc | 6 +- security/nss/gtests/ssl_gtest/test_io.cc | 4 - security/nss/gtests/ssl_gtest/test_io.h | 6 +- security/nss/gtests/ssl_gtest/tls_agent.cc | 53 +- security/nss/gtests/ssl_gtest/tls_agent.h | 38 +- security/nss/gtests/ssl_gtest/tls_connect.cc | 36 +- security/nss/gtests/ssl_gtest/tls_connect.h | 54 +- security/nss/gtests/ssl_gtest/tls_filter.cc | 8 +- security/nss/gtests/ssl_gtest/tls_filter.h | 141 +- security/nss/help.txt | 2 + security/nss/lib/certdb/stanpcertdb.c | 15 +- security/nss/lib/dev/devslot.c | 105 +- security/nss/lib/dev/devt.h | 14 +- security/nss/lib/dev/devutil.c | 2 +- security/nss/lib/freebl/Makefile | 16 +- security/nss/lib/freebl/blapii.h | 6 + security/nss/lib/freebl/blinit.c | 162 ++ security/nss/lib/freebl/chacha20.c | 19 - security/nss/lib/freebl/chacha20.h | 26 - security/nss/lib/freebl/chacha20_vec.c | 327 --- security/nss/lib/freebl/chacha20poly1305.c | 51 +- security/nss/lib/freebl/config.mk | 2 +- security/nss/lib/freebl/det_rng.c | 4 +- security/nss/lib/freebl/drbg.c | 15 +- security/nss/lib/freebl/ecl/uint128.c | 90 - security/nss/lib/freebl/ecl/uint128.h | 35 - security/nss/lib/freebl/freebl.gyp | 45 +- security/nss/lib/freebl/freebl_base.gypi | 13 +- security/nss/lib/freebl/lowhash_vector.c | 75 +- security/nss/lib/freebl/stubs.c | 8 +- .../nss/lib/freebl/verified/Hacl_Chacha20_Vec128.c | 390 ++++ .../nss/lib/freebl/verified/Hacl_Chacha20_Vec128.h | 61 + security/nss/lib/freebl/verified/kremlib_base.h | 1 + security/nss/lib/freebl/verified/vec128.h | 345 +++ security/nss/lib/nss/nss.h | 6 +- security/nss/lib/pk11wrap/dev3hack.c | 4 + security/nss/lib/pk11wrap/pk11auth.c | 2 +- security/nss/lib/pk11wrap/secmodi.h | 1 + security/nss/lib/pkcs12/p12d.c | 1 + security/nss/lib/pkcs7/p7create.c | 2 +- security/nss/lib/pkcs7/p7decode.c | 6 + security/nss/lib/pki/pkibase.c | 2 + security/nss/lib/softoken/softkver.h | 6 +- security/nss/lib/ssl/SSLerrs.h | 3 + security/nss/lib/ssl/selfencrypt.c | 44 +- security/nss/lib/ssl/ssl3con.c | 180 +- security/nss/lib/ssl/ssl3encode.c | 85 - security/nss/lib/ssl/ssl3encode.h | 26 - security/nss/lib/ssl/ssl3ext.c | 2 + security/nss/lib/ssl/ssl3exthandle.c | 14 +- security/nss/lib/ssl/ssl3gthr.c | 7 + security/nss/lib/ssl/sslcon.c | 17 +- security/nss/lib/ssl/sslencode.c | 64 +- security/nss/lib/ssl/sslencode.h | 30 +- security/nss/lib/ssl/sslerr.h | 2 + security/nss/lib/ssl/sslexp.h | 107 +- security/nss/lib/ssl/sslimpl.h | 63 +- security/nss/lib/ssl/sslinit.c | 1 + security/nss/lib/ssl/sslnonce.c | 756 ++++++- security/nss/lib/ssl/sslsecur.c | 5 +- security/nss/lib/ssl/sslsnce.c | 20 +- security/nss/lib/ssl/sslsock.c | 231 +- security/nss/lib/ssl/sslt.h | 24 +- security/nss/lib/ssl/tls13con.c | 30 +- security/nss/lib/ssl/tls13hashstate.c | 34 +- security/nss/lib/util/nssutil.h | 6 +- security/nss/lib/util/secasn1d.c | 15 +- security/nss/nss-tool/hw-support.c | 37 + security/nss/nss-tool/nss_tool.gyp | 39 +- security/nss/nss.gyp | 2 +- security/nss/tests/all.sh | 5 + security/nss/tests/bogo/bogo.sh | 2 +- security/nss/tests/common/cleanup.sh | 2 + security/nss/tests/interop/interop.sh | 10 +- 148 files changed, 5550 insertions(+), 5825 deletions(-) create mode 100644 security/nss/TAG-INFO create mode 100644 security/nss/automation/saw/bmul.cry create mode 100644 security/nss/automation/saw/bmul.saw create mode 100644 security/nss/automation/saw/chacha20.cry create mode 100644 security/nss/automation/saw/chacha20.saw create mode 100644 security/nss/automation/saw/poly1305-hacl.saw create mode 100644 security/nss/automation/saw/poly1305.cry create mode 100644 security/nss/automation/saw/poly1305.saw create mode 100644 security/nss/automation/taskcluster/docker-saw/Dockerfile create mode 100644 security/nss/automation/taskcluster/docker-saw/LLVMgold.so.zip create mode 100644 security/nss/automation/taskcluster/docker-saw/bin/checkout.sh create mode 100644 security/nss/automation/taskcluster/scripts/check_abi.sh create mode 100644 security/nss/automation/taskcluster/scripts/run_saw.sh delete mode 100644 security/nss/cmd/certcgi/HOWTO.txt delete mode 100644 security/nss/cmd/certcgi/Makefile delete mode 100644 security/nss/cmd/certcgi/ca.html delete mode 100644 security/nss/cmd/certcgi/ca_form.html delete mode 100644 security/nss/cmd/certcgi/certcgi.c delete mode 100644 security/nss/cmd/certcgi/certcgi.gyp delete mode 100644 security/nss/cmd/certcgi/index.html delete mode 100644 security/nss/cmd/certcgi/main.html delete mode 100644 security/nss/cmd/certcgi/manifest.mn delete mode 100644 security/nss/cmd/certcgi/nscp_ext_form.html delete mode 100644 security/nss/cmd/certcgi/stnd_ext_form.html create mode 100644 security/nss/gtests/der_gtest/p12_import_unittest.cc delete mode 100644 security/nss/lib/freebl/chacha20.c delete mode 100644 security/nss/lib/freebl/chacha20.h delete mode 100644 security/nss/lib/freebl/chacha20_vec.c delete mode 100644 security/nss/lib/freebl/ecl/uint128.c delete mode 100644 security/nss/lib/freebl/ecl/uint128.h create mode 100644 security/nss/lib/freebl/verified/Hacl_Chacha20_Vec128.c create mode 100644 security/nss/lib/freebl/verified/Hacl_Chacha20_Vec128.h create mode 100644 security/nss/lib/freebl/verified/vec128.h delete mode 100644 security/nss/lib/ssl/ssl3encode.c delete mode 100644 security/nss/lib/ssl/ssl3encode.h create mode 100644 security/nss/nss-tool/hw-support.c (limited to 'security') diff --git a/security/nss/TAG-INFO b/security/nss/TAG-INFO new file mode 100644 index 000000000..1d96321b3 --- /dev/null +++ b/security/nss/TAG-INFO @@ -0,0 +1 @@ +NSS_3_36_4_RTM diff --git a/security/nss/automation/abi-check/expected-report-libnspr4.so.txt b/security/nss/automation/abi-check/expected-report-libnspr4.so.txt index 44f52325f..e69de29bb 100644 --- a/security/nss/automation/abi-check/expected-report-libnspr4.so.txt +++ b/security/nss/automation/abi-check/expected-report-libnspr4.so.txt @@ -1,8 +0,0 @@ -Functions changes summary: 1 Removed, 0 Changed, 0 Added function -Variables changes summary: 0 Removed, 0 Changed, 0 Added variable - -1 Removed function: - - 'function void PR_EXPERIMENTAL_ONLY_IN_4_17_GetOverlappedIOHandle(void**)' {PR_EXPERIMENTAL_ONLY_IN_4_17_GetOverlappedIOHandle} - - diff --git a/security/nss/automation/abi-check/expected-report-libssl3.so.txt b/security/nss/automation/abi-check/expected-report-libssl3.so.txt index 2a093094f..ad818d0aa 100644 --- a/security/nss/automation/abi-check/expected-report-libssl3.so.txt +++ b/security/nss/automation/abi-check/expected-report-libssl3.so.txt @@ -1,3 +1,28 @@ -Functions changes summary: 0 Removed, 0 Changed (5 filtered out), 0 Added function -Variables changes summary: 0 Removed, 0 Changed, 0 Added variable + +1 function with some indirect sub-type change: + + [C]'function SECStatus SSL_GetChannelInfo(PRFileDesc*, SSLChannelInfo*, PRUintn)' at sslinfo.c:12:1 has some indirect sub-type changes: + parameter 2 of type 'SSLChannelInfo*' has sub-type changes: + in pointed to type 'typedef SSLChannelInfo' at sslt.h:318:1: + underlying type 'struct SSLChannelInfoStr' at sslt.h:251:1 changed: + type size hasn't changed + 1 data member change: + type of 'SSLSignatureScheme SSLChannelInfoStr::signatureScheme' changed: + underlying type 'enum __anonymous_enum__' at sslt.h:115:1 changed: + type size hasn't changed + 3 enumerator deletions: + '__anonymous_enum__::ssl_sig_rsa_pss_sha256' value '2052' + '__anonymous_enum__::ssl_sig_rsa_pss_sha384' value '2053' + '__anonymous_enum__::ssl_sig_rsa_pss_sha512' value '2054' + + 6 enumerator insertions: + '__anonymous_enum__::ssl_sig_rsa_pss_rsae_sha256' value '2052' + '__anonymous_enum__::ssl_sig_rsa_pss_rsae_sha384' value '2053' + '__anonymous_enum__::ssl_sig_rsa_pss_rsae_sha512' value '2054' + '__anonymous_enum__::ssl_sig_rsa_pss_pss_sha256' value '2057' + '__anonymous_enum__::ssl_sig_rsa_pss_pss_sha384' value '2058' + '__anonymous_enum__::ssl_sig_rsa_pss_pss_sha512' value '2059' + + + diff --git a/security/nss/automation/abi-check/previous-nss-release b/security/nss/automation/abi-check/previous-nss-release index a91a569f5..c213ca3f8 100644 --- a/security/nss/automation/abi-check/previous-nss-release +++ b/security/nss/automation/abi-check/previous-nss-release @@ -1 +1 @@ -NSS_3_34_BRANCH +NSS_3_35_BRANCH diff --git a/security/nss/automation/buildbot-slave/build.sh b/security/nss/automation/buildbot-slave/build.sh index 844254dae..00e749672 100755 --- a/security/nss/automation/buildbot-slave/build.sh +++ b/security/nss/automation/buildbot-slave/build.sh @@ -212,7 +212,7 @@ test_nss() RET=$? print_log "######## details of detected failures (if any) ########" - grep -B50 FAILED ${OUTPUTFILE} + grep -B50 -w FAILED ${OUTPUTFILE} [ $? -eq 1 ] || RET=1 print_result "NSS - tests - ${BITS} bits - ${OPT}" ${RET} 0 @@ -268,10 +268,49 @@ check_abi() fi abidiff --hd1 $PREVDIST/public/ --hd2 $NEWDIST/public \ $PREVDIST/*/lib/$SO $NEWDIST/*/lib/$SO \ + > ${HGDIR}/nss/automation/abi-check/new-report-temp$SO.txt + RET=$? + cat ${HGDIR}/nss/automation/abi-check/new-report-temp$SO.txt \ + | grep -v "^Functions changes summary:" \ + | grep -v "^Variables changes summary:" \ > ${HGDIR}/nss/automation/abi-check/new-report-$SO.txt - if [ $? -ne 0 ]; then + rm -f ${HGDIR}/nss/automation/abi-check/new-report-temp$SO.txt + ABIDIFF_ERROR=$((($RET & 0x01) != 0)) + ABIDIFF_USAGE_ERROR=$((($RET & 0x02) != 0)) + ABIDIFF_ABI_CHANGE=$((($RET & 0x04) != 0)) + ABIDIFF_ABI_INCOMPATIBLE_CHANGE=$((($RET & 0x08) != 0)) + ABIDIFF_UNKNOWN_BIT_SET=$((($RET & 0xf0) != 0)) + + # If abidiff reports an error, or a usage error, or if it sets a result + # bit value this script doesn't know yet about, we'll report failure. + # For ABI changes, we don't yet report an error. We'll compare the + # result report with our whitelist. This allows us to silence changes + # that we're already aware of and have been declared acceptable. + + REPORT_RET_AS_FAILURE=0 + if [ $ABIDIFF_ERROR -ne 0 ]; then + print_log "abidiff reported ABIDIFF_ERROR." + REPORT_RET_AS_FAILURE=1 + fi + if [ $ABIDIFF_USAGE_ERROR -ne 0 ]; then + print_log "abidiff reported ABIDIFF_USAGE_ERROR." + REPORT_RET_AS_FAILURE=1 + fi + if [ $ABIDIFF_UNKNOWN_BIT_SET -ne 0 ]; then + print_log "abidiff reported ABIDIFF_UNKNOWN_BIT_SET." + REPORT_RET_AS_FAILURE=1 + fi + + if [ $ABIDIFF_ABI_CHANGE -ne 0 ]; then + print_log "Ignoring abidiff result ABI_CHANGE, instead we'll check for non-whitelisted differences." + fi + if [ $ABIDIFF_ABI_INCOMPATIBLE_CHANGE -ne 0 ]; then + print_log "Ignoring abidiff result ABIDIFF_ABI_INCOMPATIBLE_CHANGE, instead we'll check for non-whitelisted differences." + fi + + if [ $REPORT_RET_AS_FAILURE -ne 0 ]; then ABI_PROBLEM_FOUND=1 - print_log "FAILED to run abidiff {$PREVDIST , $NEWDIST} for $SO, or failed writing to ${HGDIR}/nss/automation/abi-check/new-report-$SO.txt" + print_log "abidiff {$PREVDIST , $NEWDIST} for $SO FAILED with result $RET, or failed writing to ${HGDIR}/nss/automation/abi-check/new-report-$SO.txt" fi if [ ! -f ${HGDIR}/nss/automation/abi-check/expected-report-$SO.txt ]; then ABI_PROBLEM_FOUND=1 diff --git a/security/nss/automation/release/nspr-version.txt b/security/nss/automation/release/nspr-version.txt index 01eeb3615..701680d2c 100644 --- a/security/nss/automation/release/nspr-version.txt +++ b/security/nss/automation/release/nspr-version.txt @@ -1,4 +1,4 @@ -4.18 +4.19 # The first line of this file must contain the human readable NSPR # version number, which is the minimum required version of NSPR diff --git a/security/nss/automation/saw/bmul.cry b/security/nss/automation/saw/bmul.cry new file mode 100644 index 000000000..87303dad6 --- /dev/null +++ b/security/nss/automation/saw/bmul.cry @@ -0,0 +1,8 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +bmul : {n,m} (fin n, n >= 1, m == n*2 - 1) => [n] -> [n] -> ([n], [n]) +bmul a b = (take`{n} prod, drop`{n} prod) + where prod = pad (pmult a b : [m]) + pad x = zero # x diff --git a/security/nss/automation/saw/bmul.saw b/security/nss/automation/saw/bmul.saw new file mode 100644 index 000000000..22cd2757b --- /dev/null +++ b/security/nss/automation/saw/bmul.saw @@ -0,0 +1,26 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +import "bmul.cry"; + +print "Loading LLVM bitcode..."; +m <- llvm_load_module "../../../dist/Debug/lib/libfreeblpriv3.so.bc"; + +let SpecBinaryMul n = do { + x <- llvm_var "x" (llvm_int n); + y <- llvm_var "y" (llvm_int n); + llvm_ptr "r_high" (llvm_int n); + r_high <- llvm_var "*r_high" (llvm_int n); + llvm_ptr "r_low" (llvm_int n); + r_low <- llvm_var "*r_low" (llvm_int n); + + let res = {{ bmul x y }}; + llvm_ensure_eq "*r_high" {{ res.0 }}; + llvm_ensure_eq "*r_low" {{ res.1 }}; + + llvm_verify_tactic abc; +}; + +print "Proving equality for 32-bit bmul()..."; +time (llvm_verify m "bmul32" [] (SpecBinaryMul 32)); diff --git a/security/nss/automation/saw/chacha20.cry b/security/nss/automation/saw/chacha20.cry new file mode 100644 index 000000000..0b52d51ad --- /dev/null +++ b/security/nss/automation/saw/chacha20.cry @@ -0,0 +1,357 @@ +/* +** ChaCha20 specification +** Author: Austin Seipp . Released in the Public Domain. +** +** Based on RFC 7539 - "ChaCha20 and Poly1305 for IETF Protocols" +** https://tools.ietf.org/html/rfc7539 +*/ +module chacha20 where + +/* -------------------------------------------------------------------------- */ +/* -- Implementation -------------------------------------------------------- */ + +type Round = [16][32] // An input to the ChaCha20 core function +type Block = [64][8] // An output block from the ChaCha20 core function. +type Key = [32][8] // A 32-byte input key +type Nonce = [12][8] // A 12-byte nonce +type Counter = [32] // Starting block counter. Usually 1 or 0. + +/* ---------------------------------- */ +/* -- Quarter Round ----------------- */ + +// The quarter round. This takes 4 32-bit integers and diffuses them +// appropriately, and is the core of the column and diagonal round. +qround : [4][32] -> [4][32] +qround [ a0, b0, c0, d0 ] = [ a2, b4, c2, d4 ] + where + a1 = a0 + b0 /* a += b; d ^= a; d <<<= 16 */ + d1 = d0 ^ a1 + d2 = d1 <<< 16 + + c1 = c0 + d2 /* c += d; b ^= c; b <<<= 12 */ + b1 = b0 ^ c1 + b2 = b1 <<< 12 + + a2 = a1 + b2 /* a += b; d ^= a; d <<<= 8 */ + d3 = d2 ^ a2 + d4 = d3 <<< 8 + + c2 = c1 + d4 /* c += d; b ^= c; b <<<= 7 */ + b3 = b2 ^ c2 + b4 = b3 <<< 7 + + +/* ---------------------------------- */ +/* -- Column and diagonal rounds ---- */ + +// Perform the column round, followed by the diagonal round on the +// input state, which are both defined in terms of the quarter +// round. ChaCha20 requires 20 total rounds of interleaving +// column/diagonal passes on the state, and therefore `cdround` actually +// does two passes at once (mostly for simplicity). +cdround : Round -> Round +cdround [ x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15 ] + = [ z0, z1, z2, z3, z4, z5, z6, z7, z8, z9, z10, z11, z12, z13, z14, z15 ] + where + // Column round + [ y0, y4, y8, y12 ] = qround [ x0, x4, x8, x12 ] + [ y1, y5, y9, y13 ] = qround [ x1, x5, x9, x13 ] + [ y2, y6, y10, y14 ] = qround [ x2, x6, x10, x14 ] + [ y3, y7, y11, y15 ] = qround [ x3, x7, x11, x15 ] + + // Diagonal round + [ z0, z5, z10, z15 ] = qround [ y0, y5, y10, y15 ] + [ z1, z6, z11, z12 ] = qround [ y1, y6, y11, y12 ] + [ z2, z7, z8, z13 ] = qround [ y2, y7, y8, y13 ] + [ z3, z4, z9, z14 ] = qround [ y3, y4, y9, y14 ] + + +/* ---------------------------------- */ +/* -- Block encryption -------------- */ + +// Given an input round, calculate the core ChaCha20 algorithm over +// the round and return an output block. These output blocks form the +// stream which you XOR your plaintext with, and successive iterations of +// the core algorithm result in an infinite stream you can use as a +// cipher. +core : Round -> Block +core x = block + where + rounds = iterate cdround x // Do a bunch of column/diagonal passes... + result = rounds @ 10 // And grab the 10th result (20 total passes) + block = blocked (x + result) // Add to input, convert to output block + + +/* ---------------------------------- */ +/* -- Key Expansion ----------------- */ + +// Key expansion. Given a nonce and a key, compute a round (which is +// fed to the core algorithm above) by taking the initial round state and +// mixing in the key and nonce appropriately. +kexp : Key -> Counter -> Nonce -> Round +kexp k c n = [ c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15 ] + where + // The following describes the layout of the output round, which + // is fed into the core algorithm successively. + + // Bytes 0-3: Constants + [ c0, c1, c2, c3 ] = [ 0x61707865, 0x3320646e, 0x79622d32, 0x6b206574 ] + + // Bytes 4-11: Key + [ c4, c5, c6, c7 ] = map rjoin (groupBy`{4} kslice1 : [4][4][8]) : [4][32] + [ c8, c9, c10, c11 ] = map rjoin (groupBy`{4} kslice2 : [4][4][8]) : [4][32] + kslice1 = k @@ ([ 0 .. 15 ] : [16][32]) // Top half + kslice2 = k @@ ([ 16 .. 31 ] : [16][32]) // Bottom half + + // Bytes 12: Counter, starts off with whatever the user specified + // (usually 0 or 1) + [ c12 ] = [ c ] + + // Bytes 14-15: Nonce + [ c13, c14, c15 ] = map rjoin (groupBy`{4} n) + + +/* ---------------------------------- */ +/* -- Round increments -------------- */ + +// Take a given number of iterations and the input round (after key +// expansion!), and calculate the input round for the core algorithm +// function. This allows you to index into a particular Round which +// can be passed to the 'core' function. +iround : [64] -> Round -> Round +iround n r = (iterate once r) @ n where + // Given a round, increment the counter inside (index no 12) + once [ x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15 ] + = [ x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12+1, x13, x14, x15 ] + +/* ---------------------------------- */ +/* -- ChaCha20 encryption ----------- */ + +// Produce a psuedo-random stream given a nonce and a key, which can +// be XOR'd with your data to encrypt it. +stream : {n} (fin n) => Key -> Counter -> Nonce -> [n][8] +stream k c n = take`{n} (join rounds) // Take n bytes from the final result + where + // Expand key + key = kexp k c n + + // Produce the stream by successively incrementing the input round + // by `i`, and running the core algorithm to get the resulting + // stream for the `i`th input. Once these are concatenated, you have + // an infinite list representing the ChaCha20 stream. + rounds = [ core (iround i key) | i <- [ 0, 1 ... ] ] + + +// Given an message, a nonce, and a key, produce an encrypted +// message. This is simply defined as the XOR of the message and the +// corresponding encryption stream. +encrypt : {n} (fin n) => Key -> Counter -> Nonce -> [n][8] -> [n][8] +encrypt k c n m = m ^ (stream k c n) + +/* -------------------------------------------------------------------------- */ +/* -- Theorems, tests ------------------------------------------------------- */ + +// Tests are private +private + qround01 = qround in == out + where + in = [ 0x11111111, 0x01020304, 0x9b8d6f43, 0x01234567 ] + out = [ 0xea2a92f4, 0xcb1cf8ce, 0x4581472e, 0x5881c4bb ] + + core01 = kexp k 1 n == out + where + n = [ 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x4a, + 0x00, 0x00, 0x00, 0x00 ] + k = [ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f ] + out = [ 0x61707865, 0x3320646e, 0x79622d32, 0x6b206574, + 0x03020100, 0x07060504, 0x0b0a0908, 0x0f0e0d0c, + 0x13121110, 0x17161514, 0x1b1a1918, 0x1f1e1d1c, + 0x00000001, 0x09000000, 0x4a000000, 0x00000000 ] + + core02 = core (kexp k 1 n) == out + where + n = [ 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x4a, + 0x00, 0x00, 0x00, 0x00 ] + k = [ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f ] + out = [ 0x10, 0xf1, 0xe7, 0xe4, 0xd1, 0x3b, 0x59, 0x15, + 0x50, 0x0f, 0xdd, 0x1f, 0xa3, 0x20, 0x71, 0xc4, + 0xc7, 0xd1, 0xf4, 0xc7, 0x33, 0xc0, 0x68, 0x03, + 0x04, 0x22, 0xaa, 0x9a, 0xc3, 0xd4, 0x6c, 0x4e, + 0xd2, 0x82, 0x64, 0x46, 0x07, 0x9f, 0xaa, 0x09, + 0x14, 0xc2, 0xd7, 0x05, 0xd9, 0x8b, 0x02, 0xa2, + 0xb5, 0x12, 0x9c, 0xd1, 0xde, 0x16, 0x4e, 0xb9, + 0xcb, 0xd0, 0x83, 0xe8, 0xa2, 0x50, 0x3c, 0x4e ] + + rfctest01 = encrypt zero zero zero zero + == [ 0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90, 0x40, 0x5d, + 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28, 0xbd, 0xd2, 0x19, 0xb8, + 0xa0, 0x8d, 0xed, 0x1a, 0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, + 0x0d, 0xc7, 0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d, + 0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37, 0x6a, 0x43, + 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c, 0xc3, 0x87, 0xb6, 0x69, + 0xb2, 0xee, 0x65, 0x86 ] + + rfctest02 = encrypt (zero # [1]) 1 (zero # [2]) msg == out + where + out = [ 0xa3, 0xfb, 0xf0, 0x7d, 0xf3, 0xfa, 0x2f, 0xde, 0x4f, 0x37, + 0x6c, 0xa2, 0x3e, 0x82, 0x73, 0x70, 0x41, 0x60, 0x5d, 0x9f, + 0x4f, 0x4f, 0x57, 0xbd, 0x8c, 0xff, 0x2c, 0x1d, 0x4b, 0x79, + 0x55, 0xec, 0x2a, 0x97, 0x94, 0x8b, 0xd3, 0x72, 0x29, 0x15, + 0xc8, 0xf3, 0xd3, 0x37, 0xf7, 0xd3, 0x70, 0x05, 0x0e, 0x9e, + 0x96, 0xd6, 0x47, 0xb7, 0xc3, 0x9f, 0x56, 0xe0, 0x31, 0xca, + 0x5e, 0xb6, 0x25, 0x0d, 0x40, 0x42, 0xe0, 0x27, 0x85, 0xec, + 0xec, 0xfa, 0x4b, 0x4b, 0xb5, 0xe8, 0xea, 0xd0, 0x44, 0x0e, + 0x20, 0xb6, 0xe8, 0xdb, 0x09, 0xd8, 0x81, 0xa7, 0xc6, 0x13, + 0x2f, 0x42, 0x0e, 0x52, 0x79, 0x50, 0x42, 0xbd, 0xfa, 0x77, + 0x73, 0xd8, 0xa9, 0x05, 0x14, 0x47, 0xb3, 0x29, 0x1c, 0xe1, + 0x41, 0x1c, 0x68, 0x04, 0x65, 0x55, 0x2a, 0xa6, 0xc4, 0x05, + 0xb7, 0x76, 0x4d, 0x5e, 0x87, 0xbe, 0xa8, 0x5a, 0xd0, 0x0f, + 0x84, 0x49, 0xed, 0x8f, 0x72, 0xd0, 0xd6, 0x62, 0xab, 0x05, + 0x26, 0x91, 0xca, 0x66, 0x42, 0x4b, 0xc8, 0x6d, 0x2d, 0xf8, + 0x0e, 0xa4, 0x1f, 0x43, 0xab, 0xf9, 0x37, 0xd3, 0x25, 0x9d, + 0xc4, 0xb2, 0xd0, 0xdf, 0xb4, 0x8a, 0x6c, 0x91, 0x39, 0xdd, + 0xd7, 0xf7, 0x69, 0x66, 0xe9, 0x28, 0xe6, 0x35, 0x55, 0x3b, + 0xa7, 0x6c, 0x5c, 0x87, 0x9d, 0x7b, 0x35, 0xd4, 0x9e, 0xb2, + 0xe6, 0x2b, 0x08, 0x71, 0xcd, 0xac, 0x63, 0x89, 0x39, 0xe2, + 0x5e, 0x8a, 0x1e, 0x0e, 0xf9, 0xd5, 0x28, 0x0f, 0xa8, 0xca, + 0x32, 0x8b, 0x35, 0x1c, 0x3c, 0x76, 0x59, 0x89, 0xcb, 0xcf, + 0x3d, 0xaa, 0x8b, 0x6c, 0xcc, 0x3a, 0xaf, 0x9f, 0x39, 0x79, + 0xc9, 0x2b, 0x37, 0x20, 0xfc, 0x88, 0xdc, 0x95, 0xed, 0x84, + 0xa1, 0xbe, 0x05, 0x9c, 0x64, 0x99, 0xb9, 0xfd, 0xa2, 0x36, + 0xe7, 0xe8, 0x18, 0xb0, 0x4b, 0x0b, 0xc3, 0x9c, 0x1e, 0x87, + 0x6b, 0x19, 0x3b, 0xfe, 0x55, 0x69, 0x75, 0x3f, 0x88, 0x12, + 0x8c, 0xc0, 0x8a, 0xaa, 0x9b, 0x63, 0xd1, 0xa1, 0x6f, 0x80, + 0xef, 0x25, 0x54, 0xd7, 0x18, 0x9c, 0x41, 0x1f, 0x58, 0x69, + 0xca, 0x52, 0xc5, 0xb8, 0x3f, 0xa3, 0x6f, 0xf2, 0x16, 0xb9, + 0xc1, 0xd3, 0x00, 0x62, 0xbe, 0xbc, 0xfd, 0x2d, 0xc5, 0xbc, + 0xe0, 0x91, 0x19, 0x34, 0xfd, 0xa7, 0x9a, 0x86, 0xf6, 0xe6, + 0x98, 0xce, 0xd7, 0x59, 0xc3, 0xff, 0x9b, 0x64, 0x77, 0x33, + 0x8f, 0x3d, 0xa4, 0xf9, 0xcd, 0x85, 0x14, 0xea, 0x99, 0x82, + 0xcc, 0xaf, 0xb3, 0x41, 0xb2, 0x38, 0x4d, 0xd9, 0x02, 0xf3, + 0xd1, 0xab, 0x7a, 0xc6, 0x1d, 0xd2, 0x9c, 0x6f, 0x21, 0xba, + 0x5b, 0x86, 0x2f, 0x37, 0x30, 0xe3, 0x7c, 0xfd, 0xc4, 0xfd, + 0x80, 0x6c, 0x22, 0xf2, 0x21 ] + + msg = [ 0x41, 0x6e, 0x79, 0x20, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x49, 0x45, 0x54, 0x46, 0x20, 0x69, 0x6e, 0x74, + 0x65, 0x6e, 0x64, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, + 0x75, 0x74, 0x6f, 0x72, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x70, + 0x75, 0x62, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x20, 0x61, 0x73, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x6f, 0x72, + 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x61, + 0x6e, 0x20, 0x49, 0x45, 0x54, 0x46, 0x20, 0x49, 0x6e, 0x74, + 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2d, 0x44, 0x72, 0x61, 0x66, + 0x74, 0x20, 0x6f, 0x72, 0x20, 0x52, 0x46, 0x43, 0x20, 0x61, + 0x6e, 0x64, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x73, 0x74, 0x61, + 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x6d, 0x61, 0x64, + 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x69, 0x6e, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, + 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x20, 0x49, 0x45, 0x54, + 0x46, 0x20, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, + 0x20, 0x69, 0x73, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x64, + 0x65, 0x72, 0x65, 0x64, 0x20, 0x61, 0x6e, 0x20, 0x22, 0x49, + 0x45, 0x54, 0x46, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x69, + 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x2e, 0x20, 0x53, + 0x75, 0x63, 0x68, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, + 0x65, 0x6e, 0x74, 0x73, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75, + 0x64, 0x65, 0x20, 0x6f, 0x72, 0x61, 0x6c, 0x20, 0x73, 0x74, + 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x69, + 0x6e, 0x20, 0x49, 0x45, 0x54, 0x46, 0x20, 0x73, 0x65, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x73, 0x20, + 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x61, 0x73, 0x20, 0x77, 0x72, + 0x69, 0x74, 0x74, 0x65, 0x6e, 0x20, 0x61, 0x6e, 0x64, 0x20, + 0x65, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x6f, 0x6e, 0x69, 0x63, + 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6d, 0x61, 0x64, 0x65, + 0x20, 0x61, 0x74, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x74, 0x69, + 0x6d, 0x65, 0x20, 0x6f, 0x72, 0x20, 0x70, 0x6c, 0x61, 0x63, + 0x65, 0x2c, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x61, + 0x72, 0x65, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, + 0x65, 0x64, 0x20, 0x74, 0x6f ] + + rfctest03 = encrypt key 42 (zero # [2]) msg == out + where + key = [ 0x1c, 0x92, 0x40, 0xa5, 0xeb, 0x55, 0xd3, 0x8a, 0xf3, 0x33, + 0x88, 0x86, 0x04, 0xf6, 0xb5, 0xf0, 0x47, 0x39, 0x17, 0xc1, + 0x40, 0x2b, 0x80, 0x09, 0x9d, 0xca, 0x5c, 0xbc, 0x20, 0x70, + 0x75, 0xc0 ] + out = [ 0x27, 0x54, 0x77, 0x61, 0x73, 0x20, 0x62, 0x72, 0x69, 0x6c, + 0x6c, 0x69, 0x67, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x73, 0x6c, 0x69, 0x74, 0x68, 0x79, 0x20, + 0x74, 0x6f, 0x76, 0x65, 0x73, 0x0a, 0x44, 0x69, 0x64, 0x20, + 0x67, 0x79, 0x72, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x67, + 0x69, 0x6d, 0x62, 0x6c, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x77, 0x61, 0x62, 0x65, 0x3a, 0x0a, 0x41, + 0x6c, 0x6c, 0x20, 0x6d, 0x69, 0x6d, 0x73, 0x79, 0x20, 0x77, + 0x65, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x6f, + 0x72, 0x6f, 0x67, 0x6f, 0x76, 0x65, 0x73, 0x2c, 0x0a, 0x41, + 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x6d, + 0x65, 0x20, 0x72, 0x61, 0x74, 0x68, 0x73, 0x20, 0x6f, 0x75, + 0x74, 0x67, 0x72, 0x61, 0x62, 0x65, 0x2e ] + + msg = [ 0x62, 0xe6, 0x34, 0x7f, 0x95, 0xed, 0x87, 0xa4, 0x5f, 0xfa, + 0xe7, 0x42, 0x6f, 0x27, 0xa1, 0xdf, 0x5f, 0xb6, 0x91, 0x10, + 0x04, 0x4c, 0x0d, 0x73, 0x11, 0x8e, 0xff, 0xa9, 0x5b, 0x01, + 0xe5, 0xcf, 0x16, 0x6d, 0x3d, 0xf2, 0xd7, 0x21, 0xca, 0xf9, + 0xb2, 0x1e, 0x5f, 0xb1, 0x4c, 0x61, 0x68, 0x71, 0xfd, 0x84, + 0xc5, 0x4f, 0x9d, 0x65, 0xb2, 0x83, 0x19, 0x6c, 0x7f, 0xe4, + 0xf6, 0x05, 0x53, 0xeb, 0xf3, 0x9c, 0x64, 0x02, 0xc4, 0x22, + 0x34, 0xe3, 0x2a, 0x35, 0x6b, 0x3e, 0x76, 0x43, 0x12, 0xa6, + 0x1a, 0x55, 0x32, 0x05, 0x57, 0x16, 0xea, 0xd6, 0x96, 0x25, + 0x68, 0xf8, 0x7d, 0x3f, 0x3f, 0x77, 0x04, 0xc6, 0xa8, 0xd1, + 0xbc, 0xd1, 0xbf, 0x4d, 0x50, 0xd6, 0x15, 0x4b, 0x6d, 0xa7, + 0x31, 0xb1, 0x87, 0xb5, 0x8d, 0xfd, 0x72, 0x8a, 0xfa, 0x36, + 0x75, 0x7a, 0x79, 0x7a, 0xc1, 0x88, 0xd1 ] + +property allTestsPass = + ([ // Basic tests + qround01, core01, core02 + // Full RFC test vectors + , rfctest01, rfctest02, rfctest03 + ] : [_]Bit) == ~zero // All test bits should equal one + +/* -------------------------------------------------------------------------- */ +/* -- Private utilities ----------------------------------------------------- */ + +private + // Convert a round into a block, by splitting every 32-bit round entry + // into 4 bytes, and then serialize those values into a full block. + blocked : Round -> Block + blocked x = join (map toBytes x) + where + // This essentially splits a 32-bit number into 4-byte + // little-endian form, where 'rjoin' is the inverse and would merge + // 4 bytes as a 32-bit little endian number. + toBytes : [32] -> [4][8] + toBytes v = reverse (groupBy`{8} v) + + // Map a function over a finite list. + map : { a, b, c } + (a -> b) -> [c]a -> [c]b + map f xs = [ f x | x <- xs ] + + // Map a function iteratively over a seed value, producing an infinite + // list of successive function applications: + // + // iterate f 0 == [ 0, f 0, f (f 0), f (f (f 0)), ... ] + iterate : { a } (a -> a) -> a -> [inf]a + iterate f x = [x] # [ f v | v <- iterate f x ] + where + // NB: Needs a binded name in order to tie the recursive knot. + xs = [x] # [ f v | v <- xs ] + + // rjoin = join . reverse + // This encodes a sequence of values as a little endian number + // e.g. [ 0xaa, 0xbb, 0xcc, 0xdd ] is serialized as \xdd\xcc\xbb\xaa + rjoin : {a, b, c} + ( fin a, fin c + ) => [c][a]b -> [a * c]b + rjoin x = join (reverse x) diff --git a/security/nss/automation/saw/chacha20.saw b/security/nss/automation/saw/chacha20.saw new file mode 100644 index 000000000..92145ab74 --- /dev/null +++ b/security/nss/automation/saw/chacha20.saw @@ -0,0 +1,40 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +import "chacha20.cry" as chacha20; + +print "Proving ChaCha20 spec..."; +prove_print abc {{ chacha20::allTestsPass }}; + +print "Loading LLVM bitcode..."; +m <- llvm_load_module "../../../dist/Debug/lib/libfreeblpriv3.so.bc"; + +let SpecChaCha20 n = do { + llvm_ptr "output" (llvm_array n (llvm_int 8)); + output <- llvm_var "*output" (llvm_array n (llvm_int 8)); + + llvm_ptr "plain" (llvm_array n (llvm_int 8)); + plain <- llvm_var "*plain" (llvm_array n (llvm_int 8)); + + len <- llvm_var "len" (llvm_int 32); + llvm_assert_eq "len" {{ `n : [32] }}; + + llvm_ptr "k" (llvm_array 32 (llvm_int 8)); + k <- llvm_var "*k" (llvm_array 32 (llvm_int 8)); + + llvm_ptr "n1" (llvm_array 12 (llvm_int 8)); + n1 <- llvm_var "*n1" (llvm_array 12 (llvm_int 8)); + + ctr <- llvm_var "ctr" (llvm_int 32); + + llvm_ensure_eq "*output" {{ chacha20::encrypt k ctr n1 plain }}; + + llvm_verify_tactic abc; +}; + +print "Proving equality for a single block..."; +time (llvm_verify m "Hacl_Chacha20_chacha20" [] (SpecChaCha20 64)); + +print "Proving equality for multiple blocks..."; +time (llvm_verify m "Hacl_Chacha20_chacha20" [] (SpecChaCha20 256)); diff --git a/security/nss/automation/saw/poly1305-hacl.saw b/security/nss/automation/saw/poly1305-hacl.saw new file mode 100644 index 000000000..a4dfff6d9 --- /dev/null +++ b/security/nss/automation/saw/poly1305-hacl.saw @@ -0,0 +1,38 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +import "poly1305.cry" as poly1305; + +print "Proving Poly1305 spec..."; +prove_print abc {{ poly1305::allTestsPass }}; + +print "Loading LLVM bitcode..."; +m <- llvm_load_module "../../../dist/Debug/lib/libfreeblpriv3.so.bc"; + +let SpecPoly1305 n = do { + llvm_ptr "output" (llvm_array 16 (llvm_int 8)); + output <- llvm_var "*output" (llvm_array 16 (llvm_int 8)); + + llvm_ptr "input" (llvm_array n (llvm_int 8)); + input <- llvm_var "*input" (llvm_array n (llvm_int 8)); + + llvm_var "len1" (llvm_int 64); + llvm_ptr "k1" (llvm_array 32 (llvm_int 8)); + k1 <- llvm_var "*k1" (llvm_array 32 (llvm_int 8)); + + llvm_assert_eq "*input" {{ zero : [n][8] }}; + llvm_assert_eq "len1" {{ `n : [64] }}; + + llvm_assert_eq "*k1" {{ zero : [32][8] }}; + + let res = {{ poly1305::Poly1305 input (take`{16} k1) (drop`{16} k1) }}; + llvm_ensure_eq "*output" {{ res }}; + + llvm_verify_tactic abc; +}; + +print "Proving equality for a single block..."; +// This is currently disabled as it takes way too long. We need to help Z3 +// prove this before we can enable it on Taskcluster. +//time (llvm_verify m "Hacl_Poly1305_64_crypto_onetimeauth" [] (SpecPoly1305 16)); diff --git a/security/nss/automation/saw/poly1305.cry b/security/nss/automation/saw/poly1305.cry new file mode 100644 index 000000000..6321a4f19 --- /dev/null +++ b/security/nss/automation/saw/poly1305.cry @@ -0,0 +1,336 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* This file provides a spec of the Poly1305 one-time authenticator. + * See for details. */ + +module poly1305 where + +P : [136] +P = 2^^130 - 5 + +Poly1305 : {n} (fin n) => [n][8] -> [16][8] -> [16][8] -> [16][8] +Poly1305 msg r s = reverse (groupBy (drop ((rounds ! 0) + s'))) + where + rounds = [zero] # [ Poly1305_block acc r' b | b <- blocks | acc <- rounds ] + r' = zero # (Poly1305_clamp (join (reverse r))) + s' = zero # (join (reverse s)) + blocks = Poly1305_split msg + +private + // 0x0f - for r[3], r[7], r[11], r[15] + // 0xfc - for r[4], r[8], r[12] + Poly1305_clamp r = r && 0x0ffffffc0ffffffc0ffffffc0fffffff + + // Poly1305_block : ((acc + msg) * r) % P + Poly1305_block : [136] -> [136] -> [136] -> [136] + Poly1305_block acc r msg = drop (prod % (zero # P)) + where + acc' : [137] + // Add the current block to the accumulator. + acc' = (zero # acc) + (zero # msg) + prod : [273] + // Multiply the new accumulator value by r. + prod = ((zero : [137]) # r) * ((zero : [136]) # acc') + + Poly1305_split : {n, nb, nf} (fin n, nf == n / 16, nb == (n + 15) / 16) => [n][8] -> [nb][136] + Poly1305_split msg = take ((h1 : [nf][136]) # h2) + where + // Split all full 16-byte blocks and append 0x01, then convert to LE. + h1 = [ join (reverse (b # [0x01])) | b <- groupBy`{16} (take msg)] + // Pad the remaining bytes (if any) and convert to LE. + h2 = [join (reverse ((drop`{nf * 16} msg) # [0x01] # zero))] + +/* -------------------------------------------------------------------------- */ +/* -- Tests ----------------------------------------------------------------- */ + +private + // https://tools.ietf.org/html/rfc7539#section-2.5.2 + rval1 = [0x85, 0xd6, 0xbe, 0x78, 0x57, 0x55, 0x6d, 0x33, + 0x7f, 0x44, 0x52, 0xfe, 0x42, 0xd5, 0x06, 0xa8] + sval1 = [0x01, 0x03, 0x80, 0x8a, 0xfb, 0x0d, 0xb2, 0xfd, + 0x4a, 0xbf, 0xf6, 0xaf, 0x41, 0x49, 0xf5, 0x1b] + text1 = [0x43, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x67, 0x72, + 0x61, 0x70, 0x68, 0x69, 0x63, 0x20, 0x46, 0x6f, + 0x72, 0x75, 0x6d, 0x20, 0x52, 0x65, 0x73, 0x65, + 0x61, 0x72, 0x63, 0x68, 0x20, 0x47, 0x72, 0x6f, + 0x75, 0x70] + + rfctest01 = Poly1305 text1 rval1 sval1 + == [0xa8, 0x06, 0x1d, 0xc1, 0x30, 0x51, 0x36, 0xc6, + 0xc2, 0x2b, 0x8b, 0xaf, 0x0c, 0x01, 0x27, 0xa9] + + // https://tools.ietf.org/html/rfc7539#appendix-A.3 + // Test Vector #1 + rval2 = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + sval2 = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + text2 = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + + rfctest02 = Poly1305 text2 rval2 sval2 + == [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + + // https://tools.ietf.org/html/rfc7539#appendix-A.3 + // Test Vector #2 + rval3 = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + sval3 = [0x36, 0xe5, 0xf6, 0xb5, 0xc5, 0xe0, 0x60, 0x70, + 0xf0, 0xef, 0xca, 0x96, 0x22, 0x7a, 0x86, 0x3e] + text3 = [0x41, 0x6e, 0x79, 0x20, 0x73, 0x75, 0x62, 0x6d, + 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x74, + 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x49, 0x45, + 0x54, 0x46, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x6e, + 0x64, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61, + 0x73, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x6f, 0x72, + 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66, + 0x20, 0x61, 0x6e, 0x20, 0x49, 0x45, 0x54, 0x46, + 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, + 0x74, 0x2d, 0x44, 0x72, 0x61, 0x66, 0x74, 0x20, + 0x6f, 0x72, 0x20, 0x52, 0x46, 0x43, 0x20, 0x61, + 0x6e, 0x64, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x73, + 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, + 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x77, 0x69, + 0x74, 0x68, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, + 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x20, 0x49, + 0x45, 0x54, 0x46, 0x20, 0x61, 0x63, 0x74, 0x69, + 0x76, 0x69, 0x74, 0x79, 0x20, 0x69, 0x73, 0x20, + 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x72, + 0x65, 0x64, 0x20, 0x61, 0x6e, 0x20, 0x22, 0x49, + 0x45, 0x54, 0x46, 0x20, 0x43, 0x6f, 0x6e, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, + 0x22, 0x2e, 0x20, 0x53, 0x75, 0x63, 0x68, 0x20, + 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, + 0x74, 0x73, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75, + 0x64, 0x65, 0x20, 0x6f, 0x72, 0x61, 0x6c, 0x20, + 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, + 0x74, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x49, 0x45, + 0x54, 0x46, 0x20, 0x73, 0x65, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x73, 0x20, + 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x61, 0x73, 0x20, + 0x77, 0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x20, + 0x61, 0x6e, 0x64, 0x20, 0x65, 0x6c, 0x65, 0x63, + 0x74, 0x72, 0x6f, 0x6e, 0x69, 0x63, 0x20, 0x63, + 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6d, 0x61, + 0x64, 0x65, 0x20, 0x61, 0x74, 0x20, 0x61, 0x6e, + 0x79, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x6f, + 0x72, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x2c, + 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x61, + 0x72, 0x65, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, + 0x73, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f] + + rfctest03 = Poly1305 text3 rval3 sval3 + == [0x36, 0xe5, 0xf6, 0xb5, 0xc5, 0xe0, 0x60, 0x70, + 0xf0, 0xef, 0xca, 0x96, 0x22, 0x7a, 0x86, 0x3e] + + // https://tools.ietf.org/html/rfc7539#appendix-A.3 + // Test Vector #3 + rval4 = [0x36, 0xe5, 0xf6, 0xb5, 0xc5, 0xe0, 0x60, 0x70, + 0xf0, 0xef, 0xca, 0x96, 0x22, 0x7a, 0x86, 0x3e] + sval4 = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + text4 = [0x41, 0x6e, 0x79, 0x20, 0x73, 0x75, 0x62, 0x6d, + 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x74, + 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x49, 0x45, + 0x54, 0x46, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x6e, + 0x64, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61, + 0x73, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x6f, 0x72, + 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66, + 0x20, 0x61, 0x6e, 0x20, 0x49, 0x45, 0x54, 0x46, + 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, + 0x74, 0x2d, 0x44, 0x72, 0x61, 0x66, 0x74, 0x20, + 0x6f, 0x72, 0x20, 0x52, 0x46, 0x43, 0x20, 0x61, + 0x6e, 0x64, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x73, + 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, + 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x77, 0x69, + 0x74, 0x68, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, + 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x20, 0x49, + 0x45, 0x54, 0x46, 0x20, 0x61, 0x63, 0x74, 0x69, + 0x76, 0x69, 0x74, 0x79, 0x20, 0x69, 0x73, 0x20, + 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x72, + 0x65, 0x64, 0x20, 0x61, 0x6e, 0x20, 0x22, 0x49, + 0x45, 0x54, 0x46, 0x20, 0x43, 0x6f, 0x6e, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, + 0x22, 0x2e, 0x20, 0x53, 0x75, 0x63, 0x68, 0x20, + 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, + 0x74, 0x73, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75, + 0x64, 0x65, 0x20, 0x6f, 0x72, 0x61, 0x6c, 0x20, + 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, + 0x74, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x49, 0x45, + 0x54, 0x46, 0x20, 0x73, 0x65, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x73, 0x20, + 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x61, 0x73, 0x20, + 0x77, 0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x20, + 0x61, 0x6e, 0x64, 0x20, 0x65, 0x6c, 0x65, 0x63, + 0x74, 0x72, 0x6f, 0x6e, 0x69, 0x63, 0x20, 0x63, + 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6d, 0x61, + 0x64, 0x65, 0x20, 0x61, 0x74, 0x20, 0x61, 0x6e, + 0x79, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x6f, + 0x72, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x2c, + 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x61, + 0x72, 0x65, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, + 0x73, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f] + + rfctest04 = Poly1305 text4 rval4 sval4 + == [0xf3, 0x47, 0x7e, 0x7c, 0xd9, 0x54, 0x17, 0xaf, + 0x89, 0xa6, 0xb8, 0x79, 0x4c, 0x31, 0x0c, 0xf0] + + // https://tools.ietf.org/html/rfc7539#appendix-A.3 + // Test Vector #4 + rval5 = [0x1c, 0x92, 0x40, 0xa5, 0xeb, 0x55, 0xd3, 0x8a, + 0xf3, 0x33, 0x88, 0x86, 0x04, 0xf6, 0xb5, 0xf0] + sval5 = [0x47, 0x39, 0x17, 0xc1, 0x40, 0x2b, 0x80, 0x09, + 0x9d, 0xca, 0x5c, 0xbc, 0x20, 0x70, 0x75, 0xc0] + text5 = [0x27, 0x54, 0x77, 0x61, 0x73, 0x20, 0x62, 0x72, + 0x69, 0x6c, 0x6c, 0x69, 0x67, 0x2c, 0x20, 0x61, + 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, + 0x6c, 0x69, 0x74, 0x68, 0x79, 0x20, 0x74, 0x6f, + 0x76, 0x65, 0x73, 0x0a, 0x44, 0x69, 0x64, 0x20, + 0x67, 0x79, 0x72, 0x65, 0x20, 0x61, 0x6e, 0x64, + 0x20, 0x67, 0x69, 0x6d, 0x62, 0x6c, 0x65, 0x20, + 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, + 0x61, 0x62, 0x65, 0x3a, 0x0a, 0x41, 0x6c, 0x6c, + 0x20, 0x6d, 0x69, 0x6d, 0x73, 0x79, 0x20, 0x77, + 0x65, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x62, 0x6f, 0x72, 0x6f, 0x67, 0x6f, 0x76, 0x65, + 0x73, 0x2c, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x6d, 0x65, 0x20, + 0x72, 0x61, 0x74, 0x68, 0x73, 0x20, 0x6f, 0x75, + 0x74, 0x67, 0x72, 0x61, 0x62, 0x65, 0x2e] + + rfctest05 = Poly1305 text5 rval5 sval5 + == [0x45, 0x41, 0x66, 0x9a, 0x7e, 0xaa, 0xee, 0x61, + 0xe7, 0x08, 0xdc, 0x7c, 0xbc, 0xc5, 0xeb, 0x62] + + // https://tools.ietf.org/html/rfc7539#appendix-A.3 + // Test Vector #5 + rval6 = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + sval6 = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + text6 = [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff] + + rfctest06 = Poly1305 text6 rval6 sval6 + == [0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + + // https://tools.ietf.org/html/rfc7539#appendix-A.3 + // Test Vector #6 + rval7 = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + sval7 = [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff] + text7 = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + + rfctest07 = Poly1305 text7 rval7 sval7 + == [0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + + // https://tools.ietf.org/html/rfc7539#appendix-A.3 + // Test Vector #7 + rval8 = [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + sval8 = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + text8 = [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + + rfctest08 = Poly1305 text8 rval8 sval8 + == [0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + + // https://tools.ietf.org/html/rfc7539#appendix-A.3 + // Test Vector #8 + rval9 = [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + sval9 = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + text9 = [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xfb, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, + 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01] + + rfctest09 = Poly1305 text9 rval9 sval9 + == [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + + // https://tools.ietf.org/html/rfc7539#appendix-A.3 + // Test Vector #9 + rval10 = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + sval10 = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + text10 = [0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff] + + rfctest10 = Poly1305 text10 rval10 sval10 + == [0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff] + + // https://tools.ietf.org/html/rfc7539#appendix-A.3 + // Test Vector #10 + rval11 = [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + sval11 = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + text11 = [0xe3, 0x35, 0x94, 0xd7, 0x50, 0x5e, 0x43, 0xb9, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x33, 0x94, 0xd7, 0x50, 0x5e, 0x43, 0x79, 0xcd, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + + rfctest11 = Poly1305 text11 rval11 sval11 + == [0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + + // https://tools.ietf.org/html/rfc7539#appendix-A.3 + // Test Vector #11 + rval12 = [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + sval12 = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + text12 = [0xe3, 0x35, 0x94, 0xd7, 0x50, 0x5e, 0x43, 0xb9, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x33, 0x94, 0xd7, 0x50, 0x5e, 0x43, 0x79, 0xcd, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + + rfctest12 = Poly1305 text12 rval12 sval12 + == [0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + +property allTestsPass = + ([ // Full RFC test vectors + rfctest01, rfctest02, rfctest03, rfctest04, + rfctest05, rfctest06, rfctest07, rfctest08, + rfctest09, rfctest10, rfctest11, rfctest12 + ] : [_]Bit) == ~zero // All test bits should equal one diff --git a/security/nss/automation/saw/poly1305.saw b/security/nss/automation/saw/poly1305.saw new file mode 100644 index 000000000..44be1e3e0 --- /dev/null +++ b/security/nss/automation/saw/poly1305.saw @@ -0,0 +1,47 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +import "poly1305.cry" as poly1305; + +print "Proving Poly1305 spec..."; +prove_print abc {{ poly1305::allTestsPass }}; + +print "Loading LLVM bitcode..."; +m <- llvm_load_module "../../../dist/Debug/lib/libfreeblpriv3.so.bc"; + +let SpecPoly1305 n = do { + llvm_ptr "out" (llvm_array 16 (llvm_int 8)); + out <- llvm_var "*out" (llvm_array 16 (llvm_int 8)); + + llvm_ptr "ad" (llvm_array 16 (llvm_int 8)); + ad <- llvm_var "*ad" (llvm_array 16 (llvm_int 8)); + + adLen <- llvm_var "adLen" (llvm_int 32); + + llvm_ptr "ciphertext" (llvm_array n (llvm_int 8)); + ciphertext <- llvm_var "*ciphertext" (llvm_array n (llvm_int 8)); + + ciphertextLen <- llvm_var "ciphertextLen" (llvm_int 32); + + llvm_ptr "key" (llvm_array 32 (llvm_int 8)); + key <- llvm_var "*key" (llvm_array 32 (llvm_int 8)); + + llvm_assert_eq "*ad" {{ zero : [16][8] }}; + llvm_assert_eq "adLen" {{ 16 : [32] }}; + + llvm_assert_eq "*ciphertext" {{ zero : [n][8] }}; + llvm_assert_eq "ciphertextLen" {{ `n : [32] }}; + + llvm_assert_eq "*key" {{ zero : [32][8] }}; + + let res = {{ poly1305::Poly1305 (ad # ciphertext # [16, 0, 0, 0, 0, 0, 0, 0] # [`n, 0, 0, 0, 0, 0, 0, 0]) (take`{16} key) (drop`{16} key) }}; + llvm_ensure_eq "*out" {{ res }}; + + llvm_verify_tactic abc; +}; + +print "Proving equality for a single block..."; +// This is currently disabled as it takes way too long. We need to help Z3 +// prove this before we can enable it on Taskcluster. +//time (llvm_verify m "Poly1305Do" [] (SpecPoly1305 16)); diff --git a/security/nss/automation/taskcluster/docker-hacl/Dockerfile b/security/nss/automation/taskcluster/docker-hacl/Dockerfile index e8a88f06c..63f9a24e2 100644 --- a/security/nss/automation/taskcluster/docker-hacl/Dockerfile +++ b/security/nss/automation/taskcluster/docker-hacl/Dockerfile @@ -5,11 +5,11 @@ MAINTAINER Franziskus Kiefer # the original F* formula with Daniel Fabian # Pinned versions of HACL* (F* and KreMLin are pinned as submodules) -ENV haclrepo https://github.com/mitls/hacl-star.git +ENV haclrepo https://github.com/franziskuskiefer/hacl-star.git # Define versions of dependencies ENV opamv 4.04.2 -ENV haclversion dcd48329d535727dbde93877b124c5ec4a7a2b20 +ENV haclversion 668d6cf274c33bbe2e951e3a84b73f2b6442a51f # Install required packages and set versions ADD setup.sh /tmp/setup.sh diff --git a/security/nss/automation/taskcluster/docker-saw/Dockerfile b/security/nss/automation/taskcluster/docker-saw/Dockerfile new file mode 100644 index 000000000..a481ba048 --- /dev/null +++ b/security/nss/automation/taskcluster/docker-saw/Dockerfile @@ -0,0 +1,46 @@ +FROM ubuntu:latest +MAINTAINER Tim Taubert + +RUN useradd -d /home/worker -s /bin/bash -m worker +WORKDIR /home/worker + +ENV DEBIAN_FRONTEND noninteractive + +RUN apt-get update && apt-get install -y \ + binutils \ + build-essential \ + bzip2 \ + clang-3.8 \ + curl \ + gcc-multilib \ + g++-multilib \ + gyp \ + lib32z1-dev \ + mercurial \ + ninja-build \ + unzip \ + zlib1g-dev + +# Add missing LLVM plugin for gold linker. +ADD LLVMgold.so.zip /usr/lib/llvm-3.8/lib/LLVMgold.so.zip +RUN unzip /usr/lib/llvm-3.8/lib/LLVMgold.so.zip -d /usr/lib/llvm-3.8/lib/ + +# Install SAW/Cryptol. +RUN curl -LO https://saw.galois.com/builds/nightly/saw-0.2-2018-01-14-Ubuntu14.04-64.tar.gz && \ + tar xzvf saw-*.tar.gz -C /usr/local --strip-components=1 && \ + rm saw-*.tar.gz + +# Install Z3. +RUN curl -LO https://github.com/Z3Prover/z3/releases/download/z3-4.6.0/z3-4.6.0-x64-ubuntu-16.04.zip && \ + unzip z3*.zip && \ + cp -r z3*/* /usr/local/ && \ + rm -fr z3* + +ADD bin /home/worker/bin +RUN chmod +x /home/worker/bin/* + +# Change user. +USER worker + +# Set a default command useful for debugging +CMD ["/bin/bash", "--login"] diff --git a/security/nss/automation/taskcluster/docker-saw/LLVMgold.so.zip b/security/nss/automation/taskcluster/docker-saw/LLVMgold.so.zip new file mode 100644 index 000000000..b5e5a593d Binary files /dev/null and b/security/nss/automation/taskcluster/docker-saw/LLVMgold.so.zip differ diff --git a/security/nss/automation/taskcluster/docker-saw/bin/checkout.sh b/security/nss/automation/taskcluster/docker-saw/bin/checkout.sh new file mode 100644 index 000000000..0cdd2ac40 --- /dev/null +++ b/security/nss/automation/taskcluster/docker-saw/bin/checkout.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash + +set -v -e -x + +# Default values for testing. +REVISION=${NSS_HEAD_REVISION:-default} +REPOSITORY=${NSS_HEAD_REPOSITORY:-https://hg.mozilla.org/projects/nss} + +# Clone NSS. +for i in 0 2 5; do + sleep $i + hg clone -r $REVISION $REPOSITORY nss && exit 0 + rm -rf nss +done +exit 1 diff --git a/security/nss/automation/taskcluster/docker/setup.sh b/security/nss/automation/taskcluster/docker/setup.sh index 01f9c413a..7b90b2e69 100644 --- a/security/nss/automation/taskcluster/docker/setup.sh +++ b/security/nss/automation/taskcluster/docker/setup.sh @@ -12,6 +12,7 @@ apt-get install -y --no-install-recommends apt-utils apt_packages=() apt_packages+=('build-essential') apt_packages+=('ca-certificates') +apt_packages+=('clang-5.0') apt_packages+=('curl') apt_packages+=('npm') apt_packages+=('git') @@ -47,16 +48,17 @@ echo "deb http://ppa.launchpad.net/ubuntu-toolchain-r/test/ubuntu xenial main" > apt-get -y update apt-get install -y --no-install-recommends ${apt_packages[@]} -# Download clang. -curl -LO https://releases.llvm.org/4.0.0/clang+llvm-4.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz -curl -LO https://releases.llvm.org/4.0.0/clang+llvm-4.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz.sig -# Verify the signature. -gpg --keyserver pool.sks-keyservers.net --recv-keys B6C8F98282B944E3B0D5C2530FC3042E345AD05D -gpg --verify *.tar.xz.sig -# Install into /usr/local/. -tar xJvf *.tar.xz -C /usr/local --strip-components=1 -# Cleanup. -rm *.tar.xz* +# Latest version of abigail-tools +apt-get install -y libxml2-dev autoconf libelf-dev libdw-dev libtool +git clone git://sourceware.org/git/libabigail.git +cd ./libabigail +autoreconf -fi +./configure --prefix=/usr --disable-static --disable-apidoc --disable-manual +make +make install +cd .. +apt-get remove -y libxml2-dev autoconf libtool +rm -rf libabigail # Install latest Rust (stable). su worker -c "curl https://sh.rustup.rs -sSf | sh -s -- -y" diff --git a/security/nss/automation/taskcluster/graph/src/extend.js b/security/nss/automation/taskcluster/graph/src/extend.js index 90e23ae60..ee9ac9b74 100644 --- a/security/nss/automation/taskcluster/graph/src/extend.js +++ b/security/nss/automation/taskcluster/graph/src/extend.js @@ -30,6 +30,11 @@ const HACL_GEN_IMAGE = { path: "automation/taskcluster/docker-hacl" }; +const SAW_IMAGE = { + name: "saw", + path: "automation/taskcluster/docker-saw" +}; + const WINDOWS_CHECKOUT_CMD = "bash -c \"hg clone -r $NSS_HEAD_REVISION $NSS_HEAD_REPOSITORY nss || " + "(sleep 2; hg clone -r $NSS_HEAD_REVISION $NSS_HEAD_REPOSITORY nss) || " + @@ -72,7 +77,8 @@ queue.filter(task => { } } - if (task.tests == "fips" && task.platform == "mac") { + if (task.tests == "fips" && + (task.platform == "mac" || task.platform == "aarch64")) { return false; } @@ -88,7 +94,7 @@ queue.filter(task => { } } - // Don't run additional hardware tests on ARM (we don't have anything there). + // Don't run all additional hardware tests on ARM. if (task.group == "Cipher" && task.platform == "aarch64" && task.env && (task.env.NSS_DISABLE_PCLMUL == "1" || task.env.NSS_DISABLE_HW_AES == "1" || task.env.NSS_DISABLE_AVX == "1")) { @@ -187,8 +193,8 @@ export default async function main() { UBSAN_OPTIONS: "print_stacktrace=1", NSS_DISABLE_ARENA_FREE_LIST: "1", NSS_DISABLE_UNLOAD: "1", - CC: "clang", - CCC: "clang++", + CC: "clang-5.0", + CCC: "clang++-5.0", }, platform: "linux64", collection: "asan", @@ -266,6 +272,18 @@ export default async function main() { }, aarch64_base) ); + await scheduleLinux("Linux AArch64 (debug, make)", + merge({ + env: {USE_64: "1"}, + command: [ + "/bin/bash", + "-c", + "bin/checkout.sh && nss/automation/taskcluster/scripts/build.sh" + ], + collection: "make", + }, aarch64_base) + ); + await scheduleMac("Mac (opt)", {collection: "opt"}, "--opt"); await scheduleMac("Mac (debug)", {collection: "debug"}); } @@ -418,12 +436,12 @@ async function scheduleLinux(name, base, args = "") { // Extra builds. let extra_base = merge({group: "Builds"}, build_base); queue.scheduleTask(merge(extra_base, { - name: `${name} w/ clang-4.0`, + name: `${name} w/ clang-5.0`, env: { - CC: "clang", - CCC: "clang++", + CC: "clang-5.0", + CCC: "clang++-5.0", }, - symbol: "clang-4.0" + symbol: "clang-5.0" })); queue.scheduleTask(merge(extra_base, { @@ -894,6 +912,13 @@ function scheduleTests(task_build, task_cert, test_base) { name: "Cipher tests", symbol: "NoAVX", tests: "cipher", env: {NSS_DISABLE_AVX: "1"}, group: "Cipher" })); + queue.scheduleTask(merge(no_cert_base, { + name: "Cipher tests", symbol: "NoSSSE3|NEON", tests: "cipher", + env: { + NSS_DISABLE_ARM_NEON: "1", + NSS_DISABLE_SSSE3: "1" + }, group: "Cipher" + })); queue.scheduleTask(merge(no_cert_base, { name: "EC tests", symbol: "EC", tests: "ec" })); @@ -946,6 +971,18 @@ async function scheduleTools() { kind: "test" }; + //ABI check task + queue.scheduleTask(merge(base, { + symbol: "abi", + name: "abi", + image: LINUX_IMAGE, + command: [ + "/bin/bash", + "-c", + "bin/checkout.sh && nss/automation/taskcluster/scripts/check_abi.sh" + ], + })); + queue.scheduleTask(merge(base, { symbol: "clang-format-3.9", name: "clang-format-3.9", @@ -958,13 +995,13 @@ async function scheduleTools() { })); queue.scheduleTask(merge(base, { - symbol: "scan-build-4.0", - name: "scan-build-4.0", + symbol: "scan-build-5.0", + name: "scan-build-5.0", image: LINUX_IMAGE, env: { USE_64: "1", - CC: "clang", - CCC: "clang++", + CC: "clang-5.0", + CCC: "clang++-5.0", }, artifacts: { public: { @@ -991,5 +1028,69 @@ async function scheduleTools() { ] })); + let task_saw = queue.scheduleTask(merge(base, { + symbol: "B", + group: "SAW", + name: "LLVM bitcode build (32 bit)", + image: SAW_IMAGE, + kind: "build", + env: { + AR: "llvm-ar-3.8", + CC: "clang-3.8", + CCC: "clang++-3.8" + }, + artifacts: { + public: { + expires: 24 * 7, + type: "directory", + path: "/home/worker/artifacts" + } + }, + command: [ + "/bin/bash", + "-c", + "bin/checkout.sh && nss/automation/taskcluster/scripts/build_gyp.sh --disable-tests --emit-llvm -m32" + ] + })); + + queue.scheduleTask(merge(base, { + parent: task_saw, + symbol: "bmul", + group: "SAW", + name: "bmul.saw", + image: SAW_IMAGE, + command: [ + "/bin/bash", + "-c", + "bin/checkout.sh && nss/automation/taskcluster/scripts/run_saw.sh bmul" + ] + })); + + queue.scheduleTask(merge(base, { + parent: task_saw, + symbol: "ChaCha20", + group: "SAW", + name: "chacha20.saw", + image: SAW_IMAGE, + command: [ + "/bin/bash", + "-c", + "bin/checkout.sh && nss/automation/taskcluster/scripts/run_saw.sh chacha20" + ] + })); + + queue.scheduleTask(merge(base, { + parent: task_saw, + symbol: "Poly1305", + group: "SAW", + name: "poly1305.saw", + image: SAW_IMAGE, + command: [ + "/bin/bash", + "-c", + "bin/checkout.sh && nss/automation/taskcluster/scripts/run_saw.sh poly1305" + ] + })); + return queue.submit(); } diff --git a/security/nss/automation/taskcluster/graph/src/image_builder.js b/security/nss/automation/taskcluster/graph/src/image_builder.js index b89b6980c..d9d7755dc 100644 --- a/security/nss/automation/taskcluster/graph/src/image_builder.js +++ b/security/nss/automation/taskcluster/graph/src/image_builder.js @@ -30,7 +30,7 @@ export async function buildTask({name, path}) { let ns = `docker.images.v1.${process.env.TC_PROJECT}.${name}.hash.${hash}`; return { - name: "Image Builder", + name: `Image Builder (${name})`, image: "nssdev/image_builder:0.1.5", routes: ["index." + ns], env: { diff --git a/security/nss/automation/taskcluster/graph/src/queue.js b/security/nss/automation/taskcluster/graph/src/queue.js index 29b570729..809a17bf1 100644 --- a/security/nss/automation/taskcluster/graph/src/queue.js +++ b/security/nss/automation/taskcluster/graph/src/queue.js @@ -31,10 +31,11 @@ function parseRoutes(routes) { ]; // Notify about failures (except on try). - if (process.env.TC_PROJECT != "nss-try") { + // Turned off, too noisy. + /*if (process.env.TC_PROJECT != "nss-try") { rv.push(`notify.email.${process.env.TC_OWNER}.on-failed`, `notify.email.${process.env.TC_OWNER}.on-exception`); - } + }*/ return rv; } diff --git a/security/nss/automation/taskcluster/graph/src/try_syntax.js b/security/nss/automation/taskcluster/graph/src/try_syntax.js index 1f4e12eee..1c06dde13 100644 --- a/security/nss/automation/taskcluster/graph/src/try_syntax.js +++ b/security/nss/automation/taskcluster/graph/src/try_syntax.js @@ -51,7 +51,7 @@ function parseOptions(opts) { } // Parse tools. - let allTools = ["clang-format", "scan-build", "hacl"]; + let allTools = ["clang-format", "scan-build", "hacl", "saw", "abi"]; let tools = intersect(opts.tools.split(/\s*,\s*/), allTools); // If the given value is "all" run all tools. @@ -77,7 +77,8 @@ function filter(opts) { // are not affected by platform or build type selectors. if (task.platform == "nss-tools") { return opts.tools.some(tool => { - return task.symbol.toLowerCase().startsWith(tool); + return task.symbol.toLowerCase().startsWith(tool) || + (task.group && task.group.toLowerCase().startsWith(tool)); }); } diff --git a/security/nss/automation/taskcluster/scripts/check_abi.sh b/security/nss/automation/taskcluster/scripts/check_abi.sh new file mode 100644 index 000000000..dbc1a476f --- /dev/null +++ b/security/nss/automation/taskcluster/scripts/check_abi.sh @@ -0,0 +1,172 @@ +#! /bin/bash + +set_env() +{ + cd /home/worker + HGDIR=/home/worker + OUTPUTDIR=$(pwd)$(echo "/output") + DATE=$(date "+TB [%Y-%m-%d %H:%M:%S]") + + if [ ! -d "${OUTPUTDIR}" ]; then + echo "Creating output dir" + mkdir "${OUTPUTDIR}" + fi + + if [ ! -d "nspr" ]; then + for i in 0 2 5; do + sleep $i + hg clone -r "default" "https://hg.mozilla.org/projects/nspr" "${HGDIR}/nspr" && break + rm -rf nspr + done + fi + + cd nss + ./build.sh -v -c + cd .. +} + +check_abi() +{ + set_env + set +e #reverses set -e from build.sh to allow possible hg clone failures + if [[ "$1" != --nobuild ]]; then # Start nobuild block + + echo "######## NSS ABI CHECK ########" + echo "######## creating temporary HG clones ########" + + rm -rf ${HGDIR}/baseline + mkdir ${HGDIR}/baseline + BASE_NSS=`cat ${HGDIR}/nss/automation/abi-check/previous-nss-release` #Reads the version number of the last release from the respective file + NSS_CLONE_RESULT=0 + for i in 0 2 5; do + sleep $i + hg clone -u "${BASE_NSS}" "https://hg.mozilla.org/projects/nss" "${HGDIR}/baseline/nss" + if [ $? -eq 0 ]; then + NSS_CLONE_RESULT=0 + break + fi + rm -rf "${HGDIR}/baseline/nss" + NSS_CLONE_RESULT=1 + done + if [ ${NSS_CLONE_RESULT} -ne 0 ]; then + echo "invalid tag in automation/abi-check/previous-nss-release" + return 1 + fi + + BASE_NSPR=NSPR_$(head -1 ${HGDIR}/baseline/nss/automation/release/nspr-version.txt | cut -d . -f 1-2 | tr . _)_BRANCH + hg clone -u "${BASE_NSPR}" "https://hg.mozilla.org/projects/nspr" "${HGDIR}/baseline/nspr" + NSPR_CLONE_RESULT=$? + + if [ ${NSPR_CLONE_RESULT} -ne 0 ]; then + rm -rf "${HGDIR}/baseline/nspr" + for i in 0 2 5; do + sleep $i + hg clone -u "default" "https://hg.mozilla.org/projects/nspr" "${HGDIR}/baseline/nspr" && break + rm -rf "${HGDIR}/baseline/nspr" + done + echo "Nonexisting tag ${BASE_NSPR} derived from ${BASE_NSS} automation/release/nspr-version.txt" + echo "Using default branch instead." + fi + + echo "######## building baseline NSPR/NSS ########" + echo "${HGDIR}/baseline/nss/build.sh" + cd ${HGDIR}/baseline/nss + ./build.sh -v -c + cd ${HGDIR} + else # Else nobuild block + echo "######## using existing baseline NSPR/NSS build ########" + fi # End nobuild block + + set +e #reverses set -e from build.sh to allow abidiff failures + + echo "######## Starting abidiff procedure ########" + abi_diff +} + +#Slightly modified from builbot-slave/build.sh +abi_diff() +{ + ABI_PROBLEM_FOUND=0 + ABI_REPORT=${OUTPUTDIR}/abi-diff.txt + rm -f ${ABI_REPORT} + PREVDIST=${HGDIR}/baseline/dist + NEWDIST=${HGDIR}/dist + ALL_SOs="libfreebl3.so libfreeblpriv3.so libnspr4.so libnss3.so libnssckbi.so libnssdbm3.so libnsssysinit.so libnssutil3.so libplc4.so libplds4.so libsmime3.so libsoftokn3.so libssl3.so" + for SO in ${ALL_SOs}; do + if [ ! -f ${HGDIR}/nss/automation/abi-check/expected-report-$SO.txt ]; then + touch ${HGDIR}/nss/automation/abi-check/expected-report-$SO.txt + fi + abidiff --hd1 $PREVDIST/public/ --hd2 $NEWDIST/public \ + $PREVDIST/*/lib/$SO $NEWDIST/*/lib/$SO \ + > ${HGDIR}/nss/automation/abi-check/new-report-temp$SO.txt + RET=$? + cat ${HGDIR}/nss/automation/abi-check/new-report-temp$SO.txt \ + | grep -v "^Functions changes summary:" \ + | grep -v "^Variables changes summary:" \ + > ${HGDIR}/nss/automation/abi-check/new-report-$SO.txt + rm -f ${HGDIR}/nss/automation/abi-check/new-report-temp$SO.txt + + ABIDIFF_ERROR=$((($RET & 0x01) != 0)) + ABIDIFF_USAGE_ERROR=$((($RET & 0x02) != 0)) + ABIDIFF_ABI_CHANGE=$((($RET & 0x04) != 0)) + ABIDIFF_ABI_INCOMPATIBLE_CHANGE=$((($RET & 0x08) != 0)) + ABIDIFF_UNKNOWN_BIT_SET=$((($RET & 0xf0) != 0)) + + # If abidiff reports an error, or a usage error, or if it sets a result + # bit value this script doesn't know yet about, we'll report failure. + # For ABI changes, we don't yet report an error. We'll compare the + # result report with our whitelist. This allows us to silence changes + # that we're already aware of and have been declared acceptable. + + REPORT_RET_AS_FAILURE=0 + if [ $ABIDIFF_ERROR -ne 0 ]; then + echo "abidiff reported ABIDIFF_ERROR." + REPORT_RET_AS_FAILURE=1 + fi + if [ $ABIDIFF_USAGE_ERROR -ne 0 ]; then + echo "abidiff reported ABIDIFF_USAGE_ERROR." + REPORT_RET_AS_FAILURE=1 + fi + if [ $ABIDIFF_UNKNOWN_BIT_SET -ne 0 ]; then + echo "abidiff reported ABIDIFF_UNKNOWN_BIT_SET." + REPORT_RET_AS_FAILURE=1 + fi + + if [ $ABIDIFF_ABI_CHANGE -ne 0 ]; then + echo "Ignoring abidiff result ABI_CHANGE, instead we'll check for non-whitelisted differences." + fi + if [ $ABIDIFF_ABI_INCOMPATIBLE_CHANGE -ne 0 ]; then + echo "Ignoring abidiff result ABIDIFF_ABI_INCOMPATIBLE_CHANGE, instead we'll check for non-whitelisted differences." + fi + + if [ $REPORT_RET_AS_FAILURE -ne 0 ]; then + ABI_PROBLEM_FOUND=1 + echo "abidiff {$PREVDIST , $NEWDIST} for $SO FAILED with result $RET, or failed writing to ${HGDIR}/nss/automation/abi-check/new-report-$SO.txt" + fi + if [ ! -f ${HGDIR}/nss/automation/abi-check/expected-report-$SO.txt ]; then + ABI_PROBLEM_FOUND=1 + echo "FAILED to access report file: ${HGDIR}/nss/automation/abi-check/expected-report-$SO.txt" + fi + + diff -wB -u ${HGDIR}/nss/automation/abi-check/expected-report-$SO.txt \ + ${HGDIR}/nss/automation/abi-check/new-report-$SO.txt >> ${ABI_REPORT} + if [ ! -f ${ABI_REPORT} ]; then + ABI_PROBLEM_FOUND=1 + echo "FAILED to compare exepcted and new report: ${HGDIR}/nss/automation/abi-check/new-report-$SO.txt" + fi + done + + if [ -s ${ABI_REPORT} ]; then + echo "FAILED: there are new unexpected ABI changes" + cat ${ABI_REPORT} + return 1 + elif [ $ABI_PROBLEM_FOUND -ne 0 ]; then + echo "FAILED: failure executing the ABI checks" + cat ${ABI_REPORT} + return 1 + fi + + return 0 +} + +check_abi $1 diff --git a/security/nss/automation/taskcluster/scripts/run_saw.sh b/security/nss/automation/taskcluster/scripts/run_saw.sh new file mode 100644 index 000000000..0e9a8224a --- /dev/null +++ b/security/nss/automation/taskcluster/scripts/run_saw.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +source $(dirname "$0")/tools.sh + +# Fetch artifact if needed. +fetch_dist + +# Run SAW. +saw "nss/automation/saw/$1.saw" diff --git a/security/nss/automation/taskcluster/scripts/run_scan_build.sh b/security/nss/automation/taskcluster/scripts/run_scan_build.sh index 4024c226e..014530b42 100755 --- a/security/nss/automation/taskcluster/scripts/run_scan_build.sh +++ b/security/nss/automation/taskcluster/scripts/run_scan_build.sh @@ -34,7 +34,7 @@ for i in "${!scan[@]}"; do done # run scan-build (only building affected directories) -scan-build -o /home/worker/artifacts --use-cc=$CC --use-c++=$CCC make nss_build_all && cd .. +scan-build-5.0 -o /home/worker/artifacts --use-cc=$CC --use-c++=$CCC make nss_build_all && cd .. # print errors we found set +v +x diff --git a/security/nss/build.sh b/security/nss/build.sh index 2db8256d8..338e14beb 100755 --- a/security/nss/build.sh +++ b/security/nss/build.sh @@ -91,6 +91,7 @@ while [ $# -gt 0 ]; do --sancov=?*) enable_sancov "${1#*=}" ;; --pprof) gyp_params+=(-Duse_pprof=1) ;; --ct-verif) gyp_params+=(-Dct_verif=1) ;; + --emit-llvm) gyp_params+=(-Demit_llvm=1 -Dsign_libs=0) ;; --disable-tests) gyp_params+=(-Ddisable_tests=1) ;; --no-zdefs) gyp_params+=(-Dno_zdefs=1) ;; --system-sqlite) gyp_params+=(-Duse_system_sqlite=1) ;; diff --git a/security/nss/cmd/certcgi/HOWTO.txt b/security/nss/cmd/certcgi/HOWTO.txt deleted file mode 100644 index 54edf8e1a..000000000 --- a/security/nss/cmd/certcgi/HOWTO.txt +++ /dev/null @@ -1,137 +0,0 @@ - How to setup your very own Cert-O-Matic Root CA server - - This Source Code Form is subject to the terms of the Mozilla Public - # License, v. 2.0. If a copy of the MPL was not distributed with this - # file, You can obtain one at http://mozilla.org/MPL/2.0/. - - How to setup your very own Cert-O-Matic Root CA server - -The program certcgi is part of a small test CA that is used inside -Netscape by the NSS development team. That CA is affectionately known -as "Cert-O-Matic" or "Cert-O-Matic II". It presently runs on a server -named interzone.mcom.com inside Netscape's firewall. - -If you wish to setup your own Cert-O-Matic, here are directions. - -Disclaimer: This program does not follow good practices for root CAs. -It should be used only for playing/testing and never for production use. -Remember, you've been warned! - -Cert-O-Matic consists of some html files, shell scripts, one executable -program that uses NSS and NSPR, the usual set of NSS .db files, and a file -in which to remember the serial number of the last cert issued. The -html files and the source to the executable program are in this directory. -Sample shell scripts are shown below. - -The shell scripts and executable program run as CGI "scripts". The -entire thing runs on an ordinary http web server. It would also run on -an https web server. The shell scripts and html files must be -customized for the server on which they run. - -The package assumes you have a "document root" directory $DOCROOT, and a -"cgi-bin" directory $CGIBIN. In this example, the document root is -assumed to be located in /var/www/htdocs, and the cgi-bin directory in -/var/www/cgi-bin. - -The server is assumed to run all cgi scripts as the user "nobody". -The names of the cgi scripts run directly by the server all end in .cgi -because some servers like it that way. - -Instructions: - -- Create directory $DOCROOT/certomatic -- Copy the following files from nss/cmd/certcgi to $DOCROOT/certomatic - ca.html index.html main.html nscp_ext_form.html stnd_ext_form.html -- Edit the html files, substituting the name of your own server for the - server named in those files. -- In some web page (e.g. your server's home page), provide an html link to - $DOCROOT/certomatic/index.html. This is where users start to get their - own certs from certomatic. -- give these files and directories appropriate permissions. - -- Create directories $CGIBIN/certomatic and $CGIBIN/certomatic/bin - make sure that $CGIBIN/certomatic is writable by "nobody" - -- Create a new set of NSS db files there with the following command: - - certutil -N -d $CGIBIN/certomatic - -- when certutil prompts you for the password, enter the word foo - because that is compiled into the certcgi program. - -- Create the new Root CA cert with this command - - certutil -S -x -d $CGIBIN/certomatic -n "Cert-O-Matic II" \ - -s "CN=Cert-O-Matic II, O=Cert-O-Matic II" -t TCu,cu,cu -k rsa \ - -g 1024 -m 10001 -v 60 - - (adjust the -g, -m and -v parameters to taste. -s and -x must be as -shown.) - -- dump out the new root CA cert in base64 encoding: - - certutil -d $CGIBIN/certomatic -L -n "Cert-O-Matic II" -a > \ - $CGIBIN/certomatic/root.cacert - -- In $CGIBIN/certomatic/bin add two shell scripts - one to download the - root CA cert on demand, and one to run the certcgi program. - -download.cgi, the script to install the root CA cert into a browser on -demand, is this: - -#!/bin/sh -echo "Content-type: application/x-x509-ca-cert" -echo -cat $CGIBIN/certomatic/root.cacert - -You'll have to put the real path into that cat command because CGIBIN -won't be defined when this script is run by the server. - -certcgi.cgi, the script to run the certcgi program is similar to this: - -#!/bin/sh -cd $CGIBIN/certomatic/bin -LD_LIBRARY_PATH=$PLATFORM/lib -export LD_LIBRARY_PATH -$PLATFORM/bin/certcgi $* 2>&1 - -Where $PLATFORM/lib is where the NSPR nad NSS DSOs are located, and -$PLATFORM/bin is where certcgi is located. PLATFORM is not defined when -the server runs this script, so you'll have to substitute the right value -in your script. certcgi requires that the working directory be one level -below the NSS DBs, that is, the DBs are accessed in the directory "..". - -You'll want to provide an html link somewhere to the script that downloads -the root.cacert file. You'll probably want to put that next to the link -that loads the index.html page. On interzone, this is done with the -following html: - -Cert-O-Matic II Root CA server -

-Download and trust Root CA -certificate - -The index.html file in this directory invokes the certcgi.cgi script with -the form post method, so if you change the name of the certcgi.cgi script, -you'll also have to change the index.html file in $DOCROOT/certomatic - -The 4 files used by the certcgi program (the 3 NSS DBs, and the serial -number file) are not required to live in $CGIBIN/certomatic, but they are -required to live in $CWD/.. when certcgi starts. - -Known bugs: - -1. Because multiple of these CAs exist simultaneously, it would be best if -they didn't all have to be called "Cert-O-Matic II", but that string is -presently hard coded into certcgi.c. - -2. the html files in this directory contain numerous extraneous

tags -which appear to use the post method and have action URLS that are never -actually used. burp.cgi and echoform.cgi are never actually used. This -should be cleaned up. - -3. The html files use tags which are supported only in Netscape -Navigator and Netscape Communication 4.x browsers. The html files do -not work as intended with Netscape 6.x, Mozilla or Microsoft IE browsers. -The html files should be fixed to work with all those named browsers. - diff --git a/security/nss/cmd/certcgi/Makefile b/security/nss/cmd/certcgi/Makefile deleted file mode 100644 index c2039d82b..000000000 --- a/security/nss/cmd/certcgi/Makefile +++ /dev/null @@ -1,48 +0,0 @@ -#! gmake -# -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. - -####################################################################### -# (1) Include initial platform-independent assignments (MANDATORY). # -####################################################################### - -include manifest.mn - -####################################################################### -# (2) Include "global" configuration information. (OPTIONAL) # -####################################################################### - -include $(CORE_DEPTH)/coreconf/config.mk - -####################################################################### -# (3) Include "component" configuration information. (OPTIONAL) # -####################################################################### - -####################################################################### -# (4) Include "local" platform-dependent assignments (OPTIONAL). # -####################################################################### - -include ../platlibs.mk - -####################################################################### -# (5) Execute "global" rules. (OPTIONAL) # -####################################################################### - -include $(CORE_DEPTH)/coreconf/rules.mk - -####################################################################### -# (6) Execute "component" rules. (OPTIONAL) # -####################################################################### - - - -####################################################################### -# (7) Execute "local" rules. (OPTIONAL). # -####################################################################### - - - -include ../platrules.mk - diff --git a/security/nss/cmd/certcgi/ca.html b/security/nss/cmd/certcgi/ca.html deleted file mode 100644 index 3f3f08699..000000000 --- a/security/nss/cmd/certcgi/ca.html +++ /dev/null @@ -1,19 +0,0 @@ - - - - - Use the Cert-O-matic certificate to issue the cert

- Use a - CA long - automatically generated chain ending with the Cert-O-Matic Cert - (18 maximum)

- Use a - CA long - user input chain ending in the Cert-O-Matic Cert.

- diff --git a/security/nss/cmd/certcgi/ca_form.html b/security/nss/cmd/certcgi/ca_form.html deleted file mode 100644 index 452996b58..000000000 --- a/security/nss/cmd/certcgi/ca_form.html +++ /dev/null @@ -1,357 +0,0 @@ - - -
- - - - - - - - - - - - - -
- Common Name:

-
- Mail:

- RFC 1274 - e-mail
- Organization:

- Organizational Unit:

- RFC 1274 UID:

- Locality:

- State or Province:

- Country:

- - - - - - - -
- Serial Number:

-
- Auto Generate

-
- - Use this value:

-
- X.509 version:

-
- Version 1

-
- Version 3

- Key Type:

-
- RSA

-
- DSA

- DN:

- -

-
-

- - - - - - - - - - - - - - - - - -
- Netscape Certificate Type:

- Activate extension:

- Critical: -
- SSL Client

- SSL Server

- S/MIME

- Object Signing

- Reserved for future use (bit 4)

- SSL CA

- S/MIME CA

- Object Signing CA

-
- Netscape Base URL:

- Activate extension:

- Critical: -
- -
- Netscape Revocation URL:

- Activate extension:

- Critical: -
- -
- Netscape CA Revocation URL:

- Activate extension:

- Critical: -
- -
- Netscape Certificate Renewal URL:

- Activate extension:

- Critical: -
- -
- Netscape CA Policy URL:

- Activate extension:

- Critical: -
- -
- Netscape SSL Server Name:

- Activate extension:

- Critical: -
- -
- Netscape Comment:

- Activate extension:

- Critical: -
- -
-

-
-

- - - - - - - - - - - - - - - - - - - - - - - -
- Key Usage:

- Activate extension:

- Critical: -
- Digital Signature

- Non Repudiation

- Key Encipherment

- Data Encipherment

- Key Agreement

- Key Certificate Signing

- CRL Signing

-
- Extended Key Usage:

- Activate extension:

- Critical: -
- Server Auth

- Client Auth

- Code Signing

- Email Protection

- Timestamp

- OCSP Responder

- Step-up

- Microsoft Trust List Signing

-
- Basic Constraints:

- Activate extension:

- Critical: -
- CA:

-
True

-
False

- - Include Path length:

-
- Authority Key Identifier:

- Activate extension: -
- Key Identider

- Issuer Name and Serial number

-
- Subject Key Identifier:

- Activate extension: -
- Key Identifier: -

- This is an:

-

ascii text value

-

hex value

-

- Private Key Usage Period:

- Activate extension:

- Critical: -
- Use:

-
Not Before

-
Not After

-
Both

- Not to be used to sign before:

-
Set to time of certificate issue

-
Use This value

-
(YYYY/MM/DD HH:MM:SS): - / - / - - : - : -

- Not to be used to sign after:

-
(YYYY/MM/DD HH:MM:SS): - / - / - - : - : -

-
- Subject Alternative Name:

- Activate extension:

- Critical: -
- - - -
- General Names:

-

- - -
- -
- Name Type:
- Other Name, - OID: - RFC 822 Name
- DNS Name - X400 Address
- Directory Name - EDI Party Name
- Uniform Resource Locator - IP Address
- Registered ID - Netscape Certificate Nickname
- Name: - Binary Encoded:

-
-
- Issuer Alternative Name:

- Activate extension:

- Critical: -
- Use the Subject Alternative Name from the Issuers Certificate

- Use this Name: - - - -
- General Names:

-

- - -
- -
- Name Type:
- Other Name, - OID: - RFC 822 Name
- DNS Name - X400 Address
- Directory Name - EDI Party Name
- Uniform Resource Locator - IP Address
- Registered ID
- Name: - Binary Encoded:

-
-
- Name Constraints:

- Activate extension:

-
- - - -
- Name Constraints:

- - -

- - -
- -
- Name Type:
- Other Name, - OID: - RFC 822 Name
- DNS Name - X400 Address
- Directory Name - EDI Party Name
- Uniform Resource Locator - IP Address
- Registered ID
- Name: - Binary Encoded:

- Constraint type:

-

permited

-

excluded

- Minimum:

- Maximum:

- - - -
-
-
- - - - - - - - - - diff --git a/security/nss/cmd/certcgi/certcgi.c b/security/nss/cmd/certcgi/certcgi.c deleted file mode 100644 index 4d1a1061a..000000000 --- a/security/nss/cmd/certcgi/certcgi.c +++ /dev/null @@ -1,2245 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -/* Cert-O-Matic CGI */ - -#include "nspr.h" -#include "prtypes.h" -#include "prtime.h" -#include "prlong.h" - -#include "pk11func.h" -#include "cert.h" -#include "cryptohi.h" -#include "secoid.h" -#include "secder.h" -#include "genname.h" -#include "xconst.h" -#include "secutil.h" -#include "pk11pqg.h" -#include "certxutl.h" -#include "nss.h" - -/* #define TEST 1 */ -/* #define FILEOUT 1 */ -/* #define OFFLINE 1 */ -#define START_FIELDS 100 -#define PREFIX_LEN 6 -#define SERIAL_FILE "../serial" -#define DB_DIRECTORY ".." - -static char *progName; - -typedef struct PairStr Pair; - -struct PairStr { - char *name; - char *data; -}; - -char prefix[PREFIX_LEN]; - -const SEC_ASN1Template CERTIA5TypeTemplate[] = { - { SEC_ASN1_IA5_STRING } -}; - -SECKEYPrivateKey *privkeys[9] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL }; - -#ifdef notdef -const SEC_ASN1Template CERT_GeneralNameTemplate[] = { - { SEC_ASN1_SEQUENCE_OF, 0, SEC_AnyTemplate } -}; -#endif - -static void -error_out(char *error_string) -{ - printf("Content-type: text/plain\n\n"); - printf("%s", error_string); - fflush(stderr); - fflush(stdout); - exit(1); -} - -static void -error_allocate(void) -{ - error_out("ERROR: Unable to allocate memory"); -} - -static char * -make_copy_string(char *read_pos, - int length, - char sentinal_value) -/* copys string from to a new string it creates and - returns a pointer to the new string */ -{ - int remaining = length; - char *write_pos; - char *new; - - new = write_pos = (char *)PORT_Alloc(length); - if (new == NULL) { - error_allocate(); - } - while (*read_pos != sentinal_value) { - if (remaining == 1) { - remaining += length; - length = length * 2; - new = PORT_Realloc(new, length); - if (new == NULL) { - error_allocate(); - } - write_pos = new + length - remaining; - } - *write_pos = *read_pos; - ++write_pos; - ++read_pos; - remaining = remaining - 1; - } - *write_pos = '\0'; - return new; -} - -static SECStatus -clean_input(Pair *data) -/* converts the non-alphanumeric characters in a form post - from hex codes back to characters */ -{ - int length; - int hi_digit; - int low_digit; - char character; - char *begin_pos; - char *read_pos; - char *write_pos; - PRBool name = PR_TRUE; - - begin_pos = data->name; - while (begin_pos != NULL) { - length = strlen(begin_pos); - read_pos = write_pos = begin_pos; - while ((read_pos - begin_pos) < length) { - if (*read_pos == '+') { - *read_pos = ' '; - } - if (*read_pos == '%') { - hi_digit = *(read_pos + 1); - low_digit = *(read_pos + 2); - read_pos += 3; - if (isdigit(hi_digit)) { - hi_digit = hi_digit - '0'; - } else { - hi_digit = toupper(hi_digit); - if (isxdigit(hi_digit)) { - hi_digit = (hi_digit - 'A') + 10; - } else { - error_out("ERROR: Form data incorrectly formated"); - } - } - if (isdigit(low_digit)) { - low_digit = low_digit - '0'; - } else { - low_digit = toupper(low_digit); - if ((low_digit >= 'A') && (low_digit <= 'F')) { - low_digit = (low_digit - 'A') + 10; - } else { - error_out("ERROR: Form data incorrectly formated"); - } - } - character = (hi_digit << 4) | low_digit; - if (character != 10) { - *write_pos = character; - ++write_pos; - } - } else { - *write_pos = *read_pos; - ++write_pos; - ++read_pos; - } - } - *write_pos = '\0'; - if (name == PR_TRUE) { - begin_pos = data->data; - name = PR_FALSE; - } else { - data++; - begin_pos = data->name; - name = PR_TRUE; - } - } - return SECSuccess; -} - -static char * -make_name(char *new_data) -/* gets the next field name in the input string and returns - a pointer to a string containing a copy of it */ -{ - int length = 20; - char *name; - - name = make_copy_string(new_data, length, '='); - return name; -} - -static char * -make_data(char *new_data) -/* gets the data for the next field in the input string - and returns a pointer to a string containing it */ -{ - int length = 100; - char *data; - char *read_pos; - - read_pos = new_data; - while (*(read_pos - 1) != '=') { - ++read_pos; - } - data = make_copy_string(read_pos, length, '&'); - return data; -} - -static Pair -make_pair(char *new_data) -/* makes a pair name/data pair from the input string */ -{ - Pair temp; - - temp.name = make_name(new_data); - temp.data = make_data(new_data); - return temp; -} - -static Pair * -make_datastruct(char *data, int len) -/* parses the input from the form post into a data - structure of field name/data pairs */ -{ - Pair *datastruct; - Pair *current; - char *curr_pos; - int fields = START_FIELDS; - int remaining = START_FIELDS; - - curr_pos = data; - datastruct = current = (Pair *)PORT_Alloc(fields * sizeof(Pair)); - if (datastruct == NULL) { - error_allocate(); - } - while (curr_pos - data < len) { - if (remaining == 1) { - remaining += fields; - fields = fields * 2; - datastruct = (Pair *)PORT_Realloc(datastruct, fields * sizeof(Pair)); - if (datastruct == NULL) { - error_allocate(); - } - current = datastruct + (fields - remaining); - } - *current = make_pair(curr_pos); - while (*curr_pos != '&') { - ++curr_pos; - } - ++curr_pos; - ++current; - remaining = remaining - 1; - } - current->name = NULL; - return datastruct; -} - -static char * -return_name(Pair *data_struct, - int n) -/* returns a pointer to the name of the nth - (starting from 0) item in the data structure */ -{ - char *name; - - if ((data_struct + n)->name != NULL) { - name = (data_struct + n)->name; - return name; - } else { - return NULL; - } -} - -static char * -return_data(Pair *data_struct, int n) -/* returns a pointer to the data of the nth (starting from 0) - itme in the data structure */ -{ - char *data; - - data = (data_struct + n)->data; - return data; -} - -static char * -add_prefix(char *field_name) -{ - extern char prefix[PREFIX_LEN]; - int i = 0; - char *rv; - char *write; - - rv = write = PORT_Alloc(PORT_Strlen(prefix) + PORT_Strlen(field_name) + 1); - for (i = 0; i < PORT_Strlen(prefix); i++) { - *write = prefix[i]; - write++; - } - *write = '\0'; - rv = PORT_Strcat(rv, field_name); - return rv; -} - -static char * -find_field(Pair *data, - char *field_name, - PRBool add_pre) -/* returns a pointer to the data of the first pair - thats name matches the string it is passed */ -{ - int i = 0; - char *retrieved; - int found = 0; - - if (add_pre) { - field_name = add_prefix(field_name); - } - while (return_name(data, i) != NULL) { - if (PORT_Strcmp(return_name(data, i), field_name) == 0) { - retrieved = return_data(data, i); - found = 1; - break; - } - i++; - } - if (!found) { - retrieved = NULL; - } - return retrieved; -} - -static PRBool -find_field_bool(Pair *data, - char *fieldname, - PRBool add_pre) -{ - char *rv; - - rv = find_field(data, fieldname, add_pre); - - if ((rv != NULL) && (PORT_Strcmp(rv, "true")) == 0) { - return PR_TRUE; - } else { - return PR_FALSE; - } -} - -static CERTCertificateRequest * -makeCertReq(Pair *form_data, - int which_priv_key) -/* makes and encodes a certrequest */ -{ - - PK11SlotInfo *slot; - CERTCertificateRequest *certReq = NULL; - CERTSubjectPublicKeyInfo *spki; - SECKEYPrivateKey *privkey = NULL; - SECKEYPublicKey *pubkey = NULL; - CERTName *name; - char *key; - extern SECKEYPrivateKey *privkeys[9]; - int keySizeInBits; - char *challenge = "foo"; - SECStatus rv = SECSuccess; - PQGParams *pqgParams = NULL; - PQGVerify *pqgVfy = NULL; - - name = CERT_AsciiToName(find_field(form_data, "subject", PR_TRUE)); - if (name == NULL) { - error_out("ERROR: Unable to create Subject Name"); - } - key = find_field(form_data, "key", PR_TRUE); - if (key == NULL) { - switch (*find_field(form_data, "keysize", PR_TRUE)) { - case '0': - keySizeInBits = 2048; - break; - case '1': - keySizeInBits = 1024; - break; - case '2': - keySizeInBits = 512; - break; - default: - error_out("ERROR: Unsupported Key length selected"); - } - if (find_field_bool(form_data, "keyType-dsa", PR_TRUE)) { - rv = PK11_PQG_ParamGen(keySizeInBits, &pqgParams, &pqgVfy); - if (rv != SECSuccess) { - error_out("ERROR: Unable to generate PQG parameters"); - } - slot = PK11_GetBestSlot(CKM_DSA_KEY_PAIR_GEN, NULL); - privkey = PK11_GenerateKeyPair(slot, CKM_DSA_KEY_PAIR_GEN, - pqgParams, &pubkey, PR_FALSE, - PR_TRUE, NULL); - } else { - privkey = SECKEY_CreateRSAPrivateKey(keySizeInBits, &pubkey, NULL); - } - privkeys[which_priv_key] = privkey; - spki = SECKEY_CreateSubjectPublicKeyInfo(pubkey); - } else { - spki = SECKEY_ConvertAndDecodePublicKeyAndChallenge(key, challenge, - NULL); - if (spki == NULL) { - error_out("ERROR: Unable to decode Public Key and Challenge String"); - } - } - certReq = CERT_CreateCertificateRequest(name, spki, NULL); - if (certReq == NULL) { - error_out("ERROR: Unable to create Certificate Request"); - } - if (pubkey != NULL) { - SECKEY_DestroyPublicKey(pubkey); - } - if (spki != NULL) { - SECKEY_DestroySubjectPublicKeyInfo(spki); - } - if (pqgParams != NULL) { - PK11_PQG_DestroyParams(pqgParams); - } - if (pqgVfy != NULL) { - PK11_PQG_DestroyVerify(pqgVfy); - } - return certReq; -} - -static CERTCertificate * -MakeV1Cert(CERTCertDBHandle *handle, - CERTCertificateRequest *req, - char *issuerNameStr, - PRBool selfsign, - int serialNumber, - int warpmonths, - Pair *data) -{ - CERTCertificate *issuerCert = NULL; - CERTValidity *validity; - CERTCertificate *cert = NULL; - PRExplodedTime printableTime; - PRTime now, - after; - if (!selfsign) { - issuerCert = CERT_FindCertByNameString(handle, issuerNameStr); - if (!issuerCert) { - error_out("ERROR: Could not find issuer's certificate"); - return NULL; - } - } - if (find_field_bool(data, "manValidity", PR_TRUE)) { - (void)DER_AsciiToTime(&now, find_field(data, "notBefore", PR_TRUE)); - } else { - now = PR_Now(); - } - PR_ExplodeTime(now, PR_GMTParameters, &printableTime); - if (warpmonths) { - printableTime.tm_month += warpmonths; - now = PR_ImplodeTime(&printableTime); - PR_ExplodeTime(now, PR_GMTParameters, &printableTime); - } - if (find_field_bool(data, "manValidity", PR_TRUE)) { - (void)DER_AsciiToTime(&after, find_field(data, "notAfter", PR_TRUE)); - PR_ExplodeTime(after, PR_GMTParameters, &printableTime); - } else { - printableTime.tm_month += 3; - after = PR_ImplodeTime(&printableTime); - } - /* note that the time is now in micro-second unit */ - validity = CERT_CreateValidity(now, after); - - if (selfsign) { - cert = CERT_CreateCertificate(serialNumber, &(req->subject), validity, req); - } else { - cert = CERT_CreateCertificate(serialNumber, &(issuerCert->subject), validity, req); - } - - CERT_DestroyValidity(validity); - if (issuerCert) { - CERT_DestroyCertificate(issuerCert); - } - return (cert); -} - -static int -get_serial_number(Pair *data) -{ - int serial = 0; - int error; - char *filename = SERIAL_FILE; - char *SN; - FILE *serialFile; - - if (find_field_bool(data, "serial-auto", PR_TRUE)) { - serialFile = fopen(filename, "r"); - if (serialFile != NULL) { - size_t nread = fread(&serial, sizeof(int), 1, serialFile); - if (ferror(serialFile) != 0 || nread != 1) { - error_out("Error: Unable to read serial number file"); - } - if (serial == -1) { - serial = 21; - } - fclose(serialFile); - ++serial; - serialFile = fopen(filename, "w"); - if (serialFile == NULL) { - error_out("ERROR: Unable to open serial number file for writing"); - } - fwrite(&serial, sizeof(int), 1, serialFile); - if (ferror(serialFile) != 0) { - error_out("Error: Unable to write to serial number file"); - } - } else { - fclose(serialFile); - serialFile = fopen(filename, "w"); - if (serialFile == NULL) { - error_out("ERROR: Unable to open serial number file"); - } - serial = 21; - fwrite(&serial, sizeof(int), 1, serialFile); - if (ferror(serialFile) != 0) { - error_out("Error: Unable to write to serial number file"); - } - error = ferror(serialFile); - if (error != 0) { - error_out("ERROR: Unable to write to serial file"); - } - } - fclose(serialFile); - } else { - SN = find_field(data, "serial_value", PR_TRUE); - while (*SN != '\0') { - serial = serial * 16; - if ((*SN >= 'A') && (*SN <= 'F')) { - serial += *SN - 'A' + 10; - } else { - if ((*SN >= 'a') && (*SN <= 'f')) { - serial += *SN - 'a' + 10; - } else { - serial += *SN - '0'; - } - } - ++SN; - } - } - return serial; -} - -typedef SECStatus (*EXTEN_VALUE_ENCODER)(PLArenaPool *extHandle, void *value, SECItem *encodedValue); - -static SECStatus -EncodeAndAddExtensionValue( - PLArenaPool *arena, - void *extHandle, - void *value, - PRBool criticality, - int extenType, - EXTEN_VALUE_ENCODER EncodeValueFn) -{ - SECItem encodedValue; - SECStatus rv; - - encodedValue.data = NULL; - encodedValue.len = 0; - rv = (*EncodeValueFn)(arena, value, &encodedValue); - if (rv != SECSuccess) { - error_out("ERROR: Unable to encode extension value"); - } - rv = CERT_AddExtension(extHandle, extenType, &encodedValue, criticality, PR_TRUE); - return (rv); -} - -static SECStatus -AddKeyUsage(void *extHandle, - Pair *data) -{ - SECItem bitStringValue; - unsigned char keyUsage = 0x0; - - if (find_field_bool(data, "keyUsage-digitalSignature", PR_TRUE)) { - keyUsage |= (0x80 >> 0); - } - if (find_field_bool(data, "keyUsage-nonRepudiation", PR_TRUE)) { - keyUsage |= (0x80 >> 1); - } - if (find_field_bool(data, "keyUsage-keyEncipherment", PR_TRUE)) { - keyUsage |= (0x80 >> 2); - } - if (find_field_bool(data, "keyUsage-dataEncipherment", PR_TRUE)) { - keyUsage |= (0x80 >> 3); - } - if (find_field_bool(data, "keyUsage-keyAgreement", PR_TRUE)) { - keyUsage |= (0x80 >> 4); - } - if (find_field_bool(data, "keyUsage-keyCertSign", PR_TRUE)) { - keyUsage |= (0x80 >> 5); - } - if (find_field_bool(data, "keyUsage-cRLSign", PR_TRUE)) { - keyUsage |= (0x80 >> 6); - } - - bitStringValue.data = &keyUsage; - bitStringValue.len = 1; - - return (CERT_EncodeAndAddBitStrExtension(extHandle, SEC_OID_X509_KEY_USAGE, &bitStringValue, - (find_field_bool(data, "keyUsage-crit", PR_TRUE)))); -} - -static CERTOidSequence * -CreateOidSequence(void) -{ - CERTOidSequence *rv = (CERTOidSequence *)NULL; - PLArenaPool *arena = (PLArenaPool *)NULL; - - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if ((PLArenaPool *)NULL == arena) { - goto loser; - } - - rv = (CERTOidSequence *)PORT_ArenaZAlloc(arena, sizeof(CERTOidSequence)); - if ((CERTOidSequence *)NULL == rv) { - goto loser; - } - - rv->oids = (SECItem **)PORT_ArenaZAlloc(arena, sizeof(SECItem *)); - if ((SECItem **)NULL == rv->oids) { - goto loser; - } - - rv->arena = arena; - return rv; - -loser: - if ((PLArenaPool *)NULL != arena) { - PORT_FreeArena(arena, PR_FALSE); - } - - return (CERTOidSequence *)NULL; -} - -static SECStatus -AddOidToSequence(CERTOidSequence *os, SECOidTag oidTag) -{ - SECItem **oids; - PRUint32 count = 0; - SECOidData *od; - - od = SECOID_FindOIDByTag(oidTag); - if ((SECOidData *)NULL == od) { - return SECFailure; - } - - for (oids = os->oids; (SECItem *)NULL != *oids; oids++) { - count++; - } - - /* ArenaZRealloc */ - - { - PRUint32 i; - - oids = (SECItem **)PORT_ArenaZAlloc(os->arena, sizeof(SECItem *) * (count + 2)); - if ((SECItem **)NULL == oids) { - return SECFailure; - } - - for (i = 0; i < count; i++) { - oids[i] = os->oids[i]; - } - - /* ArenaZFree(os->oids); */ - } - - os->oids = oids; - os->oids[count] = &od->oid; - - return SECSuccess; -} - -static SECItem * -EncodeOidSequence(CERTOidSequence *os) -{ - SECItem *rv; - extern const SEC_ASN1Template CERT_OidSeqTemplate[]; - - rv = (SECItem *)PORT_ArenaZAlloc(os->arena, sizeof(SECItem)); - if ((SECItem *)NULL == rv) { - goto loser; - } - - if (!SEC_ASN1EncodeItem(os->arena, rv, os, CERT_OidSeqTemplate)) { - goto loser; - } - - return rv; - -loser: - return (SECItem *)NULL; -} - -static SECStatus -AddExtKeyUsage(void *extHandle, Pair *data) -{ - SECStatus rv; - CERTOidSequence *os; - SECItem *value; - PRBool crit; - - os = CreateOidSequence(); - if ((CERTOidSequence *)NULL == os) { - return SECFailure; - } - - if (find_field_bool(data, "extKeyUsage-serverAuth", PR_TRUE)) { - rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_SERVER_AUTH); - if (SECSuccess != rv) - goto loser; - } - - if (find_field_bool(data, "extKeyUsage-msTrustListSign", PR_TRUE)) { - rv = AddOidToSequence(os, SEC_OID_MS_EXT_KEY_USAGE_CTL_SIGNING); - if (SECSuccess != rv) - goto loser; - } - - if (find_field_bool(data, "extKeyUsage-clientAuth", PR_TRUE)) { - rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_CLIENT_AUTH); - if (SECSuccess != rv) - goto loser; - } - - if (find_field_bool(data, "extKeyUsage-codeSign", PR_TRUE)) { - rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_CODE_SIGN); - if (SECSuccess != rv) - goto loser; - } - - if (find_field_bool(data, "extKeyUsage-emailProtect", PR_TRUE)) { - rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_EMAIL_PROTECT); - if (SECSuccess != rv) - goto loser; - } - - if (find_field_bool(data, "extKeyUsage-timeStamp", PR_TRUE)) { - rv = AddOidToSequence(os, SEC_OID_EXT_KEY_USAGE_TIME_STAMP); - if (SECSuccess != rv) - goto loser; - } - - if (find_field_bool(data, "extKeyUsage-ocspResponder", PR_TRUE)) { - rv = AddOidToSequence(os, SEC_OID_OCSP_RESPONDER); - if (SECSuccess != rv) - goto loser; - } - - if (find_field_bool(data, "extKeyUsage-NS-govtApproved", PR_TRUE)) { - rv = AddOidToSequence(os, SEC_OID_NS_KEY_USAGE_GOVT_APPROVED); - if (SECSuccess != rv) - goto loser; - } - - value = EncodeOidSequence(os); - - crit = find_field_bool(data, "extKeyUsage-crit", PR_TRUE); - - rv = CERT_AddExtension(extHandle, SEC_OID_X509_EXT_KEY_USAGE, value, - crit, PR_TRUE); -/*FALLTHROUGH*/ -loser: - CERT_DestroyOidSequence(os); - return rv; -} - -static SECStatus -AddSubKeyID(void *extHandle, - Pair *data, - CERTCertificate *subjectCert) -{ - SECItem encodedValue; - SECStatus rv; - char *read; - char *write; - char *first; - char character; - int high_digit = 0, - low_digit = 0; - int len; - PRBool odd = PR_FALSE; - - encodedValue.data = NULL; - encodedValue.len = 0; - first = read = write = find_field(data, "subjectKeyIdentifier-text", - PR_TRUE); - len = PORT_Strlen(first); - odd = ((len % 2) != 0) ? PR_TRUE : PR_FALSE; - if (find_field_bool(data, "subjectKeyIdentifier-radio-hex", PR_TRUE)) { - if (odd) { - error_out("ERROR: Improperly formated subject key identifier, hex values must be expressed as an octet string"); - } - while (*read != '\0') { - if (!isxdigit(*read)) { - error_out("ERROR: Improperly formated subject key identifier"); - } - *read = toupper(*read); - if ((*read >= 'A') && (*read <= 'F')) { - high_digit = *read - 'A' + 10; - } else { - high_digit = *read - '0'; - } - ++read; - if (!isxdigit(*read)) { - error_out("ERROR: Improperly formated subject key identifier"); - } - *read = toupper(*read); - if ((*read >= 'A') && (*read <= 'F')) { - low_digit = *(read) - 'A' + 10; - } else { - low_digit = *(read) - '0'; - } - character = (high_digit << 4) | low_digit; - *write = character; - ++write; - ++read; - } - *write = '\0'; - len = write - first; - } - subjectCert->subjectKeyID.data = (unsigned char *)find_field(data, "subjectKeyIdentifier-text", PR_TRUE); - subjectCert->subjectKeyID.len = len; - rv = CERT_EncodeSubjectKeyID(NULL, &subjectCert->subjectKeyID, &encodedValue); - if (rv) { - return (rv); - } - return (CERT_AddExtension(extHandle, SEC_OID_X509_SUBJECT_KEY_ID, - &encodedValue, PR_FALSE, PR_TRUE)); -} - -static SECStatus -AddAuthKeyID(void *extHandle, - Pair *data, - char *issuerNameStr, - CERTCertDBHandle *handle) -{ - CERTAuthKeyID *authKeyID = NULL; - PLArenaPool *arena = NULL; - SECStatus rv = SECSuccess; - CERTCertificate *issuerCert = NULL; - CERTGeneralName *genNames; - CERTName *directoryName = NULL; - - issuerCert = CERT_FindCertByNameString(handle, issuerNameStr); - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if (!arena) { - error_allocate(); - } - - authKeyID = PORT_ArenaZAlloc(arena, sizeof(CERTAuthKeyID)); - if (authKeyID == NULL) { - error_allocate(); - } - if (find_field_bool(data, "authorityKeyIdentifier-radio-keyIdentifier", - PR_TRUE)) { - authKeyID->keyID.data = PORT_ArenaAlloc(arena, PORT_Strlen((char *)issuerCert->subjectKeyID.data)); - if (authKeyID->keyID.data == NULL) { - error_allocate(); - } - PORT_Memcpy(authKeyID->keyID.data, issuerCert->subjectKeyID.data, - authKeyID->keyID.len = - PORT_Strlen((char *)issuerCert->subjectKeyID.data)); - } else { - - PORT_Assert(arena); - genNames = (CERTGeneralName *)PORT_ArenaZAlloc(arena, (sizeof(CERTGeneralName))); - if (genNames == NULL) { - error_allocate(); - } - genNames->l.next = genNames->l.prev = &(genNames->l); - genNames->type = certDirectoryName; - - directoryName = CERT_AsciiToName(issuerCert->subjectName); - if (!directoryName) { - error_out("ERROR: Unable to create Directory Name"); - } - rv = CERT_CopyName(arena, &genNames->name.directoryName, - directoryName); - CERT_DestroyName(directoryName); - if (rv != SECSuccess) { - error_out("ERROR: Unable to copy Directory Name"); - } - authKeyID->authCertIssuer = genNames; - if (authKeyID->authCertIssuer == NULL && SECFailure == PORT_GetError()) { - error_out("ERROR: Unable to get Issuer General Name for Authority Key ID Extension"); - } - authKeyID->authCertSerialNumber = issuerCert->serialNumber; - } - rv = EncodeAndAddExtensionValue(arena, extHandle, authKeyID, PR_FALSE, - SEC_OID_X509_AUTH_KEY_ID, - (EXTEN_VALUE_ENCODER) - CERT_EncodeAuthKeyID); - if (arena) { - PORT_FreeArena(arena, PR_FALSE); - } - return (rv); -} - -static SECStatus -AddPrivKeyUsagePeriod(void *extHandle, - Pair *data, - CERTCertificate *cert) -{ - char *notBeforeStr; - char *notAfterStr; - PLArenaPool *arena = NULL; - SECStatus rv = SECSuccess; - CERTPrivKeyUsagePeriod *pkup; - - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if (!arena) { - error_allocate(); - } - pkup = PORT_ArenaZNew(arena, CERTPrivKeyUsagePeriod); - if (pkup == NULL) { - error_allocate(); - } - notBeforeStr = (char *)PORT_Alloc(16); - if (notBeforeStr == NULL) { - error_allocate(); - } - notAfterStr = (char *)PORT_Alloc(16); - if (notAfterStr == NULL) { - error_allocate(); - } - *notBeforeStr = '\0'; - *notAfterStr = '\0'; - pkup->arena = arena; - pkup->notBefore.len = 0; - pkup->notBefore.data = NULL; - pkup->notAfter.len = 0; - pkup->notAfter.data = NULL; - if (find_field_bool(data, "privKeyUsagePeriod-radio-notBefore", PR_TRUE) || - find_field_bool(data, "privKeyUsagePeriod-radio-both", PR_TRUE)) { - pkup->notBefore.len = 15; - pkup->notBefore.data = (unsigned char *)notBeforeStr; - if (find_field_bool(data, "privKeyUsagePeriod-notBefore-radio-manual", - PR_TRUE)) { - PORT_Strcat(notBeforeStr, find_field(data, - "privKeyUsagePeriod-notBefore-year", - PR_TRUE)); - PORT_Strcat(notBeforeStr, find_field(data, - "privKeyUsagePeriod-notBefore-month", - PR_TRUE)); - PORT_Strcat(notBeforeStr, find_field(data, - "privKeyUsagePeriod-notBefore-day", - PR_TRUE)); - PORT_Strcat(notBeforeStr, find_field(data, - "privKeyUsagePeriod-notBefore-hour", - PR_TRUE)); - PORT_Strcat(notBeforeStr, find_field(data, - "privKeyUsagePeriod-notBefore-minute", - PR_TRUE)); - PORT_Strcat(notBeforeStr, find_field(data, - "privKeyUsagePeriod-notBefore-second", - PR_TRUE)); - if ((*(notBeforeStr + 14) != '\0') || - (!isdigit(*(notBeforeStr + 13))) || - (*(notBeforeStr + 12) >= '5' && *(notBeforeStr + 12) <= '0') || - (!isdigit(*(notBeforeStr + 11))) || - (*(notBeforeStr + 10) >= '5' && *(notBeforeStr + 10) <= '0') || - (!isdigit(*(notBeforeStr + 9))) || - (*(notBeforeStr + 8) >= '2' && *(notBeforeStr + 8) <= '0') || - (!isdigit(*(notBeforeStr + 7))) || - (*(notBeforeStr + 6) >= '3' && *(notBeforeStr + 6) <= '0') || - (!isdigit(*(notBeforeStr + 5))) || - (*(notBeforeStr + 4) >= '1' && *(notBeforeStr + 4) <= '0') || - (!isdigit(*(notBeforeStr + 3))) || - (!isdigit(*(notBeforeStr + 2))) || - (!isdigit(*(notBeforeStr + 1))) || - (!isdigit(*(notBeforeStr + 0))) || - (*(notBeforeStr + 8) == '2' && *(notBeforeStr + 9) >= '4') || - (*(notBeforeStr + 6) == '3' && *(notBeforeStr + 7) >= '1') || - (*(notBeforeStr + 4) == '1' && *(notBeforeStr + 5) >= '2')) { - error_out("ERROR: Improperly formated private key usage period"); - } - *(notBeforeStr + 14) = 'Z'; - *(notBeforeStr + 15) = '\0'; - } else { - if ((*(cert->validity.notBefore.data) > '5') || - ((*(cert->validity.notBefore.data) == '5') && - (*(cert->validity.notBefore.data + 1) != '0'))) { - PORT_Strcat(notBeforeStr, "19"); - } else { - PORT_Strcat(notBeforeStr, "20"); - } - PORT_Strcat(notBeforeStr, (char *)cert->validity.notBefore.data); - } - } - if (find_field_bool(data, "privKeyUsagePeriod-radio-notAfter", PR_TRUE) || - find_field_bool(data, "privKeyUsagePeriod-radio-both", PR_TRUE)) { - pkup->notAfter.len = 15; - pkup->notAfter.data = (unsigned char *)notAfterStr; - PORT_Strcat(notAfterStr, find_field(data, "privKeyUsagePeriod-notAfter-year", - PR_TRUE)); - PORT_Strcat(notAfterStr, find_field(data, "privKeyUsagePeriod-notAfter-month", - PR_TRUE)); - PORT_Strcat(notAfterStr, find_field(data, "privKeyUsagePeriod-notAfter-day", - PR_TRUE)); - PORT_Strcat(notAfterStr, find_field(data, "privKeyUsagePeriod-notAfter-hour", - PR_TRUE)); - PORT_Strcat(notAfterStr, find_field(data, "privKeyUsagePeriod-notAfter-minute", - PR_TRUE)); - PORT_Strcat(notAfterStr, find_field(data, "privKeyUsagePeriod-notAfter-second", - PR_TRUE)); - if ((*(notAfterStr + 14) != '\0') || - (!isdigit(*(notAfterStr + 13))) || - (*(notAfterStr + 12) >= '5' && *(notAfterStr + 12) <= '0') || - (!isdigit(*(notAfterStr + 11))) || - (*(notAfterStr + 10) >= '5' && *(notAfterStr + 10) <= '0') || - (!isdigit(*(notAfterStr + 9))) || - (*(notAfterStr + 8) >= '2' && *(notAfterStr + 8) <= '0') || - (!isdigit(*(notAfterStr + 7))) || - (*(notAfterStr + 6) >= '3' && *(notAfterStr + 6) <= '0') || - (!isdigit(*(notAfterStr + 5))) || - (*(notAfterStr + 4) >= '1' && *(notAfterStr + 4) <= '0') || - (!isdigit(*(notAfterStr + 3))) || - (!isdigit(*(notAfterStr + 2))) || - (!isdigit(*(notAfterStr + 1))) || - (!isdigit(*(notAfterStr + 0))) || - (*(notAfterStr + 8) == '2' && *(notAfterStr + 9) >= '4') || - (*(notAfterStr + 6) == '3' && *(notAfterStr + 7) >= '1') || - (*(notAfterStr + 4) == '1' && *(notAfterStr + 5) >= '2')) { - error_out("ERROR: Improperly formated private key usage period"); - } - *(notAfterStr + 14) = 'Z'; - *(notAfterStr + 15) = '\0'; - } - - PORT_Assert(arena); - - rv = EncodeAndAddExtensionValue(arena, extHandle, pkup, - find_field_bool(data, - "privKeyUsagePeriod-crit", - PR_TRUE), - SEC_OID_X509_PRIVATE_KEY_USAGE_PERIOD, - (EXTEN_VALUE_ENCODER) - CERT_EncodePrivateKeyUsagePeriod); - PORT_FreeArena(arena, PR_FALSE); - PORT_Free(notBeforeStr); - PORT_Free(notAfterStr); - return (rv); -} - -static SECStatus -AddBasicConstraint(void *extHandle, - Pair *data) -{ - CERTBasicConstraints basicConstraint; - SECItem encodedValue; - SECStatus rv; - - encodedValue.data = NULL; - encodedValue.len = 0; - basicConstraint.pathLenConstraint = CERT_UNLIMITED_PATH_CONSTRAINT; - basicConstraint.isCA = (find_field_bool(data, "basicConstraints-cA-radio-CA", - PR_TRUE)); - if (find_field_bool(data, "basicConstraints-pathLengthConstraint", PR_TRUE)) { - basicConstraint.pathLenConstraint = atoi(find_field(data, "basicConstraints-pathLengthConstraint-text", - PR_TRUE)); - } - - rv = CERT_EncodeBasicConstraintValue(NULL, &basicConstraint, - &encodedValue); - if (rv) - return (rv); - rv = CERT_AddExtension(extHandle, SEC_OID_X509_BASIC_CONSTRAINTS, - &encodedValue, - (find_field_bool(data, "basicConstraints-crit", - PR_TRUE)), - PR_TRUE); - - PORT_Free(encodedValue.data); - return (rv); -} - -static SECStatus -AddNscpCertType(void *extHandle, - Pair *data) -{ - SECItem bitStringValue; - unsigned char CertType = 0x0; - - if (find_field_bool(data, "netscape-cert-type-ssl-client", PR_TRUE)) { - CertType |= (0x80 >> 0); - } - if (find_field_bool(data, "netscape-cert-type-ssl-server", PR_TRUE)) { - CertType |= (0x80 >> 1); - } - if (find_field_bool(data, "netscape-cert-type-smime", PR_TRUE)) { - CertType |= (0x80 >> 2); - } - if (find_field_bool(data, "netscape-cert-type-object-signing", PR_TRUE)) { - CertType |= (0x80 >> 3); - } - if (find_field_bool(data, "netscape-cert-type-reserved", PR_TRUE)) { - CertType |= (0x80 >> 4); - } - if (find_field_bool(data, "netscape-cert-type-ssl-ca", PR_TRUE)) { - CertType |= (0x80 >> 5); - } - if (find_field_bool(data, "netscape-cert-type-smime-ca", PR_TRUE)) { - CertType |= (0x80 >> 6); - } - if (find_field_bool(data, "netscape-cert-type-object-signing-ca", PR_TRUE)) { - CertType |= (0x80 >> 7); - } - - bitStringValue.data = &CertType; - bitStringValue.len = 1; - - return (CERT_EncodeAndAddBitStrExtension(extHandle, SEC_OID_NS_CERT_EXT_CERT_TYPE, &bitStringValue, - (find_field_bool(data, "netscape-cert-type-crit", PR_TRUE)))); -} - -static SECStatus -add_IA5StringExtension(void *extHandle, - char *string, - PRBool crit, - int idtag) -{ - SECItem encodedValue; - SECStatus rv; - - encodedValue.data = NULL; - encodedValue.len = 0; - - rv = CERT_EncodeIA5TypeExtension(NULL, string, &encodedValue); - if (rv) { - return (rv); - } - return (CERT_AddExtension(extHandle, idtag, &encodedValue, crit, PR_TRUE)); -} - -static SECItem * -string_to_oid(char *string) -{ - int i; - int length = 20; - int remaining; - int first_value; - int second_value; - int value; - int oidLength; - unsigned char *oidString; - unsigned char *write; - unsigned char *read; - unsigned char *temp; - SECItem *oid; - - remaining = length; - i = 0; - while (*string == ' ') { - string++; - } - while (isdigit(*(string + i))) { - i++; - } - if (*(string + i) == '.') { - *(string + i) = '\0'; - } else { - error_out("ERROR: Improperly formated OID"); - } - first_value = atoi(string); - if (first_value < 0 || first_value > 2) { - error_out("ERROR: Improperly formated OID"); - } - string += i + 1; - i = 0; - while (isdigit(*(string + i))) { - i++; - } - if (*(string + i) == '.') { - *(string + i) = '\0'; - } else { - error_out("ERROR: Improperly formated OID"); - } - second_value = atoi(string); - if (second_value < 0 || second_value > 39) { - error_out("ERROR: Improperly formated OID"); - } - oidString = PORT_ZAlloc(2); - *oidString = (first_value * 40) + second_value; - *(oidString + 1) = '\0'; - oidLength = 1; - string += i + 1; - i = 0; - temp = write = PORT_ZAlloc(length); - while (*string != '\0') { - value = 0; - while (isdigit(*(string + i))) { - i++; - } - if (*(string + i) == '\0') { - value = atoi(string); - string += i; - } else { - if (*(string + i) == '.') { - *(string + i) = '\0'; - value = atoi(string); - string += i + 1; - } else { - *(string + i) = '\0'; - i++; - value = atoi(string); - while (*(string + i) == ' ') - i++; - if (*(string + i) != '\0') { - error_out("ERROR: Improperly formated OID"); - } - } - } - i = 0; - while (value != 0) { - if (remaining < 1) { - remaining += length; - length = length * 2; - temp = PORT_Realloc(temp, length); - write = temp + length - remaining; - } - *write = (value & 0x7f) | (0x80); - write++; - remaining--; - value = value >> 7; - } - *temp = *temp & (0x7f); - oidLength += write - temp; - oidString = PORT_Realloc(oidString, (oidLength + 1)); - read = write - 1; - write = oidLength + oidString - 1; - for (i = 0; i < (length - remaining); i++) { - *write = *read; - write--; - read++; - } - write = temp; - remaining = length; - } - *(oidString + oidLength) = '\0'; - oid = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); - oid->data = oidString; - oid->len = oidLength; - PORT_Free(temp); - return oid; -} - -static SECItem * -string_to_ipaddress(char *string) -{ - int i = 0; - int value; - int j = 0; - SECItem *ipaddress; - - while (*string == ' ') { - string++; - } - ipaddress = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); - ipaddress->data = PORT_ZAlloc(9); - while (*string != '\0' && j < 8) { - while (isdigit(*(string + i))) { - i++; - } - if (*(string + i) == '.') { - *(string + i) = '\0'; - value = atoi(string); - string = string + i + 1; - i = 0; - } else { - if (*(string + i) == '\0') { - value = atoi(string); - string = string + i; - i = 0; - } else { - *(string + i) = '\0'; - while (*(string + i) == ' ') { - i++; - } - if (*(string + i) == '\0') { - value = atoi(string); - string = string + i; - i = 0; - } else { - error_out("ERROR: Improperly formated IP Address"); - } - } - } - if (value >= 0 && value < 256) { - *(ipaddress->data + j) = value; - } else { - error_out("ERROR: Improperly formated IP Address"); - } - j++; - } - *(ipaddress->data + j) = '\0'; - if (j != 4 && j != 8) { - error_out("ERROR: Improperly formated IP Address"); - } - ipaddress->len = j; - return ipaddress; -} - -static int -chr_to_hex(char c) -{ - if (isdigit(c)) { - return c - '0'; - } - if (isxdigit(c)) { - return toupper(c) - 'A' + 10; - } - return -1; -} - -static SECItem * -string_to_binary(char *string) -{ - SECItem *rv; - - rv = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); - if (rv == NULL) { - error_allocate(); - } - rv->data = (unsigned char *)PORT_ZAlloc((PORT_Strlen(string)) / 3 + 2); - rv->len = 0; - while (*string && !isxdigit(*string)) { - string++; - } - while (*string) { - int high, low; - high = chr_to_hex(*string++); - low = chr_to_hex(*string++); - if (high < 0 || low < 0) { - error_out("ERROR: Improperly formated binary encoding"); - } - rv->data[(rv->len)++] = high << 4 | low; - if (*string != ':') { - break; - } - ++string; - } - while (*string == ' ') { - ++string; - } - if (*string) { - error_out("ERROR: Junk after binary encoding"); - } - - return rv; -} - -static SECStatus -MakeGeneralName(char *name, - CERTGeneralName *genName, - PLArenaPool *arena) -{ - SECItem *oid; - SECOidData *oidData; - SECItem *ipaddress; - SECItem *temp = NULL; - int i; - int nameType; - PRBool binary = PR_FALSE; - SECStatus rv = SECSuccess; - PRBool nickname = PR_FALSE; - - PORT_Assert(genName); - PORT_Assert(arena); - nameType = *(name + PORT_Strlen(name) - 1) - '0'; - if (nameType == 0 && *(name + PORT_Strlen(name) - 2) == '1') { - nickname = PR_TRUE; - nameType = certOtherName; - } - if (nameType < 1 || nameType > 9) { - error_out("ERROR: Unknown General Name Type"); - } - *(name + PORT_Strlen(name) - 4) = '\0'; - genName->type = nameType; - - switch (genName->type) { - case certURI: - case certRFC822Name: - case certDNSName: { - genName->name.other.data = (unsigned char *)name; - genName->name.other.len = PORT_Strlen(name); - break; - } - - case certIPAddress: { - ipaddress = string_to_ipaddress(name); - genName->name.other.data = ipaddress->data; - genName->name.other.len = ipaddress->len; - break; - } - - case certRegisterID: { - oid = string_to_oid(name); - genName->name.other.data = oid->data; - genName->name.other.len = oid->len; - break; - } - - case certEDIPartyName: - case certX400Address: { - - genName->name.other.data = PORT_ArenaAlloc(arena, - PORT_Strlen(name) + 2); - if (genName->name.other.data == NULL) { - error_allocate(); - } - - PORT_Memcpy(genName->name.other.data + 2, name, PORT_Strlen(name)); - /* This may not be accurate for all cases. - For now, use this tag type */ - genName->name.other.data[0] = (char)(((genName->type - 1) & - 0x1f) | - 0x80); - genName->name.other.data[1] = (char)PORT_Strlen(name); - genName->name.other.len = PORT_Strlen(name) + 2; - break; - } - - case certOtherName: { - i = 0; - if (!nickname) { - while (!isdigit(*(name + PORT_Strlen(name) - i))) { - i++; - } - if (*(name + PORT_Strlen(name) - i) == '1') { - binary = PR_TRUE; - } else { - binary = PR_FALSE; - } - while (*(name + PORT_Strlen(name) - i) != '-') { - i++; - } - *(name + PORT_Strlen(name) - i - 1) = '\0'; - i = 0; - while (*(name + i) != '-') { - i++; - } - *(name + i - 1) = '\0'; - oid = string_to_oid(name + i + 2); - } else { - oidData = SECOID_FindOIDByTag(SEC_OID_NETSCAPE_NICKNAME); - oid = &oidData->oid; - while (*(name + PORT_Strlen(name) - i) != '-') { - i++; - } - *(name + PORT_Strlen(name) - i) = '\0'; - } - genName->name.OthName.oid.data = oid->data; - genName->name.OthName.oid.len = oid->len; - if (binary) { - temp = string_to_binary(name); - genName->name.OthName.name.data = temp->data; - genName->name.OthName.name.len = temp->len; - } else { - temp = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); - if (temp == NULL) { - error_allocate(); - } - temp->data = (unsigned char *)name; - temp->len = PORT_Strlen(name); - SEC_ASN1EncodeItem(arena, &(genName->name.OthName.name), temp, - CERTIA5TypeTemplate); - } - PORT_Free(temp); - break; - } - - case certDirectoryName: { - CERTName *directoryName = NULL; - - directoryName = CERT_AsciiToName(name); - if (!directoryName) { - error_out("ERROR: Improperly formated alternative name"); - break; - } - rv = CERT_CopyName(arena, &genName->name.directoryName, - directoryName); - CERT_DestroyName(directoryName); - - break; - } - } - genName->l.next = &(genName->l); - genName->l.prev = &(genName->l); - return rv; -} - -static CERTGeneralName * -MakeAltName(Pair *data, - char *which, - PLArenaPool *arena) -{ - CERTGeneralName *SubAltName; - CERTGeneralName *current; - CERTGeneralName *newname; - char *name = NULL; - SECStatus rv = SECSuccess; - int len; - - len = PORT_Strlen(which); - name = find_field(data, which, PR_TRUE); - SubAltName = current = (CERTGeneralName *)PORT_ZAlloc(sizeof(CERTGeneralName)); - if (current == NULL) { - error_allocate(); - } - while (name != NULL) { - - rv = MakeGeneralName(name, current, arena); - - if (rv != SECSuccess) { - break; - } - if (*(which + len - 1) < '9') { - *(which + len - 1) = *(which + len - 1) + 1; - } else { - if (isdigit(*(which + len - 2))) { - *(which + len - 2) = *(which + len - 2) + 1; - *(which + len - 1) = '0'; - } else { - *(which + len - 1) = '1'; - *(which + len) = '0'; - *(which + len + 1) = '\0'; - len++; - } - } - len = PORT_Strlen(which); - name = find_field(data, which, PR_TRUE); - if (name != NULL) { - newname = (CERTGeneralName *)PORT_ZAlloc(sizeof(CERTGeneralName)); - if (newname == NULL) { - error_allocate(); - } - current->l.next = &(newname->l); - newname->l.prev = &(current->l); - current = newname; - newname = NULL; - } else { - current->l.next = &(SubAltName->l); - SubAltName->l.prev = &(current->l); - } - } - if (rv == SECFailure) { - return NULL; - } - return SubAltName; -} - -static CERTNameConstraints * -MakeNameConstraints(Pair *data, - PLArenaPool *arena) -{ - CERTNameConstraints *NameConstraints; - CERTNameConstraint *current = NULL; - CERTNameConstraint *last_permited = NULL; - CERTNameConstraint *last_excluded = NULL; - char *constraint = NULL; - char *which; - SECStatus rv = SECSuccess; - int len; - int i; - long max; - long min; - PRBool permited; - - NameConstraints = (CERTNameConstraints *)PORT_ZAlloc(sizeof(CERTNameConstraints)); - which = make_copy_string("NameConstraintSelect0", 25, '\0'); - len = PORT_Strlen(which); - constraint = find_field(data, which, PR_TRUE); - NameConstraints->permited = NameConstraints->excluded = NULL; - while (constraint != NULL) { - current = (CERTNameConstraint *)PORT_ZAlloc(sizeof(CERTNameConstraint)); - if (current == NULL) { - error_allocate(); - } - i = 0; - while (*(constraint + PORT_Strlen(constraint) - i) != '-') { - i++; - } - *(constraint + PORT_Strlen(constraint) - i - 1) = '\0'; - max = (long)atoi(constraint + PORT_Strlen(constraint) + 3); - if (max > 0) { - (void)SEC_ASN1EncodeInteger(arena, ¤t->max, max); - } - i = 0; - while (*(constraint + PORT_Strlen(constraint) - i) != '-') { - i++; - } - *(constraint + PORT_Strlen(constraint) - i - 1) = '\0'; - min = (long)atoi(constraint + PORT_Strlen(constraint) + 3); - (void)SEC_ASN1EncodeInteger(arena, ¤t->min, min); - while (*(constraint + PORT_Strlen(constraint) - i) != '-') { - i++; - } - *(constraint + PORT_Strlen(constraint) - i - 1) = '\0'; - if (*(constraint + PORT_Strlen(constraint) + 3) == 'p') { - permited = PR_TRUE; - } else { - permited = PR_FALSE; - } - rv = MakeGeneralName(constraint, &(current->name), arena); - - if (rv != SECSuccess) { - break; - } - if (*(which + len - 1) < '9') { - *(which + len - 1) = *(which + len - 1) + 1; - } else { - if (isdigit(*(which + len - 2))) { - *(which + len - 2) = *(which + len - 2) + 1; - *(which + len - 1) = '0'; - } else { - *(which + len - 1) = '1'; - *(which + len) = '0'; - *(which + len + 1) = '\0'; - len++; - } - } - len = PORT_Strlen(which); - if (permited) { - if (NameConstraints->permited == NULL) { - NameConstraints->permited = last_permited = current; - } - last_permited->l.next = &(current->l); - current->l.prev = &(last_permited->l); - last_permited = current; - } else { - if (NameConstraints->excluded == NULL) { - NameConstraints->excluded = last_excluded = current; - } - last_excluded->l.next = &(current->l); - current->l.prev = &(last_excluded->l); - last_excluded = current; - } - constraint = find_field(data, which, PR_TRUE); - if (constraint != NULL) { - current = (CERTNameConstraint *)PORT_ZAlloc(sizeof(CERTNameConstraint)); - if (current == NULL) { - error_allocate(); - } - } - } - if (NameConstraints->permited != NULL) { - last_permited->l.next = &(NameConstraints->permited->l); - NameConstraints->permited->l.prev = &(last_permited->l); - } - if (NameConstraints->excluded != NULL) { - last_excluded->l.next = &(NameConstraints->excluded->l); - NameConstraints->excluded->l.prev = &(last_excluded->l); - } - if (which != NULL) { - PORT_Free(which); - } - if (rv == SECFailure) { - return NULL; - } - return NameConstraints; -} - -static SECStatus -AddAltName(void *extHandle, - Pair *data, - char *issuerNameStr, - CERTCertDBHandle *handle, - int type) -{ - PRBool autoIssuer = PR_FALSE; - PLArenaPool *arena = NULL; - CERTGeneralName *genName = NULL; - char *which = NULL; - char *name = NULL; - SECStatus rv = SECSuccess; - SECItem *issuersAltName = NULL; - CERTCertificate *issuerCert = NULL; - - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if (arena == NULL) { - error_allocate(); - } - if (type == 0) { - which = make_copy_string("SubAltNameSelect0", 20, '\0'); - genName = MakeAltName(data, which, arena); - } else { - if (autoIssuer) { - autoIssuer = find_field_bool(data, "IssuerAltNameSourceRadio-auto", - PR_TRUE); - issuerCert = CERT_FindCertByNameString(handle, issuerNameStr); - rv = cert_FindExtension((*issuerCert).extensions, - SEC_OID_X509_SUBJECT_ALT_NAME, - issuersAltName); - if (issuersAltName == NULL) { - name = PORT_Alloc(PORT_Strlen((*issuerCert).subjectName) + 4); - PORT_Strcpy(name, (*issuerCert).subjectName); - PORT_Strcat(name, " - 5"); - } - } else { - which = make_copy_string("IssuerAltNameSelect0", 20, '\0'); - genName = MakeAltName(data, which, arena); - } - } - if (type == 0) { - EncodeAndAddExtensionValue(arena, extHandle, genName, - find_field_bool(data, "SubAltName-crit", - PR_TRUE), - SEC_OID_X509_SUBJECT_ALT_NAME, - (EXTEN_VALUE_ENCODER) - CERT_EncodeAltNameExtension); - - } else { - if (autoIssuer && (name == NULL)) { - rv = CERT_AddExtension(extHandle, SEC_OID_X509_ISSUER_ALT_NAME, issuersAltName, - find_field_bool(data, "IssuerAltName-crit", PR_TRUE), PR_TRUE); - } else { - EncodeAndAddExtensionValue(arena, extHandle, genName, - find_field_bool(data, - "IssuerAltName-crit", - PR_TRUE), - SEC_OID_X509_ISSUER_ALT_NAME, - (EXTEN_VALUE_ENCODER) - CERT_EncodeAltNameExtension); - } - } - if (which != NULL) { - PORT_Free(which); - } - if (issuerCert != NULL) { - CERT_DestroyCertificate(issuerCert); - } - return rv; -} - -static SECStatus -AddNameConstraints(void *extHandle, - Pair *data) -{ - PLArenaPool *arena = NULL; - CERTNameConstraints *constraints = NULL; - SECStatus rv = SECSuccess; - - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if (arena == NULL) { - error_allocate(); - } - constraints = MakeNameConstraints(data, arena); - if (constraints != NULL) { - EncodeAndAddExtensionValue(arena, extHandle, constraints, PR_TRUE, - SEC_OID_X509_NAME_CONSTRAINTS, - (EXTEN_VALUE_ENCODER) - CERT_EncodeNameConstraintsExtension); - } - if (arena != NULL) { - PORT_ArenaRelease(arena, NULL); - } - return rv; -} - -static SECStatus -add_extensions(CERTCertificate *subjectCert, - Pair *data, - char *issuerNameStr, - CERTCertDBHandle *handle) -{ - void *extHandle; - SECStatus rv = SECSuccess; - - extHandle = CERT_StartCertExtensions(subjectCert); - if (extHandle == NULL) { - error_out("ERROR: Unable to get certificates extension handle"); - } - if (find_field_bool(data, "keyUsage", PR_TRUE)) { - rv = AddKeyUsage(extHandle, data); - if (rv != SECSuccess) { - error_out("ERROR: Unable to add Key Usage extension"); - } - } - - if (find_field_bool(data, "extKeyUsage", PR_TRUE)) { - rv = AddExtKeyUsage(extHandle, data); - if (SECSuccess != rv) { - error_out("ERROR: Unable to add Extended Key Usage extension"); - } - } - - if (find_field_bool(data, "basicConstraints", PR_TRUE)) { - rv = AddBasicConstraint(extHandle, data); - if (rv != SECSuccess) { - error_out("ERROR: Unable to add Basic Constraint extension"); - } - } - if (find_field_bool(data, "subjectKeyIdentifier", PR_TRUE)) { - rv = AddSubKeyID(extHandle, data, subjectCert); - if (rv != SECSuccess) { - error_out("ERROR: Unable to add Subject Key Identifier Extension"); - } - } - if (find_field_bool(data, "authorityKeyIdentifier", PR_TRUE)) { - rv = AddAuthKeyID(extHandle, data, issuerNameStr, handle); - if (rv != SECSuccess) { - error_out("ERROR: Unable to add Authority Key Identifier extension"); - } - } - if (find_field_bool(data, "privKeyUsagePeriod", PR_TRUE)) { - rv = AddPrivKeyUsagePeriod(extHandle, data, subjectCert); - if (rv != SECSuccess) { - error_out("ERROR: Unable to add Private Key Usage Period extension"); - } - } - if (find_field_bool(data, "SubAltName", PR_TRUE)) { - rv = AddAltName(extHandle, data, NULL, NULL, 0); - if (rv != SECSuccess) { - error_out("ERROR: Unable to add Subject Alternative Name extension"); - } - } - if (find_field_bool(data, "IssuerAltName", PR_TRUE)) { - rv = AddAltName(extHandle, data, issuerNameStr, handle, 1); - if (rv != SECSuccess) { - error_out("ERROR: Unable to add Issuer Alternative Name Extension"); - } - } - if (find_field_bool(data, "NameConstraints", PR_TRUE)) { - rv = AddNameConstraints(extHandle, data); - if (rv != SECSuccess) { - error_out("ERROR: Unable to add Name Constraints Extension"); - } - } - if (find_field_bool(data, "netscape-cert-type", PR_TRUE)) { - rv = AddNscpCertType(extHandle, data); - if (rv != SECSuccess) { - error_out("ERROR: Unable to add Netscape Certificate Type Extension"); - } - } - if (find_field_bool(data, "netscape-base-url", PR_TRUE)) { - rv = add_IA5StringExtension(extHandle, - find_field(data, "netscape-base-url-text", - PR_TRUE), - find_field_bool(data, - "netscape-base-url-crit", - PR_TRUE), - SEC_OID_NS_CERT_EXT_BASE_URL); - if (rv != SECSuccess) { - error_out("ERROR: Unable to add Netscape Base URL Extension"); - } - } - if (find_field_bool(data, "netscape-revocation-url", PR_TRUE)) { - rv = add_IA5StringExtension(extHandle, - find_field(data, - "netscape-revocation-url-text", - PR_TRUE), - find_field_bool(data, "netscape-revocation-url-crit", - PR_TRUE), - SEC_OID_NS_CERT_EXT_REVOCATION_URL); - if (rv != SECSuccess) { - error_out("ERROR: Unable to add Netscape Revocation URL Extension"); - } - } - if (find_field_bool(data, "netscape-ca-revocation-url", PR_TRUE)) { - rv = add_IA5StringExtension(extHandle, - find_field(data, - "netscape-ca-revocation-url-text", - PR_TRUE), - find_field_bool(data, "netscape-ca-revocation-url-crit", PR_TRUE), - SEC_OID_NS_CERT_EXT_CA_REVOCATION_URL); - if (rv != SECSuccess) { - error_out("ERROR: Unable to add Netscape CA Revocation URL Extension"); - } - } - if (find_field_bool(data, "netscape-cert-renewal-url", PR_TRUE)) { - rv = add_IA5StringExtension(extHandle, - find_field(data, - "netscape-cert-renewal-url-text", - PR_TRUE), - find_field_bool(data, "netscape-cert-renewal-url-crit", - PR_TRUE), - SEC_OID_NS_CERT_EXT_CERT_RENEWAL_URL); - if (rv != SECSuccess) { - error_out("ERROR: Unable to add Netscape Certificate Renewal URL Extension"); - } - } - if (find_field_bool(data, "netscape-ca-policy-url", PR_TRUE)) { - rv = add_IA5StringExtension(extHandle, - find_field(data, - "netscape-ca-policy-url-text", - PR_TRUE), - find_field_bool(data, "netscape-ca-policy-url-crit", - PR_TRUE), - SEC_OID_NS_CERT_EXT_CA_POLICY_URL); - if (rv != SECSuccess) { - error_out("ERROR: Unable to add Netscape CA Policy URL Extension"); - } - } - if (find_field_bool(data, "netscape-ssl-server-name", PR_TRUE)) { - rv = add_IA5StringExtension(extHandle, - find_field(data, - "netscape-ssl-server-name-text", - PR_TRUE), - find_field_bool(data, "netscape-ssl-server-name-crit", - PR_TRUE), - SEC_OID_NS_CERT_EXT_SSL_SERVER_NAME); - if (rv != SECSuccess) { - error_out("ERROR: Unable to add Netscape SSL Server Name Extension"); - } - } - if (find_field_bool(data, "netscape-comment", PR_TRUE)) { - rv = add_IA5StringExtension(extHandle, - find_field(data, "netscape-comment-text", - PR_TRUE), - find_field_bool(data, - "netscape-comment-crit", - PR_TRUE), - SEC_OID_NS_CERT_EXT_COMMENT); - if (rv != SECSuccess) { - error_out("ERROR: Unable to add Netscape Comment Extension"); - } - } - CERT_FinishExtensions(extHandle); - return (rv); -} - -char * -return_dbpasswd(PK11SlotInfo *slot, PRBool retry, void *data) -{ - char *rv; - - /* don't clobber our poor smart card */ - if (retry == PR_TRUE) { - return NULL; - } - rv = PORT_Alloc(4); - PORT_Strcpy(rv, "foo"); - return rv; -} - -SECKEYPrivateKey * -FindPrivateKeyFromNameStr(char *name, - CERTCertDBHandle *certHandle) -{ - SECKEYPrivateKey *key; - CERTCertificate *cert; - CERTCertificate *p11Cert; - - /* We don't presently have a PK11 function to find a cert by - ** subject name. - ** We do have a function to find a cert in the internal slot's - ** cert db by subject name, but it doesn't setup the slot info. - ** So, this HACK works, but should be replaced as soon as we - ** have a function to search for certs accross slots by subject name. - */ - cert = CERT_FindCertByNameString(certHandle, name); - if (cert == NULL || cert->nickname == NULL) { - error_out("ERROR: Unable to retrieve issuers certificate"); - } - p11Cert = PK11_FindCertFromNickname(cert->nickname, NULL); - if (p11Cert == NULL) { - error_out("ERROR: Unable to retrieve issuers certificate"); - } - key = PK11_FindKeyByAnyCert(p11Cert, NULL); - return key; -} - -static SECItem * -SignCert(CERTCertificate *cert, - char *issuerNameStr, - Pair *data, - CERTCertDBHandle *handle, - int which_key) -{ - SECItem der; - SECKEYPrivateKey *caPrivateKey = NULL; - SECStatus rv; - PLArenaPool *arena; - SECOidTag algID; - - if (which_key == 0) { - caPrivateKey = FindPrivateKeyFromNameStr(issuerNameStr, handle); - } else { - caPrivateKey = privkeys[which_key - 1]; - } - if (caPrivateKey == NULL) { - error_out("ERROR: unable to retrieve issuers key"); - } - - arena = cert->arena; - - algID = SEC_GetSignatureAlgorithmOidTag(caPrivateKey->keyType, - SEC_OID_UNKNOWN); - if (algID == SEC_OID_UNKNOWN) { - error_out("ERROR: Unknown key type for issuer."); - goto done; - } - - rv = SECOID_SetAlgorithmID(arena, &cert->signature, algID, 0); - if (rv != SECSuccess) { - error_out("ERROR: Could not set signature algorithm id."); - } - - if (find_field_bool(data, "ver-1", PR_TRUE)) { - *(cert->version.data) = 0; - cert->version.len = 1; - } else { - *(cert->version.data) = 2; - cert->version.len = 1; - } - der.data = NULL; - der.len = 0; - (void)SEC_ASN1EncodeItem(arena, &der, cert, CERT_CertificateTemplate); - if (der.data == NULL) { - error_out("ERROR: Could not encode certificate.\n"); - } - rv = SEC_DerSignData(arena, &(cert->derCert), der.data, der.len, caPrivateKey, - algID); - if (rv != SECSuccess) { - error_out("ERROR: Could not sign encoded certificate data.\n"); - } -done: - SECKEY_DestroyPrivateKey(caPrivateKey); - return &(cert->derCert); -} - -int -main(int argc, char **argv) -{ - int length = 500; - int remaining = 500; - int n; - int i; - int serial; - int chainLen; - int which_key; - char *pos; -#ifdef OFFLINE - char *form_output = "key=MIIBPTCBpzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA7" - "SLqjWBL9Wl11Vlg%0AaMqZCvcQOL%2FnvSqYPPRP0XZy9SoAeyWzQnBOiCm2t8H5mK7r2" - "jnKdAQOmfhjaJil%0A3hNVu3SekHOXF6Ze7bkWa6%2FSGVcY%2FojkydxFSgY43nd1iyd" - "zPQDp8WWLL%2BpVpt%2B%2B%0ATRhFtVXbF0fQI03j9h3BoTgP2lkCAwEAARYDZm9vMA0" - "GCSqGSIb3DQEBBAUAA4GB%0AAJ8UfRKJ0GtG%2B%2BufCC6tAfTzKrq3CTBHnom55EyXc" - "sAsv6WbDqI%2F0rLAPkn2Xo1r%0AnNhtMxIuj441blMt%2Fa3AGLOy5zmC7Qawt8IytvQ" - "ikQ1XTpTBCXevytrmLjCmlURr%0ANJryTM48WaMQHiMiJpbXCqVJC1d%2FpEWBtqvALzZ" - "aOOIy&subject=CN%3D%22test%22%26serial-auto%3Dtrue%26serial_value%3D%" - "26ver-1%3Dtrue%26ver-3%3Dfalse%26caChoiceradio-SignWithDefaultkey%3Dt" - "rue%26caChoiceradio-SignWithRandomChain%3Dfalse%26autoCAs%3D%26caChoi" - "ceradio-SignWithSpecifiedChain%3Dfalse%26manCAs%3D%26%24"; -#else - char *form_output; -#endif - char *issuerNameStr; - char *certName; - char *DBdir = DB_DIRECTORY; - char *prefixs[10] = { "CA#1-", "CA#2-", "CA#3-", - "CA#4-", "CA#5-", "CA#6-", - "CA#7-", "CA#8-", "CA#9-", "" }; - Pair *form_data; - CERTCertificate *cert; - CERTCertDBHandle *handle; - CERTCertificateRequest *certReq = NULL; - int warpmonths = 0; - SECItem *certDER; -#ifdef FILEOUT - FILE *outfile; -#endif - SECStatus status = SECSuccess; - extern char prefix[PREFIX_LEN]; - SEC_PKCS7ContentInfo *certChain; - SECItem *encodedCertChain; - PRBool UChain = PR_FALSE; - - progName = strrchr(argv[0], '/'); - progName = progName ? progName + 1 : argv[0]; - -#ifdef TEST - sleep(20); -#endif - SECU_ConfigDirectory(DBdir); - - PK11_SetPasswordFunc(return_dbpasswd); - status = NSS_InitReadWrite(DBdir); - if (status != SECSuccess) { - SECU_PrintPRandOSError(progName); - return -1; - } - handle = CERT_GetDefaultCertDB(); - - prefix[0] = '\0'; -#if !defined(OFFLINE) - form_output = (char *)PORT_Alloc(length); - if (form_output == NULL) { - error_allocate(); - } - pos = form_output; - while (feof(stdin) == 0) { - if (remaining <= 1) { - remaining += length; - length = length * 2; - form_output = PORT_Realloc(form_output, (length)); - if (form_output == NULL) { - error_allocate(); - } - pos = form_output + length - remaining; - } - n = fread(pos, 1, (size_t)(remaining - 1), stdin); - pos += n; - remaining -= n; - } - *pos = '&'; - pos++; - length = pos - form_output; -#else - length = PORT_Strlen(form_output); -#endif -#ifdef FILEOUT - printf("Content-type: text/plain\n\n"); - fwrite(form_output, 1, (size_t)length, stdout); - printf("\n"); -#endif -#ifdef FILEOUT - fwrite(form_output, 1, (size_t)length, stdout); - printf("\n"); - fflush(stdout); -#endif - form_data = make_datastruct(form_output, length); - status = clean_input(form_data); -#if !defined(OFFLINE) - PORT_Free(form_output); -#endif -#ifdef FILEOUT - i = 0; - while (return_name(form_data, i) != NULL) { - printf("%s", return_name(form_data, i)); - printf("=\n"); - printf("%s", return_data(form_data, i)); - printf("\n"); - i++; - } - printf("I got that done, woo hoo\n"); - fflush(stdout); -#endif - issuerNameStr = PORT_Alloc(200); - if (find_field_bool(form_data, "caChoiceradio-SignWithSpecifiedChain", - PR_FALSE)) { - UChain = PR_TRUE; - chainLen = atoi(find_field(form_data, "manCAs", PR_FALSE)); - PORT_Strcpy(prefix, prefixs[0]); - issuerNameStr = PORT_Strcpy(issuerNameStr, - "CN=Cert-O-Matic II, O=Cert-O-Matic II"); - if (chainLen == 0) { - UChain = PR_FALSE; - } - } else { - if (find_field_bool(form_data, "caChoiceradio-SignWithRandomChain", - PR_FALSE)) { - PORT_Strcpy(prefix, prefixs[9]); - chainLen = atoi(find_field(form_data, "autoCAs", PR_FALSE)); - if (chainLen < 1 || chainLen > 18) { - issuerNameStr = PORT_Strcpy(issuerNameStr, - "CN=CA18, O=Cert-O-Matic II"); - } - issuerNameStr = PORT_Strcpy(issuerNameStr, "CN=CA"); - issuerNameStr = PORT_Strcat(issuerNameStr, - find_field(form_data, "autoCAs", PR_FALSE)); - issuerNameStr = PORT_Strcat(issuerNameStr, ", O=Cert-O-Matic II"); - } else { - issuerNameStr = PORT_Strcpy(issuerNameStr, - "CN=Cert-O-Matic II, O=Cert-O-Matic II"); - } - chainLen = 0; - } - - i = -1; - which_key = 0; - do { - extern SECStatus cert_GetKeyID(CERTCertificate * cert); - i++; - if (i != 0 && UChain) { - PORT_Strcpy(prefix, prefixs[i]); - } - /* find_field(form_data,"subject", PR_TRUE); */ - certReq = makeCertReq(form_data, which_key); -#ifdef OFFLINE - serial = 900; -#else - serial = get_serial_number(form_data); -#endif - cert = MakeV1Cert(handle, certReq, issuerNameStr, PR_FALSE, - serial, warpmonths, form_data); - if (certReq != NULL) { - CERT_DestroyCertificateRequest(certReq); - } - if (find_field_bool(form_data, "ver-3", PR_TRUE)) { - status = add_extensions(cert, form_data, issuerNameStr, handle); - if (status != SECSuccess) { - error_out("ERROR: Unable to add extensions"); - } - } - status = cert_GetKeyID(cert); - if (status == SECFailure) { - error_out("ERROR: Unable to get Key ID."); - } - certDER = SignCert(cert, issuerNameStr, form_data, handle, which_key); - CERT_NewTempCertificate(handle, certDER, NULL, PR_FALSE, PR_TRUE); - issuerNameStr = find_field(form_data, "subject", PR_TRUE); - /* SECITEM_FreeItem(certDER, PR_TRUE); */ - CERT_DestroyCertificate(cert); - if (i == (chainLen - 1)) { - i = 8; - } - ++which_key; - } while (i < 9 && UChain); - -#ifdef FILEOUT - outfile = fopen("../certout", "wb"); -#endif - certName = find_field(form_data, "subject", PR_FALSE); - cert = CERT_FindCertByNameString(handle, certName); - certChain = SEC_PKCS7CreateCertsOnly(cert, PR_TRUE, handle); - if (certChain == NULL) { - error_out("ERROR: No certificates in cert chain"); - } - encodedCertChain = SEC_PKCS7EncodeItem(NULL, NULL, certChain, NULL, NULL, - NULL); - if (encodedCertChain) { -#if !defined(FILEOUT) - printf("Content-type: application/x-x509-user-cert\r\n"); - printf("Content-length: %d\r\n\r\n", encodedCertChain->len); - fwrite(encodedCertChain->data, 1, encodedCertChain->len, stdout); -#else - fwrite(encodedCertChain->data, 1, encodedCertChain->len, outfile); -#endif - - } else { - error_out("Error: Unable to DER encode certificate"); - } -#ifdef FILEOUT - printf("\nI got here!\n"); - fflush(outfile); - fclose(outfile); -#endif - fflush(stdout); - if (NSS_Shutdown() != SECSuccess) { - exit(1); - } - return 0; -} diff --git a/security/nss/cmd/certcgi/certcgi.gyp b/security/nss/cmd/certcgi/certcgi.gyp deleted file mode 100644 index 5ad2893e0..000000000 --- a/security/nss/cmd/certcgi/certcgi.gyp +++ /dev/null @@ -1,33 +0,0 @@ -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. -{ - 'includes': [ - '../../coreconf/config.gypi', - '../../cmd/platlibs.gypi' - ], - 'targets': [ - { - 'target_name': 'certcgi', - 'type': 'executable', - 'sources': [ - 'certcgi.c' - ], - 'dependencies': [ - '<(DEPTH)/exports.gyp:dbm_exports', - '<(DEPTH)/exports.gyp:nss_exports', - '<(DEPTH)/lib/sqlite/sqlite.gyp:sqlite3' - ] - } - ], - 'target_defaults': { - 'defines': [ - 'NSPR20', - 'NSS_USE_STATIC_LIBS' - ] - }, - 'variables': { - 'module': 'nss', - 'use_static_libs': 1 - } -} \ No newline at end of file diff --git a/security/nss/cmd/certcgi/index.html b/security/nss/cmd/certcgi/index.html deleted file mode 100644 index 3ae6a10d4..000000000 --- a/security/nss/cmd/certcgi/index.html +++ /dev/null @@ -1,789 +0,0 @@ - - - - - - - -Cert-O-Matic - - - - - diff --git a/security/nss/cmd/certcgi/main.html b/security/nss/cmd/certcgi/main.html deleted file mode 100644 index 05dd9daad..000000000 --- a/security/nss/cmd/certcgi/main.html +++ /dev/null @@ -1,76 +0,0 @@ - - - - Main Layer for CertOMatic - - -
- - - - - - - - - - - - - - - - - - - - - - -
- Common Name:

-
- Organization:

- MAIL= - - E= - - - - Organizational Unit:

- UID=

- Locality:

- State or Province:

- Country:

- Serial Number: -
Auto Generate -
- Use this hex value: 

-
- X.509 version: -
Version 1 -
Version 3

- Key Type: -
RSA -
DSA

- Intermediate CA Key Sizes: -
-
- Validity: -
- Generate Automatically -
Use these values: -
Not Before:  -
Not After:    -
         - YYMMDDhhmm[ss]{Z|+hhmm|-hhmm} -
- DN:

-
- diff --git a/security/nss/cmd/certcgi/manifest.mn b/security/nss/cmd/certcgi/manifest.mn deleted file mode 100644 index 9e17cef9d..000000000 --- a/security/nss/cmd/certcgi/manifest.mn +++ /dev/null @@ -1,22 +0,0 @@ -# -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. - -CORE_DEPTH = ../.. - -# MODULE public and private header directories are implicitly REQUIREd. -MODULE = nss - -# This next line is used by .mk files -# and gets translated into $LINCS in manifest.mnw -REQUIRES = seccmd dbm - -DEFINES = -DNSPR20 - -CSRCS = certcgi.c - -PROGRAM = certcgi - -USE_STATIC_LIBS = 1 - diff --git a/security/nss/cmd/certcgi/nscp_ext_form.html b/security/nss/cmd/certcgi/nscp_ext_form.html deleted file mode 100644 index f2a4a20c3..000000000 --- a/security/nss/cmd/certcgi/nscp_ext_form.html +++ /dev/null @@ -1,84 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - -
- Netscape Certificate Type:

- Activate extension:

- Critical: -
- SSL Client

- SSL Server

- S/MIME

- Object Signing

- Reserved for future use (bit 4)

- SSL CA

- S/MIME CA

- Object Signing CA

-
- Netscape Base URL:

- Activate extension:

- Critical: -
- -
- Netscape Revocation URL:

- Activate extension:

- Critical: -
- -
- Netscape CA Revocation URL:

- Activate extension:

- Critical: -
- -
- Netscape Certificate Renewal URL:

- Activate extension:

- Critical: -
- -
- Netscape CA Policy URL:

- Activate extension:

- Critical: -
- -
- Netscape SSL Server Name:

- Activate extension:

- Critical: -
- -
- Netscape Comment:

- Activate extension:

- Critical: -
- -
- - diff --git a/security/nss/cmd/certcgi/stnd_ext_form.html b/security/nss/cmd/certcgi/stnd_ext_form.html deleted file mode 100644 index 60d4d86a0..000000000 --- a/security/nss/cmd/certcgi/stnd_ext_form.html +++ /dev/null @@ -1,219 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- Key Usage:

- Activate extension:

- Critical: -
- Digital Signature

- Non Repudiation

- Key Encipherment

- Data Encipherment

- Key Agreement

- Key Certificate Signing

- CRL Signing

-
- Extended Key Usage:

- Activate extension:

- Critical: -
- Server Auth

- Client Auth

- Code Signing

- Email Protection

- Timestamp

- OCSP Responder

- Step-up

- Microsoft Trust List Signing

-
- Basic Constraints:

- Activate extension:

- Critical: -
- CA:

-
True

-
False

- - Include Path length:

-
- Authority Key Identifier:

- Activate extension: -
- Key Identider

- Issuer Name and Serial number

-
- Subject Key Identifier:

- Activate extension: -
- Key Identifier: -

- This is an:

-

ascii text value

-

hex value

-

- Private Key Usage Period:

- Activate extension:

- Critical: -
- Use:

-
Not Before

-
Not After

-
Both

- Not to be used to sign before:

-
Set to time of certificate issue

-
Use This value

-
(YYYY/MM/DD HH:MM:SS): - / - / - - : - : -

- Not to be used to sign after:

-
(YYYY/MM/DD HH:MM:SS): - / - / - - : - : -

-
- Subject Alternative Name:

- Activate extension:

- Critical: -
- - - -
- General Names:

-

- - -
- -
- Name Type:
- Other Name, - OID: - RFC 822 Name
- DNS Name - X400 Address
- Directory Name - EDI Party Name
- Uniform Resource Locator - IP Address
- Registered ID - Netscape Certificate Nickname
- Name: - Binary Encoded:

-
-
- Issuer Alternative Name:

- Activate extension:

- Critical: -
- Use the Subject Alternative Name from the Issuers Certificate

- Use this Name: - - - -
- General Names:

-

- - -
- -
- Name Type:
- Other Name, - OID: - RFC 822 Name
- DNS Name - X400 Address
- Directory Name - EDI Party Name
- Uniform Resource Locator - IP Address
- Registered ID
- Name: - Binary Encoded:

-
-
- Name Constraints:

- Activate extension:

-
- - - -
- Name Constraints:

-

- - -
- -
- Name Type:
- Other Name, - OID: - RFC 822 Name
- DNS Name - X400 Address
- Directory Name - EDI Party Name
- Uniform Resource Locator - IP Address
- Registered ID
- Name: - Binary Encoded:

- Constraint type:

-

permited

-

excluded

- Minimum:

- Maximum:

-
-
- - - - - - - - - - diff --git a/security/nss/cmd/certutil/certutil.c b/security/nss/cmd/certutil/certutil.c index 03f4478b7..20722ae78 100644 --- a/security/nss/cmd/certutil/certutil.c +++ b/security/nss/cmd/certutil/certutil.c @@ -1371,7 +1371,7 @@ luF(enum usage_level ul, const char *command) { int is_my_command = (command && 0 == strcmp(command, "F")); if (ul == usage_all || !command || is_my_command) - FPS "%-15s Delete a key from the database\n", + FPS "%-15s Delete a key and associated certificate from the database\n", "-F"); if (ul == usage_selected && !is_my_command) return; diff --git a/security/nss/cmd/manifest.mn b/security/nss/cmd/manifest.mn index f5e6bc236..567c6bb9d 100644 --- a/security/nss/cmd/manifest.mn +++ b/security/nss/cmd/manifest.mn @@ -36,7 +36,6 @@ NSS_SRCDIRS = \ addbuiltin \ atob \ btoa \ - certcgi \ certutil \ chktest \ crlutil \ diff --git a/security/nss/cmd/signtool/sign.c b/security/nss/cmd/signtool/sign.c index 6e776069a..6f8e43946 100644 --- a/security/nss/cmd/signtool/sign.c +++ b/security/nss/cmd/signtool/sign.c @@ -43,6 +43,7 @@ SignArchive(char *tree, char *keyName, char *zip_file, int javascript, int status; char tempfn[FNSIZE], fullfn[FNSIZE]; int keyType = rsaKey; + int count; metafile = meta_file; optimize = _optimize; @@ -81,9 +82,18 @@ SignArchive(char *tree, char *keyName, char *zip_file, int javascript, } /* rsa/dsa to zip */ - sprintf(tempfn, "META-INF/%s.%s", base, (keyType == dsaKey ? "dsa" - : "rsa")); - sprintf(fullfn, "%s/%s", tree, tempfn); + count = snprintf(tempfn, sizeof(tempfn), "META-INF/%s.%s", base, (keyType == dsaKey ? "dsa" : "rsa")); + if (count >= sizeof(tempfn)) { + PR_fprintf(errorFD, "unable to write key metadata\n"); + errorCount++; + exit(ERRX); + } + count = snprintf(fullfn, sizeof(fullfn), "%s/%s", tree, tempfn); + if (count >= sizeof(fullfn)) { + PR_fprintf(errorFD, "unable to write key metadata\n"); + errorCount++; + exit(ERRX); + } JzipAdd(fullfn, tempfn, zipfile, compression_level); /* Loop through all files & subdirectories, add to archive */ @@ -93,20 +103,44 @@ SignArchive(char *tree, char *keyName, char *zip_file, int javascript, } /* mf to zip */ strcpy(tempfn, "META-INF/manifest.mf"); - sprintf(fullfn, "%s/%s", tree, tempfn); + count = snprintf(fullfn, sizeof(fullfn), "%s/%s", tree, tempfn); + if (count >= sizeof(fullfn)) { + PR_fprintf(errorFD, "unable to write manifest\n"); + errorCount++; + exit(ERRX); + } JzipAdd(fullfn, tempfn, zipfile, compression_level); /* sf to zip */ - sprintf(tempfn, "META-INF/%s.sf", base); - sprintf(fullfn, "%s/%s", tree, tempfn); + count = snprintf(tempfn, sizeof(tempfn), "META-INF/%s.sf", base); + if (count >= sizeof(tempfn)) { + PR_fprintf(errorFD, "unable to write sf metadata\n"); + errorCount++; + exit(ERRX); + } + count = snprintf(fullfn, sizeof(fullfn), "%s/%s", tree, tempfn); + if (count >= sizeof(fullfn)) { + PR_fprintf(errorFD, "unable to write sf metadata\n"); + errorCount++; + exit(ERRX); + } JzipAdd(fullfn, tempfn, zipfile, compression_level); /* Add the rsa/dsa file to the zip archive normally */ if (!xpi_arc) { /* rsa/dsa to zip */ - sprintf(tempfn, "META-INF/%s.%s", base, (keyType == dsaKey ? "dsa" - : "rsa")); - sprintf(fullfn, "%s/%s", tree, tempfn); + count = snprintf(tempfn, sizeof(tempfn), "META-INF/%s.%s", base, (keyType == dsaKey ? "dsa" : "rsa")); + if (count >= sizeof(tempfn)) { + PR_fprintf(errorFD, "unable to write key metadata\n"); + errorCount++; + exit(ERRX); + } + count = snprintf(fullfn, sizeof(fullfn), "%s/%s", tree, tempfn); + if (count >= sizeof(fullfn)) { + PR_fprintf(errorFD, "unable to write key metadata\n"); + errorCount++; + exit(ERRX); + } JzipAdd(fullfn, tempfn, zipfile, compression_level); } @@ -408,6 +442,7 @@ static int manifesto_xpi_fn(char *relpath, char *basedir, char *reldir, char *filename, void *arg) { char fullname[FNSIZE]; + int count; if (verbosity >= 0) { PR_fprintf(outputFD, "--> %s\n", relpath); @@ -421,7 +456,10 @@ manifesto_xpi_fn(char *relpath, char *basedir, char *reldir, char *filename, voi if (!PL_HashTableLookup(extensions, ext)) return 0; } - sprintf(fullname, "%s/%s", basedir, relpath); + count = snprintf(fullname, sizeof(fullname), "%s/%s", basedir, relpath); + if (count >= sizeof(fullname)) { + return 1; + } JzipAdd(fullname, relpath, zipfile, compression_level); return 0; diff --git a/security/nss/coreconf/config.gypi b/security/nss/coreconf/config.gypi index f4c3fbd0f..58137872c 100644 --- a/security/nss/coreconf/config.gypi +++ b/security/nss/coreconf/config.gypi @@ -105,6 +105,7 @@ 'sign_libs%': 1, 'use_pprof%': 0, 'ct_verif%': 0, + 'emit_llvm%': 0, 'nss_public_dist_dir%': '<(nss_dist_dir)/public', 'nss_private_dist_dir%': '<(nss_dist_dir)/private', 'only_dev_random%': 1, @@ -431,6 +432,10 @@ 'LIBRARY_SEARCH_PATHS': ['/usr/lib <(sanitizer_flags)'], }, }], + [ 'emit_llvm==1', { + 'cflags': ['-flto'], + 'ldflags': ['-flto', '-fuse-ld=gold', '-Wl,-plugin-opt=save-temps'], + }], [ 'OS=="android" and mozilla_client==0', { 'defines': [ 'NO_SYSINFO', diff --git a/security/nss/cpputil/scoped_ptrs.h b/security/nss/cpputil/scoped_ptrs.h index b92b8132b..8a0b4f5ab 100644 --- a/security/nss/cpputil/scoped_ptrs.h +++ b/security/nss/cpputil/scoped_ptrs.h @@ -10,8 +10,10 @@ #include #include "cert.h" #include "keyhi.h" +#include "p12.h" #include "pk11pub.h" #include "pkcs11uri.h" +#include "sslexp.h" struct ScopedDelete { void operator()(CERTCertificate* cert) { CERT_DestroyCertificate(cert); } @@ -37,6 +39,12 @@ struct ScopedDelete { void operator()(PLArenaPool* arena) { PORT_FreeArena(arena, PR_FALSE); } void operator()(PK11Context* context) { PK11_DestroyContext(context, true); } void operator()(PK11GenericObject* obj) { PK11_DestroyGenericObject(obj); } + void operator()(SSLResumptionTokenInfo* token) { + SSL_DestroyResumptionTokenInfo(token); + } + void operator()(SEC_PKCS12DecoderContext* dcx) { + SEC_PKCS12DecoderFinish(dcx); + } }; template @@ -68,6 +76,8 @@ SCOPED(PK11URI); SCOPED(PLArenaPool); SCOPED(PK11Context); SCOPED(PK11GenericObject); +SCOPED(SSLResumptionTokenInfo); +SCOPED(SEC_PKCS12DecoderContext); #undef SCOPED diff --git a/security/nss/cpputil/tls_parser.h b/security/nss/cpputil/tls_parser.h index a5f5771d5..436c11e76 100644 --- a/security/nss/cpputil/tls_parser.h +++ b/security/nss/cpputil/tls_parser.h @@ -47,6 +47,7 @@ const uint8_t kTlsAlertUnexpectedMessage = 10; const uint8_t kTlsAlertBadRecordMac = 20; const uint8_t kTlsAlertRecordOverflow = 22; const uint8_t kTlsAlertHandshakeFailure = 40; +const uint8_t kTlsAlertBadCertificate = 42; const uint8_t kTlsAlertIllegalParameter = 47; const uint8_t kTlsAlertDecodeError = 50; const uint8_t kTlsAlertDecryptError = 51; diff --git a/security/nss/doc/certutil.xml b/security/nss/doc/certutil.xml index d5062bd5e..4622c75e4 100644 --- a/security/nss/doc/certutil.xml +++ b/security/nss/doc/certutil.xml @@ -84,11 +84,11 @@ -F - Delete a private key from a key database. Specify the key to delete with the -n argument. Specify the database from which to delete the key with the - argument. Use the argument to specify explicitly whether to delete a DSA, RSA, or ECC key. If you don't use the argument, the option looks for an RSA key matching the specified nickname. + Delete a private key and the associated certificate from a database. Specify the key to delete with the -n argument. Specify the database from which to delete the key with the + argument. -When you delete keys, be sure to also remove any certificates associated with those keys from the certificate database, by using -D. Some smart cards do not let you remove a public key you have generated. In such a case, only the private key is deleted from the key pair. You can display the public key with the command certutil -K -h tokenname. +Some smart cards do not let you remove a public key you have generated. In such a case, only the private key is deleted from the key pair. diff --git a/security/nss/gtests/der_gtest/der_gtest.gyp b/security/nss/gtests/der_gtest/der_gtest.gyp index 9a382912e..2df9242d3 100644 --- a/security/nss/gtests/der_gtest/der_gtest.gyp +++ b/security/nss/gtests/der_gtest/der_gtest.gyp @@ -13,6 +13,7 @@ 'sources': [ 'der_getint_unittest.cc', 'der_quickder_unittest.cc', + 'p12_import_unittest.cc', '<(DEPTH)/gtests/common/gtests.cc' ], 'dependencies': [ @@ -21,6 +22,8 @@ '<(DEPTH)/lib/util/util.gyp:nssutil3', '<(DEPTH)/lib/ssl/ssl.gyp:ssl3', '<(DEPTH)/lib/nss/nss.gyp:nss3', + '<(DEPTH)/lib/pkcs12/pkcs12.gyp:pkcs12', + '<(DEPTH)/lib/pkcs7/pkcs7.gyp:pkcs7', ] } ], diff --git a/security/nss/gtests/der_gtest/manifest.mn b/security/nss/gtests/der_gtest/manifest.mn index a61d0f104..f0d6b519f 100644 --- a/security/nss/gtests/der_gtest/manifest.mn +++ b/security/nss/gtests/der_gtest/manifest.mn @@ -9,6 +9,7 @@ MODULE = nss CPPSRCS = \ der_getint_unittest.cc \ der_quickder_unittest.cc \ + p12_import_unittest.cc \ $(NULL) INCLUDES += -I$(CORE_DEPTH)/gtests/google_test/gtest/include \ diff --git a/security/nss/gtests/der_gtest/p12_import_unittest.cc b/security/nss/gtests/der_gtest/p12_import_unittest.cc new file mode 100644 index 000000000..6ffcda348 --- /dev/null +++ b/security/nss/gtests/der_gtest/p12_import_unittest.cc @@ -0,0 +1,251 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "nss.h" +#include "p12.h" + +#include "gtest/gtest.h" +#include "scoped_ptrs.h" + +namespace nss_test { + +static const uint8_t cert_p12[] = { + 0x30, 0x82, 0x0a, 0x1f, 0x02, 0x01, 0x03, 0x30, 0x82, 0x09, 0xe5, 0x06, + 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x82, + 0x09, 0xd6, 0x04, 0x82, 0x09, 0xd2, 0x30, 0x82, 0x09, 0xce, 0x30, 0x82, + 0x04, 0x42, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, + 0x06, 0xa0, 0x82, 0x04, 0x33, 0x30, 0x82, 0x04, 0x2f, 0x02, 0x01, 0x00, + 0x30, 0x82, 0x04, 0x28, 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, 0x05, + 0x66, 0xc7, 0x5c, 0x27, 0x4e, 0x15, 0xd9, 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, 0x4e, 0x61, 0xa7, 0x23, 0xc4, 0x3b, 0x37, 0xea, + 0xba, 0xe9, 0x9f, 0x44, 0x8e, 0x5e, 0xf7, 0xf2, 0x80, 0x82, 0x03, 0xc0, + 0x76, 0x7d, 0x91, 0x89, 0xe1, 0x04, 0x59, 0x91, 0x0c, 0x72, 0x14, 0x93, + 0xc4, 0x37, 0xe8, 0xd1, 0xbb, 0x49, 0xfc, 0x23, 0x49, 0x19, 0x6f, 0xc9, + 0x05, 0x08, 0x52, 0xd8, 0x63, 0xdf, 0x27, 0x63, 0x24, 0x85, 0x73, 0x11, + 0xfa, 0x6d, 0xca, 0xed, 0xb2, 0x91, 0x77, 0xc6, 0x1f, 0x0b, 0xdb, 0x4d, + 0x66, 0x34, 0xb9, 0x51, 0xef, 0xf0, 0x8f, 0xf8, 0x71, 0x2b, 0x68, 0xf7, + 0x5c, 0xdf, 0x99, 0x21, 0x7c, 0xb6, 0xa7, 0x45, 0xdb, 0x71, 0x69, 0x0b, + 0xb3, 0x2e, 0xff, 0x84, 0xcd, 0xd1, 0xb8, 0x87, 0xe9, 0xaa, 0x3e, 0xcd, + 0x11, 0x90, 0xcb, 0xd8, 0xe7, 0x08, 0x87, 0x32, 0x82, 0x26, 0x69, 0x9b, + 0xa6, 0xb1, 0x76, 0xf2, 0x28, 0xe2, 0x6c, 0xf5, 0x50, 0x16, 0x2d, 0x13, + 0x75, 0x73, 0xed, 0xd1, 0x40, 0x1b, 0xd9, 0x43, 0xf5, 0x1d, 0x60, 0x98, + 0x33, 0x5e, 0x18, 0xb0, 0xba, 0xe0, 0x8a, 0xaa, 0xa4, 0x3b, 0x78, 0x49, + 0x59, 0x5f, 0xa4, 0xd5, 0xb5, 0x10, 0xb8, 0x87, 0x46, 0x48, 0xff, 0x5e, + 0x91, 0x3b, 0xf9, 0xef, 0x29, 0x92, 0x99, 0xfd, 0x22, 0x8c, 0xcd, 0x05, + 0x2e, 0x0a, 0x24, 0xbf, 0xe4, 0x1b, 0x95, 0x86, 0x94, 0xf2, 0xd9, 0x8c, + 0x4d, 0xac, 0xe8, 0xb8, 0x49, 0x93, 0x74, 0xcd, 0x79, 0x3f, 0xa4, 0x29, + 0x09, 0x5a, 0x00, 0x44, 0xfe, 0x75, 0x53, 0x23, 0x7e, 0xe4, 0xf5, 0x71, + 0xcf, 0x1e, 0x48, 0x1d, 0x89, 0x42, 0x67, 0xa6, 0x1d, 0x0d, 0x0b, 0xe0, + 0x4a, 0x7a, 0x59, 0xe0, 0x88, 0x63, 0xfc, 0x72, 0x97, 0xc2, 0x9f, 0x5d, + 0xc3, 0xb2, 0x75, 0x73, 0x25, 0x10, 0x6f, 0x40, 0x93, 0x4f, 0x7d, 0x69, + 0x01, 0x2d, 0xf4, 0xbe, 0xa9, 0xd9, 0x3c, 0x83, 0x77, 0x92, 0xf4, 0xa1, + 0x2a, 0x7d, 0x3e, 0xab, 0x2d, 0xa1, 0x53, 0x63, 0x98, 0xaf, 0xc6, 0x11, + 0x78, 0x3d, 0x37, 0xa9, 0x3f, 0x9c, 0xa8, 0xce, 0xc1, 0x9f, 0xac, 0x45, + 0x9a, 0x2e, 0x38, 0x9f, 0x08, 0xf9, 0x2d, 0x9e, 0xf5, 0xca, 0x4d, 0x33, + 0x77, 0x89, 0x2b, 0xde, 0x32, 0x05, 0xe4, 0x39, 0x1a, 0x78, 0x06, 0x7f, + 0x74, 0x28, 0xab, 0x07, 0xbc, 0x59, 0xd0, 0x52, 0x11, 0x1b, 0x6a, 0x98, + 0x51, 0xed, 0x5c, 0xf7, 0x96, 0x59, 0xad, 0xb1, 0x48, 0x81, 0xc8, 0xde, + 0xec, 0xb0, 0x16, 0x7d, 0x61, 0x09, 0xaf, 0x36, 0xe8, 0x2d, 0xd3, 0x88, + 0x99, 0x35, 0xf2, 0x72, 0xa5, 0xfd, 0xd9, 0xbe, 0xf5, 0x6d, 0x52, 0x4f, + 0xdb, 0x65, 0x1b, 0x06, 0xfd, 0x1f, 0x61, 0xb3, 0xae, 0x03, 0x96, 0x50, + 0x96, 0xc4, 0x74, 0x28, 0x26, 0xda, 0x51, 0xc2, 0xd4, 0xff, 0xce, 0xc5, + 0x26, 0xea, 0x8c, 0xfd, 0x1e, 0x22, 0x03, 0xf0, 0xcd, 0x00, 0xf2, 0x72, + 0xf3, 0x81, 0x46, 0x1e, 0x95, 0xaf, 0xe1, 0xc1, 0x0a, 0x12, 0xfe, 0xb0, + 0x97, 0x2d, 0x40, 0xe8, 0x6d, 0xde, 0xe0, 0x9c, 0x7f, 0xad, 0x85, 0x89, + 0x28, 0x88, 0x4a, 0x64, 0xc1, 0xa4, 0x2f, 0xb6, 0x25, 0xae, 0x89, 0xb4, + 0xab, 0x02, 0xea, 0xca, 0xd6, 0x05, 0x4f, 0x3a, 0x64, 0xd0, 0xbf, 0x2d, + 0xba, 0x0a, 0x9c, 0x5a, 0xa5, 0x0b, 0xf5, 0xc7, 0x84, 0x6e, 0xb4, 0x5c, + 0x0e, 0x43, 0x96, 0xac, 0xfe, 0xc1, 0xc5, 0x3d, 0x15, 0x2b, 0x4d, 0x67, + 0x2a, 0x09, 0xd8, 0x64, 0x83, 0x13, 0x00, 0x10, 0xe1, 0x60, 0x76, 0x9b, + 0xf0, 0xa0, 0xdc, 0x8c, 0x4b, 0x4f, 0xc5, 0x93, 0xa8, 0xf8, 0xef, 0xd9, + 0x75, 0xdc, 0x62, 0xe9, 0xcf, 0xdf, 0x3f, 0x7b, 0x8d, 0x2c, 0x0e, 0x5a, + 0x99, 0xc6, 0x38, 0x4c, 0xd9, 0xfb, 0xe6, 0xb5, 0x1b, 0x6e, 0xbd, 0xae, + 0xef, 0x89, 0x71, 0x4e, 0xfd, 0x74, 0x46, 0x35, 0xf9, 0x48, 0x43, 0x11, + 0x81, 0xcd, 0x6f, 0xdc, 0xf3, 0x2e, 0x92, 0x93, 0x9e, 0xca, 0xf8, 0xfa, + 0xc6, 0x56, 0x75, 0x1e, 0x04, 0x89, 0x7d, 0x1c, 0x2e, 0xdb, 0xbd, 0x5b, + 0xec, 0xc8, 0x2d, 0xa3, 0xe2, 0x05, 0xef, 0xe9, 0x5f, 0x05, 0x4b, 0x89, + 0x82, 0x0c, 0x1e, 0x8c, 0x74, 0xe1, 0x5a, 0x67, 0xe4, 0x97, 0x9b, 0x22, + 0xd7, 0xdc, 0xe2, 0x74, 0xcf, 0x93, 0xc1, 0xca, 0xc6, 0xde, 0xae, 0xc0, + 0xd2, 0xf9, 0x57, 0xc5, 0x90, 0x96, 0x48, 0x0a, 0x25, 0x43, 0x75, 0xc1, + 0x94, 0xa4, 0xd5, 0x14, 0xb2, 0x27, 0xf8, 0x45, 0xf1, 0x3c, 0x01, 0xd6, + 0xb8, 0x73, 0x1c, 0xb6, 0x55, 0xc5, 0xc9, 0x10, 0x28, 0x2f, 0xba, 0x18, + 0x36, 0x8d, 0xfe, 0x0b, 0x23, 0xf3, 0x9a, 0x98, 0xfb, 0x2f, 0x59, 0x52, + 0x3a, 0x0f, 0x75, 0x60, 0xa0, 0x92, 0x0d, 0x78, 0xf0, 0xc7, 0x5d, 0x9d, + 0x3a, 0x72, 0xd0, 0xd1, 0x30, 0x73, 0x9e, 0x3c, 0x03, 0x99, 0x4c, 0xe2, + 0xe5, 0xd4, 0x77, 0xfe, 0x3a, 0x92, 0x08, 0x5b, 0x99, 0x51, 0x15, 0x57, + 0x05, 0x13, 0x51, 0xc2, 0xf4, 0xb5, 0x2d, 0xae, 0x68, 0x9f, 0x4e, 0xbf, + 0x00, 0x11, 0xc1, 0xe1, 0x48, 0xb3, 0xce, 0x36, 0x42, 0x6a, 0x74, 0xd7, + 0xe7, 0x84, 0x1e, 0xf3, 0x47, 0xc4, 0xab, 0x59, 0x18, 0x15, 0x31, 0xa4, + 0x28, 0x68, 0x16, 0xa3, 0x68, 0xbf, 0x6c, 0xfe, 0x7a, 0x36, 0xd9, 0xc1, + 0x22, 0xd6, 0x5e, 0x2d, 0xbb, 0x9a, 0x1f, 0xb6, 0x8c, 0xa6, 0x65, 0x24, + 0x3e, 0x01, 0x9c, 0x75, 0x5e, 0x17, 0x42, 0x12, 0x89, 0x85, 0x6f, 0x05, + 0xac, 0x54, 0xd5, 0x02, 0xea, 0x1e, 0xc2, 0xe1, 0xcd, 0x61, 0x0e, 0x53, + 0xd5, 0x9d, 0x3a, 0x67, 0x1b, 0x50, 0x9b, 0x90, 0x18, 0x66, 0x6d, 0xb2, + 0x7f, 0x3a, 0x69, 0xc9, 0xef, 0x07, 0x17, 0x91, 0x8a, 0xe9, 0x15, 0x35, + 0xed, 0x70, 0x9e, 0x74, 0x8c, 0xe7, 0xf4, 0xaa, 0xcf, 0xbe, 0xa3, 0x98, + 0x89, 0x8d, 0x3c, 0x5e, 0xa4, 0x6b, 0x8f, 0x1b, 0x18, 0x04, 0x79, 0xd2, + 0x11, 0x64, 0xb1, 0xc7, 0x68, 0xca, 0xaf, 0x44, 0xa1, 0x39, 0x29, 0x58, + 0x70, 0x4e, 0xce, 0xb7, 0x7a, 0x3c, 0x4b, 0xdc, 0x32, 0x92, 0x76, 0x74, + 0xab, 0x0a, 0x6f, 0x8b, 0x74, 0xf5, 0xfd, 0xed, 0x3b, 0x11, 0x95, 0xe8, + 0x10, 0x74, 0x4c, 0xd8, 0xbe, 0x0f, 0x50, 0xee, 0xa0, 0xee, 0x39, 0xd8, + 0x9f, 0xa1, 0xa0, 0x21, 0xa3, 0x47, 0x8c, 0xa6, 0xd9, 0xca, 0x8c, 0xb3, + 0x8b, 0x86, 0x9e, 0x31, 0x3b, 0xcc, 0x7f, 0xea, 0x23, 0xb1, 0x25, 0x73, + 0xfb, 0x66, 0x99, 0x28, 0xff, 0xf4, 0xe9, 0xb7, 0x19, 0x3e, 0xd5, 0xc6, + 0x5d, 0xd1, 0xaa, 0x08, 0x6f, 0xf2, 0xff, 0xab, 0x39, 0x69, 0x1f, 0xd3, + 0x6b, 0x20, 0xf3, 0x2f, 0xe4, 0xd5, 0xb8, 0x76, 0x3f, 0x6c, 0x8f, 0x05, + 0x3c, 0xe0, 0x18, 0x81, 0x82, 0xca, 0x05, 0x7f, 0xc0, 0x8e, 0x87, 0x50, + 0xfb, 0xb1, 0x65, 0xfa, 0x2f, 0xb7, 0xba, 0x20, 0x0b, 0x35, 0x5c, 0x87, + 0xba, 0x90, 0x5a, 0x7f, 0xfc, 0xe9, 0xf2, 0x98, 0x5f, 0x6e, 0xb2, 0xcc, + 0xef, 0x4b, 0x2d, 0xde, 0xdd, 0x6f, 0xd9, 0x8e, 0x79, 0x89, 0x45, 0xcd, + 0x4c, 0xdf, 0x27, 0xf1, 0x26, 0x47, 0x9e, 0x83, 0xdb, 0x73, 0x4a, 0x20, + 0x84, 0xde, 0x09, 0xe0, 0x58, 0xfe, 0x19, 0xcb, 0x92, 0xc4, 0x5b, 0x83, + 0x30, 0x82, 0x05, 0x84, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, + 0x01, 0x07, 0x01, 0xa0, 0x82, 0x05, 0x75, 0x04, 0x82, 0x05, 0x71, 0x30, + 0x82, 0x05, 0x6d, 0x30, 0x82, 0x05, 0x69, 0x06, 0x0b, 0x2a, 0x86, 0x48, + 0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x0a, 0x01, 0x02, 0xa0, 0x82, 0x05, 0x31, + 0x30, 0x82, 0x05, 0x2d, 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, + 0x5c, 0x72, 0x5e, 0xfb, 0xbc, 0x49, 0xaa, 0xa1, 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, 0xcb, 0xa8, 0xda, 0x75, 0xba, 0x64, 0x22, + 0x70, 0x39, 0x3c, 0x83, 0x35, 0x0b, 0x41, 0xc4, 0x49, 0x04, 0x82, 0x04, + 0xd0, 0xb3, 0x3d, 0x9b, 0x03, 0x34, 0xdf, 0x62, 0x37, 0xb0, 0xbb, 0x37, + 0x0d, 0x88, 0x8c, 0x6b, 0xf2, 0x46, 0x33, 0xa4, 0x4b, 0x48, 0x86, 0x0a, + 0x36, 0x37, 0x24, 0x21, 0x08, 0x8e, 0x86, 0xbf, 0x4e, 0x9c, 0xe7, 0xa9, + 0x56, 0x4a, 0x02, 0xb4, 0x74, 0x6a, 0x8a, 0x1e, 0x51, 0x91, 0xe3, 0x8f, + 0xe3, 0xf6, 0xca, 0x0a, 0x2d, 0xe7, 0x09, 0x5e, 0x1e, 0x59, 0x46, 0x01, + 0xda, 0xe9, 0x5b, 0xb9, 0xd8, 0x15, 0x7c, 0x05, 0xd9, 0x5f, 0x8c, 0x3d, + 0xd4, 0xb2, 0xff, 0x25, 0x9d, 0xfe, 0x0e, 0xe3, 0x0c, 0xf0, 0x7f, 0x30, + 0x25, 0x92, 0x0e, 0x44, 0xf4, 0x16, 0xc7, 0xa2, 0x22, 0xb2, 0x31, 0xfa, + 0x55, 0x97, 0xf7, 0xd0, 0xd7, 0x58, 0x1f, 0x96, 0x81, 0x06, 0x86, 0xbb, + 0x07, 0x30, 0x9d, 0x01, 0xb8, 0x15, 0xb2, 0x81, 0xa9, 0x35, 0x09, 0x2c, + 0x97, 0xbc, 0x8e, 0x2e, 0x2e, 0x30, 0x20, 0x51, 0x94, 0x9d, 0x9f, 0xbd, + 0x83, 0x48, 0x7b, 0x25, 0xfc, 0x95, 0x42, 0xd7, 0x29, 0xd5, 0x67, 0xcd, + 0x48, 0xc6, 0x78, 0xe1, 0x6d, 0xdf, 0xf8, 0x0b, 0x3a, 0x95, 0xcc, 0xd0, + 0x93, 0xfe, 0x23, 0x8d, 0x99, 0xd9, 0x8c, 0x67, 0x38, 0x9f, 0xd0, 0x4c, + 0xff, 0x32, 0x45, 0x32, 0xa9, 0xe8, 0x9d, 0xbc, 0xbf, 0xaa, 0xb2, 0x49, + 0xaa, 0x1d, 0xa0, 0x04, 0x53, 0x14, 0xa4, 0x77, 0x96, 0x3f, 0x17, 0xbb, + 0x2e, 0x14, 0xbe, 0x39, 0x6b, 0x69, 0x16, 0x7a, 0x99, 0xb2, 0xf4, 0x16, + 0x1a, 0xb7, 0xaa, 0x0a, 0x97, 0xd9, 0x1d, 0x62, 0xbe, 0xfc, 0x38, 0x00, + 0x6c, 0x65, 0x75, 0xe0, 0xb0, 0x65, 0x8f, 0xb6, 0x4b, 0xe7, 0x21, 0x41, + 0x65, 0x65, 0x5a, 0x7c, 0x5b, 0xe8, 0x70, 0x83, 0x71, 0xd6, 0x65, 0x7c, + 0x4f, 0x00, 0x90, 0x55, 0xca, 0xff, 0xc9, 0x3f, 0x61, 0x1e, 0xc0, 0x41, + 0x67, 0x0c, 0x71, 0xb2, 0xef, 0x12, 0x8e, 0xb1, 0xaa, 0xcf, 0xf1, 0x78, + 0x9f, 0x5b, 0xb9, 0x7b, 0xbe, 0x04, 0x39, 0xf0, 0x87, 0xca, 0x3a, 0x77, + 0x31, 0xab, 0x85, 0x8f, 0x4f, 0x06, 0xad, 0x45, 0xf2, 0xe2, 0xc2, 0x20, + 0x74, 0xf1, 0xdc, 0x21, 0x3f, 0x79, 0x0d, 0xcc, 0xcf, 0x7f, 0xb9, 0x85, + 0x9e, 0x1a, 0x1b, 0x84, 0xe2, 0x5b, 0xe3, 0x77, 0x27, 0x91, 0xcc, 0xf2, + 0xe4, 0xf2, 0x19, 0xdd, 0x98, 0x64, 0x9d, 0xcb, 0xf1, 0xc5, 0xe6, 0x7b, + 0x75, 0x55, 0x4e, 0xa5, 0xca, 0xe3, 0x5b, 0xbe, 0xc2, 0xcd, 0x83, 0x27, + 0x92, 0xe1, 0x23, 0x3f, 0xd7, 0x3d, 0xb7, 0x3a, 0x8b, 0x3a, 0x26, 0xc1, + 0xfb, 0xed, 0x69, 0x7a, 0xab, 0xec, 0x0a, 0xe5, 0xaa, 0x81, 0x9f, 0xdf, + 0x97, 0x45, 0x64, 0x35, 0x7d, 0xad, 0x88, 0x4a, 0x75, 0x13, 0xc3, 0x13, + 0xd6, 0x9a, 0xf3, 0xa2, 0x94, 0xf7, 0x96, 0x09, 0xa7, 0xbe, 0xb8, 0xe4, + 0x29, 0x7d, 0xb0, 0xef, 0x4a, 0x5d, 0x0d, 0x02, 0xb4, 0x10, 0x54, 0x17, + 0x62, 0xef, 0xe2, 0xad, 0x89, 0x6d, 0x91, 0x51, 0x7e, 0x35, 0x28, 0xb4, + 0xe7, 0x02, 0xbb, 0xcb, 0x03, 0x37, 0xa6, 0xeb, 0x55, 0x51, 0xc0, 0xc2, + 0x21, 0x7a, 0x78, 0x44, 0x44, 0x70, 0x06, 0xb0, 0x5d, 0x19, 0xaa, 0xcb, + 0xf1, 0x9f, 0xaa, 0xd3, 0x5a, 0x29, 0xc4, 0xc7, 0x7a, 0x36, 0x1d, 0x65, + 0x21, 0x52, 0xf9, 0xe2, 0xc7, 0x60, 0xd4, 0x32, 0x03, 0xdf, 0x03, 0xcc, + 0xe5, 0x7c, 0xf9, 0x15, 0xe3, 0xe6, 0x46, 0xeb, 0xa8, 0xa8, 0x6f, 0xe7, + 0x46, 0x03, 0xc7, 0x5c, 0x29, 0xf6, 0xac, 0x61, 0x2d, 0xbe, 0xa0, 0xda, + 0xdc, 0xca, 0x29, 0x35, 0x3b, 0xa0, 0x43, 0x22, 0x22, 0x61, 0x65, 0x8f, + 0x2d, 0x13, 0xce, 0x61, 0x7c, 0x27, 0x45, 0x9d, 0x9b, 0x8d, 0xd6, 0xc1, + 0xb5, 0x8c, 0x5b, 0xdb, 0xbb, 0xf6, 0x7e, 0x9a, 0xd4, 0x5c, 0x6b, 0x7e, + 0xf3, 0x6d, 0x7e, 0x45, 0x2e, 0x55, 0x7d, 0x9f, 0x62, 0xc7, 0xf4, 0x03, + 0x6f, 0xb9, 0x02, 0xcf, 0x3d, 0x07, 0xc5, 0xc8, 0xce, 0x9e, 0xac, 0x56, + 0x43, 0x8b, 0xcc, 0xf0, 0x2d, 0xc5, 0x56, 0xfa, 0x61, 0xf9, 0xee, 0x1b, + 0x89, 0xa9, 0xd6, 0xe8, 0x1e, 0xa2, 0xdf, 0xfd, 0x0d, 0x33, 0x03, 0x91, + 0xd9, 0x30, 0x4d, 0xfb, 0x2d, 0x7e, 0x5b, 0xb0, 0xb5, 0x55, 0x1e, 0x9c, + 0x13, 0x96, 0x5a, 0xa6, 0xab, 0x88, 0x79, 0xe7, 0x42, 0x31, 0xb2, 0x2d, + 0xf8, 0x40, 0x89, 0xe4, 0x96, 0x4c, 0x42, 0xc9, 0x72, 0xd1, 0x8f, 0x3f, + 0x2d, 0xee, 0x1d, 0x91, 0xe0, 0xfb, 0x1f, 0xb5, 0x94, 0x41, 0xce, 0x89, + 0xed, 0xe7, 0xec, 0xa0, 0xb6, 0xb2, 0xa2, 0x5c, 0x72, 0xa1, 0x91, 0x40, + 0x82, 0xde, 0x62, 0xba, 0x12, 0x12, 0xa1, 0xab, 0x31, 0x62, 0x38, 0x48, + 0x4c, 0x49, 0x9e, 0x6c, 0xf3, 0xf1, 0x69, 0x3e, 0x8b, 0x6a, 0x24, 0x45, + 0x99, 0x5c, 0x5a, 0xe3, 0x52, 0x24, 0xb7, 0xcf, 0xf0, 0xc8, 0x82, 0x5e, + 0x9e, 0x10, 0x29, 0xcf, 0xda, 0x01, 0xd0, 0xc0, 0x81, 0xfd, 0x56, 0x15, + 0x1c, 0x6b, 0xff, 0x78, 0x91, 0xaa, 0x47, 0x63, 0xb0, 0xe2, 0xbd, 0x67, + 0x0d, 0x24, 0xc5, 0xfd, 0x1a, 0x6a, 0x6a, 0x71, 0x9b, 0xca, 0xc4, 0xb3, + 0xc0, 0x07, 0x3d, 0xd7, 0x3b, 0xf4, 0xc0, 0xb7, 0xb5, 0xc4, 0x46, 0x85, + 0x3d, 0x22, 0x03, 0x1b, 0xcf, 0xe6, 0xce, 0x2f, 0xae, 0x41, 0xcf, 0x67, + 0x6b, 0xd3, 0x87, 0x3f, 0xca, 0x4c, 0xb7, 0x9f, 0x47, 0x36, 0xa5, 0xd7, + 0xd3, 0x70, 0xf7, 0xc4, 0x9f, 0x7d, 0xbd, 0xe4, 0xc6, 0xec, 0x7b, 0x03, + 0xca, 0xb0, 0x78, 0x06, 0xa3, 0xf1, 0xd0, 0x98, 0xdf, 0x1c, 0x60, 0x90, + 0x61, 0xcb, 0x7b, 0x68, 0xd2, 0x8e, 0x24, 0x76, 0x7b, 0xf6, 0x2f, 0xf3, + 0x7b, 0x96, 0x2d, 0x80, 0x6f, 0xae, 0xc5, 0x2b, 0xe9, 0xad, 0x78, 0x25, + 0x78, 0x4e, 0xd7, 0x81, 0xb7, 0x60, 0x20, 0x0c, 0x20, 0x46, 0xb4, 0x88, + 0xfe, 0x12, 0x0a, 0x8d, 0x7a, 0x9a, 0x0b, 0xdd, 0x6d, 0x37, 0xb3, 0xa5, + 0x99, 0x1d, 0xf2, 0xd4, 0xa6, 0x79, 0x1e, 0x89, 0x1a, 0xda, 0xe8, 0x83, + 0x24, 0xc9, 0xd9, 0x1f, 0x76, 0x82, 0xec, 0x64, 0x35, 0x6b, 0x9b, 0xfd, + 0x91, 0x31, 0x96, 0xf2, 0x8b, 0x4f, 0x30, 0xbb, 0xd9, 0xcd, 0xe0, 0x66, + 0x73, 0xfd, 0xd7, 0x05, 0x16, 0x7c, 0xed, 0x94, 0xc0, 0xa0, 0x73, 0x9e, + 0xe7, 0x85, 0xac, 0x0e, 0x20, 0xd1, 0x5e, 0x66, 0x7a, 0xef, 0x93, 0x20, + 0xd7, 0x3f, 0xb5, 0xbd, 0xb7, 0xb7, 0xcb, 0x64, 0xc8, 0xde, 0x2f, 0xd9, + 0x92, 0x5f, 0xa1, 0xb6, 0xbd, 0xd0, 0xe6, 0xb4, 0x55, 0xf4, 0xa1, 0xa8, + 0x51, 0x5e, 0x00, 0x6f, 0xaa, 0x09, 0xff, 0x56, 0xb4, 0xbc, 0xdf, 0xc1, + 0x20, 0x13, 0xc4, 0x3c, 0x48, 0xb1, 0x6d, 0xeb, 0x19, 0xb8, 0xbf, 0x4f, + 0x3d, 0x35, 0x96, 0x14, 0xc3, 0xc3, 0xef, 0x8e, 0x0b, 0x95, 0xbc, 0x78, + 0x47, 0x6a, 0x6c, 0x24, 0x10, 0xbd, 0x06, 0x13, 0x5c, 0x69, 0x7b, 0xb5, + 0x53, 0x43, 0xd1, 0x7a, 0x1d, 0x9a, 0x7f, 0x57, 0xcd, 0x81, 0xc5, 0x3f, + 0xde, 0x98, 0xb5, 0x73, 0x95, 0xd2, 0x10, 0xcf, 0x4f, 0x6a, 0xce, 0xac, + 0x35, 0x49, 0x4d, 0xf3, 0xbe, 0xbf, 0x38, 0xf2, 0xcf, 0x1b, 0x1c, 0x19, + 0x27, 0xa3, 0x3f, 0xd9, 0x35, 0xfe, 0xc2, 0xe5, 0x49, 0x16, 0x28, 0xd0, + 0x8e, 0xb9, 0x34, 0x6e, 0x8b, 0xa5, 0xe2, 0x9c, 0xbe, 0xad, 0xa1, 0x43, + 0x61, 0x2e, 0x48, 0x65, 0xb3, 0x20, 0xe7, 0x1d, 0x65, 0x00, 0x9d, 0x6e, + 0x71, 0xe7, 0x79, 0x44, 0xac, 0x0c, 0x38, 0x5a, 0x1d, 0x40, 0x06, 0x30, + 0xd0, 0xe8, 0xbe, 0x95, 0x16, 0xaf, 0xd8, 0x5f, 0x67, 0xd3, 0xb0, 0x6a, + 0xa3, 0x7c, 0xc1, 0x9b, 0x3f, 0xc7, 0xae, 0x27, 0xb1, 0xc1, 0xb5, 0xce, + 0xdf, 0xbb, 0xa4, 0x4f, 0xb4, 0x58, 0xa1, 0xb9, 0x7c, 0x9c, 0x5f, 0x26, + 0x4f, 0x13, 0xfa, 0x7c, 0x1a, 0xb7, 0x1b, 0x69, 0xd6, 0x0e, 0x1b, 0x92, + 0x31, 0x4b, 0xb4, 0x71, 0x12, 0xc8, 0xc4, 0xbd, 0x99, 0xe3, 0xc8, 0x9d, + 0x68, 0xb3, 0x38, 0x35, 0x3f, 0x16, 0xd8, 0xde, 0x01, 0x71, 0xf6, 0x66, + 0x77, 0xcb, 0xbd, 0xe2, 0x97, 0x10, 0x91, 0x41, 0x00, 0xa1, 0x0d, 0x9d, + 0x40, 0x0b, 0xfc, 0x25, 0xc8, 0x44, 0xc3, 0x78, 0xaa, 0x89, 0xd5, 0x59, + 0xe4, 0xa2, 0x9e, 0xd0, 0x85, 0xa2, 0xdd, 0x80, 0x3b, 0x35, 0x5a, 0x50, + 0x86, 0xcd, 0x72, 0xf4, 0x9d, 0x69, 0x0e, 0x2d, 0x97, 0x42, 0x09, 0x5e, + 0xa6, 0x86, 0xf7, 0x35, 0xcf, 0x9b, 0x42, 0xa7, 0x60, 0xa0, 0x71, 0x41, + 0x28, 0x35, 0x22, 0xd6, 0x55, 0xe1, 0xdb, 0xb3, 0x8e, 0x0d, 0x47, 0xb7, + 0xd6, 0x02, 0x0f, 0xb1, 0xdf, 0xb8, 0xfb, 0xd8, 0x20, 0xcf, 0x6a, 0x47, + 0x3f, 0x8a, 0x91, 0x08, 0x64, 0x08, 0xba, 0x19, 0x10, 0x1f, 0xcf, 0xe5, + 0x34, 0xf1, 0x32, 0x49, 0x3b, 0xaf, 0x18, 0x67, 0x96, 0x47, 0x7f, 0x21, + 0x8a, 0x37, 0x15, 0x5c, 0xc0, 0xe8, 0x7b, 0xd6, 0x08, 0x5b, 0x45, 0x10, + 0x1f, 0x1c, 0x7f, 0xce, 0x3b, 0x88, 0xe5, 0x0e, 0xd9, 0x00, 0xce, 0xe5, + 0x9b, 0x4b, 0x25, 0xc7, 0x11, 0x8a, 0x4f, 0x22, 0xa7, 0x31, 0x25, 0x30, + 0x23, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x15, + 0x31, 0x16, 0x04, 0x14, 0xad, 0x7f, 0xeb, 0xe6, 0xb2, 0x6c, 0xf4, 0xdc, + 0x9f, 0x4d, 0x52, 0x40, 0x07, 0x15, 0xd9, 0xe8, 0xbc, 0x0d, 0x4e, 0xd7, + 0x30, 0x31, 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, + 0x1a, 0x05, 0x00, 0x04, 0x14, 0xa4, 0xac, 0xdb, 0xa8, 0x4c, 0xe9, 0x7a, + 0x02, 0x9d, 0x07, 0x39, 0x21, 0xf0, 0x71, 0xae, 0x46, 0x5a, 0xd8, 0x13, + 0x51, 0x04, 0x08, 0xa1, 0x52, 0xdd, 0x64, 0x46, 0xe9, 0x9e, 0x3e, 0x02, + 0x02, 0x08, 0x00}; + +class PK12ImportTest : public ::testing::Test {}; + +TEST_F(PK12ImportTest, ImportPK12With2P7) { + SECItem password = {siBuffer, nullptr, 0}; + ScopedPK11SlotInfo slot(PK11_GetInternalSlot()); + ScopedSEC_PKCS12DecoderContext dcx( + SEC_PKCS12DecoderStart(&password, slot.get(), nullptr, nullptr, nullptr, + nullptr, nullptr, nullptr)); + ASSERT_TRUE(dcx); + SECStatus rv = SEC_PKCS12DecoderUpdate( + dcx.get(), const_cast(cert_p12), sizeof(cert_p12)); + ASSERT_EQ(SECSuccess, rv); + rv = SEC_PKCS12DecoderVerify(dcx.get()); + // NSS can't properly decode this P12. But it shouldn't crash. + ASSERT_EQ(SECFailure, rv); +} + +} // namespace nss_test diff --git a/security/nss/gtests/nss_bogo_shim/config.json b/security/nss/gtests/nss_bogo_shim/config.json index fed7ca993..03f875466 100644 --- a/security/nss/gtests/nss_bogo_shim/config.json +++ b/security/nss/gtests/nss_bogo_shim/config.json @@ -1,6 +1,70 @@ { "DisabledTests": { "### These tests break whenever we rev versions, so just leave them here for easy uncommenting":"", + "SendWarningAlerts-Pass":"BoringSSL updated", + "SendBogusAlertType":"BoringSSL updated", + "SendEmptyRecords-Pass":"BoringSSL updated", + "ExtraCompressionMethods-TLS12":"BoringSSL updated", + "SendSNIWarningAlert":"BoringSSL updated", + "NoNullCompression-TLS12":"BoringSSL updated", + "InvalidCompressionMethod":"BoringSSL updated", + "SupportTicketsWithSessionID":"BoringSSL updated", + "NoSharedCipher":"BoringSSL updated", + "ServerHelloBogusCipher":"BoringSSL updated", + "ClientHelloVersionTooHigh":"BoringSSL updated", + "ServerAuth-SignatureType":"BoringSSL updated", + "ECDSACurveMismatch-Verify-TLS12":"BoringSSL updated", + "UnknownExtension-Client":"BoringSSL updated", + "UnofferedExtension-Client":"BoringSSL updated", + "SendClientVersion-RSA":"BoringSSL updated", + "SupportedCurves-ServerHello-TLS12":"BoringSSL updated", + "Basic-Client*Sync":"BoringSSL updated", + "Resume-Client-CipherMismatch":"BoringSSL updated", + "ClientAuth-SignatureType":"BoringSSL updated", + "Agree-Digest-Default":"BoringSSL updated", + "Basic-Server*Sync":"BoringSSL updated", + "ClientAuth-*-Sync":"BoringSSL updated", + "RSA-PSS-Default*":"BoringSSL updated", + "Renegotiate-Server-NoExt*":"BoringSSL updated", + "Downgrade-TLS12*":"BoringSSL updated", + "MaxCBCPadding":"BoringSSL updated", + "UnknownCipher":"BoringSSL updated", + "LargeMessage":"BoringSSL updated", + "NoCommonCurves":"BoringSSL updated", + "UnknownCurve":"BoringSSL updated", + "SessionTicketsDisabled*":"BoringSSL updated", + "BadFinished-*":"BoringSSL updated", + "ServerSkipCertificateVerify":"BoringSSL updated", + "*VersionTolerance":"BoringSSL updated", + "ConflictingVersionNegotiation*":"BoringSSL updated", + "Ed25519DefaultDisable*":"BoringSSL updated", + "*SHA1-Fallback*":"BoringSSL updated", + "ExtendedMasterSecret-NoToNo*":"BoringSSL updated", + "ServerNameExtensionClientMissing*":"BoringSSL updated", + "NoClientCertificate*":"BoringSSL updated", + "ServerCipherFilter*":"BoringSSL updated", + "*FallbackSCSV*":"BoringSSL updated", + "LooseInitialRecordVersion*":"BoringSSL updated", + "ALPNClient*":"BoringSSL updated", + "MinimumVersion*":"BoringSSL updated", + "VersionNegotiation*":"BoringSSL updated", + "*Client-ClientAuth*":"BoringSSL updated", + "*Server-ClientAuth*":"BoringSSL updated", + "NoExtendedMasterSecret*":"BoringSSL updated", + "PointFormat*":"BoringSSL updated", + "*Sync-SplitHandshakeRecords*":"BoringSSL updated", + "*Sync-PackHandshakeFlight*":"BoringSSL updated", + "TicketSessionIDLength*":"BoringSSL updated", + "*LargeRecord*":"BoringSSL updated", + "WrongMessageType-NewSessionTicket":"BoringSSL updated", + "WrongMessageType*Certificate*":"BoringSSL updated", + "WrongMessageType*Client*":"BoringSSL updated", + "WrongMessageType*Server*":"BoringSSL updated", + "WrongMessageType*DTLS":"BoringSSL updated", + "GarbageCertificate*":"BoringSSL updated", + "EmptyExtensions*":"BoringSSL updated", + "*OmitExtensions*":"BoringSSL updated", + "SupportedVersionSelection-TLS12":"Should maybe reject TLS 1.2 in SH.supported_versions (Bug 1438266)", "*TLS13*":"(NSS=19, BoGo=18)", "*HelloRetryRequest*":"(NSS=19, BoGo=18)", "*KeyShare*":"(NSS=19, BoGo=18)", diff --git a/security/nss/gtests/ssl_gtest/bloomfilter_unittest.cc b/security/nss/gtests/ssl_gtest/bloomfilter_unittest.cc index 110cfa13a..6efe06ec7 100644 --- a/security/nss/gtests/ssl_gtest/bloomfilter_unittest.cc +++ b/security/nss/gtests/ssl_gtest/bloomfilter_unittest.cc @@ -105,4 +105,4 @@ static const BloomFilterConfig kBloomFilterConfigurations[] = { INSTANTIATE_TEST_CASE_P(BloomFilterConfigurations, BloomFilterTest, ::testing::ValuesIn(kBloomFilterConfigurations)); -} // namespace nspr_test +} // namespace nss_test diff --git a/security/nss/gtests/ssl_gtest/libssl_internals.c b/security/nss/gtests/ssl_gtest/libssl_internals.c index 887d85278..17b4ffe49 100644 --- a/security/nss/gtests/ssl_gtest/libssl_internals.c +++ b/security/nss/gtests/ssl_gtest/libssl_internals.c @@ -332,10 +332,6 @@ void SSLInt_SetTicketLifetime(uint32_t lifetime) { ssl_ticket_lifetime = lifetime; } -void SSLInt_SetMaxEarlyDataSize(uint32_t size) { - ssl_max_early_data_size = size; -} - SECStatus SSLInt_SetSocketMaxEarlyDataSize(PRFileDesc *fd, uint32_t size) { sslSocket *ss; diff --git a/security/nss/gtests/ssl_gtest/libssl_internals.h b/security/nss/gtests/ssl_gtest/libssl_internals.h index 95d4afdaf..3efb362c2 100644 --- a/security/nss/gtests/ssl_gtest/libssl_internals.h +++ b/security/nss/gtests/ssl_gtest/libssl_internals.h @@ -50,7 +50,6 @@ PK11SymKey *SSLInt_CipherSpecToKey(const ssl3CipherSpec *spec); SSLCipherAlgorithm SSLInt_CipherSpecToAlgorithm(const ssl3CipherSpec *spec); const PRUint8 *SSLInt_CipherSpecToIv(const ssl3CipherSpec *spec); void SSLInt_SetTicketLifetime(uint32_t lifetime); -void SSLInt_SetMaxEarlyDataSize(uint32_t size); SECStatus SSLInt_SetSocketMaxEarlyDataSize(PRFileDesc *fd, uint32_t size); void SSLInt_RolloverAntiReplay(void); diff --git a/security/nss/gtests/ssl_gtest/ssl_0rtt_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_0rtt_unittest.cc index a60295490..08781af71 100644 --- a/security/nss/gtests/ssl_gtest/ssl_0rtt_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_0rtt_unittest.cc @@ -94,7 +94,7 @@ class TlsZeroRttReplayTest : public TlsConnectTls13 { // Now run a true 0-RTT handshake, but capture the first packet. auto first_packet = std::make_shared(); - client_->SetPacketFilter(first_packet); + client_->SetFilter(first_packet); client_->Set0RttEnabled(true); server_->Set0RttEnabled(true); ExpectResumption(RESUME_TICKET); @@ -116,8 +116,7 @@ class TlsZeroRttReplayTest : public TlsConnectTls13 { // Capture the early_data extension, which should not appear. auto early_data_ext = - std::make_shared(ssl_tls13_early_data_xtn); - server_->SetPacketFilter(early_data_ext); + MakeTlsFilter(server_, ssl_tls13_early_data_xtn); // Finally, replay the ClientHello and force the server to consume it. Stop // after the server sends its first flight; the client will not be able to @@ -405,6 +404,9 @@ TEST_P(TlsConnectTls13, TestTls13ZeroRttDowngrade) { // The client should abort the connection when sending a 0-rtt handshake but // the servers responds with a TLS 1.2 ServerHello. (with app data) TEST_P(TlsConnectTls13, TestTls13ZeroRttDowngradeEarlyData) { + const char* k0RttData = "ABCDEF"; + const PRInt32 k0RttDataLen = static_cast(strlen(k0RttData)); + ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET); server_->Set0RttEnabled(true); // set ticket_allow_early_data Connect(); @@ -422,27 +424,28 @@ TEST_P(TlsConnectTls13, TestTls13ZeroRttDowngradeEarlyData) { // Send the early data xtn in the CH, followed by early app data. The server // will fail right after sending its flight, when receiving the early data. client_->Set0RttEnabled(true); - ZeroRttSendReceive(true, false, [this]() { - client_->ExpectSendAlert(kTlsAlertIllegalParameter); - if (variant_ == ssl_variant_stream) { - server_->ExpectSendAlert(kTlsAlertUnexpectedMessage); - } - return true; - }); - - client_->Handshake(); - server_->Handshake(); - ASSERT_TRUE_WAIT( - (client_->error_code() == SSL_ERROR_DOWNGRADE_WITH_EARLY_DATA), 2000); + client_->Handshake(); // Send ClientHello. + PRInt32 rv = + PR_Write(client_->ssl_fd(), k0RttData, k0RttDataLen); // 0-RTT write. + EXPECT_EQ(k0RttDataLen, rv); - // DTLS will timeout as we bump the epoch when installing the early app data - // cipher suite. Thus the encrypted alert will be ignored. if (variant_ == ssl_variant_stream) { - // The server sends an alert when receiving the early app data record. - ASSERT_TRUE_WAIT( - (server_->error_code() == SSL_ERROR_RX_UNEXPECTED_APPLICATION_DATA), - 2000); + // When the server receives the early data, it will fail. + server_->ExpectSendAlert(kTlsAlertUnexpectedMessage); + server_->Handshake(); // Consume ClientHello + EXPECT_EQ(TlsAgent::STATE_ERROR, server_->state()); + server_->CheckErrorCode(SSL_ERROR_RX_UNEXPECTED_APPLICATION_DATA); + } else { + // If it's datagram, we just discard the early data. + server_->Handshake(); // Consume ClientHello + EXPECT_EQ(TlsAgent::STATE_CONNECTING, server_->state()); } + + // The client now reads the ServerHello and fails. + ASSERT_EQ(TlsAgent::STATE_CONNECTING, client_->state()); + client_->ExpectSendAlert(kTlsAlertIllegalParameter); + client_->Handshake(); + client_->CheckErrorCode(SSL_ERROR_DOWNGRADE_WITH_EARLY_DATA); } static void CheckEarlyDataLimit(const std::shared_ptr& agent, @@ -455,10 +458,13 @@ static void CheckEarlyDataLimit(const std::shared_ptr& agent, } TEST_P(TlsConnectTls13, SendTooMuchEarlyData) { + EnsureTlsSetup(); const char* big_message = "0123456789abcdef"; const size_t short_size = strlen(big_message) - 1; const PRInt32 short_length = static_cast(short_size); - SSLInt_SetMaxEarlyDataSize(static_cast(short_size)); + EXPECT_EQ(SECSuccess, + SSL_SetMaxEarlyDataSize(server_->ssl_fd(), + static_cast(short_size))); SetupForZeroRtt(); client_->Set0RttEnabled(true); @@ -510,8 +516,10 @@ TEST_P(TlsConnectTls13, SendTooMuchEarlyData) { } TEST_P(TlsConnectTls13, ReceiveTooMuchEarlyData) { + EnsureTlsSetup(); + const size_t limit = 5; - SSLInt_SetMaxEarlyDataSize(limit); + EXPECT_EQ(SECSuccess, SSL_SetMaxEarlyDataSize(server_->ssl_fd(), limit)); SetupForZeroRtt(); client_->Set0RttEnabled(true); @@ -521,6 +529,8 @@ TEST_P(TlsConnectTls13, ReceiveTooMuchEarlyData) { client_->Handshake(); // Send ClientHello CheckEarlyDataLimit(client_, limit); + server_->Handshake(); // Process ClientHello, send server flight. + // Lift the limit on the client. EXPECT_EQ(SECSuccess, SSLInt_SetSocketMaxEarlyDataSize(client_->ssl_fd(), 1000)); @@ -534,21 +544,31 @@ TEST_P(TlsConnectTls13, ReceiveTooMuchEarlyData) { // This error isn't fatal for DTLS. ExpectAlert(server_, kTlsAlertUnexpectedMessage); } - server_->Handshake(); // Process ClientHello, send server flight. - server_->Handshake(); // Just to make sure that we don't read ahead. + + server_->Handshake(); // This reads the early data and maybe throws an error. + if (variant_ == ssl_variant_stream) { + server_->CheckErrorCode(SSL_ERROR_TOO_MUCH_EARLY_DATA); + } else { + EXPECT_EQ(TlsAgent::STATE_CONNECTING, server_->state()); + } CheckEarlyDataLimit(server_, limit); - // Attempt to read early data. + // Attempt to read early data. This will get an error. std::vector buf(strlen(message) + 1); EXPECT_GT(0, PR_Read(server_->ssl_fd(), buf.data(), buf.capacity())); if (variant_ == ssl_variant_stream) { - server_->CheckErrorCode(SSL_ERROR_TOO_MUCH_EARLY_DATA); + EXPECT_EQ(SSL_ERROR_HANDSHAKE_FAILED, PORT_GetError()); + } else { + EXPECT_EQ(PR_WOULD_BLOCK_ERROR, PORT_GetError()); } - client_->Handshake(); // Process the handshake. - client_->Handshake(); // Process the alert. + client_->Handshake(); // Process the server's first flight. if (variant_ == ssl_variant_stream) { + client_->Handshake(); // Process the alert. client_->CheckErrorCode(SSL_ERROR_HANDSHAKE_UNEXPECTED_ALERT); + } else { + server_->Handshake(); // Finish connecting. + EXPECT_EQ(TlsAgent::STATE_CONNECTED, server_->state()); } } @@ -583,7 +603,7 @@ TEST_P(TlsConnectTls13, ZeroRttOrdering) { // Now, coalesce the next three things from the client: early data, second // flight and 1-RTT data. auto coalesce = std::make_shared(); - client_->SetPacketFilter(coalesce); + client_->SetFilter(coalesce); // Send (and hold) early data. static const std::vector early_data = {3, 2, 1}; diff --git a/security/nss/gtests/ssl_gtest/ssl_agent_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_agent_unittest.cc index 0aa9a4c78..f0c57e8b1 100644 --- a/security/nss/gtests/ssl_gtest/ssl_agent_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_agent_unittest.cc @@ -160,9 +160,8 @@ TEST_F(TlsAgentStreamTestClient, Set0RttOptionThenWrite) { SSL_LIBRARY_VERSION_TLS_1_3); agent_->StartConnect(); agent_->Set0RttEnabled(true); - auto filter = std::make_shared( - kTlsHandshakeClientHello); - agent_->SetPacketFilter(filter); + auto filter = + MakeTlsFilter(agent_, kTlsHandshakeClientHello); PRInt32 rv = PR_Write(agent_->ssl_fd(), k0RttData, strlen(k0RttData)); EXPECT_EQ(-1, rv); int32_t err = PORT_GetError(); diff --git a/security/nss/gtests/ssl_gtest/ssl_auth_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_auth_unittest.cc index dbcdd92ea..7f2b2840d 100644 --- a/security/nss/gtests/ssl_gtest/ssl_auth_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_auth_unittest.cc @@ -95,10 +95,9 @@ TEST_P(TlsConnectGeneric, ClientAuthBigRsa) { } // Offset is the position in the captured buffer where the signature sits. -static void CheckSigScheme( - std::shared_ptr& capture, size_t offset, - std::shared_ptr& peer, uint16_t expected_scheme, - size_t expected_size) { +static void CheckSigScheme(std::shared_ptr& capture, + size_t offset, std::shared_ptr& peer, + uint16_t expected_scheme, size_t expected_size) { EXPECT_LT(offset + 2U, capture->buffer().len()); uint32_t scheme = 0; @@ -114,9 +113,8 @@ static void CheckSigScheme( // in the default certificate. TEST_P(TlsConnectTls12, ServerAuthCheckSigAlg) { EnsureTlsSetup(); - auto capture_ske = std::make_shared( - kTlsHandshakeServerKeyExchange); - server_->SetPacketFilter(capture_ske); + auto capture_ske = MakeTlsFilter( + server_, kTlsHandshakeServerKeyExchange); Connect(); CheckKeys(); @@ -127,15 +125,14 @@ TEST_P(TlsConnectTls12, ServerAuthCheckSigAlg) { EXPECT_TRUE(buffer.Read(1, 2, &tmp)) << "read NamedCurve"; EXPECT_EQ(ssl_grp_ec_curve25519, tmp); EXPECT_TRUE(buffer.Read(3, 1, &tmp)) << " read ECPoint"; - CheckSigScheme(capture_ske, 4 + tmp, client_, ssl_sig_rsa_pss_sha256, 1024); + CheckSigScheme(capture_ske, 4 + tmp, client_, ssl_sig_rsa_pss_rsae_sha256, + 1024); } TEST_P(TlsConnectTls12, ClientAuthCheckSigAlg) { EnsureTlsSetup(); - auto capture_cert_verify = - std::make_shared( - kTlsHandshakeCertificateVerify); - client_->SetPacketFilter(capture_cert_verify); + auto capture_cert_verify = MakeTlsFilter( + client_, kTlsHandshakeCertificateVerify); client_->SetupClientAuth(); server_->RequestClientAuth(true); Connect(); @@ -146,21 +143,20 @@ TEST_P(TlsConnectTls12, ClientAuthCheckSigAlg) { TEST_P(TlsConnectTls12, ClientAuthBigRsaCheckSigAlg) { Reset(TlsAgent::kServerRsa, TlsAgent::kRsa2048); - auto capture_cert_verify = - std::make_shared( - kTlsHandshakeCertificateVerify); - client_->SetPacketFilter(capture_cert_verify); + auto capture_cert_verify = MakeTlsFilter( + client_, kTlsHandshakeCertificateVerify); client_->SetupClientAuth(); server_->RequestClientAuth(true); Connect(); CheckKeys(); - CheckSigScheme(capture_cert_verify, 0, server_, ssl_sig_rsa_pss_sha256, 2048); + CheckSigScheme(capture_cert_verify, 0, server_, ssl_sig_rsa_pss_rsae_sha256, + 2048); } class TlsZeroCertificateRequestSigAlgsFilter : public TlsHandshakeFilter { public: - TlsZeroCertificateRequestSigAlgsFilter() - : TlsHandshakeFilter({kTlsHandshakeCertificateRequest}) {} + TlsZeroCertificateRequestSigAlgsFilter(const std::shared_ptr& agent) + : TlsHandshakeFilter(agent, {kTlsHandshakeCertificateRequest}) {} virtual PacketFilter::Action FilterHandshake( const TlsHandshakeFilter::HandshakeHeader& header, const DataBuffer& input, DataBuffer* output) { @@ -205,12 +201,9 @@ class TlsZeroCertificateRequestSigAlgsFilter : public TlsHandshakeFilter { // supported_signature_algorithms in the CertificateRequest message. TEST_P(TlsConnectTls12, ClientAuthNoSigAlgsFallback) { EnsureTlsSetup(); - auto filter = std::make_shared(); - server_->SetPacketFilter(filter); - auto capture_cert_verify = - std::make_shared( - kTlsHandshakeCertificateVerify); - client_->SetPacketFilter(capture_cert_verify); + MakeTlsFilter(server_); + auto capture_cert_verify = MakeTlsFilter( + client_, kTlsHandshakeCertificateVerify); client_->SetupClientAuth(); server_->RequestClientAuth(true); @@ -358,8 +351,7 @@ TEST_P(TlsConnectPre12, SignatureAlgorithmNoOverlapEcdsa) { // The signature_algorithms extension is mandatory in TLS 1.3. TEST_P(TlsConnectTls13, SignatureAlgorithmDrop) { - client_->SetPacketFilter( - std::make_shared(ssl_signature_algorithms_xtn)); + MakeTlsFilter(client_, ssl_signature_algorithms_xtn); ConnectExpectAlert(server_, kTlsAlertMissingExtension); client_->CheckErrorCode(SSL_ERROR_MISSING_EXTENSION_ALERT); server_->CheckErrorCode(SSL_ERROR_MISSING_SIGNATURE_ALGORITHMS_EXTENSION); @@ -368,8 +360,7 @@ TEST_P(TlsConnectTls13, SignatureAlgorithmDrop) { // TLS 1.2 has trouble detecting this sort of modification: it uses SHA1 and // only fails when the Finished is checked. TEST_P(TlsConnectTls12, SignatureAlgorithmDrop) { - client_->SetPacketFilter( - std::make_shared(ssl_signature_algorithms_xtn)); + MakeTlsFilter(client_, ssl_signature_algorithms_xtn); ConnectExpectAlert(server_, kTlsAlertDecryptError); client_->CheckErrorCode(SSL_ERROR_DECRYPT_ERROR_ALERT); server_->CheckErrorCode(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE); @@ -387,11 +378,11 @@ class BeforeFinished : public TlsRecordFilter { enum HandshakeState { BEFORE_CCS, AFTER_CCS, DONE }; public: - BeforeFinished(std::shared_ptr& client, - std::shared_ptr& server, VoidFunction before_ccs, - VoidFunction before_finished) - : client_(client), - server_(server), + BeforeFinished(const std::shared_ptr& server, + const std::shared_ptr& client, + VoidFunction before_ccs, VoidFunction before_finished) + : TlsRecordFilter(server), + client_(client), before_ccs_(before_ccs), before_finished_(before_finished), state_(BEFORE_CCS) {} @@ -411,7 +402,7 @@ class BeforeFinished : public TlsRecordFilter { // but that means that they both get processed together. DataBuffer ccs; header.Write(&ccs, 0, body); - server_.lock()->SendDirect(ccs); + agent()->SendDirect(ccs); client_.lock()->Handshake(); state_ = AFTER_CCS; // Request that the original record be dropped by the filter. @@ -436,7 +427,6 @@ class BeforeFinished : public TlsRecordFilter { private: std::weak_ptr client_; - std::weak_ptr server_; VoidFunction before_ccs_; VoidFunction before_finished_; HandshakeState state_; @@ -461,11 +451,11 @@ class BeforeFinished13 : public PacketFilter { }; public: - BeforeFinished13(std::shared_ptr& client, - std::shared_ptr& server, + BeforeFinished13(const std::shared_ptr& server, + const std::shared_ptr& client, VoidFunction before_finished) - : client_(client), - server_(server), + : server_(server), + client_(client), before_finished_(before_finished), records_(0) {} @@ -497,8 +487,8 @@ class BeforeFinished13 : public PacketFilter { } private: - std::weak_ptr client_; std::weak_ptr server_; + std::weak_ptr client_; VoidFunction before_finished_; size_t records_; }; @@ -512,11 +502,9 @@ static SECStatus AuthCompleteBlock(TlsAgent*, PRBool, PRBool) { // processed by the client, SSL_AuthCertificateComplete() is called. TEST_F(TlsConnectDatagram13, AuthCompleteBeforeFinished) { client_->SetAuthCertificateCallback(AuthCompleteBlock); - server_->SetPacketFilter( - std::make_shared(client_, server_, [this]() { - EXPECT_EQ(SECSuccess, - SSL_AuthCertificateComplete(client_->ssl_fd(), 0)); - })); + MakeTlsFilter(server_, client_, [this]() { + EXPECT_EQ(SECSuccess, SSL_AuthCertificateComplete(client_->ssl_fd(), 0)); + }); Connect(); } @@ -544,13 +532,13 @@ TEST_F(TlsConnectDatagram13, AuthCompleteAfterFinished) { TEST_P(TlsConnectGenericPre13, ClientWriteBetweenCCSAndFinishedWithFalseStart) { client_->EnableFalseStart(); - server_->SetPacketFilter(std::make_shared( - client_, server_, + MakeTlsFilter( + server_, client_, [this]() { EXPECT_TRUE(client_->can_falsestart_hook_called()); }, [this]() { // Write something, which used to fail: bug 1235366. client_->SendData(10); - })); + }); Connect(); server_->SendData(10); @@ -560,8 +548,8 @@ TEST_P(TlsConnectGenericPre13, ClientWriteBetweenCCSAndFinishedWithFalseStart) { TEST_P(TlsConnectGenericPre13, AuthCompleteBeforeFinishedWithFalseStart) { client_->EnableFalseStart(); client_->SetAuthCertificateCallback(AuthCompleteBlock); - server_->SetPacketFilter(std::make_shared( - client_, server_, + MakeTlsFilter( + server_, client_, []() { // Do nothing before CCS }, @@ -572,7 +560,7 @@ TEST_P(TlsConnectGenericPre13, AuthCompleteBeforeFinishedWithFalseStart) { SSL_AuthCertificateComplete(client_->ssl_fd(), 0)); EXPECT_TRUE(client_->can_falsestart_hook_called()); client_->SendData(10); - })); + }); Connect(); server_->SendData(10); @@ -606,7 +594,7 @@ TEST_P(TlsConnectGenericPre13, AuthCompleteDelayed) { EXPECT_EQ(TlsAgent::STATE_CONNECTED, server_->state()); // The client should send nothing from here on. - client_->SetPacketFilter(std::make_shared()); + client_->SetFilter(std::make_shared()); client_->Handshake(); EXPECT_EQ(TlsAgent::STATE_CONNECTING, client_->state()); @@ -616,8 +604,33 @@ TEST_P(TlsConnectGenericPre13, AuthCompleteDelayed) { EXPECT_EQ(TlsAgent::STATE_CONNECTED, client_->state()); EXPECT_EQ(TlsAgent::STATE_CONNECTED, server_->state()); - // Remove this before closing or the close_notify alert will trigger it. - client_->DeletePacketFilter(); + // Remove filter before closing or the close_notify alert will trigger it. + client_->ClearFilter(); +} + +TEST_P(TlsConnectGenericPre13, AuthCompleteFailDelayed) { + client_->SetAuthCertificateCallback(AuthCompleteBlock); + + StartConnect(); + client_->Handshake(); // Send ClientHello + server_->Handshake(); // Send ServerHello + client_->Handshake(); // Send ClientKeyExchange and Finished + server_->Handshake(); // Send Finished + // The server should now report that it is connected + EXPECT_EQ(TlsAgent::STATE_CONNECTED, server_->state()); + + // The client should send nothing from here on. + client_->SetFilter(std::make_shared()); + client_->Handshake(); + EXPECT_EQ(TlsAgent::STATE_CONNECTING, client_->state()); + + // Report failure. + client_->ClearFilter(); + client_->ExpectSendAlert(kTlsAlertBadCertificate); + EXPECT_EQ(SECSuccess, SSL_AuthCertificateComplete(client_->ssl_fd(), + SSL_ERROR_BAD_CERTIFICATE)); + client_->Handshake(); // Fail + EXPECT_EQ(TlsAgent::STATE_ERROR, client_->state()); } // TLS 1.3 handles a delayed AuthComplete callback differently since the @@ -632,12 +645,12 @@ TEST_P(TlsConnectTls13, AuthCompleteDelayed) { EXPECT_EQ(TlsAgent::STATE_CONNECTING, server_->state()); // The client will send nothing until AuthCertificateComplete is called. - client_->SetPacketFilter(std::make_shared()); + client_->SetFilter(std::make_shared()); client_->Handshake(); EXPECT_EQ(TlsAgent::STATE_CONNECTING, client_->state()); // This should allow the handshake to complete now. - client_->DeletePacketFilter(); + client_->ClearFilter(); EXPECT_EQ(SECSuccess, SSL_AuthCertificateComplete(client_->ssl_fd(), 0)); client_->Handshake(); // Send Finished server_->Handshake(); // Transition to connected and send NewSessionTicket @@ -645,6 +658,44 @@ TEST_P(TlsConnectTls13, AuthCompleteDelayed) { EXPECT_EQ(TlsAgent::STATE_CONNECTED, server_->state()); } +TEST_P(TlsConnectTls13, AuthCompleteFailDelayed) { + client_->SetAuthCertificateCallback(AuthCompleteBlock); + + StartConnect(); + client_->Handshake(); // Send ClientHello + server_->Handshake(); // Send ServerHello + EXPECT_EQ(TlsAgent::STATE_CONNECTING, client_->state()); + EXPECT_EQ(TlsAgent::STATE_CONNECTING, server_->state()); + + // The client will send nothing until AuthCertificateComplete is called. + client_->SetFilter(std::make_shared()); + client_->Handshake(); + EXPECT_EQ(TlsAgent::STATE_CONNECTING, client_->state()); + + // Report failure. + client_->ClearFilter(); + ExpectAlert(client_, kTlsAlertBadCertificate); + EXPECT_EQ(SECSuccess, SSL_AuthCertificateComplete(client_->ssl_fd(), + SSL_ERROR_BAD_CERTIFICATE)); + client_->Handshake(); // This should now fail. + server_->Handshake(); // Get the error. + EXPECT_EQ(TlsAgent::STATE_ERROR, client_->state()); + EXPECT_EQ(TlsAgent::STATE_ERROR, server_->state()); +} + +static SECStatus AuthCompleteFail(TlsAgent*, PRBool, PRBool) { + PORT_SetError(SSL_ERROR_BAD_CERTIFICATE); + return SECFailure; +} + +TEST_P(TlsConnectGeneric, AuthFailImmediate) { + client_->SetAuthCertificateCallback(AuthCompleteFail); + + StartConnect(); + ConnectExpectAlert(client_, kTlsAlertBadCertificate); + client_->CheckErrorCode(SSL_ERROR_BAD_CERTIFICATE); +} + static const SSLExtraServerCertData ServerCertDataRsaPkcs1Decrypt = { ssl_auth_rsa_decrypt, nullptr, nullptr, nullptr}; static const SSLExtraServerCertData ServerCertDataRsaPkcs1Sign = { @@ -767,8 +818,7 @@ TEST_P(TlsSignatureSchemeConfiguration, SignatureSchemeConfigServer) { TEST_P(TlsSignatureSchemeConfiguration, SignatureSchemeConfigClient) { Reset(certificate_); auto capture = - std::make_shared(ssl_signature_algorithms_xtn); - client_->SetPacketFilter(capture); + MakeTlsFilter(client_, ssl_signature_algorithms_xtn); TestSignatureSchemeConfig(client_); const DataBuffer& ext = capture->extension(); @@ -796,8 +846,8 @@ INSTANTIATE_TEST_CASE_P( ::testing::Values(TlsAgent::kServerRsaSign), ::testing::Values(ssl_auth_rsa_sign), ::testing::Values(ssl_sig_rsa_pkcs1_sha256, ssl_sig_rsa_pkcs1_sha384, - ssl_sig_rsa_pkcs1_sha512, ssl_sig_rsa_pss_sha256, - ssl_sig_rsa_pss_sha384))); + ssl_sig_rsa_pkcs1_sha512, ssl_sig_rsa_pss_rsae_sha256, + ssl_sig_rsa_pss_rsae_sha384))); // PSS with SHA-512 needs a bigger key to work. INSTANTIATE_TEST_CASE_P( SignatureSchemeBigRsa, TlsSignatureSchemeConfiguration, @@ -805,7 +855,7 @@ INSTANTIATE_TEST_CASE_P( TlsConnectTestBase::kTlsV12Plus, ::testing::Values(TlsAgent::kRsa2048), ::testing::Values(ssl_auth_rsa_sign), - ::testing::Values(ssl_sig_rsa_pss_sha512))); + ::testing::Values(ssl_sig_rsa_pss_rsae_sha512))); INSTANTIATE_TEST_CASE_P( SignatureSchemeRsaSha1, TlsSignatureSchemeConfiguration, ::testing::Combine(TlsConnectTestBase::kTlsVariantsAll, @@ -842,4 +892,4 @@ INSTANTIATE_TEST_CASE_P( TlsAgent::kServerEcdsa384), ::testing::Values(ssl_auth_ecdsa), ::testing::Values(ssl_sig_ecdsa_sha1))); -} +} // namespace nss_test diff --git a/security/nss/gtests/ssl_gtest/ssl_cert_ext_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_cert_ext_unittest.cc index 36ee104af..573c69c75 100644 --- a/security/nss/gtests/ssl_gtest/ssl_cert_ext_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_cert_ext_unittest.cc @@ -180,9 +180,8 @@ TEST_P(TlsConnectGenericPre13, OcspMangled) { server_->ConfigServerCert(TlsAgent::kServerRsa, true, &kOcspExtraData)); static const uint8_t val[] = {1}; - auto replacer = std::make_shared( - ssl_cert_status_xtn, DataBuffer(val, sizeof(val))); - server_->SetPacketFilter(replacer); + auto replacer = MakeTlsFilter( + server_, ssl_cert_status_xtn, DataBuffer(val, sizeof(val))); ConnectExpectAlert(client_, kTlsAlertIllegalParameter); client_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_SERVER_HELLO); server_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT); @@ -192,8 +191,7 @@ TEST_P(TlsConnectGeneric, OcspSuccess) { EnsureTlsSetup(); client_->SetOption(SSL_ENABLE_OCSP_STAPLING, PR_TRUE); auto capture_ocsp = - std::make_shared(ssl_cert_status_xtn); - server_->SetPacketFilter(capture_ocsp); + MakeTlsFilter(server_, ssl_cert_status_xtn); // The value should be available during the AuthCertificateCallback client_->SetAuthCertificateCallback([](TlsAgent* agent, bool checksig, @@ -245,4 +243,4 @@ TEST_P(TlsConnectGeneric, OcspHugeSuccess) { Connect(); } -} // namespace nspr_test +} // namespace nss_test diff --git a/security/nss/gtests/ssl_gtest/ssl_ciphersuite_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_ciphersuite_unittest.cc index 810656868..fa2238be7 100644 --- a/security/nss/gtests/ssl_gtest/ssl_ciphersuite_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_ciphersuite_unittest.cc @@ -74,12 +74,12 @@ class TlsCipherSuiteTestBase : public TlsConnectTestBase { Reset(TlsAgent::kServerRsaSign); auth_type_ = ssl_auth_rsa_sign; break; - case ssl_sig_rsa_pss_sha256: - case ssl_sig_rsa_pss_sha384: + case ssl_sig_rsa_pss_rsae_sha256: + case ssl_sig_rsa_pss_rsae_sha384: Reset(TlsAgent::kServerRsaSign); auth_type_ = ssl_auth_rsa_sign; break; - case ssl_sig_rsa_pss_sha512: + case ssl_sig_rsa_pss_rsae_sha512: // You can't fit SHA-512 PSS in a 1024-bit key. Reset(TlsAgent::kRsa2048); auth_type_ = ssl_auth_rsa_sign; @@ -313,8 +313,8 @@ static const auto kDummySignatureSchemesParams = static SSLSignatureScheme kSignatureSchemesParamsArr[] = { ssl_sig_rsa_pkcs1_sha256, ssl_sig_rsa_pkcs1_sha384, ssl_sig_rsa_pkcs1_sha512, ssl_sig_ecdsa_secp256r1_sha256, - ssl_sig_ecdsa_secp384r1_sha384, ssl_sig_rsa_pss_sha256, - ssl_sig_rsa_pss_sha384, ssl_sig_rsa_pss_sha512, + ssl_sig_ecdsa_secp384r1_sha384, ssl_sig_rsa_pss_rsae_sha256, + ssl_sig_rsa_pss_rsae_sha384, ssl_sig_rsa_pss_rsae_sha512, }; #endif @@ -466,4 +466,4 @@ static const SecStatusParams kSecStatusTestValuesArr[] = { INSTANTIATE_TEST_CASE_P(TestSecurityStatus, SecurityStatusTest, ::testing::ValuesIn(kSecStatusTestValuesArr)); -} // namespace nspr_test +} // namespace nss_test diff --git a/security/nss/gtests/ssl_gtest/ssl_custext_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_custext_unittest.cc index dad944a1f..c2f582a93 100644 --- a/security/nss/gtests/ssl_gtest/ssl_custext_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_custext_unittest.cc @@ -150,9 +150,8 @@ TEST_F(TlsConnectStreamTls13, CustomExtensionWriterDisable) { client_->ssl_fd(), ssl_signed_cert_timestamp_xtn, NoopExtensionWriter, nullptr, NoopExtensionHandler, nullptr); EXPECT_EQ(SECSuccess, rv); - auto capture = - std::make_shared(ssl_signed_cert_timestamp_xtn); - client_->SetPacketFilter(capture); + auto capture = MakeTlsFilter( + client_, ssl_signed_cert_timestamp_xtn); Connect(); // So nothing will be sent. @@ -204,9 +203,8 @@ TEST_F(TlsConnectStreamTls13, CustomExtensionOverride) { EXPECT_EQ(SECSuccess, rv); // Capture it to see what we got. - auto capture = - std::make_shared(ssl_signed_cert_timestamp_xtn); - client_->SetPacketFilter(capture); + auto capture = MakeTlsFilter( + client_, ssl_signed_cert_timestamp_xtn); ConnectExpectAlert(server_, kTlsAlertDecodeError); @@ -246,8 +244,7 @@ TEST_F(TlsConnectStreamTls13, CustomExtensionClientToServer) { EXPECT_EQ(SECSuccess, rv); // Capture it to see what we got. - auto capture = std::make_shared(extension_code); - client_->SetPacketFilter(capture); + auto capture = MakeTlsFilter(client_, extension_code); // Handle it so that the handshake completes. rv = SSL_InstallExtensionHooks(server_->ssl_fd(), extension_code, @@ -290,9 +287,8 @@ TEST_F(TlsConnectStreamTls13, CustomExtensionServerToClientSH) { EXPECT_EQ(SECSuccess, rv); // Capture the extension from the ServerHello only and check it. - auto capture = std::make_shared(extension_code); + auto capture = MakeTlsFilter(server_, extension_code); capture->SetHandshakeTypes({kTlsHandshakeServerHello}); - server_->SetPacketFilter(capture); Connect(); @@ -329,9 +325,9 @@ TEST_F(TlsConnectStreamTls13, CustomExtensionServerToClientEE) { EXPECT_EQ(SECSuccess, rv); // Capture the extension from the EncryptedExtensions only and check it. - auto capture = std::make_shared(extension_code); + auto capture = MakeTlsFilter(server_, extension_code); capture->SetHandshakeTypes({kTlsHandshakeEncryptedExtensions}); - server_->SetTlsRecordFilter(capture); + capture->EnableDecryption(); Connect(); @@ -350,8 +346,7 @@ TEST_F(TlsConnectStreamTls13, CustomExtensionUnsolicitedServer) { EXPECT_EQ(SECSuccess, rv); // Capture it to see what we got. - auto capture = std::make_shared(extension_code); - server_->SetPacketFilter(capture); + auto capture = MakeTlsFilter(server_, extension_code); client_->ExpectSendAlert(kTlsAlertUnsupportedExtension); server_->ExpectSendAlert(kTlsAlertBadRecordMac); @@ -500,4 +495,4 @@ TEST_F(TlsConnectStreamTls13, CustomExtensionOverrunBuffer) { client_->CheckErrorCode(SEC_ERROR_APPLICATION_CALLBACK_ERROR); } -} // namespace "nss_test" +} // namespace nss_test diff --git a/security/nss/gtests/ssl_gtest/ssl_damage_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_damage_unittest.cc index d1668b823..b8836d7fc 100644 --- a/security/nss/gtests/ssl_gtest/ssl_damage_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_damage_unittest.cc @@ -50,19 +50,19 @@ TEST_F(TlsConnectTest, DamageSecretHandleServerFinished) { SSL_LIBRARY_VERSION_TLS_1_3); server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1, SSL_LIBRARY_VERSION_TLS_1_3); - server_->SetPacketFilter(std::make_shared( + MakeTlsFilter( server_, client_, 0, // ServerHello. - [this]() { SSLInt_DamageServerHsTrafficSecret(client_->ssl_fd()); })); + [this]() { SSLInt_DamageServerHsTrafficSecret(client_->ssl_fd()); }); ConnectExpectAlert(client_, kTlsAlertDecryptError); client_->CheckErrorCode(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE); } TEST_P(TlsConnectGenericPre13, DamageServerSignature) { EnsureTlsSetup(); - auto filter = - std::make_shared(kTlsHandshakeServerKeyExchange); - server_->SetTlsRecordFilter(filter); + auto filter = MakeTlsFilter( + server_, kTlsHandshakeServerKeyExchange); + filter->EnableDecryption(); ExpectAlert(client_, kTlsAlertDecryptError); ConnectExpectFail(); client_->CheckErrorCode(SEC_ERROR_BAD_SIGNATURE); @@ -71,9 +71,9 @@ TEST_P(TlsConnectGenericPre13, DamageServerSignature) { TEST_P(TlsConnectTls13, DamageServerSignature) { EnsureTlsSetup(); - auto filter = - std::make_shared(kTlsHandshakeCertificateVerify); - server_->SetTlsRecordFilter(filter); + auto filter = MakeTlsFilter( + server_, kTlsHandshakeCertificateVerify); + filter->EnableDecryption(); ConnectExpectAlert(client_, kTlsAlertDecryptError); client_->CheckErrorCode(SEC_ERROR_BAD_SIGNATURE); } @@ -82,9 +82,9 @@ TEST_P(TlsConnectGeneric, DamageClientSignature) { EnsureTlsSetup(); client_->SetupClientAuth(); server_->RequestClientAuth(true); - auto filter = - std::make_shared(kTlsHandshakeCertificateVerify); - client_->SetTlsRecordFilter(filter); + auto filter = MakeTlsFilter( + client_, kTlsHandshakeCertificateVerify); + filter->EnableDecryption(); server_->ExpectSendAlert(kTlsAlertDecryptError); // Do these handshakes by hand to avoid race condition on // the client processing the server's alert. @@ -100,4 +100,4 @@ TEST_P(TlsConnectGeneric, DamageClientSignature) { server_->CheckErrorCode(SEC_ERROR_BAD_SIGNATURE); } -} // namespace nspr_test +} // namespace nss_test diff --git a/security/nss/gtests/ssl_gtest/ssl_dhe_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_dhe_unittest.cc index 4aa3bb639..cdafa7a84 100644 --- a/security/nss/gtests/ssl_gtest/ssl_dhe_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_dhe_unittest.cc @@ -24,7 +24,7 @@ TEST_P(TlsConnectGeneric, ConnectDhe) { EnableOnlyDheCiphers(); Connect(); CheckKeys(ssl_kea_dh, ssl_grp_ffdhe_2048, ssl_auth_rsa_sign, - ssl_sig_rsa_pss_sha256); + ssl_sig_rsa_pss_rsae_sha256); } TEST_P(TlsConnectTls13, SharesForBothEcdheAndDhe) { @@ -32,12 +32,12 @@ TEST_P(TlsConnectTls13, SharesForBothEcdheAndDhe) { client_->ConfigNamedGroups(kAllDHEGroups); auto groups_capture = - std::make_shared(ssl_supported_groups_xtn); + std::make_shared(client_, ssl_supported_groups_xtn); auto shares_capture = - std::make_shared(ssl_tls13_key_share_xtn); + std::make_shared(client_, ssl_tls13_key_share_xtn); std::vector> captures = {groups_capture, shares_capture}; - client_->SetPacketFilter(std::make_shared(captures)); + client_->SetFilter(std::make_shared(captures)); Connect(); @@ -61,12 +61,12 @@ TEST_P(TlsConnectGeneric, ConnectFfdheClient) { EnableOnlyDheCiphers(); client_->SetOption(SSL_REQUIRE_DH_NAMED_GROUPS, PR_TRUE); auto groups_capture = - std::make_shared(ssl_supported_groups_xtn); + std::make_shared(client_, ssl_supported_groups_xtn); auto shares_capture = - std::make_shared(ssl_tls13_key_share_xtn); + std::make_shared(client_, ssl_tls13_key_share_xtn); std::vector> captures = {groups_capture, shares_capture}; - client_->SetPacketFilter(std::make_shared(captures)); + client_->SetFilter(std::make_shared(captures)); Connect(); @@ -103,8 +103,8 @@ TEST_P(TlsConnectGenericPre13, ConnectFfdheServer) { class TlsDheServerKeyExchangeDamager : public TlsHandshakeFilter { public: - TlsDheServerKeyExchangeDamager() - : TlsHandshakeFilter({kTlsHandshakeServerKeyExchange}) {} + TlsDheServerKeyExchangeDamager(const std::shared_ptr& agent) + : TlsHandshakeFilter(agent, {kTlsHandshakeServerKeyExchange}) {} virtual PacketFilter::Action FilterHandshake( const TlsHandshakeFilter::HandshakeHeader& header, const DataBuffer& input, DataBuffer* output) { @@ -122,7 +122,7 @@ class TlsDheServerKeyExchangeDamager : public TlsHandshakeFilter { TEST_P(TlsConnectGenericPre13, DamageServerKeyShare) { EnableOnlyDheCiphers(); client_->SetOption(SSL_REQUIRE_DH_NAMED_GROUPS, PR_TRUE); - server_->SetPacketFilter(std::make_shared()); + MakeTlsFilter(server_); ConnectExpectAlert(client_, kTlsAlertIllegalParameter); @@ -141,8 +141,9 @@ class TlsDheSkeChangeY : public TlsHandshakeFilter { kYZeroPad }; - TlsDheSkeChangeY(uint8_t handshake_type, ChangeYTo change) - : TlsHandshakeFilter({handshake_type}), change_Y_(change) {} + TlsDheSkeChangeY(const std::shared_ptr& agent, + uint8_t handshake_type, ChangeYTo change) + : TlsHandshakeFilter(agent, {handshake_type}), change_Y_(change) {} protected: void ChangeY(const DataBuffer& input, DataBuffer* output, size_t offset, @@ -207,8 +208,9 @@ class TlsDheSkeChangeY : public TlsHandshakeFilter { class TlsDheSkeChangeYServer : public TlsDheSkeChangeY { public: - TlsDheSkeChangeYServer(ChangeYTo change, bool modify) - : TlsDheSkeChangeY(kTlsHandshakeServerKeyExchange, change), + TlsDheSkeChangeYServer(const std::shared_ptr& agent, + ChangeYTo change, bool modify) + : TlsDheSkeChangeY(agent, kTlsHandshakeServerKeyExchange, change), modify_(modify), p_() {} @@ -245,9 +247,9 @@ class TlsDheSkeChangeYServer : public TlsDheSkeChangeY { class TlsDheSkeChangeYClient : public TlsDheSkeChangeY { public: TlsDheSkeChangeYClient( - ChangeYTo change, + const std::shared_ptr& agent, ChangeYTo change, std::shared_ptr server_filter) - : TlsDheSkeChangeY(kTlsHandshakeClientKeyExchange, change), + : TlsDheSkeChangeY(agent, kTlsHandshakeClientKeyExchange, change), server_filter_(server_filter) {} protected: @@ -282,8 +284,7 @@ TEST_P(TlsDamageDHYTest, DamageServerY) { client_->SetOption(SSL_REQUIRE_DH_NAMED_GROUPS, PR_TRUE); } TlsDheSkeChangeY::ChangeYTo change = std::get<2>(GetParam()); - server_->SetPacketFilter( - std::make_shared(change, true)); + MakeTlsFilter(server_, change, true); if (change == TlsDheSkeChangeY::kYZeroPad) { ExpectAlert(client_, kTlsAlertDecryptError); @@ -312,14 +313,12 @@ TEST_P(TlsDamageDHYTest, DamageClientY) { client_->SetOption(SSL_REQUIRE_DH_NAMED_GROUPS, PR_TRUE); } // The filter on the server is required to capture the prime. - auto server_filter = - std::make_shared(TlsDheSkeChangeY::kYZero, false); - server_->SetPacketFilter(server_filter); + auto server_filter = MakeTlsFilter( + server_, TlsDheSkeChangeY::kYZero, false); // The client filter does the damage. TlsDheSkeChangeY::ChangeYTo change = std::get<2>(GetParam()); - client_->SetPacketFilter( - std::make_shared(change, server_filter)); + MakeTlsFilter(client_, change, server_filter); if (change == TlsDheSkeChangeY::kYZeroPad) { ExpectAlert(server_, kTlsAlertDecryptError); @@ -358,7 +357,9 @@ INSTANTIATE_TEST_CASE_P( class TlsDheSkeMakePEven : public TlsHandshakeFilter { public: - TlsDheSkeMakePEven() : TlsHandshakeFilter({kTlsHandshakeServerKeyExchange}) {} + TlsDheSkeMakePEven(const std::shared_ptr& agent) + : TlsHandshakeFilter(agent, {kTlsHandshakeServerKeyExchange}) {} + virtual PacketFilter::Action FilterHandshake( const TlsHandshakeFilter::HandshakeHeader& header, const DataBuffer& input, DataBuffer* output) { @@ -379,7 +380,7 @@ class TlsDheSkeMakePEven : public TlsHandshakeFilter { // Even without requiring named groups, an even value for p is bad news. TEST_P(TlsConnectGenericPre13, MakeDhePEven) { EnableOnlyDheCiphers(); - server_->SetPacketFilter(std::make_shared()); + MakeTlsFilter(server_); ConnectExpectAlert(client_, kTlsAlertIllegalParameter); @@ -389,7 +390,9 @@ TEST_P(TlsConnectGenericPre13, MakeDhePEven) { class TlsDheSkeZeroPadP : public TlsHandshakeFilter { public: - TlsDheSkeZeroPadP() : TlsHandshakeFilter({kTlsHandshakeServerKeyExchange}) {} + TlsDheSkeZeroPadP(const std::shared_ptr& agent) + : TlsHandshakeFilter(agent, {kTlsHandshakeServerKeyExchange}) {} + virtual PacketFilter::Action FilterHandshake( const TlsHandshakeFilter::HandshakeHeader& header, const DataBuffer& input, DataBuffer* output) { @@ -407,7 +410,7 @@ class TlsDheSkeZeroPadP : public TlsHandshakeFilter { // Zero padding only causes signature failure. TEST_P(TlsConnectGenericPre13, PadDheP) { EnableOnlyDheCiphers(); - server_->SetPacketFilter(std::make_shared()); + MakeTlsFilter(server_); ConnectExpectAlert(client_, kTlsAlertDecryptError); @@ -455,7 +458,7 @@ TEST_P(TlsConnectGenericPre13, NamedGroupMismatchPre13) { Connect(); CheckKeys(ssl_kea_dh, ssl_grp_ffdhe_custom, ssl_auth_rsa_sign, - ssl_sig_rsa_pss_sha256); + ssl_sig_rsa_pss_rsae_sha256); } // Same test but for TLS 1.3. This has to fail. @@ -499,8 +502,8 @@ TEST_P(TlsConnectGenericPre13, PreferredFfdhe) { Connect(); client_->CheckKEA(ssl_kea_dh, ssl_grp_ffdhe_3072, 3072); server_->CheckKEA(ssl_kea_dh, ssl_grp_ffdhe_3072, 3072); - client_->CheckAuthType(ssl_auth_rsa_sign, ssl_sig_rsa_pss_sha256); - server_->CheckAuthType(ssl_auth_rsa_sign, ssl_sig_rsa_pss_sha256); + client_->CheckAuthType(ssl_auth_rsa_sign, ssl_sig_rsa_pss_rsae_sha256); + server_->CheckAuthType(ssl_auth_rsa_sign, ssl_sig_rsa_pss_rsae_sha256); } TEST_P(TlsConnectGenericPre13, MismatchDHE) { @@ -524,29 +527,28 @@ TEST_P(TlsConnectTls13, ResumeFfdhe) { Connect(); SendReceive(); // Need to read so that we absorb the session ticket. CheckKeys(ssl_kea_dh, ssl_grp_ffdhe_2048, ssl_auth_rsa_sign, - ssl_sig_rsa_pss_sha256); + ssl_sig_rsa_pss_rsae_sha256); Reset(); ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET); EnableOnlyDheCiphers(); auto clientCapture = - std::make_shared(ssl_tls13_pre_shared_key_xtn); - client_->SetPacketFilter(clientCapture); + MakeTlsFilter(client_, ssl_tls13_pre_shared_key_xtn); auto serverCapture = - std::make_shared(ssl_tls13_pre_shared_key_xtn); - server_->SetPacketFilter(serverCapture); + MakeTlsFilter(server_, ssl_tls13_pre_shared_key_xtn); ExpectResumption(RESUME_TICKET); Connect(); CheckKeys(ssl_kea_dh, ssl_grp_ffdhe_2048, ssl_auth_rsa_sign, - ssl_sig_rsa_pss_sha256); + ssl_sig_rsa_pss_rsae_sha256); ASSERT_LT(0UL, clientCapture->extension().len()); ASSERT_LT(0UL, serverCapture->extension().len()); } class TlsDheSkeChangeSignature : public TlsHandshakeFilter { public: - TlsDheSkeChangeSignature(uint16_t version, const uint8_t* data, size_t len) - : TlsHandshakeFilter({kTlsHandshakeServerKeyExchange}), + TlsDheSkeChangeSignature(const std::shared_ptr& agent, + uint16_t version, const uint8_t* data, size_t len) + : TlsHandshakeFilter(agent, {kTlsHandshakeServerKeyExchange}), version_(version), data_(data), len_(len) {} @@ -595,8 +597,8 @@ TEST_P(TlsConnectGenericPre13, InvalidDERSignatureFfdhe) { const std::vector client_groups = {ssl_grp_ffdhe_2048}; client_->ConfigNamedGroups(client_groups); - server_->SetPacketFilter(std::make_shared( - version_, kBogusDheSignature, sizeof(kBogusDheSignature))); + MakeTlsFilter(server_, version_, kBogusDheSignature, + sizeof(kBogusDheSignature)); ConnectExpectAlert(client_, kTlsAlertDecryptError); client_->CheckErrorCode(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE); diff --git a/security/nss/gtests/ssl_gtest/ssl_drop_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_drop_unittest.cc index c059e9938..ee8906deb 100644 --- a/security/nss/gtests/ssl_gtest/ssl_drop_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_drop_unittest.cc @@ -22,13 +22,13 @@ extern "C" { namespace nss_test { TEST_P(TlsConnectDatagramPre13, DropClientFirstFlightOnce) { - client_->SetPacketFilter(std::make_shared(0x1)); + client_->SetFilter(std::make_shared(0x1)); Connect(); SendReceive(); } TEST_P(TlsConnectDatagramPre13, DropServerFirstFlightOnce) { - server_->SetPacketFilter(std::make_shared(0x1)); + server_->SetFilter(std::make_shared(0x1)); Connect(); SendReceive(); } @@ -37,32 +37,32 @@ TEST_P(TlsConnectDatagramPre13, DropServerFirstFlightOnce) { // flights that they send. Note: In DTLS 1.3, the shorter handshake means that // this will also drop some application data, so we can't call SendReceive(). TEST_P(TlsConnectDatagramPre13, DropAllFirstTransmissions) { - client_->SetPacketFilter(std::make_shared(0x15)); - server_->SetPacketFilter(std::make_shared(0x5)); + client_->SetFilter(std::make_shared(0x15)); + server_->SetFilter(std::make_shared(0x5)); Connect(); } // This drops the server's first flight three times. TEST_P(TlsConnectDatagramPre13, DropServerFirstFlightThrice) { - server_->SetPacketFilter(std::make_shared(0x7)); + server_->SetFilter(std::make_shared(0x7)); Connect(); } // This drops the client's second flight once TEST_P(TlsConnectDatagramPre13, DropClientSecondFlightOnce) { - client_->SetPacketFilter(std::make_shared(0x2)); + client_->SetFilter(std::make_shared(0x2)); Connect(); } // This drops the client's second flight three times. TEST_P(TlsConnectDatagramPre13, DropClientSecondFlightThrice) { - client_->SetPacketFilter(std::make_shared(0xe)); + client_->SetFilter(std::make_shared(0xe)); Connect(); } // This drops the server's second flight three times. TEST_P(TlsConnectDatagramPre13, DropServerSecondFlightThrice) { - server_->SetPacketFilter(std::make_shared(0xe)); + server_->SetFilter(std::make_shared(0xe)); Connect(); } @@ -74,7 +74,7 @@ class TlsDropDatagram13 : public TlsConnectDatagram13 { expected_client_acks_(0), expected_server_acks_(1) {} - void SetUp() { + void SetUp() override { TlsConnectDatagram13::SetUp(); ConfigureSessionCache(RESUME_NONE, RESUME_NONE); SetFilters(); @@ -82,12 +82,8 @@ class TlsDropDatagram13 : public TlsConnectDatagram13 { void SetFilters() { EnsureTlsSetup(); - client_->SetPacketFilter(client_filters_.chain_); - client_filters_.ack_->SetAgent(client_.get()); - client_filters_.ack_->EnableDecryption(); - server_->SetPacketFilter(server_filters_.chain_); - server_filters_.ack_->SetAgent(server_.get()); - server_filters_.ack_->EnableDecryption(); + client_filters_.Init(client_); + server_filters_.Init(server_); } void HandshakeAndAck(const std::shared_ptr& agent) { @@ -119,11 +115,17 @@ class TlsDropDatagram13 : public TlsConnectDatagram13 { class DropAckChain { public: DropAckChain() - : records_(std::make_shared()), - ack_(std::make_shared(content_ack)), - drop_(std::make_shared(0, false)), - chain_(std::make_shared( - ChainedPacketFilterInit({records_, ack_, drop_}))) {} + : records_(nullptr), ack_(nullptr), drop_(nullptr), chain_(nullptr) {} + + void Init(const std::shared_ptr& agent) { + records_ = std::make_shared(agent); + ack_ = std::make_shared(agent, content_ack); + ack_->EnableDecryption(); + drop_ = std::make_shared(agent, 0, false); + chain_ = std::make_shared( + ChainedPacketFilterInit({records_, ack_, drop_})); + agent->SetFilter(chain_); + } const TlsRecord& record(size_t i) const { return records_->record(i); } @@ -227,7 +229,7 @@ TEST_F(TlsDropDatagram13, DropServerSecondRecordOnce) { HandshakeAndAck(client_); expected_client_acks_ = 1; CheckedHandshakeSendReceive(); - CheckAcks(client_filters_, 0, {0}); + CheckAcks(client_filters_, 0, {0}); // ServerHello CheckAcks(server_filters_, 0, {0x0002000000000000ULL}); } @@ -257,7 +259,7 @@ TEST_F(TlsDropDatagram13, DropServerAckOnce) { CheckPostHandshake(); // There should be two copies of the finished ACK CheckAcks(server_filters_, 0, {0x0002000000000000ULL}); - CheckAcks(server_filters_, 0, {0x0002000000000000ULL}); + CheckAcks(server_filters_, 1, {0x0002000000000000ULL}); } // Drop the client certificate verify. @@ -276,10 +278,9 @@ TEST_F(TlsDropDatagram13, DropClientCertVerify) { // Ack of the whole client handshake. CheckAcks( server_filters_, 1, - {0x0002000000000000ULL, // CH (we drop everything after this on client) - 0x0002000000000003ULL, // CT (2) - 0x0002000000000004ULL} // FIN (2) - ); + {0x0002000000000000ULL, // CH (we drop everything after this on client) + 0x0002000000000003ULL, // CT (2) + 0x0002000000000004ULL}); // FIN (2) } // Shrink the MTU down so that certs get split and drop the first piece. @@ -303,10 +304,9 @@ TEST_F(TlsDropDatagram13, DropFirstHalfOfServerCertificate) { EXPECT_EQ(ct1_size, server_filters_.record(0).buffer.len()); CheckedHandshakeSendReceive(); CheckAcks(client_filters_, 0, - {0, // SH - 0x0002000000000000ULL, // EE - 0x0002000000000002ULL} // CT2 - ); + {0, // SH + 0x0002000000000000ULL, // EE + 0x0002000000000002ULL}); // CT2 CheckAcks(server_filters_, 0, {0x0002000000000000ULL}); } @@ -540,7 +540,10 @@ TEST_F(TlsDropDatagram13, NoDropsDuringZeroRtt) { ExpectEarlyDataAccepted(true); CheckConnected(); SendReceive(); - CheckAcks(server_filters_, 0, {0x0002000000000000ULL}); + EXPECT_EQ(0U, client_filters_.ack_->count()); + CheckAcks(server_filters_, 0, + {0x0001000000000001ULL, // EOED + 0x0002000000000000ULL}); // Finished } TEST_F(TlsDropDatagram13, DropEEDuringZeroRtt) { @@ -558,7 +561,9 @@ TEST_F(TlsDropDatagram13, DropEEDuringZeroRtt) { CheckConnected(); SendReceive(); CheckAcks(client_filters_, 0, {0}); - CheckAcks(server_filters_, 0, {0x0002000000000000ULL}); + CheckAcks(server_filters_, 0, + {0x0001000000000002ULL, // EOED + 0x0002000000000000ULL}); // Finished } class TlsReorderDatagram13 : public TlsDropDatagram13 { @@ -688,6 +693,7 @@ TEST_F(TlsDropDatagram13, SendOutOfOrderHsNonsenseWithHandshakeKey) { kTlsHandshakeType, DataBuffer(buf, sizeof(buf)))); server_->Handshake(); EXPECT_EQ(2UL, server_filters_.ack_->count()); + // The server acknowledges client Finished twice. CheckAcks(server_filters_, 0, {0x0002000000000000ULL}); CheckAcks(server_filters_, 1, {0x0002000000000000ULL}); } @@ -746,7 +752,9 @@ TEST_F(TlsReorderDatagram13, DataAfterEOEDDuringZeroRtt) { ReSend(TlsAgent::CLIENT, std::vector({1, 0, 2})); server_->Handshake(); CheckConnected(); - CheckAcks(server_filters_, 0, {0x0002000000000000ULL}); + EXPECT_EQ(0U, client_filters_.ack_->count()); + // Acknowledgements for EOED and Finished. + CheckAcks(server_filters_, 0, {0x0001000000000002ULL, 0x0002000000000000ULL}); uint8_t buf[8]; rv = PR_Read(server_->ssl_fd(), buf, sizeof(buf)); EXPECT_EQ(-1, rv); @@ -783,7 +791,9 @@ TEST_F(TlsReorderDatagram13, DataAfterFinDuringZeroRtt) { ReSend(TlsAgent::CLIENT, std::vector({1, 2, 0})); server_->Handshake(); CheckConnected(); - CheckAcks(server_filters_, 0, {0x0002000000000000ULL}); + EXPECT_EQ(0U, client_filters_.ack_->count()); + // Acknowledgements for EOED and Finished. + CheckAcks(server_filters_, 0, {0x0001000000000002ULL, 0x0002000000000000ULL}); uint8_t buf[8]; rv = PR_Read(server_->ssl_fd(), buf, sizeof(buf)); EXPECT_EQ(-1, rv); diff --git a/security/nss/gtests/ssl_gtest/ssl_ecdh_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_ecdh_unittest.cc index e0f8b1f55..3c7cd2ecf 100644 --- a/security/nss/gtests/ssl_gtest/ssl_ecdh_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_ecdh_unittest.cc @@ -69,20 +69,19 @@ TEST_P(TlsConnectGeneric, ConnectEcdheP384Client) { server_->ConfigNamedGroups(groups); Connect(); CheckKeys(ssl_kea_ecdh, ssl_grp_ec_secp384r1, ssl_auth_rsa_sign, - ssl_sig_rsa_pss_sha256); + ssl_sig_rsa_pss_rsae_sha256); } // This causes a HelloRetryRequest in TLS 1.3. Earlier versions don't care. TEST_P(TlsConnectGeneric, ConnectEcdheP384Server) { EnsureTlsSetup(); - auto hrr_capture = std::make_shared( - kTlsHandshakeHelloRetryRequest); - server_->SetPacketFilter(hrr_capture); + auto hrr_capture = MakeTlsFilter( + server_, kTlsHandshakeHelloRetryRequest); const std::vector groups = {ssl_grp_ec_secp384r1}; server_->ConfigNamedGroups(groups); Connect(); CheckKeys(ssl_kea_ecdh, ssl_grp_ec_secp384r1, ssl_auth_rsa_sign, - ssl_sig_rsa_pss_sha256); + ssl_sig_rsa_pss_rsae_sha256); EXPECT_EQ(version_ == SSL_LIBRARY_VERSION_TLS_1_3, hrr_capture->buffer().len() != 0); } @@ -112,7 +111,7 @@ TEST_P(TlsKeyExchangeTest, P384Priority) { Connect(); CheckKeys(ssl_kea_ecdh, ssl_grp_ec_secp384r1, ssl_auth_rsa_sign, - ssl_sig_rsa_pss_sha256); + ssl_sig_rsa_pss_rsae_sha256); std::vector shares = {ssl_grp_ec_secp384r1}; CheckKEXDetails(groups, shares); @@ -129,7 +128,7 @@ TEST_P(TlsKeyExchangeTest, DuplicateGroupConfig) { Connect(); CheckKeys(ssl_kea_ecdh, ssl_grp_ec_secp384r1, ssl_auth_rsa_sign, - ssl_sig_rsa_pss_sha256); + ssl_sig_rsa_pss_rsae_sha256); std::vector shares = {ssl_grp_ec_secp384r1}; std::vector expectedGroups = {ssl_grp_ec_secp384r1, @@ -147,7 +146,7 @@ TEST_P(TlsKeyExchangeTest, P384PriorityDHEnabled) { Connect(); CheckKeys(ssl_kea_ecdh, ssl_grp_ec_secp384r1, ssl_auth_rsa_sign, - ssl_sig_rsa_pss_sha256); + ssl_sig_rsa_pss_rsae_sha256); if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) { std::vector shares = {ssl_grp_ec_secp384r1}; @@ -172,7 +171,7 @@ TEST_P(TlsConnectGenericPre13, P384PriorityOnServer) { Connect(); CheckKeys(ssl_kea_ecdh, ssl_grp_ec_secp384r1, ssl_auth_rsa_sign, - ssl_sig_rsa_pss_sha256); + ssl_sig_rsa_pss_rsae_sha256); } TEST_P(TlsConnectGenericPre13, P384PriorityFromModelSocket) { @@ -188,13 +187,13 @@ TEST_P(TlsConnectGenericPre13, P384PriorityFromModelSocket) { Connect(); CheckKeys(ssl_kea_ecdh, ssl_grp_ec_secp384r1, ssl_auth_rsa_sign, - ssl_sig_rsa_pss_sha256); + ssl_sig_rsa_pss_rsae_sha256); } class TlsKeyExchangeGroupCapture : public TlsHandshakeFilter { public: - TlsKeyExchangeGroupCapture() - : TlsHandshakeFilter({kTlsHandshakeServerKeyExchange}), + TlsKeyExchangeGroupCapture(const std::shared_ptr &agent) + : TlsHandshakeFilter(agent, {kTlsHandshakeServerKeyExchange}), group_(ssl_grp_none) {} SSLNamedGroup group() const { return group_; } @@ -221,10 +220,8 @@ class TlsKeyExchangeGroupCapture : public TlsHandshakeFilter { // P-256 is supported by the client (<= 1.2 only). TEST_P(TlsConnectGenericPre13, DropSupportedGroupExtensionP256) { EnsureTlsSetup(); - client_->SetPacketFilter( - std::make_shared(ssl_supported_groups_xtn)); - auto group_capture = std::make_shared(); - server_->SetPacketFilter(group_capture); + MakeTlsFilter(client_, ssl_supported_groups_xtn); + auto group_capture = MakeTlsFilter(server_); ConnectExpectAlert(server_, kTlsAlertDecryptError); client_->CheckErrorCode(SSL_ERROR_DECRYPT_ERROR_ALERT); @@ -236,8 +233,7 @@ TEST_P(TlsConnectGenericPre13, DropSupportedGroupExtensionP256) { // Supported groups is mandatory in TLS 1.3. TEST_P(TlsConnectTls13, DropSupportedGroupExtension) { EnsureTlsSetup(); - client_->SetPacketFilter( - std::make_shared(ssl_supported_groups_xtn)); + MakeTlsFilter(client_, ssl_supported_groups_xtn); ConnectExpectAlert(server_, kTlsAlertMissingExtension); client_->CheckErrorCode(SSL_ERROR_MISSING_EXTENSION_ALERT); server_->CheckErrorCode(SSL_ERROR_MISSING_SUPPORTED_GROUPS_EXTENSION); @@ -276,7 +272,7 @@ TEST_P(TlsConnectStreamPre13, ConfiguredGroupsRenegotiate) { Connect(); CheckKeys(ssl_kea_ecdh, ssl_grp_ec_secp256r1, ssl_auth_rsa_sign, - ssl_sig_rsa_pss_sha256); + ssl_sig_rsa_pss_rsae_sha256); CheckConnected(); // The renegotiation has to use the same preferences as the original session. @@ -284,7 +280,7 @@ TEST_P(TlsConnectStreamPre13, ConfiguredGroupsRenegotiate) { client_->StartRenegotiate(); Handshake(); CheckKeys(ssl_kea_ecdh, ssl_grp_ec_secp256r1, ssl_auth_rsa_sign, - ssl_sig_rsa_pss_sha256); + ssl_sig_rsa_pss_rsae_sha256); } TEST_P(TlsKeyExchangeTest, Curve25519) { @@ -318,7 +314,7 @@ TEST_P(TlsConnectGenericPre13, GroupPreferenceServerPriority) { Connect(); CheckKeys(ssl_kea_ecdh, ssl_grp_ec_curve25519, ssl_auth_rsa_sign, - ssl_sig_rsa_pss_sha256); + ssl_sig_rsa_pss_rsae_sha256); } #ifndef NSS_DISABLE_TLS_1_3 @@ -337,7 +333,7 @@ TEST_P(TlsKeyExchangeTest13, Curve25519P256EqualPriorityClient13) { Connect(); CheckKeys(ssl_kea_ecdh, ssl_grp_ec_secp256r1, ssl_auth_rsa_sign, - ssl_sig_rsa_pss_sha256); + ssl_sig_rsa_pss_rsae_sha256); const std::vector shares = {ssl_grp_ec_secp256r1}; CheckKEXDetails(client_groups, shares); } @@ -357,7 +353,7 @@ TEST_P(TlsKeyExchangeTest13, Curve25519P256EqualPriorityServer13) { Connect(); CheckKeys(ssl_kea_ecdh, ssl_grp_ec_curve25519, ssl_auth_rsa_sign, - ssl_sig_rsa_pss_sha256); + ssl_sig_rsa_pss_rsae_sha256); const std::vector shares = {ssl_grp_ec_curve25519}; CheckKEXDetails(client_groups, shares); } @@ -379,7 +375,7 @@ TEST_P(TlsKeyExchangeTest13, EqualPriorityTestRetryECServer13) { Connect(); CheckKeys(ssl_kea_ecdh, ssl_grp_ec_secp256r1, ssl_auth_rsa_sign, - ssl_sig_rsa_pss_sha256); + ssl_sig_rsa_pss_rsae_sha256); const std::vector shares = {ssl_grp_ec_curve25519}; CheckKEXDetails(client_groups, shares, ssl_grp_ec_secp256r1); } @@ -401,7 +397,7 @@ TEST_P(TlsKeyExchangeTest13, NotEqualPriorityWithIntermediateGroup13) { Connect(); CheckKeys(ssl_kea_ecdh, ssl_grp_ec_secp256r1, ssl_auth_rsa_sign, - ssl_sig_rsa_pss_sha256); + ssl_sig_rsa_pss_rsae_sha256); const std::vector shares = {ssl_grp_ec_curve25519}; CheckKEXDetails(client_groups, shares, ssl_grp_ec_secp256r1); } @@ -423,7 +419,7 @@ TEST_P(TlsKeyExchangeTest13, Connect(); CheckKeys(ssl_kea_ecdh, ssl_grp_ec_secp256r1, ssl_auth_rsa_sign, - ssl_sig_rsa_pss_sha256); + ssl_sig_rsa_pss_rsae_sha256); const std::vector shares = {ssl_grp_ec_curve25519}; CheckKEXDetails(client_groups, shares, ssl_grp_ec_secp256r1); } @@ -445,7 +441,7 @@ TEST_P(TlsKeyExchangeTest13, Connect(); CheckKeys(ssl_kea_ecdh, ssl_grp_ec_secp256r1, ssl_auth_rsa_sign, - ssl_sig_rsa_pss_sha256); + ssl_sig_rsa_pss_rsae_sha256); const std::vector shares = {ssl_grp_ec_curve25519}; CheckKEXDetails(client_groups, shares, ssl_grp_ec_secp256r1); } @@ -507,7 +503,7 @@ TEST_P(TlsKeyExchangeTest13, MultipleClientShares) { // The server would accept 25519 but its preferred group (P256) has to win. CheckKeys(ssl_kea_ecdh, ssl_grp_ec_secp256r1, ssl_auth_rsa_sign, - ssl_sig_rsa_pss_sha256); + ssl_sig_rsa_pss_rsae_sha256); const std::vector shares = {ssl_grp_ec_curve25519, ssl_grp_ec_secp256r1}; CheckKEXDetails(client_groups, shares); @@ -516,7 +512,8 @@ TEST_P(TlsKeyExchangeTest13, MultipleClientShares) { // Replace the point in the client key exchange message with an empty one class ECCClientKEXFilter : public TlsHandshakeFilter { public: - ECCClientKEXFilter() : TlsHandshakeFilter({kTlsHandshakeClientKeyExchange}) {} + ECCClientKEXFilter(const std::shared_ptr &client) + : TlsHandshakeFilter(client, {kTlsHandshakeClientKeyExchange}) {} protected: virtual PacketFilter::Action FilterHandshake(const HandshakeHeader &header, @@ -532,7 +529,8 @@ class ECCClientKEXFilter : public TlsHandshakeFilter { // Replace the point in the server key exchange message with an empty one class ECCServerKEXFilter : public TlsHandshakeFilter { public: - ECCServerKEXFilter() : TlsHandshakeFilter({kTlsHandshakeServerKeyExchange}) {} + ECCServerKEXFilter(const std::shared_ptr &server) + : TlsHandshakeFilter(server, {kTlsHandshakeServerKeyExchange}) {} protected: virtual PacketFilter::Action FilterHandshake(const HandshakeHeader &header, @@ -550,15 +548,13 @@ class ECCServerKEXFilter : public TlsHandshakeFilter { }; TEST_P(TlsConnectGenericPre13, ConnectECDHEmptyServerPoint) { - // add packet filter - server_->SetPacketFilter(std::make_shared()); + MakeTlsFilter(server_); ConnectExpectAlert(client_, kTlsAlertIllegalParameter); client_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_SERVER_KEY_EXCH); } TEST_P(TlsConnectGenericPre13, ConnectECDHEmptyClientPoint) { - // add packet filter - client_->SetPacketFilter(std::make_shared()); + MakeTlsFilter(client_); ConnectExpectAlert(server_, kTlsAlertIllegalParameter); server_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_CLIENT_KEY_EXCH); } diff --git a/security/nss/gtests/ssl_gtest/ssl_extension_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_extension_unittest.cc index 4142ab07a..0453dabdb 100644 --- a/security/nss/gtests/ssl_gtest/ssl_extension_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_extension_unittest.cc @@ -19,8 +19,9 @@ namespace nss_test { class TlsExtensionTruncator : public TlsExtensionFilter { public: - TlsExtensionTruncator(uint16_t extension, size_t length) - : extension_(extension), length_(length) {} + TlsExtensionTruncator(const std::shared_ptr& agent, + uint16_t extension, size_t length) + : TlsExtensionFilter(agent), extension_(extension), length_(length) {} virtual PacketFilter::Action FilterExtension(uint16_t extension_type, const DataBuffer& input, DataBuffer* output) { @@ -42,8 +43,9 @@ class TlsExtensionTruncator : public TlsExtensionFilter { class TlsExtensionDamager : public TlsExtensionFilter { public: - TlsExtensionDamager(uint16_t extension, size_t index) - : extension_(extension), index_(index) {} + TlsExtensionDamager(const std::shared_ptr& agent, + uint16_t extension, size_t index) + : TlsExtensionFilter(agent), extension_(extension), index_(index) {} virtual PacketFilter::Action FilterExtension(uint16_t extension_type, const DataBuffer& input, DataBuffer* output) { @@ -63,8 +65,11 @@ class TlsExtensionDamager : public TlsExtensionFilter { class TlsExtensionAppender : public TlsHandshakeFilter { public: - TlsExtensionAppender(uint8_t handshake_type, uint16_t ext, DataBuffer& data) - : TlsHandshakeFilter({handshake_type}), extension_(ext), data_(data) {} + TlsExtensionAppender(const std::shared_ptr& agent, + uint8_t handshake_type, uint16_t ext, DataBuffer& data) + : TlsHandshakeFilter(agent, {handshake_type}), + extension_(ext), + data_(data) {} virtual PacketFilter::Action FilterHandshake(const HandshakeHeader& header, const DataBuffer& input, @@ -124,13 +129,13 @@ class TlsExtensionTestBase : public TlsConnectTestBase { void ClientHelloErrorTest(std::shared_ptr filter, uint8_t desc = kTlsAlertDecodeError) { - client_->SetPacketFilter(filter); + client_->SetFilter(filter); ConnectExpectAlert(server_, desc); } void ServerHelloErrorTest(std::shared_ptr filter, uint8_t desc = kTlsAlertDecodeError) { - server_->SetPacketFilter(filter); + server_->SetFilter(filter); ConnectExpectAlert(client_, desc); } @@ -156,7 +161,7 @@ class TlsExtensionTestBase : public TlsConnectTestBase { StartConnect(); client_->Handshake(); // Send ClientHello server_->Handshake(); // Send HRR. - client_->SetPacketFilter(std::make_shared(type)); + MakeTlsFilter(client_, type); Handshake(); client_->CheckErrorCode(client_error); server_->CheckErrorCode(server_error); @@ -197,8 +202,8 @@ class TlsExtensionTest13 void ConnectWithBogusVersionList(const uint8_t* buf, size_t len) { DataBuffer versions_buf(buf, len); - client_->SetPacketFilter(std::make_shared( - ssl_tls13_supported_versions_xtn, versions_buf)); + MakeTlsFilter( + client_, ssl_tls13_supported_versions_xtn, versions_buf); ConnectExpectAlert(server_, kTlsAlertIllegalParameter); client_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT); server_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO); @@ -209,8 +214,8 @@ class TlsExtensionTest13 size_t index = versions_buf.Write(0, 2, 1); versions_buf.Write(index, version, 2); - client_->SetPacketFilter(std::make_shared( - ssl_tls13_supported_versions_xtn, versions_buf)); + MakeTlsFilter( + client_, ssl_tls13_supported_versions_xtn, versions_buf); ConnectExpectFail(); } }; @@ -241,26 +246,26 @@ class TlsExtensionTestPre13 : public TlsExtensionTestBase, TEST_P(TlsExtensionTestGeneric, DamageSniLength) { ClientHelloErrorTest( - std::make_shared(ssl_server_name_xtn, 1)); + std::make_shared(client_, ssl_server_name_xtn, 1)); } TEST_P(TlsExtensionTestGeneric, DamageSniHostLength) { ClientHelloErrorTest( - std::make_shared(ssl_server_name_xtn, 4)); + std::make_shared(client_, ssl_server_name_xtn, 4)); } TEST_P(TlsExtensionTestGeneric, TruncateSni) { ClientHelloErrorTest( - std::make_shared(ssl_server_name_xtn, 7)); + std::make_shared(client_, ssl_server_name_xtn, 7)); } // A valid extension that appears twice will be reported as unsupported. TEST_P(TlsExtensionTestGeneric, RepeatSni) { DataBuffer extension; InitSimpleSni(&extension); - ClientHelloErrorTest( - std::make_shared(ssl_server_name_xtn, extension), - kTlsAlertIllegalParameter); + ClientHelloErrorTest(std::make_shared( + client_, ssl_server_name_xtn, extension), + kTlsAlertIllegalParameter); } // An SNI entry with zero length is considered invalid (strangely, not if it is @@ -272,23 +277,23 @@ TEST_P(TlsExtensionTestGeneric, BadSni) { extension.Allocate(simple.len() + 3); extension.Write(0, static_cast(0), 3); extension.Write(3, simple); - ClientHelloErrorTest( - std::make_shared(ssl_server_name_xtn, extension)); + ClientHelloErrorTest(std::make_shared( + client_, ssl_server_name_xtn, extension)); } TEST_P(TlsExtensionTestGeneric, EmptySni) { DataBuffer extension; extension.Allocate(2); extension.Write(0, static_cast(0), 2); - ClientHelloErrorTest( - std::make_shared(ssl_server_name_xtn, extension)); + ClientHelloErrorTest(std::make_shared( + client_, ssl_server_name_xtn, extension)); } TEST_P(TlsExtensionTestGeneric, EmptyAlpnExtension) { EnableAlpn(); DataBuffer extension; ClientHelloErrorTest(std::make_shared( - ssl_app_layer_protocol_xtn, extension), + client_, ssl_app_layer_protocol_xtn, extension), kTlsAlertIllegalParameter); } @@ -299,21 +304,21 @@ TEST_P(TlsExtensionTestGeneric, EmptyAlpnList) { const uint8_t val[] = {0x00, 0x00}; DataBuffer extension(val, sizeof(val)); ClientHelloErrorTest(std::make_shared( - ssl_app_layer_protocol_xtn, extension), + client_, ssl_app_layer_protocol_xtn, extension), kTlsAlertNoApplicationProtocol); } TEST_P(TlsExtensionTestGeneric, OneByteAlpn) { EnableAlpn(); - ClientHelloErrorTest( - std::make_shared(ssl_app_layer_protocol_xtn, 1)); + ClientHelloErrorTest(std::make_shared( + client_, ssl_app_layer_protocol_xtn, 1)); } TEST_P(TlsExtensionTestGeneric, AlpnMissingValue) { EnableAlpn(); // This will leave the length of the second entry, but no value. - ClientHelloErrorTest( - std::make_shared(ssl_app_layer_protocol_xtn, 5)); + ClientHelloErrorTest(std::make_shared( + client_, ssl_app_layer_protocol_xtn, 5)); } TEST_P(TlsExtensionTestGeneric, AlpnZeroLength) { @@ -321,7 +326,7 @@ TEST_P(TlsExtensionTestGeneric, AlpnZeroLength) { const uint8_t val[] = {0x01, 0x61, 0x00}; DataBuffer extension(val, sizeof(val)); ClientHelloErrorTest(std::make_shared( - ssl_app_layer_protocol_xtn, extension)); + client_, ssl_app_layer_protocol_xtn, extension)); } TEST_P(TlsExtensionTestGeneric, AlpnMismatch) { @@ -340,7 +345,7 @@ TEST_P(TlsExtensionTestPre13, AlpnReturnedEmptyList) { const uint8_t val[] = {0x00, 0x00}; DataBuffer extension(val, sizeof(val)); ServerHelloErrorTest(std::make_shared( - ssl_app_layer_protocol_xtn, extension)); + server_, ssl_app_layer_protocol_xtn, extension)); } TEST_P(TlsExtensionTestPre13, AlpnReturnedEmptyName) { @@ -348,7 +353,7 @@ TEST_P(TlsExtensionTestPre13, AlpnReturnedEmptyName) { const uint8_t val[] = {0x00, 0x01, 0x00}; DataBuffer extension(val, sizeof(val)); ServerHelloErrorTest(std::make_shared( - ssl_app_layer_protocol_xtn, extension)); + server_, ssl_app_layer_protocol_xtn, extension)); } TEST_P(TlsExtensionTestPre13, AlpnReturnedListTrailingData) { @@ -356,7 +361,7 @@ TEST_P(TlsExtensionTestPre13, AlpnReturnedListTrailingData) { const uint8_t val[] = {0x00, 0x02, 0x01, 0x61, 0x00}; DataBuffer extension(val, sizeof(val)); ServerHelloErrorTest(std::make_shared( - ssl_app_layer_protocol_xtn, extension)); + server_, ssl_app_layer_protocol_xtn, extension)); } TEST_P(TlsExtensionTestPre13, AlpnReturnedExtraEntry) { @@ -364,7 +369,7 @@ TEST_P(TlsExtensionTestPre13, AlpnReturnedExtraEntry) { const uint8_t val[] = {0x00, 0x04, 0x01, 0x61, 0x01, 0x62}; DataBuffer extension(val, sizeof(val)); ServerHelloErrorTest(std::make_shared( - ssl_app_layer_protocol_xtn, extension)); + server_, ssl_app_layer_protocol_xtn, extension)); } TEST_P(TlsExtensionTestPre13, AlpnReturnedBadListLength) { @@ -372,7 +377,7 @@ TEST_P(TlsExtensionTestPre13, AlpnReturnedBadListLength) { const uint8_t val[] = {0x00, 0x99, 0x01, 0x61, 0x00}; DataBuffer extension(val, sizeof(val)); ServerHelloErrorTest(std::make_shared( - ssl_app_layer_protocol_xtn, extension)); + server_, ssl_app_layer_protocol_xtn, extension)); } TEST_P(TlsExtensionTestPre13, AlpnReturnedBadNameLength) { @@ -380,7 +385,7 @@ TEST_P(TlsExtensionTestPre13, AlpnReturnedBadNameLength) { const uint8_t val[] = {0x00, 0x02, 0x99, 0x61}; DataBuffer extension(val, sizeof(val)); ServerHelloErrorTest(std::make_shared( - ssl_app_layer_protocol_xtn, extension)); + server_, ssl_app_layer_protocol_xtn, extension)); } TEST_P(TlsExtensionTestPre13, AlpnReturnedUnknownName) { @@ -388,55 +393,64 @@ TEST_P(TlsExtensionTestPre13, AlpnReturnedUnknownName) { const uint8_t val[] = {0x00, 0x02, 0x01, 0x67}; DataBuffer extension(val, sizeof(val)); ServerHelloErrorTest(std::make_shared( - ssl_app_layer_protocol_xtn, extension), + server_, ssl_app_layer_protocol_xtn, extension), kTlsAlertIllegalParameter); } TEST_P(TlsExtensionTestDtls, SrtpShort) { EnableSrtp(); ClientHelloErrorTest( - std::make_shared(ssl_use_srtp_xtn, 3)); + std::make_shared(client_, ssl_use_srtp_xtn, 3)); } TEST_P(TlsExtensionTestDtls, SrtpOdd) { EnableSrtp(); const uint8_t val[] = {0x00, 0x01, 0xff, 0x00}; DataBuffer extension(val, sizeof(val)); - ClientHelloErrorTest( - std::make_shared(ssl_use_srtp_xtn, extension)); + ClientHelloErrorTest(std::make_shared( + client_, ssl_use_srtp_xtn, extension)); } TEST_P(TlsExtensionTest12Plus, SignatureAlgorithmsBadLength) { const uint8_t val[] = {0x00}; DataBuffer extension(val, sizeof(val)); ClientHelloErrorTest(std::make_shared( - ssl_signature_algorithms_xtn, extension)); + client_, ssl_signature_algorithms_xtn, extension)); } TEST_P(TlsExtensionTest12Plus, SignatureAlgorithmsTrailingData) { const uint8_t val[] = {0x00, 0x02, 0x04, 0x01, 0x00}; // sha-256, rsa DataBuffer extension(val, sizeof(val)); ClientHelloErrorTest(std::make_shared( - ssl_signature_algorithms_xtn, extension)); + client_, ssl_signature_algorithms_xtn, extension)); } TEST_P(TlsExtensionTest12Plus, SignatureAlgorithmsEmpty) { const uint8_t val[] = {0x00, 0x00}; DataBuffer extension(val, sizeof(val)); ClientHelloErrorTest(std::make_shared( - ssl_signature_algorithms_xtn, extension)); + client_, ssl_signature_algorithms_xtn, extension), + kTlsAlertHandshakeFailure); +} + +TEST_P(TlsExtensionTest12Plus, SignatureAlgorithmsNoOverlap) { + const uint8_t val[] = {0x00, 0x02, 0xff, 0xff}; + DataBuffer extension(val, sizeof(val)); + ClientHelloErrorTest(std::make_shared( + client_, ssl_signature_algorithms_xtn, extension), + kTlsAlertHandshakeFailure); } TEST_P(TlsExtensionTest12Plus, SignatureAlgorithmsOddLength) { const uint8_t val[] = {0x00, 0x01, 0x04}; DataBuffer extension(val, sizeof(val)); ClientHelloErrorTest(std::make_shared( - ssl_signature_algorithms_xtn, extension)); + client_, ssl_signature_algorithms_xtn, extension)); } TEST_P(TlsExtensionTestGeneric, NoSupportedGroups) { ClientHelloErrorTest( - std::make_shared(ssl_supported_groups_xtn), + std::make_shared(client_, ssl_supported_groups_xtn), version_ < SSL_LIBRARY_VERSION_TLS_1_3 ? kTlsAlertDecryptError : kTlsAlertMissingExtension); } @@ -445,75 +459,74 @@ TEST_P(TlsExtensionTestGeneric, SupportedCurvesShort) { const uint8_t val[] = {0x00, 0x01, 0x00}; DataBuffer extension(val, sizeof(val)); ClientHelloErrorTest(std::make_shared( - ssl_elliptic_curves_xtn, extension)); + client_, ssl_elliptic_curves_xtn, extension)); } TEST_P(TlsExtensionTestGeneric, SupportedCurvesBadLength) { const uint8_t val[] = {0x09, 0x99, 0x00, 0x00}; DataBuffer extension(val, sizeof(val)); ClientHelloErrorTest(std::make_shared( - ssl_elliptic_curves_xtn, extension)); + client_, ssl_elliptic_curves_xtn, extension)); } TEST_P(TlsExtensionTestGeneric, SupportedCurvesTrailingData) { const uint8_t val[] = {0x00, 0x02, 0x00, 0x00, 0x00}; DataBuffer extension(val, sizeof(val)); ClientHelloErrorTest(std::make_shared( - ssl_elliptic_curves_xtn, extension)); + client_, ssl_elliptic_curves_xtn, extension)); } TEST_P(TlsExtensionTestPre13, SupportedPointsEmpty) { const uint8_t val[] = {0x00}; DataBuffer extension(val, sizeof(val)); ClientHelloErrorTest(std::make_shared( - ssl_ec_point_formats_xtn, extension)); + client_, ssl_ec_point_formats_xtn, extension)); } TEST_P(TlsExtensionTestPre13, SupportedPointsBadLength) { const uint8_t val[] = {0x99, 0x00, 0x00}; DataBuffer extension(val, sizeof(val)); ClientHelloErrorTest(std::make_shared( - ssl_ec_point_formats_xtn, extension)); + client_, ssl_ec_point_formats_xtn, extension)); } TEST_P(TlsExtensionTestPre13, SupportedPointsTrailingData) { const uint8_t val[] = {0x01, 0x00, 0x00}; DataBuffer extension(val, sizeof(val)); ClientHelloErrorTest(std::make_shared( - ssl_ec_point_formats_xtn, extension)); + client_, ssl_ec_point_formats_xtn, extension)); } TEST_P(TlsExtensionTestPre13, RenegotiationInfoBadLength) { const uint8_t val[] = {0x99}; DataBuffer extension(val, sizeof(val)); ClientHelloErrorTest(std::make_shared( - ssl_renegotiation_info_xtn, extension)); + client_, ssl_renegotiation_info_xtn, extension)); } TEST_P(TlsExtensionTestPre13, RenegotiationInfoMismatch) { const uint8_t val[] = {0x01, 0x00}; DataBuffer extension(val, sizeof(val)); ClientHelloErrorTest(std::make_shared( - ssl_renegotiation_info_xtn, extension)); + client_, ssl_renegotiation_info_xtn, extension)); } // The extension has to contain a length. TEST_P(TlsExtensionTestPre13, RenegotiationInfoExtensionEmpty) { DataBuffer extension; ClientHelloErrorTest(std::make_shared( - ssl_renegotiation_info_xtn, extension)); + client_, ssl_renegotiation_info_xtn, extension)); } // This only works on TLS 1.2, since it relies on static RSA; otherwise libssl // picks the wrong cipher suite. TEST_P(TlsExtensionTest12, SignatureAlgorithmConfiguration) { - const SSLSignatureScheme schemes[] = {ssl_sig_rsa_pss_sha512, - ssl_sig_rsa_pss_sha384}; + const SSLSignatureScheme schemes[] = {ssl_sig_rsa_pss_rsae_sha512, + ssl_sig_rsa_pss_rsae_sha384}; auto capture = - std::make_shared(ssl_signature_algorithms_xtn); + MakeTlsFilter(client_, ssl_signature_algorithms_xtn); client_->SetSignatureSchemes(schemes, PR_ARRAY_SIZE(schemes)); - client_->SetPacketFilter(capture); EnableOnlyStaticRsaCiphers(); Connect(); @@ -531,9 +544,9 @@ TEST_P(TlsExtensionTest12, SignatureAlgorithmConfiguration) { // Temporary test to verify that we choke on an empty ClientKeyShare. // This test will fail when we implement HelloRetryRequest. TEST_P(TlsExtensionTest13, EmptyClientKeyShare) { - ClientHelloErrorTest( - std::make_shared(ssl_tls13_key_share_xtn, 2), - kTlsAlertHandshakeFailure); + ClientHelloErrorTest(std::make_shared( + client_, ssl_tls13_key_share_xtn, 2), + kTlsAlertHandshakeFailure); } // These tests only work in stream mode because the client sends a @@ -542,8 +555,7 @@ TEST_P(TlsExtensionTest13, EmptyClientKeyShare) { // packet gets dropped. TEST_F(TlsExtensionTest13Stream, DropServerKeyShare) { EnsureTlsSetup(); - server_->SetPacketFilter( - std::make_shared(ssl_tls13_key_share_xtn)); + MakeTlsFilter(server_, ssl_tls13_key_share_xtn); client_->ExpectSendAlert(kTlsAlertMissingExtension); server_->ExpectSendAlert(kTlsAlertBadRecordMac); ConnectExpectFail(); @@ -563,8 +575,7 @@ TEST_F(TlsExtensionTest13Stream, WrongServerKeyShare) { 0x02}; DataBuffer buf(key_share, sizeof(key_share)); EnsureTlsSetup(); - server_->SetPacketFilter( - std::make_shared(ssl_tls13_key_share_xtn, buf)); + MakeTlsFilter(server_, ssl_tls13_key_share_xtn, buf); client_->ExpectSendAlert(kTlsAlertIllegalParameter); server_->ExpectSendAlert(kTlsAlertBadRecordMac); ConnectExpectFail(); @@ -585,8 +596,7 @@ TEST_F(TlsExtensionTest13Stream, UnknownServerKeyShare) { 0x02}; DataBuffer buf(key_share, sizeof(key_share)); EnsureTlsSetup(); - server_->SetPacketFilter( - std::make_shared(ssl_tls13_key_share_xtn, buf)); + MakeTlsFilter(server_, ssl_tls13_key_share_xtn, buf); client_->ExpectSendAlert(kTlsAlertMissingExtension); server_->ExpectSendAlert(kTlsAlertBadRecordMac); ConnectExpectFail(); @@ -597,8 +607,8 @@ TEST_F(TlsExtensionTest13Stream, UnknownServerKeyShare) { TEST_F(TlsExtensionTest13Stream, AddServerSignatureAlgorithmsOnResumption) { SetupForResume(); DataBuffer empty; - server_->SetPacketFilter(std::make_shared( - ssl_signature_algorithms_xtn, empty)); + MakeTlsFilter(server_, ssl_signature_algorithms_xtn, + empty); client_->ExpectSendAlert(kTlsAlertUnsupportedExtension); server_->ExpectSendAlert(kTlsAlertBadRecordMac); ConnectExpectFail(); @@ -618,8 +628,12 @@ typedef std::function class TlsPreSharedKeyReplacer : public TlsExtensionFilter { public: - TlsPreSharedKeyReplacer(TlsPreSharedKeyReplacerFunc function) - : identities_(), binders_(), function_(function) {} + TlsPreSharedKeyReplacer(const std::shared_ptr& agent, + TlsPreSharedKeyReplacerFunc function) + : TlsExtensionFilter(agent), + identities_(), + binders_(), + function_(function) {} static size_t CopyAndMaybeReplace(TlsParser* parser, size_t size, const std::unique_ptr& replace, @@ -733,8 +747,10 @@ class TlsPreSharedKeyReplacer : public TlsExtensionFilter { TEST_F(TlsExtensionTest13Stream, ResumeEmptyPskLabel) { SetupForResume(); - client_->SetPacketFilter(std::make_shared([]( - TlsPreSharedKeyReplacer* r) { r->identities_[0].identity.Truncate(0); })); + MakeTlsFilter( + client_, [](TlsPreSharedKeyReplacer* r) { + r->identities_[0].identity.Truncate(0); + }); ConnectExpectAlert(server_, kTlsAlertIllegalParameter); client_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT); server_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO); @@ -744,10 +760,10 @@ TEST_F(TlsExtensionTest13Stream, ResumeEmptyPskLabel) { TEST_F(TlsExtensionTest13Stream, ResumeIncorrectBinderValue) { SetupForResume(); - client_->SetPacketFilter( - std::make_shared([](TlsPreSharedKeyReplacer* r) { + MakeTlsFilter( + client_, [](TlsPreSharedKeyReplacer* r) { r->binders_[0].Write(0, r->binders_[0].data()[0] ^ 0xff, 1); - })); + }); ConnectExpectAlert(server_, kTlsAlertDecryptError); client_->CheckErrorCode(SSL_ERROR_DECRYPT_ERROR_ALERT); server_->CheckErrorCode(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE); @@ -757,10 +773,10 @@ TEST_F(TlsExtensionTest13Stream, ResumeIncorrectBinderValue) { TEST_F(TlsExtensionTest13Stream, ResumeIncorrectBinderLength) { SetupForResume(); - client_->SetPacketFilter( - std::make_shared([](TlsPreSharedKeyReplacer* r) { + MakeTlsFilter( + client_, [](TlsPreSharedKeyReplacer* r) { r->binders_[0].Write(r->binders_[0].len(), 0xff, 1); - })); + }); ConnectExpectAlert(server_, kTlsAlertIllegalParameter); client_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT); server_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO); @@ -770,8 +786,8 @@ TEST_F(TlsExtensionTest13Stream, ResumeIncorrectBinderLength) { TEST_F(TlsExtensionTest13Stream, ResumeBinderTooShort) { SetupForResume(); - client_->SetPacketFilter(std::make_shared( - [](TlsPreSharedKeyReplacer* r) { r->binders_[0].Truncate(31); })); + MakeTlsFilter( + client_, [](TlsPreSharedKeyReplacer* r) { r->binders_[0].Truncate(31); }); ConnectExpectAlert(server_, kTlsAlertIllegalParameter); client_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT); server_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO); @@ -782,11 +798,11 @@ TEST_F(TlsExtensionTest13Stream, ResumeBinderTooShort) { TEST_F(TlsExtensionTest13Stream, ResumeTwoPsks) { SetupForResume(); - client_->SetPacketFilter( - std::make_shared([](TlsPreSharedKeyReplacer* r) { + MakeTlsFilter( + client_, [](TlsPreSharedKeyReplacer* r) { r->identities_.push_back(r->identities_[0]); r->binders_.push_back(r->binders_[0]); - })); + }); ConnectExpectAlert(server_, kTlsAlertDecryptError); client_->CheckErrorCode(SSL_ERROR_DECRYPT_ERROR_ALERT); server_->CheckErrorCode(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE); @@ -797,10 +813,10 @@ TEST_F(TlsExtensionTest13Stream, ResumeTwoPsks) { TEST_F(TlsExtensionTest13Stream, ResumeTwoIdentitiesOneBinder) { SetupForResume(); - client_->SetPacketFilter( - std::make_shared([](TlsPreSharedKeyReplacer* r) { + MakeTlsFilter( + client_, [](TlsPreSharedKeyReplacer* r) { r->identities_.push_back(r->identities_[0]); - })); + }); ConnectExpectAlert(server_, kTlsAlertIllegalParameter); client_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT); server_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO); @@ -809,8 +825,10 @@ TEST_F(TlsExtensionTest13Stream, ResumeTwoIdentitiesOneBinder) { TEST_F(TlsExtensionTest13Stream, ResumeOneIdentityTwoBinders) { SetupForResume(); - client_->SetPacketFilter(std::make_shared([]( - TlsPreSharedKeyReplacer* r) { r->binders_.push_back(r->binders_[0]); })); + MakeTlsFilter( + client_, [](TlsPreSharedKeyReplacer* r) { + r->binders_.push_back(r->binders_[0]); + }); ConnectExpectAlert(server_, kTlsAlertIllegalParameter); client_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT); server_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO); @@ -822,8 +840,8 @@ TEST_F(TlsExtensionTest13Stream, ResumePskExtensionNotLast) { const uint8_t empty_buf[] = {0}; DataBuffer empty(empty_buf, 0); // Inject an unused extension after the PSK extension. - client_->SetPacketFilter(std::make_shared( - kTlsHandshakeClientHello, 0xffff, empty)); + MakeTlsFilter(client_, kTlsHandshakeClientHello, 0xffff, + empty); ConnectExpectAlert(server_, kTlsAlertIllegalParameter); client_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT); server_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO); @@ -833,8 +851,8 @@ TEST_F(TlsExtensionTest13Stream, ResumeNoKeModes) { SetupForResume(); DataBuffer empty; - client_->SetPacketFilter(std::make_shared( - ssl_tls13_psk_key_exchange_modes_xtn)); + MakeTlsFilter(client_, + ssl_tls13_psk_key_exchange_modes_xtn); ConnectExpectAlert(server_, kTlsAlertMissingExtension); client_->CheckErrorCode(SSL_ERROR_MISSING_EXTENSION_ALERT); server_->CheckErrorCode(SSL_ERROR_MISSING_PSK_KEY_EXCHANGE_MODES); @@ -849,8 +867,8 @@ TEST_F(TlsExtensionTest13Stream, ResumeBogusKeModes) { kTls13PskKe}; DataBuffer modes(ke_modes, sizeof(ke_modes)); - client_->SetPacketFilter(std::make_shared( - ssl_tls13_psk_key_exchange_modes_xtn, modes)); + MakeTlsFilter( + client_, ssl_tls13_psk_key_exchange_modes_xtn, modes); client_->ExpectSendAlert(kTlsAlertBadRecordMac); server_->ExpectSendAlert(kTlsAlertBadRecordMac); ConnectExpectFail(); @@ -860,9 +878,8 @@ TEST_F(TlsExtensionTest13Stream, ResumeBogusKeModes) { TEST_P(TlsExtensionTest13, NoKeModesIfResumptionOff) { ConfigureSessionCache(RESUME_NONE, RESUME_NONE); - auto capture = std::make_shared( - ssl_tls13_psk_key_exchange_modes_xtn); - client_->SetPacketFilter(capture); + auto capture = MakeTlsFilter( + client_, ssl_tls13_psk_key_exchange_modes_xtn); Connect(); EXPECT_FALSE(capture->captured()); } @@ -958,11 +975,9 @@ class TlsBogusExtensionTest : public TlsConnectTestBase, static uint8_t empty_buf[1] = {0}; DataBuffer empty(empty_buf, 0); auto filter = - std::make_shared(message, extension, empty); + MakeTlsFilter(server_, message, extension, empty); if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) { - server_->SetTlsRecordFilter(filter); - } else { - server_->SetPacketFilter(filter); + filter->EnableDecryption(); } } @@ -1078,8 +1093,7 @@ TEST_P(TlsConnectStream, IncludePadding) { SECStatus rv = SSL_SetURL(client_->ssl_fd(), long_name); EXPECT_EQ(SECSuccess, rv); - auto capture = std::make_shared(ssl_padding_xtn); - client_->SetPacketFilter(capture); + auto capture = MakeTlsFilter(client_, ssl_padding_xtn); client_->StartConnect(); client_->Handshake(); EXPECT_TRUE(capture->captured()); diff --git a/security/nss/gtests/ssl_gtest/ssl_fragment_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_fragment_unittest.cc index 64b824786..f4940bf28 100644 --- a/security/nss/gtests/ssl_gtest/ssl_fragment_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_fragment_unittest.cc @@ -149,13 +149,13 @@ class RecordFragmenter : public PacketFilter { }; TEST_P(TlsConnectDatagram, FragmentClientPackets) { - client_->SetPacketFilter(std::make_shared()); + client_->SetFilter(std::make_shared()); Connect(); SendReceive(); } TEST_P(TlsConnectDatagram, FragmentServerPackets) { - server_->SetPacketFilter(std::make_shared()); + server_->SetFilter(std::make_shared()); Connect(); SendReceive(); } diff --git a/security/nss/gtests/ssl_gtest/ssl_fuzz_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_fuzz_unittest.cc index ab4c0eab7..99448321c 100644 --- a/security/nss/gtests/ssl_gtest/ssl_fuzz_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_fuzz_unittest.cc @@ -27,7 +27,8 @@ class TlsFuzzTest : public ::testing::Test {}; // Record the application data stream. class TlsApplicationDataRecorder : public TlsRecordFilter { public: - TlsApplicationDataRecorder() : buffer_() {} + TlsApplicationDataRecorder(const std::shared_ptr& agent) + : TlsRecordFilter(agent), buffer_() {} virtual PacketFilter::Action FilterRecord(const TlsRecordHeader& header, const DataBuffer& input, @@ -106,16 +107,16 @@ FUZZ_P(TlsConnectGeneric, DeterministicTranscript) { DisableECDHEServerKeyReuse(); DataBuffer buffer; - client_->SetPacketFilter(std::make_shared(buffer)); - server_->SetPacketFilter(std::make_shared(buffer)); + MakeTlsFilter(client_, buffer); + MakeTlsFilter(server_, buffer); // Reset the RNG state. EXPECT_EQ(SECSuccess, RNG_RandomUpdate(NULL, 0)); Connect(); // Ensure the filters go away before |buffer| does. - client_->DeletePacketFilter(); - server_->DeletePacketFilter(); + client_->ClearFilter(); + server_->ClearFilter(); if (last.len() > 0) { EXPECT_EQ(last, buffer); @@ -133,10 +134,8 @@ FUZZ_P(TlsConnectGeneric, ConnectSendReceive_NullCipher) { EnsureTlsSetup(); // Set up app data filters. - auto client_recorder = std::make_shared(); - client_->SetPacketFilter(client_recorder); - auto server_recorder = std::make_shared(); - server_->SetPacketFilter(server_recorder); + auto client_recorder = MakeTlsFilter(client_); + auto server_recorder = MakeTlsFilter(server_); Connect(); @@ -161,10 +160,9 @@ FUZZ_P(TlsConnectGeneric, ConnectSendReceive_NullCipher) { FUZZ_P(TlsConnectGeneric, BogusClientFinished) { EnsureTlsSetup(); - auto i1 = std::make_shared( - kTlsHandshakeFinished, + MakeTlsFilter( + client_, kTlsHandshakeFinished, DataBuffer(kShortEmptyFinished, sizeof(kShortEmptyFinished))); - client_->SetPacketFilter(i1); Connect(); SendReceive(); } @@ -173,10 +171,9 @@ FUZZ_P(TlsConnectGeneric, BogusClientFinished) { FUZZ_P(TlsConnectGeneric, BogusServerFinished) { EnsureTlsSetup(); - auto i1 = std::make_shared( - kTlsHandshakeFinished, + MakeTlsFilter( + server_, kTlsHandshakeFinished, DataBuffer(kLongEmptyFinished, sizeof(kLongEmptyFinished))); - server_->SetPacketFilter(i1); Connect(); SendReceive(); } @@ -187,7 +184,7 @@ FUZZ_P(TlsConnectGeneric, BogusServerAuthSignature) { uint8_t msg_type = version_ == SSL_LIBRARY_VERSION_TLS_1_3 ? kTlsHandshakeCertificateVerify : kTlsHandshakeServerKeyExchange; - server_->SetPacketFilter(std::make_shared(msg_type)); + MakeTlsFilter(server_, msg_type); Connect(); SendReceive(); } @@ -197,8 +194,7 @@ FUZZ_P(TlsConnectGeneric, BogusClientAuthSignature) { EnsureTlsSetup(); client_->SetupClientAuth(); server_->RequestClientAuth(true); - client_->SetPacketFilter( - std::make_shared(kTlsHandshakeCertificateVerify)); + MakeTlsFilter(client_, kTlsHandshakeCertificateVerify); Connect(); } @@ -219,29 +215,28 @@ FUZZ_P(TlsConnectGeneric, SessionTicketResumption) { FUZZ_P(TlsConnectGeneric, UnencryptedSessionTickets) { ConfigureSessionCache(RESUME_TICKET, RESUME_TICKET); - auto i1 = std::make_shared( - kTlsHandshakeNewSessionTicket); - server_->SetPacketFilter(i1); + auto filter = MakeTlsFilter( + server_, kTlsHandshakeNewSessionTicket); Connect(); - std::cerr << "ticket" << i1->buffer() << std::endl; + std::cerr << "ticket" << filter->buffer() << std::endl; size_t offset = 4; /* lifetime */ if (version_ == SSL_LIBRARY_VERSION_TLS_1_3) { offset += 4; /* ticket_age_add */ uint32_t nonce_len = 0; - EXPECT_TRUE(i1->buffer().Read(offset, 1, &nonce_len)); + EXPECT_TRUE(filter->buffer().Read(offset, 1, &nonce_len)); offset += 1 + nonce_len; } offset += 2 + /* ticket length */ 2; /* TLS_EX_SESS_TICKET_VERSION */ // Check the protocol version number. uint32_t tls_version = 0; - EXPECT_TRUE(i1->buffer().Read(offset, sizeof(version_), &tls_version)); + EXPECT_TRUE(filter->buffer().Read(offset, sizeof(version_), &tls_version)); EXPECT_EQ(version_, static_cast(tls_version)); // Check the cipher suite. uint32_t suite = 0; - EXPECT_TRUE(i1->buffer().Read(offset + sizeof(version_), 2, &suite)); + EXPECT_TRUE(filter->buffer().Read(offset + sizeof(version_), 2, &suite)); client_->CheckCipherSuite(static_cast(suite)); } } diff --git a/security/nss/gtests/ssl_gtest/ssl_hrr_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_hrr_unittest.cc index 93e19a720..05ae87034 100644 --- a/security/nss/gtests/ssl_gtest/ssl_hrr_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_hrr_unittest.cc @@ -35,17 +35,15 @@ TEST_P(TlsConnectTls13, HelloRetryRequestAbortsZeroRtt) { // Send first ClientHello and send 0-RTT data auto capture_early_data = - std::make_shared(ssl_tls13_early_data_xtn); - client_->SetPacketFilter(capture_early_data); + MakeTlsFilter(client_, ssl_tls13_early_data_xtn); client_->Handshake(); EXPECT_EQ(k0RttDataLen, PR_Write(client_->ssl_fd(), k0RttData, k0RttDataLen)); // 0-RTT write. EXPECT_TRUE(capture_early_data->captured()); // Send the HelloRetryRequest - auto hrr_capture = std::make_shared( - kTlsHandshakeHelloRetryRequest); - server_->SetPacketFilter(hrr_capture); + auto hrr_capture = MakeTlsFilter( + server_, kTlsHandshakeHelloRetryRequest); server_->Handshake(); EXPECT_LT(0U, hrr_capture->buffer().len()); @@ -56,8 +54,7 @@ TEST_P(TlsConnectTls13, HelloRetryRequestAbortsZeroRtt) { // Make a new capture for the early data. capture_early_data = - std::make_shared(ssl_tls13_early_data_xtn); - client_->SetPacketFilter(capture_early_data); + MakeTlsFilter(client_, ssl_tls13_early_data_xtn); // Complete the handshake successfully Handshake(); @@ -71,6 +68,10 @@ TEST_P(TlsConnectTls13, HelloRetryRequestAbortsZeroRtt) { // packet. If the record is split into two packets, or there are multiple // handshake packets, this will break. class CorrectMessageSeqAfterHrrFilter : public TlsRecordFilter { + public: + CorrectMessageSeqAfterHrrFilter(const std::shared_ptr& agent) + : TlsRecordFilter(agent) {} + protected: PacketFilter::Action FilterRecord(const TlsRecordHeader& header, const DataBuffer& record, size_t* offset, @@ -131,8 +132,7 @@ TEST_P(TlsConnectTls13, SecondClientHelloRejectEarlyDataXtn) { // Correct the DTLS message sequence number after an HRR. if (variant_ == ssl_variant_datagram) { - client_->SetPacketFilter( - std::make_shared()); + MakeTlsFilter(client_); } server_->SetPeer(client_); @@ -151,7 +151,8 @@ TEST_P(TlsConnectTls13, SecondClientHelloRejectEarlyDataXtn) { class KeyShareReplayer : public TlsExtensionFilter { public: - KeyShareReplayer() {} + KeyShareReplayer(const std::shared_ptr& agent) + : TlsExtensionFilter(agent) {} virtual PacketFilter::Action FilterExtension(uint16_t extension_type, const DataBuffer& input, @@ -178,7 +179,7 @@ class KeyShareReplayer : public TlsExtensionFilter { // server should reject this. TEST_P(TlsConnectTls13, RetryWithSameKeyShare) { EnsureTlsSetup(); - client_->SetPacketFilter(std::make_shared()); + MakeTlsFilter(client_); static const std::vector groups = {ssl_grp_ec_secp384r1, ssl_grp_ec_secp521r1}; server_->ConfigNamedGroups(groups); @@ -192,7 +193,7 @@ TEST_P(TlsConnectTls13, RetryWithSameKeyShare) { TEST_P(TlsConnectTls13, RetryWithTwoShares) { EnsureTlsSetup(); EXPECT_EQ(SECSuccess, SSL_SendAdditionalKeyShares(client_->ssl_fd(), 1)); - client_->SetPacketFilter(std::make_shared()); + MakeTlsFilter(client_); static const std::vector groups = {ssl_grp_ec_secp384r1, ssl_grp_ec_secp521r1}; @@ -238,9 +239,9 @@ TEST_P(TlsConnectTls13, RetryCallbackAcceptGroupMismatch) { return ssl_hello_retry_accept; }; - auto capture = std::make_shared(ssl_tls13_cookie_xtn); + auto capture = + MakeTlsFilter(server_, ssl_tls13_cookie_xtn); capture->SetHandshakeTypes({kTlsHandshakeHelloRetryRequest}); - server_->SetPacketFilter(capture); static const std::vector groups = {ssl_grp_ec_secp384r1}; server_->ConfigNamedGroups(groups); @@ -359,14 +360,14 @@ SSLHelloRetryRequestAction RetryHello(PRBool firstHello, TEST_P(TlsConnectTls13, RetryCallbackRetry) { EnsureTlsSetup(); - auto capture_hrr = std::make_shared( - ssl_hs_hello_retry_request); + auto capture_hrr = std::make_shared( + server_, ssl_hs_hello_retry_request); auto capture_key_share = - std::make_shared(ssl_tls13_key_share_xtn); + std::make_shared(server_, ssl_tls13_key_share_xtn); capture_key_share->SetHandshakeTypes({kTlsHandshakeHelloRetryRequest}); std::vector> chain = {capture_hrr, capture_key_share}; - server_->SetPacketFilter(std::make_shared(chain)); + server_->SetFilter(std::make_shared(chain)); size_t cb_called = 0; EXPECT_EQ(SECSuccess, SSL_HelloRetryRequestCallback(server_->ssl_fd(), @@ -383,8 +384,7 @@ TEST_P(TlsConnectTls13, RetryCallbackRetry) { << "no key_share extension expected"; auto capture_cookie = - std::make_shared(ssl_tls13_cookie_xtn); - client_->SetPacketFilter(capture_cookie); + MakeTlsFilter(client_, ssl_tls13_cookie_xtn); Handshake(); CheckConnected(); @@ -413,9 +413,8 @@ TEST_P(TlsConnectTls13, RetryCallbackRetryWithAdditionalShares) { EXPECT_EQ(SECSuccess, SSL_SendAdditionalKeyShares(client_->ssl_fd(), 1)); auto capture_server = - std::make_shared(ssl_tls13_key_share_xtn); + MakeTlsFilter(server_, ssl_tls13_key_share_xtn); capture_server->SetHandshakeTypes({kTlsHandshakeHelloRetryRequest}); - server_->SetPacketFilter(capture_server); size_t cb_called = 0; EXPECT_EQ(SECSuccess, SSL_HelloRetryRequestCallback(server_->ssl_fd(), @@ -431,8 +430,7 @@ TEST_P(TlsConnectTls13, RetryCallbackRetryWithAdditionalShares) { << "no key_share extension expected from server"; auto capture_client_2nd = - std::make_shared(ssl_tls13_key_share_xtn); - client_->SetPacketFilter(capture_client_2nd); + MakeTlsFilter(client_, ssl_tls13_key_share_xtn); Handshake(); CheckConnected(); @@ -449,12 +447,12 @@ TEST_P(TlsConnectTls13, RetryCallbackRetryWithGroupMismatch) { EnsureTlsSetup(); auto capture_cookie = - std::make_shared(ssl_tls13_cookie_xtn); + std::make_shared(server_, ssl_tls13_cookie_xtn); capture_cookie->SetHandshakeTypes({kTlsHandshakeHelloRetryRequest}); auto capture_key_share = - std::make_shared(ssl_tls13_key_share_xtn); + std::make_shared(server_, ssl_tls13_key_share_xtn); capture_key_share->SetHandshakeTypes({kTlsHandshakeHelloRetryRequest}); - server_->SetPacketFilter(std::make_shared( + server_->SetFilter(std::make_shared( ChainedPacketFilterInit{capture_cookie, capture_key_share})); static const std::vector groups = {ssl_grp_ec_secp384r1}; @@ -493,9 +491,8 @@ TEST_P(TlsConnectTls13, RetryCallbackRetryWithToken) { EnsureTlsSetup(); auto capture_key_share = - std::make_shared(ssl_tls13_key_share_xtn); + MakeTlsFilter(server_, ssl_tls13_key_share_xtn); capture_key_share->SetHandshakeTypes({kTlsHandshakeHelloRetryRequest}); - server_->SetPacketFilter(capture_key_share); size_t cb_called = 0; EXPECT_EQ(SECSuccess, @@ -513,9 +510,8 @@ TEST_P(TlsConnectTls13, RetryCallbackRetryWithTokenAndGroupMismatch) { server_->ConfigNamedGroups(groups); auto capture_key_share = - std::make_shared(ssl_tls13_key_share_xtn); + MakeTlsFilter(server_, ssl_tls13_key_share_xtn); capture_key_share->SetHandshakeTypes({kTlsHandshakeHelloRetryRequest}); - server_->SetPacketFilter(capture_key_share); size_t cb_called = 0; EXPECT_EQ(SECSuccess, @@ -589,8 +585,7 @@ TEST_P(TlsConnectTls13, RetryStatefulDropCookie) { EnsureTlsSetup(); TriggerHelloRetryRequest(client_, server_); - client_->SetPacketFilter( - std::make_shared(ssl_tls13_cookie_xtn)); + MakeTlsFilter(client_, ssl_tls13_cookie_xtn); ExpectAlert(server_, kTlsAlertMissingExtension); Handshake(); @@ -603,8 +598,8 @@ TEST_F(TlsConnectStreamTls13, RetryStatelessDamageFirstClientHello) { ConfigureSelfEncrypt(); EnsureTlsSetup(); - auto damage_ch = std::make_shared(0xfff3, DataBuffer()); - client_->SetPacketFilter(damage_ch); + auto damage_ch = + MakeTlsFilter(client_, 0xfff3, DataBuffer()); TriggerHelloRetryRequest(client_, server_); MakeNewServer(); @@ -625,8 +620,8 @@ TEST_F(TlsConnectStreamTls13, RetryStatelessDamageSecondClientHello) { TriggerHelloRetryRequest(client_, server_); MakeNewServer(); - auto damage_ch = std::make_shared(0xfff3, DataBuffer()); - client_->SetPacketFilter(damage_ch); + auto damage_ch = + MakeTlsFilter(client_, 0xfff3, DataBuffer()); // Key exchange fails when the handshake continues because client and server // disagree about the transcript. @@ -640,7 +635,7 @@ TEST_F(TlsConnectStreamTls13, RetryStatelessDamageSecondClientHello) { // Read the cipher suite from the HRR and disable it on the identified agent. static void DisableSuiteFromHrr( std::shared_ptr& agent, - std::shared_ptr& capture_hrr) { + std::shared_ptr& capture_hrr) { uint32_t tmp; size_t offset = 2 + 32; // skip version + server_random ASSERT_TRUE( @@ -657,9 +652,8 @@ TEST_P(TlsConnectTls13, RetryStatelessDisableSuiteClient) { ConfigureSelfEncrypt(); EnsureTlsSetup(); - auto capture_hrr = std::make_shared( - ssl_hs_hello_retry_request); - server_->SetPacketFilter(capture_hrr); + auto capture_hrr = + MakeTlsFilter(server_, ssl_hs_hello_retry_request); TriggerHelloRetryRequest(client_, server_); MakeNewServer(); @@ -678,9 +672,8 @@ TEST_P(TlsConnectTls13, RetryStatelessDisableSuiteServer) { ConfigureSelfEncrypt(); EnsureTlsSetup(); - auto capture_hrr = std::make_shared( - ssl_hs_hello_retry_request); - server_->SetPacketFilter(capture_hrr); + auto capture_hrr = + MakeTlsFilter(server_, ssl_hs_hello_retry_request); TriggerHelloRetryRequest(client_, server_); MakeNewServer(); @@ -761,8 +754,8 @@ TEST_F(TlsConnectStreamTls13, RetryWithDifferentCipherSuite) { static const std::vector groups = {ssl_grp_ec_secp384r1}; server_->ConfigNamedGroups(groups); // Then switch out the default suite (TLS_AES_128_GCM_SHA256). - server_->SetPacketFilter(std::make_shared( - TLS_CHACHA20_POLY1305_SHA256)); + MakeTlsFilter(server_, + TLS_CHACHA20_POLY1305_SHA256); client_->ExpectSendAlert(kTlsAlertIllegalParameter); server_->ExpectSendAlert(kTlsAlertBadRecordMac); @@ -777,7 +770,7 @@ TEST_F(TlsConnectDatagram13, DropClientSecondFlightWithHelloRetry) { static const std::vector groups = {ssl_grp_ec_secp384r1, ssl_grp_ec_secp521r1}; server_->ConfigNamedGroups(groups); - server_->SetPacketFilter(std::make_shared(0x2)); + server_->SetFilter(std::make_shared(0x2)); Connect(); } @@ -833,9 +826,9 @@ TEST_P(TlsKeyExchange13, EXPECT_EQ(SECSuccess, SSL_SendAdditionalKeyShares(client_->ssl_fd(), 1)); auto capture_server = - std::make_shared(ssl_tls13_key_share_xtn); + std::make_shared(server_, ssl_tls13_key_share_xtn); capture_server->SetHandshakeTypes({kTlsHandshakeHelloRetryRequest}); - server_->SetPacketFilter(std::make_shared( + server_->SetFilter(std::make_shared( ChainedPacketFilterInit{capture_hrr_, capture_server})); size_t cb_called = 0; diff --git a/security/nss/gtests/ssl_gtest/ssl_keylog_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_keylog_unittest.cc index 8ed342305..322b64837 100644 --- a/security/nss/gtests/ssl_gtest/ssl_keylog_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_keylog_unittest.cc @@ -20,8 +20,8 @@ static const std::string keylog_env = "SSLKEYLOGFILE=" + keylog_file_path; class KeyLogFileTest : public TlsConnectGeneric { public: - void SetUp() { - TlsConnectTestBase::SetUp(); + void SetUp() override { + TlsConnectGeneric::SetUp(); // Remove previous results (if any). (void)remove(keylog_file_path.c_str()); PR_SetEnv(keylog_env.c_str()); diff --git a/security/nss/gtests/ssl_gtest/ssl_loopback_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_loopback_unittest.cc index 4bc6e60ab..f1b78f52f 100644 --- a/security/nss/gtests/ssl_gtest/ssl_loopback_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_loopback_unittest.cc @@ -56,7 +56,8 @@ TEST_P(TlsConnectGeneric, CipherSuiteMismatch) { class TlsAlertRecorder : public TlsRecordFilter { public: - TlsAlertRecorder() : level_(255), description_(255) {} + TlsAlertRecorder(const std::shared_ptr& agent) + : TlsRecordFilter(agent), level_(255), description_(255) {} PacketFilter::Action FilterRecord(const TlsRecordHeader& header, const DataBuffer& input, @@ -86,9 +87,9 @@ class TlsAlertRecorder : public TlsRecordFilter { class HelloTruncator : public TlsHandshakeFilter { public: - HelloTruncator() + HelloTruncator(const std::shared_ptr& agent) : TlsHandshakeFilter( - {kTlsHandshakeClientHello, kTlsHandshakeServerHello}) {} + agent, {kTlsHandshakeClientHello, kTlsHandshakeServerHello}) {} PacketFilter::Action FilterHandshake(const HandshakeHeader& header, const DataBuffer& input, DataBuffer* output) override { @@ -99,9 +100,8 @@ class HelloTruncator : public TlsHandshakeFilter { // Verify that when NSS reports that an alert is sent, it is actually sent. TEST_P(TlsConnectGeneric, CaptureAlertServer) { - client_->SetPacketFilter(std::make_shared()); - auto alert_recorder = std::make_shared(); - server_->SetPacketFilter(alert_recorder); + MakeTlsFilter(client_); + auto alert_recorder = MakeTlsFilter(server_); ConnectExpectAlert(server_, kTlsAlertDecodeError); EXPECT_EQ(kTlsAlertFatal, alert_recorder->level()); @@ -109,9 +109,8 @@ TEST_P(TlsConnectGeneric, CaptureAlertServer) { } TEST_P(TlsConnectGenericPre13, CaptureAlertClient) { - server_->SetPacketFilter(std::make_shared()); - auto alert_recorder = std::make_shared(); - client_->SetPacketFilter(alert_recorder); + MakeTlsFilter(server_); + auto alert_recorder = MakeTlsFilter(client_); ConnectExpectAlert(client_, kTlsAlertDecodeError); EXPECT_EQ(kTlsAlertFatal, alert_recorder->level()); @@ -120,9 +119,8 @@ TEST_P(TlsConnectGenericPre13, CaptureAlertClient) { // In TLS 1.3, the server can't read the client alert. TEST_P(TlsConnectTls13, CaptureAlertClient) { - server_->SetPacketFilter(std::make_shared()); - auto alert_recorder = std::make_shared(); - client_->SetPacketFilter(alert_recorder); + MakeTlsFilter(server_); + auto alert_recorder = MakeTlsFilter(client_); StartConnect(); @@ -173,7 +171,8 @@ TEST_P(TlsConnectGeneric, ConnectSendReceive) { class SaveTlsRecord : public TlsRecordFilter { public: - SaveTlsRecord(size_t index) : index_(index), count_(0), contents_() {} + SaveTlsRecord(const std::shared_ptr& agent, size_t index) + : TlsRecordFilter(agent), index_(index), count_(0), contents_() {} const DataBuffer& contents() const { return contents_; } @@ -198,8 +197,8 @@ class SaveTlsRecord : public TlsRecordFilter { TEST_F(TlsConnectStreamTls13, DecryptRecordClient) { EnsureTlsSetup(); // 0 = ClientHello, 1 = Finished, 2 = SendReceive, 3 = SendBuffer - auto saved = std::make_shared(3); - client_->SetTlsRecordFilter(saved); + auto saved = MakeTlsFilter(client_, 3); + saved->EnableDecryption(); Connect(); SendReceive(); @@ -215,8 +214,8 @@ TEST_F(TlsConnectStreamTls13, DecryptRecordServer) { EXPECT_EQ(SECSuccess, SSL_OptionSet(server_->ssl_fd(), SSL_ENABLE_SESSION_TICKETS, PR_FALSE)); // 0 = ServerHello, 1 = other handshake, 2 = SendReceive, 3 = SendBuffer - auto saved = std::make_shared(3); - server_->SetTlsRecordFilter(saved); + auto saved = MakeTlsFilter(server_, 3); + saved->EnableDecryption(); Connect(); SendReceive(); @@ -228,7 +227,8 @@ TEST_F(TlsConnectStreamTls13, DecryptRecordServer) { class DropTlsRecord : public TlsRecordFilter { public: - DropTlsRecord(size_t index) : index_(index), count_(0) {} + DropTlsRecord(const std::shared_ptr& agent, size_t index) + : TlsRecordFilter(agent), index_(index), count_(0) {} protected: PacketFilter::Action FilterRecord(const TlsRecordHeader& header, @@ -253,7 +253,8 @@ TEST_F(TlsConnectStreamTls13, DropRecordServer) { SSL_ENABLE_SESSION_TICKETS, PR_FALSE)); // 0 = ServerHello, 1 = other handshake, 2 = first write - server_->SetTlsRecordFilter(std::make_shared(2)); + auto filter = MakeTlsFilter(server_, 2); + filter->EnableDecryption(); Connect(); server_->SendData(23, 23); // This should be dropped, so it won't be counted. server_->ResetSentBytes(); @@ -263,7 +264,8 @@ TEST_F(TlsConnectStreamTls13, DropRecordServer) { TEST_F(TlsConnectStreamTls13, DropRecordClient) { EnsureTlsSetup(); // 0 = ClientHello, 1 = Finished, 2 = first write - client_->SetTlsRecordFilter(std::make_shared(2)); + auto filter = MakeTlsFilter(client_, 2); + filter->EnableDecryption(); Connect(); client_->SendData(26, 26); // This should be dropped, so it won't be counted. client_->ResetSentBytes(); @@ -371,7 +373,8 @@ TEST_P(TlsHolddownTest, TestDtlsHolddownExpiryResumption) { class TlsPreCCSHeaderInjector : public TlsRecordFilter { public: - TlsPreCCSHeaderInjector() {} + TlsPreCCSHeaderInjector(const std::shared_ptr& agent) + : TlsRecordFilter(agent) {} virtual PacketFilter::Action FilterRecord( const TlsRecordHeader& record_header, const DataBuffer& input, size_t* offset, DataBuffer* output) override { @@ -388,14 +391,14 @@ class TlsPreCCSHeaderInjector : public TlsRecordFilter { }; TEST_P(TlsConnectStreamPre13, ClientFinishedHeaderBeforeCCS) { - client_->SetPacketFilter(std::make_shared()); + MakeTlsFilter(client_); ConnectExpectAlert(server_, kTlsAlertUnexpectedMessage); client_->CheckErrorCode(SSL_ERROR_HANDSHAKE_UNEXPECTED_ALERT); server_->CheckErrorCode(SSL_ERROR_RX_UNEXPECTED_CHANGE_CIPHER); } TEST_P(TlsConnectStreamPre13, ServerFinishedHeaderBeforeCCS) { - server_->SetPacketFilter(std::make_shared()); + MakeTlsFilter(server_); StartConnect(); ExpectAlert(client_, kTlsAlertUnexpectedMessage); Handshake(); @@ -476,8 +479,7 @@ TEST_F(TlsConnectTest, OneNRecordSplitting) { ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_0); EnsureTlsSetup(); ConnectWithCipherSuite(TLS_RSA_WITH_AES_128_CBC_SHA); - auto records = std::make_shared(); - server_->SetPacketFilter(records); + auto records = MakeTlsFilter(server_); // This should be split into 1, 16384 and 20. DataBuffer big_buffer; big_buffer.Allocate(1 + 16384 + 20); @@ -535,4 +537,27 @@ INSTANTIATE_TEST_CASE_P(Version12Plus, TlsConnectTls12Plus, ::testing::Combine(TlsConnectTestBase::kTlsVariantsAll, TlsConnectTestBase::kTlsV12Plus)); -} // namespace nspr_test +INSTANTIATE_TEST_CASE_P( + GenericStream, TlsConnectGenericResumption, + ::testing::Combine(TlsConnectTestBase::kTlsVariantsStream, + TlsConnectTestBase::kTlsVAll, + ::testing::Values(true, false))); +INSTANTIATE_TEST_CASE_P( + GenericDatagram, TlsConnectGenericResumption, + ::testing::Combine(TlsConnectTestBase::kTlsVariantsDatagram, + TlsConnectTestBase::kTlsV11Plus, + ::testing::Values(true, false))); + +INSTANTIATE_TEST_CASE_P( + GenericStream, TlsConnectGenericResumptionToken, + ::testing::Combine(TlsConnectTestBase::kTlsVariantsStream, + TlsConnectTestBase::kTlsVAll)); +INSTANTIATE_TEST_CASE_P( + GenericDatagram, TlsConnectGenericResumptionToken, + ::testing::Combine(TlsConnectTestBase::kTlsVariantsDatagram, + TlsConnectTestBase::kTlsV11Plus)); + +INSTANTIATE_TEST_CASE_P(GenericDatagram, TlsConnectTls13ResumptionToken, + TlsConnectTestBase::kTlsVariantsAll); + +} // namespace nss_test diff --git a/security/nss/gtests/ssl_gtest/ssl_record_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_record_unittest.cc index d1d496f49..3b8727850 100644 --- a/security/nss/gtests/ssl_gtest/ssl_record_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_record_unittest.cc @@ -103,8 +103,8 @@ TEST_P(TlsPaddingTest, LastByteOfPadWrong) { class RecordReplacer : public TlsRecordFilter { public: - RecordReplacer(size_t size) - : TlsRecordFilter(), enabled_(false), size_(size) {} + RecordReplacer(const std::shared_ptr& agent, size_t size) + : TlsRecordFilter(agent), enabled_(false), size_(size) {} PacketFilter::Action FilterRecord(const TlsRecordHeader& header, const DataBuffer& data, @@ -135,8 +135,8 @@ TEST_F(TlsConnectStreamTls13, LargeRecord) { EnsureTlsSetup(); const size_t record_limit = 16384; - auto replacer = std::make_shared(record_limit); - client_->SetTlsRecordFilter(replacer); + auto replacer = MakeTlsFilter(client_, record_limit); + replacer->EnableDecryption(); Connect(); replacer->Enable(); @@ -149,8 +149,8 @@ TEST_F(TlsConnectStreamTls13, TooLargeRecord) { EnsureTlsSetup(); const size_t record_limit = 16384; - auto replacer = std::make_shared(record_limit + 1); - client_->SetTlsRecordFilter(replacer); + auto replacer = MakeTlsFilter(client_, record_limit + 1); + replacer->EnableDecryption(); Connect(); replacer->Enable(); @@ -177,4 +177,4 @@ auto kTrueFalse = ::testing::ValuesIn(kTrueFalseArr); INSTANTIATE_TEST_CASE_P(TlsPadding, TlsPaddingTest, ::testing::Combine(kContentSizes, kTrueFalse)); -} // namespace nspr_test +} // namespace nss_test diff --git a/security/nss/gtests/ssl_gtest/ssl_resumption_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_resumption_unittest.cc index a413caf2c..eb78c0585 100644 --- a/security/nss/gtests/ssl_gtest/ssl_resumption_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_resumption_unittest.cc @@ -60,7 +60,7 @@ TEST_P(TlsConnectGenericPre13, ConnectResumed) { Connect(); } -TEST_P(TlsConnectGeneric, ConnectClientCacheDisabled) { +TEST_P(TlsConnectGenericResumption, ConnectClientCacheDisabled) { ConfigureSessionCache(RESUME_NONE, RESUME_SESSIONID); Connect(); SendReceive(); @@ -71,7 +71,7 @@ TEST_P(TlsConnectGeneric, ConnectClientCacheDisabled) { SendReceive(); } -TEST_P(TlsConnectGeneric, ConnectServerCacheDisabled) { +TEST_P(TlsConnectGenericResumption, ConnectServerCacheDisabled) { ConfigureSessionCache(RESUME_SESSIONID, RESUME_NONE); Connect(); SendReceive(); @@ -82,7 +82,7 @@ TEST_P(TlsConnectGeneric, ConnectServerCacheDisabled) { SendReceive(); } -TEST_P(TlsConnectGeneric, ConnectSessionCacheDisabled) { +TEST_P(TlsConnectGenericResumption, ConnectSessionCacheDisabled) { ConfigureSessionCache(RESUME_NONE, RESUME_NONE); Connect(); SendReceive(); @@ -93,7 +93,7 @@ TEST_P(TlsConnectGeneric, ConnectSessionCacheDisabled) { SendReceive(); } -TEST_P(TlsConnectGeneric, ConnectResumeSupportBoth) { +TEST_P(TlsConnectGenericResumption, ConnectResumeSupportBoth) { // This prefers tickets. ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH); Connect(); @@ -106,7 +106,7 @@ TEST_P(TlsConnectGeneric, ConnectResumeSupportBoth) { SendReceive(); } -TEST_P(TlsConnectGeneric, ConnectResumeClientTicketServerBoth) { +TEST_P(TlsConnectGenericResumption, ConnectResumeClientTicketServerBoth) { // This causes no resumption because the client needs the // session cache to resume even with tickets. ConfigureSessionCache(RESUME_TICKET, RESUME_BOTH); @@ -120,7 +120,7 @@ TEST_P(TlsConnectGeneric, ConnectResumeClientTicketServerBoth) { SendReceive(); } -TEST_P(TlsConnectGeneric, ConnectResumeClientBothTicketServerTicket) { +TEST_P(TlsConnectGenericResumption, ConnectResumeClientBothTicketServerTicket) { // This causes a ticket resumption. ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET); Connect(); @@ -133,7 +133,7 @@ TEST_P(TlsConnectGeneric, ConnectResumeClientBothTicketServerTicket) { SendReceive(); } -TEST_P(TlsConnectGeneric, ConnectResumeClientServerTicketOnly) { +TEST_P(TlsConnectGenericResumption, ConnectResumeClientServerTicketOnly) { // This causes no resumption because the client needs the // session cache to resume even with tickets. ConfigureSessionCache(RESUME_TICKET, RESUME_TICKET); @@ -147,7 +147,7 @@ TEST_P(TlsConnectGeneric, ConnectResumeClientServerTicketOnly) { SendReceive(); } -TEST_P(TlsConnectGeneric, ConnectResumeClientBothServerNone) { +TEST_P(TlsConnectGenericResumption, ConnectResumeClientBothServerNone) { ConfigureSessionCache(RESUME_BOTH, RESUME_NONE); Connect(); SendReceive(); @@ -159,7 +159,7 @@ TEST_P(TlsConnectGeneric, ConnectResumeClientBothServerNone) { SendReceive(); } -TEST_P(TlsConnectGeneric, ConnectResumeClientNoneServerBoth) { +TEST_P(TlsConnectGenericResumption, ConnectResumeClientNoneServerBoth) { ConfigureSessionCache(RESUME_NONE, RESUME_BOTH); Connect(); SendReceive(); @@ -202,7 +202,7 @@ TEST_P(TlsConnectGeneric, ConnectResumeClientBothTicketServerTicketForget) { SendReceive(); } -TEST_P(TlsConnectGeneric, ConnectWithExpiredTicketAtClient) { +TEST_P(TlsConnectGenericResumption, ConnectWithExpiredTicketAtClient) { SSLInt_SetTicketLifetime(1); // one second // This causes a ticket resumption. ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET); @@ -219,8 +219,7 @@ TEST_P(TlsConnectGeneric, ConnectWithExpiredTicketAtClient) { SSLExtensionType xtn = (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) ? ssl_tls13_pre_shared_key_xtn : ssl_session_ticket_xtn; - auto capture = std::make_shared(xtn); - client_->SetPacketFilter(capture); + auto capture = MakeTlsFilter(client_, xtn); Connect(); if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) { @@ -245,8 +244,7 @@ TEST_P(TlsConnectGeneric, ConnectWithExpiredTicketAtServer) { SSLExtensionType xtn = (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) ? ssl_tls13_pre_shared_key_xtn : ssl_session_ticket_xtn; - auto capture = std::make_shared(xtn); - client_->SetPacketFilter(capture); + auto capture = MakeTlsFilter(client_, xtn); StartConnect(); client_->Handshake(); EXPECT_TRUE(capture->captured()); @@ -327,25 +325,23 @@ TEST_P(TlsConnectGeneric, ServerSNICertTypeSwitch) { // Prior to TLS 1.3, we were not fully ephemeral; though 1.3 fixes that TEST_P(TlsConnectGenericPre13, ConnectEcdheTwiceReuseKey) { - auto i1 = std::make_shared( - kTlsHandshakeServerKeyExchange); - server_->SetPacketFilter(i1); + auto filter = MakeTlsFilter( + server_, kTlsHandshakeServerKeyExchange); Connect(); CheckKeys(); TlsServerKeyExchangeEcdhe dhe1; - EXPECT_TRUE(dhe1.Parse(i1->buffer())); + EXPECT_TRUE(dhe1.Parse(filter->buffer())); // Restart Reset(); - auto i2 = std::make_shared( - kTlsHandshakeServerKeyExchange); - server_->SetPacketFilter(i2); + auto filter2 = MakeTlsFilter( + server_, kTlsHandshakeServerKeyExchange); ConfigureSessionCache(RESUME_NONE, RESUME_NONE); Connect(); CheckKeys(); TlsServerKeyExchangeEcdhe dhe2; - EXPECT_TRUE(dhe2.Parse(i2->buffer())); + EXPECT_TRUE(dhe2.Parse(filter2->buffer())); // Make sure they are the same. EXPECT_EQ(dhe1.public_key_.len(), dhe2.public_key_.len()); @@ -356,26 +352,24 @@ TEST_P(TlsConnectGenericPre13, ConnectEcdheTwiceReuseKey) { // This test parses the ServerKeyExchange, which isn't in 1.3 TEST_P(TlsConnectGenericPre13, ConnectEcdheTwiceNewKey) { server_->SetOption(SSL_REUSE_SERVER_ECDHE_KEY, PR_FALSE); - auto i1 = std::make_shared( - kTlsHandshakeServerKeyExchange); - server_->SetPacketFilter(i1); + auto filter = MakeTlsFilter( + server_, kTlsHandshakeServerKeyExchange); Connect(); CheckKeys(); TlsServerKeyExchangeEcdhe dhe1; - EXPECT_TRUE(dhe1.Parse(i1->buffer())); + EXPECT_TRUE(dhe1.Parse(filter->buffer())); // Restart Reset(); server_->SetOption(SSL_REUSE_SERVER_ECDHE_KEY, PR_FALSE); - auto i2 = std::make_shared( - kTlsHandshakeServerKeyExchange); - server_->SetPacketFilter(i2); + auto filter2 = MakeTlsFilter( + server_, kTlsHandshakeServerKeyExchange); ConfigureSessionCache(RESUME_NONE, RESUME_NONE); Connect(); CheckKeys(); TlsServerKeyExchangeEcdhe dhe2; - EXPECT_TRUE(dhe2.Parse(i2->buffer())); + EXPECT_TRUE(dhe2.Parse(filter2->buffer())); // Make sure they are different. EXPECT_FALSE((dhe1.public_key_.len() == dhe2.public_key_.len()) && @@ -397,7 +391,7 @@ TEST_P(TlsConnectTls13, TestTls13ResumeDifferentGroup) { server_->ConfigNamedGroups(kFFDHEGroups); Connect(); CheckKeys(ssl_kea_dh, ssl_grp_ffdhe_2048, ssl_auth_rsa_sign, - ssl_sig_rsa_pss_sha256); + ssl_sig_rsa_pss_rsae_sha256); } // We need to enable different cipher suites at different times in the following @@ -417,7 +411,7 @@ static uint16_t ChooseAnotherCipher(uint16_t version) { } // Test that we don't resume when we can't negotiate the same cipher. -TEST_P(TlsConnectGeneric, TestResumeClientDifferentCipher) { +TEST_P(TlsConnectGenericResumption, TestResumeClientDifferentCipher) { ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET); client_->EnableSingleCipher(ChooseOneCipher(version_)); Connect(); @@ -434,15 +428,15 @@ TEST_P(TlsConnectGeneric, TestResumeClientDifferentCipher) { } else { ticket_extension = ssl_session_ticket_xtn; } - auto ticket_capture = std::make_shared(ticket_extension); - client_->SetPacketFilter(ticket_capture); + auto ticket_capture = + MakeTlsFilter(client_, ticket_extension); Connect(); CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign); EXPECT_EQ(0U, ticket_capture->extension().len()); } // Test that we don't resume when we can't negotiate the same cipher. -TEST_P(TlsConnectGeneric, TestResumeServerDifferentCipher) { +TEST_P(TlsConnectGenericResumption, TestResumeServerDifferentCipher) { ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET); server_->EnableSingleCipher(ChooseOneCipher(version_)); Connect(); @@ -468,8 +462,8 @@ TEST_P(TlsConnectStream, TestResumptionOverrideCipher) { Reset(); ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET); - server_->SetPacketFilter(std::make_shared( - ChooseAnotherCipher(version_))); + MakeTlsFilter(server_, + ChooseAnotherCipher(version_)); if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) { client_->ExpectSendAlert(kTlsAlertIllegalParameter); @@ -490,8 +484,10 @@ TEST_P(TlsConnectStream, TestResumptionOverrideCipher) { class SelectedVersionReplacer : public TlsHandshakeFilter { public: - SelectedVersionReplacer(uint16_t version) - : TlsHandshakeFilter({kTlsHandshakeServerHello}), version_(version) {} + SelectedVersionReplacer(const std::shared_ptr& agent, + uint16_t version) + : TlsHandshakeFilter(agent, {kTlsHandshakeServerHello}), + version_(version) {} protected: PacketFilter::Action FilterHandshake(const HandshakeHeader& header, @@ -543,8 +539,7 @@ TEST_P(TlsConnectGenericPre13, TestResumptionOverrideVersion) { // Enable the lower version on the client. client_->SetVersionRange(version_ - 1, version_); server_->EnableSingleCipher(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA); - server_->SetPacketFilter( - std::make_shared(override_version)); + MakeTlsFilter(server_, override_version); ConnectExpectAlert(client_, kTlsAlertHandshakeFailure); client_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_SERVER_HELLO); @@ -567,12 +562,12 @@ TEST_F(TlsConnectTest, TestTls13ResumptionTwice) { ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET); ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3); ExpectResumption(RESUME_TICKET); - auto c1 = std::make_shared(ssl_tls13_pre_shared_key_xtn); - client_->SetPacketFilter(c1); + auto c1 = + MakeTlsFilter(client_, ssl_tls13_pre_shared_key_xtn); Connect(); SendReceive(); CheckKeys(ssl_kea_ecdh, ssl_grp_ec_curve25519, ssl_auth_rsa_sign, - ssl_sig_rsa_pss_sha256); + ssl_sig_rsa_pss_rsae_sha256); // The filter will go away when we reset, so save the captured extension. DataBuffer initialTicket(c1->extension()); ASSERT_LT(0U, initialTicket.len()); @@ -584,13 +579,13 @@ TEST_F(TlsConnectTest, TestTls13ResumptionTwice) { ClearStats(); ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET); ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3); - auto c2 = std::make_shared(ssl_tls13_pre_shared_key_xtn); - client_->SetPacketFilter(c2); + auto c2 = + MakeTlsFilter(client_, ssl_tls13_pre_shared_key_xtn); ExpectResumption(RESUME_TICKET); Connect(); SendReceive(); CheckKeys(ssl_kea_ecdh, ssl_grp_ec_curve25519, ssl_auth_rsa_sign, - ssl_sig_rsa_pss_sha256); + ssl_sig_rsa_pss_rsae_sha256); ASSERT_LT(0U, c2->extension().len()); ScopedCERTCertificate cert2(SSL_PeerCertificate(client_->ssl_fd())); @@ -656,9 +651,9 @@ TEST_F(TlsConnectTest, TestTls13ResumptionDuplicateNSTWithToken) { ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET); ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3); - auto nst_capture = std::make_shared( - ssl_hs_new_session_ticket); - server_->SetTlsRecordFilter(nst_capture); + auto nst_capture = + MakeTlsFilter(server_, ssl_hs_new_session_ticket); + nst_capture->EnableDecryption(); Connect(); // Clear the session ticket keys to invalidate the old ticket. @@ -679,8 +674,7 @@ TEST_F(TlsConnectTest, TestTls13ResumptionDuplicateNSTWithToken) { ExpectResumption(RESUME_TICKET); auto psk_capture = - std::make_shared(ssl_tls13_pre_shared_key_xtn); - client_->SetPacketFilter(psk_capture); + MakeTlsFilter(client_, ssl_tls13_pre_shared_key_xtn); Connect(); SendReceive(); @@ -696,9 +690,9 @@ TEST_F(TlsConnectTest, SendSessionTicketWithTicketsDisabled) { EXPECT_EQ(SECSuccess, SSL_OptionSet(server_->ssl_fd(), SSL_ENABLE_SESSION_TICKETS, PR_FALSE)); - auto nst_capture = std::make_shared( - ssl_hs_new_session_ticket); - server_->SetTlsRecordFilter(nst_capture); + auto nst_capture = + MakeTlsFilter(server_, ssl_hs_new_session_ticket); + nst_capture->EnableDecryption(); Connect(); EXPECT_EQ(0U, nst_capture->buffer().len()) << "expect nothing captured yet"; @@ -715,8 +709,7 @@ TEST_F(TlsConnectTest, SendSessionTicketWithTicketsDisabled) { ExpectResumption(RESUME_TICKET); auto psk_capture = - std::make_shared(ssl_tls13_pre_shared_key_xtn); - client_->SetPacketFilter(psk_capture); + MakeTlsFilter(client_, ssl_tls13_pre_shared_key_xtn); Connect(); SendReceive(); @@ -819,20 +812,20 @@ TEST_F(TlsConnectTest, TestTls13ResumptionForcedDowngrade) { // We will eventually fail the (sid.version == SH.version) check. std::vector> filters; filters.push_back(std::make_shared( - TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256)); - filters.push_back( - std::make_shared(SSL_LIBRARY_VERSION_TLS_1_2)); + server_, TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256)); + filters.push_back(std::make_shared( + server_, SSL_LIBRARY_VERSION_TLS_1_2)); // Drop a bunch of extensions so that we get past the SH processing. The // version extension says TLS 1.3, which is counter to our goal, the others // are not permitted in TLS 1.2 handshakes. + filters.push_back(std::make_shared( + server_, ssl_tls13_supported_versions_xtn)); filters.push_back( - std::make_shared(ssl_tls13_supported_versions_xtn)); - filters.push_back( - std::make_shared(ssl_tls13_key_share_xtn)); - filters.push_back( - std::make_shared(ssl_tls13_pre_shared_key_xtn)); - server_->SetPacketFilter(std::make_shared(filters)); + std::make_shared(server_, ssl_tls13_key_share_xtn)); + filters.push_back(std::make_shared( + server_, ssl_tls13_pre_shared_key_xtn)); + server_->SetFilter(std::make_shared(filters)); // The client here generates an unexpected_message alert when it receives an // encrypted handshake message from the server (EncryptedExtension). The @@ -845,13 +838,13 @@ TEST_F(TlsConnectTest, TestTls13ResumptionForcedDowngrade) { server_->CheckErrorCode(SSL_ERROR_BAD_MAC_READ); } -TEST_P(TlsConnectGeneric, ReConnectTicket) { +TEST_P(TlsConnectGenericResumption, ReConnectTicket) { ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH); server_->EnableSingleCipher(ChooseOneCipher(version_)); Connect(); SendReceive(); CheckKeys(ssl_kea_ecdh, ssl_grp_ec_curve25519, ssl_auth_rsa_sign, - ssl_sig_rsa_pss_sha256); + ssl_sig_rsa_pss_rsae_sha256); // Resume Reset(); ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH); @@ -859,7 +852,7 @@ TEST_P(TlsConnectGeneric, ReConnectTicket) { Connect(); // Only the client knows this. CheckKeysResumption(ssl_kea_ecdh, ssl_grp_none, ssl_grp_ec_curve25519, - ssl_auth_rsa_sign, ssl_sig_rsa_pss_sha256); + ssl_auth_rsa_sign, ssl_sig_rsa_pss_rsae_sha256); } TEST_P(TlsConnectGenericPre13, ReConnectCache) { @@ -868,22 +861,22 @@ TEST_P(TlsConnectGenericPre13, ReConnectCache) { Connect(); SendReceive(); CheckKeys(ssl_kea_ecdh, ssl_grp_ec_curve25519, ssl_auth_rsa_sign, - ssl_sig_rsa_pss_sha256); + ssl_sig_rsa_pss_rsae_sha256); // Resume Reset(); ExpectResumption(RESUME_SESSIONID); Connect(); CheckKeysResumption(ssl_kea_ecdh, ssl_grp_none, ssl_grp_ec_curve25519, - ssl_auth_rsa_sign, ssl_sig_rsa_pss_sha256); + ssl_auth_rsa_sign, ssl_sig_rsa_pss_rsae_sha256); } -TEST_P(TlsConnectGeneric, ReConnectAgainTicket) { +TEST_P(TlsConnectGenericResumption, ReConnectAgainTicket) { ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH); server_->EnableSingleCipher(ChooseOneCipher(version_)); Connect(); SendReceive(); CheckKeys(ssl_kea_ecdh, ssl_grp_ec_curve25519, ssl_auth_rsa_sign, - ssl_sig_rsa_pss_sha256); + ssl_sig_rsa_pss_rsae_sha256); // Resume Reset(); ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH); @@ -891,7 +884,7 @@ TEST_P(TlsConnectGeneric, ReConnectAgainTicket) { Connect(); // Only the client knows this. CheckKeysResumption(ssl_kea_ecdh, ssl_grp_none, ssl_grp_ec_curve25519, - ssl_auth_rsa_sign, ssl_sig_rsa_pss_sha256); + ssl_auth_rsa_sign, ssl_sig_rsa_pss_rsae_sha256); // Resume connection again Reset(); ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH); @@ -899,7 +892,140 @@ TEST_P(TlsConnectGeneric, ReConnectAgainTicket) { Connect(); // Only the client knows this. CheckKeysResumption(ssl_kea_ecdh, ssl_grp_none, ssl_grp_ec_curve25519, - ssl_auth_rsa_sign, ssl_sig_rsa_pss_sha256); + ssl_auth_rsa_sign, ssl_sig_rsa_pss_rsae_sha256); +} + +void CheckGetInfoResult(uint32_t alpnSize, uint32_t earlyDataSize, + ScopedCERTCertificate& cert, + ScopedSSLResumptionTokenInfo& token) { + ASSERT_TRUE(cert); + ASSERT_TRUE(token->peerCert); + + // Check that the server cert is the correct one. + ASSERT_EQ(cert->derCert.len, token->peerCert->derCert.len); + EXPECT_EQ(0, memcmp(cert->derCert.data, token->peerCert->derCert.data, + cert->derCert.len)); + + ASSERT_EQ(alpnSize, token->alpnSelectionLen); + EXPECT_EQ(0, memcmp("a", token->alpnSelection, token->alpnSelectionLen)); + + ASSERT_EQ(earlyDataSize, token->maxEarlyDataSize); +} + +TEST_P(TlsConnectGenericResumptionToken, ConnectResumeGetInfo) { + ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH); + Connect(); + SendReceive(); + + Reset(); + ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH); + ExpectResumption(RESUME_TICKET); + + StartConnect(); + ASSERT_TRUE(client_->MaybeSetResumptionToken()); + + // Get resumption token infos + SSLResumptionTokenInfo tokenInfo = {0}; + ScopedSSLResumptionTokenInfo token(&tokenInfo); + client_->GetTokenInfo(token); + ScopedCERTCertificate cert( + PK11_FindCertFromNickname(server_->name().c_str(), nullptr)); + + CheckGetInfoResult(0, 0, cert, token); + + Handshake(); + CheckConnected(); + + SendReceive(); +} + +TEST_P(TlsConnectGenericResumptionToken, ConnectResumeGetInfoAlpn) { + EnableAlpn(); + ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH); + Connect(); + CheckAlpn("a"); + SendReceive(); + + Reset(); + EnableAlpn(); + ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH); + ExpectResumption(RESUME_TICKET); + + StartConnect(); + ASSERT_TRUE(client_->MaybeSetResumptionToken()); + + // Get resumption token infos + SSLResumptionTokenInfo tokenInfo = {0}; + ScopedSSLResumptionTokenInfo token(&tokenInfo); + client_->GetTokenInfo(token); + ScopedCERTCertificate cert( + PK11_FindCertFromNickname(server_->name().c_str(), nullptr)); + + CheckGetInfoResult(1, 0, cert, token); + + Handshake(); + CheckConnected(); + CheckAlpn("a"); + + SendReceive(); +} + +TEST_P(TlsConnectTls13ResumptionToken, ConnectResumeGetInfoZeroRtt) { + EnableAlpn(); + SSLInt_RolloverAntiReplay(); + ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH); + server_->Set0RttEnabled(true); + Connect(); + CheckAlpn("a"); + SendReceive(); + + Reset(); + EnableAlpn(); + ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH); + ExpectResumption(RESUME_TICKET); + + StartConnect(); + server_->Set0RttEnabled(true); + client_->Set0RttEnabled(true); + ASSERT_TRUE(client_->MaybeSetResumptionToken()); + + // Get resumption token infos + SSLResumptionTokenInfo tokenInfo = {0}; + ScopedSSLResumptionTokenInfo token(&tokenInfo); + client_->GetTokenInfo(token); + ScopedCERTCertificate cert( + PK11_FindCertFromNickname(server_->name().c_str(), nullptr)); + + CheckGetInfoResult(1, 1024, cert, token); + + ZeroRttSendReceive(true, true); + Handshake(); + ExpectEarlyDataAccepted(true); + CheckConnected(); + CheckAlpn("a"); + + SendReceive(); +} + +// Resumption on sessions with client authentication only works with internal +// caching. +TEST_P(TlsConnectGenericResumption, ConnectResumeClientAuth) { + ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH); + client_->SetupClientAuth(); + server_->RequestClientAuth(true); + Connect(); + SendReceive(); + EXPECT_FALSE(client_->resumption_callback_called()); + + Reset(); + ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH); + if (use_external_cache()) { + ExpectResumption(RESUME_NONE); + } else { + ExpectResumption(RESUME_TICKET); + } + Connect(); + SendReceive(); } } // namespace nss_test diff --git a/security/nss/gtests/ssl_gtest/ssl_skip_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_skip_unittest.cc index 335bfecfa..e4a9e5aed 100644 --- a/security/nss/gtests/ssl_gtest/ssl_skip_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_skip_unittest.cc @@ -22,8 +22,11 @@ namespace nss_test { class TlsHandshakeSkipFilter : public TlsRecordFilter { public: // A TLS record filter that skips handshake messages of the identified type. - TlsHandshakeSkipFilter(uint8_t handshake_type) - : handshake_type_(handshake_type), skipped_(false) {} + TlsHandshakeSkipFilter(const std::shared_ptr& agent, + uint8_t handshake_type) + : TlsRecordFilter(agent), + handshake_type_(handshake_type), + skipped_(false) {} protected: // Takes a record; if it is a handshake record, it removes the first handshake @@ -92,9 +95,14 @@ class TlsSkipTest : public TlsConnectTestBase, TlsSkipTest() : TlsConnectTestBase(std::get<0>(GetParam()), std::get<1>(GetParam())) {} + void SetUp() override { + TlsConnectTestBase::SetUp(); + EnsureTlsSetup(); + } + void ServerSkipTest(std::shared_ptr filter, uint8_t alert = kTlsAlertUnexpectedMessage) { - server_->SetPacketFilter(filter); + server_->SetFilter(filter); ConnectExpectAlert(client_, alert); } }; @@ -105,9 +113,14 @@ class Tls13SkipTest : public TlsConnectTestBase, Tls13SkipTest() : TlsConnectTestBase(GetParam(), SSL_LIBRARY_VERSION_TLS_1_3) {} - void ServerSkipTest(std::shared_ptr filter, int32_t error) { + void SetUp() override { + TlsConnectTestBase::SetUp(); EnsureTlsSetup(); - server_->SetTlsRecordFilter(filter); + } + + void ServerSkipTest(std::shared_ptr filter, int32_t error) { + filter->EnableDecryption(); + server_->SetFilter(filter); ExpectAlert(client_, kTlsAlertUnexpectedMessage); ConnectExpectFail(); client_->CheckErrorCode(error); @@ -115,8 +128,8 @@ class Tls13SkipTest : public TlsConnectTestBase, } void ClientSkipTest(std::shared_ptr filter, int32_t error) { - EnsureTlsSetup(); - client_->SetTlsRecordFilter(filter); + filter->EnableDecryption(); + client_->SetFilter(filter); server_->ExpectSendAlert(kTlsAlertUnexpectedMessage); ConnectExpectFailOneSide(TlsAgent::SERVER); @@ -129,48 +142,49 @@ class Tls13SkipTest : public TlsConnectTestBase, TEST_P(TlsSkipTest, SkipCertificateRsa) { EnableOnlyStaticRsaCiphers(); - ServerSkipTest( - std::make_shared(kTlsHandshakeCertificate)); + ServerSkipTest(std::make_shared( + server_, kTlsHandshakeCertificate)); client_->CheckErrorCode(SSL_ERROR_RX_UNEXPECTED_HELLO_DONE); } TEST_P(TlsSkipTest, SkipCertificateDhe) { - ServerSkipTest( - std::make_shared(kTlsHandshakeCertificate)); + ServerSkipTest(std::make_shared( + server_, kTlsHandshakeCertificate)); client_->CheckErrorCode(SSL_ERROR_RX_UNEXPECTED_SERVER_KEY_EXCH); } TEST_P(TlsSkipTest, SkipCertificateEcdhe) { - ServerSkipTest( - std::make_shared(kTlsHandshakeCertificate)); + ServerSkipTest(std::make_shared( + server_, kTlsHandshakeCertificate)); client_->CheckErrorCode(SSL_ERROR_RX_UNEXPECTED_SERVER_KEY_EXCH); } TEST_P(TlsSkipTest, SkipCertificateEcdsa) { Reset(TlsAgent::kServerEcdsa256); - ServerSkipTest( - std::make_shared(kTlsHandshakeCertificate)); + ServerSkipTest(std::make_shared( + server_, kTlsHandshakeCertificate)); client_->CheckErrorCode(SSL_ERROR_RX_UNEXPECTED_SERVER_KEY_EXCH); } TEST_P(TlsSkipTest, SkipServerKeyExchange) { - ServerSkipTest( - std::make_shared(kTlsHandshakeServerKeyExchange)); + ServerSkipTest(std::make_shared( + server_, kTlsHandshakeServerKeyExchange)); client_->CheckErrorCode(SSL_ERROR_RX_UNEXPECTED_HELLO_DONE); } TEST_P(TlsSkipTest, SkipServerKeyExchangeEcdsa) { Reset(TlsAgent::kServerEcdsa256); - ServerSkipTest( - std::make_shared(kTlsHandshakeServerKeyExchange)); + ServerSkipTest(std::make_shared( + server_, kTlsHandshakeServerKeyExchange)); client_->CheckErrorCode(SSL_ERROR_RX_UNEXPECTED_HELLO_DONE); } TEST_P(TlsSkipTest, SkipCertAndKeyExch) { - auto chain = std::make_shared(ChainedPacketFilterInit{ - std::make_shared(kTlsHandshakeCertificate), - std::make_shared( - kTlsHandshakeServerKeyExchange)}); + auto chain = std::make_shared( + ChainedPacketFilterInit{std::make_shared( + server_, kTlsHandshakeCertificate), + std::make_shared( + server_, kTlsHandshakeServerKeyExchange)}); ServerSkipTest(chain); client_->CheckErrorCode(SSL_ERROR_RX_UNEXPECTED_HELLO_DONE); } @@ -178,48 +192,48 @@ TEST_P(TlsSkipTest, SkipCertAndKeyExch) { TEST_P(TlsSkipTest, SkipCertAndKeyExchEcdsa) { Reset(TlsAgent::kServerEcdsa256); auto chain = std::make_shared(); - chain->Add( - std::make_shared(kTlsHandshakeCertificate)); - chain->Add( - std::make_shared(kTlsHandshakeServerKeyExchange)); + chain->Add(std::make_shared( + server_, kTlsHandshakeCertificate)); + chain->Add(std::make_shared( + server_, kTlsHandshakeServerKeyExchange)); ServerSkipTest(chain); client_->CheckErrorCode(SSL_ERROR_RX_UNEXPECTED_HELLO_DONE); } TEST_P(Tls13SkipTest, SkipEncryptedExtensions) { ServerSkipTest(std::make_shared( - kTlsHandshakeEncryptedExtensions), + server_, kTlsHandshakeEncryptedExtensions), SSL_ERROR_RX_UNEXPECTED_CERTIFICATE); } TEST_P(Tls13SkipTest, SkipServerCertificate) { - ServerSkipTest( - std::make_shared(kTlsHandshakeCertificate), - SSL_ERROR_RX_UNEXPECTED_CERT_VERIFY); + ServerSkipTest(std::make_shared( + server_, kTlsHandshakeCertificate), + SSL_ERROR_RX_UNEXPECTED_CERT_VERIFY); } TEST_P(Tls13SkipTest, SkipServerCertificateVerify) { - ServerSkipTest( - std::make_shared(kTlsHandshakeCertificateVerify), - SSL_ERROR_RX_UNEXPECTED_FINISHED); + ServerSkipTest(std::make_shared( + server_, kTlsHandshakeCertificateVerify), + SSL_ERROR_RX_UNEXPECTED_FINISHED); } TEST_P(Tls13SkipTest, SkipClientCertificate) { client_->SetupClientAuth(); server_->RequestClientAuth(true); client_->ExpectReceiveAlert(kTlsAlertUnexpectedMessage); - ClientSkipTest( - std::make_shared(kTlsHandshakeCertificate), - SSL_ERROR_RX_UNEXPECTED_CERT_VERIFY); + ClientSkipTest(std::make_shared( + client_, kTlsHandshakeCertificate), + SSL_ERROR_RX_UNEXPECTED_CERT_VERIFY); } TEST_P(Tls13SkipTest, SkipClientCertificateVerify) { client_->SetupClientAuth(); server_->RequestClientAuth(true); client_->ExpectReceiveAlert(kTlsAlertUnexpectedMessage); - ClientSkipTest( - std::make_shared(kTlsHandshakeCertificateVerify), - SSL_ERROR_RX_UNEXPECTED_FINISHED); + ClientSkipTest(std::make_shared( + client_, kTlsHandshakeCertificateVerify), + SSL_ERROR_RX_UNEXPECTED_FINISHED); } INSTANTIATE_TEST_CASE_P( diff --git a/security/nss/gtests/ssl_gtest/ssl_staticrsa_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_staticrsa_unittest.cc index e7fe44d92..e5fccc12b 100644 --- a/security/nss/gtests/ssl_gtest/ssl_staticrsa_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_staticrsa_unittest.cc @@ -48,10 +48,9 @@ TEST_P(TlsConnectGenericPre13, ConnectStaticRSA) { // This test is stream so we can catch the bad_record_mac alert. TEST_P(TlsConnectStreamPre13, ConnectStaticRSABogusCKE) { EnableOnlyStaticRsaCiphers(); - auto i1 = std::make_shared( - kTlsHandshakeClientKeyExchange, + MakeTlsFilter( + client_, kTlsHandshakeClientKeyExchange, DataBuffer(kBogusClientKeyExchange, sizeof(kBogusClientKeyExchange))); - client_->SetPacketFilter(i1); ConnectExpectAlert(server_, kTlsAlertBadRecordMac); } @@ -59,8 +58,7 @@ TEST_P(TlsConnectStreamPre13, ConnectStaticRSABogusCKE) { // This test is stream so we can catch the bad_record_mac alert. TEST_P(TlsConnectStreamPre13, ConnectStaticRSABogusPMSVersionDetect) { EnableOnlyStaticRsaCiphers(); - client_->SetPacketFilter( - std::make_shared(server_)); + MakeTlsFilter(client_, server_); ConnectExpectAlert(server_, kTlsAlertBadRecordMac); } @@ -69,8 +67,7 @@ TEST_P(TlsConnectStreamPre13, ConnectStaticRSABogusPMSVersionDetect) { // ConnectStaticRSABogusPMSVersionDetect. TEST_P(TlsConnectGenericPre13, ConnectStaticRSABogusPMSVersionIgnore) { EnableOnlyStaticRsaCiphers(); - client_->SetPacketFilter( - std::make_shared(server_)); + MakeTlsFilter(client_, server_); server_->SetOption(SSL_ROLLBACK_DETECTION, PR_FALSE); Connect(); } @@ -79,10 +76,9 @@ TEST_P(TlsConnectGenericPre13, ConnectStaticRSABogusPMSVersionIgnore) { TEST_P(TlsConnectStreamPre13, ConnectExtendedMasterSecretStaticRSABogusCKE) { EnableOnlyStaticRsaCiphers(); EnableExtendedMasterSecret(); - auto inspect = std::make_shared( - kTlsHandshakeClientKeyExchange, + MakeTlsFilter( + client_, kTlsHandshakeClientKeyExchange, DataBuffer(kBogusClientKeyExchange, sizeof(kBogusClientKeyExchange))); - client_->SetPacketFilter(inspect); ConnectExpectAlert(server_, kTlsAlertBadRecordMac); } @@ -91,8 +87,7 @@ TEST_P(TlsConnectStreamPre13, ConnectExtendedMasterSecretStaticRSABogusPMSVersionDetect) { EnableOnlyStaticRsaCiphers(); EnableExtendedMasterSecret(); - client_->SetPacketFilter( - std::make_shared(server_)); + MakeTlsFilter(client_, server_); ConnectExpectAlert(server_, kTlsAlertBadRecordMac); } @@ -100,10 +95,9 @@ TEST_P(TlsConnectStreamPre13, ConnectExtendedMasterSecretStaticRSABogusPMSVersionIgnore) { EnableOnlyStaticRsaCiphers(); EnableExtendedMasterSecret(); - client_->SetPacketFilter( - std::make_shared(server_)); + MakeTlsFilter(client_, server_); server_->SetOption(SSL_ROLLBACK_DETECTION, PR_FALSE); Connect(); } -} // namespace nspr_test +} // namespace nss_test diff --git a/security/nss/gtests/ssl_gtest/ssl_tls13compat_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_tls13compat_unittest.cc index 75cee52fc..f5ccf096b 100644 --- a/security/nss/gtests/ssl_gtest/ssl_tls13compat_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_tls13compat_unittest.cc @@ -67,10 +67,7 @@ class Tls13CompatTest : public TlsConnectStreamTls13 { private: struct Recorders { - Recorders() - : records_(new TlsRecordRecorder()), - hello_(new TlsInspectorRecordHandshakeMessage(std::set( - {kTlsHandshakeClientHello, kTlsHandshakeServerHello}))) {} + Recorders() : records_(nullptr), hello_(nullptr) {} uint8_t session_id_length() const { // session_id is always after version (2) and random (32). @@ -91,12 +88,22 @@ class Tls13CompatTest : public TlsConnectStreamTls13 { } void Install(std::shared_ptr& agent) { - agent->SetPacketFilter(std::make_shared( + if (records_ && records_->agent() == agent) { + // Avoid replacing the filters if they are already installed on this + // agent. This ensures that InstallFilters() can be used after + // MakeNewServer() without losing state on the client filters. + return; + } + records_.reset(new TlsRecordRecorder(agent)); + hello_.reset(new TlsHandshakeRecorder( + agent, std::set( + {kTlsHandshakeClientHello, kTlsHandshakeServerHello}))); + agent->SetFilter(std::make_shared( ChainedPacketFilterInit({records_, hello_}))); } std::shared_ptr records_; - std::shared_ptr hello_; + std::shared_ptr hello_; }; void CheckRecordsAreTls12(const std::string& agent, @@ -171,16 +178,20 @@ TEST_F(Tls13CompatTest, EnabledStatelessHrr) { server_->StartConnect(); client_->Handshake(); server_->Handshake(); + + // The server should send CCS before HRR. CheckForCCS(false, true); - // A new server should just work, but not send another CCS. + // A new server should complete the handshake, and not send CCS. MakeNewServer(); InstallFilters(); server_->ConfigNamedGroups({ssl_grp_ec_secp384r1}); Handshake(); CheckConnected(); - CheckForCompatHandshake(); + CheckRecordVersions(); + CheckHelloVersions(); + CheckForCCS(true, false); } TEST_F(Tls13CompatTest, EnabledHrrZeroRtt) { @@ -262,10 +273,8 @@ TEST_F(TlsConnectStreamTls13, ChangeCipherSpecBeforeClientHello12) { TEST_F(TlsConnectDatagram13, CompatModeDtlsClient) { EnsureTlsSetup(); client_->SetOption(SSL_ENABLE_TLS13_COMPAT_MODE, PR_TRUE); - auto client_records = std::make_shared(); - client_->SetPacketFilter(client_records); - auto server_records = std::make_shared(); - server_->SetPacketFilter(server_records); + auto client_records = MakeTlsFilter(client_); + auto server_records = MakeTlsFilter(server_); Connect(); ASSERT_EQ(2U, client_records->count()); // CH, Fin @@ -283,7 +292,8 @@ TEST_F(TlsConnectDatagram13, CompatModeDtlsClient) { class AddSessionIdFilter : public TlsHandshakeFilter { public: - AddSessionIdFilter() : TlsHandshakeFilter({ssl_hs_client_hello}) {} + AddSessionIdFilter(const std::shared_ptr& client) + : TlsHandshakeFilter(client, {ssl_hs_client_hello}) {} protected: PacketFilter::Action FilterHandshake(const HandshakeHeader& header, @@ -303,14 +313,14 @@ class AddSessionIdFilter : public TlsHandshakeFilter { // mode. It should be ignored instead. TEST_F(TlsConnectDatagram13, CompatModeDtlsServer) { EnsureTlsSetup(); - auto client_records = std::make_shared(); - client_->SetPacketFilter( + auto client_records = std::make_shared(client_); + client_->SetFilter( std::make_shared(ChainedPacketFilterInit( - {client_records, std::make_shared()}))); - auto server_hello = std::make_shared( - kTlsHandshakeServerHello); - auto server_records = std::make_shared(); - server_->SetPacketFilter(std::make_shared( + {client_records, std::make_shared(client_)}))); + auto server_hello = + std::make_shared(server_, kTlsHandshakeServerHello); + auto server_records = std::make_shared(server_); + server_->SetFilter(std::make_shared( ChainedPacketFilterInit({server_records, server_hello}))); StartConnect(); client_->Handshake(); @@ -334,4 +344,20 @@ TEST_F(TlsConnectDatagram13, CompatModeDtlsServer) { EXPECT_EQ(0U, session_id_len); } -} // nss_test +TEST_F(Tls13CompatTest, ConnectWith12ThenAttemptToResume13CompatMode) { + ConfigureSessionCache(RESUME_SESSIONID, RESUME_SESSIONID); + ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_2); + Connect(); + + Reset(); + ExpectResumption(RESUME_NONE); + version_ = SSL_LIBRARY_VERSION_TLS_1_3; + client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2, + SSL_LIBRARY_VERSION_TLS_1_3); + server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2, + SSL_LIBRARY_VERSION_TLS_1_3); + EnableCompatMode(); + Connect(); +} + +} // namespace nss_test diff --git a/security/nss/gtests/ssl_gtest/ssl_v2_client_hello_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_v2_client_hello_unittest.cc index 2f8ddd6fe..100595732 100644 --- a/security/nss/gtests/ssl_gtest/ssl_v2_client_hello_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_v2_client_hello_unittest.cc @@ -23,7 +23,8 @@ namespace nss_test { // Replaces the client hello with an SSLv2 version once. class SSLv2ClientHelloFilter : public PacketFilter { public: - SSLv2ClientHelloFilter(std::shared_ptr& client, uint16_t version) + SSLv2ClientHelloFilter(const std::shared_ptr& client, + uint16_t version) : replaced_(false), client_(client), version_(version), @@ -147,10 +148,9 @@ class SSLv2ClientHelloTestF : public TlsConnectTestBase { SSLv2ClientHelloTestF(SSLProtocolVariant variant, uint16_t version) : TlsConnectTestBase(variant, version), filter_(nullptr) {} - void SetUp() { + void SetUp() override { TlsConnectTestBase::SetUp(); - filter_ = std::make_shared(client_, version_); - client_->SetPacketFilter(filter_); + filter_ = MakeTlsFilter(client_, version_); } void SetExpectedVersion(uint16_t version) { diff --git a/security/nss/gtests/ssl_gtest/ssl_version_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_version_unittest.cc index 9db293b07..4e9099561 100644 --- a/security/nss/gtests/ssl_gtest/ssl_version_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_version_unittest.cc @@ -56,18 +56,15 @@ TEST_P(TlsConnectGeneric, ServerNegotiateTls12) { // two validate that we can also detect fallback using the // SSL_SetDowngradeCheckVersion() API. TEST_F(TlsConnectTest, TestDowngradeDetectionToTls11) { - client_->SetPacketFilter( - std::make_shared( - SSL_LIBRARY_VERSION_TLS_1_1)); + MakeTlsFilter(client_, + SSL_LIBRARY_VERSION_TLS_1_1); ConnectExpectFail(); ASSERT_EQ(SSL_ERROR_RX_MALFORMED_SERVER_HELLO, client_->error_code()); } /* Attempt to negotiate the bogus DTLS 1.1 version. */ TEST_F(DtlsConnectTest, TestDtlsVersion11) { - client_->SetPacketFilter( - std::make_shared( - ((~0x0101) & 0xffff))); + MakeTlsFilter(client_, ((~0x0101) & 0xffff)); ConnectExpectFail(); // It's kind of surprising that SSL_ERROR_NO_CYPHER_OVERLAP is // what is returned here, but this is deliberate in ssl3_HandleAlert(). @@ -78,9 +75,8 @@ TEST_F(DtlsConnectTest, TestDtlsVersion11) { // Disabled as long as we have draft version. TEST_F(TlsConnectTest, TestDowngradeDetectionToTls12) { EnsureTlsSetup(); - client_->SetPacketFilter( - std::make_shared( - SSL_LIBRARY_VERSION_TLS_1_2)); + MakeTlsFilter(client_, + SSL_LIBRARY_VERSION_TLS_1_2); client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2, SSL_LIBRARY_VERSION_TLS_1_3); server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2, @@ -92,9 +88,8 @@ TEST_F(TlsConnectTest, TestDowngradeDetectionToTls12) { // TLS 1.1 clients do not check the random values, so we should // instead get a handshake failure alert from the server. TEST_F(TlsConnectTest, TestDowngradeDetectionToTls10) { - client_->SetPacketFilter( - std::make_shared( - SSL_LIBRARY_VERSION_TLS_1_0)); + MakeTlsFilter(client_, + SSL_LIBRARY_VERSION_TLS_1_0); client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_0, SSL_LIBRARY_VERSION_TLS_1_1); server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_0, @@ -177,12 +172,10 @@ class Tls13NoSupportedVersions : public TlsConnectStreamTls12 { client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2, SSL_LIBRARY_VERSION_TLS_1_2); server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2, max_server_version); - client_->SetPacketFilter( - std::make_shared( - overwritten_client_version)); - auto capture = std::make_shared( - kTlsHandshakeServerHello); - server_->SetPacketFilter(capture); + MakeTlsFilter(client_, + overwritten_client_version); + auto capture = + MakeTlsFilter(server_, kTlsHandshakeServerHello); ConnectExpectAlert(server_, kTlsAlertDecryptError); client_->CheckErrorCode(SSL_ERROR_DECRYPT_ERROR_ALERT); server_->CheckErrorCode(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE); @@ -214,12 +207,10 @@ TEST_F(Tls13NoSupportedVersions, // Offer 1.3 but with ClientHello.legacy_version == TLS 1.4. This // causes a bad MAC error when we read EncryptedExtensions. TEST_F(TlsConnectStreamTls13, Tls14ClientHelloWithSupportedVersions) { - client_->SetPacketFilter( - std::make_shared( - SSL_LIBRARY_VERSION_TLS_1_3 + 1)); - auto capture = - std::make_shared(ssl_tls13_supported_versions_xtn); - server_->SetPacketFilter(capture); + MakeTlsFilter(client_, + SSL_LIBRARY_VERSION_TLS_1_3 + 1); + auto capture = MakeTlsFilter( + server_, ssl_tls13_supported_versions_xtn); client_->ExpectSendAlert(kTlsAlertBadRecordMac); server_->ExpectSendAlert(kTlsAlertBadRecordMac); ConnectExpectFail(); diff --git a/security/nss/gtests/ssl_gtest/ssl_versionpolicy_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_versionpolicy_unittest.cc index eda96831c..7f3c4a896 100644 --- a/security/nss/gtests/ssl_gtest/ssl_versionpolicy_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_versionpolicy_unittest.cc @@ -189,12 +189,12 @@ class TestPolicyVersionRange } } - void SetUp() { - SetPolicy(policy_.range()); + void SetUp() override { TlsConnectTestBase::SetUp(); + SetPolicy(policy_.range()); } - void TearDown() { + void TearDown() override { TlsConnectTestBase::TearDown(); saved_version_policy_.RestoreOriginalPolicy(); } diff --git a/security/nss/gtests/ssl_gtest/test_io.cc b/security/nss/gtests/ssl_gtest/test_io.cc index adcdbfbaf..728217851 100644 --- a/security/nss/gtests/ssl_gtest/test_io.cc +++ b/security/nss/gtests/ssl_gtest/test_io.cc @@ -25,10 +25,6 @@ namespace nss_test { if (g_ssl_gtest_verbose) LOG(a); \ } while (false) -void DummyPrSocket::SetPacketFilter(std::shared_ptr filter) { - filter_ = filter; -} - ScopedPRFileDesc DummyPrSocket::CreateFD() { static PRDescIdentity test_fd_identity = PR_GetUniqueIdentity("testtransportadapter"); diff --git a/security/nss/gtests/ssl_gtest/test_io.h b/security/nss/gtests/ssl_gtest/test_io.h index 469d90a7c..dbeb6b9d4 100644 --- a/security/nss/gtests/ssl_gtest/test_io.h +++ b/security/nss/gtests/ssl_gtest/test_io.h @@ -74,7 +74,9 @@ class DummyPrSocket : public DummyIOLayerMethods { std::weak_ptr& peer() { return peer_; } void SetPeer(const std::shared_ptr& peer) { peer_ = peer; } - void SetPacketFilter(std::shared_ptr filter); + void SetPacketFilter(const std::shared_ptr& filter) { + filter_ = filter; + } // Drops peer, packet filter and any outstanding packets. void Reset(); @@ -176,6 +178,6 @@ class Poller { timers_; }; -} // end of namespace +} // namespace nss_test #endif diff --git a/security/nss/gtests/ssl_gtest/tls_agent.cc b/security/nss/gtests/ssl_gtest/tls_agent.cc index 3b939bba8..2f71caedb 100644 --- a/security/nss/gtests/ssl_gtest/tls_agent.cc +++ b/security/nss/gtests/ssl_gtest/tls_agent.cc @@ -12,6 +12,7 @@ #include "sslerr.h" #include "sslexp.h" #include "sslproto.h" +#include "tls_filter.h" #include "tls_parser.h" extern "C" { @@ -66,6 +67,7 @@ TlsAgent::TlsAgent(const std::string& name, Role role, expected_sent_alert_(kTlsAlertCloseNotify), expected_sent_alert_level_(kTlsAlertWarning), handshake_callback_called_(false), + resumption_callback_called_(false), error_code_(0), send_ctr_(0), recv_ctr_(0), @@ -73,7 +75,8 @@ TlsAgent::TlsAgent(const std::string& name, Role role, handshake_callback_(), auth_certificate_callback_(), sni_callback_(), - skip_version_checks_(false) { + skip_version_checks_(false), + resumption_token_() { memset(&info_, 0, sizeof(info_)); memset(&csinfo_, 0, sizeof(csinfo_)); SECStatus rv = SSL_VersionRangeGetDefault(variant_, &vrange_); @@ -182,6 +185,10 @@ bool TlsAgent::EnsureTlsSetup(PRFileDesc* modelSocket) { ScopedCERTCertList anchors(CERT_NewCertList()); rv = SSL_SetTrustAnchors(ssl_fd(), anchors.get()); if (rv != SECSuccess) return false; + + rv = SSL_SetMaxEarlyDataSize(ssl_fd(), 1024); + EXPECT_EQ(SECSuccess, rv); + if (rv != SECSuccess) return false; } else { rv = SSL_SetURL(ssl_fd(), "server"); EXPECT_EQ(SECSuccess, rv); @@ -207,6 +214,29 @@ bool TlsAgent::EnsureTlsSetup(PRFileDesc* modelSocket) { return true; } +bool TlsAgent::MaybeSetResumptionToken() { + if (!resumption_token_.empty()) { + SECStatus rv = SSL_SetResumptionToken(ssl_fd(), resumption_token_.data(), + resumption_token_.size()); + + // rv is SECFailure with error set to SSL_ERROR_BAD_RESUMPTION_TOKEN_ERROR + // if the resumption token was bad (expired/malformed/etc.). + if (expect_resumption_) { + // Only in case we expect resumption this has to be successful. We might + // not expect resumption due to some reason but the token is totally fine. + EXPECT_EQ(SECSuccess, rv); + } + if (rv != SECSuccess) { + EXPECT_EQ(SSL_ERROR_BAD_RESUMPTION_TOKEN_ERROR, PORT_GetError()); + resumption_token_.clear(); + EXPECT_FALSE(expect_resumption_); + if (expect_resumption_) return false; + } + } + + return true; +} + void TlsAgent::SetupClientAuth() { EXPECT_TRUE(EnsureTlsSetup()); ASSERT_EQ(CLIENT, role_); @@ -386,6 +416,27 @@ void TlsAgent::SetVersionRange(uint16_t minver, uint16_t maxver) { } } +SECStatus ResumptionTokenCallback(PRFileDesc* fd, + const PRUint8* resumptionToken, + unsigned int len, void* ctx) { + EXPECT_NE(nullptr, resumptionToken); + if (!resumptionToken) { + return SECFailure; + } + + std::vector new_token(resumptionToken, resumptionToken + len); + reinterpret_cast(ctx)->SetResumptionToken(new_token); + reinterpret_cast(ctx)->SetResumptionCallbackCalled(); + return SECSuccess; +} + +void TlsAgent::SetResumptionTokenCallback() { + EXPECT_TRUE(EnsureTlsSetup()); + SECStatus rv = + SSL_SetResumptionTokenCallback(ssl_fd(), ResumptionTokenCallback, this); + EXPECT_EQ(SECSuccess, rv); +} + void TlsAgent::GetVersionRange(uint16_t* minver, uint16_t* maxver) { *minver = vrange_.min; *maxver = vrange_.max; diff --git a/security/nss/gtests/ssl_gtest/tls_agent.h b/security/nss/gtests/ssl_gtest/tls_agent.h index b3fd892ae..6cd6d5073 100644 --- a/security/nss/gtests/ssl_gtest/tls_agent.h +++ b/security/nss/gtests/ssl_gtest/tls_agent.h @@ -14,7 +14,6 @@ #include #include "test_io.h" -#include "tls_filter.h" #define GTEST_HAS_RTTI 0 #include "gtest/gtest.h" @@ -37,7 +36,10 @@ enum SessionResumptionMode { RESUME_BOTH = RESUME_SESSIONID | RESUME_TICKET }; +class PacketFilter; class TlsAgent; +class TlsCipherSpec; +struct TlsRecord; const extern std::vector kAllDHEGroups; const extern std::vector kECDHEGroups; @@ -80,18 +82,10 @@ class TlsAgent : public PollTarget { adapter_->SetPeer(peer->adapter_); } - // Set a filter that can access plaintext (TLS 1.3 only). - void SetTlsRecordFilter(std::shared_ptr filter) { - filter->SetAgent(this); + void SetFilter(std::shared_ptr filter) { adapter_->SetPacketFilter(filter); - filter->EnableDecryption(); } - - void SetPacketFilter(std::shared_ptr filter) { - adapter_->SetPacketFilter(filter); - } - - void DeletePacketFilter() { adapter_->SetPacketFilter(nullptr); } + void ClearFilter() { adapter_->SetPacketFilter(nullptr); } void StartConnect(PRFileDesc* model = nullptr); void CheckKEA(SSLKEAType kea_type, SSLNamedGroup group, @@ -165,6 +159,24 @@ class TlsAgent : public PollTarget { void DisableECDHEServerKeyReuse(); bool GetPeerChainLength(size_t* count); void CheckCipherSuite(uint16_t cipher_suite); + void SetResumptionTokenCallback(); + bool MaybeSetResumptionToken(); + void SetResumptionToken(const std::vector& resumption_token) { + resumption_token_ = resumption_token; + } + const std::vector& GetResumptionToken() const { + return resumption_token_; + } + void GetTokenInfo(ScopedSSLResumptionTokenInfo& token) { + SECStatus rv = SSL_GetResumptionTokenInfo( + resumption_token_.data(), resumption_token_.size(), token.get(), + sizeof(SSLResumptionTokenInfo)); + ASSERT_EQ(SECSuccess, rv); + } + void SetResumptionCallbackCalled() { resumption_callback_called_ = true; } + bool resumption_callback_called() const { + return resumption_callback_called_; + } const std::string& name() const { return name_; } @@ -382,6 +394,7 @@ class TlsAgent : public PollTarget { uint8_t expected_sent_alert_; uint8_t expected_sent_alert_level_; bool handshake_callback_called_; + bool resumption_callback_called_; SSLChannelInfo info_; SSLCipherSuiteInfo csinfo_; SSLVersionRange vrange_; @@ -393,6 +406,7 @@ class TlsAgent : public PollTarget { AuthCertificateCallbackFunction auth_certificate_callback_; SniCallbackFunction sni_callback_; bool skip_version_checks_; + std::vector resumption_token_; }; inline std::ostream& operator<<(std::ostream& stream, @@ -443,7 +457,7 @@ class TlsAgentTestBase : public ::testing::Test { void ProcessMessage(const DataBuffer& buffer, TlsAgent::State expected_state, int32_t error_code = 0); - std::unique_ptr agent_; + std::shared_ptr agent_; TlsAgent::Role role_; SSLProtocolVariant variant_; uint16_t version_; diff --git a/security/nss/gtests/ssl_gtest/tls_connect.cc b/security/nss/gtests/ssl_gtest/tls_connect.cc index 0af5123e9..8567b392f 100644 --- a/security/nss/gtests/ssl_gtest/tls_connect.cc +++ b/security/nss/gtests/ssl_gtest/tls_connect.cc @@ -197,7 +197,6 @@ void TlsConnectTestBase::SetUp() { SSL_ConfigServerSessionIDCache(1024, 0, 0, g_working_dir_path.c_str()); SSLInt_ClearSelfEncryptKey(); SSLInt_SetTicketLifetime(30); - SSLInt_SetMaxEarlyDataSize(1024); SSL_SetupAntiReplay(1 * PR_USEC_PER_SEC, 1, 3); ClearStats(); Init(); @@ -230,7 +229,9 @@ void TlsConnectTestBase::Reset() { void TlsConnectTestBase::Reset(const std::string& server_name, const std::string& client_name) { + auto token = client_->GetResumptionToken(); client_.reset(new TlsAgent(client_name, TlsAgent::CLIENT, variant_)); + client_->SetResumptionToken(token); server_.reset(new TlsAgent(server_name, TlsAgent::SERVER, variant_)); if (skip_version_checks_) { client_->SkipVersionChecks(); @@ -290,6 +291,7 @@ void TlsConnectTestBase::EnableExtendedMasterSecret() { void TlsConnectTestBase::Connect() { server_->StartConnect(server_model_ ? server_model_->ssl_fd() : nullptr); client_->StartConnect(client_model_ ? client_model_->ssl_fd() : nullptr); + client_->MaybeSetResumptionToken(); Handshake(); CheckConnected(); } @@ -402,13 +404,13 @@ void TlsConnectTestBase::CheckKeys(SSLKEAType kea_type, break; case ssl_auth_rsa_sign: if (version_ >= SSL_LIBRARY_VERSION_TLS_1_2) { - scheme = ssl_sig_rsa_pss_sha256; + scheme = ssl_sig_rsa_pss_rsae_sha256; } else { scheme = ssl_sig_rsa_pkcs1_sha256; } break; case ssl_auth_rsa_pss: - scheme = ssl_sig_rsa_pss_sha256; + scheme = ssl_sig_rsa_pss_rsae_sha256; break; case ssl_auth_ecdsa: scheme = ssl_sig_ecdsa_secp256r1_sha256; @@ -670,7 +672,8 @@ void TlsConnectTestBase::ZeroRttSendReceive( EXPECT_EQ(k0RttDataLen, rv); } else { EXPECT_EQ(SECFailure, rv); - EXPECT_EQ(PR_WOULD_BLOCK_ERROR, PORT_GetError()); + EXPECT_EQ(PR_WOULD_BLOCK_ERROR, PORT_GetError()) + << "Unexpected error: " << PORT_ErrorToName(PORT_GetError()); } // Do a second read. this should fail. @@ -754,20 +757,29 @@ TlsConnectTls12Plus::TlsConnectTls12Plus() TlsConnectTls13::TlsConnectTls13() : TlsConnectTestBase(GetParam(), SSL_LIBRARY_VERSION_TLS_1_3) {} +TlsConnectGenericResumption::TlsConnectGenericResumption() + : TlsConnectTestBase(std::get<0>(GetParam()), std::get<1>(GetParam())), + external_cache_(std::get<2>(GetParam())) {} + +TlsConnectTls13ResumptionToken::TlsConnectTls13ResumptionToken() + : TlsConnectTestBase(GetParam(), SSL_LIBRARY_VERSION_TLS_1_3) {} + +TlsConnectGenericResumptionToken::TlsConnectGenericResumptionToken() + : TlsConnectTestBase(std::get<0>(GetParam()), std::get<1>(GetParam())) {} + void TlsKeyExchangeTest::EnsureKeyShareSetup() { EnsureTlsSetup(); groups_capture_ = - std::make_shared(ssl_supported_groups_xtn); + std::make_shared(client_, ssl_supported_groups_xtn); shares_capture_ = - std::make_shared(ssl_tls13_key_share_xtn); - shares_capture2_ = - std::make_shared(ssl_tls13_key_share_xtn, true); + std::make_shared(client_, ssl_tls13_key_share_xtn); + shares_capture2_ = std::make_shared( + client_, ssl_tls13_key_share_xtn, true); std::vector> captures = { groups_capture_, shares_capture_, shares_capture2_}; - client_->SetPacketFilter(std::make_shared(captures)); - capture_hrr_ = std::make_shared( - kTlsHandshakeHelloRetryRequest); - server_->SetPacketFilter(capture_hrr_); + client_->SetFilter(std::make_shared(captures)); + capture_hrr_ = MakeTlsFilter( + server_, kTlsHandshakeHelloRetryRequest); } void TlsKeyExchangeTest::ConfigNamedGroups( diff --git a/security/nss/gtests/ssl_gtest/tls_connect.h b/security/nss/gtests/ssl_gtest/tls_connect.h index c650dda1d..7dffe7f8a 100644 --- a/security/nss/gtests/ssl_gtest/tls_connect.h +++ b/security/nss/gtests/ssl_gtest/tls_connect.h @@ -45,8 +45,8 @@ class TlsConnectTestBase : public ::testing::Test { TlsConnectTestBase(SSLProtocolVariant variant, uint16_t version); virtual ~TlsConnectTestBase(); - void SetUp(); - void TearDown(); + virtual void SetUp(); + virtual void TearDown(); // Initialize client and server. void Init(); @@ -55,7 +55,7 @@ class TlsConnectTestBase : public ::testing::Test { // Clear the server session cache. void ClearServerCache(); // Make sure TLS is configured for a connection. - void EnsureTlsSetup(); + virtual void EnsureTlsSetup(); // Reset and keep the same certificate names void Reset(); // Reset, and update the certificate names on both peers @@ -208,6 +208,52 @@ class TlsConnectGeneric : public TlsConnectTestBase, TlsConnectGeneric(); }; +class TlsConnectGenericResumption + : public TlsConnectTestBase, + public ::testing::WithParamInterface< + std::tuple> { + private: + bool external_cache_; + + public: + TlsConnectGenericResumption(); + + virtual void EnsureTlsSetup() { + TlsConnectTestBase::EnsureTlsSetup(); + // Enable external resumption token cache. + if (external_cache_) { + client_->SetResumptionTokenCallback(); + } + } + + bool use_external_cache() const { return external_cache_; } +}; + +class TlsConnectTls13ResumptionToken + : public TlsConnectTestBase, + public ::testing::WithParamInterface { + public: + TlsConnectTls13ResumptionToken(); + + virtual void EnsureTlsSetup() { + TlsConnectTestBase::EnsureTlsSetup(); + client_->SetResumptionTokenCallback(); + } +}; + +class TlsConnectGenericResumptionToken + : public TlsConnectTestBase, + public ::testing::WithParamInterface< + std::tuple> { + public: + TlsConnectGenericResumptionToken(); + + virtual void EnsureTlsSetup() { + TlsConnectTestBase::EnsureTlsSetup(); + client_->SetResumptionTokenCallback(); + } +}; + // A Pre TLS 1.2 generic test. class TlsConnectPre12 : public TlsConnectTestBase, public ::testing::WithParamInterface< @@ -273,7 +319,7 @@ class TlsKeyExchangeTest : public TlsConnectGeneric { std::shared_ptr groups_capture_; std::shared_ptr shares_capture_; std::shared_ptr shares_capture2_; - std::shared_ptr capture_hrr_; + std::shared_ptr capture_hrr_; void EnsureKeyShareSetup(); void ConfigNamedGroups(const std::vector& groups); diff --git a/security/nss/gtests/ssl_gtest/tls_filter.cc b/security/nss/gtests/ssl_gtest/tls_filter.cc index 89f201295..d34b13bcb 100644 --- a/security/nss/gtests/ssl_gtest/tls_filter.cc +++ b/security/nss/gtests/ssl_gtest/tls_filter.cc @@ -452,7 +452,7 @@ size_t TlsHandshakeFilter::HandshakeHeader::Write( return offset; } -PacketFilter::Action TlsInspectorRecordHandshakeMessage::FilterHandshake( +PacketFilter::Action TlsHandshakeRecorder::FilterHandshake( const HandshakeHeader& header, const DataBuffer& input, DataBuffer* output) { // Only do this once. @@ -763,7 +763,7 @@ PacketFilter::Action AfterRecordN::FilterRecord(const TlsRecordHeader& header, if (counter_++ == record_) { DataBuffer buf; header.Write(&buf, 0, body); - src_.lock()->SendDirect(buf); + agent()->SendDirect(buf); dest_.lock()->Handshake(); func_(); return DROP; @@ -772,7 +772,7 @@ PacketFilter::Action AfterRecordN::FilterRecord(const TlsRecordHeader& header, return KEEP; } -PacketFilter::Action TlsInspectorClientHelloVersionChanger::FilterHandshake( +PacketFilter::Action TlsClientHelloVersionChanger::FilterHandshake( const HandshakeHeader& header, const DataBuffer& input, DataBuffer* output) { EXPECT_EQ(SECSuccess, @@ -808,7 +808,7 @@ PacketFilter::Action SelectiveRecordDropFilter::FilterRecord( return pattern; } -PacketFilter::Action TlsInspectorClientHelloVersionSetter::FilterHandshake( +PacketFilter::Action TlsClientHelloVersionSetter::FilterHandshake( const HandshakeHeader& header, const DataBuffer& input, DataBuffer* output) { *output = input; diff --git a/security/nss/gtests/ssl_gtest/tls_filter.h b/security/nss/gtests/ssl_gtest/tls_filter.h index 1db3b90f6..1bbe190ab 100644 --- a/security/nss/gtests/ssl_gtest/tls_filter.h +++ b/security/nss/gtests/ssl_gtest/tls_filter.h @@ -13,6 +13,7 @@ #include #include "test_io.h" +#include "tls_agent.h" #include "tls_parser.h" #include "tls_protect.h" @@ -23,7 +24,6 @@ extern "C" { namespace nss_test { class TlsCipherSpec; -class TlsAgent; class TlsVersioned { public: @@ -71,19 +71,27 @@ struct TlsRecord { const DataBuffer buffer; }; +// Make a filter and install it on a TlsAgent. +template +inline std::shared_ptr MakeTlsFilter(const std::shared_ptr& agent, + Args&&... args) { + auto filter = std::make_shared(agent, std::forward(args)...); + agent->SetFilter(filter); + return filter; +} + // Abstract filter that operates on entire (D)TLS records. class TlsRecordFilter : public PacketFilter { public: - TlsRecordFilter() - : agent_(nullptr), + TlsRecordFilter(const std::shared_ptr& agent) + : agent_(agent), count_(0), cipher_spec_(), dropped_record_(false), in_sequence_number_(0), out_sequence_number_(0) {} - void SetAgent(const TlsAgent* agent) { agent_ = agent; } - const TlsAgent* agent() const { return agent_; } + std::shared_ptr agent() const { return agent_.lock(); } // External interface. Overrides PacketFilter. PacketFilter::Action Filter(const DataBuffer& input, DataBuffer* output); @@ -126,7 +134,7 @@ class TlsRecordFilter : public PacketFilter { static void CipherSpecChanged(void* arg, PRBool sending, ssl3CipherSpec* newSpec); - const TlsAgent* agent_; + std::weak_ptr agent_; size_t count_; std::unique_ptr cipher_spec_; // Whether we dropped a record since the cipher spec changed. @@ -175,9 +183,13 @@ inline std::ostream& operator<<(std::ostream& stream, // records and that they don't span records or anything crazy like that. class TlsHandshakeFilter : public TlsRecordFilter { public: - TlsHandshakeFilter() : handshake_types_(), preceding_fragment_() {} - TlsHandshakeFilter(const std::set& types) - : handshake_types_(types), preceding_fragment_() {} + TlsHandshakeFilter(const std::shared_ptr& agent) + : TlsRecordFilter(agent), handshake_types_(), preceding_fragment_() {} + TlsHandshakeFilter(const std::shared_ptr& agent, + const std::set& types) + : TlsRecordFilter(agent), + handshake_types_(types), + preceding_fragment_() {} // This filter can be set to be selective based on handshake message type. If // this function isn't used (or the set is empty), then all handshake messages @@ -229,12 +241,14 @@ class TlsHandshakeFilter : public TlsRecordFilter { }; // Make a copy of the first instance of a handshake message. -class TlsInspectorRecordHandshakeMessage : public TlsHandshakeFilter { +class TlsHandshakeRecorder : public TlsHandshakeFilter { public: - TlsInspectorRecordHandshakeMessage(uint8_t handshake_type) - : TlsHandshakeFilter({handshake_type}), buffer_() {} - TlsInspectorRecordHandshakeMessage(const std::set& handshake_types) - : TlsHandshakeFilter(handshake_types), buffer_() {} + TlsHandshakeRecorder(const std::shared_ptr& agent, + uint8_t handshake_type) + : TlsHandshakeFilter(agent, {handshake_type}), buffer_() {} + TlsHandshakeRecorder(const std::shared_ptr& agent, + const std::set& handshake_types) + : TlsHandshakeFilter(agent, handshake_types), buffer_() {} virtual PacketFilter::Action FilterHandshake(const HandshakeHeader& header, const DataBuffer& input, @@ -251,9 +265,10 @@ class TlsInspectorRecordHandshakeMessage : public TlsHandshakeFilter { // Replace all instances of a handshake message. class TlsInspectorReplaceHandshakeMessage : public TlsHandshakeFilter { public: - TlsInspectorReplaceHandshakeMessage(uint8_t handshake_type, + TlsInspectorReplaceHandshakeMessage(const std::shared_ptr& agent, + uint8_t handshake_type, const DataBuffer& replacement) - : TlsHandshakeFilter({handshake_type}), buffer_(replacement) {} + : TlsHandshakeFilter(agent, {handshake_type}), buffer_(replacement) {} virtual PacketFilter::Action FilterHandshake(const HandshakeHeader& header, const DataBuffer& input, @@ -266,9 +281,11 @@ class TlsInspectorReplaceHandshakeMessage : public TlsHandshakeFilter { // Make a copy of each record of a given type. class TlsRecordRecorder : public TlsRecordFilter { public: - TlsRecordRecorder(uint8_t ct) : filter_(true), ct_(ct), records_() {} - TlsRecordRecorder() - : filter_(false), + TlsRecordRecorder(const std::shared_ptr& agent, uint8_t ct) + : TlsRecordFilter(agent), filter_(true), ct_(ct), records_() {} + TlsRecordRecorder(const std::shared_ptr& agent) + : TlsRecordFilter(agent), + filter_(false), ct_(content_handshake), // dummy ( is C++14) records_() {} virtual PacketFilter::Action FilterRecord(const TlsRecordHeader& header, @@ -289,7 +306,9 @@ class TlsRecordRecorder : public TlsRecordFilter { // Make a copy of the complete conversation. class TlsConversationRecorder : public TlsRecordFilter { public: - TlsConversationRecorder(DataBuffer& buffer) : buffer_(buffer) {} + TlsConversationRecorder(const std::shared_ptr& agent, + DataBuffer& buffer) + : TlsRecordFilter(agent), buffer_(buffer) {} virtual PacketFilter::Action FilterRecord(const TlsRecordHeader& header, const DataBuffer& input, @@ -302,6 +321,8 @@ class TlsConversationRecorder : public TlsRecordFilter { // Make a copy of the records class TlsHeaderRecorder : public TlsRecordFilter { public: + TlsHeaderRecorder(const std::shared_ptr& agent) + : TlsRecordFilter(agent) {} virtual PacketFilter::Action FilterRecord(const TlsRecordHeader& header, const DataBuffer& input, DataBuffer* output); @@ -338,13 +359,15 @@ typedef std::function class TlsExtensionFilter : public TlsHandshakeFilter { public: - TlsExtensionFilter() - : TlsHandshakeFilter({kTlsHandshakeClientHello, kTlsHandshakeServerHello, + TlsExtensionFilter(const std::shared_ptr& agent) + : TlsHandshakeFilter(agent, + {kTlsHandshakeClientHello, kTlsHandshakeServerHello, kTlsHandshakeHelloRetryRequest, kTlsHandshakeEncryptedExtensions}) {} - TlsExtensionFilter(const std::set& types) - : TlsHandshakeFilter(types) {} + TlsExtensionFilter(const std::shared_ptr& agent, + const std::set& types) + : TlsHandshakeFilter(agent, types) {} static bool FindExtensions(TlsParser* parser, const HandshakeHeader& header); @@ -365,8 +388,13 @@ class TlsExtensionFilter : public TlsHandshakeFilter { class TlsExtensionCapture : public TlsExtensionFilter { public: - TlsExtensionCapture(uint16_t ext, bool last = false) - : extension_(ext), captured_(false), last_(last), data_() {} + TlsExtensionCapture(const std::shared_ptr& agent, uint16_t ext, + bool last = false) + : TlsExtensionFilter(agent), + extension_(ext), + captured_(false), + last_(last), + data_() {} const DataBuffer& extension() const { return data_; } bool captured() const { return captured_; } @@ -385,8 +413,9 @@ class TlsExtensionCapture : public TlsExtensionFilter { class TlsExtensionReplacer : public TlsExtensionFilter { public: - TlsExtensionReplacer(uint16_t extension, const DataBuffer& data) - : extension_(extension), data_(data) {} + TlsExtensionReplacer(const std::shared_ptr& agent, + uint16_t extension, const DataBuffer& data) + : TlsExtensionFilter(agent), extension_(extension), data_(data) {} PacketFilter::Action FilterExtension(uint16_t extension_type, const DataBuffer& input, DataBuffer* output) override; @@ -398,7 +427,9 @@ class TlsExtensionReplacer : public TlsExtensionFilter { class TlsExtensionDropper : public TlsExtensionFilter { public: - TlsExtensionDropper(uint16_t extension) : extension_(extension) {} + TlsExtensionDropper(const std::shared_ptr& agent, + uint16_t extension) + : TlsExtensionFilter(agent), extension_(extension) {} PacketFilter::Action FilterExtension(uint16_t extension_type, const DataBuffer&, DataBuffer*) override; @@ -408,8 +439,9 @@ class TlsExtensionDropper : public TlsExtensionFilter { class TlsExtensionInjector : public TlsHandshakeFilter { public: - TlsExtensionInjector(uint16_t ext, const DataBuffer& data) - : extension_(ext), data_(data) {} + TlsExtensionInjector(const std::shared_ptr& agent, uint16_t ext, + const DataBuffer& data) + : TlsHandshakeFilter(agent), extension_(ext), data_(data) {} protected: PacketFilter::Action FilterHandshake(const HandshakeHeader& header, @@ -426,16 +458,20 @@ typedef std::function VoidFunction; class AfterRecordN : public TlsRecordFilter { public: - AfterRecordN(std::shared_ptr& src, std::shared_ptr& dest, - unsigned int record, VoidFunction func) - : src_(src), dest_(dest), record_(record), func_(func), counter_(0) {} + AfterRecordN(const std::shared_ptr& src, + const std::shared_ptr& dest, unsigned int record, + VoidFunction func) + : TlsRecordFilter(src), + dest_(dest), + record_(record), + func_(func), + counter_(0) {} virtual PacketFilter::Action FilterRecord(const TlsRecordHeader& header, const DataBuffer& body, DataBuffer* out) override; private: - std::weak_ptr src_; std::weak_ptr dest_; unsigned int record_; VoidFunction func_; @@ -444,10 +480,12 @@ class AfterRecordN : public TlsRecordFilter { // When we see the ClientKeyExchange from |client|, increment the // ClientHelloVersion on |server|. -class TlsInspectorClientHelloVersionChanger : public TlsHandshakeFilter { +class TlsClientHelloVersionChanger : public TlsHandshakeFilter { public: - TlsInspectorClientHelloVersionChanger(std::shared_ptr& server) - : TlsHandshakeFilter({kTlsHandshakeClientKeyExchange}), server_(server) {} + TlsClientHelloVersionChanger(const std::shared_ptr& client, + const std::shared_ptr& server) + : TlsHandshakeFilter(client, {kTlsHandshakeClientKeyExchange}), + server_(server) {} virtual PacketFilter::Action FilterHandshake(const HandshakeHeader& header, const DataBuffer& input, @@ -477,14 +515,16 @@ class SelectiveDropFilter : public PacketFilter { // datagram, we just drop one. class SelectiveRecordDropFilter : public TlsRecordFilter { public: - SelectiveRecordDropFilter(uint32_t pattern, bool enabled = true) - : pattern_(pattern), counter_(0) { + SelectiveRecordDropFilter(const std::shared_ptr& agent, + uint32_t pattern, bool enabled = true) + : TlsRecordFilter(agent), pattern_(pattern), counter_(0) { if (!enabled) { Disable(); } } - SelectiveRecordDropFilter(std::initializer_list records) - : SelectiveRecordDropFilter(ToPattern(records), true) {} + SelectiveRecordDropFilter(const std::shared_ptr& agent, + std::initializer_list records) + : SelectiveRecordDropFilter(agent, ToPattern(records), true) {} void Reset(uint32_t pattern) { counter_ = 0; @@ -509,10 +549,12 @@ class SelectiveRecordDropFilter : public TlsRecordFilter { }; // Set the version number in the ClientHello. -class TlsInspectorClientHelloVersionSetter : public TlsHandshakeFilter { +class TlsClientHelloVersionSetter : public TlsHandshakeFilter { public: - TlsInspectorClientHelloVersionSetter(uint16_t version) - : TlsHandshakeFilter({kTlsHandshakeClientHello}), version_(version) {} + TlsClientHelloVersionSetter(const std::shared_ptr& agent, + uint16_t version) + : TlsHandshakeFilter(agent, {kTlsHandshakeClientHello}), + version_(version) {} virtual PacketFilter::Action FilterHandshake(const HandshakeHeader& header, const DataBuffer& input, @@ -525,7 +567,8 @@ class TlsInspectorClientHelloVersionSetter : public TlsHandshakeFilter { // Damages the last byte of a handshake message. class TlsLastByteDamager : public TlsHandshakeFilter { public: - TlsLastByteDamager(uint8_t type) : type_(type) {} + TlsLastByteDamager(const std::shared_ptr& agent, uint8_t type) + : TlsHandshakeFilter(agent), type_(type) {} PacketFilter::Action FilterHandshake( const TlsHandshakeFilter::HandshakeHeader& header, const DataBuffer& input, DataBuffer* output) override { @@ -545,8 +588,10 @@ class TlsLastByteDamager : public TlsHandshakeFilter { class SelectedCipherSuiteReplacer : public TlsHandshakeFilter { public: - SelectedCipherSuiteReplacer(uint16_t suite) - : TlsHandshakeFilter({kTlsHandshakeServerHello}), cipher_suite_(suite) {} + SelectedCipherSuiteReplacer(const std::shared_ptr& agent, + uint16_t suite) + : TlsHandshakeFilter(agent, {kTlsHandshakeServerHello}), + cipher_suite_(suite) {} protected: PacketFilter::Action FilterHandshake(const HandshakeHeader& header, diff --git a/security/nss/help.txt b/security/nss/help.txt index 03ed36e6c..b4ffc0382 100644 --- a/security/nss/help.txt +++ b/security/nss/help.txt @@ -37,6 +37,8 @@ NSS build tool options: --msan do an msan build --sancov do sanitize coverage builds --sancov=func sets coverage to function level for example + --emit-llvm emit LLVM bitcode while building + (requires the gold linker, use clang-3.8 for SAW) --disable-tests don't build tests and corresponding cmdline utils --system-sqlite use system sqlite --no-zdefs don't set -Wl,-z,defs diff --git a/security/nss/lib/certdb/stanpcertdb.c b/security/nss/lib/certdb/stanpcertdb.c index beaa66040..d5d19c39d 100644 --- a/security/nss/lib/certdb/stanpcertdb.c +++ b/security/nss/lib/certdb/stanpcertdb.c @@ -30,6 +30,7 @@ #include "pkistore.h" #include "dev3hack.h" #include "dev.h" +#include "secmodi.h" PRBool SEC_CertNicknameConflict(const char *nickname, const SECItem *derSubject, @@ -280,6 +281,18 @@ __CERT_AddTempCertToPerm(CERTCertificate *cert, char *nickname, nssCertificateStore_RemoveCertLOCKED(context->certStore, c); nssCertificateStore_Unlock(context->certStore, &lockTrace, &unlockTrace); c->object.cryptoContext = NULL; + + /* if the id has not been set explicitly yet, create one from the public + * key. */ + if (c->id.data == NULL) { + SECItem *keyID = pk11_mkcertKeyID(cert); + if (keyID) { + nssItem_Create(c->object.arena, &c->id, keyID->len, keyID->data); + SECITEM_FreeItem(keyID, PR_TRUE); + } + /* if any of these failed, continue with our null c->id */ + } + /* Import the perm instance onto the internal token */ slot = PK11_GetInternalKeySlot(); internal = PK11Slot_GetNSSToken(slot); @@ -343,7 +356,7 @@ CERT_NewTempCertificate(CERTCertDBHandle *handle, SECItem *derCert, /* First, see if it is already a temp cert */ c = NSSCryptoContext_FindCertificateByEncodedCertificate(gCC, &encoding); - if (!c) { + if (!c && handle) { /* Then, see if it is already a perm cert */ c = NSSTrustDomain_FindCertificateByEncodedCertificate(handle, &encoding); diff --git a/security/nss/lib/dev/devslot.c b/security/nss/lib/dev/devslot.c index 9f0bd8226..ebd6e6aa5 100644 --- a/security/nss/lib/dev/devslot.c +++ b/security/nss/lib/dev/devslot.c @@ -33,6 +33,8 @@ nssSlot_Destroy( if (PR_ATOMIC_DECREMENT(&slot->base.refCount) == 0) { PK11_FreeSlot(slot->pk11slot); PZ_DestroyLock(slot->base.lock); + PZ_DestroyCondVar(slot->isPresentCondition); + PZ_DestroyLock(slot->isPresentLock); return nssArena_Destroy(slot->base.arena); } } @@ -88,20 +90,28 @@ NSS_IMPLEMENT void nssSlot_ResetDelay( NSSSlot *slot) { - slot->lastTokenPing = 0; + PZ_Lock(slot->isPresentLock); + slot->lastTokenPingState = nssSlotLastPingState_Reset; + PZ_Unlock(slot->isPresentLock); } static PRBool -within_token_delay_period(const NSSSlot *slot) +token_status_checked(const NSSSlot *slot) { - PRIntervalTime time, lastTime; + PRIntervalTime time; + int lastPingState = slot->lastTokenPingState; + /* When called from the same thread, that means + * nssSlot_IsTokenPresent() is called recursively through + * nssSlot_Refresh(). Return immediately in that case. */ + if (slot->isPresentThread == PR_GetCurrentThread()) { + return PR_TRUE; + } /* Set the delay time for checking the token presence */ if (s_token_delay_time == 0) { s_token_delay_time = PR_SecondsToInterval(NSSSLOT_TOKEN_DELAY_TIME); } time = PR_IntervalNow(); - lastTime = slot->lastTokenPing; - if ((lastTime) && ((time - lastTime) < s_token_delay_time)) { + if ((lastPingState == nssSlotLastPingState_Valid) && ((time - slot->lastTokenPingTime) < s_token_delay_time)) { return PR_TRUE; } return PR_FALSE; @@ -117,35 +127,63 @@ nssSlot_IsTokenPresent( nssSession *session; CK_SLOT_INFO slotInfo; void *epv; + PRBool isPresent = PR_FALSE; + /* permanent slots are always present unless they're disabled */ if (nssSlot_IsPermanent(slot)) { return !PK11_IsDisabled(slot->pk11slot); } + /* avoid repeated calls to check token status within set interval */ - if (within_token_delay_period(slot)) { - return ((slot->ckFlags & CKF_TOKEN_PRESENT) != 0); + PZ_Lock(slot->isPresentLock); + if (token_status_checked(slot)) { + CK_FLAGS ckFlags = slot->ckFlags; + PZ_Unlock(slot->isPresentLock); + return ((ckFlags & CKF_TOKEN_PRESENT) != 0); } + PZ_Unlock(slot->isPresentLock); - /* First obtain the slot info */ + /* First obtain the slot epv before we set up the condition + * variable, so we can just return if we couldn't get it. */ epv = slot->epv; if (!epv) { return PR_FALSE; } + + /* set up condition so only one thread is active in this part of the code at a time */ + PZ_Lock(slot->isPresentLock); + while (slot->isPresentThread) { + PR_WaitCondVar(slot->isPresentCondition, PR_INTERVAL_NO_TIMEOUT); + } + /* if we were one of multiple threads here, the first thread will have + * given us the answer, no need to make more queries of the token. */ + if (token_status_checked(slot)) { + CK_FLAGS ckFlags = slot->ckFlags; + PZ_Unlock(slot->isPresentLock); + return ((ckFlags & CKF_TOKEN_PRESENT) != 0); + } + /* this is the winning thread, block all others until we've determined + * if the token is present and that it needs initialization. */ + slot->lastTokenPingState = nssSlotLastPingState_Update; + slot->isPresentThread = PR_GetCurrentThread(); + + PZ_Unlock(slot->isPresentLock); + nssSlot_EnterMonitor(slot); ckrv = CKAPI(epv)->C_GetSlotInfo(slot->slotID, &slotInfo); nssSlot_ExitMonitor(slot); if (ckrv != CKR_OK) { slot->token->base.name[0] = 0; /* XXX */ - slot->lastTokenPing = PR_IntervalNow(); - return PR_FALSE; + isPresent = PR_FALSE; + goto done; } slot->ckFlags = slotInfo.flags; /* check for the presence of the token */ if ((slot->ckFlags & CKF_TOKEN_PRESENT) == 0) { if (!slot->token) { /* token was never present */ - slot->lastTokenPing = PR_IntervalNow(); - return PR_FALSE; + isPresent = PR_FALSE; + goto done; } session = nssToken_GetDefaultSession(slot->token); if (session) { @@ -167,15 +205,15 @@ nssSlot_IsTokenPresent( slot->token->base.name[0] = 0; /* XXX */ /* clear the token cache */ nssToken_Remove(slot->token); - slot->lastTokenPing = PR_IntervalNow(); - return PR_FALSE; + isPresent = PR_FALSE; + goto done; } /* token is present, use the session info to determine if the card * has been removed and reinserted. */ session = nssToken_GetDefaultSession(slot->token); if (session) { - PRBool isPresent = PR_FALSE; + PRBool tokenRemoved; nssSession_EnterMonitor(session); if (session->handle != CK_INVALID_SESSION) { CK_SESSION_INFO sessionInfo; @@ -187,12 +225,12 @@ nssSlot_IsTokenPresent( session->handle = CK_INVALID_SESSION; } } - isPresent = session->handle != CK_INVALID_SESSION; + tokenRemoved = (session->handle == CK_INVALID_SESSION); nssSession_ExitMonitor(session); /* token not removed, finished */ - if (isPresent) { - slot->lastTokenPing = PR_IntervalNow(); - return PR_TRUE; + if (!tokenRemoved) { + isPresent = PR_TRUE; + goto done; } } /* the token has been removed, and reinserted, or the slot contains @@ -203,15 +241,32 @@ nssSlot_IsTokenPresent( nssToken_Remove(slot->token); /* token has been removed, need to refresh with new session */ nssrv = nssSlot_Refresh(slot); + isPresent = PR_TRUE; if (nssrv != PR_SUCCESS) { slot->token->base.name[0] = 0; /* XXX */ slot->ckFlags &= ~CKF_TOKEN_PRESENT; - /* TODO: insert a barrier here to avoid reordering of the assingments */ - slot->lastTokenPing = PR_IntervalNow(); - return PR_FALSE; + isPresent = PR_FALSE; + } +done: + /* Once we've set up the condition variable, + * Before returning, it's necessary to: + * 1) Set the lastTokenPingTime so that any other threads waiting on this + * initialization and any future calls within the initialization window + * return the just-computed status. + * 2) Indicate we're complete, waking up all other threads that may still + * be waiting on initialization can progress. + */ + PZ_Lock(slot->isPresentLock); + /* don't update the time if we were reset while we were + * getting the token state */ + if (slot->lastTokenPingState == nssSlotLastPingState_Update) { + slot->lastTokenPingTime = PR_IntervalNow(); + slot->lastTokenPingState = nssSlotLastPingState_Valid; } - slot->lastTokenPing = PR_IntervalNow(); - return PR_TRUE; + slot->isPresentThread = NULL; + PR_NotifyAllCondVar(slot->isPresentCondition); + PZ_Unlock(slot->isPresentLock); + return isPresent; } NSS_IMPLEMENT void * @@ -229,7 +284,7 @@ nssSlot_GetToken( if (nssSlot_IsTokenPresent(slot)) { /* Even if a token should be present, check `slot->token` too as it - * might be gone already. This would happen mostly on shutdown. */ + * might be gone already. This would happen mostly on shutdown. */ nssSlot_EnterMonitor(slot); if (slot->token) rvToken = nssToken_AddRef(slot->token); diff --git a/security/nss/lib/dev/devt.h b/security/nss/lib/dev/devt.h index db93deb12..0f6d9e49a 100644 --- a/security/nss/lib/dev/devt.h +++ b/security/nss/lib/dev/devt.h @@ -70,6 +70,14 @@ struct nssSlotAuthInfoStr { PRIntervalTime askPasswordTimeout; }; +/* values for lastTokenPingState */ +typedef enum { + nssSlotLastPingState_Reset = 0, /* the state has just been reset, discard + * our cache */ + nssSlotLastPingState_Update = 1, /* we are updating the lastTokenPingTime */ + nssSlotLastPingState_Valid = 2, /* lastTokenPingTime is valid */ +} nssSlotLastPingState; + struct NSSSlotStr { struct nssDeviceBaseStr base; NSSModule *module; /* Parent */ @@ -77,10 +85,14 @@ struct NSSSlotStr { CK_SLOT_ID slotID; CK_FLAGS ckFlags; /* from CK_SLOT_INFO.flags */ struct nssSlotAuthInfoStr authInfo; - PRIntervalTime lastTokenPing; + PRIntervalTime lastTokenPingTime; + nssSlotLastPingState lastTokenPingState; PZLock *lock; void *epv; PK11SlotInfo *pk11slot; + PZLock *isPresentLock; + PRCondVar *isPresentCondition; + PRThread *isPresentThread; }; struct nssSessionStr { diff --git a/security/nss/lib/dev/devutil.c b/security/nss/lib/dev/devutil.c index 42ce03c97..74c32f088 100644 --- a/security/nss/lib/dev/devutil.c +++ b/security/nss/lib/dev/devutil.c @@ -32,7 +32,7 @@ nssCryptokiObject_Create( /* a failure here indicates a device error */ return (nssCryptokiObject *)NULL; } - if (cert_template[0].ulValueLen == 0) { + if (cert_template[0].ulValueLen == 0 || !cert_template[0].pValue) { nss_ZFreeIf(cert_template[1].pValue); return (nssCryptokiObject *)NULL; } diff --git a/security/nss/lib/freebl/Makefile b/security/nss/lib/freebl/Makefile index 0b3daa275..a4b1a86ae 100644 --- a/security/nss/lib/freebl/Makefile +++ b/security/nss/lib/freebl/Makefile @@ -519,18 +519,16 @@ ifndef NSS_DISABLE_CHACHAPOLY else EXTRA_SRCS += poly1305.c endif - - ifneq (1,$(CC_IS_GCC)) - EXTRA_SRCS += chacha20.c - VERIFIED_SRCS += Hacl_Chacha20.c + else + ifeq ($(CPU_ARCH),aarch64) + EXTRA_SRCS += Hacl_Poly1305_64.c else - EXTRA_SRCS += chacha20_vec.c + EXTRA_SRCS += poly1305.c endif - else - EXTRA_SRCS += poly1305.c - EXTRA_SRCS += chacha20.c - VERIFIED_SRCS += Hacl_Chacha20.c endif # x86_64 + + VERIFIED_SRCS += Hacl_Chacha20.c + VERIFIED_SRCS += Hacl_Chacha20_Vec128.c endif # NSS_DISABLE_CHACHAPOLY ifeq (,$(filter-out i386 x386 x86 x86_64 aarch64,$(CPU_ARCH))) diff --git a/security/nss/lib/freebl/blapii.h b/security/nss/lib/freebl/blapii.h index bcf62e9f3..743a1168b 100644 --- a/security/nss/lib/freebl/blapii.h +++ b/security/nss/lib/freebl/blapii.h @@ -80,5 +80,11 @@ SECStatus generate_prime(mp_int *prime, int primeLen); PRBool aesni_support(); PRBool clmul_support(); PRBool avx_support(); +PRBool ssse3_support(); +PRBool arm_neon_support(); +PRBool arm_aes_support(); +PRBool arm_pmull_support(); +PRBool arm_sha1_support(); +PRBool arm_sha2_support(); #endif /* _BLAPII_H_ */ diff --git a/security/nss/lib/freebl/blinit.c b/security/nss/lib/freebl/blinit.c index d7f2ec53a..f369e62e7 100644 --- a/security/nss/lib/freebl/blinit.c +++ b/security/nss/lib/freebl/blinit.c @@ -23,6 +23,12 @@ static PRCallOnceType coFreeblInit; static PRBool aesni_support_ = PR_FALSE; static PRBool clmul_support_ = PR_FALSE; static PRBool avx_support_ = PR_FALSE; +static PRBool ssse3_support_ = PR_FALSE; +static PRBool arm_neon_support_ = PR_FALSE; +static PRBool arm_aes_support_ = PR_FALSE; +static PRBool arm_sha1_support_ = PR_FALSE; +static PRBool arm_sha2_support_ = PR_FALSE; +static PRBool arm_pmull_support_ = PR_FALSE; #ifdef NSS_X86_OR_X64 /* @@ -62,6 +68,7 @@ check_xcr0_ymm() #define ECX_XSAVE (1 << 26) #define ECX_OSXSAVE (1 << 27) #define ECX_AVX (1 << 28) +#define ECX_SSSE3 (1 << 9) #define AVX_BITS (ECX_XSAVE | ECX_OSXSAVE | ECX_AVX) void @@ -71,6 +78,7 @@ CheckX86CPUSupport() char *disable_hw_aes = PR_GetEnvSecure("NSS_DISABLE_HW_AES"); char *disable_pclmul = PR_GetEnvSecure("NSS_DISABLE_PCLMUL"); char *disable_avx = PR_GetEnvSecure("NSS_DISABLE_AVX"); + char *disable_ssse3 = PR_GetEnvSecure("NSS_DISABLE_SSSE3"); freebl_cpuid(1, &eax, &ebx, &ecx, &edx); aesni_support_ = (PRBool)((ecx & ECX_AESNI) != 0 && disable_hw_aes == NULL); clmul_support_ = (PRBool)((ecx & ECX_CLMUL) != 0 && disable_pclmul == NULL); @@ -78,9 +86,131 @@ CheckX86CPUSupport() * as well as XMM and YMM state. */ avx_support_ = (PRBool)((ecx & AVX_BITS) == AVX_BITS) && check_xcr0_ymm() && disable_avx == NULL; + ssse3_support_ = (PRBool)((ecx & ECX_SSSE3) != 0 && + disable_ssse3 == NULL); } #endif /* NSS_X86_OR_X64 */ +/* clang-format off */ +#if (defined(__aarch64__) || defined(__arm__)) && !defined(__ANDROID__) +#ifndef __has_include +#define __has_include(x) 0 +#endif +#if (__has_include() || defined(__linux__)) && \ + defined(__GNUC__) && __GNUC__ >= 2 && defined(__ELF__) +#include +extern unsigned long getauxval(unsigned long type) __attribute__((weak)); +#else +static unsigned long (*getauxval)(unsigned long) = NULL; +#define AT_HWCAP2 0 +#define AT_HWCAP 0 +#endif /* defined(__GNUC__) && __GNUC__ >= 2 && defined(__ELF__)*/ +#endif /* (defined(__aarch64__) || defined(__arm__)) && !defined(__ANDROID__) */ +/* clang-format on */ + +#if defined(__aarch64__) && !defined(__ANDROID__) +// Defines from hwcap.h in Linux kernel - ARM64 +#ifndef HWCAP_AES +#define HWCAP_AES (1 << 3) +#endif +#ifndef HWCAP_PMULL +#define HWCAP_PMULL (1 << 4) +#endif +#ifndef HWCAP_SHA1 +#define HWCAP_SHA1 (1 << 5) +#endif +#ifndef HWCAP_SHA2 +#define HWCAP_SHA2 (1 << 6) +#endif + +void +CheckARMSupport() +{ + char *disable_arm_neon = PR_GetEnvSecure("NSS_DISABLE_ARM_NEON"); + char *disable_hw_aes = PR_GetEnvSecure("NSS_DISABLE_HW_AES"); + if (getauxval) { + long hwcaps = getauxval(AT_HWCAP); + arm_aes_support_ = hwcaps & HWCAP_AES && disable_hw_aes == NULL; + arm_pmull_support_ = hwcaps & HWCAP_PMULL; + arm_sha1_support_ = hwcaps & HWCAP_SHA1; + arm_sha2_support_ = hwcaps & HWCAP_SHA2; + } + /* aarch64 must support NEON. */ + arm_neon_support_ = disable_arm_neon == NULL; +} +#endif /* defined(__aarch64__) && !defined(__ANDROID__) */ + +#if defined(__arm__) && !defined(__ANDROID__) +// Defines from hwcap.h in Linux kernel - ARM +/* + * HWCAP flags - for elf_hwcap (in kernel) and AT_HWCAP + */ +#ifndef HWCAP_NEON +#define HWCAP_NEON (1 << 12) +#endif + +/* + * HWCAP2 flags - for elf_hwcap2 (in kernel) and AT_HWCAP2 + */ +#ifndef HWCAP2_AES +#define HWCAP2_AES (1 << 0) +#endif +#ifndef HWCAP2_PMULL +#define HWCAP2_PMULL (1 << 1) +#endif +#ifndef HWCAP2_SHA1 +#define HWCAP2_SHA1 (1 << 2) +#endif +#ifndef HWCAP2_SHA2 +#define HWCAP2_SHA2 (1 << 3) +#endif + +void +CheckARMSupport() +{ + char *disable_arm_neon = PR_GetEnvSecure("NSS_DISABLE_ARM_NEON"); + char *disable_hw_aes = PR_GetEnvSecure("NSS_DISABLE_HW_AES"); + if (getauxval) { + long hwcaps = getauxval(AT_HWCAP2); + arm_aes_support_ = hwcaps & HWCAP2_AES && disable_hw_aes == NULL; + arm_pmull_support_ = hwcaps & HWCAP2_PMULL; + arm_sha1_support_ = hwcaps & HWCAP2_SHA1; + arm_sha2_support_ = hwcaps & HWCAP2_SHA2; + arm_neon_support_ = hwcaps & HWCAP_NEON && disable_arm_neon == NULL; + } +} +#endif /* defined(__arm__) && !defined(__ANDROID__) */ + +// Enable when Firefox can use it. +// #if defined(__ANDROID__) && (defined(__arm__) || defined(__aarch64__)) +// #include +// void +// CheckARMSupport() +// { +// char *disable_arm_neon = PR_GetEnvSecure("NSS_DISABLE_ARM_NEON"); +// char *disable_hw_aes = PR_GetEnvSecure("NSS_DISABLE_HW_AES"); +// AndroidCpuFamily family = android_getCpuFamily(); +// uint64_t features = android_getCpuFeatures(); +// if (family == ANDROID_CPU_FAMILY_ARM64) { +// arm_aes_support_ = features & ANDROID_CPU_ARM64_FEATURE_AES && +// disable_hw_aes == NULL; +// arm_pmull_support_ = features & ANDROID_CPU_ARM64_FEATURE_PMULL; +// arm_sha1_support_ = features & ANDROID_CPU_ARM64_FEATURE_SHA1; +// arm_sha2_support_ = features & ANDROID_CPU_ARM64_FEATURE_SHA2; +// arm_neon_support_ = disable_arm_neon == NULL; +// } +// if (family == ANDROID_CPU_FAMILY_ARM) { +// arm_aes_support_ = features & ANDROID_CPU_ARM_FEATURE_AES && +// disable_hw_aes == NULL; +// arm_pmull_support_ = features & ANDROID_CPU_ARM_FEATURE_PMULL; +// arm_sha1_support_ = features & ANDROID_CPU_ARM_FEATURE_SHA1; +// arm_sha2_support_ = features & ANDROID_CPU_ARM_FEATURE_SHA2; +// arm_neon_support_ = hwcaps & ANDROID_CPU_ARM_FEATURE_NEON && +// disable_arm_neon == NULL; +// } +// } +// #endif /* defined(__ANDROID__) && (defined(__arm__) || defined(__aarch64__)) */ + PRBool aesni_support() { @@ -96,12 +226,44 @@ avx_support() { return avx_support_; } +PRBool +ssse3_support() +{ + return ssse3_support_; +} +PRBool +arm_neon_support() +{ + return arm_neon_support_; +} +PRBool +arm_aes_support() +{ + return arm_aes_support_; +} +PRBool +arm_pmull_support() +{ + return arm_pmull_support_; +} +PRBool +arm_sha1_support() +{ + return arm_sha1_support_; +} +PRBool +arm_sha2_support() +{ + return arm_sha2_support_; +} static PRStatus FreeblInit(void) { #ifdef NSS_X86_OR_X64 CheckX86CPUSupport(); +#elif (defined(__aarch64__) || defined(__arm__)) && !defined(__ANDROID__) + CheckARMSupport(); #endif return PR_SUCCESS; } diff --git a/security/nss/lib/freebl/chacha20.c b/security/nss/lib/freebl/chacha20.c deleted file mode 100644 index 15ed67b5b..000000000 --- a/security/nss/lib/freebl/chacha20.c +++ /dev/null @@ -1,19 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -/* Adopted from the public domain code in NaCl by djb. */ - -#include -#include - -#include "chacha20.h" -#include "verified/Hacl_Chacha20.h" - -void -ChaCha20XOR(unsigned char *out, const unsigned char *in, unsigned int inLen, - const unsigned char key[32], const unsigned char nonce[12], - uint32_t counter) -{ - Hacl_Chacha20_chacha20(out, (uint8_t *)in, inLen, (uint8_t *)key, (uint8_t *)nonce, counter); -} diff --git a/security/nss/lib/freebl/chacha20.h b/security/nss/lib/freebl/chacha20.h deleted file mode 100644 index 7e396fa8c..000000000 --- a/security/nss/lib/freebl/chacha20.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * chacha20.h - header file for ChaCha20 implementation. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef FREEBL_CHACHA20_H_ -#define FREEBL_CHACHA20_H_ - -#if defined(_MSC_VER) && _MSC_VER < 1600 -#include "prtypes.h" -typedef PRUint32 uint32_t; -typedef PRUint64 uint64_t; -#else -#include -#endif - -/* ChaCha20XOR encrypts |inLen| bytes from |in| with the given key and - * nonce and writes the result to |out|, which may be equal to |in|. The - * initial block counter is specified by |counter|. */ -extern void ChaCha20XOR(unsigned char *out, const unsigned char *in, - unsigned int inLen, const unsigned char key[32], - const unsigned char nonce[12], uint32_t counter); - -#endif /* FREEBL_CHACHA20_H_ */ diff --git a/security/nss/lib/freebl/chacha20_vec.c b/security/nss/lib/freebl/chacha20_vec.c deleted file mode 100644 index 12f94d897..000000000 --- a/security/nss/lib/freebl/chacha20_vec.c +++ /dev/null @@ -1,327 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -/* This implementation is by Ted Krovetz and was submitted to SUPERCOP and - * marked as public domain. It was been altered to allow for non-aligned inputs - * and to allow the block counter to be passed in specifically. */ - -#include - -#include "chacha20.h" -#include "blapii.h" - -#ifndef CHACHA_RNDS -#define CHACHA_RNDS 20 /* 8 (high speed), 20 (conservative), 12 (middle) */ -#endif - -/* Architecture-neutral way to specify 16-byte vector of ints */ -typedef unsigned vec __attribute__((vector_size(16))); - -/* This implementation is designed for Neon, SSE and AltiVec machines. The - * following specify how to do certain vector operations efficiently on - * each architecture, using intrinsics. - * This implementation supports parallel processing of multiple blocks, - * including potentially using general-purpose registers. - */ -#if __ARM_NEON__ -#include -#define GPR_TOO 1 -#define VBPI 2 -#define ONE (vec) vsetq_lane_u32(1, vdupq_n_u32(0), 0) -#define LOAD(m) (vec)(*((vec *)(m))) -#define STORE(m, r) (*((vec *)(m))) = (r) -#define ROTV1(x) (vec) vextq_u32((uint32x4_t)x, (uint32x4_t)x, 1) -#define ROTV2(x) (vec) vextq_u32((uint32x4_t)x, (uint32x4_t)x, 2) -#define ROTV3(x) (vec) vextq_u32((uint32x4_t)x, (uint32x4_t)x, 3) -#define ROTW16(x) (vec) vrev32q_u16((uint16x8_t)x) -#if __clang__ -#define ROTW7(x) (x << ((vec){ 7, 7, 7, 7 })) ^ (x >> ((vec){ 25, 25, 25, 25 })) -#define ROTW8(x) (x << ((vec){ 8, 8, 8, 8 })) ^ (x >> ((vec){ 24, 24, 24, 24 })) -#define ROTW12(x) (x << ((vec){ 12, 12, 12, 12 })) ^ (x >> ((vec){ 20, 20, 20, 20 })) -#else -#define ROTW7(x) (vec) vsriq_n_u32(vshlq_n_u32((uint32x4_t)x, 7), (uint32x4_t)x, 25) -#define ROTW8(x) (vec) vsriq_n_u32(vshlq_n_u32((uint32x4_t)x, 8), (uint32x4_t)x, 24) -#define ROTW12(x) (vec) vsriq_n_u32(vshlq_n_u32((uint32x4_t)x, 12), (uint32x4_t)x, 20) -#endif -#elif __SSE2__ -#include -#define GPR_TOO 0 -#if __clang__ -#define VBPI 4 -#else -#define VBPI 3 -#endif -#define ONE (vec) _mm_set_epi32(0, 0, 0, 1) -#define LOAD(m) (vec) _mm_loadu_si128((__m128i *)(m)) -#define STORE(m, r) _mm_storeu_si128((__m128i *)(m), (__m128i)(r)) -#define ROTV1(x) (vec) _mm_shuffle_epi32((__m128i)x, _MM_SHUFFLE(0, 3, 2, 1)) -#define ROTV2(x) (vec) _mm_shuffle_epi32((__m128i)x, _MM_SHUFFLE(1, 0, 3, 2)) -#define ROTV3(x) (vec) _mm_shuffle_epi32((__m128i)x, _MM_SHUFFLE(2, 1, 0, 3)) -#define ROTW7(x) (vec)(_mm_slli_epi32((__m128i)x, 7) ^ _mm_srli_epi32((__m128i)x, 25)) -#define ROTW12(x) (vec)(_mm_slli_epi32((__m128i)x, 12) ^ _mm_srli_epi32((__m128i)x, 20)) -#if __SSSE3__ -#include -#define ROTW8(x) (vec) _mm_shuffle_epi8((__m128i)x, _mm_set_epi8(14, 13, 12, 15, 10, 9, 8, 11, 6, 5, 4, 7, 2, 1, 0, 3)) -#define ROTW16(x) (vec) _mm_shuffle_epi8((__m128i)x, _mm_set_epi8(13, 12, 15, 14, 9, 8, 11, 10, 5, 4, 7, 6, 1, 0, 3, 2)) -#else -#define ROTW8(x) (vec)(_mm_slli_epi32((__m128i)x, 8) ^ _mm_srli_epi32((__m128i)x, 24)) -#define ROTW16(x) (vec)(_mm_slli_epi32((__m128i)x, 16) ^ _mm_srli_epi32((__m128i)x, 16)) -#endif -#else -#error-- Implementation supports only machines with neon or SSE2 -#endif - -#ifndef REVV_BE -#define REVV_BE(x) (x) -#endif - -#ifndef REVW_BE -#define REVW_BE(x) (x) -#endif - -#define BPI (VBPI + GPR_TOO) /* Blocks computed per loop iteration */ - -#define DQROUND_VECTORS(a, b, c, d) \ - a += b; \ - d ^= a; \ - d = ROTW16(d); \ - c += d; \ - b ^= c; \ - b = ROTW12(b); \ - a += b; \ - d ^= a; \ - d = ROTW8(d); \ - c += d; \ - b ^= c; \ - b = ROTW7(b); \ - b = ROTV1(b); \ - c = ROTV2(c); \ - d = ROTV3(d); \ - a += b; \ - d ^= a; \ - d = ROTW16(d); \ - c += d; \ - b ^= c; \ - b = ROTW12(b); \ - a += b; \ - d ^= a; \ - d = ROTW8(d); \ - c += d; \ - b ^= c; \ - b = ROTW7(b); \ - b = ROTV3(b); \ - c = ROTV2(c); \ - d = ROTV1(d); - -#define QROUND_WORDS(a, b, c, d) \ - a = a + b; \ - d ^= a; \ - d = d << 16 | d >> 16; \ - c = c + d; \ - b ^= c; \ - b = b << 12 | b >> 20; \ - a = a + b; \ - d ^= a; \ - d = d << 8 | d >> 24; \ - c = c + d; \ - b ^= c; \ - b = b << 7 | b >> 25; - -#define WRITE_XOR(in, op, d, v0, v1, v2, v3) \ - STORE(op + d + 0, LOAD(in + d + 0) ^ REVV_BE(v0)); \ - STORE(op + d + 4, LOAD(in + d + 4) ^ REVV_BE(v1)); \ - STORE(op + d + 8, LOAD(in + d + 8) ^ REVV_BE(v2)); \ - STORE(op + d + 12, LOAD(in + d + 12) ^ REVV_BE(v3)); - -void NO_SANITIZE_ALIGNMENT -ChaCha20XOR(unsigned char *out, const unsigned char *in, unsigned int inlen, - const unsigned char key[32], const unsigned char nonce[12], - uint32_t counter) -{ - unsigned iters, i, *op = (unsigned *)out, *ip = (unsigned *)in, *kp; -#if defined(__ARM_NEON__) - unsigned *np; -#endif - vec s0, s1, s2, s3; -#if !defined(__ARM_NEON__) && !defined(__SSE2__) - __attribute__((aligned(16))) unsigned key[8], nonce[4]; -#endif - __attribute__((aligned(16))) unsigned chacha_const[] = - { 0x61707865, 0x3320646E, 0x79622D32, 0x6B206574 }; -#if defined(__ARM_NEON__) || defined(__SSE2__) - kp = (unsigned *)key; -#else - ((vec *)key)[0] = REVV_BE(((vec *)key)[0]); - ((vec *)key)[1] = REVV_BE(((vec *)key)[1]); - ((unsigned *)nonce)[0] = REVW_BE(((unsigned *)nonce)[0]); - ((unsigned *)nonce)[1] = REVW_BE(((unsigned *)nonce)[1]); - ((unsigned *)nonce)[2] = REVW_BE(((unsigned *)nonce)[2]); - ((unsigned *)nonce)[3] = REVW_BE(((unsigned *)nonce)[3]); - kp = (unsigned *)key; - np = (unsigned *)nonce; -#endif -#if defined(__ARM_NEON__) - np = (unsigned *)nonce; -#endif - s0 = LOAD(chacha_const); - s1 = LOAD(&((vec *)kp)[0]); - s2 = LOAD(&((vec *)kp)[1]); - s3 = (vec){ - counter, - ((uint32_t *)nonce)[0], - ((uint32_t *)nonce)[1], - ((uint32_t *)nonce)[2] - }; - - for (iters = 0; iters < inlen / (BPI * 64); iters++) { -#if GPR_TOO - register unsigned x0, x1, x2, x3, x4, x5, x6, x7, x8, - x9, x10, x11, x12, x13, x14, x15; -#endif -#if VBPI > 2 - vec v8, v9, v10, v11; -#endif -#if VBPI > 3 - vec v12, v13, v14, v15; -#endif - - vec v0, v1, v2, v3, v4, v5, v6, v7; - v4 = v0 = s0; - v5 = v1 = s1; - v6 = v2 = s2; - v3 = s3; - v7 = v3 + ONE; -#if VBPI > 2 - v8 = v4; - v9 = v5; - v10 = v6; - v11 = v7 + ONE; -#endif -#if VBPI > 3 - v12 = v8; - v13 = v9; - v14 = v10; - v15 = v11 + ONE; -#endif -#if GPR_TOO - x0 = chacha_const[0]; - x1 = chacha_const[1]; - x2 = chacha_const[2]; - x3 = chacha_const[3]; - x4 = kp[0]; - x5 = kp[1]; - x6 = kp[2]; - x7 = kp[3]; - x8 = kp[4]; - x9 = kp[5]; - x10 = kp[6]; - x11 = kp[7]; - x12 = counter + BPI * iters + (BPI - 1); - x13 = np[0]; - x14 = np[1]; - x15 = np[2]; -#endif - for (i = CHACHA_RNDS / 2; i; i--) { - DQROUND_VECTORS(v0, v1, v2, v3) - DQROUND_VECTORS(v4, v5, v6, v7) -#if VBPI > 2 - DQROUND_VECTORS(v8, v9, v10, v11) -#endif -#if VBPI > 3 - DQROUND_VECTORS(v12, v13, v14, v15) -#endif -#if GPR_TOO - QROUND_WORDS(x0, x4, x8, x12) - QROUND_WORDS(x1, x5, x9, x13) - QROUND_WORDS(x2, x6, x10, x14) - QROUND_WORDS(x3, x7, x11, x15) - QROUND_WORDS(x0, x5, x10, x15) - QROUND_WORDS(x1, x6, x11, x12) - QROUND_WORDS(x2, x7, x8, x13) - QROUND_WORDS(x3, x4, x9, x14) -#endif - } - - WRITE_XOR(ip, op, 0, v0 + s0, v1 + s1, v2 + s2, v3 + s3) - s3 += ONE; - WRITE_XOR(ip, op, 16, v4 + s0, v5 + s1, v6 + s2, v7 + s3) - s3 += ONE; -#if VBPI > 2 - WRITE_XOR(ip, op, 32, v8 + s0, v9 + s1, v10 + s2, v11 + s3) - s3 += ONE; -#endif -#if VBPI > 3 - WRITE_XOR(ip, op, 48, v12 + s0, v13 + s1, v14 + s2, v15 + s3) - s3 += ONE; -#endif - ip += VBPI * 16; - op += VBPI * 16; -#if GPR_TOO - op[0] = REVW_BE(REVW_BE(ip[0]) ^ (x0 + chacha_const[0])); - op[1] = REVW_BE(REVW_BE(ip[1]) ^ (x1 + chacha_const[1])); - op[2] = REVW_BE(REVW_BE(ip[2]) ^ (x2 + chacha_const[2])); - op[3] = REVW_BE(REVW_BE(ip[3]) ^ (x3 + chacha_const[3])); - op[4] = REVW_BE(REVW_BE(ip[4]) ^ (x4 + kp[0])); - op[5] = REVW_BE(REVW_BE(ip[5]) ^ (x5 + kp[1])); - op[6] = REVW_BE(REVW_BE(ip[6]) ^ (x6 + kp[2])); - op[7] = REVW_BE(REVW_BE(ip[7]) ^ (x7 + kp[3])); - op[8] = REVW_BE(REVW_BE(ip[8]) ^ (x8 + kp[4])); - op[9] = REVW_BE(REVW_BE(ip[9]) ^ (x9 + kp[5])); - op[10] = REVW_BE(REVW_BE(ip[10]) ^ (x10 + kp[6])); - op[11] = REVW_BE(REVW_BE(ip[11]) ^ (x11 + kp[7])); - op[12] = REVW_BE(REVW_BE(ip[12]) ^ (x12 + counter + BPI * iters + (BPI - 1))); - op[13] = REVW_BE(REVW_BE(ip[13]) ^ (x13 + np[0])); - op[14] = REVW_BE(REVW_BE(ip[14]) ^ (x14 + np[1])); - op[15] = REVW_BE(REVW_BE(ip[15]) ^ (x15 + np[2])); - s3 += ONE; - ip += 16; - op += 16; -#endif - } - - for (iters = inlen % (BPI * 64) / 64; iters != 0; iters--) { - vec v0 = s0, v1 = s1, v2 = s2, v3 = s3; - for (i = CHACHA_RNDS / 2; i; i--) { - DQROUND_VECTORS(v0, v1, v2, v3); - } - WRITE_XOR(ip, op, 0, v0 + s0, v1 + s1, v2 + s2, v3 + s3) - s3 += ONE; - ip += 16; - op += 16; - } - - inlen = inlen % 64; - if (inlen) { - __attribute__((aligned(16))) vec buf[4]; - vec v0, v1, v2, v3; - v0 = s0; - v1 = s1; - v2 = s2; - v3 = s3; - for (i = CHACHA_RNDS / 2; i; i--) { - DQROUND_VECTORS(v0, v1, v2, v3); - } - - if (inlen >= 16) { - STORE(op + 0, LOAD(ip + 0) ^ REVV_BE(v0 + s0)); - if (inlen >= 32) { - STORE(op + 4, LOAD(ip + 4) ^ REVV_BE(v1 + s1)); - if (inlen >= 48) { - STORE(op + 8, LOAD(ip + 8) ^ REVV_BE(v2 + s2)); - buf[3] = REVV_BE(v3 + s3); - } else { - buf[2] = REVV_BE(v2 + s2); - } - } else { - buf[1] = REVV_BE(v1 + s1); - } - } else { - buf[0] = REVV_BE(v0 + s0); - } - - for (i = inlen & ~15; i < inlen; i++) { - ((char *)op)[i] = ((char *)ip)[i] ^ ((char *)buf)[i]; - } - } -} diff --git a/security/nss/lib/freebl/chacha20poly1305.c b/security/nss/lib/freebl/chacha20poly1305.c index 991fa0ca3..859d05316 100644 --- a/security/nss/lib/freebl/chacha20poly1305.c +++ b/security/nss/lib/freebl/chacha20poly1305.c @@ -12,25 +12,28 @@ #include "seccomon.h" #include "secerr.h" #include "blapit.h" +#include "blapii.h" #ifndef NSS_DISABLE_CHACHAPOLY -#if defined(HAVE_INT128_SUPPORT) && (defined(NSS_X86_OR_X64) || defined(__aarch64__)) -#include "verified/Hacl_Poly1305_64.h" -#else -#include "poly1305.h" -#endif -#include "chacha20.h" #include "chacha20poly1305.h" -#endif +// Forward declaration from "Hacl_Chacha20_Vec128.h". +extern void Hacl_Chacha20_Vec128_chacha20(uint8_t *output, uint8_t *plain, + uint32_t len, uint8_t *k, uint8_t *n1, + uint32_t ctr); +// Forward declaration from "Hacl_Chacha20.h". +extern void Hacl_Chacha20_chacha20(uint8_t *output, uint8_t *plain, uint32_t len, + uint8_t *k, uint8_t *n1, uint32_t ctr); /* Poly1305Do writes the Poly1305 authenticator of the given additional data * and ciphertext to |out|. */ -#ifndef NSS_DISABLE_CHACHAPOLY - #if defined(HAVE_INT128_SUPPORT) && (defined(NSS_X86_OR_X64) || defined(__aarch64__)) +/* Use HACL* Poly1305 on 64-bit Intel and ARM */ +#include "verified/Hacl_Poly1305_64.h" static void -Poly1305PadUpdate(Hacl_Impl_Poly1305_64_State_poly1305_state state, unsigned char *block, const unsigned char *p, const unsigned int pLen) +Poly1305PadUpdate(Hacl_Impl_Poly1305_64_State_poly1305_state state, + unsigned char *block, const unsigned char *p, + const unsigned int pLen) { unsigned int pRemLen = pLen % 16; Hacl_Poly1305_64_update(state, (uint8_t *)p, (pLen / 16)); @@ -46,7 +49,8 @@ Poly1305Do(unsigned char *out, const unsigned char *ad, unsigned int adLen, const unsigned char key[32]) { uint64_t tmp1[6U] = { 0U }; - Hacl_Impl_Poly1305_64_State_poly1305_state state = Hacl_Poly1305_64_mk_state(tmp1, tmp1 + 3); + Hacl_Impl_Poly1305_64_State_poly1305_state state = + Hacl_Poly1305_64_mk_state(tmp1, tmp1 + 3); unsigned char block[16] = { 0 }; Hacl_Poly1305_64_init(state, (uint8_t *)key); @@ -68,6 +72,8 @@ Poly1305Do(unsigned char *out, const unsigned char *ad, unsigned int adLen, Hacl_Poly1305_64_finish(state, out, (uint8_t *)(key + 16)); } #else +/* All other platforms get the 32-bit poly1305 reference implementation. */ +#include "poly1305.h" static void Poly1305Do(unsigned char *out, const unsigned char *ad, unsigned int adLen, @@ -165,6 +171,17 @@ ChaCha20Poly1305_DestroyContext(ChaCha20Poly1305Context *ctx, PRBool freeit) #endif } +void +ChaCha20Xor(uint8_t *output, uint8_t *block, uint32_t len, uint8_t *k, + uint8_t *nonce, uint32_t ctr) +{ + if (ssse3_support() || arm_neon_support()) { + Hacl_Chacha20_Vec128_chacha20(output, block, len, k, nonce, ctr); + } else { + Hacl_Chacha20_chacha20(output, block, len, k, nonce, ctr); + } +} + SECStatus ChaCha20Poly1305_Seal(const ChaCha20Poly1305Context *ctx, unsigned char *output, unsigned int *outputLen, unsigned int maxOutputLen, @@ -191,8 +208,10 @@ ChaCha20Poly1305_Seal(const ChaCha20Poly1305Context *ctx, unsigned char *output, PORT_Memset(block, 0, sizeof(block)); // Generate a block of keystream. The first 32 bytes will be the poly1305 // key. The remainder of the block is discarded. - ChaCha20XOR(block, block, sizeof(block), ctx->key, nonce, 0); - ChaCha20XOR(output, input, inputLen, ctx->key, nonce, 1); + ChaCha20Xor(block, (uint8_t *)block, sizeof(block), (uint8_t *)ctx->key, + (uint8_t *)nonce, 0); + ChaCha20Xor(output, (uint8_t *)input, inputLen, (uint8_t *)ctx->key, + (uint8_t *)nonce, 1); Poly1305Do(tag, ad, adLen, output, inputLen, block); PORT_Memcpy(output + inputLen, tag, ctx->tagLen); @@ -233,14 +252,16 @@ ChaCha20Poly1305_Open(const ChaCha20Poly1305Context *ctx, unsigned char *output, PORT_Memset(block, 0, sizeof(block)); // Generate a block of keystream. The first 32 bytes will be the poly1305 // key. The remainder of the block is discarded. - ChaCha20XOR(block, block, sizeof(block), ctx->key, nonce, 0); + ChaCha20Xor(block, (uint8_t *)block, sizeof(block), (uint8_t *)ctx->key, + (uint8_t *)nonce, 0); Poly1305Do(tag, ad, adLen, input, ciphertextLen, block); if (NSS_SecureMemcmp(tag, &input[ciphertextLen], ctx->tagLen) != 0) { PORT_SetError(SEC_ERROR_BAD_DATA); return SECFailure; } - ChaCha20XOR(output, input, ciphertextLen, ctx->key, nonce, 1); + ChaCha20Xor(output, (uint8_t *)input, ciphertextLen, (uint8_t *)ctx->key, + (uint8_t *)nonce, 1); return SECSuccess; #endif diff --git a/security/nss/lib/freebl/config.mk b/security/nss/lib/freebl/config.mk index f15077096..7ac50db65 100644 --- a/security/nss/lib/freebl/config.mk +++ b/security/nss/lib/freebl/config.mk @@ -90,7 +90,7 @@ EXTRA_SHARED_LIBS += \ endif endif -ifeq ($(OS_ARCH), Linux) +ifeq (,$(filter-out DragonFly FreeBSD Linux NetBSD OpenBSD, $(OS_TARGET))) CFLAGS += -std=gnu99 endif diff --git a/security/nss/lib/freebl/det_rng.c b/security/nss/lib/freebl/det_rng.c index 53d48bc7c..56be2d356 100644 --- a/security/nss/lib/freebl/det_rng.c +++ b/security/nss/lib/freebl/det_rng.c @@ -4,7 +4,7 @@ #include "blapi.h" #include "blapit.h" -#include "chacha20.h" +#include "Hacl_Chacha20.h" #include "nssilock.h" #include "seccomon.h" #include "secerr.h" @@ -99,7 +99,7 @@ RNG_GenerateGlobalRandomBytes(void *dest, size_t len) memset(dest, 0, len); memcpy(dest, globalBytes, PR_MIN(len, GLOBAL_BYTES_SIZE)); - ChaCha20XOR(dest, dest, len, key, nonce, 0); + Hacl_Chacha20_chacha20(dest, (uint8_t *)dest, len, (uint8_t *)key, nonce, 0); ChaCha20Poly1305_DestroyContext(cx, PR_TRUE); PZ_Unlock(rng_lock); diff --git a/security/nss/lib/freebl/drbg.c b/security/nss/lib/freebl/drbg.c index 224bbe87d..70ae2618e 100644 --- a/security/nss/lib/freebl/drbg.c +++ b/security/nss/lib/freebl/drbg.c @@ -74,8 +74,7 @@ struct RNGContextStr { #define V_type V_Data[0] #define V(rng) (((rng)->V_Data) + 1) #define VSize(rng) ((sizeof(rng)->V_Data) - 1) - PRUint8 C[PRNG_SEEDLEN]; /* internal state variables */ - PRUint8 lastOutput[SHA256_LENGTH]; /* for continuous rng checking */ + PRUint8 C[PRNG_SEEDLEN]; /* internal state variables */ /* If we get calls for the PRNG to return less than the length of our * hash, we extend the request for a full hash (since we'll be doing * the full hash anyway). Future requests for random numbers are fulfilled @@ -286,7 +285,6 @@ prng_Hashgen(RNGContext *rng, PRUint8 *returned_bytes, { PRUint8 data[VSize(rng)]; PRUint8 thisHash[SHA256_LENGTH]; - PRUint8 *lastHash = rng->lastOutput; PORT_Memcpy(data, V(rng), VSize(rng)); while (no_of_returned_bytes) { @@ -297,15 +295,10 @@ prng_Hashgen(RNGContext *rng, PRUint8 *returned_bytes, SHA256_Begin(&ctx); SHA256_Update(&ctx, data, sizeof data); SHA256_End(&ctx, thisHash, &len, SHA256_LENGTH); - if (PORT_Memcmp(lastHash, thisHash, len) == 0) { - rng->isValid = PR_FALSE; - break; - } if (no_of_returned_bytes < SHA256_LENGTH) { len = no_of_returned_bytes; } PORT_Memcpy(returned_bytes, thisHash, len); - lastHash = returned_bytes; returned_bytes += len; no_of_returned_bytes -= len; /* The carry parameter is a bool (increment or not). @@ -313,7 +306,6 @@ prng_Hashgen(RNGContext *rng, PRUint8 *returned_bytes, carry = no_of_returned_bytes; PRNG_ADD_CARRY_ONLY(data, (sizeof data) - 1, carry); } - PORT_Memcpy(rng->lastOutput, thisHash, SHA256_LENGTH); PORT_Memset(data, 0, sizeof data); PORT_Memset(thisHash, 0, sizeof thisHash); } @@ -361,11 +353,6 @@ prng_generateNewBytes(RNGContext *rng, if (no_of_returned_bytes == SHA256_LENGTH) { /* short_cut to hashbuf and a couple of copies and clears */ SHA256_HashBuf(returned_bytes, V(rng), VSize(rng)); - /* continuous rng check */ - if (memcmp(rng->lastOutput, returned_bytes, SHA256_LENGTH) == 0) { - rng->isValid = PR_FALSE; - } - PORT_Memcpy(rng->lastOutput, returned_bytes, sizeof rng->lastOutput); } else { prng_Hashgen(rng, returned_bytes, no_of_returned_bytes); } diff --git a/security/nss/lib/freebl/ecl/uint128.c b/security/nss/lib/freebl/ecl/uint128.c deleted file mode 100644 index 5465875ad..000000000 --- a/security/nss/lib/freebl/ecl/uint128.c +++ /dev/null @@ -1,90 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "uint128.h" - -/* helper functions */ -uint64_t -mask51(uint128_t x) -{ - return x.lo & MASK51; -} - -uint64_t -mask_lower(uint128_t x) -{ - return x.lo; -} - -uint128_t -mask51full(uint128_t x) -{ - uint128_t ret = { x.lo & MASK51, 0 }; - return ret; -} - -uint128_t -init128x(uint64_t x) -{ - uint128_t ret = { x, 0 }; - return ret; -} - -#define CONSTANT_TIME_CARRY(a, b) \ - ((a ^ ((a ^ b) | ((a - b) ^ b))) >> (sizeof(a) * 8 - 1)) - -/* arithmetic */ - -uint128_t -add128(uint128_t a, uint128_t b) -{ - uint128_t ret; - ret.lo = a.lo + b.lo; - ret.hi = a.hi + b.hi + CONSTANT_TIME_CARRY(ret.lo, b.lo); - return ret; -} - -/* out = 19 * a */ -uint128_t -mul12819(uint128_t a) -{ - uint128_t ret = lshift128(a, 4); - ret = add128(ret, a); - ret = add128(ret, a); - ret = add128(ret, a); - return ret; -} - -uint128_t -mul6464(uint64_t a, uint64_t b) -{ - uint128_t ret; - uint64_t t0 = ((uint64_t)(uint32_t)a) * ((uint64_t)(uint32_t)b); - uint64_t t1 = (a >> 32) * ((uint64_t)(uint32_t)b) + (t0 >> 32); - uint64_t t2 = (b >> 32) * ((uint64_t)(uint32_t)a) + ((uint32_t)t1); - ret.lo = (((uint64_t)((uint32_t)t2)) << 32) + ((uint32_t)t0); - ret.hi = (a >> 32) * (b >> 32); - ret.hi += (t2 >> 32) + (t1 >> 32); - return ret; -} - -/* only defined for n < 64 */ -uint128_t -rshift128(uint128_t x, uint8_t n) -{ - uint128_t ret; - ret.lo = (x.lo >> n) + (x.hi << (64 - n)); - ret.hi = x.hi >> n; - return ret; -} - -/* only defined for n < 64 */ -uint128_t -lshift128(uint128_t x, uint8_t n) -{ - uint128_t ret; - ret.hi = (x.hi << n) + (x.lo >> (64 - n)); - ret.lo = x.lo << n; - return ret; -} diff --git a/security/nss/lib/freebl/ecl/uint128.h b/security/nss/lib/freebl/ecl/uint128.h deleted file mode 100644 index a3a71e6e7..000000000 --- a/security/nss/lib/freebl/ecl/uint128.h +++ /dev/null @@ -1,35 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include - -#define MASK51 0x7ffffffffffffULL - -#ifdef HAVE_INT128_SUPPORT -typedef unsigned __int128 uint128_t; -#define add128(a, b) (a) + (b) -#define mul6464(a, b) (uint128_t)(a) * (uint128_t)(b) -#define mul12819(a) (uint128_t)(a) * 19 -#define rshift128(x, n) (x) >> (n) -#define lshift128(x, n) (x) << (n) -#define mask51(x) (x) & 0x7ffffffffffff -#define mask_lower(x) (uint64_t)(x) -#define mask51full(x) (x) & 0x7ffffffffffff -#define init128x(x) (x) -#else /* uint128_t for Windows and 32 bit intel systems */ -struct uint128_t_str { - uint64_t lo; - uint64_t hi; -}; -typedef struct uint128_t_str uint128_t; -uint128_t add128(uint128_t a, uint128_t b); -uint128_t mul6464(uint64_t a, uint64_t b); -uint128_t mul12819(uint128_t a); -uint128_t rshift128(uint128_t x, uint8_t n); -uint128_t lshift128(uint128_t x, uint8_t n); -uint64_t mask51(uint128_t x); -uint64_t mask_lower(uint128_t x); -uint128_t mask51full(uint128_t x); -uint128_t init128x(uint64_t x); -#endif diff --git a/security/nss/lib/freebl/freebl.gyp b/security/nss/lib/freebl/freebl.gyp index 8b6a546e7..fae56f709 100644 --- a/security/nss/lib/freebl/freebl.gyp +++ b/security/nss/lib/freebl/freebl.gyp @@ -10,7 +10,7 @@ 'target_name': 'intel-gcm-wrap_c_lib', 'type': 'static_library', 'sources': [ - 'intel-gcm-wrap.c' + 'intel-gcm-wrap.c', ], 'dependencies': [ '<(DEPTH)/exports.gyp:nss_exports' @@ -22,6 +22,38 @@ '-mssse3' ] }, + { + # TODO: make this so that all hardware accelerated code is in here. + 'target_name': 'hw-acc-crypto', + 'type': 'static_library', + 'sources': [ + 'verified/Hacl_Chacha20_Vec128.c', + ], + 'dependencies': [ + '<(DEPTH)/exports.gyp:nss_exports' + ], + 'conditions': [ + [ 'target_arch=="ia32" or target_arch=="x64"', { + 'cflags': [ + '-mssse3' + ], + 'cflags_mozilla': [ + '-mssse3' + ], + # GCC doesn't define this. + 'defines': [ + '__SSSE3__', + ], + }], + [ 'OS=="android"', { + # On Android we can't use any of the hardware acceleration :( + 'defines!': [ + '__ARM_NEON__', + '__ARM_NEON', + ], + }], + ], + }, { 'target_name': 'gcm-aes-x86_c_lib', 'type': 'static_library', @@ -74,11 +106,12 @@ ], 'dependencies': [ '<(DEPTH)/exports.gyp:nss_exports', + 'hw-acc-crypto', ], 'conditions': [ [ 'target_arch=="ia32" or target_arch=="x64"', { 'dependencies': [ - 'gcm-aes-x86_c_lib' + 'gcm-aes-x86_c_lib', ], }], [ 'OS=="linux"', { @@ -110,11 +143,12 @@ ], 'dependencies': [ '<(DEPTH)/exports.gyp:nss_exports', + 'hw-acc-crypto', ], 'conditions': [ [ 'target_arch=="ia32" or target_arch=="x64"', { 'dependencies': [ - 'gcm-aes-x86_c_lib' + 'gcm-aes-x86_c_lib', ] }], [ 'OS!="linux" and OS!="android"', { @@ -275,6 +309,11 @@ '-std=gnu99', ], }], + [ 'OS=="dragonfly" or OS=="freebsd" or OS=="netbsd" or OS=="openbsd"', { + 'cflags': [ + '-std=gnu99', + ], + }], [ 'OS=="linux" or OS=="android"', { 'conditions': [ [ 'target_arch=="x64"', { diff --git a/security/nss/lib/freebl/freebl_base.gypi b/security/nss/lib/freebl/freebl_base.gypi index 44e28963b..ebd1018d8 100644 --- a/security/nss/lib/freebl/freebl_base.gypi +++ b/security/nss/lib/freebl/freebl_base.gypi @@ -144,12 +144,17 @@ ], }], [ 'disable_chachapoly==0', { + # The ChaCha20 code is linked in through the static ssse3-crypto lib on + # all platforms that support SSSE3. There are runtime checks in place to + # choose the correct ChaCha implementation at runtime. + 'sources': [ + 'verified/Hacl_Chacha20.c', + ], 'conditions': [ [ 'OS!="win"', { 'conditions': [ [ 'target_arch=="x64"', { 'sources': [ - 'chacha20_vec.c', 'verified/Hacl_Poly1305_64.c', ], }, { @@ -157,15 +162,11 @@ 'conditions': [ [ 'target_arch=="arm64" or target_arch=="aarch64"', { 'sources': [ - 'chacha20.c', - 'verified/Hacl_Chacha20.c', 'verified/Hacl_Poly1305_64.c', ], }, { # !Windows & !x64 & !arm64 & !aarch64 'sources': [ - 'chacha20.c', - 'verified/Hacl_Chacha20.c', 'poly1305.c', ], }], @@ -175,8 +176,6 @@ }, { # Windows 'sources': [ - 'chacha20.c', - 'verified/Hacl_Chacha20.c', 'poly1305.c', ], }], diff --git a/security/nss/lib/freebl/lowhash_vector.c b/security/nss/lib/freebl/lowhash_vector.c index 7690c98da..be53bbdc6 100644 --- a/security/nss/lib/freebl/lowhash_vector.c +++ b/security/nss/lib/freebl/lowhash_vector.c @@ -102,13 +102,13 @@ freebl_LoadDSO(void) static PRCallOnceType loadFreeBLOnce; -static PRStatus +static void freebl_RunLoaderOnce(void) { /* Don't have NSPR, so can use the real PR_CallOnce, implement a stripped * down version. */ if (loadFreeBLOnce.initialized) { - return loadFreeBLOnce.status; + return; } if (__sync_lock_test_and_set(&loadFreeBLOnce.inProgress, 1) == 0) { loadFreeBLOnce.status = freebl_LoadDSO(); @@ -122,17 +122,21 @@ freebl_RunLoaderOnce(void) sleep(1); /* don't have condition variables, just give up the CPU */ } } +} - return loadFreeBLOnce.status; +static const NSSLOWVector * +freebl_InitVector(void) +{ + if (!vector) { + freebl_RunLoaderOnce(); + } + return vector; } const FREEBLVector * FREEBL_GetVector(void) { - if (!vector && PR_SUCCESS != freebl_RunLoaderOnce()) { - return NULL; - } - if (vector) { + if (freebl_InitVector()) { return (vector->p_FREEBL_GetVector)(); } return NULL; @@ -141,25 +145,26 @@ FREEBL_GetVector(void) NSSLOWInitContext * NSSLOW_Init(void) { - if (!vector && PR_SUCCESS != freebl_RunLoaderOnce()) - return NULL; - return (vector->p_NSSLOW_Init)(); + if (freebl_InitVector()) { + return (vector->p_NSSLOW_Init)(); + } + return NULL; } void NSSLOW_Shutdown(NSSLOWInitContext *context) { - if (!vector && PR_SUCCESS != freebl_RunLoaderOnce()) - return; - (vector->p_NSSLOW_Shutdown)(context); + if (freebl_InitVector()) { + (vector->p_NSSLOW_Shutdown)(context); + } } void NSSLOW_Reset(NSSLOWInitContext *context) { - if (!vector && PR_SUCCESS != freebl_RunLoaderOnce()) - return; - (vector->p_NSSLOW_Reset)(context); + if (freebl_InitVector()) { + (vector->p_NSSLOW_Reset)(context); + } } NSSLOWHASHContext * @@ -167,17 +172,18 @@ NSSLOWHASH_NewContext( NSSLOWInitContext *initContext, HASH_HashType hashType) { - if (!vector && PR_SUCCESS != freebl_RunLoaderOnce()) - return NULL; - return (vector->p_NSSLOWHASH_NewContext)(initContext, hashType); + if (freebl_InitVector()) { + return (vector->p_NSSLOWHASH_NewContext)(initContext, hashType); + } + return NULL; } void NSSLOWHASH_Begin(NSSLOWHASHContext *context) { - if (!vector && PR_SUCCESS != freebl_RunLoaderOnce()) - return; - (vector->p_NSSLOWHASH_Begin)(context); + if (freebl_InitVector()) { + (vector->p_NSSLOWHASH_Begin)(context); + } } void @@ -185,9 +191,9 @@ NSSLOWHASH_Update(NSSLOWHASHContext *context, const unsigned char *buf, unsigned int len) { - if (!vector && PR_SUCCESS != freebl_RunLoaderOnce()) - return; - (vector->p_NSSLOWHASH_Update)(context, buf, len); + if (freebl_InitVector()) { + (vector->p_NSSLOWHASH_Update)(context, buf, len); + } } void @@ -195,23 +201,24 @@ NSSLOWHASH_End(NSSLOWHASHContext *context, unsigned char *buf, unsigned int *ret, unsigned int len) { - if (!vector && PR_SUCCESS != freebl_RunLoaderOnce()) - return; - (vector->p_NSSLOWHASH_End)(context, buf, ret, len); + if (freebl_InitVector()) { + (vector->p_NSSLOWHASH_End)(context, buf, ret, len); + } } void NSSLOWHASH_Destroy(NSSLOWHASHContext *context) { - if (!vector && PR_SUCCESS != freebl_RunLoaderOnce()) - return; - (vector->p_NSSLOWHASH_Destroy)(context); + if (freebl_InitVector()) { + (vector->p_NSSLOWHASH_Destroy)(context); + } } unsigned int NSSLOWHASH_Length(NSSLOWHASHContext *context) { - if (!vector && PR_SUCCESS != freebl_RunLoaderOnce()) - return -1; - return (vector->p_NSSLOWHASH_Length)(context); + if (freebl_InitVector()) { + return (vector->p_NSSLOWHASH_Length)(context); + } + return -1; } diff --git a/security/nss/lib/freebl/stubs.c b/security/nss/lib/freebl/stubs.c index 4d41ef975..c42f694d7 100644 --- a/security/nss/lib/freebl/stubs.c +++ b/security/nss/lib/freebl/stubs.c @@ -36,6 +36,7 @@ #include #include #include +#include #include /* Android API < 21 doesn't define RTLD_NOLOAD */ @@ -252,7 +253,12 @@ PORT_ZAllocAligned_stub(size_t bytes, size_t alignment, void **mem) } memset(*mem, 0, len); - return (void *)(((uintptr_t)*mem + x) & ~(uintptr_t)x); + + /* We're pretty sure this is non-zero, but let's assure scan-build too. */ + void *ret = (void *)(((uintptr_t)*mem + x) & ~(uintptr_t)x); + assert(ret); + + return ret; } extern void * diff --git a/security/nss/lib/freebl/verified/Hacl_Chacha20_Vec128.c b/security/nss/lib/freebl/verified/Hacl_Chacha20_Vec128.c new file mode 100644 index 000000000..4eba49f47 --- /dev/null +++ b/security/nss/lib/freebl/verified/Hacl_Chacha20_Vec128.c @@ -0,0 +1,390 @@ +/* Copyright 2016-2017 INRIA and Microsoft Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "Hacl_Chacha20_Vec128.h" + +inline static void +Hacl_Impl_Chacha20_Vec128_State_state_incr(vec *k) +{ + vec k3 = k[3U]; + k[3U] = vec_increment(k3); +} + +inline static void +Hacl_Impl_Chacha20_Vec128_State_state_to_key_block(uint8_t *stream_block, vec *k) +{ + vec k0 = k[0U]; + vec k1 = k[1U]; + vec k2 = k[2U]; + vec k3 = k[3U]; + uint8_t *a = stream_block; + uint8_t *b = stream_block + (uint32_t)16U; + uint8_t *c = stream_block + (uint32_t)32U; + uint8_t *d = stream_block + (uint32_t)48U; + vec_store_le(a, k0); + vec_store_le(b, k1); + vec_store_le(c, k2); + vec_store_le(d, k3); +} + +inline static void +Hacl_Impl_Chacha20_Vec128_State_state_setup(vec *st, uint8_t *k, uint8_t *n1, uint32_t c) +{ + st[0U] = + vec_load_32x4((uint32_t)0x61707865U, + (uint32_t)0x3320646eU, + (uint32_t)0x79622d32U, + (uint32_t)0x6b206574U); + vec k0 = vec_load128_le(k); + vec k1 = vec_load128_le(k + (uint32_t)16U); + st[1U] = k0; + st[2U] = k1; + uint32_t n0 = load32_le(n1); + uint8_t *x00 = n1 + (uint32_t)4U; + uint32_t n10 = load32_le(x00); + uint8_t *x0 = n1 + (uint32_t)8U; + uint32_t n2 = load32_le(x0); + vec v1 = vec_load_32x4(c, n0, n10, n2); + st[3U] = v1; +} + +inline static void +Hacl_Impl_Chacha20_Vec128_round(vec *st) +{ + vec sa = st[0U]; + vec sb0 = st[1U]; + vec sd0 = st[3U]; + vec sa10 = vec_add(sa, sb0); + vec sd10 = vec_rotate_left(vec_xor(sd0, sa10), (uint32_t)16U); + st[0U] = sa10; + st[3U] = sd10; + vec sa0 = st[2U]; + vec sb1 = st[3U]; + vec sd2 = st[1U]; + vec sa11 = vec_add(sa0, sb1); + vec sd11 = vec_rotate_left(vec_xor(sd2, sa11), (uint32_t)12U); + st[2U] = sa11; + st[1U] = sd11; + vec sa2 = st[0U]; + vec sb2 = st[1U]; + vec sd3 = st[3U]; + vec sa12 = vec_add(sa2, sb2); + vec sd12 = vec_rotate_left(vec_xor(sd3, sa12), (uint32_t)8U); + st[0U] = sa12; + st[3U] = sd12; + vec sa3 = st[2U]; + vec sb = st[3U]; + vec sd = st[1U]; + vec sa1 = vec_add(sa3, sb); + vec sd1 = vec_rotate_left(vec_xor(sd, sa1), (uint32_t)7U); + st[2U] = sa1; + st[1U] = sd1; +} + +inline static void +Hacl_Impl_Chacha20_Vec128_double_round(vec *st) +{ + Hacl_Impl_Chacha20_Vec128_round(st); + vec r1 = st[1U]; + vec r20 = st[2U]; + vec r30 = st[3U]; + st[1U] = vec_shuffle_right(r1, (uint32_t)1U); + st[2U] = vec_shuffle_right(r20, (uint32_t)2U); + st[3U] = vec_shuffle_right(r30, (uint32_t)3U); + Hacl_Impl_Chacha20_Vec128_round(st); + vec r10 = st[1U]; + vec r2 = st[2U]; + vec r3 = st[3U]; + st[1U] = vec_shuffle_right(r10, (uint32_t)3U); + st[2U] = vec_shuffle_right(r2, (uint32_t)2U); + st[3U] = vec_shuffle_right(r3, (uint32_t)1U); +} + +inline static void +Hacl_Impl_Chacha20_Vec128_double_round3(vec *st, vec *st_, vec *st__) +{ + Hacl_Impl_Chacha20_Vec128_double_round(st); + Hacl_Impl_Chacha20_Vec128_double_round(st_); + Hacl_Impl_Chacha20_Vec128_double_round(st__); +} + +inline static void +Hacl_Impl_Chacha20_Vec128_sum_states(vec *st_, vec *st) +{ + vec s0 = st[0U]; + vec s1 = st[1U]; + vec s2 = st[2U]; + vec s3 = st[3U]; + vec s0_ = st_[0U]; + vec s1_ = st_[1U]; + vec s2_ = st_[2U]; + vec s3_ = st_[3U]; + st_[0U] = vec_add(s0_, s0); + st_[1U] = vec_add(s1_, s1); + st_[2U] = vec_add(s2_, s2); + st_[3U] = vec_add(s3_, s3); +} + +inline static void +Hacl_Impl_Chacha20_Vec128_copy_state(vec *st_, vec *st) +{ + vec st0 = st[0U]; + vec st1 = st[1U]; + vec st2 = st[2U]; + vec st3 = st[3U]; + st_[0U] = st0; + st_[1U] = st1; + st_[2U] = st2; + st_[3U] = st3; +} + +inline static void +Hacl_Impl_Chacha20_Vec128_chacha20_core(vec *k, vec *st) +{ + Hacl_Impl_Chacha20_Vec128_copy_state(k, st); + for (uint32_t i = (uint32_t)0U; i < (uint32_t)10U; i = i + (uint32_t)1U) + Hacl_Impl_Chacha20_Vec128_double_round(k); + Hacl_Impl_Chacha20_Vec128_sum_states(k, st); +} + +static void +Hacl_Impl_Chacha20_Vec128_state_incr(vec *st) +{ + Hacl_Impl_Chacha20_Vec128_State_state_incr(st); +} + +inline static void +Hacl_Impl_Chacha20_Vec128_chacha20_incr3(vec *k0, vec *k1, vec *k2, vec *st) +{ + Hacl_Impl_Chacha20_Vec128_copy_state(k0, st); + Hacl_Impl_Chacha20_Vec128_copy_state(k1, st); + Hacl_Impl_Chacha20_Vec128_state_incr(k1); + Hacl_Impl_Chacha20_Vec128_copy_state(k2, k1); + Hacl_Impl_Chacha20_Vec128_state_incr(k2); +} + +inline static void +Hacl_Impl_Chacha20_Vec128_chacha20_sum3(vec *k0, vec *k1, vec *k2, vec *st) +{ + Hacl_Impl_Chacha20_Vec128_sum_states(k0, st); + Hacl_Impl_Chacha20_Vec128_state_incr(st); + Hacl_Impl_Chacha20_Vec128_sum_states(k1, st); + Hacl_Impl_Chacha20_Vec128_state_incr(st); + Hacl_Impl_Chacha20_Vec128_sum_states(k2, st); +} + +inline static void +Hacl_Impl_Chacha20_Vec128_chacha20_core3(vec *k0, vec *k1, vec *k2, vec *st) +{ + Hacl_Impl_Chacha20_Vec128_chacha20_incr3(k0, k1, k2, st); + for (uint32_t i = (uint32_t)0U; i < (uint32_t)10U; i = i + (uint32_t)1U) + Hacl_Impl_Chacha20_Vec128_double_round3(k0, k1, k2); + Hacl_Impl_Chacha20_Vec128_chacha20_sum3(k0, k1, k2, st); +} + +inline static void +Hacl_Impl_Chacha20_Vec128_chacha20_block(uint8_t *stream_block, vec *st) +{ + KRML_CHECK_SIZE(vec_zero(), (uint32_t)4U); + vec k[4U]; + for (uint32_t _i = 0U; _i < (uint32_t)4U; ++_i) + k[_i] = vec_zero(); + Hacl_Impl_Chacha20_Vec128_chacha20_core(k, st); + Hacl_Impl_Chacha20_Vec128_State_state_to_key_block(stream_block, k); +} + +inline static void +Hacl_Impl_Chacha20_Vec128_init(vec *st, uint8_t *k, uint8_t *n1, uint32_t ctr) +{ + Hacl_Impl_Chacha20_Vec128_State_state_setup(st, k, n1, ctr); +} + +static void +Hacl_Impl_Chacha20_Vec128_update_last(uint8_t *output, uint8_t *plain, uint32_t len, vec *st) +{ + uint8_t block[64U] = { 0U }; + Hacl_Impl_Chacha20_Vec128_chacha20_block(block, st); + uint8_t *mask = block; + for (uint32_t i = (uint32_t)0U; i < len; i = i + (uint32_t)1U) { + uint8_t xi = plain[i]; + uint8_t yi = mask[i]; + output[i] = xi ^ yi; + } +} + +static void +Hacl_Impl_Chacha20_Vec128_xor_block(uint8_t *output, uint8_t *plain, vec *st) +{ + vec p0 = vec_load_le(plain); + vec p1 = vec_load_le(plain + (uint32_t)16U); + vec p2 = vec_load_le(plain + (uint32_t)32U); + vec p3 = vec_load_le(plain + (uint32_t)48U); + vec k0 = st[0U]; + vec k1 = st[1U]; + vec k2 = st[2U]; + vec k3 = st[3U]; + vec o00 = vec_xor(p0, k0); + vec o10 = vec_xor(p1, k1); + vec o20 = vec_xor(p2, k2); + vec o30 = vec_xor(p3, k3); + uint8_t *o0 = output; + uint8_t *o1 = output + (uint32_t)16U; + uint8_t *o2 = output + (uint32_t)32U; + uint8_t *o3 = output + (uint32_t)48U; + vec_store_le(o0, o00); + vec_store_le(o1, o10); + vec_store_le(o2, o20); + vec_store_le(o3, o30); +} + +static void +Hacl_Impl_Chacha20_Vec128_update(uint8_t *output, uint8_t *plain, vec *st) +{ + KRML_CHECK_SIZE(vec_zero(), (uint32_t)4U); + vec k[4U]; + for (uint32_t _i = 0U; _i < (uint32_t)4U; ++_i) + k[_i] = vec_zero(); + Hacl_Impl_Chacha20_Vec128_chacha20_core(k, st); + Hacl_Impl_Chacha20_Vec128_xor_block(output, plain, k); +} + +static void +Hacl_Impl_Chacha20_Vec128_update3(uint8_t *output, uint8_t *plain, vec *st) +{ + KRML_CHECK_SIZE(vec_zero(), (uint32_t)4U); + vec k0[4U]; + for (uint32_t _i = 0U; _i < (uint32_t)4U; ++_i) + k0[_i] = vec_zero(); + KRML_CHECK_SIZE(vec_zero(), (uint32_t)4U); + vec k1[4U]; + for (uint32_t _i = 0U; _i < (uint32_t)4U; ++_i) + k1[_i] = vec_zero(); + KRML_CHECK_SIZE(vec_zero(), (uint32_t)4U); + vec k2[4U]; + for (uint32_t _i = 0U; _i < (uint32_t)4U; ++_i) + k2[_i] = vec_zero(); + Hacl_Impl_Chacha20_Vec128_chacha20_core3(k0, k1, k2, st); + uint8_t *p0 = plain; + uint8_t *p1 = plain + (uint32_t)64U; + uint8_t *p2 = plain + (uint32_t)128U; + uint8_t *o0 = output; + uint8_t *o1 = output + (uint32_t)64U; + uint8_t *o2 = output + (uint32_t)128U; + Hacl_Impl_Chacha20_Vec128_xor_block(o0, p0, k0); + Hacl_Impl_Chacha20_Vec128_xor_block(o1, p1, k1); + Hacl_Impl_Chacha20_Vec128_xor_block(o2, p2, k2); +} + +static void +Hacl_Impl_Chacha20_Vec128_update3_( + uint8_t *output, + uint8_t *plain, + uint32_t len, + vec *st, + uint32_t i) +{ + uint8_t *out_block = output + (uint32_t)192U * i; + uint8_t *plain_block = plain + (uint32_t)192U * i; + Hacl_Impl_Chacha20_Vec128_update3(out_block, plain_block, st); + Hacl_Impl_Chacha20_Vec128_state_incr(st); +} + +static void +Hacl_Impl_Chacha20_Vec128_chacha20_counter_mode_blocks3( + uint8_t *output, + uint8_t *plain, + uint32_t len, + vec *st) +{ + for (uint32_t i = (uint32_t)0U; i < len; i = i + (uint32_t)1U) + Hacl_Impl_Chacha20_Vec128_update3_(output, plain, len, st, i); +} + +static void +Hacl_Impl_Chacha20_Vec128_chacha20_counter_mode_blocks( + uint8_t *output, + uint8_t *plain, + uint32_t len, + vec *st) +{ + uint32_t len3 = len / (uint32_t)3U; + uint32_t rest3 = len % (uint32_t)3U; + uint8_t *plain_ = plain; + uint8_t *blocks1 = plain + (uint32_t)192U * len3; + uint8_t *output_ = output; + uint8_t *outs = output + (uint32_t)192U * len3; + Hacl_Impl_Chacha20_Vec128_chacha20_counter_mode_blocks3(output_, plain_, len3, st); + if (rest3 == (uint32_t)2U) { + uint8_t *block0 = blocks1; + uint8_t *block1 = blocks1 + (uint32_t)64U; + uint8_t *out0 = outs; + uint8_t *out1 = outs + (uint32_t)64U; + Hacl_Impl_Chacha20_Vec128_update(out0, block0, st); + Hacl_Impl_Chacha20_Vec128_state_incr(st); + Hacl_Impl_Chacha20_Vec128_update(out1, block1, st); + Hacl_Impl_Chacha20_Vec128_state_incr(st); + } else if (rest3 == (uint32_t)1U) { + Hacl_Impl_Chacha20_Vec128_update(outs, blocks1, st); + Hacl_Impl_Chacha20_Vec128_state_incr(st); + } +} + +static void +Hacl_Impl_Chacha20_Vec128_chacha20_counter_mode( + uint8_t *output, + uint8_t *plain, + uint32_t len, + vec *st) +{ + uint32_t blocks_len = len >> (uint32_t)6U; + uint32_t part_len = len & (uint32_t)0x3fU; + uint8_t *output_ = output; + uint8_t *plain_ = plain; + uint8_t *output__ = output + (uint32_t)64U * blocks_len; + uint8_t *plain__ = plain + (uint32_t)64U * blocks_len; + Hacl_Impl_Chacha20_Vec128_chacha20_counter_mode_blocks(output_, plain_, blocks_len, st); + if (part_len > (uint32_t)0U) + Hacl_Impl_Chacha20_Vec128_update_last(output__, plain__, part_len, st); +} + +static void +Hacl_Impl_Chacha20_Vec128_chacha20( + uint8_t *output, + uint8_t *plain, + uint32_t len, + uint8_t *k, + uint8_t *n1, + uint32_t ctr) +{ + KRML_CHECK_SIZE(vec_zero(), (uint32_t)4U); + vec buf[4U]; + for (uint32_t _i = 0U; _i < (uint32_t)4U; ++_i) + buf[_i] = vec_zero(); + vec *st = buf; + Hacl_Impl_Chacha20_Vec128_init(st, k, n1, ctr); + Hacl_Impl_Chacha20_Vec128_chacha20_counter_mode(output, plain, len, st); +} + +void +Hacl_Chacha20_Vec128_chacha20( + uint8_t *output, + uint8_t *plain, + uint32_t len, + uint8_t *k, + uint8_t *n1, + uint32_t ctr) +{ + Hacl_Impl_Chacha20_Vec128_chacha20(output, plain, len, k, n1, ctr); +} diff --git a/security/nss/lib/freebl/verified/Hacl_Chacha20_Vec128.h b/security/nss/lib/freebl/verified/Hacl_Chacha20_Vec128.h new file mode 100644 index 000000000..57942093d --- /dev/null +++ b/security/nss/lib/freebl/verified/Hacl_Chacha20_Vec128.h @@ -0,0 +1,61 @@ +/* Copyright 2016-2017 INRIA and Microsoft Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "kremlib.h" +#ifndef __Hacl_Chacha20_Vec128_H +#define __Hacl_Chacha20_Vec128_H + +#include "vec128.h" + +typedef uint32_t Hacl_Impl_Xor_Lemmas_u32; + +typedef uint8_t Hacl_Impl_Xor_Lemmas_u8; + +typedef uint32_t Hacl_Impl_Chacha20_Vec128_State_u32; + +typedef uint32_t Hacl_Impl_Chacha20_Vec128_State_h32; + +typedef uint8_t *Hacl_Impl_Chacha20_Vec128_State_uint8_p; + +typedef vec *Hacl_Impl_Chacha20_Vec128_State_state; + +typedef uint32_t Hacl_Impl_Chacha20_Vec128_u32; + +typedef uint32_t Hacl_Impl_Chacha20_Vec128_h32; + +typedef uint8_t *Hacl_Impl_Chacha20_Vec128_uint8_p; + +typedef uint32_t Hacl_Impl_Chacha20_Vec128_idx; + +typedef struct +{ + void *k; + void *n; + uint32_t ctr; +} Hacl_Impl_Chacha20_Vec128_log_t_; + +typedef void *Hacl_Impl_Chacha20_Vec128_log_t; + +typedef uint8_t *Hacl_Chacha20_Vec128_uint8_p; + +void +Hacl_Chacha20_Vec128_chacha20( + uint8_t *output, + uint8_t *plain, + uint32_t len, + uint8_t *k, + uint8_t *n1, + uint32_t ctr); +#endif diff --git a/security/nss/lib/freebl/verified/kremlib_base.h b/security/nss/lib/freebl/verified/kremlib_base.h index 61bac11d4..14170625d 100644 --- a/security/nss/lib/freebl/verified/kremlib_base.h +++ b/security/nss/lib/freebl/verified/kremlib_base.h @@ -17,6 +17,7 @@ #define __KREMLIB_BASE_H #include +#include #include #include #include diff --git a/security/nss/lib/freebl/verified/vec128.h b/security/nss/lib/freebl/verified/vec128.h new file mode 100644 index 000000000..986e9db82 --- /dev/null +++ b/security/nss/lib/freebl/verified/vec128.h @@ -0,0 +1,345 @@ +/* Copyright 2016-2017 INRIA and Microsoft Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __Vec_H +#define __Vec_H + +#ifdef __MSVC__ +#define forceinline __forceinline inline +#elif (defined(__GNUC__) || defined(__clang__)) +#define forceinline __attribute__((always_inline)) inline +#else +#define forceinline inline +#endif + +#if defined(__SSSE3__) || defined(__AVX2__) || defined(__AVX__) + +#include +#include + +#define VEC128 +#define vec_size 4 + +typedef __m128i vec; + +static forceinline vec +vec_rotate_left_8(vec v) +{ + __m128i x = _mm_set_epi8(14, 13, 12, 15, 10, 9, 8, 11, 6, 5, 4, 7, 2, 1, 0, 3); + return _mm_shuffle_epi8(v, x); +} + +static forceinline vec +vec_rotate_left_16(vec v) +{ + __m128i x = _mm_set_epi8(13, 12, 15, 14, 9, 8, 11, 10, 5, 4, 7, 6, 1, 0, 3, 2); + return _mm_shuffle_epi8(v, x); +} + +static forceinline vec +vec_rotate_left(vec v, unsigned int n) +{ + if (n == 8) + return vec_rotate_left_8(v); + if (n == 16) + return vec_rotate_left_16(v); + return _mm_xor_si128(_mm_slli_epi32(v, n), + _mm_srli_epi32(v, 32 - n)); +} + +static forceinline vec +vec_rotate_right(vec v, unsigned int n) +{ + return (vec_rotate_left(v, 32 - n)); +} + +#define vec_shuffle_right(x, n) \ + _mm_shuffle_epi32(x, _MM_SHUFFLE((3 + (n)) % 4, (2 + (n)) % 4, (1 + (n)) % 4, (n) % 4)) + +#define vec_shuffle_left(x, n) vec_shuffle_right((x), 4 - (n)) + +static forceinline vec +vec_load_32x4(uint32_t x1, uint32_t x2, uint32_t x3, uint32_t x4) +{ + return _mm_set_epi32(x4, x3, x2, x1); +} + +static forceinline vec +vec_load_32x8(uint32_t x1, uint32_t x2, uint32_t x3, uint32_t x4, uint32_t x5, uint32_t x6, uint32_t x7, uint32_t x8) +{ + return _mm_set_epi32(x4, x3, x2, x1); +} + +static forceinline vec +vec_load_le(const unsigned char* in) +{ + return _mm_loadu_si128((__m128i*)(in)); +} + +static forceinline vec +vec_load128_le(const unsigned char* in) +{ + return vec_load_le(in); +} + +static forceinline void +vec_store_le(unsigned char* out, vec v) +{ + _mm_storeu_si128((__m128i*)(out), v); +} + +static forceinline vec +vec_add(vec v1, vec v2) +{ + return _mm_add_epi32(v1, v2); +} + +static forceinline vec +vec_add_u32(vec v1, uint32_t x) +{ + vec v2 = vec_load_32x4(x, 0, 0, 0); + return _mm_add_epi32(v1, v2); +} + +static forceinline vec +vec_increment(vec v1) +{ + vec one = vec_load_32x4(1, 0, 0, 0); + return _mm_add_epi32(v1, one); +} + +static forceinline vec +vec_xor(vec v1, vec v2) +{ + return _mm_xor_si128(v1, v2); +} + +#define vec_zero() _mm_set_epi32(0, 0, 0, 0) + +#elif defined(__ARM_NEON__) || defined(__ARM_NEON) +#include + +typedef uint32x4_t vec; + +static forceinline vec +vec_xor(vec v1, vec v2) +{ + return veorq_u32(v1, v2); +} + +#define vec_rotate_left(x, n) \ + vsriq_n_u32(vshlq_n_u32((x), (n)), (x), 32 - (n)) + +#define vec_rotate_right(a, b) \ + vec_rotate_left((b), 32 - (b)) + +#define vec_shuffle_right(x, n) \ + vextq_u32((x), (x), (n)) + +#define vec_shuffle_left(a, b) \ + vec_shuffle_right((a), 4 - (b)) + +static forceinline vec +vec_load_32x4(uint32_t x1, uint32_t x2, uint32_t x3, uint32_t x4) +{ + uint32_t a[4] = { x1, x2, x3, x4 }; + return vld1q_u32(a); +} + +static forceinline vec +vec_load_32(uint32_t x1) +{ + uint32_t a[4] = { x1, x1, x1, x1 }; + return vld1q_u32(a); +} + +static forceinline vec +vec_load_32x8(uint32_t x1, uint32_t x2, uint32_t x3, uint32_t x4, uint32_t x5, uint32_t x6, uint32_t x7, uint32_t x8) +{ + return vec_load_32x4(x1, x2, x3, x4); +} + +static forceinline vec +vec_load_le(const unsigned char* in) +{ + return vld1q_u32((uint32_t*)in); +} + +static forceinline vec +vec_load128_le(const unsigned char* in) +{ + return vec_load_le(in); +} + +static forceinline void +vec_store_le(unsigned char* out, vec v) +{ + vst1q_u32((uint32_t*)out, v); +} + +static forceinline vec +vec_add(vec v1, vec v2) +{ + return vaddq_u32(v1, v2); +} + +static forceinline vec +vec_add_u32(vec v1, uint32_t x) +{ + vec v2 = vec_load_32x4(x, 0, 0, 0); + return vec_add(v1, v2); +} + +static forceinline vec +vec_increment(vec v1) +{ + vec one = vec_load_32x4(1, 0, 0, 0); + return vec_add(v1, one); +} + +#define vec_zero() vec_load_32x4(0, 0, 0, 0) + +#else + +#define VEC128 +#define vec_size 4 + +typedef struct { + uint32_t v[4]; +} vec; + +static forceinline vec +vec_xor(vec v1, vec v2) +{ + vec r; + r.v[0] = v1.v[0] ^ v2.v[0]; + r.v[1] = v1.v[1] ^ v2.v[1]; + r.v[2] = v1.v[2] ^ v2.v[2]; + r.v[3] = v1.v[3] ^ v2.v[3]; + return r; +} + +static forceinline vec +vec_rotate_left(vec v, unsigned int n) +{ + vec r; + r.v[0] = (v.v[0] << n) ^ (v.v[0] >> (32 - n)); + r.v[1] = (v.v[1] << n) ^ (v.v[1] >> (32 - n)); + r.v[2] = (v.v[2] << n) ^ (v.v[2] >> (32 - n)); + r.v[3] = (v.v[3] << n) ^ (v.v[3] >> (32 - n)); + return r; +} + +static forceinline vec +vec_rotate_right(vec v, unsigned int n) +{ + return (vec_rotate_left(v, 32 - n)); +} + +static forceinline vec +vec_shuffle_right(vec v, unsigned int n) +{ + vec r; + r.v[0] = v.v[n % 4]; + r.v[1] = v.v[(n + 1) % 4]; + r.v[2] = v.v[(n + 2) % 4]; + r.v[3] = v.v[(n + 3) % 4]; + return r; +} + +static forceinline vec +vec_shuffle_left(vec x, unsigned int n) +{ + return vec_shuffle_right(x, 4 - n); +} + +static forceinline vec +vec_load_32x4(uint32_t x0, uint32_t x1, uint32_t x2, uint32_t x3) +{ + vec v; + v.v[0] = x0; + v.v[1] = x1; + v.v[2] = x2; + v.v[3] = x3; + return v; +} + +static forceinline vec +vec_load_32(uint32_t x0) +{ + vec v; + v.v[0] = x0; + v.v[1] = x0; + v.v[2] = x0; + v.v[3] = x0; + return v; +} + +static forceinline vec +vec_load_le(const uint8_t* in) +{ + vec r; + r.v[0] = load32_le((uint8_t*)in); + r.v[1] = load32_le((uint8_t*)in + 4); + r.v[2] = load32_le((uint8_t*)in + 8); + r.v[3] = load32_le((uint8_t*)in + 12); + return r; +} + +static forceinline void +vec_store_le(unsigned char* out, vec r) +{ + store32_le(out, r.v[0]); + store32_le(out + 4, r.v[1]); + store32_le(out + 8, r.v[2]); + store32_le(out + 12, r.v[3]); +} + +static forceinline vec +vec_load128_le(const unsigned char* in) +{ + return vec_load_le(in); +} + +static forceinline vec +vec_add(vec v1, vec v2) +{ + vec r; + r.v[0] = v1.v[0] + v2.v[0]; + r.v[1] = v1.v[1] + v2.v[1]; + r.v[2] = v1.v[2] + v2.v[2]; + r.v[3] = v1.v[3] + v2.v[3]; + return r; +} + +static forceinline vec +vec_add_u32(vec v1, uint32_t x) +{ + vec v2 = vec_load_32x4(x, 0, 0, 0); + return vec_add(v1, v2); +} + +static forceinline vec +vec_increment(vec v1) +{ + vec one = vec_load_32x4(1, 0, 0, 0); + return vec_add(v1, one); +} + +#define vec_zero() vec_load_32x4(0, 0, 0, 0) + +#endif + +#endif diff --git a/security/nss/lib/nss/nss.h b/security/nss/lib/nss/nss.h index 62cf36730..d62f4957b 100644 --- a/security/nss/lib/nss/nss.h +++ b/security/nss/lib/nss/nss.h @@ -22,10 +22,10 @@ * The format of the version string should be * ".[.[.]][ ][ ]" */ -#define NSS_VERSION "3.35" _NSS_CUSTOMIZED +#define NSS_VERSION "3.36.4" _NSS_CUSTOMIZED #define NSS_VMAJOR 3 -#define NSS_VMINOR 35 -#define NSS_VPATCH 0 +#define NSS_VMINOR 36 +#define NSS_VPATCH 4 #define NSS_VBUILD 0 #define NSS_BETA PR_FALSE diff --git a/security/nss/lib/pk11wrap/dev3hack.c b/security/nss/lib/pk11wrap/dev3hack.c index 39afd6743..3fb0cb0aa 100644 --- a/security/nss/lib/pk11wrap/dev3hack.c +++ b/security/nss/lib/pk11wrap/dev3hack.c @@ -120,6 +120,10 @@ nssSlot_CreateFromPK11SlotInfo(NSSTrustDomain *td, PK11SlotInfo *nss3slot) /* Grab the slot name from the PKCS#11 fixed-length buffer */ rvSlot->base.name = nssUTF8_Duplicate(nss3slot->slot_name, td->arena); rvSlot->lock = (nss3slot->isThreadSafe) ? NULL : nss3slot->sessionLock; + rvSlot->isPresentLock = PZ_NewLock(nssiLockOther); + rvSlot->isPresentCondition = PR_NewCondVar(rvSlot->isPresentLock); + rvSlot->isPresentThread = NULL; + rvSlot->lastTokenPingState = nssSlotLastPingState_Reset; return rvSlot; } diff --git a/security/nss/lib/pk11wrap/pk11auth.c b/security/nss/lib/pk11wrap/pk11auth.c index 625fa2dc6..6a3ba40d9 100644 --- a/security/nss/lib/pk11wrap/pk11auth.c +++ b/security/nss/lib/pk11wrap/pk11auth.c @@ -636,7 +636,7 @@ PK11_DoPassword(PK11SlotInfo *slot, CK_SESSION_HANDLE session, break; } if (rv == SECSuccess) { - if (!PK11_IsFriendly(slot)) { + if (!contextSpecific && !PK11_IsFriendly(slot)) { nssTrustDomain_UpdateCachedTokenCerts(slot->nssToken->trustDomain, slot->nssToken); } diff --git a/security/nss/lib/pk11wrap/secmodi.h b/security/nss/lib/pk11wrap/secmodi.h index 1225661ad..84f5f2a30 100644 --- a/security/nss/lib/pk11wrap/secmodi.h +++ b/security/nss/lib/pk11wrap/secmodi.h @@ -164,6 +164,7 @@ CERTCertificate *PK11_MakeCertFromHandle(PK11SlotInfo *slot, SECItem *pk11_GenerateNewParamWithKeyLen(CK_MECHANISM_TYPE type, int keyLen); SECItem *pk11_ParamFromIVWithLen(CK_MECHANISM_TYPE type, SECItem *iv, int keyLen); +SECItem *pk11_mkcertKeyID(CERTCertificate *cert); SEC_END_PROTOS diff --git a/security/nss/lib/pkcs12/p12d.c b/security/nss/lib/pkcs12/p12d.c index dfe7015df..34362db2d 100644 --- a/security/nss/lib/pkcs12/p12d.c +++ b/security/nss/lib/pkcs12/p12d.c @@ -813,6 +813,7 @@ sec_pkcs12_decoder_asafes_notify(void *arg, PRBool before, void *dest, unsigned int cnt = p12dcx->safeContentsCnt - 1; safeContentsCtx = p12dcx->safeContentsList[cnt]; if (safeContentsCtx->safeContentsA1Dcx) { + SEC_ASN1DecoderClearFilterProc(p12dcx->aSafeA1Dcx); SEC_ASN1DecoderFinish(safeContentsCtx->safeContentsA1Dcx); safeContentsCtx->safeContentsA1Dcx = NULL; } diff --git a/security/nss/lib/pkcs7/p7create.c b/security/nss/lib/pkcs7/p7create.c index a79d5aa26..f19330386 100644 --- a/security/nss/lib/pkcs7/p7create.c +++ b/security/nss/lib/pkcs7/p7create.c @@ -22,7 +22,7 @@ const int NSS_PBE_DEFAULT_ITERATION_COUNT = /* used in p12e.c too */ #ifdef DEBUG 10000 #else - 1000000 + 600000 #endif ; diff --git a/security/nss/lib/pkcs7/p7decode.c b/security/nss/lib/pkcs7/p7decode.c index 658c61e44..4f17b8e84 100644 --- a/security/nss/lib/pkcs7/p7decode.c +++ b/security/nss/lib/pkcs7/p7decode.c @@ -560,6 +560,7 @@ sec_pkcs7_decoder_start_decrypt(SEC_PKCS7DecoderContext *p7dcx, int depth, return SECSuccess; no_decryption: + PK11_FreeSymKey(bulkkey); /* * For some reason (error set already, if appropriate), we cannot * decrypt the content. I am not sure what exactly is the right @@ -1031,6 +1032,11 @@ SECStatus SEC_PKCS7DecoderUpdate(SEC_PKCS7DecoderContext *p7dcx, const char *buf, unsigned long len) { + if (!p7dcx) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + if (p7dcx->cinfo != NULL && p7dcx->dcx != NULL) { PORT_Assert(p7dcx->error == 0); if (p7dcx->error == 0) { diff --git a/security/nss/lib/pki/pkibase.c b/security/nss/lib/pki/pkibase.c index 4082a37bd..f58a262cf 100644 --- a/security/nss/lib/pki/pkibase.c +++ b/security/nss/lib/pki/pkibase.c @@ -923,9 +923,11 @@ nssPKIObjectCollection_AddInstanceAsObject( return PR_FAILURE; } if (!node->haveObject) { + nssPKIObject *original = node->object; node->object = (*collection->createObject)(node->object); if (!node->object) { /*remove bogus object from list*/ + nssPKIObject_Destroy(original); nssPKIObjectCollection_RemoveNode(collection, node); return PR_FAILURE; } diff --git a/security/nss/lib/softoken/softkver.h b/security/nss/lib/softoken/softkver.h index 9fd99a8e0..f760ba21d 100644 --- a/security/nss/lib/softoken/softkver.h +++ b/security/nss/lib/softoken/softkver.h @@ -17,10 +17,10 @@ * The format of the version string should be * ".[.[.]][ ][ ]" */ -#define SOFTOKEN_VERSION "3.35" SOFTOKEN_ECC_STRING +#define SOFTOKEN_VERSION "3.36.4" SOFTOKEN_ECC_STRING #define SOFTOKEN_VMAJOR 3 -#define SOFTOKEN_VMINOR 35 -#define SOFTOKEN_VPATCH 0 +#define SOFTOKEN_VMINOR 36 +#define SOFTOKEN_VPATCH 4 #define SOFTOKEN_VBUILD 0 #define SOFTOKEN_BETA PR_FALSE diff --git a/security/nss/lib/ssl/SSLerrs.h b/security/nss/lib/ssl/SSLerrs.h index c95fe661a..d3f087544 100644 --- a/security/nss/lib/ssl/SSLerrs.h +++ b/security/nss/lib/ssl/SSLerrs.h @@ -540,3 +540,6 @@ ER3(SSL_ERROR_RX_MALFORMED_KEY_UPDATE, (SSL_ERROR_BASE + 170), ER3(SSL_ERROR_TOO_MANY_KEY_UPDATES, (SSL_ERROR_BASE + 171), "SSL attempted too many key updates.") + +ER3(SSL_ERROR_HANDSHAKE_FAILED, (SSL_ERROR_BASE + 172), + "SSL handshake has already failed. No more operations possible.") diff --git a/security/nss/lib/ssl/selfencrypt.c b/security/nss/lib/ssl/selfencrypt.c index 97217b4a6..1c70f7635 100644 --- a/security/nss/lib/ssl/selfencrypt.c +++ b/security/nss/lib/ssl/selfencrypt.c @@ -192,75 +192,71 @@ ssl_SelfEncryptUnprotectInt( const PRUint8 *in, unsigned int inLen, PRUint8 *out, unsigned int *outLen, unsigned int maxOutLen) { - unsigned char *encodedKeyName; - unsigned char *iv; - SECItem ivItem = { siBuffer, NULL, 0 }; - SECItem inItem = { siBuffer, (unsigned char *)in, inLen }; - unsigned char *cipherText; - PRUint32 cipherTextLen; - unsigned char *encodedMac; - unsigned char computedMac[SHA256_LENGTH]; - unsigned int computedMacLen; - unsigned int bytesToMac; - SECStatus rv; + sslReader reader = SSL_READER(in, inLen); - rv = ssl3_ConsumeFromItem(&inItem, &encodedKeyName, - SELF_ENCRYPT_KEY_NAME_LEN); + sslReadBuffer encodedKeyNameBuffer = { 0 }; + SECStatus rv = sslRead_Read(&reader, SELF_ENCRYPT_KEY_NAME_LEN, + &encodedKeyNameBuffer); if (rv != SECSuccess) { return SECFailure; } - rv = ssl3_ConsumeFromItem(&inItem, &iv, AES_BLOCK_SIZE); + sslReadBuffer ivBuffer = { 0 }; + rv = sslRead_Read(&reader, AES_BLOCK_SIZE, &ivBuffer); if (rv != SECSuccess) { return SECFailure; } - rv = ssl3_ConsumeNumberFromItem(&inItem, &cipherTextLen, 2); + PRUint64 cipherTextLen = 0; + rv = sslRead_ReadNumber(&reader, 2, &cipherTextLen); if (rv != SECSuccess) { return SECFailure; } - rv = ssl3_ConsumeFromItem(&inItem, &cipherText, cipherTextLen); + sslReadBuffer cipherTextBuffer = { 0 }; + rv = sslRead_Read(&reader, (unsigned int)cipherTextLen, &cipherTextBuffer); if (rv != SECSuccess) { return SECFailure; } - bytesToMac = inItem.data - in; + unsigned int bytesToMac = reader.offset; - rv = ssl3_ConsumeFromItem(&inItem, &encodedMac, SHA256_LENGTH); + sslReadBuffer encodedMacBuffer = { 0 }; + rv = sslRead_Read(&reader, SHA256_LENGTH, &encodedMacBuffer); if (rv != SECSuccess) { return SECFailure; } /* Make sure we're at the end of the block. */ - if (inItem.len) { + if (reader.offset != reader.buf.len) { PORT_SetError(SEC_ERROR_BAD_DATA); return SECFailure; } /* Now that everything is decoded, we can make progress. */ /* 1. Check that we have the right key. */ - if (PORT_Memcmp(keyName, encodedKeyName, SELF_ENCRYPT_KEY_NAME_LEN)) { + if (PORT_Memcmp(keyName, encodedKeyNameBuffer.buf, SELF_ENCRYPT_KEY_NAME_LEN)) { PORT_SetError(SEC_ERROR_NOT_A_RECIPIENT); return SECFailure; } /* 2. Check the MAC */ + unsigned char computedMac[SHA256_LENGTH]; + unsigned int computedMacLen = 0; rv = ssl_MacBuffer(macKey, CKM_SHA256_HMAC, in, bytesToMac, computedMac, &computedMacLen, sizeof(computedMac)); if (rv != SECSuccess) { return SECFailure; } PORT_Assert(computedMacLen == SHA256_LENGTH); - if (NSS_SecureMemcmp(computedMac, encodedMac, computedMacLen) != 0) { + if (NSS_SecureMemcmp(computedMac, encodedMacBuffer.buf, computedMacLen) != 0) { PORT_SetError(SEC_ERROR_BAD_DATA); return SECFailure; } /* 3. OK, it verifies, now decrypt. */ - ivItem.data = iv; - ivItem.len = AES_BLOCK_SIZE; + SECItem ivItem = { siBuffer, (unsigned char *)ivBuffer.buf, AES_BLOCK_SIZE }; rv = PK11_Decrypt(encKey, CKM_AES_CBC_PAD, &ivItem, - out, outLen, maxOutLen, cipherText, cipherTextLen); + out, outLen, maxOutLen, cipherTextBuffer.buf, cipherTextLen); if (rv != SECSuccess) { return SECFailure; } diff --git a/security/nss/lib/ssl/ssl3con.c b/security/nss/lib/ssl/ssl3con.c index 61878ae99..2593bbacc 100644 --- a/security/nss/lib/ssl/ssl3con.c +++ b/security/nss/lib/ssl/ssl3con.c @@ -183,9 +183,9 @@ static const SSLSignatureScheme defaultSignatureSchemes[] = { ssl_sig_ecdsa_secp384r1_sha384, ssl_sig_ecdsa_secp521r1_sha512, ssl_sig_ecdsa_sha1, - ssl_sig_rsa_pss_sha256, - ssl_sig_rsa_pss_sha384, - ssl_sig_rsa_pss_sha512, + ssl_sig_rsa_pss_rsae_sha256, + ssl_sig_rsa_pss_rsae_sha384, + ssl_sig_rsa_pss_rsae_sha512, ssl_sig_rsa_pkcs1_sha256, ssl_sig_rsa_pkcs1_sha384, ssl_sig_rsa_pkcs1_sha512, @@ -852,7 +852,7 @@ ssl3_config_match_init(sslSocket *ss) * enabled, has a certificate (as needed), has a viable key agreement method, is * usable with the negotiated TLS version, and is otherwise usable. */ static PRBool -config_match(const ssl3CipherSuiteCfg *suite, int policy, +config_match(const ssl3CipherSuiteCfg *suite, PRUint8 policy, const SSLVersionRange *vrange, const sslSocket *ss) { const ssl3CipherSuiteDef *cipher_def; @@ -888,7 +888,7 @@ config_match(const ssl3CipherSuiteCfg *suite, int policy, /* Return the number of cipher suites that are usable. */ /* called from ssl3_SendClientHello */ static unsigned int -count_cipher_suites(sslSocket *ss, int policy) +count_cipher_suites(sslSocket *ss, PRUint8 policy) { unsigned int i, count = 0; @@ -2336,6 +2336,11 @@ ssl3_SendRecord(sslSocket *ss, if (ss->ssl3.fatalAlertSent) { SSL_TRC(3, ("%d: SSL3[%d] Suppress write, fatal alert already sent", SSL_GETPID(), ss->fd)); + if (type != content_alert) { + /* If we are sending an alert, then we already have an + * error, so don't overwrite. */ + PORT_SetError(SSL_ERROR_HANDSHAKE_FAILED); + } return SECFailure; } @@ -2647,9 +2652,7 @@ ssl3_HandleNoCertificate(sslSocket *ss) (ss->opt.requireCertificate == SSL_REQUIRE_FIRST_HANDSHAKE))) { PRFileDesc *lower; - if (!ss->opt.noCache) { - ss->sec.uncache(ss->sec.ci.sid); - } + ssl_UncacheSessionID(ss); SSL3_SendAlert(ss, alert_fatal, bad_certificate); lower = ss->fd->lower; @@ -2711,8 +2714,8 @@ SSL3_SendAlert(sslSocket *ss, SSL3AlertLevel level, SSL3AlertDescription desc) ssl_GetSSL3HandshakeLock(ss); } if (level == alert_fatal) { - if (!ss->opt.noCache && ss->sec.ci.sid) { - ss->sec.uncache(ss->sec.ci.sid); + if (ss->sec.ci.sid) { + ssl_UncacheSessionID(ss); } } @@ -2976,9 +2979,7 @@ ssl3_HandleAlert(sslSocket *ss, sslBuffer *buf) } } if (level == alert_fatal) { - if (!ss->opt.noCache) { - ss->sec.uncache(ss->sec.ci.sid); - } + ssl_UncacheSessionID(ss); if ((ss->ssl3.hs.ws == wait_server_hello) && (desc == handshake_failure)) { /* XXX This is a hack. We're assuming that any handshake failure @@ -3962,17 +3963,20 @@ ssl_SignatureSchemeToHashType(SSLSignatureScheme scheme) return ssl_hash_sha1; case ssl_sig_rsa_pkcs1_sha256: case ssl_sig_ecdsa_secp256r1_sha256: - case ssl_sig_rsa_pss_sha256: + case ssl_sig_rsa_pss_rsae_sha256: + case ssl_sig_rsa_pss_pss_sha256: case ssl_sig_dsa_sha256: return ssl_hash_sha256; case ssl_sig_rsa_pkcs1_sha384: case ssl_sig_ecdsa_secp384r1_sha384: - case ssl_sig_rsa_pss_sha384: + case ssl_sig_rsa_pss_rsae_sha384: + case ssl_sig_rsa_pss_pss_sha384: case ssl_sig_dsa_sha384: return ssl_hash_sha384; case ssl_sig_rsa_pkcs1_sha512: case ssl_sig_ecdsa_secp521r1_sha512: - case ssl_sig_rsa_pss_sha512: + case ssl_sig_rsa_pss_rsae_sha512: + case ssl_sig_rsa_pss_pss_sha512: case ssl_sig_dsa_sha512: return ssl_hash_sha512; case ssl_sig_rsa_pkcs1_sha1md5: @@ -3994,9 +3998,12 @@ ssl_SignatureSchemeToKeyType(SSLSignatureScheme scheme) case ssl_sig_rsa_pkcs1_sha384: case ssl_sig_rsa_pkcs1_sha512: case ssl_sig_rsa_pkcs1_sha1: - case ssl_sig_rsa_pss_sha256: - case ssl_sig_rsa_pss_sha384: - case ssl_sig_rsa_pss_sha512: + case ssl_sig_rsa_pss_rsae_sha256: + case ssl_sig_rsa_pss_rsae_sha384: + case ssl_sig_rsa_pss_rsae_sha512: + case ssl_sig_rsa_pss_pss_sha256: + case ssl_sig_rsa_pss_pss_sha384: + case ssl_sig_rsa_pss_pss_sha512: case ssl_sig_rsa_pkcs1_sha1md5: return rsaKey; case ssl_sig_ecdsa_secp256r1_sha256: @@ -4131,9 +4138,9 @@ ssl_IsSupportedSignatureScheme(SSLSignatureScheme scheme) case ssl_sig_rsa_pkcs1_sha256: case ssl_sig_rsa_pkcs1_sha384: case ssl_sig_rsa_pkcs1_sha512: - case ssl_sig_rsa_pss_sha256: - case ssl_sig_rsa_pss_sha384: - case ssl_sig_rsa_pss_sha512: + case ssl_sig_rsa_pss_rsae_sha256: + case ssl_sig_rsa_pss_rsae_sha384: + case ssl_sig_rsa_pss_rsae_sha512: case ssl_sig_ecdsa_secp256r1_sha256: case ssl_sig_ecdsa_secp384r1_sha384: case ssl_sig_ecdsa_secp521r1_sha512: @@ -4145,6 +4152,9 @@ ssl_IsSupportedSignatureScheme(SSLSignatureScheme scheme) return PR_TRUE; case ssl_sig_rsa_pkcs1_sha1md5: + case ssl_sig_rsa_pss_pss_sha256: + case ssl_sig_rsa_pss_pss_sha384: + case ssl_sig_rsa_pss_pss_sha512: case ssl_sig_none: case ssl_sig_ed25519: case ssl_sig_ed448: @@ -4157,9 +4167,9 @@ PRBool ssl_IsRsaPssSignatureScheme(SSLSignatureScheme scheme) { switch (scheme) { - case ssl_sig_rsa_pss_sha256: - case ssl_sig_rsa_pss_sha384: - case ssl_sig_rsa_pss_sha512: + case ssl_sig_rsa_pss_rsae_sha256: + case ssl_sig_rsa_pss_rsae_sha384: + case ssl_sig_rsa_pss_rsae_sha512: return PR_TRUE; default: @@ -4262,6 +4272,7 @@ ssl3_ComputeHandshakeHashes(sslSocket *ss, sizeof(stackBuf), &stateLen); if (stateBuf == NULL) { ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE); + rv = SECFailure; goto tls12_loser; } rv |= PK11_DigestFinal(h, hashes->u.raw, &hashes->len, @@ -4273,7 +4284,6 @@ ssl3_ComputeHandshakeHashes(sslSocket *ss, } hashes->hashAlg = ssl3_GetSuitePrfHash(ss); - rv = SECSuccess; tls12_loser: if (stateBuf) { @@ -4305,6 +4315,7 @@ ssl3_ComputeHandshakeHashes(sslSocket *ss, sizeof md5StackBuf, &md5StateLen); if (md5StateBuf == NULL) { ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE); + rv = SECFailure; goto loser; } md5 = ss->ssl3.hs.md5; @@ -4313,6 +4324,7 @@ ssl3_ComputeHandshakeHashes(sslSocket *ss, sizeof shaStackBuf, &shaStateLen); if (shaStateBuf == NULL) { ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE); + rv = SECFailure; goto loser; } sha = ss->ssl3.hs.sha; @@ -4408,7 +4420,6 @@ ssl3_ComputeHandshakeHashes(sslSocket *ss, PRINT_BUF(60, (NULL, "SHA outer: result", hashes->u.s.sha, SHA1_LENGTH)); hashes->len = MD5_LENGTH + SHA1_LENGTH; - rv = SECSuccess; loser: if (md5StateBuf) { @@ -4589,13 +4600,24 @@ ssl3_SendClientHello(sslSocket *ss, sslClientHelloType type) } } - /* We ignore ss->sec.ci.sid here, and use ssl_Lookup because Lookup - * handles expired entries and other details. - * XXX If we've been called from ssl_BeginClientHandshake, then - * this lookup is duplicative and wasteful. - */ - sid = (ss->opt.noCache) ? NULL - : ssl_LookupSID(&ss->sec.ci.peer, ss->sec.ci.port, ss->peerID, ss->url); + /* Check if we have a ss->sec.ci.sid. + * Check that it's not expired. + * If we have an sid and it comes from an external cache, we use it. */ + if (ss->sec.ci.sid && ss->sec.ci.sid->cached == in_external_cache) { + PORT_Assert(!ss->sec.isServer); + sid = ss->sec.ci.sid; + SSL_TRC(3, ("%d: SSL3[%d]: using external resumption token in ClientHello", + SSL_GETPID(), ss->fd)); + } else if (!ss->opt.noCache) { + /* We ignore ss->sec.ci.sid here, and use ssl_Lookup because Lookup + * handles expired entries and other details. + * XXX If we've been called from ssl_BeginClientHandshake, then + * this lookup is duplicative and wasteful. + */ + sid = ssl_LookupSID(&ss->sec.ci.peer, ss->sec.ci.port, ss->peerID, ss->url); + } else { + sid = NULL; + } /* We can't resume based on a different token. If the sid exists, * make sure the token that holds the master secret still exists ... @@ -4686,7 +4708,7 @@ ssl3_SendClientHello(sslSocket *ss, sslClientHelloType type) if (!sidOK) { SSL_AtomicIncrementLong(&ssl3stats.sch_sid_cache_not_ok); - ss->sec.uncache(sid); + ssl_UncacheSessionID(ss); ssl_FreeSID(sid); sid = NULL; } @@ -5017,7 +5039,7 @@ ssl3_HandleHelloRequest(sslSocket *ss) } if (sid) { - ss->sec.uncache(sid); + ssl_UncacheSessionID(ss); ssl_FreeSID(sid); ss->sec.ci.sid = NULL; } @@ -6130,6 +6152,48 @@ ssl_ClientSetCipherSuite(sslSocket *ss, SSL3ProtocolVersion version, return ssl3_SetupCipherSuite(ss, initHashes); } +/* Check that session ID we received from the server, if any, matches our + * expectations, depending on whether we're in compat mode and whether we + * negotiated TLS 1.3+ or TLS 1.2-. + */ +static PRBool +ssl_CheckServerSessionIdCorrectness(sslSocket *ss, SECItem *sidBytes) +{ + sslSessionID *sid = ss->sec.ci.sid; + PRBool sidMatch = PR_FALSE; + PRBool sentFakeSid = PR_FALSE; + PRBool sentRealSid = sid && sid->version < SSL_LIBRARY_VERSION_TLS_1_3; + + /* If attempting to resume a TLS 1.2 connection, the session ID won't be a + * fake. Check for the real value. */ + if (sentRealSid) { + sidMatch = (sidBytes->len == sid->u.ssl3.sessionIDLength) && + PORT_Memcmp(sid->u.ssl3.sessionID, sidBytes->data, sidBytes->len) == 0; + } else { + /* Otherwise, the session ID was a fake if TLS 1.3 compat mode is + * enabled. If so, check for the fake value. */ + sentFakeSid = ss->opt.enableTls13CompatMode && !IS_DTLS(ss); + if (sentFakeSid && sidBytes->len == SSL3_SESSIONID_BYTES) { + PRUint8 buf[SSL3_SESSIONID_BYTES]; + ssl_MakeFakeSid(ss, buf); + sidMatch = PORT_Memcmp(buf, sidBytes->data, sidBytes->len) == 0; + } + } + + /* TLS 1.2: Session ID shouldn't match if we sent a fake. */ + if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) { + return !sentFakeSid || !sidMatch; + } + + /* TLS 1.3: We sent a session ID. The server's should match. */ + if (sentRealSid || sentFakeSid) { + return sidMatch; + } + + /* TLS 1.3: The server shouldn't send a session ID. */ + return sidBytes->len == 0; +} + /* Called from ssl3_HandleHandshakeMessage() when it has deciphered a complete * ssl3 ServerHello message. * Caller must hold Handshake and RecvBuf locks. @@ -6337,22 +6401,10 @@ ssl3_HandleServerHello(sslSocket *ss, PRUint8 *b, PRUint32 length) } /* Check that the session ID is as expected. */ - if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_3) { - PRUint8 buf[SSL3_SESSIONID_BYTES]; - unsigned int expectedSidLen; - if (ss->opt.enableTls13CompatMode && !IS_DTLS(ss)) { - expectedSidLen = SSL3_SESSIONID_BYTES; - ssl_MakeFakeSid(ss, buf); - } else { - expectedSidLen = 0; - } - if (sidBytes.len != expectedSidLen || - (expectedSidLen > 0 && - PORT_Memcmp(buf, sidBytes.data, expectedSidLen) != 0)) { - desc = illegal_parameter; - errCode = SSL_ERROR_RX_MALFORMED_SERVER_HELLO; - goto alert_loser; - } + if (!ssl_CheckServerSessionIdCorrectness(ss, &sidBytes)) { + desc = illegal_parameter; + errCode = SSL_ERROR_RX_MALFORMED_SERVER_HELLO; + goto alert_loser; } /* Only initialize hashes if this isn't a Hello Retry. */ @@ -6592,7 +6644,7 @@ ssl3_HandleServerHelloPart2(sslSocket *ss, const SECItem *sidBytes, /* throw the old one away */ sid->u.ssl3.keys.resumable = PR_FALSE; - ss->sec.uncache(sid); + ssl_UncacheSessionID(ss); ssl_FreeSID(sid); /* get a new sid */ @@ -7502,8 +7554,6 @@ ssl3_NewSessionID(sslSocket *ss, PRBool is_server) sid->u.ssl3.keys.resumable = PR_TRUE; sid->u.ssl3.policy = SSL_ALLOWED; - sid->u.ssl3.clientWriteKey = NULL; - sid->u.ssl3.serverWriteKey = NULL; sid->u.ssl3.keys.extendedMasterSecretUsed = PR_FALSE; if (is_server) { @@ -8102,6 +8152,9 @@ ssl3_HandleClientHello(sslSocket *ss, PRUint8 *b, PRUint32 length) rv = ssl3_HandleParsedExtensions(ss, ssl_hs_client_hello); ssl3_DestroyRemoteExtensions(&ss->ssl3.hs.remoteExtensions); if (rv != SECSuccess) { + if (PORT_GetError() == SSL_ERROR_UNSUPPORTED_SIGNATURE_ALGORITHM) { + errCode = SSL_ERROR_UNSUPPORTED_SIGNATURE_ALGORITHM; + } goto loser; /* malformed */ } @@ -8229,7 +8282,7 @@ ssl3_HandleClientHello(sslSocket *ss, PRUint8 *b, PRUint32 length) !ss->firstHsDone))) { SSL_AtomicIncrementLong(&ssl3stats.hch_sid_cache_not_ok); - ss->sec.uncache(sid); + ssl_UncacheSessionID(ss); ssl_FreeSID(sid); sid = NULL; } @@ -8435,7 +8488,7 @@ cipher_found: } if (ss->sec.ci.sid) { - ss->sec.uncache(ss->sec.ci.sid); + ssl_UncacheSessionID(ss); PORT_Assert(ss->sec.ci.sid != sid); /* should be impossible, but ... */ if (ss->sec.ci.sid != sid) { ssl_FreeSID(ss->sec.ci.sid); @@ -8531,7 +8584,7 @@ cipher_found: if (sid) { /* we had a sid, but it's no longer valid, free it */ ss->statelessResume = PR_FALSE; SSL_AtomicIncrementLong(&ssl3stats.hch_sid_cache_not_ok); - ss->sec.uncache(sid); + ssl_UncacheSessionID(ss); ssl_FreeSID(sid); sid = NULL; } @@ -8597,7 +8650,7 @@ alert_loser: /* FALLTHRU */ loser: if (sid && sid != ss->sec.ci.sid) { - ss->sec.uncache(sid); + ssl_UncacheSessionID(ss); ssl_FreeSID(sid); } @@ -11137,6 +11190,7 @@ ssl3_FillInCachedSID(sslSocket *ss, sslSessionID *sid, PK11SymKey *secret) if (ss->xtnData.nextProtoState != SSL_NEXT_PROTO_NO_SUPPORT && ss->xtnData.nextProto.data) { + SECITEM_FreeItem(&sid->u.ssl3.alpnSelection, PR_FALSE); if (SECITEM_CopyItem( NULL, &sid->u.ssl3.alpnSelection, &ss->xtnData.nextProto) != SECSuccess) { return SECFailure; /* error already set. */ @@ -11166,7 +11220,7 @@ ssl3_FinishHandshake(sslSocket *ss) * the handshake is finished (we have verified the server's Finished * AND the server's certificate) before we update the ticket in the sid. * - * This must be done before we call ss->sec.cache(ss->sec.ci.sid) + * This must be done before we call ssl_CacheSessionID(ss) * because CacheSID requires the session ticket to already be set, and also * because of the lazy lock creation scheme used by CacheSID and * ssl3_SetSIDSessionTicket. @@ -11181,7 +11235,7 @@ ssl3_FinishHandshake(sslSocket *ss) if (ss->ssl3.hs.cacheSID) { PORT_Assert(ss->sec.ci.sid->cached == never_cached); - ss->sec.cache(ss->sec.ci.sid); + ssl_CacheSessionID(ss); ss->ssl3.hs.cacheSID = PR_FALSE; } @@ -12645,8 +12699,8 @@ ssl3_RedoHandshake(sslSocket *ss, PRBool flushCache) } if (sid && flushCache) { - ss->sec.uncache(sid); /* remove it from whichever cache it's in. */ - ssl_FreeSID(sid); /* dec ref count and free if zero. */ + ssl_UncacheSessionID(ss); /* remove it from whichever cache it's in. */ + ssl_FreeSID(sid); /* dec ref count and free if zero. */ ss->sec.ci.sid = NULL; } diff --git a/security/nss/lib/ssl/ssl3encode.c b/security/nss/lib/ssl/ssl3encode.c deleted file mode 100644 index 960208a0f..000000000 --- a/security/nss/lib/ssl/ssl3encode.c +++ /dev/null @@ -1,85 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is PRIVATE to SSL. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "prnetdb.h" -#include "seccomon.h" -#include "secerr.h" -#include "ssl3encode.h" - -SECStatus -ssl3_AppendToItem(SECItem *item, const unsigned char *buf, PRUint32 bytes) -{ - if (bytes > item->len) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return SECFailure; - } - - PORT_Memcpy(item->data, buf, bytes); - item->data += bytes; - item->len -= bytes; - return SECSuccess; -} - -SECStatus -ssl3_AppendNumberToItem(SECItem *item, PRUint32 num, PRInt32 lenSize) -{ - SECStatus rv; - PRUint8 b[4]; - - ssl_EncodeUintX(num, lenSize, b); - rv = ssl3_AppendToItem(item, &b[0], lenSize); - return rv; -} - -SECStatus -ssl3_ConsumeFromItem(SECItem *item, unsigned char **buf, PRUint32 bytes) -{ - if (bytes > item->len) { - PORT_SetError(SEC_ERROR_BAD_DATA); - return SECFailure; - } - - *buf = item->data; - item->data += bytes; - item->len -= bytes; - return SECSuccess; -} - -SECStatus -ssl3_ConsumeNumberFromItem(SECItem *item, PRUint32 *num, PRUint32 bytes) -{ - int i; - - if (bytes > item->len || bytes > sizeof(*num)) { - PORT_SetError(SEC_ERROR_BAD_DATA); - return SECFailure; - } - - *num = 0; - for (i = 0; i < bytes; i++) { - *num = (*num << 8) + item->data[i]; - } - - item->data += bytes; - item->len -= bytes; - - return SECSuccess; -} - -/* Helper function to encode an unsigned integer into a buffer. */ -PRUint8 * -ssl_EncodeUintX(PRUint64 value, unsigned int bytes, PRUint8 *to) -{ - PRUint64 encoded; - - PORT_Assert(bytes > 0 && bytes <= sizeof(encoded)); - - encoded = PR_htonll(value); - memcpy(to, ((unsigned char *)(&encoded)) + (sizeof(encoded) - bytes), bytes); - return to + bytes; -} diff --git a/security/nss/lib/ssl/ssl3encode.h b/security/nss/lib/ssl/ssl3encode.h deleted file mode 100644 index 3b88f7e7b..000000000 --- a/security/nss/lib/ssl/ssl3encode.h +++ /dev/null @@ -1,26 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is PRIVATE to SSL. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef __ssl3encode_h_ -#define __ssl3encode_h_ - -#include "seccomon.h" - -/* All of these functions modify the underlying SECItem, and so should - * be performed on a shallow copy.*/ -SECStatus ssl3_AppendToItem(SECItem *item, - const unsigned char *buf, PRUint32 bytes); -SECStatus ssl3_AppendNumberToItem(SECItem *item, - PRUint32 num, PRInt32 lenSize); -SECStatus ssl3_ConsumeFromItem(SECItem *item, - unsigned char **buf, PRUint32 bytes); -SECStatus ssl3_ConsumeNumberFromItem(SECItem *item, - PRUint32 *num, PRUint32 bytes); -PRUint8 *ssl_EncodeUintX(PRUint64 value, unsigned int bytes, PRUint8 *to); - -#endif diff --git a/security/nss/lib/ssl/ssl3ext.c b/security/nss/lib/ssl/ssl3ext.c index ade280903..5a5077998 100644 --- a/security/nss/lib/ssl/ssl3ext.c +++ b/security/nss/lib/ssl/ssl3ext.c @@ -519,6 +519,8 @@ ssl3_HandleParsedExtensions(sslSocket *ss, SSLHandshakeType message) } /* Fall through. */ case tls13_extension_disallowed: + SSL_TRC(3, ("%d: TLS13: unexpected extension %d in message %d", + SSL_GETPID(), extension, message)); tls13_FatalError(ss, SSL_ERROR_EXTENSION_DISALLOWED_FOR_VERSION, unsupported_extension); return SECFailure; diff --git a/security/nss/lib/ssl/ssl3exthandle.c b/security/nss/lib/ssl/ssl3exthandle.c index c0fbda7ab..e6388945e 100644 --- a/security/nss/lib/ssl/ssl3exthandle.c +++ b/security/nss/lib/ssl/ssl3exthandle.c @@ -182,7 +182,7 @@ ssl3_ClientSendSessionTicketXtn(const sslSocket *ss, TLSExtensionData *xtnData, /* Never send an extension with a ticket for TLS 1.3, but * OK to send the empty one in case the server does 1.2. */ - if (sid->cached == in_client_cache && + if ((sid->cached == in_client_cache || sid->cached == in_external_cache) && sid->version >= SSL_LIBRARY_VERSION_TLS_1_3) { return SECSuccess; } @@ -821,7 +821,7 @@ ssl3_EncodeSessionTicket(sslSocket *ss, const NewSessionTicket *ticket, if (rv != SECSuccess) goto loser; - rv = sslBuffer_AppendNumber(&plaintext, ssl_max_early_data_size, 4); + rv = sslBuffer_AppendNumber(&plaintext, ss->opt.maxEarlyDataSize, 4); if (rv != SECSuccess) goto loser; @@ -1219,6 +1219,7 @@ ssl_CreateSIDFromTicket(sslSocket *ss, const SECItem *rawTicket, } } if (parsedTicket->alpnSelection.data != NULL) { + SECITEM_FreeItem(&sid->u.ssl3.alpnSelection, PR_FALSE); rv = SECITEM_CopyItem(NULL, &sid->u.ssl3.alpnSelection, &parsedTicket->alpnSelection); if (rv != SECSuccess) { @@ -1245,7 +1246,7 @@ ssl3_ProcessSessionTicketCommon(sslSocket *ss, const SECItem *ticket, SECStatus rv; if (ss->sec.ci.sid != NULL) { - ss->sec.uncache(ss->sec.ci.sid); + ssl_UncacheSessionID(ss); ssl_FreeSID(ss->sec.ci.sid); ss->sec.ci.sid = NULL; } @@ -1652,11 +1653,16 @@ ssl3_HandleSigAlgsXtn(const sslSocket *ss, TLSExtensionData *xtnData, &xtnData->sigSchemes, &xtnData->numSigSchemes, &data->data, &data->len); - if (rv != SECSuccess || xtnData->numSigSchemes == 0) { + if (rv != SECSuccess) { ssl3_ExtSendAlert(ss, alert_fatal, decode_error); PORT_SetError(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO); return SECFailure; } + if (xtnData->numSigSchemes == 0) { + ssl3_ExtSendAlert(ss, alert_fatal, handshake_failure); + PORT_SetError(SSL_ERROR_UNSUPPORTED_SIGNATURE_ALGORITHM); + return SECFailure; + } /* Check for trailing data. */ if (data->len != 0) { ssl3_ExtSendAlert(ss, alert_fatal, decode_error); diff --git a/security/nss/lib/ssl/ssl3gthr.c b/security/nss/lib/ssl/ssl3gthr.c index 20404f4da..8b323bb05 100644 --- a/security/nss/lib/ssl/ssl3gthr.c +++ b/security/nss/lib/ssl/ssl3gthr.c @@ -386,6 +386,13 @@ ssl3_GatherCompleteHandshake(sslSocket *ss, int flags) SSL3Ciphertext cText; PRBool keepGoing = PR_TRUE; + if (ss->ssl3.fatalAlertSent) { + SSL_TRC(3, ("%d: SSL3[%d] Cannot gather data; fatal alert already sent", + SSL_GETPID(), ss->fd)); + PORT_SetError(SSL_ERROR_HANDSHAKE_FAILED); + return SECFailure; + } + SSL_TRC(30, ("%d: SSL3[%d]: ssl3_GatherCompleteHandshake", SSL_GETPID(), ss->fd)); diff --git a/security/nss/lib/ssl/sslcon.c b/security/nss/lib/ssl/sslcon.c index 448170640..bc63e1537 100644 --- a/security/nss/lib/ssl/sslcon.c +++ b/security/nss/lib/ssl/sslcon.c @@ -119,13 +119,12 @@ ssl_CheckConfigSanity(sslSocket *ss) SECStatus ssl_BeginClientHandshake(sslSocket *ss) { - sslSessionID *sid; + sslSessionID *sid = NULL; SECStatus rv; PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss)); ss->sec.isServer = PR_FALSE; - ssl_ChooseSessionIDProcs(&ss->sec); rv = ssl_CheckConfigSanity(ss); if (rv != SECSuccess) @@ -156,19 +155,22 @@ ssl_BeginClientHandshake(sslSocket *ss) SSL_TRC(3, ("%d: SSL[%d]: sending client-hello", SSL_GETPID(), ss->fd)); - /* Try to find server in our session-id cache */ - if (ss->opt.noCache) { - sid = NULL; - } else { + /* If there's an sid set from an external cache, use it. */ + if (ss->sec.ci.sid && ss->sec.ci.sid->cached == in_external_cache) { + sid = ss->sec.ci.sid; + SSL_TRC(3, ("%d: SSL[%d]: using external token", SSL_GETPID(), ss->fd)); + } else if (!ss->opt.noCache) { + /* Try to find server in our session-id cache */ sid = ssl_LookupSID(&ss->sec.ci.peer, ss->sec.ci.port, ss->peerID, ss->url); } + if (sid) { if (sid->version >= ss->vrange.min && sid->version <= ss->vrange.max) { PORT_Assert(!ss->sec.localCert); ss->sec.localCert = CERT_DupCertificate(sid->localCert); } else { - ss->sec.uncache(sid); + ssl_UncacheSessionID(ss); ssl_FreeSID(sid); sid = NULL; } @@ -218,7 +220,6 @@ ssl_BeginServerHandshake(sslSocket *ss) ss->sec.isServer = PR_TRUE; ss->ssl3.hs.ws = wait_client_hello; - ssl_ChooseSessionIDProcs(&ss->sec); rv = ssl_CheckConfigSanity(ss); if (rv != SECSuccess) diff --git a/security/nss/lib/ssl/sslencode.c b/security/nss/lib/ssl/sslencode.c index 2f127fe8f..e50880451 100644 --- a/security/nss/lib/ssl/sslencode.c +++ b/security/nss/lib/ssl/sslencode.c @@ -29,6 +29,7 @@ ssl_EncodeUintX(PRUint8 *to, PRUint64 value, unsigned int bytes) SECStatus sslBuffer_Grow(sslBuffer *b, unsigned int newLen) { + PORT_Assert(b); if (b->fixed) { PORT_Assert(newLen <= b->space); if (newLen > b->space) { @@ -84,6 +85,7 @@ sslBuffer_AppendVariable(sslBuffer *b, const PRUint8 *data, unsigned int len, unsigned int size) { PORT_Assert(size <= 4 && size > 0); + PORT_Assert(b); if (len >= (1ULL << (8 * size))) { PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); return SECFailure; @@ -95,7 +97,11 @@ sslBuffer_AppendVariable(sslBuffer *b, const PRUint8 *data, unsigned int len, ssl_EncodeUintX(SSL_BUFFER_NEXT(b), len, size); b->len += size; - PORT_Memcpy(SSL_BUFFER_NEXT(b), data, len); + if (len != 0) { + PORT_Assert(data); + /* We sometimes pass NULL, 0 and memcpy() doesn't want NULL. */ + PORT_Memcpy(SSL_BUFFER_NEXT(b), data, len); + } b->len += len; return SECSuccess; } @@ -169,37 +175,63 @@ sslBuffer_Clear(sslBuffer *b) } SECStatus -ssl3_ConsumeFromItem(SECItem *item, unsigned char **buf, unsigned int size) +sslRead_Read(sslReader *reader, unsigned int count, sslReadBuffer *out) { - if (size > item->len) { + if (!reader || !out) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + if (reader->buf.len < reader->offset || + count > SSL_READER_REMAINING(reader)) { PORT_SetError(SEC_ERROR_BAD_DATA); return SECFailure; } - *buf = item->data; - item->data += size; - item->len -= size; + out->buf = SSL_READER_CURRENT(reader); + out->len = count; + reader->offset += count; + return SECSuccess; } SECStatus -ssl3_ConsumeNumberFromItem(SECItem *item, PRUint32 *num, unsigned int size) +sslRead_ReadVariable(sslReader *reader, unsigned int sizeLen, sslReadBuffer *out) { - int i; - - if (size > item->len || size > sizeof(*num)) { + PRUint64 variableLen = 0; + SECStatus rv = sslRead_ReadNumber(reader, sizeLen, &variableLen); + if (rv != SECSuccess) { PORT_SetError(SEC_ERROR_BAD_DATA); return SECFailure; } - - *num = 0; - for (i = 0; i < size; i++) { - *num = (*num << 8) + item->data[i]; + if (!variableLen) { + // It is ok to have an empty variable. + out->len = variableLen; + return SECSuccess; } + return sslRead_Read(reader, variableLen, out); +} - item->data += size; - item->len -= size; +SECStatus +sslRead_ReadNumber(sslReader *reader, unsigned int bytes, PRUint64 *num) +{ + if (!reader || !num) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + if (reader->buf.len < reader->offset || + bytes > SSL_READER_REMAINING(reader) || + bytes > 8) { + PORT_SetError(SEC_ERROR_BAD_DATA); + return SECFailure; + } + unsigned int i; + PRUint64 number = 0; + for (i = 0; i < bytes; i++) { + number = (number << 8) + reader->buf.buf[i + reader->offset]; + } + reader->offset = reader->offset + bytes; + *num = number; return SECSuccess; } diff --git a/security/nss/lib/ssl/sslencode.h b/security/nss/lib/ssl/sslencode.h index a1b04d88f..f43e1c54b 100644 --- a/security/nss/lib/ssl/sslencode.h +++ b/security/nss/lib/ssl/sslencode.h @@ -47,13 +47,6 @@ SECStatus sslBuffer_InsertLength(sslBuffer *b, unsigned int at, unsigned int size); void sslBuffer_Clear(sslBuffer *b); -/* All of these functions modify the underlying SECItem, and so should - * be performed on a shallow copy.*/ -SECStatus ssl3_ConsumeFromItem(SECItem *item, - PRUint8 **buf, unsigned int size); -SECStatus ssl3_ConsumeNumberFromItem(SECItem *item, - PRUint32 *num, unsigned int size); - SECStatus ssl3_AppendHandshake(sslSocket *ss, const void *void_src, unsigned int bytes); SECStatus ssl3_AppendHandshakeHeader(sslSocket *ss, @@ -66,4 +59,27 @@ SECStatus ssl3_AppendBufferToHandshake(sslSocket *ss, sslBuffer *buf); SECStatus ssl3_AppendBufferToHandshakeVariable(sslSocket *ss, sslBuffer *buf, unsigned int lenSize); +typedef struct { + const PRUint8 *buf; + unsigned int len; +} sslReadBuffer; +typedef struct { + sslReadBuffer buf; + unsigned int offset; +} sslReader; +#define SSL_READER(b, l) \ + { \ + { b, l }, 0 \ + } +#define SSL_READER_CURRENT(r) \ + ((r)->buf.buf + (r)->offset) +#define SSL_READER_REMAINING(r) \ + ((r)->buf.len - (r)->offset) +SECStatus sslRead_Read(sslReader *reader, unsigned int count, + sslReadBuffer *out); +SECStatus sslRead_ReadVariable(sslReader *reader, unsigned int sizeLen, + sslReadBuffer *out); +SECStatus sslRead_ReadNumber(sslReader *reader, unsigned int bytes, + PRUint64 *val); + #endif /* __sslencode_h_ */ diff --git a/security/nss/lib/ssl/sslerr.h b/security/nss/lib/ssl/sslerr.h index 90815dd79..b94d0cc62 100644 --- a/security/nss/lib/ssl/sslerr.h +++ b/security/nss/lib/ssl/sslerr.h @@ -260,6 +260,8 @@ typedef enum { SSL_ERROR_RX_UNEXPECTED_KEY_UPDATE = (SSL_ERROR_BASE + 169), SSL_ERROR_RX_MALFORMED_KEY_UPDATE = (SSL_ERROR_BASE + 170), SSL_ERROR_TOO_MANY_KEY_UPDATES = (SSL_ERROR_BASE + 171), + SSL_ERROR_HANDSHAKE_FAILED = (SSL_ERROR_BASE + 172), + SSL_ERROR_BAD_RESUMPTION_TOKEN_ERROR = (SSL_ERROR_BASE + 173), SSL_ERROR_END_OF_LIST /* let the c compiler determine the value of this. */ } SSLErrorCodes; #endif /* NO_SECURITY_ERROR_ENUM */ diff --git a/security/nss/lib/ssl/sslexp.h b/security/nss/lib/ssl/sslexp.h index 569add861..08654f885 100644 --- a/security/nss/lib/ssl/sslexp.h +++ b/security/nss/lib/ssl/sslexp.h @@ -350,8 +350,111 @@ typedef SSLHelloRetryRequestAction(PR_CALLBACK *SSLHelloRetryRequestCallback)( (PRFileDesc * _fd, PRBool _requestUpdate), \ (fd, requestUpdate)) -#define SSL_UseAltServerHelloType(fd, enable) \ - SSL_DEPRECATED_EXPERIMENTAL_API +/* + * Session cache API. + */ + +/* + * Information that can be retrieved about a resumption token. + * See SSL_GetResumptionTokenInfo for details about how to use this API. + * Note that peerCert points to a certificate in the NSS database and must be + * copied by the application if it should be used after NSS shutdown or after + * calling SSL_DestroyResumptionTokenInfo. + */ +typedef struct SSLResumptionTokenInfoStr { + PRUint16 length; + CERTCertificate *peerCert; + PRUint8 *alpnSelection; + PRUint32 alpnSelectionLen; + PRUint32 maxEarlyDataSize; +} SSLResumptionTokenInfo; + +/* + * Allows applications to retrieve information about a resumption token. + * This does not require a TLS session. + * + * - The |tokenData| argument is a pointer to the resumption token as byte array + * of length |tokenLen|. + * - The |token| argument is a pointer to a SSLResumptionTokenInfo struct of + * of |len|. The struct gets filled by this function. + * See SSL_DestroyResumptionTokenInfo for information about how to manage the + * |token| memory. + */ +#define SSL_GetResumptionTokenInfo(tokenData, tokenLen, token, len) \ + SSL_EXPERIMENTAL_API("SSL_GetResumptionTokenInfo", \ + (const PRUint8 *_tokenData, unsigned int _tokenLen, \ + SSLResumptionTokenInfo *_token, PRUintn _len), \ + (tokenData, tokenLen, token, len)) + +/* + * SSL_GetResumptionTokenInfo allocates memory in order to populate |tokenInfo|. + * Any SSLResumptionTokenInfo struct filled with SSL_GetResumptionTokenInfo + * has to be freed with SSL_DestroyResumptionTokenInfo. + */ +#define SSL_DestroyResumptionTokenInfo(tokenInfo) \ + SSL_EXPERIMENTAL_API( \ + "SSL_DestroyResumptionTokenInfo", \ + (SSLResumptionTokenInfo * _tokenInfo), \ + (tokenInfo)) + +/* + * This is the function signature for function pointers used as resumption + * token callback. The caller has to copy the memory at |resumptionToken| with + * length |len| before returning. + * + * - The |fd| argument is the socket file descriptor. + * - The |resumptionToken| is a pointer to the resumption token as byte array + * of length |len|. + * - The |ctx| is a void pointer to the context set by the application in + * SSL_SetResumptionTokenCallback. + */ +typedef SECStatus(PR_CALLBACK *SSLResumptionTokenCallback)( + PRFileDesc *fd, const PRUint8 *resumptionToken, unsigned int len, + void *ctx); + +/* + * This allows setting a callback for external session caches to store + * resumption tokens. + * + * - The |fd| argument is the socket file descriptor. + * - The |cb| is a function pointer to an implementation of + * SSLResumptionTokenCallback. + * - The |ctx| is a pointer to some application specific context, which is + * returned when |cb| is called. + */ +#define SSL_SetResumptionTokenCallback(fd, cb, ctx) \ + SSL_EXPERIMENTAL_API( \ + "SSL_SetResumptionTokenCallback", \ + (PRFileDesc * _fd, SSLResumptionTokenCallback _cb, void *_ctx), \ + (fd, cb, ctx)) + +/* + * This allows setting a resumption token for a session. + * The function returns SECSuccess iff the resumption token can be used, + * SECFailure in any other case. The caller should remove the |token| from its + * cache when the function returns SECFailure. + * + * - The |fd| argument is the socket file descriptor. + * - The |token| is a pointer to the resumption token as byte array + * of length |len|. + */ +#define SSL_SetResumptionToken(fd, token, len) \ + SSL_EXPERIMENTAL_API( \ + "SSL_SetResumptionToken", \ + (PRFileDesc * _fd, const PRUint8 *_token, const unsigned int _len), \ + (fd, token, len)) + +/* TLS 1.3 allows a server to set a limit on the number of bytes of early data + * that can be received. This allows that limit to be set. This function has no + * effect on a client. */ +#define SSL_SetMaxEarlyDataSize(fd, size) \ + SSL_EXPERIMENTAL_API("SSL_SetMaxEarlyDataSize", \ + (PRFileDesc * _fd, PRUint32 _size), \ + (fd, size)) + +/* Deprecated experimental APIs */ + +#define SSL_UseAltServerHelloType(fd, enable) SSL_DEPRECATED_EXPERIMENTAL_API SEC_END_PROTOS diff --git a/security/nss/lib/ssl/sslimpl.h b/security/nss/lib/ssl/sslimpl.h index dee9aa20f..10d0333d9 100644 --- a/security/nss/lib/ssl/sslimpl.h +++ b/security/nss/lib/ssl/sslimpl.h @@ -168,8 +168,11 @@ struct ssl3CertNodeStr { typedef SECStatus (*sslHandshakeFunc)(sslSocket *ss); -typedef void (*sslSessionIDCacheFunc)(sslSessionID *sid); -typedef void (*sslSessionIDUncacheFunc)(sslSessionID *sid); +void ssl_CacheSessionID(sslSocket *ss); +void ssl_UncacheSessionID(sslSocket *ss); +void ssl_ServerCacheSessionID(sslSessionID *sid); +void ssl_ServerUncacheSessionID(sslSessionID *sid); + typedef sslSessionID *(*sslSessionIDLookupFunc)(const PRIPv6Addr *addr, unsigned char *sid, unsigned int sidLen, @@ -230,6 +233,7 @@ typedef struct sslOptionsStr { * list of supported protocols. */ SECItem nextProtoNego; + PRUint32 maxEarlyDataSize; unsigned int useSecurity : 1; unsigned int useSocks : 1; unsigned int requestCertificate : 1; @@ -341,9 +345,11 @@ struct sslGatherStr { #define GS_HEADER 1 #define GS_DATA 2 +#define WRAPPED_MASTER_SECRET_SIZE 48 + typedef struct { - PRUint8 wrapped_master_secret[48]; - PRUint16 wrapped_master_secret_len; + PRUint8 wrapped_master_secret[WRAPPED_MASTER_SECRET_SIZE]; + PRUint8 wrapped_master_secret_len; PRUint8 resumable; PRUint8 extendedMasterSecretUsed; } ssl3SidKeys; /* 52 bytes */ @@ -351,7 +357,8 @@ typedef struct { typedef enum { never_cached, in_client_cache, in_server_cache, - invalid_cache /* no longer in any cache. */ + invalid_cache, /* no longer in any cache. */ + in_external_cache } Cached; #include "sslcert.h" @@ -398,17 +405,11 @@ struct sslSessionIDStr { PRUint8 sessionID[SSL3_SESSIONID_BYTES]; ssl3CipherSuite cipherSuite; - int policy; + PRUint8 policy; ssl3SidKeys keys; /* mechanism used to wrap master secret */ CK_MECHANISM_TYPE masterWrapMech; - /* The following values are NOT restored from the server's on-disk - * session cache, but are restored from the client's cache. - */ - PK11SymKey *clientWriteKey; - PK11SymKey *serverWriteKey; - /* The following values pertain to the slot that wrapped the ** master secret. (used only in client) */ @@ -740,7 +741,7 @@ struct ssl3StateStr { CERTCertificateList *clientCertChain; /* used by client */ PRBool sendEmptyCert; /* used by client */ - int policy; + PRUint8 policy; /* This says what cipher suites we can do, and should * be either SSL_ALLOWED or SSL_RESTRICTED */ @@ -897,14 +898,6 @@ struct sslSecurityInfoStr { /* The selected certificate (for servers only). */ const sslServerCert *serverCert; - /* - ** Procs used for SID cache (nonce) management. - ** Different implementations exist for clients/servers - ** The lookup proc is only used for servers. Baloney! - */ - sslSessionIDCacheFunc cache; - sslSessionIDUncacheFunc uncache; - /* These are used during a connection handshake */ sslConnectInfo ci; }; @@ -982,6 +975,8 @@ struct sslSocketStr { SSLHelloRetryRequestCallback hrrCallback; void *hrrCallbackArg; PRCList extensionHooks; + SSLResumptionTokenCallback resumptionTokenCallback; + void *resumptionTokenContext; PRIntervalTime rTimeout; /* timeout for NSPR I/O */ PRIntervalTime wTimeout; /* timeout for NSPR I/O */ @@ -1075,13 +1070,10 @@ extern FILE *ssl_keylog_iob; extern PZLock *ssl_keylog_lock; extern PRUint32 ssl3_sid_timeout; extern PRUint32 ssl_ticket_lifetime; -extern PRUint32 ssl_max_early_data_size; extern const char *const ssl3_cipherName[]; extern sslSessionIDLookupFunc ssl_sid_lookup; -extern sslSessionIDCacheFunc ssl_sid_cache; -extern sslSessionIDUncacheFunc ssl_sid_uncache; extern const sslNamedGroupDef ssl_named_groups[]; @@ -1163,14 +1155,13 @@ extern SECStatus ssl_BeginClientHandshake(sslSocket *ss); extern SECStatus ssl_BeginServerHandshake(sslSocket *ss); extern int ssl_Do1stHandshake(sslSocket *ss); -extern void ssl_ChooseSessionIDProcs(sslSecurityInfo *sec); - extern SECStatus ssl3_InitPendingCipherSpecs(sslSocket *ss, PK11SymKey *secret, PRBool derive); extern sslSessionID *ssl3_NewSessionID(sslSocket *ss, PRBool is_server); extern sslSessionID *ssl_LookupSID(const PRIPv6Addr *addr, PRUint16 port, const char *peerID, const char *urlSvrName); extern void ssl_FreeSID(sslSessionID *sid); +extern void ssl_DestroySID(sslSessionID *sid, PRBool freeIt); extern int ssl3_SendApplicationData(sslSocket *ss, const PRUint8 *in, int len, int flags); @@ -1692,6 +1683,26 @@ PRBool ssl_AlpnTagAllowed(const sslSocket *ss, const SECItem *tag); void ssl_Trace(const char *format, ...); +void ssl_CacheExternalToken(sslSocket *ss); +SECStatus ssl_DecodeResumptionToken(sslSessionID *sid, const PRUint8 *encodedTicket, + PRUint32 encodedTicketLen); +PRBool ssl_IsResumptionTokenValid(sslSocket *ss); + +/* Remove when stable. */ + +SECStatus SSLExp_SetResumptionTokenCallback(PRFileDesc *fd, + SSLResumptionTokenCallback cb, + void *ctx); +SECStatus SSLExp_SetResumptionToken(PRFileDesc *fd, const PRUint8 *token, + unsigned int len); + +SECStatus SSLExp_GetResumptionTokenInfo(const PRUint8 *tokenData, unsigned int tokenLen, + SSLResumptionTokenInfo *token, unsigned int version); + +SECStatus SSLExp_DestroyResumptionTokenInfo(SSLResumptionTokenInfo *token); + +#define SSLResumptionTokenVersion 2 + SEC_END_PROTOS #if defined(XP_UNIX) || defined(XP_OS2) || defined(XP_BEOS) diff --git a/security/nss/lib/ssl/sslinit.c b/security/nss/lib/ssl/sslinit.c index 0f38c0b57..07d57ce6e 100644 --- a/security/nss/lib/ssl/sslinit.c +++ b/security/nss/lib/ssl/sslinit.c @@ -15,6 +15,7 @@ static int ssl_isInited = 0; static PRCallOnceType ssl_init = { 0 }; +PR_STATIC_ASSERT(sizeof(unsigned long) <= sizeof(PRUint64)); PRStatus ssl_InitCallOnce(void *arg) diff --git a/security/nss/lib/ssl/sslnonce.c b/security/nss/lib/ssl/sslnonce.c index 228834e3d..f79c23fc7 100644 --- a/security/nss/lib/ssl/sslnonce.c +++ b/security/nss/lib/ssl/sslnonce.c @@ -15,6 +15,7 @@ #include "sslimpl.h" #include "sslproto.h" #include "nssilock.h" +#include "sslencode.h" #if defined(XP_UNIX) || defined(XP_WIN) || defined(_WINDOWS) || defined(XP_BEOS) #include #endif @@ -24,12 +25,13 @@ PRUint32 ssl3_sid_timeout = 86400L; /* 24 hours */ static sslSessionID *cache = NULL; static PZLock *cacheLock = NULL; -/* sids can be in one of 4 states: +/* sids can be in one of 5 states: * * never_cached, created, but not yet put into cache. * in_client_cache, in the client cache's linked list. * in_server_cache, entry came from the server's cache file. * invalid_cache has been removed from the cache. + * in_external_cache sid comes from an external cache. */ #define LOCK_CACHE lock_cache() @@ -164,8 +166,8 @@ lock_cache(void) /* BEWARE: This function gets called for both client and server SIDs !! * If the unreferenced sid is not in the cache, Free sid and its contents. */ -static void -ssl_DestroySID(sslSessionID *sid) +void +ssl_DestroySID(sslSessionID *sid, PRBool freeIt) { SSL_TRC(8, ("SSL: destroy sid: sid=0x%x cached=%d", sid, sid->cached)); PORT_Assert(sid->references == 0); @@ -186,11 +188,8 @@ ssl_DestroySID(sslSessionID *sid) PR_DestroyRWLock(sid->u.ssl3.lock); } - if (sid->peerID != NULL) - PORT_Free((void *)sid->peerID); /* CONST */ - - if (sid->urlSvrName != NULL) - PORT_Free((void *)sid->urlSvrName); /* CONST */ + PORT_Free((void *)sid->peerID); + PORT_Free((void *)sid->urlSvrName); if (sid->peerCert) { CERT_DestroyCertificate(sid->peerCert); @@ -205,7 +204,9 @@ ssl_DestroySID(sslSessionID *sid) SECITEM_FreeItem(&sid->u.ssl3.alpnSelection, PR_FALSE); - PORT_ZFree(sid, sizeof(sslSessionID)); + if (freeIt) { + PORT_ZFree(sid, sizeof(sslSessionID)); + } } /* BEWARE: This function gets called for both client and server SIDs !! @@ -220,7 +221,7 @@ ssl_FreeLockedSID(sslSessionID *sid) { PORT_Assert(sid->references >= 1); if (--sid->references == 0) { - ssl_DestroySID(sid); + ssl_DestroySID(sid, PR_TRUE); } } @@ -306,6 +307,7 @@ ssl_LookupSID(const PRIPv6Addr *addr, PRUint16 port, const char *peerID, static void CacheSID(sslSessionID *sid) { + PORT_Assert(sid); PORT_Assert(sid->cached == never_cached); SSL_TRC(8, ("SSL: Cache: sid=0x%x cached=%d addr=0x%08x%08x%08x%08x port=0x%04x " @@ -400,7 +402,7 @@ UncacheSID(sslSessionID *zap) /* If sid "zap" is in the cache, * removes sid from cache, and decrements reference count. * Although this function is static, it is called externally via - * ss->sec.uncache(). + * ssl_UncacheSessionID. */ static void LockAndUncacheSID(sslSessionID *zap) @@ -410,16 +412,734 @@ LockAndUncacheSID(sslSessionID *zap) UNLOCK_CACHE; } -/* choose client or server cache functions for this sslsocket. */ +SECStatus +ReadVariableFromBuffer(sslReader *reader, sslReadBuffer *readerBuffer, + uint8_t lenBytes, SECItem *dest) +{ + if (sslRead_ReadVariable(reader, lenBytes, readerBuffer) != SECSuccess) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + if (readerBuffer->len) { + SECItem tempItem = { siBuffer, (unsigned char *)readerBuffer->buf, + readerBuffer->len }; + SECStatus rv = SECITEM_CopyItem(NULL, dest, &tempItem); + if (rv != SECSuccess) { + return rv; + } + } + return SECSuccess; +} + +/* Fill sid with the values from the encoded resumption token. + * sid has to be allocated. + * We don't care about locks here as this cache entry is externally stored. + */ +SECStatus +ssl_DecodeResumptionToken(sslSessionID *sid, const PRUint8 *encodedToken, + PRUint32 encodedTokenLen) +{ + PORT_Assert(encodedTokenLen); + PORT_Assert(encodedToken); + PORT_Assert(sid); + if (!sid || !encodedToken || !encodedTokenLen) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + + if (encodedToken[0] != SSLResumptionTokenVersion) { + /* Unknown token format version. */ + PORT_SetError(SSL_ERROR_BAD_RESUMPTION_TOKEN_ERROR); + return SECFailure; + } + + /* These variables are used across macros. Don't use them outside. */ + sslReader reader = SSL_READER(encodedToken, encodedTokenLen); + reader.offset += 1; // We read the version already. Skip the first byte. + sslReadBuffer readerBuffer = { 0 }; + PRUint64 tmpInt = 0; + + if (sslRead_ReadNumber(&reader, 8, &tmpInt) != SECSuccess) { + return SECFailure; + } + sid->lastAccessTime = (PRTime)tmpInt; + if (sslRead_ReadNumber(&reader, 8, &tmpInt) != SECSuccess) { + return SECFailure; + } + sid->expirationTime = (PRTime)tmpInt; + if (sslRead_ReadNumber(&reader, 8, &tmpInt) != SECSuccess) { + return SECFailure; + } + sid->u.ssl3.locked.sessionTicket.received_timestamp = (PRTime)tmpInt; + + if (sslRead_ReadNumber(&reader, 4, &tmpInt) != SECSuccess) { + return SECFailure; + } + sid->u.ssl3.locked.sessionTicket.ticket_lifetime_hint = (PRUint32)tmpInt; + if (sslRead_ReadNumber(&reader, 4, &tmpInt) != SECSuccess) { + return SECFailure; + } + sid->u.ssl3.locked.sessionTicket.flags = (PRUint32)tmpInt; + if (sslRead_ReadNumber(&reader, 4, &tmpInt) != SECSuccess) { + return SECFailure; + } + sid->u.ssl3.locked.sessionTicket.ticket_age_add = (PRUint32)tmpInt; + if (sslRead_ReadNumber(&reader, 4, &tmpInt) != SECSuccess) { + return SECFailure; + } + sid->u.ssl3.locked.sessionTicket.max_early_data_size = (PRUint32)tmpInt; + + if (sslRead_ReadVariable(&reader, 3, &readerBuffer) != SECSuccess) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + if (readerBuffer.len) { + PORT_Assert(!sid->peerCert); + SECItem tempItem = { siBuffer, (unsigned char *)readerBuffer.buf, + readerBuffer.len }; + sid->peerCert = CERT_NewTempCertificate(NULL, /* dbHandle */ + &tempItem, + NULL, PR_FALSE, PR_TRUE); + if (!sid->peerCert) { + return SECFailure; + } + } + + if (sslRead_ReadVariable(&reader, 2, &readerBuffer) != SECSuccess) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + if (readerBuffer.len) { + SECITEM_AllocArray(NULL, &sid->peerCertStatus, 1); + if (!sid->peerCertStatus.items) { + return SECFailure; + } + SECItem tempItem = { siBuffer, (unsigned char *)readerBuffer.buf, + readerBuffer.len }; + SECITEM_CopyItem(NULL, &sid->peerCertStatus.items[0], &tempItem); + } + + if (sslRead_ReadVariable(&reader, 1, &readerBuffer) != SECSuccess) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + if (readerBuffer.len) { + PORT_Assert(readerBuffer.buf); + sid->peerID = PORT_Strdup((const char *)readerBuffer.buf); + } + + if (sslRead_ReadVariable(&reader, 1, &readerBuffer) != SECSuccess) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + if (readerBuffer.len) { + if (sid->urlSvrName) { + PORT_Free((void *)sid->urlSvrName); + } + PORT_Assert(readerBuffer.buf); + sid->urlSvrName = PORT_Strdup((const char *)readerBuffer.buf); + } + + if (sslRead_ReadVariable(&reader, 3, &readerBuffer) != SECSuccess) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + if (readerBuffer.len) { + PORT_Assert(!sid->localCert); + SECItem tempItem = { siBuffer, (unsigned char *)readerBuffer.buf, + readerBuffer.len }; + sid->localCert = CERT_NewTempCertificate(NULL, /* dbHandle */ + &tempItem, + NULL, PR_FALSE, PR_TRUE); + } + + if (sslRead_ReadNumber(&reader, 8, &sid->addr.pr_s6_addr64[0]) != SECSuccess) { + return SECFailure; + } + if (sslRead_ReadNumber(&reader, 8, &sid->addr.pr_s6_addr64[1]) != SECSuccess) { + return SECFailure; + } + + if (sslRead_ReadNumber(&reader, 2, &tmpInt) != SECSuccess) { + return SECFailure; + } + sid->port = (PRUint16)tmpInt; + if (sslRead_ReadNumber(&reader, 2, &tmpInt) != SECSuccess) { + return SECFailure; + } + sid->version = (PRUint16)tmpInt; + + if (sslRead_ReadNumber(&reader, 8, &tmpInt) != SECSuccess) { + return SECFailure; + } + sid->creationTime = (PRTime)tmpInt; + + if (sslRead_ReadNumber(&reader, 2, &tmpInt) != SECSuccess) { + return SECFailure; + } + sid->authType = (SSLAuthType)tmpInt; + if (sslRead_ReadNumber(&reader, 4, &tmpInt) != SECSuccess) { + return SECFailure; + } + sid->authKeyBits = (PRUint32)tmpInt; + if (sslRead_ReadNumber(&reader, 2, &tmpInt) != SECSuccess) { + return SECFailure; + } + sid->keaType = (SSLKEAType)tmpInt; + if (sslRead_ReadNumber(&reader, 4, &tmpInt) != SECSuccess) { + return SECFailure; + } + sid->keaKeyBits = (PRUint32)tmpInt; + if (sslRead_ReadNumber(&reader, 3, &tmpInt) != SECSuccess) { + return SECFailure; + } + sid->keaGroup = (SSLNamedGroup)tmpInt; + + if (sslRead_ReadNumber(&reader, 3, &tmpInt) != SECSuccess) { + return SECFailure; + } + sid->sigScheme = (SSLSignatureScheme)tmpInt; + + if (sslRead_ReadNumber(&reader, 1, &tmpInt) != SECSuccess) { + return SECFailure; + } + sid->u.ssl3.sessionIDLength = (PRUint8)tmpInt; + + if (sslRead_ReadVariable(&reader, 1, &readerBuffer) != SECSuccess) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + if (readerBuffer.len) { + PORT_Assert(readerBuffer.buf); + PORT_Memcpy(sid->u.ssl3.sessionID, readerBuffer.buf, readerBuffer.len); + } + + if (sslRead_ReadNumber(&reader, 2, &tmpInt) != SECSuccess) { + return SECFailure; + } + sid->u.ssl3.cipherSuite = (PRUint16)tmpInt; + if (sslRead_ReadNumber(&reader, 1, &tmpInt) != SECSuccess) { + return SECFailure; + } + sid->u.ssl3.policy = (PRUint8)tmpInt; + + if (sslRead_ReadVariable(&reader, 1, &readerBuffer) != SECSuccess) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + PORT_Assert(readerBuffer.len == WRAPPED_MASTER_SECRET_SIZE); + if (readerBuffer.len != WRAPPED_MASTER_SECRET_SIZE) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + PORT_Assert(readerBuffer.buf); + PORT_Memcpy(sid->u.ssl3.keys.wrapped_master_secret, readerBuffer.buf, + readerBuffer.len); + + if (sslRead_ReadNumber(&reader, 1, &tmpInt) != SECSuccess) { + return SECFailure; + } + sid->u.ssl3.keys.wrapped_master_secret_len = (PRUint8)tmpInt; + if (sslRead_ReadNumber(&reader, 1, &tmpInt) != SECSuccess) { + return SECFailure; + } + sid->u.ssl3.keys.extendedMasterSecretUsed = (PRUint8)tmpInt; + + if (sslRead_ReadNumber(&reader, 8, &tmpInt) != SECSuccess) { + return SECFailure; + } + sid->u.ssl3.masterWrapMech = (unsigned long)tmpInt; + if (sslRead_ReadNumber(&reader, 8, &tmpInt) != SECSuccess) { + return SECFailure; + } + sid->u.ssl3.masterModuleID = (unsigned long)tmpInt; + if (sslRead_ReadNumber(&reader, 8, &tmpInt) != SECSuccess) { + return SECFailure; + } + sid->u.ssl3.masterSlotID = (unsigned long)tmpInt; + + if (sslRead_ReadNumber(&reader, 4, &tmpInt) != SECSuccess) { + return SECFailure; + } + sid->u.ssl3.masterWrapIndex = (PRUint32)tmpInt; + if (sslRead_ReadNumber(&reader, 2, &tmpInt) != SECSuccess) { + return SECFailure; + } + sid->u.ssl3.masterWrapSeries = (PRUint16)tmpInt; + + if (sslRead_ReadNumber(&reader, 1, &tmpInt) != SECSuccess) { + return SECFailure; + } + sid->u.ssl3.masterValid = (char)tmpInt; + + if (ReadVariableFromBuffer(&reader, &readerBuffer, 1, + &sid->u.ssl3.srvName) != SECSuccess) { + return SECFailure; + } + if (ReadVariableFromBuffer(&reader, &readerBuffer, 2, + &sid->u.ssl3.signedCertTimestamps) != SECSuccess) { + return SECFailure; + } + if (ReadVariableFromBuffer(&reader, &readerBuffer, 1, + &sid->u.ssl3.alpnSelection) != SECSuccess) { + return SECFailure; + } + if (ReadVariableFromBuffer(&reader, &readerBuffer, 2, + &sid->u.ssl3.locked.sessionTicket.ticket) != SECSuccess) { + return SECFailure; + } + if (!sid->u.ssl3.locked.sessionTicket.ticket.len) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + + /* At this point we must have read everything. */ + PORT_Assert(reader.offset == reader.buf.len); + if (reader.offset != reader.buf.len) { + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); + return SECFailure; + } + + return SECSuccess; +} + +PRBool +ssl_IsResumptionTokenValid(sslSocket *ss) +{ + PORT_Assert(ss); + sslSessionID *sid = ss->sec.ci.sid; + PORT_Assert(sid); + + // Check that the ticket didn't expire. + PRTime endTime = 0; + NewSessionTicket *ticket = &sid->u.ssl3.locked.sessionTicket; + if (ticket->ticket_lifetime_hint != 0) { + endTime = ticket->received_timestamp + + (PRTime)(ticket->ticket_lifetime_hint * PR_USEC_PER_SEC); + if (endTime < ssl_TimeUsec()) { + return PR_FALSE; + } + } + + // Check that the session entry didn't expire. + if (sid->expirationTime < ssl_TimeUsec()) { + return PR_FALSE; + } + + // Check that the server name (SNI) matches the one set for this session. + // Don't use the token if there's no server name. + if (sid->urlSvrName == NULL || PORT_Strcmp(ss->url, sid->urlSvrName) != 0) { + return PR_FALSE; + } + + // This shouldn't be false, but let's check it anyway. + if (!sid->u.ssl3.keys.resumable) { + return PR_FALSE; + } + + return PR_TRUE; +} + +/* Encode a session ticket into a byte array that can be handed out to a cache. + * Needed memory in encodedToken has to be allocated according to + * *encodedTokenLen. */ +static SECStatus +ssl_EncodeResumptionToken(sslSessionID *sid, sslBuffer *encodedTokenBuf) +{ + PORT_Assert(encodedTokenBuf); + PORT_Assert(sid); + if (!sid || !sid->u.ssl3.locked.sessionTicket.ticket.len || + !encodedTokenBuf || !sid->u.ssl3.keys.resumable || !sid->urlSvrName) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + + /* Encoding format: + * 0-byte: version + * Integers are encoded according to their length. + * SECItems are prepended with a 64-bit length field followed by the bytes. + * Optional bytes are encoded as a 0-length item if not present. + */ + SECStatus rv = sslBuffer_AppendNumber(encodedTokenBuf, + SSLResumptionTokenVersion, 1); + if (rv != SECSuccess) { + return SECFailure; + } + + rv = sslBuffer_AppendNumber(encodedTokenBuf, sid->lastAccessTime, 8); + if (rv != SECSuccess) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + rv = sslBuffer_AppendNumber(encodedTokenBuf, sid->expirationTime, 8); + if (rv != SECSuccess) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + + // session ticket + rv = sslBuffer_AppendNumber(encodedTokenBuf, + sid->u.ssl3.locked.sessionTicket.received_timestamp, + 8); + if (rv != SECSuccess) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + rv = sslBuffer_AppendNumber(encodedTokenBuf, + sid->u.ssl3.locked.sessionTicket.ticket_lifetime_hint, + 4); + if (rv != SECSuccess) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + rv = sslBuffer_AppendNumber(encodedTokenBuf, + sid->u.ssl3.locked.sessionTicket.flags, + 4); + if (rv != SECSuccess) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + rv = sslBuffer_AppendNumber(encodedTokenBuf, + sid->u.ssl3.locked.sessionTicket.ticket_age_add, + 4); + if (rv != SECSuccess) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + rv = sslBuffer_AppendNumber(encodedTokenBuf, + sid->u.ssl3.locked.sessionTicket.max_early_data_size, + 4); + if (rv != SECSuccess) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + + rv = sslBuffer_AppendVariable(encodedTokenBuf, sid->peerCert->derCert.data, + sid->peerCert->derCert.len, 3); + if (rv != SECSuccess) { + return SECFailure; + } + + if (sid->peerCertStatus.len > 1) { + /* This is not implemented so it shouldn't happen. + * If it gets implemented, this has to change. + */ + PORT_Assert(0); + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); + return SECFailure; + } + + if (sid->peerCertStatus.len == 1 && sid->peerCertStatus.items[0].len) { + rv = sslBuffer_AppendVariable(encodedTokenBuf, + sid->peerCertStatus.items[0].data, + sid->peerCertStatus.items[0].len, 2); + if (rv != SECSuccess) { + return SECFailure; + } + } else { + rv = sslBuffer_AppendVariable(encodedTokenBuf, NULL, 0, 2); + if (rv != SECSuccess) { + return SECFailure; + } + } + + PRUint64 len = sid->peerID ? strlen(sid->peerID) : 0; + if (len > PR_UINT8_MAX) { + // This string really shouldn't be that long. + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); + return SECFailure; + } + rv = sslBuffer_AppendVariable(encodedTokenBuf, + (const unsigned char *)sid->peerID, len, 1); + if (rv != SECSuccess) { + return SECFailure; + } + + len = sid->urlSvrName ? strlen(sid->urlSvrName) : 0; + if (!len) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + if (len > PR_UINT8_MAX) { + // This string really shouldn't be that long. + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); + return SECFailure; + } + rv = sslBuffer_AppendVariable(encodedTokenBuf, + (const unsigned char *)sid->urlSvrName, + len, 1); + if (rv != SECSuccess) { + return SECFailure; + } + + if (sid->localCert) { + rv = sslBuffer_AppendVariable(encodedTokenBuf, + sid->localCert->derCert.data, + sid->localCert->derCert.len, 3); + if (rv != SECSuccess) { + return SECFailure; + } + } else { + rv = sslBuffer_AppendVariable(encodedTokenBuf, NULL, 0, 3); + if (rv != SECSuccess) { + return SECFailure; + } + } + + rv = sslBuffer_AppendNumber(encodedTokenBuf, sid->addr.pr_s6_addr64[0], 8); + if (rv != SECSuccess) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + rv = sslBuffer_AppendNumber(encodedTokenBuf, sid->addr.pr_s6_addr64[1], 8); + if (rv != SECSuccess) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + rv = sslBuffer_AppendNumber(encodedTokenBuf, sid->port, 2); + if (rv != SECSuccess) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + rv = sslBuffer_AppendNumber(encodedTokenBuf, sid->version, 2); + if (rv != SECSuccess) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + rv = sslBuffer_AppendNumber(encodedTokenBuf, sid->creationTime, 8); + if (rv != SECSuccess) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + rv = sslBuffer_AppendNumber(encodedTokenBuf, sid->authType, 2); + if (rv != SECSuccess) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + rv = sslBuffer_AppendNumber(encodedTokenBuf, sid->authKeyBits, 4); + if (rv != SECSuccess) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + rv = sslBuffer_AppendNumber(encodedTokenBuf, sid->keaType, 2); + if (rv != SECSuccess) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + rv = sslBuffer_AppendNumber(encodedTokenBuf, sid->keaKeyBits, 4); + if (rv != SECSuccess) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + rv = sslBuffer_AppendNumber(encodedTokenBuf, sid->keaGroup, 3); + if (rv != SECSuccess) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + rv = sslBuffer_AppendNumber(encodedTokenBuf, sid->sigScheme, 3); + if (rv != SECSuccess) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + + rv = sslBuffer_AppendNumber(encodedTokenBuf, sid->u.ssl3.sessionIDLength, 1); + if (rv != SECSuccess) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + rv = sslBuffer_AppendVariable(encodedTokenBuf, sid->u.ssl3.sessionID, + SSL3_SESSIONID_BYTES, 1); + if (rv != SECSuccess) { + return SECFailure; + } + + rv = sslBuffer_AppendNumber(encodedTokenBuf, sid->u.ssl3.cipherSuite, 2); + if (rv != SECSuccess) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + rv = sslBuffer_AppendNumber(encodedTokenBuf, sid->u.ssl3.policy, 1); + if (rv != SECSuccess) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + + rv = sslBuffer_AppendVariable(encodedTokenBuf, + sid->u.ssl3.keys.wrapped_master_secret, + WRAPPED_MASTER_SECRET_SIZE, 1); + if (rv != SECSuccess) { + return SECFailure; + } + + rv = sslBuffer_AppendNumber(encodedTokenBuf, + sid->u.ssl3.keys.wrapped_master_secret_len, + 1); + if (rv != SECSuccess) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + rv = sslBuffer_AppendNumber(encodedTokenBuf, + sid->u.ssl3.keys.extendedMasterSecretUsed, + 1); + if (rv != SECSuccess) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + + rv = sslBuffer_AppendNumber(encodedTokenBuf, sid->u.ssl3.masterWrapMech, 8); + if (rv != SECSuccess) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + rv = sslBuffer_AppendNumber(encodedTokenBuf, sid->u.ssl3.masterModuleID, 8); + if (rv != SECSuccess) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + rv = sslBuffer_AppendNumber(encodedTokenBuf, sid->u.ssl3.masterSlotID, 8); + if (rv != SECSuccess) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + rv = sslBuffer_AppendNumber(encodedTokenBuf, sid->u.ssl3.masterWrapIndex, 4); + if (rv != SECSuccess) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + rv = sslBuffer_AppendNumber(encodedTokenBuf, sid->u.ssl3.masterWrapSeries, 2); + if (rv != SECSuccess) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + + rv = sslBuffer_AppendNumber(encodedTokenBuf, sid->u.ssl3.masterValid, 1); + if (rv != SECSuccess) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + + rv = sslBuffer_AppendVariable(encodedTokenBuf, sid->u.ssl3.srvName.data, + sid->u.ssl3.srvName.len, 1); + if (rv != SECSuccess) { + return SECFailure; + } + rv = sslBuffer_AppendVariable(encodedTokenBuf, + sid->u.ssl3.signedCertTimestamps.data, + sid->u.ssl3.signedCertTimestamps.len, 2); + if (rv != SECSuccess) { + return SECFailure; + } + + rv = sslBuffer_AppendVariable(encodedTokenBuf, + sid->u.ssl3.alpnSelection.data, + sid->u.ssl3.alpnSelection.len, 1); + if (rv != SECSuccess) { + return SECFailure; + } + + PORT_Assert(sid->u.ssl3.locked.sessionTicket.ticket.len > 1); + rv = sslBuffer_AppendVariable(encodedTokenBuf, + sid->u.ssl3.locked.sessionTicket.ticket.data, + sid->u.ssl3.locked.sessionTicket.ticket.len, + 2); + if (rv != SECSuccess) { + return SECFailure; + } + + return SECSuccess; +} + void -ssl_ChooseSessionIDProcs(sslSecurityInfo *sec) +ssl_CacheExternalToken(sslSocket *ss) { + PORT_Assert(ss); + sslSessionID *sid = ss->sec.ci.sid; + PORT_Assert(sid); + PORT_Assert(sid->cached == never_cached); + PORT_Assert(ss->resumptionTokenCallback); + + SSL_TRC(8, ("SSL [%d]: Cache External: sid=0x%x cached=%d " + "addr=0x%08x%08x%08x%08x port=0x%04x time=%x cached=%d", + ss->fd, + sid, sid->cached, sid->addr.pr_s6_addr32[0], + sid->addr.pr_s6_addr32[1], sid->addr.pr_s6_addr32[2], + sid->addr.pr_s6_addr32[3], sid->port, sid->creationTime, + sid->cached)); + + /* This is only available for stateless resumption. */ + if (sid->u.ssl3.locked.sessionTicket.ticket.data == NULL) { + return; + } + + /* Don't export token if the session used client authentication. */ + if (sid->u.ssl3.clAuthValid) { + return; + } + + if (!sid->creationTime) { + sid->lastAccessTime = sid->creationTime = ssl_TimeUsec(); + } + if (!sid->expirationTime) { + sid->expirationTime = sid->creationTime + ssl3_sid_timeout; + } + + sslBuffer encodedToken = SSL_BUFFER_EMPTY; + + if (ssl_EncodeResumptionToken(sid, &encodedToken) != SECSuccess) { + SSL_TRC(3, ("SSL [%d]: encoding resumption token failed", ss->fd)); + return; + } + PORT_Assert(SSL_BUFFER_LEN(&encodedToken) > 0); + PRINT_BUF(40, (ss, "SSL: encoded resumption token", + SSL_BUFFER_BASE(&encodedToken), + SSL_BUFFER_LEN(&encodedToken))); + ss->resumptionTokenCallback(ss->fd, SSL_BUFFER_BASE(&encodedToken), + SSL_BUFFER_LEN(&encodedToken), + ss->resumptionTokenContext); + + sslBuffer_Clear(&encodedToken); +} + +void +ssl_CacheSessionID(sslSocket *ss) +{ + sslSecurityInfo *sec = &ss->sec; + PORT_Assert(sec); + + if (sec->ci.sid && !sec->ci.sid->u.ssl3.keys.resumable) { + return; + } + + if (!ss->sec.isServer && ss->resumptionTokenCallback) { + ssl_CacheExternalToken(ss); + return; + } + + PORT_Assert(!ss->resumptionTokenCallback); if (sec->isServer) { - sec->cache = ssl_sid_cache; - sec->uncache = ssl_sid_uncache; - } else { - sec->cache = CacheSID; - sec->uncache = LockAndUncacheSID; + ssl_ServerCacheSessionID(sec->ci.sid); + return; + } + + CacheSID(sec->ci.sid); +} + +void +ssl_UncacheSessionID(sslSocket *ss) +{ + if (ss->opt.noCache) { + return; + } + + sslSecurityInfo *sec = &ss->sec; + PORT_Assert(sec); + + if (sec->ci.sid) { + if (sec->isServer) { + ssl_ServerUncacheSessionID(sec->ci.sid); + } else if (!ss->resumptionTokenCallback) { + LockAndUncacheSID(sec->ci.sid); + } } } diff --git a/security/nss/lib/ssl/sslsecur.c b/security/nss/lib/ssl/sslsecur.c index 3f7060f22..f09ec067c 100644 --- a/security/nss/lib/ssl/sslsecur.c +++ b/security/nss/lib/ssl/sslsecur.c @@ -599,9 +599,6 @@ ssl_CopySecurityInfo(sslSocket *ss, sslSocket *os) if (os->sec.peerCert && !ss->sec.peerCert) goto loser; - ss->sec.cache = os->sec.cache; - ss->sec.uncache = os->sec.uncache; - return SECSuccess; loser: @@ -1159,7 +1156,7 @@ SSL_InvalidateSession(PRFileDesc *fd) ssl_GetSSL3HandshakeLock(ss); if (ss->sec.ci.sid) { - ss->sec.uncache(ss->sec.ci.sid); + ssl_UncacheSessionID(ss); rv = SECSuccess; } diff --git a/security/nss/lib/ssl/sslsnce.c b/security/nss/lib/ssl/sslsnce.c index 279f3c015..d7abb3dc3 100644 --- a/security/nss/lib/ssl/sslsnce.c +++ b/security/nss/lib/ssl/sslsnce.c @@ -495,12 +495,6 @@ ConvertToSID(sidCacheEntry *from, PORT_Memcpy(to->u.ssl3.sessionID, from->sessionID, from->sessionIDLength); - /* the portions of the SID that are only restored on the client - * are set to invalid values on the server. - */ - to->u.ssl3.clientWriteKey = NULL; - to->u.ssl3.serverWriteKey = NULL; - to->urlSvrName = NULL; to->u.ssl3.masterModuleID = (SECMODModuleID)-1; /* invalid value */ @@ -735,9 +729,11 @@ ServerSessionIDLookup(const PRIPv6Addr *addr, /* ** Place a sid into the cache, if it isn't already there. */ -static void -ServerSessionIDCache(sslSessionID *sid) +void +ssl_ServerCacheSessionID(sslSessionID *sid) { + PORT_Assert(sid); + sidCacheEntry sce; PRUint32 now = 0; cacheDesc *cache = &globalCache; @@ -800,8 +796,8 @@ ServerSessionIDCache(sslSessionID *sid) ** Although this is static, it is called from ssl via global function pointer ** ssl_sid_uncache. This invalidates the referenced cache entry. */ -static void -ServerSessionIDUncache(sslSessionID *sid) +void +ssl_ServerUncacheSessionID(sslSessionID *sid) { cacheDesc *cache = &globalCache; PRUint8 *sessionID; @@ -1172,8 +1168,6 @@ ssl_ConfigServerSessionIDCacheInstanceWithOpt(cacheDesc *cache, } ssl_sid_lookup = ServerSessionIDLookup; - ssl_sid_cache = ServerSessionIDCache; - ssl_sid_uncache = ServerSessionIDUncache; return SECSuccess; } @@ -1356,8 +1350,6 @@ SSL_InheritMPServerSIDCacheInstance(cacheDesc *cache, const char *envString) ssl_InitSessionCacheLocks(PR_FALSE); ssl_sid_lookup = ServerSessionIDLookup; - ssl_sid_cache = ServerSessionIDCache; - ssl_sid_uncache = ServerSessionIDUncache; if (!envString) { envString = PR_GetEnvSecure(envVarName); diff --git a/security/nss/lib/ssl/sslsock.c b/security/nss/lib/ssl/sslsock.c index 4893cb9f9..e08d5e232 100644 --- a/security/nss/lib/ssl/sslsock.c +++ b/security/nss/lib/ssl/sslsock.c @@ -53,34 +53,35 @@ static const sslSocketOps ssl_secure_ops = { /* SSL. */ ** default settings for socket enables */ static sslOptions ssl_defaults = { - { siBuffer, NULL, 0 }, /* nextProtoNego */ - PR_TRUE, /* useSecurity */ - PR_FALSE, /* useSocks */ - PR_FALSE, /* requestCertificate */ - 2, /* requireCertificate */ - PR_FALSE, /* handshakeAsClient */ - PR_FALSE, /* handshakeAsServer */ - PR_FALSE, /* noCache */ - PR_FALSE, /* fdx */ - PR_TRUE, /* detectRollBack */ - PR_FALSE, /* noLocks */ - PR_FALSE, /* enableSessionTickets */ - PR_FALSE, /* enableDeflate */ - 2, /* enableRenegotiation (default: requires extension) */ - PR_FALSE, /* requireSafeNegotiation */ - PR_FALSE, /* enableFalseStart */ - PR_TRUE, /* cbcRandomIV */ - PR_FALSE, /* enableOCSPStapling */ - PR_FALSE, /* enableNPN */ - PR_TRUE, /* enableALPN */ - PR_TRUE, /* reuseServerECDHEKey */ - PR_FALSE, /* enableFallbackSCSV */ - PR_TRUE, /* enableServerDhe */ - PR_FALSE, /* enableExtendedMS */ - PR_FALSE, /* enableSignedCertTimestamps */ - PR_FALSE, /* requireDHENamedGroups */ - PR_FALSE, /* enable0RttData */ - PR_FALSE /* enableTls13CompatMode */ + .nextProtoNego = { siBuffer, NULL, 0 }, + .maxEarlyDataSize = 1 << 16, + .useSecurity = PR_TRUE, + .useSocks = PR_FALSE, + .requestCertificate = PR_FALSE, + .requireCertificate = SSL_REQUIRE_FIRST_HANDSHAKE, + .handshakeAsClient = PR_FALSE, + .handshakeAsServer = PR_FALSE, + .noCache = PR_FALSE, + .fdx = PR_FALSE, + .detectRollBack = PR_TRUE, + .noLocks = PR_FALSE, + .enableSessionTickets = PR_FALSE, + .enableDeflate = PR_FALSE, + .enableRenegotiation = SSL_RENEGOTIATE_REQUIRES_XTN, + .requireSafeNegotiation = PR_FALSE, + .enableFalseStart = PR_FALSE, + .cbcRandomIV = PR_TRUE, + .enableOCSPStapling = PR_FALSE, + .enableNPN = PR_FALSE, + .enableALPN = PR_TRUE, + .reuseServerECDHEKey = PR_TRUE, + .enableFallbackSCSV = PR_FALSE, + .enableServerDhe = PR_TRUE, + .enableExtendedMS = PR_FALSE, + .enableSignedCertTimestamps = PR_FALSE, + .requireDHENamedGroups = PR_FALSE, + .enable0RttData = PR_FALSE, + .enableTls13CompatMode = PR_FALSE }; /* @@ -104,8 +105,6 @@ static SSLVersionRange versions_defaults_datagram = { (variant == ssl_variant_stream ? NSS_TLS_VERSION_MAX_POLICY : NSS_DTLS_VERSION_MAX_POLICY) sslSessionIDLookupFunc ssl_sid_lookup; -sslSessionIDCacheFunc ssl_sid_cache; -sslSessionIDUncacheFunc ssl_sid_uncache; static PRDescIdentity ssl_layer_id; @@ -356,6 +355,8 @@ ssl_DupSocket(sslSocket *os) os->namedGroupPreferences, sizeof(ss->namedGroupPreferences)); ss->additionalShares = os->additionalShares; + ss->resumptionTokenCallback = os->resumptionTokenCallback; + ss->resumptionTokenContext = os->resumptionTokenContext; /* Create security data */ rv = ssl_CopySecurityInfo(ss, os); @@ -1252,6 +1253,18 @@ SSL_OptionSetDefault(PRInt32 which, PRIntn val) return SECSuccess; } +SECStatus +SSLExp_SetMaxEarlyDataSize(PRFileDesc *fd, PRUint32 size) +{ + sslSocket *ss = ssl_FindSocket(fd); + if (!ss) { + return SECFailure; /* Error code already set. */ + } + + ss->opt.maxEarlyDataSize = size; + return SECSuccess; +} + /* function tells us if the cipher suite is one that we no longer support. */ static PRBool ssl_IsRemovedCipherSuite(PRInt32 suite) @@ -3932,7 +3945,12 @@ struct { EXP(InstallExtensionHooks), EXP(KeyUpdate), EXP(SendSessionTicket), + EXP(SetMaxEarlyDataSize), EXP(SetupAntiReplay), + EXP(SetResumptionTokenCallback), + EXP(SetResumptionToken), + EXP(GetResumptionTokenInfo), + EXP(DestroyResumptionTokenInfo), #endif { "", NULL } }; @@ -3967,3 +3985,156 @@ ssl_ClearPRCList(PRCList *list, void (*f)(void *)) PORT_Free(cursor); } } + +/* Experimental APIs for session cache handling. */ + +SECStatus +SSLExp_SetResumptionTokenCallback(PRFileDesc *fd, + SSLResumptionTokenCallback cb, + void *ctx) +{ + sslSocket *ss = ssl_FindSocket(fd); + + if (!ss) { + SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetResumptionTokenCallback", + SSL_GETPID(), fd)); + return SECFailure; + } + + ssl_Get1stHandshakeLock(ss); + ssl_GetSSL3HandshakeLock(ss); + ss->resumptionTokenCallback = cb; + ss->resumptionTokenContext = ctx; + ssl_ReleaseSSL3HandshakeLock(ss); + ssl_Release1stHandshakeLock(ss); + + return SECSuccess; +} + +SECStatus +SSLExp_SetResumptionToken(PRFileDesc *fd, const PRUint8 *token, + unsigned int len) +{ + sslSocket *ss = ssl_FindSocket(fd); + + if (!ss) { + SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetResumptionToken", + SSL_GETPID(), fd)); + return SECFailure; + } + + ssl_Get1stHandshakeLock(ss); + ssl_GetSSL3HandshakeLock(ss); + + if (ss->firstHsDone || ss->ssl3.hs.ws != idle_handshake || + ss->sec.isServer || len == 0 || !token) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + goto done; + } + + // We override any previously set session. + if (ss->sec.ci.sid) { + ssl_FreeSID(ss->sec.ci.sid); + ss->sec.ci.sid = NULL; + } + + PRINT_BUF(50, (ss, "incoming resumption token", token, len)); + + ss->sec.ci.sid = ssl3_NewSessionID(ss, PR_FALSE); + if (!ss->sec.ci.sid) { + goto done; + } + + /* Populate NewSessionTicket values */ + SECStatus rv = ssl_DecodeResumptionToken(ss->sec.ci.sid, token, len); + if (rv != SECSuccess) { + // If decoding fails, we assume the token is bad. + PORT_SetError(SSL_ERROR_BAD_RESUMPTION_TOKEN_ERROR); + ssl_FreeSID(ss->sec.ci.sid); + ss->sec.ci.sid = NULL; + goto done; + } + + // Make sure that the token is valid. + if (!ssl_IsResumptionTokenValid(ss)) { + ssl_FreeSID(ss->sec.ci.sid); + ss->sec.ci.sid = NULL; + PORT_SetError(SSL_ERROR_BAD_RESUMPTION_TOKEN_ERROR); + goto done; + } + + /* Use the sid->cached as marker that this is from an external cache and + * we don't have to look up anything in the NSS internal cache. */ + ss->sec.ci.sid->cached = in_external_cache; + // This has to be 2 to not free this in sendClientHello. + ss->sec.ci.sid->references = 2; + ss->sec.ci.sid->lastAccessTime = ssl_TimeSec(); + + ssl_ReleaseSSL3HandshakeLock(ss); + ssl_Release1stHandshakeLock(ss); + return SECSuccess; + +done: + ssl_ReleaseSSL3HandshakeLock(ss); + ssl_Release1stHandshakeLock(ss); + + return SECFailure; +} + +SECStatus +SSLExp_DestroyResumptionTokenInfo(SSLResumptionTokenInfo *token) +{ + if (!token) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + if (token->peerCert) { + CERT_DestroyCertificate(token->peerCert); + } + PORT_Free(token->alpnSelection); + PORT_Memset(token, 0, token->length); + return SECSuccess; +} + +SECStatus +SSLExp_GetResumptionTokenInfo(const PRUint8 *tokenData, unsigned int tokenLen, + SSLResumptionTokenInfo *tokenOut, PRUintn len) +{ + if (!tokenData || !tokenOut || !tokenLen || + len > sizeof(SSLResumptionTokenInfo)) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + sslSessionID sid = { 0 }; + SSLResumptionTokenInfo token; + + /* Populate sid values */ + if (ssl_DecodeResumptionToken(&sid, tokenData, tokenLen) != SECSuccess) { + // If decoding fails, we assume the token is bad. + PORT_SetError(SSL_ERROR_BAD_RESUMPTION_TOKEN_ERROR); + return SECFailure; + } + + token.peerCert = CERT_DupCertificate(sid.peerCert); + + token.alpnSelectionLen = sid.u.ssl3.alpnSelection.len; + token.alpnSelection = PORT_ZAlloc(token.alpnSelectionLen); + if (!token.alpnSelection) { + return SECFailure; + } + PORT_Memcpy(token.alpnSelection, sid.u.ssl3.alpnSelection.data, + token.alpnSelectionLen); + + if (sid.u.ssl3.locked.sessionTicket.flags & ticket_allow_early_data) { + token.maxEarlyDataSize = + sid.u.ssl3.locked.sessionTicket.max_early_data_size; + } else { + token.maxEarlyDataSize = 0; + } + + token.length = PR_MIN(sizeof(SSLResumptionTokenInfo), len); + PORT_Memcpy(tokenOut, &token, token.length); + + ssl_DestroySID(&sid, PR_FALSE); + return SECSuccess; +} diff --git a/security/nss/lib/ssl/sslt.h b/security/nss/lib/ssl/sslt.h index ce8f6e281..e2b80fb43 100644 --- a/security/nss/lib/ssl/sslt.h +++ b/security/nss/lib/ssl/sslt.h @@ -123,11 +123,14 @@ typedef enum { ssl_sig_ecdsa_secp256r1_sha256 = 0x0403, ssl_sig_ecdsa_secp384r1_sha384 = 0x0503, ssl_sig_ecdsa_secp521r1_sha512 = 0x0603, - ssl_sig_rsa_pss_sha256 = 0x0804, - ssl_sig_rsa_pss_sha384 = 0x0805, - ssl_sig_rsa_pss_sha512 = 0x0806, + ssl_sig_rsa_pss_rsae_sha256 = 0x0804, + ssl_sig_rsa_pss_rsae_sha384 = 0x0805, + ssl_sig_rsa_pss_rsae_sha512 = 0x0806, ssl_sig_ed25519 = 0x0807, ssl_sig_ed448 = 0x0808, + ssl_sig_rsa_pss_pss_sha256 = 0x0809, + ssl_sig_rsa_pss_pss_sha384 = 0x080a, + ssl_sig_rsa_pss_pss_sha512 = 0x080b, ssl_sig_dsa_sha1 = 0x0202, ssl_sig_dsa_sha256 = 0x0402, @@ -143,20 +146,25 @@ typedef enum { ssl_sig_rsa_pkcs1_sha1md5 = 0x10101, } SSLSignatureScheme; +/* Deprecated names maintained only for source compatibility. */ +#define ssl_sig_rsa_pss_sha256 ssl_sig_rsa_pss_rsae_sha256 +#define ssl_sig_rsa_pss_sha384 ssl_sig_rsa_pss_rsae_sha384 +#define ssl_sig_rsa_pss_sha512 ssl_sig_rsa_pss_rsae_sha512 + /* ** SSLAuthType describes the type of key that is used to authenticate a ** connection. That is, the type of key in the end-entity certificate. */ typedef enum { ssl_auth_null = 0, - ssl_auth_rsa_decrypt = 1, /* static RSA */ + ssl_auth_rsa_decrypt = 1, /* RSA key exchange. */ ssl_auth_dsa = 2, ssl_auth_kea = 3, /* unused */ ssl_auth_ecdsa = 4, - ssl_auth_ecdh_rsa = 5, /* ECDH cert with an RSA signature */ - ssl_auth_ecdh_ecdsa = 6, /* ECDH cert with an ECDSA signature */ - ssl_auth_rsa_sign = 7, /* RSA PKCS#1.5 signing */ - ssl_auth_rsa_pss = 8, + ssl_auth_ecdh_rsa = 5, /* ECDH cert with an RSA signature. */ + ssl_auth_ecdh_ecdsa = 6, /* ECDH cert with an ECDSA signature. */ + ssl_auth_rsa_sign = 7, /* RSA signing with an rsaEncryption key. */ + ssl_auth_rsa_pss = 8, /* RSA signing with a PSS key. */ ssl_auth_psk = 9, ssl_auth_tls13_any = 10, ssl_auth_size /* number of authentication types */ diff --git a/security/nss/lib/ssl/tls13con.c b/security/nss/lib/ssl/tls13con.c index 1fecaf3f8..c06acc83a 100644 --- a/security/nss/lib/ssl/tls13con.c +++ b/security/nss/lib/ssl/tls13con.c @@ -462,7 +462,7 @@ tls13_SetupClientHello(sslSocket *ss) if (rv != SECSuccess) { FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error); SSL_AtomicIncrementLong(&ssl3stats->sch_sid_cache_not_ok); - ss->sec.uncache(ss->sec.ci.sid); + ssl_UncacheSessionID(ss); ssl_FreeSID(ss->sec.ci.sid); ss->sec.ci.sid = NULL; return SECFailure; @@ -1426,9 +1426,9 @@ ssl_SignatureSchemeToAuthType(SSLSignatureScheme scheme) case ssl_sig_rsa_pkcs1_sha384: case ssl_sig_rsa_pkcs1_sha512: /* We report PSS signatures as being just RSA signatures. */ - case ssl_sig_rsa_pss_sha256: - case ssl_sig_rsa_pss_sha384: - case ssl_sig_rsa_pss_sha512: + case ssl_sig_rsa_pss_rsae_sha256: + case ssl_sig_rsa_pss_rsae_sha384: + case ssl_sig_rsa_pss_rsae_sha512: return ssl_auth_rsa_sign; case ssl_sig_ecdsa_secp256r1_sha256: case ssl_sig_ecdsa_secp384r1_sha384: @@ -1719,7 +1719,7 @@ tls13_HandleClientHelloPart2(sslSocket *ss, } if (hrr) { if (sid) { /* Free the sid. */ - ss->sec.uncache(sid); + ssl_UncacheSessionID(ss); ssl_FreeSID(sid); } PORT_Assert(ss->ssl3.hs.helloRetry); @@ -1769,8 +1769,7 @@ tls13_HandleClientHelloPart2(sslSocket *ss, } else { if (sid) { /* we had a sid, but it's no longer valid, free it */ SSL_AtomicIncrementLong(&ssl3stats->hch_sid_cache_not_ok); - if (ss->sec.uncache) - ss->sec.uncache(sid); + ssl_UncacheSessionID(ss); ssl_FreeSID(sid); sid = NULL; } @@ -1830,7 +1829,7 @@ tls13_HandleClientHelloPart2(sslSocket *ss, if (sid) { /* We had a sid, but it's no longer valid, free it. */ SSL_AtomicIncrementLong(&ssl3stats->hch_sid_cache_not_ok); - ss->sec.uncache(sid); + ssl_UncacheSessionID(ss); ssl_FreeSID(sid); } else { SSL_AtomicIncrementLong(&ssl3stats->hch_sid_cache_misses); @@ -1866,7 +1865,7 @@ tls13_HandleClientHelloPart2(sslSocket *ss, loser: if (sid) { - ss->sec.uncache(sid); + ssl_UncacheSessionID(ss); ssl_FreeSID(sid); } return SECFailure; @@ -2539,7 +2538,7 @@ tls13_HandleServerHelloPart2(sslSocket *ss) } if (sid->cached == in_client_cache) { /* If we tried to resume and failed, let's not try again. */ - ss->sec.uncache(sid); + ssl_UncacheSessionID(ss); } } @@ -4418,8 +4417,6 @@ tls13_SendClientSecondRound(sslSocket *ss) * } NewSessionTicket; */ -PRUint32 ssl_max_early_data_size = (2 << 16); /* Arbitrary limit. */ - static SECStatus tls13_SendNewSessionTicket(sslSocket *ss, const PRUint8 *appToken, unsigned int appTokenLen) @@ -4521,7 +4518,7 @@ tls13_SendNewSessionTicket(sslSocket *ss, const PRUint8 *appToken, if (rv != SECSuccess) goto loser; - rv = ssl3_AppendHandshakeNumber(ss, ssl_max_early_data_size, 4); + rv = ssl3_AppendHandshakeNumber(ss, ss->opt.maxEarlyDataSize, 4); if (rv != SECSuccess) goto loser; } @@ -4681,7 +4678,7 @@ tls13_HandleNewSessionTicket(sslSocket *ss, PRUint8 *b, PRUint32 length) } /* Destroy the old SID. */ - ss->sec.uncache(ss->sec.ci.sid); + ssl_UncacheSessionID(ss); ssl_FreeSID(ss->sec.ci.sid); ss->sec.ci.sid = sid; } @@ -4707,7 +4704,7 @@ tls13_HandleNewSessionTicket(sslSocket *ss, PRUint8 *b, PRUint32 length) } /* Cache the session. */ - ss->sec.cache(ss->sec.ci.sid); + ssl_CacheSessionID(ss); } return SECSuccess; @@ -4772,9 +4769,6 @@ tls13_ExtensionStatus(PRUint16 extension, SSLHandshakeType message) /* Return "disallowed" if the message mask bit isn't set. */ if (!(_M(message) & KnownExtensions[i].messages)) { - SSL_TRC(3, ("%d: TLS13: unexpected extension %d in message %d", - SSL_GETPID(), extension, message)); - return tls13_extension_disallowed; } diff --git a/security/nss/lib/ssl/tls13hashstate.c b/security/nss/lib/ssl/tls13hashstate.c index e3232f524..cc0ed286b 100644 --- a/security/nss/lib/ssl/tls13hashstate.c +++ b/security/nss/lib/ssl/tls13hashstate.c @@ -88,36 +88,37 @@ tls13_RecoverHashState(sslSocket *ss, { SECStatus rv; unsigned char plaintext[1024]; - SECItem ptItem = { siBuffer, plaintext, 0 }; + unsigned int plaintextLen = 0; sslBuffer messageBuf = SSL_BUFFER_EMPTY; - PRUint32 sentinel; - PRUint32 cipherSuite; - PRUint32 group; + PRUint64 sentinel; + PRUint64 cipherSuite; + PRUint64 group; const sslNamedGroupDef *selectedGroup; - PRUint32 appTokenLen; - PRUint8 *appToken; + PRUint64 appTokenLen; rv = ssl_SelfEncryptUnprotect(ss, cookie, cookieLen, - ptItem.data, &ptItem.len, sizeof(plaintext)); + plaintext, &plaintextLen, sizeof(plaintext)); if (rv != SECSuccess) { return SECFailure; } + sslReader reader = SSL_READER(plaintext, plaintextLen); + /* Should start with 0xff. */ - rv = ssl3_ConsumeNumberFromItem(&ptItem, &sentinel, 1); + rv = sslRead_ReadNumber(&reader, 1, &sentinel); if ((rv != SECSuccess) || (sentinel != 0xff)) { FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CLIENT_HELLO, illegal_parameter); return SECFailure; } /* The cipher suite should be the same or there are some shenanigans. */ - rv = ssl3_ConsumeNumberFromItem(&ptItem, &cipherSuite, 2); + rv = sslRead_ReadNumber(&reader, 2, &cipherSuite); if (rv != SECSuccess) { FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CLIENT_HELLO, illegal_parameter); return SECFailure; } /* The named group, if any. */ - rv = ssl3_ConsumeNumberFromItem(&ptItem, &group, 2); + rv = sslRead_ReadNumber(&reader, 2, &group); if (rv != SECSuccess) { FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CLIENT_HELLO, illegal_parameter); return SECFailure; @@ -126,7 +127,7 @@ tls13_RecoverHashState(sslSocket *ss, /* Application token. */ PORT_Assert(ss->xtnData.applicationToken.len == 0); - rv = ssl3_ConsumeNumberFromItem(&ptItem, &appTokenLen, 2); + rv = sslRead_ReadNumber(&reader, 2, &appTokenLen); if (rv != SECSuccess) { FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CLIENT_HELLO, illegal_parameter); return SECFailure; @@ -137,15 +138,18 @@ tls13_RecoverHashState(sslSocket *ss, return SECFailure; } ss->xtnData.applicationToken.len = appTokenLen; - rv = ssl3_ConsumeFromItem(&ptItem, &appToken, appTokenLen); + sslReadBuffer appTokenReader = { 0 }; + rv = sslRead_Read(&reader, appTokenLen, &appTokenReader); if (rv != SECSuccess) { FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CLIENT_HELLO, illegal_parameter); return SECFailure; } - PORT_Memcpy(ss->xtnData.applicationToken.data, appToken, appTokenLen); + PORT_Assert(appTokenReader.len == appTokenLen); + PORT_Memcpy(ss->xtnData.applicationToken.data, appTokenReader.buf, appTokenLen); /* The remainder is the hash. */ - if (ptItem.len != tls13_GetHashSize(ss)) { + unsigned int hashLen = SSL_READER_REMAINING(&reader); + if (hashLen != tls13_GetHashSize(ss)) { FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CLIENT_HELLO, illegal_parameter); return SECFailure; } @@ -153,7 +157,7 @@ tls13_RecoverHashState(sslSocket *ss, /* Now reinject the message. */ SSL_ASSERT_HASHES_EMPTY(ss); rv = ssl_HashHandshakeMessageInt(ss, ssl_hs_message_hash, 0, - ptItem.data, ptItem.len); + SSL_READER_CURRENT(&reader), hashLen); if (rv != SECSuccess) { return SECFailure; } diff --git a/security/nss/lib/util/nssutil.h b/security/nss/lib/util/nssutil.h index f86dfa91e..b65d4a0c9 100644 --- a/security/nss/lib/util/nssutil.h +++ b/security/nss/lib/util/nssutil.h @@ -19,10 +19,10 @@ * The format of the version string should be * ".[.[.]][ ]" */ -#define NSSUTIL_VERSION "3.35" +#define NSSUTIL_VERSION "3.36.4" #define NSSUTIL_VMAJOR 3 -#define NSSUTIL_VMINOR 35 -#define NSSUTIL_VPATCH 0 +#define NSSUTIL_VMINOR 36 +#define NSSUTIL_VPATCH 4 #define NSSUTIL_VBUILD 0 #define NSSUTIL_BETA PR_FALSE diff --git a/security/nss/lib/util/secasn1d.c b/security/nss/lib/util/secasn1d.c index 4c5f0ce4b..ccd97481d 100644 --- a/security/nss/lib/util/secasn1d.c +++ b/security/nss/lib/util/secasn1d.c @@ -175,7 +175,7 @@ static int /* bool */ } } } else { - sprintf(buf, " [%d]", k); + sprintf(buf, " [%lu]", k); } buf += strlen(buf); @@ -982,7 +982,7 @@ sec_asn1d_prepare_for_contents(sec_asn1d_state *state) #ifdef DEBUG_ASN1D_STATES { - printf("Found Length %d %s\n", state->contents_length, + printf("Found Length %lu %s\n", state->contents_length, state->indefinite ? "indefinite" : ""); } #endif @@ -2717,16 +2717,15 @@ dump_states(SEC_ASN1DecoderContext *cx) } i = formatKind(state->theTemplate->kind, kindBuf); - printf("%s: tmpl %08x, kind%s", + printf("%s: tmpl kind %s", (state == cx->current) ? "STATE" : "State", - state->theTemplate, kindBuf); printf(" %s", (state->place >= 0 && state->place <= notInUse) ? place_names[state->place] : "(undefined)"); if (!i) - printf(", expect 0x%02x", + printf(", expect 0x%02lx", state->expect_tag_number | state->expect_tag_modifiers); - printf("%s%s%s %d\n", + printf("%s%s%s %lu\n", state->indefinite ? ", indef" : "", state->missing ? ", miss" : "", state->endofcontents ? ", EOC" : "", @@ -2754,7 +2753,7 @@ SEC_ASN1DecoderUpdate(SEC_ASN1DecoderContext *cx, what = SEC_ASN1_Contents; consumed = 0; #ifdef DEBUG_ASN1D_STATES - printf("\nPLACE = %s, next byte = 0x%02x, %08x[%d]\n", + printf("\nPLACE = %s, next byte = 0x%02x, %p[%lu]\n", (state->place >= 0 && state->place <= notInUse) ? place_names[state->place] : "(undefined)", len ? (unsigned int)((unsigned char *)buf)[consumed] : 0, buf, consumed); @@ -2977,7 +2976,7 @@ SEC_ASN1DecoderFinish(SEC_ASN1DecoderContext *cx) { SECStatus rv; - if (cx->status == needBytes) { + if (!cx || cx->status == needBytes) { PORT_SetError(SEC_ERROR_BAD_DER); rv = SECFailure; } else { diff --git a/security/nss/nss-tool/hw-support.c b/security/nss/nss-tool/hw-support.c new file mode 100644 index 000000000..0aa097ffc --- /dev/null +++ b/security/nss/nss-tool/hw-support.c @@ -0,0 +1,37 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifdef FREEBL_NO_DEPEND +#include "stubs.h" +#endif + +/* This is a freebl command line utility that prints hardware support as freebl + * sees it from its detection in blinit.c + */ + +#include + +#include "blapi.h" +#include "blapii.h" +#include "nss.h" + +int main(int argc, char const *argv[]) { + BL_Init(); + printf("\n\n ========== NSS Hardware Report ==========\n"); +#if defined(NSS_X86_OR_X64) + printf("\tAES-NI \t%s supported\n", aesni_support() ? "" : "not"); + printf("\tPCLMUL \t%s supported\n", clmul_support() ? "" : "not"); + printf("\tAVX \t%s supported\n", avx_support() ? "" : "not"); + printf("\tSSSE3 \t%s supported\n", ssse3_support() ? "" : "not"); +#elif defined(__aarch64__) || defined(__arm__) + printf("\tNEON \t%s supported\n", arm_neon_support() ? "" : "not"); + printf("\tAES \t%s supported\n", arm_aes_support() ? "" : "not"); + printf("\tPMULL \t%s supported\n", arm_pmull_support() ? "" : "not"); + printf("\tSHA1 \t%s supported\n", arm_sha1_support() ? "" : "not"); + printf("\tSHA2 \t%s supported\n", arm_sha2_support() ? "" : "not"); +#endif + printf(" ========== Hardware Report End ==========\n\n\n"); + BL_Cleanup(); + return 0; +} diff --git a/security/nss/nss-tool/nss_tool.gyp b/security/nss/nss-tool/nss_tool.gyp index a5d03fcf9..d0741b426 100644 --- a/security/nss/nss-tool/nss_tool.gyp +++ b/security/nss/nss-tool/nss_tool.gyp @@ -26,6 +26,43 @@ '<(DEPTH)/exports.gyp:dbm_exports', '<(DEPTH)/exports.gyp:nss_exports', ], - } + }, + { + 'target_name': 'hw-support', + 'type': 'executable', + 'sources': [ + 'hw-support.c', + ], + 'conditions': [ + [ 'OS=="win"', { + 'libraries': [ + 'advapi32.lib', + ], + }], + ], + 'dependencies' : [ + '<(DEPTH)/exports.gyp:nss_exports', + '<(DEPTH)/lib/util/util.gyp:nssutil3', + '<(DEPTH)/lib/nss/nss.gyp:nss_static', + '<(DEPTH)/lib/pk11wrap/pk11wrap.gyp:pk11wrap_static', + '<(DEPTH)/lib/cryptohi/cryptohi.gyp:cryptohi', + '<(DEPTH)/lib/certhigh/certhigh.gyp:certhi', + '<(DEPTH)/lib/certdb/certdb.gyp:certdb', + '<(DEPTH)/lib/base/base.gyp:nssb', + '<(DEPTH)/lib/dev/dev.gyp:nssdev', + '<(DEPTH)/lib/pki/pki.gyp:nsspki', + ], + 'include_dirs': [ + '<(DEPTH)/lib/freebl', + '<(DEPTH)/lib/freebl/mpi', + ], + 'defines': [ + 'NSS_USE_STATIC_LIBS' + ], + 'variables': { + 'module': 'nss', + 'use_static_libs': 1 + }, + }, ], } diff --git a/security/nss/nss.gyp b/security/nss/nss.gyp index 9e9b49f7f..36b0dd974 100644 --- a/security/nss/nss.gyp +++ b/security/nss/nss.gyp @@ -107,6 +107,7 @@ 'cmd/ssltap/ssltap.gyp:ssltap', 'cmd/symkeyutil/symkeyutil.gyp:symkeyutil', 'nss-tool/nss_tool.gyp:nss', + 'nss-tool/nss_tool.gyp:hw-support', ], }], ], @@ -123,7 +124,6 @@ 'cmd/atob/atob.gyp:atob', 'cmd/bltest/bltest.gyp:bltest', 'cmd/btoa/btoa.gyp:btoa', - 'cmd/certcgi/certcgi.gyp:certcgi', 'cmd/chktest/chktest.gyp:chktest', 'cmd/crmftest/crmftest.gyp:crmftest', 'cmd/dbtest/dbtest.gyp:dbtest', diff --git a/security/nss/tests/all.sh b/security/nss/tests/all.sh index 8d5bd2dbb..3a02debef 100755 --- a/security/nss/tests/all.sh +++ b/security/nss/tests/all.sh @@ -325,6 +325,11 @@ NSS_SSL_RUN="${NSS_SSL_RUN:-$nss_ssl_run}" ENV_BACKUP=${HOSTDIR}/env.sh env_backup > ${ENV_BACKUP} +# Print hardware support if we built it. +if [ -f ${BINDIR}/hw-support ]; then + ${BINDIR}/hw-support +fi + if [ "${O_CRON}" = "ON" ]; then run_cycles >> ${LOGFILE} else diff --git a/security/nss/tests/bogo/bogo.sh b/security/nss/tests/bogo/bogo.sh index 26dfb0abb..d1a93bf9b 100755 --- a/security/nss/tests/bogo/bogo.sh +++ b/security/nss/tests/bogo/bogo.sh @@ -25,7 +25,7 @@ bogo_init() BORING=${BORING:=boringssl} if [ ! -d "$BORING" ]; then git clone -q https://boringssl.googlesource.com/boringssl "$BORING" - git -C "$BORING" checkout -q bbfe603519bc54fbc4c8dd87efe1ed385df550b4 + git -C "$BORING" checkout -q a513e86c1ebb1383930c9e504bdabcc302a85f30 fi SCRIPTNAME="bogo.sh" diff --git a/security/nss/tests/common/cleanup.sh b/security/nss/tests/common/cleanup.sh index 40885bc79..97c139321 100755 --- a/security/nss/tests/common/cleanup.sh +++ b/security/nss/tests/common/cleanup.sh @@ -30,6 +30,8 @@ if [ -z "${CLEANUP}" -o "${CLEANUP}" = "${SCRIPTNAME}" ]; then echo "NSS_DISABLE_HW_AES=${NSS_DISABLE_HW_AES}" echo "NSS_DISABLE_PCLMUL=${NSS_DISABLE_PCLMUL}" echo "NSS_DISABLE_AVX=${NSS_DISABLE_AVX}" + echo "NSS_DISABLE_ARM_NEON=${NSS_DISABLE_ARM_NEON}" + echo "NSS_DISABLE_SSSE3=${NSS_DISABLE_SSSE3}" echo echo "Tests summary:" echo "--------------" diff --git a/security/nss/tests/interop/interop.sh b/security/nss/tests/interop/interop.sh index 59f0cb481..97c82e0ca 100644 --- a/security/nss/tests/interop/interop.sh +++ b/security/nss/tests/interop/interop.sh @@ -24,7 +24,8 @@ interop_init() cd "${HOSTDIR}/interop" INTEROP=${INTEROP:=tls_interop} if [ ! -d "$INTEROP" ]; then - git clone -q https://github.com/mozilla/tls-interop "$INTEROP" + git clone -q https://github.com/ttaubert/tls-interop "$INTEROP" + git -C "$INTEROP" checkout -q 07930b791827c1bdb6f4c19ca0aa63850fd59e22 fi INTEROP=$(cd "$INTEROP";pwd -P) @@ -56,7 +57,12 @@ interop_run() (cd "$INTEROP"; cargo run -- --client "$client" --server "$server" --rootdir "$BORING"/ssl/test/runner/ --test-cases cases.json) 2>interop-${test_name}.errors | tee interop-${test_name}.log - html_msg "${PIPESTATUS[0]}" 0 "Interop" "Run successfully" + RESULT=${PIPESTATUS[0]} + html_msg "${RESULT}" 0 "Interop" "Run successfully" + if [ $RESULT -ne 0 ]; then + cat interop-${test_name}.errors + cat interop-${test_name}.log + fi grep -i 'FAILED\|Assertion failure' interop-${test_name}.errors html_msg $? 1 "Interop" "No failures" } -- cgit v1.2.3