зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1432177 - land NSS 10f7e0179b18 UPGRADE_NSS_RELEASE, r=me
--HG-- extra : rebase_source : 73060b7dd79b86f22b4f53d2d3491266b1968904
This commit is contained in:
Родитель
3bdf7ef24a
Коммит
cdd881cf58
|
@ -1 +1 @@
|
|||
NSS_3_35_RTM
|
||||
10f7e0179b18
|
||||
|
|
|
@ -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}
|
||||
|
||||
|
|
@ -1,3 +1,28 @@
|
|||
Functions changes summary: 0 Removed, 0 Changed (5 filtered out), 0 Added function
|
||||
Functions changes summary: 0 Removed, 1 Changed (2 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(SSLChannelInfo*, PRUintn)' at sslinfo.c:12:1 has some indirect sub-type changes:
|
||||
parameter 1 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:259:1 changed:
|
||||
1 data member change:
|
||||
type of 'SSLSignatureScheme SSLChannelInfoStr::signatureScheme' changed:
|
||||
underlying type 'enum __anonymous_enum__' 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'
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
NSS_3_34_BRANCH
|
||||
NSS_3_35_BRANCH
|
||||
|
|
|
@ -269,9 +269,43 @@ check_abi()
|
|||
abidiff --hd1 $PREVDIST/public/ --hd2 $NEWDIST/public \
|
||||
$PREVDIST/*/lib/$SO $NEWDIST/*/lib/$SO \
|
||||
> ${HGDIR}/nss/automation/abi-check/new-report-$SO.txt
|
||||
if [ $? -ne 0 ]; then
|
||||
RET=$?
|
||||
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
|
||||
|
|
|
@ -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
|
|
@ -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));
|
|
@ -0,0 +1,357 @@
|
|||
/*
|
||||
** ChaCha20 specification
|
||||
** Author: Austin Seipp <aseipp@pobox.com>. 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)
|
|
@ -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));
|
|
@ -0,0 +1,46 @@
|
|||
FROM ubuntu:latest
|
||||
MAINTAINER Tim Taubert <ttaubert@mozilla.com>
|
||||
|
||||
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"]
|
Двоичный файл не отображается.
|
@ -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
|
|
@ -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) || " +
|
||||
|
@ -991,5 +996,56 @@ 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"
|
||||
]
|
||||
}));
|
||||
|
||||
return queue.submit();
|
||||
}
|
||||
|
|
|
@ -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: {
|
||||
|
|
|
@ -51,7 +51,7 @@ function parseOptions(opts) {
|
|||
}
|
||||
|
||||
// Parse tools.
|
||||
let allTools = ["clang-format", "scan-build", "hacl"];
|
||||
let allTools = ["clang-format", "scan-build", "hacl", "saw"];
|
||||
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));
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -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"
|
|
@ -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) ;;
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -10,4 +10,3 @@
|
|||
*/
|
||||
|
||||
#error "Do not include this header file."
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "keyhi.h"
|
||||
#include "pk11pub.h"
|
||||
#include "pkcs11uri.h"
|
||||
#include "sslexp.h"
|
||||
|
||||
struct ScopedDelete {
|
||||
void operator()(CERTCertificate* cert) { CERT_DestroyCertificate(cert); }
|
||||
|
@ -37,6 +38,9 @@ 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);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
|
@ -68,6 +72,7 @@ SCOPED(PK11URI);
|
|||
SCOPED(PLArenaPool);
|
||||
SCOPED(PK11Context);
|
||||
SCOPED(PK11GenericObject);
|
||||
SCOPED(SSLResumptionTokenInfo);
|
||||
|
||||
#undef SCOPED
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -405,6 +405,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<PRInt32>(strlen(k0RttData));
|
||||
|
||||
ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
|
||||
server_->Set0RttEnabled(true); // set ticket_allow_early_data
|
||||
Connect();
|
||||
|
@ -422,27 +425,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(); // Send ClientHello.
|
||||
PRInt32 rv =
|
||||
PR_Write(client_->ssl_fd(), k0RttData, k0RttDataLen); // 0-RTT write.
|
||||
EXPECT_EQ(k0RttDataLen, rv);
|
||||
|
||||
client_->Handshake();
|
||||
server_->Handshake();
|
||||
ASSERT_TRUE_WAIT(
|
||||
(client_->error_code() == SSL_ERROR_DOWNGRADE_WITH_EARLY_DATA), 2000);
|
||||
|
||||
// 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<TlsAgent>& agent,
|
||||
|
@ -521,6 +525,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 +540,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<uint8_t> 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());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -127,7 +127,8 @@ 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) {
|
||||
|
@ -154,7 +155,8 @@ TEST_P(TlsConnectTls12, ClientAuthBigRsaCheckSigAlg) {
|
|||
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 {
|
||||
|
@ -620,6 +622,31 @@ TEST_P(TlsConnectGenericPre13, AuthCompleteDelayed) {
|
|||
client_->DeletePacketFilter();
|
||||
}
|
||||
|
||||
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_->SetPacketFilter(std::make_shared<EnforceNoActivity>());
|
||||
client_->Handshake();
|
||||
EXPECT_EQ(TlsAgent::STATE_CONNECTING, client_->state());
|
||||
|
||||
// Report failure.
|
||||
client_->DeletePacketFilter();
|
||||
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
|
||||
// shape of the handshake is different.
|
||||
TEST_P(TlsConnectTls13, AuthCompleteDelayed) {
|
||||
|
@ -645,6 +672,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_->SetPacketFilter(std::make_shared<EnforceNoActivity>());
|
||||
client_->Handshake();
|
||||
EXPECT_EQ(TlsAgent::STATE_CONNECTING, client_->state());
|
||||
|
||||
// Report failure.
|
||||
client_->DeletePacketFilter();
|
||||
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 = {
|
||||
|
@ -796,8 +861,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 +870,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,
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
@ -455,7 +455,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 +499,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,7 +524,7 @@ 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);
|
||||
|
@ -538,7 +538,7 @@ TEST_P(TlsConnectTls13, ResumeFfdhe) {
|
|||
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());
|
||||
}
|
||||
|
|
|
@ -69,7 +69,7 @@ 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.
|
||||
|
@ -82,7 +82,7 @@ TEST_P(TlsConnectGeneric, ConnectEcdheP384Server) {
|
|||
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 +112,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<SSLNamedGroup> shares = {ssl_grp_ec_secp384r1};
|
||||
CheckKEXDetails(groups, shares);
|
||||
|
@ -129,7 +129,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<SSLNamedGroup> shares = {ssl_grp_ec_secp384r1};
|
||||
std::vector<SSLNamedGroup> expectedGroups = {ssl_grp_ec_secp384r1,
|
||||
|
@ -147,7 +147,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<SSLNamedGroup> shares = {ssl_grp_ec_secp384r1};
|
||||
|
@ -172,7 +172,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,7 +188,7 @@ 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 {
|
||||
|
@ -276,7 +276,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 +284,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 +318,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 +337,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<SSLNamedGroup> shares = {ssl_grp_ec_secp256r1};
|
||||
CheckKEXDetails(client_groups, shares);
|
||||
}
|
||||
|
@ -357,7 +357,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<SSLNamedGroup> shares = {ssl_grp_ec_curve25519};
|
||||
CheckKEXDetails(client_groups, shares);
|
||||
}
|
||||
|
@ -379,7 +379,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<SSLNamedGroup> shares = {ssl_grp_ec_curve25519};
|
||||
CheckKEXDetails(client_groups, shares, ssl_grp_ec_secp256r1);
|
||||
}
|
||||
|
@ -401,7 +401,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<SSLNamedGroup> shares = {ssl_grp_ec_curve25519};
|
||||
CheckKEXDetails(client_groups, shares, ssl_grp_ec_secp256r1);
|
||||
}
|
||||
|
@ -423,7 +423,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<SSLNamedGroup> shares = {ssl_grp_ec_curve25519};
|
||||
CheckKEXDetails(client_groups, shares, ssl_grp_ec_secp256r1);
|
||||
}
|
||||
|
@ -445,7 +445,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<SSLNamedGroup> shares = {ssl_grp_ec_curve25519};
|
||||
CheckKEXDetails(client_groups, shares, ssl_grp_ec_secp256r1);
|
||||
}
|
||||
|
@ -507,7 +507,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<SSLNamedGroup> shares = {ssl_grp_ec_curve25519,
|
||||
ssl_grp_ec_secp256r1};
|
||||
CheckKEXDetails(client_groups, shares);
|
||||
|
|
|
@ -424,7 +424,16 @@ TEST_P(TlsExtensionTest12Plus, SignatureAlgorithmsEmpty) {
|
|||
const uint8_t val[] = {0x00, 0x00};
|
||||
DataBuffer extension(val, sizeof(val));
|
||||
ClientHelloErrorTest(std::make_shared<TlsExtensionReplacer>(
|
||||
ssl_signature_algorithms_xtn, extension));
|
||||
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<TlsExtensionReplacer>(
|
||||
ssl_signature_algorithms_xtn, extension),
|
||||
kTlsAlertHandshakeFailure);
|
||||
}
|
||||
|
||||
TEST_P(TlsExtensionTest12Plus, SignatureAlgorithmsOddLength) {
|
||||
|
@ -507,8 +516,8 @@ TEST_P(TlsExtensionTestPre13, RenegotiationInfoExtensionEmpty) {
|
|||
// 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<TlsExtensionCapture>(ssl_signature_algorithms_xtn);
|
||||
|
|
|
@ -535,4 +535,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
|
||||
|
|
|
@ -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);
|
||||
|
@ -397,7 +397,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 +417,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();
|
||||
|
@ -442,7 +442,7 @@ TEST_P(TlsConnectGeneric, TestResumeClientDifferentCipher) {
|
|||
}
|
||||
|
||||
// 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();
|
||||
|
@ -572,7 +572,7 @@ TEST_F(TlsConnectTest, TestTls13ResumptionTwice) {
|
|||
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());
|
||||
|
@ -590,7 +590,7 @@ TEST_F(TlsConnectTest, TestTls13ResumptionTwice) {
|
|||
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()));
|
||||
|
@ -845,13 +845,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 +859,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 +868,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 +891,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 +899,119 @@ 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();
|
||||
}
|
||||
|
||||
} // namespace nss_test
|
||||
|
|
|
@ -73,7 +73,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_);
|
||||
|
@ -207,6 +208,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 +410,26 @@ 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<uint8_t> new_token(resumptionToken, resumptionToken + len);
|
||||
reinterpret_cast<TlsAgent*>(ctx)->SetResumptionToken(new_token);
|
||||
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;
|
||||
|
|
|
@ -165,6 +165,20 @@ 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<uint8_t>& resumption_token) {
|
||||
resumption_token_ = resumption_token;
|
||||
}
|
||||
const std::vector<uint8_t>& 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);
|
||||
}
|
||||
|
||||
const std::string& name() const { return name_; }
|
||||
|
||||
|
@ -393,6 +407,7 @@ class TlsAgent : public PollTarget {
|
|||
AuthCertificateCallbackFunction auth_certificate_callback_;
|
||||
SniCallbackFunction sni_callback_;
|
||||
bool skip_version_checks_;
|
||||
std::vector<uint8_t> resumption_token_;
|
||||
};
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& stream,
|
||||
|
|
|
@ -230,7 +230,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 +292,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 +405,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 +673,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,6 +758,16 @@ 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_ =
|
||||
|
|
|
@ -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,50 @@ class TlsConnectGeneric : public TlsConnectTestBase,
|
|||
TlsConnectGeneric();
|
||||
};
|
||||
|
||||
class TlsConnectGenericResumption
|
||||
: public TlsConnectTestBase,
|
||||
public ::testing::WithParamInterface<
|
||||
std::tuple<SSLProtocolVariant, uint16_t, bool>> {
|
||||
private:
|
||||
bool external_cache_;
|
||||
|
||||
public:
|
||||
TlsConnectGenericResumption();
|
||||
|
||||
virtual void EnsureTlsSetup() {
|
||||
TlsConnectTestBase::EnsureTlsSetup();
|
||||
// Enable external resumption token cache.
|
||||
if (external_cache_) {
|
||||
client_->SetResumptionTokenCallback();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class TlsConnectTls13ResumptionToken
|
||||
: public TlsConnectTestBase,
|
||||
public ::testing::WithParamInterface<SSLProtocolVariant> {
|
||||
public:
|
||||
TlsConnectTls13ResumptionToken();
|
||||
|
||||
virtual void EnsureTlsSetup() {
|
||||
TlsConnectTestBase::EnsureTlsSetup();
|
||||
client_->SetResumptionTokenCallback();
|
||||
}
|
||||
};
|
||||
|
||||
class TlsConnectGenericResumptionToken
|
||||
: public TlsConnectTestBase,
|
||||
public ::testing::WithParamInterface<
|
||||
std::tuple<SSLProtocolVariant, uint16_t>> {
|
||||
public:
|
||||
TlsConnectGenericResumptionToken();
|
||||
|
||||
virtual void EnsureTlsSetup() {
|
||||
TlsConnectTestBase::EnsureTlsSetup();
|
||||
client_->SetResumptionTokenCallback();
|
||||
}
|
||||
};
|
||||
|
||||
// A Pre TLS 1.2 generic test.
|
||||
class TlsConnectPre12 : public TlsConnectTestBase,
|
||||
public ::testing::WithParamInterface<
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -343,7 +343,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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -117,35 +119,61 @@ 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);
|
||||
}
|
||||
|
||||
/* First obtain the slot info */
|
||||
/* avoid repeated calls to check token status within set interval */
|
||||
PZ_Lock(slot->isPresentLock);
|
||||
if (within_token_delay_period(slot)) {
|
||||
CK_FLAGS ckFlags = slot->ckFlags;
|
||||
PZ_Unlock(slot->isPresentLock);
|
||||
return ((ckFlags & CKF_TOKEN_PRESENT) != 0);
|
||||
}
|
||||
PZ_Unlock(slot->isPresentLock);
|
||||
|
||||
/* 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->inIsPresent) {
|
||||
PR_WaitCondVar(slot->isPresentCondition, 0);
|
||||
}
|
||||
/* 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 (within_token_delay_period(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->inIsPresent = PR_TRUE;
|
||||
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 +195,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 +215,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 +231,27 @@ 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 lastTokenPing time 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);
|
||||
slot->lastTokenPing = PR_IntervalNow();
|
||||
return PR_TRUE;
|
||||
slot->inIsPresent = PR_FALSE;
|
||||
PR_NotifyAllCondVar(slot->isPresentCondition);
|
||||
PZ_Unlock(slot->isPresentLock);
|
||||
return isPresent;
|
||||
}
|
||||
|
||||
NSS_IMPLEMENT void *
|
||||
|
@ -229,7 +269,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);
|
||||
|
|
|
@ -81,6 +81,9 @@ struct NSSSlotStr {
|
|||
PZLock *lock;
|
||||
void *epv;
|
||||
PK11SlotInfo *pk11slot;
|
||||
PZLock *isPresentLock;
|
||||
PRCondVar *isPresentCondition;
|
||||
PRBool inIsPresent;
|
||||
};
|
||||
|
||||
struct nssSessionStr {
|
||||
|
|
|
@ -22,12 +22,12 @@
|
|||
* The format of the version string should be
|
||||
* "<major version>.<minor version>[.<patch level>[.<build number>]][ <ECC>][ <Beta>]"
|
||||
*/
|
||||
#define NSS_VERSION "3.35" _NSS_CUSTOMIZED
|
||||
#define NSS_VERSION "3.36" _NSS_CUSTOMIZED " Beta"
|
||||
#define NSS_VMAJOR 3
|
||||
#define NSS_VMINOR 35
|
||||
#define NSS_VMINOR 36
|
||||
#define NSS_VPATCH 0
|
||||
#define NSS_VBUILD 0
|
||||
#define NSS_BETA PR_FALSE
|
||||
#define NSS_BETA PR_TRUE
|
||||
|
||||
#ifndef RC_INVOKED
|
||||
|
||||
|
|
|
@ -120,6 +120,9 @@ 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->inIsPresent = PR_FALSE;
|
||||
return rvSlot;
|
||||
}
|
||||
|
||||
|
|
|
@ -17,11 +17,11 @@
|
|||
* The format of the version string should be
|
||||
* "<major version>.<minor version>[.<patch level>[.<build number>]][ <ECC>][ <Beta>]"
|
||||
*/
|
||||
#define SOFTOKEN_VERSION "3.35" SOFTOKEN_ECC_STRING
|
||||
#define SOFTOKEN_VERSION "3.36" SOFTOKEN_ECC_STRING " Beta"
|
||||
#define SOFTOKEN_VMAJOR 3
|
||||
#define SOFTOKEN_VMINOR 35
|
||||
#define SOFTOKEN_VMINOR 36
|
||||
#define SOFTOKEN_VPATCH 0
|
||||
#define SOFTOKEN_VBUILD 0
|
||||
#define SOFTOKEN_BETA PR_FALSE
|
||||
#define SOFTOKEN_BETA PR_TRUE
|
||||
|
||||
#endif /* _SOFTKVER_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.")
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
@ -4589,13 +4599,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 +4707,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 +5038,7 @@ ssl3_HandleHelloRequest(sslSocket *ss)
|
|||
}
|
||||
|
||||
if (sid) {
|
||||
ss->sec.uncache(sid);
|
||||
ssl_UncacheSessionID(ss);
|
||||
ssl_FreeSID(sid);
|
||||
ss->sec.ci.sid = NULL;
|
||||
}
|
||||
|
@ -6592,7 +6613,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 +7523,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 +8121,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 +8251,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 +8457,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 +8553,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 +8619,7 @@ alert_loser:
|
|||
/* FALLTHRU */
|
||||
loser:
|
||||
if (sid && sid != ss->sec.ci.sid) {
|
||||
ss->sec.uncache(sid);
|
||||
ssl_UncacheSessionID(ss);
|
||||
ssl_FreeSID(sid);
|
||||
}
|
||||
|
||||
|
@ -11137,6 +11159,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 +11189,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 +11204,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 +12668,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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
if (!variableLen) {
|
||||
// It is ok to have an empty variable.
|
||||
out->len = variableLen;
|
||||
return SECSuccess;
|
||||
}
|
||||
return sslRead_Read(reader, variableLen, out);
|
||||
}
|
||||
|
||||
*num = 0;
|
||||
for (i = 0; i < size; i++) {
|
||||
*num = (*num << 8) + item->data[i];
|
||||
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];
|
||||
}
|
||||
|
||||
item->data += size;
|
||||
item->len -= size;
|
||||
|
||||
reader->offset = reader->offset + bytes;
|
||||
*num = number;
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
|
|
|
@ -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_ */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -350,8 +350,103 @@ 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))
|
||||
|
||||
/* Deprecated experimental APIs */
|
||||
|
||||
#define SSL_UseAltServerHelloType(fd, enable) SSL_DEPRECATED_EXPERIMENTAL_API
|
||||
|
||||
SEC_END_PROTOS
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
@ -341,9 +344,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 +356,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 +404,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 +740,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 +897,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 +974,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 */
|
||||
|
@ -1080,8 +1074,6 @@ 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 1
|
||||
|
||||
SEC_END_PROTOS
|
||||
|
||||
#if defined(XP_UNIX) || defined(XP_OS2) || defined(XP_BEOS)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 <time.h>
|
||||
#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,758 @@ LockAndUncacheSID(sslSessionID *zap)
|
|||
UNLOCK_CACHE;
|
||||
}
|
||||
|
||||
/* choose client or server cache functions for this sslsocket. */
|
||||
void
|
||||
ssl_ChooseSessionIDProcs(sslSecurityInfo *sec)
|
||||
SECStatus
|
||||
ReadVariableFromBuffer(sslReader *reader, sslReadBuffer *readerBuffer,
|
||||
uint8_t lenBytes, SECItem *dest)
|
||||
{
|
||||
if (sec->isServer) {
|
||||
sec->cache = ssl_sid_cache;
|
||||
sec->uncache = ssl_sid_uncache;
|
||||
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 };
|
||||
SECITEM_CopyItem(NULL, dest, &tempItem);
|
||||
}
|
||||
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) {
|
||||
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);
|
||||
}
|
||||
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_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_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, 8, &tmpInt) != SECSuccess) {
|
||||
return SECFailure;
|
||||
}
|
||||
sid->u.ssl3.clAuthModuleID = (unsigned long)tmpInt;
|
||||
if (sslRead_ReadNumber(&reader, 8, &tmpInt) != SECSuccess) {
|
||||
return SECFailure;
|
||||
}
|
||||
sid->u.ssl3.clAuthSlotID = (unsigned long)tmpInt;
|
||||
if (sslRead_ReadNumber(&reader, 2, &tmpInt) != SECSuccess) {
|
||||
return SECFailure;
|
||||
}
|
||||
sid->u.ssl3.clAuthSeries = (PRUint16)tmpInt;
|
||||
|
||||
if (sslRead_ReadNumber(&reader, 1, &tmpInt) != SECSuccess) {
|
||||
return SECFailure;
|
||||
}
|
||||
sid->u.ssl3.masterValid = (char)tmpInt;
|
||||
if (sslRead_ReadNumber(&reader, 1, &tmpInt) != SECSuccess) {
|
||||
return SECFailure;
|
||||
}
|
||||
sid->u.ssl3.clAuthValid = (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->u.ssl3.locked.sessionTicket.ticket.len || !encodedTokenBuf ||
|
||||
!sid || !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 {
|
||||
sec->cache = CacheSID;
|
||||
sec->uncache = LockAndUncacheSID;
|
||||
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.clAuthModuleID, 8);
|
||||
if (rv != SECSuccess) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
rv = sslBuffer_AppendNumber(encodedTokenBuf, sid->u.ssl3.clAuthSlotID, 8);
|
||||
if (rv != SECSuccess) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
return SECFailure;
|
||||
}
|
||||
rv = sslBuffer_AppendNumber(encodedTokenBuf, sid->u.ssl3.clAuthSeries, 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_AppendNumber(encodedTokenBuf, sid->u.ssl3.clAuthValid, 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_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;
|
||||
}
|
||||
|
||||
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) {
|
||||
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->isServer) {
|
||||
ssl_ServerUncacheSessionID(sec->ci.sid);
|
||||
} else if (!ss->resumptionTokenCallback) {
|
||||
LockAndUncacheSID(sec->ci.sid);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -104,8 +104,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 +354,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);
|
||||
|
@ -3933,6 +3933,10 @@ struct {
|
|||
EXP(KeyUpdate),
|
||||
EXP(SendSessionTicket),
|
||||
EXP(SetupAntiReplay),
|
||||
EXP(SetResumptionTokenCallback),
|
||||
EXP(SetResumptionToken),
|
||||
EXP(GetResumptionTokenInfo),
|
||||
EXP(DestroyResumptionTokenInfo),
|
||||
#endif
|
||||
{ "", NULL }
|
||||
};
|
||||
|
@ -3967,3 +3971,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;
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4681,7 +4680,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 +4706,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 +4771,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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -19,12 +19,12 @@
|
|||
* The format of the version string should be
|
||||
* "<major version>.<minor version>[.<patch level>[.<build number>]][ <Beta>]"
|
||||
*/
|
||||
#define NSSUTIL_VERSION "3.35"
|
||||
#define NSSUTIL_VERSION "3.36 Beta"
|
||||
#define NSSUTIL_VMAJOR 3
|
||||
#define NSSUTIL_VMINOR 35
|
||||
#define NSSUTIL_VMINOR 36
|
||||
#define NSSUTIL_VPATCH 0
|
||||
#define NSSUTIL_VBUILD 0
|
||||
#define NSSUTIL_BETA PR_FALSE
|
||||
#define NSSUTIL_BETA PR_TRUE
|
||||
|
||||
SEC_BEGIN_PROTOS
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче