summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--BORINGSSL_REVISION2
-rw-r--r--linux-x86_64/crypto/cipher/chacha20_poly1305_x86_64.S3
-rw-r--r--mac-x86_64/crypto/cipher/chacha20_poly1305_x86_64.S3
-rw-r--r--sources.bp6
-rw-r--r--src/crypto/CMakeLists.txt1
-rwxr-xr-xsrc/crypto/bn/asm/rsaz-avx2.pl17
-rw-r--r--src/crypto/bn/bn_test.cc90
-rw-r--r--src/crypto/bn/cmp.c14
-rw-r--r--src/crypto/bn/div.c80
-rw-r--r--src/crypto/cipher/asm/chacha20_poly1305_x86_64.pl3
-rw-r--r--src/crypto/dh/dh_test.cc1
-rw-r--r--src/crypto/dsa/dsa_test.cc1
-rw-r--r--src/crypto/err/CMakeLists.txt11
-rw-r--r--src/crypto/err/err_test.cc113
-rwxr-xr-xsrc/crypto/perlasm/x86_64-xlate.pl133
-rw-r--r--src/crypto/test/gtest_main.cc25
-rw-r--r--src/crypto/test/test_util.cc17
-rw-r--r--src/crypto/test/test_util.h32
-rw-r--r--src/crypto/x509/pkcs7_test.c1
-rw-r--r--src/crypto/x509v3/v3_cpols.c2
-rw-r--r--src/include/openssl/bn.h10
-rw-r--r--src/include/openssl/digest.h3
-rw-r--r--src/include/openssl/ssl.h39
-rw-r--r--src/include/openssl/ssl3.h3
-rw-r--r--src/ssl/CMakeLists.txt10
-rw-r--r--src/ssl/d1_both.c9
-rw-r--r--src/ssl/dtls_method.c3
-rw-r--r--src/ssl/handshake_client.c62
-rw-r--r--src/ssl/handshake_server.c287
-rw-r--r--src/ssl/internal.h263
-rw-r--r--src/ssl/s3_both.c52
-rw-r--r--src/ssl/s3_lib.c16
-rw-r--r--src/ssl/s3_pkt.c2
-rw-r--r--src/ssl/ssl_asn1.c38
-rw-r--r--src/ssl/ssl_cert.c358
-rw-r--r--src/ssl/ssl_cipher.c5
-rw-r--r--src/ssl/ssl_file.c11
-rw-r--r--src/ssl/ssl_lib.c58
-rw-r--r--src/ssl/ssl_privkey.c (renamed from src/ssl/ssl_rsa.c)150
-rw-r--r--src/ssl/ssl_privkey_cc.cc (renamed from src/ssl/ssl_rsa_cc.cc)0
-rw-r--r--src/ssl/ssl_session.c104
-rw-r--r--src/ssl/ssl_stat.c18
-rw-r--r--src/ssl/ssl_test.cc522
-rw-r--r--src/ssl/ssl_transcript.c (renamed from src/ssl/s3_enc.c)299
-rw-r--r--src/ssl/ssl_x509.c518
-rw-r--r--src/ssl/t1_enc.c233
-rw-r--r--src/ssl/t1_lib.c74
-rw-r--r--src/ssl/test/bssl_shim.cc2
-rw-r--r--src/ssl/test/runner/common.go17
-rw-r--r--src/ssl/test/runner/handshake_client.go16
-rw-r--r--src/ssl/test/runner/handshake_messages.go7
-rw-r--r--src/ssl/test/runner/handshake_server.go2
-rw-r--r--src/ssl/test/runner/runner.go112
-rw-r--r--src/ssl/tls13_both.c21
-rw-r--r--src/ssl/tls13_client.c36
-rw-r--r--src/ssl/tls13_enc.c110
-rw-r--r--src/ssl/tls13_server.c43
-rw-r--r--src/ssl/tls_method.c26
-rw-r--r--src/tool/client.cc20
-rw-r--r--src/tool/server.cc20
-rw-r--r--src/util/all_tests.go13
-rw-r--r--src/util/all_tests.json1
62 files changed, 2196 insertions, 1952 deletions
diff --git a/BORINGSSL_REVISION b/BORINGSSL_REVISION
index 14bbebce..f26983b6 100644
--- a/BORINGSSL_REVISION
+++ b/BORINGSSL_REVISION
@@ -1 +1 @@
-ab20cec1c1de815de8da6cc74c2503460efd6e1c
+040bc4944be97f5d4b44da176f6e801fc804a176
diff --git a/linux-x86_64/crypto/cipher/chacha20_poly1305_x86_64.S b/linux-x86_64/crypto/cipher/chacha20_poly1305_x86_64.S
index 241d7d02..c7e673fc 100644
--- a/linux-x86_64/crypto/cipher/chacha20_poly1305_x86_64.S
+++ b/linux-x86_64/crypto/cipher/chacha20_poly1305_x86_64.S
@@ -2,6 +2,9 @@
.text
.extern OPENSSL_ia32cap_P
.hidden OPENSSL_ia32cap_P
+
+chacha20_poly1305_constants:
+
.align 64
.chacha20_consts:
.byte 'e','x','p','a','n','d',' ','3','2','-','b','y','t','e',' ','k'
diff --git a/mac-x86_64/crypto/cipher/chacha20_poly1305_x86_64.S b/mac-x86_64/crypto/cipher/chacha20_poly1305_x86_64.S
index 4e5c0f35..03cd8725 100644
--- a/mac-x86_64/crypto/cipher/chacha20_poly1305_x86_64.S
+++ b/mac-x86_64/crypto/cipher/chacha20_poly1305_x86_64.S
@@ -1,6 +1,9 @@
#if defined(__x86_64__)
.text
+
+chacha20_poly1305_constants:
+
.p2align 6
.chacha20_consts:
.byte 'e','x','p','a','n','d',' ','3','2','-','b','y','t','e',' ','k'
diff --git a/sources.bp b/sources.bp
index 99720a58..8e13f1af 100644
--- a/sources.bp
+++ b/sources.bp
@@ -408,7 +408,6 @@ cc_defaults {
"src/ssl/handshake_client.c",
"src/ssl/handshake_server.c",
"src/ssl/s3_both.c",
- "src/ssl/s3_enc.c",
"src/ssl/s3_lib.c",
"src/ssl/s3_pkt.c",
"src/ssl/ssl_aead_ctx.c",
@@ -419,10 +418,11 @@ cc_defaults {
"src/ssl/ssl_ecdh.c",
"src/ssl/ssl_file.c",
"src/ssl/ssl_lib.c",
- "src/ssl/ssl_rsa.c",
- "src/ssl/ssl_rsa_cc.cc",
+ "src/ssl/ssl_privkey.c",
+ "src/ssl/ssl_privkey_cc.cc",
"src/ssl/ssl_session.c",
"src/ssl/ssl_stat.c",
+ "src/ssl/ssl_transcript.c",
"src/ssl/ssl_x509.c",
"src/ssl/t1_enc.c",
"src/ssl/t1_lib.c",
diff --git a/src/crypto/CMakeLists.txt b/src/crypto/CMakeLists.txt
index 36224fc1..bbc68d00 100644
--- a/src/crypto/CMakeLists.txt
+++ b/src/crypto/CMakeLists.txt
@@ -214,6 +214,7 @@ add_executable(
dh/dh_test.cc
dsa/dsa_test.cc
+ err/err_test.cc
$<TARGET_OBJECTS:gtest_main>
$<TARGET_OBJECTS:test_support>
diff --git a/src/crypto/bn/asm/rsaz-avx2.pl b/src/crypto/bn/asm/rsaz-avx2.pl
index 73db3c2b..b8e830e2 100755
--- a/src/crypto/bn/asm/rsaz-avx2.pl
+++ b/src/crypto/bn/asm/rsaz-avx2.pl
@@ -804,6 +804,7 @@ $code.=<<___;
mov %rbp, %rax
___
$code.=<<___ if ($win64);
+.Lsqr_1024_in_tail:
movaps -0xd8(%rax),%xmm6
movaps -0xc8(%rax),%xmm7
movaps -0xb8(%rax),%xmm8
@@ -1437,6 +1438,7 @@ $code.=<<___;
mov %rbp, %rax
___
$code.=<<___ if ($win64);
+.Lmul_1024_in_tail:
movaps -0xd8(%rax),%xmm6
movaps -0xc8(%rax),%xmm7
movaps -0xb8(%rax),%xmm8
@@ -1792,14 +1794,17 @@ rsaz_se_handler:
cmp %r10,%rbx # context->Rip<prologue label
jb .Lcommon_seh_tail
- mov 152($context),%rax # pull context->Rsp
-
mov 4(%r11),%r10d # HandlerData[1]
lea (%rsi,%r10),%r10 # epilogue label
cmp %r10,%rbx # context->Rip>=epilogue label
jae .Lcommon_seh_tail
- mov 160($context),%rax # pull context->Rbp
+ mov 160($context),%rbp # pull context->Rbp
+
+ mov 8(%r11),%r10d # HandlerData[2]
+ lea (%rsi,%r10),%r10 # "in tail" label
+ cmp %r10,%rbx # context->Rip>="in tail" label
+ cmovc %rbp,%rax
mov -48(%rax),%r15
mov -40(%rax),%r14
@@ -1877,11 +1882,13 @@ rsaz_se_handler:
.LSEH_info_rsaz_1024_sqr_avx2:
.byte 9,0,0,0
.rva rsaz_se_handler
- .rva .Lsqr_1024_body,.Lsqr_1024_epilogue
+ .rva .Lsqr_1024_body,.Lsqr_1024_epilogue,.Lsqr_1024_in_tail
+ .long 0
.LSEH_info_rsaz_1024_mul_avx2:
.byte 9,0,0,0
.rva rsaz_se_handler
- .rva .Lmul_1024_body,.Lmul_1024_epilogue
+ .rva .Lmul_1024_body,.Lmul_1024_epilogue,.Lmul_1024_in_tail
+ .long 0
.LSEH_info_rsaz_1024_gather5:
.byte 0x01,0x36,0x17,0x0b
.byte 0x36,0xf8,0x09,0x00 # vmovaps 0x90(rsp),xmm15
diff --git a/src/crypto/bn/bn_test.cc b/src/crypto/bn/bn_test.cc
index a152cdf7..c0af58d9 100644
--- a/src/crypto/bn/bn_test.cc
+++ b/src/crypto/bn/bn_test.cc
@@ -1668,6 +1668,93 @@ static bool TestBNSetGetU64() {
return true;
}
+static bool TestBNPow2(BN_CTX *ctx) {
+ bssl::UniquePtr<BIGNUM>
+ power_of_two(BN_new()),
+ random(BN_new()),
+ expected(BN_new()),
+ actual(BN_new());
+
+ if (!power_of_two.get() ||
+ !random.get() ||
+ !expected.get() ||
+ !actual.get()) {
+ return false;
+ }
+
+ // Choose an exponent.
+ for (size_t e = 3; e < 512; e += 11) {
+ // Choose a bit length for our randoms.
+ for (int len = 3; len < 512; len += 23) {
+ // Set power_of_two = 2^e.
+ if (!BN_lshift(power_of_two.get(), BN_value_one(), (int) e)) {
+ fprintf(stderr, "Failed to shiftl.\n");
+ return false;
+ }
+
+ // Test BN_is_pow2 on power_of_two.
+ if (!BN_is_pow2(power_of_two.get())) {
+ fprintf(stderr, "BN_is_pow2 returned false for a power of two.\n");
+ hexdump(stderr, "Arg: ", power_of_two->d,
+ power_of_two->top * sizeof(BN_ULONG));
+ return false;
+ }
+
+ // Pick a large random value, ensuring it isn't a power of two.
+ if (!BN_rand(random.get(), len, BN_RAND_TOP_TWO, BN_RAND_BOTTOM_ANY)) {
+ fprintf(stderr, "Failed to generate random in TestBNPow2.\n");
+ return false;
+ }
+
+ // Test BN_is_pow2 on |r|.
+ if (BN_is_pow2(random.get())) {
+ fprintf(stderr, "BN_is_pow2 returned true for a non-power of two.\n");
+ hexdump(stderr, "Arg: ", random->d, random->top * sizeof(BN_ULONG));
+ return false;
+ }
+
+ // Test BN_mod_pow2 on |r|.
+ if (!BN_mod(expected.get(), random.get(), power_of_two.get(), ctx) ||
+ !BN_mod_pow2(actual.get(), random.get(), e) ||
+ BN_cmp(actual.get(), expected.get())) {
+ fprintf(stderr, "BN_mod_pow2 returned the wrong value:\n");
+ hexdump(stderr, "Expected: ", expected->d,
+ expected->top * sizeof(BN_ULONG));
+ hexdump(stderr, "Got: ", actual->d,
+ actual->top * sizeof(BN_ULONG));
+ return false;
+ }
+
+ // Test BN_nnmod_pow2 on |r|.
+ if (!BN_nnmod(expected.get(), random.get(), power_of_two.get(), ctx) ||
+ !BN_nnmod_pow2(actual.get(), random.get(), e) ||
+ BN_cmp(actual.get(), expected.get())) {
+ fprintf(stderr, "BN_nnmod_pow2 failed on positive input:\n");
+ hexdump(stderr, "Expected: ", expected->d,
+ expected->top * sizeof(BN_ULONG));
+ hexdump(stderr, "Got: ", actual->d,
+ actual->top * sizeof(BN_ULONG));
+ return false;
+ }
+
+ // Test BN_nnmod_pow2 on -|r|.
+ BN_set_negative(random.get(), 1);
+ if (!BN_nnmod(expected.get(), random.get(), power_of_two.get(), ctx) ||
+ !BN_nnmod_pow2(actual.get(), random.get(), e) ||
+ BN_cmp(actual.get(), expected.get())) {
+ fprintf(stderr, "BN_nnmod_pow2 failed on negative input:\n");
+ hexdump(stderr, "Expected: ", expected->d,
+ expected->top * sizeof(BN_ULONG));
+ hexdump(stderr, "Got: ", actual->d,
+ actual->top * sizeof(BN_ULONG));
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
int main(int argc, char *argv[]) {
CRYPTO_library_init();
@@ -1695,7 +1782,8 @@ int main(int argc, char *argv[]) {
!TestSmallPrime(ctx.get()) ||
!TestCmpWord() ||
!TestBN2Dec() ||
- !TestBNSetGetU64()) {
+ !TestBNSetGetU64() ||
+ !TestBNPow2(ctx.get())) {
return 1;
}
diff --git a/src/crypto/bn/cmp.c b/src/crypto/bn/cmp.c
index 9cf33b48..71c04658 100644
--- a/src/crypto/bn/cmp.c
+++ b/src/crypto/bn/cmp.c
@@ -212,6 +212,20 @@ int BN_is_odd(const BIGNUM *bn) {
return bn->top > 0 && (bn->d[0] & 1) == 1;
}
+int BN_is_pow2(const BIGNUM *bn) {
+ if (bn->top == 0 || bn->neg) {
+ return 0;
+ }
+
+ for (int i = 0; i < bn->top - 1; i++) {
+ if (bn->d[i] != 0) {
+ return 0;
+ }
+ }
+
+ return 0 == (bn->d[bn->top-1] & (bn->d[bn->top-1] - 1));
+}
+
int BN_equal_consttime(const BIGNUM *a, const BIGNUM *b) {
if (a->top != b->top) {
return 0;
diff --git a/src/crypto/bn/div.c b/src/crypto/bn/div.c
index 6e3df7d3..de3fa1f1 100644
--- a/src/crypto/bn/div.c
+++ b/src/crypto/bn/div.c
@@ -58,6 +58,7 @@
#include <assert.h>
#include <limits.h>
+
#include <openssl/err.h>
#include "internal.h"
@@ -646,3 +647,82 @@ BN_ULONG BN_mod_word(const BIGNUM *a, BN_ULONG w) {
}
return (BN_ULONG)ret;
}
+
+int BN_mod_pow2(BIGNUM *r, const BIGNUM *a, size_t e) {
+ if (e == 0 || a->top == 0) {
+ BN_zero(r);
+ return 1;
+ }
+
+ size_t num_words = 1 + ((e - 1) / BN_BITS2);
+
+ /* If |a| definitely has less than |e| bits, just BN_copy. */
+ if ((size_t) a->top < num_words) {
+ return BN_copy(r, a) != NULL;
+ }
+
+ /* Otherwise, first make sure we have enough space in |r|.
+ * Note that this will fail if num_words > INT_MAX. */
+ if (bn_wexpand(r, num_words) == NULL) {
+ return 0;
+ }
+
+ /* Copy the content of |a| into |r|. */
+ OPENSSL_memcpy(r->d, a->d, num_words * sizeof(BN_ULONG));
+
+ /* If |e| isn't word-aligned, we have to mask off some of our bits. */
+ size_t top_word_exponent = e % (sizeof(BN_ULONG) * 8);
+ if (top_word_exponent != 0) {
+ r->d[num_words - 1] &= (((BN_ULONG) 1) << top_word_exponent) - 1;
+ }
+
+ /* Fill in the remaining fields of |r|. */
+ r->neg = a->neg;
+ r->top = (int) num_words;
+ bn_correct_top(r);
+ return 1;
+}
+
+int BN_nnmod_pow2(BIGNUM *r, const BIGNUM *a, size_t e) {
+ if (!BN_mod_pow2(r, a, e)) {
+ return 0;
+ }
+
+ /* If the returned value was non-negative, we're done. */
+ if (BN_is_zero(r) || !r->neg) {
+ return 1;
+ }
+
+ size_t num_words = 1 + (e - 1) / BN_BITS2;
+
+ /* Expand |r| to the size of our modulus. */
+ if (bn_wexpand(r, num_words) == NULL) {
+ return 0;
+ }
+
+ /* Clear the upper words of |r|. */
+ OPENSSL_memset(&r->d[r->top], 0, (num_words - r->top) * BN_BYTES);
+
+ /* Set parameters of |r|. */
+ r->neg = 0;
+ r->top = (int) num_words;
+
+ /* Now, invert every word. The idea here is that we want to compute 2^e-|x|,
+ * which is actually equivalent to the twos-complement representation of |x|
+ * in |e| bits, which is -x = ~x + 1. */
+ for (int i = 0; i < r->top; i++) {
+ r->d[i] = ~r->d[i];
+ }
+
+ /* If our exponent doesn't span the top word, we have to mask the rest. */
+ size_t top_word_exponent = e % BN_BITS2;
+ if (top_word_exponent != 0) {
+ r->d[r->top - 1] &= (((BN_ULONG) 1) << top_word_exponent) - 1;
+ }
+
+ /* Keep the correct_top invariant for BN_add. */
+ bn_correct_top(r);
+
+ /* Finally, add one, for the reason described above. */
+ return BN_add(r, r, BN_value_one());
+}
diff --git a/src/crypto/cipher/asm/chacha20_poly1305_x86_64.pl b/src/crypto/cipher/asm/chacha20_poly1305_x86_64.pl
index 44590c2f..857f1d5d 100644
--- a/src/crypto/cipher/asm/chacha20_poly1305_x86_64.pl
+++ b/src/crypto/cipher/asm/chacha20_poly1305_x86_64.pl
@@ -39,6 +39,9 @@ $avx = 2;
$code.=<<___;
.text
.extern OPENSSL_ia32cap_P
+
+chacha20_poly1305_constants:
+
.align 64
.chacha20_consts:
.byte 'e','x','p','a','n','d',' ','3','2','-','b','y','t','e',' ','k'
diff --git a/src/crypto/dh/dh_test.cc b/src/crypto/dh/dh_test.cc
index 9cde6796..e08664fa 100644
--- a/src/crypto/dh/dh_test.cc
+++ b/src/crypto/dh/dh_test.cc
@@ -86,7 +86,6 @@ TEST(DHTest, AllTests) {
!TestBadY() ||
!TestASN1() ||
!TestRFC3526()) {
- ERR_print_errors_fp(stderr);
ADD_FAILURE() << "Tests failed.";
}
}
diff --git a/src/crypto/dsa/dsa_test.cc b/src/crypto/dsa/dsa_test.cc
index d2cd33e3..63b78036 100644
--- a/src/crypto/dsa/dsa_test.cc
+++ b/src/crypto/dsa/dsa_test.cc
@@ -312,7 +312,6 @@ TEST(DSATest, AllTests) {
!TestVerify(fips_sig_extra, sizeof(fips_sig_extra), -1) ||
!TestVerify(fips_sig_bad_length, sizeof(fips_sig_bad_length), -1) ||
!TestVerify(fips_sig_bad_r, sizeof(fips_sig_bad_r), 0)) {
- ERR_print_errors_fp(stderr);
ADD_FAILURE() << "Tests failed";
}
}
diff --git a/src/crypto/err/CMakeLists.txt b/src/crypto/err/CMakeLists.txt
index a095b542..579a35be 100644
--- a/src/crypto/err/CMakeLists.txt
+++ b/src/crypto/err/CMakeLists.txt
@@ -37,14 +37,3 @@ add_library(
err.c
err_data.c
)
-
-add_executable(
- err_test
-
- err_test.cc
-
- $<TARGET_OBJECTS:test_support>
-)
-
-target_link_libraries(err_test crypto)
-add_dependencies(all_tests err_test)
diff --git a/src/crypto/err/err_test.cc b/src/crypto/err/err_test.cc
index d6913558..8e820b85 100644
--- a/src/crypto/err/err_test.cc
+++ b/src/crypto/err/err_test.cc
@@ -15,40 +15,34 @@
#include <stdio.h>
#include <string.h>
+#include <gtest/gtest.h>
+
#include <openssl/crypto.h>
#include <openssl/err.h>
#include <openssl/mem.h>
-static bool TestOverflow() {
+TEST(ErrTest, Overflow) {
for (unsigned i = 0; i < ERR_NUM_ERRORS*2; i++) {
ERR_put_error(1, 0 /* unused */, i+1, "test", 1);
}
for (unsigned i = 0; i < ERR_NUM_ERRORS - 1; i++) {
+ SCOPED_TRACE(i);
uint32_t err = ERR_get_error();
/* Errors are returned in order they were pushed, with the least recent ones
* removed, up to |ERR_NUM_ERRORS - 1| errors. So the errors returned are
* |ERR_NUM_ERRORS + 2| through |ERR_NUM_ERRORS * 2|, inclusive. */
- if (err == 0 || ((unsigned)ERR_GET_REASON(err)) != i + ERR_NUM_ERRORS + 2) {
- fprintf(stderr, "ERR_get_error failed at %u\n", i);
- return false;
- }
- }
-
- if (ERR_get_error() != 0) {
- fprintf(stderr, "ERR_get_error more than the expected number of values.\n");
- return false;
+ EXPECT_NE(0u, err);
+ EXPECT_EQ(static_cast<int>(i + ERR_NUM_ERRORS + 2), ERR_GET_REASON(err));
}
- return true;
+ EXPECT_EQ(0u, ERR_get_error());
}
-static bool TestPutError() {
- if (ERR_get_error() != 0) {
- fprintf(stderr, "ERR_get_error returned value before an error was added.\n");
- return false;
- }
+TEST(ErrTest, PutError) {
+ ASSERT_EQ(0u, ERR_get_error())
+ << "ERR_get_error returned value before an error was added.";
ERR_put_error(1, 0 /* unused */, 2, "test", 4);
ERR_add_error_data(1, "testing");
@@ -60,45 +54,31 @@ static bool TestPutError() {
&peeked_flags);
uint32_t packed_error = ERR_get_error_line_data(&file, &line, &data, &flags);
- if (peeked_packed_error != packed_error ||
- peeked_file != file ||
- peeked_data != data ||
- peeked_flags != flags) {
- fprintf(stderr, "Bad peeked error data returned.\n");
- return false;
- }
-
- if (strcmp(file, "test") != 0 ||
- line != 4 ||
- (flags & ERR_FLAG_STRING) == 0 ||
- ERR_GET_LIB(packed_error) != 1 ||
- ERR_GET_REASON(packed_error) != 2 ||
- strcmp(data, "testing") != 0) {
- fprintf(stderr, "Bad error data returned.\n");
- return false;
- }
-
- return true;
+ EXPECT_EQ(peeked_packed_error, packed_error);
+ EXPECT_EQ(peeked_file, file);
+ EXPECT_EQ(peeked_data, data);
+ EXPECT_EQ(peeked_flags, flags);
+
+ EXPECT_STREQ("test", file);
+ EXPECT_EQ(4, line);
+ EXPECT_TRUE(flags & ERR_FLAG_STRING);
+ EXPECT_EQ(1, ERR_GET_LIB(packed_error));
+ EXPECT_EQ(2, ERR_GET_REASON(packed_error));
+ EXPECT_STREQ("testing", data);
}
-static bool TestClearError() {
- if (ERR_get_error() != 0) {
- fprintf(stderr, "ERR_get_error returned value before an error was added.\n");
- return false;
- }
+TEST(ErrTest, ClearError) {
+ ASSERT_EQ(0u, ERR_get_error())
+ << "ERR_get_error returned value before an error was added.";
ERR_put_error(1, 0 /* unused */, 2, "test", 4);
ERR_clear_error();
- if (ERR_get_error() != 0) {
- fprintf(stderr, "Error remained after clearing.\n");
- return false;
- }
-
- return true;
+ // The error queue should be cleared.
+ EXPECT_EQ(0u, ERR_get_error());
}
-static bool TestPrint() {
+TEST(ErrTest, Print) {
ERR_put_error(1, 0 /* unused */, 2, "test", 4);
ERR_add_error_data(1, "testing");
uint32_t packed_error = ERR_get_error();
@@ -107,14 +87,14 @@ static bool TestPrint() {
for (size_t i = 0; i <= sizeof(buf); i++) {
ERR_error_string_n(packed_error, buf, i);
}
-
- return true;
}
-static bool TestRelease() {
+TEST(ErrTest, Release) {
ERR_put_error(1, 0 /* unused */, 2, "test", 4);
ERR_remove_thread_state(NULL);
- return true;
+
+ // The error queue should be cleared.
+ EXPECT_EQ(0u, ERR_get_error());
}
static bool HasSuffix(const char *str, const char *suffix) {
@@ -126,7 +106,7 @@ static bool HasSuffix(const char *str, const char *suffix) {
return strcmp(str + str_len - suffix_len, suffix) == 0;
}
-static bool TestPutMacro() {
+TEST(ErrTest, PutMacro) {
int expected_line = __LINE__ + 1;
OPENSSL_PUT_ERROR(USER, ERR_R_INTERNAL_ERROR);
@@ -134,29 +114,8 @@ static bool TestPutMacro() {
const char *file;
uint32_t error = ERR_get_error_line(&file, &line);
- if (!HasSuffix(file, "err_test.cc") ||
- line != expected_line ||
- ERR_GET_LIB(error) != ERR_LIB_USER ||
- ERR_GET_REASON(error) != ERR_R_INTERNAL_ERROR) {
- fprintf(stderr, "Bad error data returned.\n");
- return false;
- }
-
- return true;
-}
-
-int main() {
- CRYPTO_library_init();
-
- if (!TestOverflow() ||
- !TestPutError() ||
- !TestClearError() ||
- !TestPrint() ||
- !TestRelease() ||
- !TestPutMacro()) {
- return 1;
- }
-
- printf("PASS\n");
- return 0;
+ EXPECT_PRED2(HasSuffix, file, "err_test.cc");
+ EXPECT_EQ(expected_line, line);
+ EXPECT_EQ(ERR_LIB_USER, ERR_GET_LIB(error));
+ EXPECT_EQ(ERR_R_INTERNAL_ERROR, ERR_GET_REASON(error));
}
diff --git a/src/crypto/perlasm/x86_64-xlate.pl b/src/crypto/perlasm/x86_64-xlate.pl
index 074f185e..16553f2a 100755
--- a/src/crypto/perlasm/x86_64-xlate.pl
+++ b/src/crypto/perlasm/x86_64-xlate.pl
@@ -51,12 +51,7 @@
# 7. Stick to explicit ip-relative addressing. If you have to use
# GOTPCREL addressing, stick to mov symbol@GOTPCREL(%rip),%r??.
# Both are recognized and translated to proper Win64 addressing
-# modes. To support legacy code a synthetic directive, .picmeup,
-# is implemented. It puts address of the *next* instruction into
-# target register, e.g.:
-#
-# .picmeup %rax
-# lea .Label-.(%rax),%rax
+# modes.
#
# 8. In order to provide for structured exception handling unified
# Win64 prologue copies %rsp value to %rax. For further details
@@ -125,7 +120,7 @@ my %globals;
$self->{sz} = "";
} elsif ($self->{op} =~ /^p/ && $' !~ /^(ush|op|insrw)/) { # SSEn
$self->{sz} = "";
- } elsif ($self->{op} =~ /^v/) { # VEX
+ } elsif ($self->{op} =~ /^[vk]/) { # VEX or k* such as kmov
$self->{sz} = "";
} elsif ($self->{op} =~ /mov[dq]/ && $$line =~ /%xmm/) {
$self->{sz} = "";
@@ -218,18 +213,26 @@ my %globals;
}
}
{ package ea; # pick up effective addresses: expr(%reg,%reg,scale)
+
+ my %szmap = ( b=>"BYTE$PTR", w=>"WORD$PTR",
+ l=>"DWORD$PTR", d=>"DWORD$PTR",
+ q=>"QWORD$PTR", o=>"OWORD$PTR",
+ x=>"XMMWORD$PTR", y=>"YMMWORD$PTR",
+ z=>"ZMMWORD$PTR" ) if (!$gas);
+
sub re {
my ($class, $line, $opcode) = @_;
my $self = {};
my $ret;
# optional * ----vvv--- appears in indirect jmp/call
- if ($$line =~ /^(\*?)([^\(,]*)\(([%\w,]+)\)/) {
+ if ($$line =~ /^(\*?)([^\(,]*)\(([%\w,]+)\)((?:{[^}]+})*)/) {
bless $self, $class;
$self->{asterisk} = $1;
$self->{label} = $2;
($self->{base},$self->{index},$self->{scale})=split(/,/,$3);
$self->{scale} = 1 if (!defined($self->{scale}));
+ $self->{opmask} = $4;
$ret = $self;
$$line = substr($$line,@+[0]); $$line =~ s/^\s+//;
@@ -270,6 +273,8 @@ my %globals;
$self->{label} =~ s/\b([0-9]+)\b/$1>>0/eg;
}
+ # if base register is %rbp or %r13, see if it's possible to
+ # flip base and ingex registers [for better performance]
if (!$self->{label} && $self->{index} && $self->{scale}==1 &&
$self->{base} =~ /(rbp|r13)/) {
$self->{base} = $self->{index}; $self->{index} = $1;
@@ -279,19 +284,16 @@ my %globals;
$self->{label} =~ s/^___imp_/__imp__/ if ($flavour eq "mingw64");
if (defined($self->{index})) {
- sprintf "%s%s(%s,%%%s,%d)",$self->{asterisk},
- $self->{label},
+ sprintf "%s%s(%s,%%%s,%d)%s",
+ $self->{asterisk},$self->{label},
$self->{base}?"%$self->{base}":"",
- $self->{index},$self->{scale};
+ $self->{index},$self->{scale},
+ $self->{opmask};
} else {
- sprintf "%s%s(%%%s)", $self->{asterisk},$self->{label},$self->{base};
+ sprintf "%s%s(%%%s)%s", $self->{asterisk},$self->{label},
+ $self->{base},$self->{opmask};
}
} else {
- my %szmap = ( b=>"BYTE$PTR", w=>"WORD$PTR",
- l=>"DWORD$PTR", d=>"DWORD$PTR",
- q=>"QWORD$PTR", o=>"OWORD$PTR",
- x=>"XMMWORD$PTR", y=>"YMMWORD$PTR", z=>"ZMMWORD$PTR" );
-
$self->{label} =~ s/\./\$/g;
$self->{label} =~ s/(?<![\w\$\.])0x([0-9a-f]+)/0$1h/ig;
$self->{label} = "($self->{label})" if ($self->{label} =~ /[\*\+\-\/]/);
@@ -303,17 +305,20 @@ my %globals;
($mnemonic =~ /^vpbroadcast([qdwb])$/) && ($sz=$1) ||
($mnemonic =~ /^v(?!perm)[a-z]+[fi]128$/) && ($sz="x");
+ $self->{opmask} =~ s/%(k[0-7])/$1/;
+
if (defined($self->{index})) {
- sprintf "%s[%s%s*%d%s]",$szmap{$sz},
+ sprintf "%s[%s%s*%d%s]%s",$szmap{$sz},
$self->{label}?"$self->{label}+":"",
$self->{index},$self->{scale},
- $self->{base}?"+$self->{base}":"";
+ $self->{base}?"+$self->{base}":"",
+ $self->{opmask};
} elsif ($self->{base} eq "rip") {
sprintf "%s[%s]",$szmap{$sz},$self->{label};
} else {
- sprintf "%s[%s%s]",$szmap{$sz},
+ sprintf "%s[%s%s]%s", $szmap{$sz},
$self->{label}?"$self->{label}+":"",
- $self->{base};
+ $self->{base},$self->{opmask};
}
}
}
@@ -325,10 +330,11 @@ my %globals;
my $ret;
# optional * ----vvv--- appears in indirect jmp/call
- if ($$line =~ /^(\*?)%(\w+)/) {
+ if ($$line =~ /^(\*?)%(\w+)((?:{[^}]+})*)/) {
bless $self,$class;
$self->{asterisk} = $1;
$self->{value} = $2;
+ $self->{opmask} = $3;
$opcode->size($self->size());
$ret = $self;
$$line = substr($$line,@+[0]); $$line =~ s/^\s+//;
@@ -352,8 +358,11 @@ my %globals;
}
sub out {
my $self = shift;
- if ($gas) { sprintf "%s%%%s",$self->{asterisk},$self->{value}; }
- else { $self->{value}; }
+ if ($gas) { sprintf "%s%%%s%s", $self->{asterisk},
+ $self->{value},
+ $self->{opmask}; }
+ else { $self->{opmask} =~ s/%(k[0-7])/$1/;
+ $self->{value}.$self->{opmask}; }
}
}
{ package label; # pick up labels, which end with :
@@ -377,9 +386,8 @@ my %globals;
if ($gas) {
my $func = ($globals{$self->{value}} or $self->{value}) . ":";
- if ($win64 &&
- $current_function->{name} eq $self->{value} &&
- $current_function->{abi} eq "svr4") {
+ if ($win64 && $current_function->{name} eq $self->{value}
+ && $current_function->{abi} eq "svr4") {
$func .= "\n";
$func .= " movq %rdi,8(%rsp)\n";
$func .= " movq %rsi,16(%rsp)\n";
@@ -458,15 +466,6 @@ my %globals;
my $self = {};
my $ret;
my $dir;
- my %opcode = # lea 2f-1f(%rip),%dst; 1: nop; 2:
- ( "%rax"=>0x01058d48, "%rcx"=>0x010d8d48,
- "%rdx"=>0x01158d48, "%rbx"=>0x011d8d48,
- "%rsp"=>0x01258d48, "%rbp"=>0x012d8d48,
- "%rsi"=>0x01358d48, "%rdi"=>0x013d8d48,
- "%r8" =>0x01058d4c, "%r9" =>0x010d8d4c,
- "%r10"=>0x01158d4c, "%r11"=>0x011d8d4c,
- "%r12"=>0x01258d4c, "%r13"=>0x012d8d4c,
- "%r14"=>0x01358d4c, "%r15"=>0x013d8d4c );
if ($$line =~ /^\s*(\.\w+)/) {
bless $self,$class;
@@ -476,12 +475,6 @@ my %globals;
$$line = substr($$line,@+[0]); $$line =~ s/^\s+//;
SWITCH: for ($dir) {
- /\.picmeup/ && do { if ($$line =~ /(%r[\w]+)/i) {
- $dir="\t.long";
- $$line=sprintf "0x%x,0x90000000",$opcode{$1};
- }
- last;
- };
/\.global|\.globl|\.extern/
&& do { $globals{$$line} = $prefix . $$line;
$$line = $globals{$$line} if ($prefix);
@@ -696,15 +689,6 @@ my %globals;
}
}
-sub rex {
- my $opcode=shift;
- my ($dst,$src,$rex)=@_;
-
- $rex|=0x04 if($dst>=8);
- $rex|=0x01 if($src>=8);
- push @$opcode,($rex|0x40) if ($rex);
-}
-
# Upon initial x86_64 introduction SSE>2 extensions were not introduced
# yet. In order not to be bothered by tracing exact assembler versions,
# but at the same time to provide a bare security minimum of AES-NI, we
@@ -715,6 +699,15 @@ sub rex {
my %regrm = ( "%eax"=>0, "%ecx"=>1, "%edx"=>2, "%ebx"=>3,
"%esp"=>4, "%ebp"=>5, "%esi"=>6, "%edi"=>7 );
+sub rex {
+ my $opcode=shift;
+ my ($dst,$src,$rex)=@_;
+
+ $rex|=0x04 if($dst>=8);
+ $rex|=0x01 if($src>=8);
+ push @$opcode,($rex|0x40) if ($rex);
+}
+
my $movq = sub { # elderly gas can't handle inter-register movq
my $arg = shift;
my @opcode=(0x66);
@@ -838,6 +831,10 @@ my $rdseed = sub {
}
};
+# Not all AVX-capable assemblers recognize AMD XOP extension. Since we
+# are using only two instructions hand-code them in order to be excused
+# from chasing assembler versions...
+
sub rxb {
my $opcode=shift;
my ($dst,$src1,$src2,$rxb)=@_;
@@ -877,10 +874,15 @@ my $vprotq = sub {
}
};
+# Intel Control-flow Enforcement Technology extension. All functions and
+# indirect branch targets will have to start with this instruction...
+
my $endbranch = sub {
(0xf3,0x0f,0x1e,0xfa);
};
+########################################################################
+
if ($nasm) {
print <<___;
default rel
@@ -1077,6 +1079,7 @@ close STDOUT;
# movq -16(%rcx),%rbx
# movq -8(%rcx),%r15
# movq %rcx,%rsp # restore original rsp
+# magic_epilogue:
# ret
# .size function,.-function
#
@@ -1089,11 +1092,16 @@ close STDOUT;
# EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame,
# CONTEXT *context,DISPATCHER_CONTEXT *disp)
# { ULONG64 *rsp = (ULONG64 *)context->Rax;
-# if (context->Rip >= magic_point)
-# { rsp = ((ULONG64 **)context->Rsp)[0];
-# context->Rbp = rsp[-3];
-# context->Rbx = rsp[-2];
-# context->R15 = rsp[-1];
+# ULONG64 rip = context->Rip;
+#
+# if (rip >= magic_point)
+# { rsp = (ULONG64 *)context->Rsp;
+# if (rip < magic_epilogue)
+# { rsp = (ULONG64 *)rsp[0];
+# context->Rbp = rsp[-3];
+# context->Rbx = rsp[-2];
+# context->R15 = rsp[-1];
+# }
# }
# context->Rsp = (ULONG64)rsp;
# context->Rdi = rsp[1];
@@ -1185,13 +1193,12 @@ close STDOUT;
# instruction and reflecting it in finer grade unwind logic in handler.
# After all, isn't it why it's called *language-specific* handler...
#
-# Attentive reader can notice that exceptions would be mishandled in
-# auto-generated "gear" epilogue. Well, exception effectively can't
-# occur there, because if memory area used by it was subject to
-# segmentation violation, then it would be raised upon call to the
-# function (and as already mentioned be accounted to caller, which is
-# not a problem). If you're still not comfortable, then define tail
-# "magic point" just prior ret instruction and have handler treat it...
+# SE handlers are also involved in unwinding stack when executable is
+# profiled or debugged. Profiling implies additional limitations that
+# are too subtle to discuss here. For now it's sufficient to say that
+# in order to simplify handlers one should either a) offload original
+# %rsp to stack (like discussed above); or b) if you have a register to
+# spare for frame pointer, choose volatile one.
#
# (*) Note that we're talking about run-time, not debug-time. Lack of
# unwind information makes debugging hard on both Windows and
diff --git a/src/crypto/test/gtest_main.cc b/src/crypto/test/gtest_main.cc
index 50147bc8..50970af3 100644
--- a/src/crypto/test/gtest_main.cc
+++ b/src/crypto/test/gtest_main.cc
@@ -14,10 +14,35 @@
#include <gtest/gtest.h>
+#include <stdio.h>
+
+#include <openssl/err.h>
#include <openssl/crypto.h>
+namespace {
+
+class ErrorTestEventListener : public testing::EmptyTestEventListener {
+ public:
+ ErrorTestEventListener() {}
+ ~ErrorTestEventListener() override {}
+
+ void OnTestEnd(const testing::TestInfo &test_info) override {
+ // If the test failed, print any errors left in the error queue.
+ if (test_info.result()->Failed()) {
+ ERR_print_errors_fp(stdout);
+ }
+
+ // Clean up the error queue for the next run.
+ ERR_clear_error();
+ }
+};
+
+} // namespace
+
int main(int argc, char **argv) {
CRYPTO_library_init();
testing::InitGoogleTest(&argc, argv);
+ testing::UnitTest::GetInstance()->listeners().Append(
+ new ErrorTestEventListener);
return RUN_ALL_TESTS();
}
diff --git a/src/crypto/test/test_util.cc b/src/crypto/test/test_util.cc
index 928972a3..493b1247 100644
--- a/src/crypto/test/test_util.cc
+++ b/src/crypto/test/test_util.cc
@@ -12,11 +12,12 @@
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
-#include <stdint.h>
-#include <stdio.h>
-
#include "test_util.h"
+#include <ostream>
+
+#include "../internal.h"
+
void hexdump(FILE *fp, const char *msg, const void *in, size_t len) {
const uint8_t *data = reinterpret_cast<const uint8_t*>(in);
@@ -27,3 +28,13 @@ void hexdump(FILE *fp, const char *msg, const void *in, size_t len) {
}
fputs("\n", fp);
}
+
+std::ostream &operator<<(std::ostream &os, const Bytes &in) {
+ // Print a byte slice as hex.
+ static const char hex[] = "0123456789abcdef";
+ for (size_t i = 0; i < in.len; i++) {
+ os << hex[in.data[i] >> 4];
+ os << hex[in.data[i] & 0xf];
+ }
+ return os;
+}
diff --git a/src/crypto/test/test_util.h b/src/crypto/test/test_util.h
index 972e2065..d834973e 100644
--- a/src/crypto/test/test_util.h
+++ b/src/crypto/test/test_util.h
@@ -16,20 +16,38 @@
#define OPENSSL_HEADER_CRYPTO_TEST_TEST_UTIL_H
#include <stddef.h>
+#include <stdint.h>
#include <stdio.h>
-#if defined(__cplusplus)
-extern "C" {
-#endif
+#include <iosfwd>
+#include "../internal.h"
-/* hexdump writes |msg| to |fp| followed by the hex encoding of |len| bytes
- * from |in|. */
+
+// hexdump writes |msg| to |fp| followed by the hex encoding of |len| bytes
+// from |in|.
void hexdump(FILE *fp, const char *msg, const void *in, size_t len);
+// Bytes is a wrapper over a byte slice which may be compared for equality. This
+// allows it to be used in EXPECT_EQ macros.
+struct Bytes {
+ Bytes(const uint8_t *data_arg, size_t len_arg)
+ : data(data_arg), len(len_arg) {}
+
+ template <size_t N>
+ Bytes(const uint8_t (&array)[N]) : data(array), len(N) {}
+
+ const uint8_t *data;
+ size_t len;
+};
-#if defined(__cplusplus)
+inline bool operator==(const Bytes &a, const Bytes &b) {
+ return a.len == b.len && OPENSSL_memcmp(a.data, b.data, a.len) == 0;
}
-#endif
+
+inline bool operator!=(const Bytes &a, const Bytes &b) { return !(a == b); }
+
+std::ostream &operator<<(std::ostream &os, const Bytes &in);
+
#endif /* OPENSSL_HEADER_CRYPTO_TEST_TEST_UTIL_H */
diff --git a/src/crypto/x509/pkcs7_test.c b/src/crypto/x509/pkcs7_test.c
index 7bf4b81d..f620b9bc 100644
--- a/src/crypto/x509/pkcs7_test.c
+++ b/src/crypto/x509/pkcs7_test.c
@@ -23,7 +23,6 @@
#include <openssl/x509.h>
#include "../internal.h"
-#include "../test/test_util.h"
/* kPKCS7NSS contains the certificate chain of mail.google.com, as saved by NSS
diff --git a/src/crypto/x509v3/v3_cpols.c b/src/crypto/x509v3/v3_cpols.c
index d67dcb08..7de54962 100644
--- a/src/crypto/x509v3/v3_cpols.c
+++ b/src/crypto/x509v3/v3_cpols.c
@@ -400,10 +400,10 @@ static int nref_nos(STACK_OF(ASN1_INTEGER) *nnums, STACK_OF(CONF_VALUE) *nos)
return 1;
merr:
+ ASN1_INTEGER_free(aint);
OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
err:
- sk_ASN1_INTEGER_pop_free(nnums, ASN1_STRING_free);
return 0;
}
diff --git a/src/include/openssl/bn.h b/src/include/openssl/bn.h
index 77f61963..a57c23a9 100644
--- a/src/include/openssl/bn.h
+++ b/src/include/openssl/bn.h
@@ -476,6 +476,8 @@ OPENSSL_EXPORT int BN_is_word(const BIGNUM *bn, BN_ULONG w);
/* BN_is_odd returns one if |bn| is odd and zero otherwise. */
OPENSSL_EXPORT int BN_is_odd(const BIGNUM *bn);
+/* BN_is_pow2 returns 1 if |a| is a power of two, and 0 otherwise. */
+OPENSSL_EXPORT int BN_is_pow2(const BIGNUM *a);
/* Bitwise operations. */
@@ -519,6 +521,14 @@ OPENSSL_EXPORT int BN_mask_bits(BIGNUM *a, int n);
/* BN_mod_word returns |a| mod |w| or (BN_ULONG)-1 on error. */
OPENSSL_EXPORT BN_ULONG BN_mod_word(const BIGNUM *a, BN_ULONG w);
+/* BN_mod_pow2 sets |r| = |a| mod 2^|e|. It returns 1 on success and
+ * 0 on error. */
+OPENSSL_EXPORT int BN_mod_pow2(BIGNUM *r, const BIGNUM *a, size_t e);
+
+/* BN_nnmod_pow2 sets |r| = |a| mod 2^|e| where |r| is always positive.
+ * It returns 1 on success and 0 on error. */
+OPENSSL_EXPORT int BN_nnmod_pow2(BIGNUM *r, const BIGNUM *a, size_t e);
+
/* BN_mod is a helper macro that calls |BN_div| and discards the quotient. */
#define BN_mod(rem, numerator, divisor, ctx) \
BN_div(NULL, (rem), (numerator), (divisor), (ctx))
diff --git a/src/include/openssl/digest.h b/src/include/openssl/digest.h
index caf58610..87de3dfe 100644
--- a/src/include/openssl/digest.h
+++ b/src/include/openssl/digest.h
@@ -102,7 +102,8 @@ OPENSSL_EXPORT const EVP_MD *EVP_get_digestbyobj(const ASN1_OBJECT *obj);
* An EVP_MD_CTX represents the state of a specific digest operation in
* progress. */
-/* EVP_MD_CTX_init initialises an, already allocated, |EVP_MD_CTX|. */
+/* EVP_MD_CTX_init initialises an, already allocated, |EVP_MD_CTX|. This is the
+ * same as setting the structure to zero. */
OPENSSL_EXPORT void EVP_MD_CTX_init(EVP_MD_CTX *ctx);
/* EVP_MD_CTX_create allocates and initialises a fresh |EVP_MD_CTX| and returns
diff --git a/src/include/openssl/ssl.h b/src/include/openssl/ssl.h
index 263b2728..497093db 100644
--- a/src/include/openssl/ssl.h
+++ b/src/include/openssl/ssl.h
@@ -904,6 +904,14 @@ OPENSSL_EXPORT int SSL_CTX_set_signed_cert_timestamp_list(SSL_CTX *ctx,
const uint8_t *list,
size_t list_len);
+/* SSL_set_signed_cert_timestamp_list sets the list of signed certificate
+ * timestamps that is sent to clients that request is. The same format as the
+ * one used for |SSL_CTX_set_signed_cert_timestamp_list| applies. The caller
+ * retains ownership of |list|. */
+OPENSSL_EXPORT int SSL_set_signed_cert_timestamp_list(SSL *ctx,
+ const uint8_t *list,
+ size_t list_len);
+
/* SSL_CTX_set_ocsp_response sets the OCSP response that is sent to clients
* which request it. It returns one on success and zero on error. The caller
* retains ownership of |response|. */
@@ -1562,9 +1570,9 @@ DECLARE_LHASH_OF(SSL_SESSION)
DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION)
/* SSL_SESSION_new returns a newly-allocated blank |SSL_SESSION| or NULL on
- * error. This may be useful in writing tests but otherwise should not be
- * used outside the library. */
-OPENSSL_EXPORT SSL_SESSION *SSL_SESSION_new(void);
+ * error. This may be useful when writing tests but should otherwise not be
+ * used. */
+OPENSSL_EXPORT SSL_SESSION *SSL_SESSION_new(const SSL_CTX *ctx);
/* SSL_SESSION_up_ref increments the reference count of |session| and returns
* one. */
@@ -1589,8 +1597,8 @@ OPENSSL_EXPORT int SSL_SESSION_to_bytes_for_ticket(const SSL_SESSION *in,
/* SSL_SESSION_from_bytes parses |in_len| bytes from |in| as an SSL_SESSION. It
* returns a newly-allocated |SSL_SESSION| on success or NULL on error. */
-OPENSSL_EXPORT SSL_SESSION *SSL_SESSION_from_bytes(const uint8_t *in,
- size_t in_len);
+OPENSSL_EXPORT SSL_SESSION *SSL_SESSION_from_bytes(
+ const uint8_t *in, size_t in_len, const SSL_CTX *ctx);
/* SSL_SESSION_get_version returns a string describing the TLS version |session|
* was established at. For example, "TLSv1.2" or "SSLv3". */
@@ -1753,20 +1761,6 @@ OPENSSL_EXPORT void SSL_CTX_set_session_psk_dhe_timeout(SSL_CTX *ctx,
* sessions created in |ctx|. */
OPENSSL_EXPORT long SSL_CTX_get_timeout(const SSL_CTX *ctx);
-/* SSL_set_session_timeout sets the default lifetime, in seconds, of a TLS 1.2
- * (or earlier) session created in |ssl| to |timeout|, and returns the old
- * value.
- *
- * By default the value |SSL_DEFAULT_SESSION_TIMEOUT| is used, which can be
- * overridden at the context level by calling |SSL_CTX_set_timeout|.
- *
- * If |timeout| is zero the newly created session will not be resumable. */
-OPENSSL_EXPORT long SSL_set_session_timeout(SSL *ssl, long timeout);
-
-/* SSL_set_session_psk_dhe_timeout sets the lifetime, in seconds, of TLS 1.3
- * sessions created in |ssl| to |timeout|. */
-OPENSSL_EXPORT void SSL_set_session_psk_dhe_timeout(SSL *ssl, long timeout);
-
/* SSL_CTX_set_session_id_context sets |ctx|'s session ID context to |sid_ctx|.
* It returns one on success and zero on error. The session ID context is an
* application-defined opaque byte string. A session will not be used in a
@@ -3688,6 +3682,7 @@ OPENSSL_EXPORT long BIO_set_ssl(BIO *bio, SSL *ssl, int take_owership);
* deprecated. */
typedef struct ssl_protocol_method_st SSL_PROTOCOL_METHOD;
+typedef struct ssl_x509_method_st SSL_X509_METHOD;
struct ssl_cipher_st {
/* name is the OpenSSL name for the cipher. */
@@ -3739,6 +3734,8 @@ struct ssl_session_st {
* certificate. */
STACK_OF(CRYPTO_BUFFER) *certs;
+ const SSL_X509_METHOD *x509_method;
+
/* x509_peer is the peer's certificate. */
X509 *x509_peer;
@@ -3866,6 +3863,7 @@ struct ssl_cipher_preference_list_st {
* connections. */
struct ssl_ctx_st {
const SSL_PROTOCOL_METHOD *method;
+ const SSL_X509_METHOD *x509_method;
/* lock is used to protect various operations on this object. */
CRYPTO_MUTEX lock;
@@ -4064,8 +4062,7 @@ struct ssl_ctx_st {
EVP_PKEY *tlsext_channel_id_private;
/* Signed certificate timestamp list to be sent to the client, if requested */
- uint8_t *signed_cert_timestamp_list;
- size_t signed_cert_timestamp_list_length;
+ CRYPTO_BUFFER *signed_cert_timestamp_list;
/* OCSP response to be sent to the client, if requested. */
CRYPTO_BUFFER *ocsp_response;
diff --git a/src/include/openssl/ssl3.h b/src/include/openssl/ssl3.h
index 84051ff2..6a03d1be 100644
--- a/src/include/openssl/ssl3.h
+++ b/src/include/openssl/ssl3.h
@@ -345,9 +345,6 @@ OPENSSL_COMPILE_ASSERT(
#define SSL3_ST_SR_CLNT_HELLO_C (0x112 | SSL_ST_ACCEPT)
#define SSL3_ST_SR_CLNT_HELLO_D (0x113 | SSL_ST_ACCEPT)
/* write to client */
-#define SSL3_ST_SW_HELLO_REQ_A (0x120 | SSL_ST_ACCEPT)
-#define SSL3_ST_SW_HELLO_REQ_B (0x121 | SSL_ST_ACCEPT)
-#define SSL3_ST_SW_HELLO_REQ_C (0x122 | SSL_ST_ACCEPT)
#define SSL3_ST_SW_SRVR_HELLO_A (0x130 | SSL_ST_ACCEPT)
#define SSL3_ST_SW_CERT_A (0x140 | SSL_ST_ACCEPT)
#define SSL3_ST_SW_KEY_EXCH_A (0x150 | SSL_ST_ACCEPT)
diff --git a/src/ssl/CMakeLists.txt b/src/ssl/CMakeLists.txt
index afc3a398..5b5ea976 100644
--- a/src/ssl/CMakeLists.txt
+++ b/src/ssl/CMakeLists.txt
@@ -5,16 +5,15 @@ add_library(
bio_ssl.c
custom_extensions.c
- handshake_server.c
- handshake_client.c
d1_both.c
d1_lib.c
d1_pkt.c
d1_srtp.c
dtls_method.c
dtls_record.c
+ handshake_client.c
+ handshake_server.c
s3_both.c
- s3_enc.c
s3_lib.c
s3_pkt.c
ssl_aead_ctx.c
@@ -25,10 +24,11 @@ add_library(
ssl_ecdh.c
ssl_file.c
ssl_lib.c
- ssl_rsa.c
- ssl_rsa_cc.cc
+ ssl_privkey.c
+ ssl_privkey_cc.cc
ssl_session.c
ssl_stat.c
+ ssl_transcript.c
ssl_x509.c
t1_enc.c
t1_lib.c
diff --git a/src/ssl/d1_both.c b/src/ssl/d1_both.c
index 48a5c542..b864e426 100644
--- a/src/ssl/d1_both.c
+++ b/src/ssl/d1_both.c
@@ -549,7 +549,14 @@ static int add_outgoing(SSL *ssl, int is_ccs, uint8_t *data, size_t len) {
}
if (!is_ccs) {
- ssl3_update_handshake_hash(ssl, data, len);
+ /* TODO(svaldez): Move this up a layer to fix abstraction for SSL_TRANSCRIPT
+ * on hs. */
+ if (ssl->s3->hs != NULL &&
+ !SSL_TRANSCRIPT_update(&ssl->s3->hs->transcript, data, len)) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+ OPENSSL_free(data);
+ return 0;
+ }
ssl->d1->handshake_write_seq++;
}
diff --git a/src/ssl/dtls_method.c b/src/ssl/dtls_method.c
index 7a35b398..60847895 100644
--- a/src/ssl/dtls_method.c
+++ b/src/ssl/dtls_method.c
@@ -165,6 +165,7 @@ const SSL_METHOD *DTLS_method(void) {
static const SSL_METHOD kMethod = {
0,
&kDTLSProtocolMethod,
+ &ssl_crypto_x509_method,
};
return &kMethod;
}
@@ -175,6 +176,7 @@ const SSL_METHOD *DTLSv1_2_method(void) {
static const SSL_METHOD kMethod = {
DTLS1_2_VERSION,
&kDTLSProtocolMethod,
+ &ssl_crypto_x509_method,
};
return &kMethod;
}
@@ -183,6 +185,7 @@ const SSL_METHOD *DTLSv1_method(void) {
static const SSL_METHOD kMethod = {
DTLS1_VERSION,
&kDTLSProtocolMethod,
+ &ssl_crypto_x509_method,
};
return &kMethod;
}
diff --git a/src/ssl/handshake_client.c b/src/ssl/handshake_client.c
index 23a4cffc..427213c2 100644
--- a/src/ssl/handshake_client.c
+++ b/src/ssl/handshake_client.c
@@ -399,7 +399,7 @@ int ssl3_connect(SSL_HANDSHAKE *hs) {
* record the handshake hashes at this point in the session so that
* any resumption of this session with ChannelID can sign those
* hashes. */
- ret = tls1_record_handshake_hashes_for_channel_id(ssl);
+ ret = tls1_record_handshake_hashes_for_channel_id(hs);
if (ret <= 0) {
goto end;
}
@@ -732,7 +732,7 @@ int ssl_write_client_hello(SSL_HANDSHAKE *hs) {
/* Now that the length prefixes have been computed, fill in the placeholder
* PSK binder. */
if (hs->needs_psk_binder &&
- !tls13_write_psk_binder(ssl, msg, len)) {
+ !tls13_write_psk_binder(hs, msg, len)) {
OPENSSL_free(msg);
goto err;
}
@@ -748,7 +748,7 @@ static int ssl3_send_client_hello(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
/* The handshake buffer is reset on every ClientHello. Notably, in DTLS, we
* may send multiple ClientHellos if we receive HelloVerifyRequest. */
- if (!ssl3_init_handshake_buffer(ssl)) {
+ if (!SSL_TRANSCRIPT_init(&hs->transcript)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
return -1;
}
@@ -819,9 +819,6 @@ static int dtls1_get_hello_verify(SSL_HANDSHAKE *hs) {
return 1;
}
- /* The handshake transcript is reset on HelloVerifyRequst, so do not bother
- * hashing it. */
-
CBS_init(&hello_verify_request, ssl->init_msg, ssl->init_num);
if (!CBS_get_u16(&hello_verify_request, &server_version) ||
!CBS_get_u8_length_prefixed(&hello_verify_request, &cookie) ||
@@ -897,8 +894,6 @@ static int ssl3_get_server_hello(SSL_HANDSHAKE *hs) {
assert(ssl->s3->have_version == ssl->s3->initial_handshake_complete);
if (!ssl->s3->have_version) {
ssl->version = server_wire_version;
- ssl->s3->enc_method = ssl3_get_enc_method(server_version);
- assert(ssl->s3->enc_method != NULL);
/* At this point, the connection's version is known and ssl->version is
* fixed. Begin enforcing the record-layer version. */
ssl->s3->have_version = 1;
@@ -999,8 +994,9 @@ static int ssl3_get_server_hello(SSL_HANDSHAKE *hs) {
/* Now that the cipher is known, initialize the handshake hash and hash the
* ServerHello. */
- if (!ssl3_init_handshake_hash(ssl) ||
- !ssl_hash_current_message(ssl)) {
+ if (!SSL_TRANSCRIPT_init_hash(&hs->transcript, ssl3_protocol_version(ssl),
+ c->algorithm_prf) ||
+ !ssl_hash_current_message(hs)) {
goto f_err;
}
@@ -1009,7 +1005,7 @@ static int ssl3_get_server_hello(SSL_HANDSHAKE *hs) {
* buffer may be released. */
if (ssl->session != NULL ||
!ssl_cipher_uses_certificate_auth(ssl->s3->tmp.new_cipher)) {
- ssl3_free_handshake_buffer(ssl);
+ SSL_TRANSCRIPT_free_buffer(&hs->transcript);
}
/* Only the NULL compression algorithm is supported. */
@@ -1061,14 +1057,14 @@ static int ssl3_get_server_certificate(SSL_HANDSHAKE *hs) {
}
if (!ssl_check_message_type(ssl, SSL3_MT_CERTIFICATE) ||
- !ssl_hash_current_message(ssl)) {
+ !ssl_hash_current_message(hs)) {
return -1;
}
CBS cbs;
CBS_init(&cbs, ssl->init_msg, ssl->init_num);
- uint8_t alert;
+ uint8_t alert = SSL_AD_DECODE_ERROR;
sk_CRYPTO_BUFFER_pop_free(ssl->s3->new_session->certs, CRYPTO_BUFFER_free);
EVP_PKEY_free(hs->peer_pubkey);
hs->peer_pubkey = NULL;
@@ -1081,7 +1077,7 @@ static int ssl3_get_server_certificate(SSL_HANDSHAKE *hs) {
if (sk_CRYPTO_BUFFER_num(ssl->s3->new_session->certs) == 0 ||
CBS_len(&cbs) != 0 ||
- !ssl_session_x509_cache_objects(ssl->s3->new_session)) {
+ !ssl->ctx->x509_method->session_cache_objects(ssl->s3->new_session)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
return -1;
@@ -1115,7 +1111,7 @@ static int ssl3_get_cert_status(SSL_HANDSHAKE *hs) {
return 1;
}
- if (!ssl_hash_current_message(ssl)) {
+ if (!ssl_hash_current_message(hs)) {
return -1;
}
@@ -1177,7 +1173,7 @@ static int ssl3_get_server_key_exchange(SSL_HANDSHAKE *hs) {
return 1;
}
- if (!ssl_hash_current_message(ssl)) {
+ if (!ssl_hash_current_message(hs)) {
return -1;
}
@@ -1403,12 +1399,12 @@ static int ssl3_get_certificate_request(SSL_HANDSHAKE *hs) {
ssl->s3->tmp.reuse_message = 1;
/* If we get here we don't need the handshake buffer as we won't be doing
* client auth. */
- ssl3_free_handshake_buffer(ssl);
+ SSL_TRANSCRIPT_free_buffer(&hs->transcript);
return 1;
}
if (!ssl_check_message_type(ssl, SSL3_MT_CERTIFICATE_REQUEST) ||
- !ssl_hash_current_message(ssl)) {
+ !ssl_hash_current_message(hs)) {
return -1;
}
@@ -1439,7 +1435,7 @@ static int ssl3_get_certificate_request(SSL_HANDSHAKE *hs) {
}
}
- uint8_t alert;
+ uint8_t alert = SSL_AD_DECODE_ERROR;
STACK_OF(X509_NAME) *ca_sk = ssl_parse_client_CA_list(ssl, &alert, &cbs);
if (ca_sk == NULL) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
@@ -1467,7 +1463,7 @@ static int ssl3_get_server_hello_done(SSL_HANDSHAKE *hs) {
}
if (!ssl_check_message_type(ssl, SSL3_MT_SERVER_HELLO_DONE) ||
- !ssl_hash_current_message(ssl)) {
+ !ssl_hash_current_message(hs)) {
return -1;
}
@@ -1499,7 +1495,7 @@ static int ssl3_send_client_certificate(SSL_HANDSHAKE *hs) {
if (!ssl_has_certificate(ssl)) {
/* Without a client certificate, the handshake buffer may be released. */
- ssl3_free_handshake_buffer(ssl);
+ SSL_TRANSCRIPT_free_buffer(&hs->transcript);
/* In SSL 3.0, the Certificate message is replaced with a warning alert. */
if (ssl->version == SSL3_VERSION) {
@@ -1619,7 +1615,7 @@ static int ssl3_send_client_key_exchange(SSL_HANDSHAKE *hs) {
}
/* Compute the premaster. */
- uint8_t alert;
+ uint8_t alert = SSL_AD_DECODE_ERROR;
if (!SSL_ECDH_CTX_accept(&hs->ecdh_ctx, &child, &pms, &pms_len, &alert,
hs->peer_key, hs->peer_key_len)) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
@@ -1680,9 +1676,8 @@ static int ssl3_send_client_key_exchange(SSL_HANDSHAKE *hs) {
goto err;
}
- ssl->s3->new_session->master_key_length =
- tls1_generate_master_secret(ssl, ssl->s3->new_session->master_key, pms,
- pms_len);
+ ssl->s3->new_session->master_key_length = tls1_generate_master_secret(
+ hs, ssl->s3->new_session->master_key, pms, pms_len);
if (ssl->s3->new_session->master_key_length == 0) {
goto err;
}
@@ -1743,11 +1738,11 @@ static int ssl3_send_cert_verify(SSL_HANDSHAKE *hs) {
goto err;
}
- const EVP_MD *md;
uint8_t digest[EVP_MAX_MD_SIZE];
size_t digest_len;
- if (!ssl3_cert_verify_hash(ssl, &md, digest, &digest_len,
- signature_algorithm)) {
+ if (!SSL_TRANSCRIPT_ssl3_cert_verify_hash(
+ &hs->transcript, digest, &digest_len, ssl->s3->new_session,
+ signature_algorithm)) {
goto err;
}
@@ -1756,7 +1751,6 @@ static int ssl3_send_cert_verify(SSL_HANDSHAKE *hs) {
EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new(ssl->cert->privatekey, NULL);
if (pctx == NULL ||
!EVP_PKEY_sign_init(pctx) ||
- !EVP_PKEY_CTX_set_signature_md(pctx, md) ||
!EVP_PKEY_sign(pctx, ptr, &sig_len, digest, digest_len)) {
EVP_PKEY_CTX_free(pctx);
sign_result = ssl_private_key_failure;
@@ -1766,12 +1760,12 @@ static int ssl3_send_cert_verify(SSL_HANDSHAKE *hs) {
} else {
sign_result = ssl_private_key_sign(
ssl, ptr, &sig_len, max_sig_len, signature_algorithm,
- (const uint8_t *)ssl->s3->handshake_buffer->data,
- ssl->s3->handshake_buffer->length);
+ (const uint8_t *)hs->transcript.buffer->data,
+ hs->transcript.buffer->length);
}
/* The handshake buffer is no longer necessary. */
- ssl3_free_handshake_buffer(ssl);
+ SSL_TRANSCRIPT_free_buffer(&hs->transcript);
} else {
assert(hs->state == SSL3_ST_CW_CERT_VRFY_B);
sign_result = ssl_private_key_complete(ssl, ptr, &sig_len, max_sig_len);
@@ -1834,7 +1828,7 @@ static int ssl3_send_channel_id(SSL_HANDSHAKE *hs) {
CBB cbb, body;
if (!ssl->method->init_message(ssl, &cbb, &body, SSL3_MT_CHANNEL_ID) ||
- !tls1_write_channel_id(ssl, &body) ||
+ !tls1_write_channel_id(hs, &body) ||
!ssl_add_message_cbb(ssl, &cbb)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
CBB_cleanup(&cbb);
@@ -1852,7 +1846,7 @@ static int ssl3_get_new_session_ticket(SSL_HANDSHAKE *hs) {
}
if (!ssl_check_message_type(ssl, SSL3_MT_NEW_SESSION_TICKET) ||
- !ssl_hash_current_message(ssl)) {
+ !ssl_hash_current_message(hs)) {
return -1;
}
diff --git a/src/ssl/handshake_server.c b/src/ssl/handshake_server.c
index 00f451e4..c352dd95 100644
--- a/src/ssl/handshake_server.c
+++ b/src/ssl/handshake_server.c
@@ -171,7 +171,9 @@
#include "../crypto/internal.h"
-static int ssl3_get_client_hello(SSL_HANDSHAKE *hs);
+static int ssl3_process_client_hello(SSL_HANDSHAKE *hs);
+static int ssl3_select_certificate(SSL_HANDSHAKE *hs);
+static int ssl3_select_parameters(SSL_HANDSHAKE *hs);
static int ssl3_send_server_hello(SSL_HANDSHAKE *hs);
static int ssl3_send_server_certificate(SSL_HANDSHAKE *hs);
static int ssl3_send_certificate_status(SSL_HANDSHAKE *hs);
@@ -216,24 +218,37 @@ int ssl3_accept(SSL_HANDSHAKE *hs) {
case SSL_ST_ACCEPT:
ssl_do_info_callback(ssl, SSL_CB_HANDSHAKE_START, 1);
+ hs->state = SSL3_ST_SR_CLNT_HELLO_A;
+ break;
- if (!ssl3_init_handshake_buffer(ssl)) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
- ret = -1;
+ case SSL3_ST_SR_CLNT_HELLO_A:
+ ret = ssl->method->ssl_get_message(ssl);
+ if (ret <= 0) {
goto end;
}
-
- hs->state = SSL3_ST_SR_CLNT_HELLO_A;
+ hs->state = SSL3_ST_SR_CLNT_HELLO_B;
break;
- case SSL3_ST_SR_CLNT_HELLO_A:
case SSL3_ST_SR_CLNT_HELLO_B:
+ ret = ssl3_process_client_hello(hs);
+ if (ret <= 0) {
+ goto end;
+ }
+ hs->state = SSL3_ST_SR_CLNT_HELLO_C;
+ break;
+
case SSL3_ST_SR_CLNT_HELLO_C:
- case SSL3_ST_SR_CLNT_HELLO_D:
- ret = ssl3_get_client_hello(hs);
- if (hs->state == SSL_ST_TLS13) {
- break;
+ ret = ssl3_select_certificate(hs);
+ if (ret <= 0) {
+ goto end;
+ }
+ if (hs->state != SSL_ST_TLS13) {
+ hs->state = SSL3_ST_SR_CLNT_HELLO_D;
}
+ break;
+
+ case SSL3_ST_SR_CLNT_HELLO_D:
+ ret = ssl3_select_parameters(hs);
if (ret <= 0) {
goto end;
}
@@ -399,7 +414,7 @@ int ssl3_accept(SSL_HANDSHAKE *hs) {
* hashes in |ssl->s3->new_session| in case we need them to verify a
* ChannelID signature on a resumption of this session in the future. */
if (ssl->session == NULL && ssl->s3->tlsext_channel_id_valid) {
- ret = tls1_record_handshake_hashes_for_channel_id(ssl);
+ ret = tls1_record_handshake_hashes_for_channel_id(hs);
if (ret <= 0) {
goto end;
}
@@ -468,10 +483,10 @@ int ssl3_accept(SSL_HANDSHAKE *hs) {
* now. */
if (ssl->s3->new_session != NULL &&
ssl->retain_only_sha256_of_client_certs) {
- X509_free(ssl->s3->new_session->x509_peer);
- ssl->s3->new_session->x509_peer = NULL;
- sk_X509_pop_free(ssl->s3->new_session->x509_chain, X509_free);
- ssl->s3->new_session->x509_chain = NULL;
+ sk_CRYPTO_BUFFER_pop_free(ssl->s3->new_session->certs,
+ CRYPTO_BUFFER_free);
+ ssl->s3->new_session->certs = NULL;
+ ssl->ctx->x509_method->session_clear(ssl->s3->new_session);
}
SSL_SESSION_free(ssl->s3->established_session);
@@ -632,8 +647,6 @@ static int negotiate_version(SSL_HANDSHAKE *hs, uint8_t *out_alert,
hs->client_version = client_hello->version;
ssl->version = ssl->method->version_to_wire(version);
- ssl->s3->enc_method = ssl3_get_enc_method(version);
- assert(ssl->s3->enc_method != NULL);
/* At this point, the connection's version is known and |ssl->version| is
* fixed. Begin enforcing the record-layer version. */
@@ -807,126 +820,130 @@ static const SSL_CIPHER *ssl3_choose_cipher(
return ret;
}
-static int ssl3_get_client_hello(SSL_HANDSHAKE *hs) {
+static int ssl3_process_client_hello(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
- uint8_t al = SSL_AD_INTERNAL_ERROR;
- int ret = -1;
- SSL_SESSION *session = NULL;
-
- if (hs->state == SSL3_ST_SR_CLNT_HELLO_A) {
- /* The first time around, read the ClientHello. */
- int msg_ret = ssl->method->ssl_get_message(ssl);
- if (msg_ret <= 0) {
- return msg_ret;
- }
-
- if (!ssl_check_message_type(ssl, SSL3_MT_CLIENT_HELLO)) {
- return -1;
- }
-
- hs->state = SSL3_ST_SR_CLNT_HELLO_B;
+ if (!ssl_check_message_type(ssl, SSL3_MT_CLIENT_HELLO)) {
+ return -1;
}
SSL_CLIENT_HELLO client_hello;
if (!ssl_client_hello_init(ssl, &client_hello, ssl->init_msg,
ssl->init_num)) {
- al = SSL_AD_DECODE_ERROR;
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
- goto f_err;
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+ return -1;
}
- if (hs->state == SSL3_ST_SR_CLNT_HELLO_B) {
- /* Run the early callback. */
- if (ssl->ctx->select_certificate_cb != NULL) {
- switch (ssl->ctx->select_certificate_cb(&client_hello)) {
- case 0:
- ssl->rwstate = SSL_CERTIFICATE_SELECTION_PENDING;
- goto err;
+ /* Run the early callback. */
+ if (ssl->ctx->select_certificate_cb != NULL) {
+ switch (ssl->ctx->select_certificate_cb(&client_hello)) {
+ case 0:
+ ssl->rwstate = SSL_CERTIFICATE_SELECTION_PENDING;
+ return -1;
- case -1:
- /* Connection rejected. */
- al = SSL_AD_HANDSHAKE_FAILURE;
- OPENSSL_PUT_ERROR(SSL, SSL_R_CONNECTION_REJECTED);
- goto f_err;
+ case -1:
+ /* Connection rejected. */
+ OPENSSL_PUT_ERROR(SSL, SSL_R_CONNECTION_REJECTED);
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
+ return -1;
- default:
- /* fallthrough */;
- }
+ default:
+ /* fallthrough */;
}
+ }
- if (!negotiate_version(hs, &al, &client_hello)) {
- goto f_err;
- }
+ uint8_t alert = SSL_AD_DECODE_ERROR;
+ if (!negotiate_version(hs, &alert, &client_hello)) {
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
+ return -1;
+ }
- /* Load the client random. */
- if (client_hello.random_len != SSL3_RANDOM_SIZE) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+ /* Load the client random. */
+ if (client_hello.random_len != SSL3_RANDOM_SIZE) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+ return -1;
+ }
+ OPENSSL_memcpy(ssl->s3->client_random, client_hello.random,
+ client_hello.random_len);
+
+ /* Only null compression is supported. TLS 1.3 further requires the peer
+ * advertise no other compression. */
+ if (OPENSSL_memchr(client_hello.compression_methods, 0,
+ client_hello.compression_methods_len) == NULL ||
+ (ssl3_protocol_version(ssl) >= TLS1_3_VERSION &&
+ client_hello.compression_methods_len != 1)) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_COMPRESSION_LIST);
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
+ return -1;
+ }
+
+ /* TLS extensions. */
+ if (!ssl_parse_clienthello_tlsext(hs, &client_hello)) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_PARSE_TLSEXT);
+ return -1;
+ }
+
+ return 1;
+}
+
+static int ssl3_select_certificate(SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
+ /* Call |cert_cb| to update server certificates if required. */
+ if (ssl->cert->cert_cb != NULL) {
+ int rv = ssl->cert->cert_cb(ssl, ssl->cert->cert_cb_arg);
+ if (rv == 0) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_CERT_CB_ERROR);
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
return -1;
}
- OPENSSL_memcpy(ssl->s3->client_random, client_hello.random,
- client_hello.random_len);
-
- /* Only null compression is supported. TLS 1.3 further requires the peer
- * advertise no other compression. */
- if (OPENSSL_memchr(client_hello.compression_methods, 0,
- client_hello.compression_methods_len) == NULL ||
- (ssl3_protocol_version(ssl) >= TLS1_3_VERSION &&
- client_hello.compression_methods_len != 1)) {
- al = SSL_AD_ILLEGAL_PARAMETER;
- OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_COMPRESSION_LIST);
- goto f_err;
+ if (rv < 0) {
+ ssl->rwstate = SSL_X509_LOOKUP;
+ return -1;
}
+ }
- /* TLS extensions. */
- if (!ssl_parse_clienthello_tlsext(hs, &client_hello)) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_PARSE_TLSEXT);
- goto err;
- }
+ if (!ssl_auto_chain_if_needed(ssl)) {
+ return -1;
+ }
- hs->state = SSL3_ST_SR_CLNT_HELLO_C;
+ if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION) {
+ /* Jump to the TLS 1.3 state machine. */
+ hs->state = SSL_ST_TLS13;
+ hs->do_tls13_handshake = tls13_server_handshake;
+ return 1;
}
- if (hs->state == SSL3_ST_SR_CLNT_HELLO_C) {
- /* Call |cert_cb| to update server certificates if required. */
- if (ssl->cert->cert_cb != NULL) {
- int rv = ssl->cert->cert_cb(ssl, ssl->cert->cert_cb_arg);
- if (rv == 0) {
- al = SSL_AD_INTERNAL_ERROR;
- OPENSSL_PUT_ERROR(SSL, SSL_R_CERT_CB_ERROR);
- goto f_err;
- }
- if (rv < 0) {
- ssl->rwstate = SSL_X509_LOOKUP;
- goto err;
- }
- }
+ SSL_CLIENT_HELLO client_hello;
+ if (!ssl_client_hello_init(ssl, &client_hello, ssl->init_msg,
+ ssl->init_num)) {
+ return -1;
+ }
- if (!ssl_auto_chain_if_needed(ssl)) {
- goto err;
- }
+ /* Negotiate the cipher suite. This must be done after |cert_cb| so the
+ * certificate is finalized. */
+ ssl->s3->tmp.new_cipher =
+ ssl3_choose_cipher(hs, &client_hello, ssl_get_cipher_preferences(ssl));
+ if (ssl->s3->tmp.new_cipher == NULL) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_NO_SHARED_CIPHER);
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
+ return -1;
+ }
- if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION) {
- /* Jump to the TLS 1.3 state machine. */
- hs->state = SSL_ST_TLS13;
- hs->do_tls13_handshake = tls13_server_handshake;
- return 1;
- }
+ return 1;
+}
- /* Negotiate the cipher suite. This must be done after |cert_cb| so the
- * certificate is finalized. */
- ssl->s3->tmp.new_cipher =
- ssl3_choose_cipher(hs, &client_hello, ssl_get_cipher_preferences(ssl));
- if (ssl->s3->tmp.new_cipher == NULL) {
- al = SSL_AD_HANDSHAKE_FAILURE;
- OPENSSL_PUT_ERROR(SSL, SSL_R_NO_SHARED_CIPHER);
- goto f_err;
- }
+static int ssl3_select_parameters(SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
+ uint8_t al = SSL_AD_INTERNAL_ERROR;
+ int ret = -1;
+ SSL_SESSION *session = NULL;
- hs->state = SSL3_ST_SR_CLNT_HELLO_D;
+ SSL_CLIENT_HELLO client_hello;
+ if (!ssl_client_hello_init(ssl, &client_hello, ssl->init_msg,
+ ssl->init_num)) {
+ return -1;
}
- assert(hs->state == SSL3_ST_SR_CLNT_HELLO_D);
-
/* Determine whether we are doing session resumption. */
int tickets_supported = 0, renew_ticket = 0;
switch (ssl_get_prev_session(ssl, &session, &tickets_supported, &renew_ticket,
@@ -1027,14 +1044,15 @@ static int ssl3_get_client_hello(SSL_HANDSHAKE *hs) {
/* Now that all parameters are known, initialize the handshake hash and hash
* the ClientHello. */
- if (!ssl3_init_handshake_hash(ssl) ||
- !ssl_hash_current_message(ssl)) {
+ if (!SSL_TRANSCRIPT_init_hash(&hs->transcript, ssl3_protocol_version(ssl),
+ ssl->s3->tmp.new_cipher->algorithm_prf) ||
+ !ssl_hash_current_message(hs)) {
goto f_err;
}
/* Release the handshake buffer if client authentication isn't required. */
if (!hs->cert_request) {
- ssl3_free_handshake_buffer(ssl);
+ SSL_TRANSCRIPT_free_buffer(&hs->transcript);
}
ret = 1;
@@ -1431,7 +1449,7 @@ static int ssl3_get_client_certificate(SSL_HANDSHAKE *hs) {
return -1;
}
- if (!ssl_hash_current_message(ssl)) {
+ if (!ssl_hash_current_message(hs)) {
return -1;
}
@@ -1441,7 +1459,7 @@ static int ssl3_get_client_certificate(SSL_HANDSHAKE *hs) {
sk_CRYPTO_BUFFER_pop_free(ssl->s3->new_session->certs, CRYPTO_BUFFER_free);
EVP_PKEY_free(hs->peer_pubkey);
hs->peer_pubkey = NULL;
- uint8_t alert;
+ uint8_t alert = SSL_AD_DECODE_ERROR;
ssl->s3->new_session->certs =
ssl_parse_cert_chain(&alert, &hs->peer_pubkey,
ssl->retain_only_sha256_of_client_certs
@@ -1454,7 +1472,7 @@ static int ssl3_get_client_certificate(SSL_HANDSHAKE *hs) {
}
if (CBS_len(&certificate_msg) != 0 ||
- !ssl_session_x509_cache_objects(ssl->s3->new_session)) {
+ !ssl->ctx->x509_method->session_cache_objects(ssl->s3->new_session)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
return -1;
@@ -1462,7 +1480,7 @@ static int ssl3_get_client_certificate(SSL_HANDSHAKE *hs) {
if (sk_CRYPTO_BUFFER_num(ssl->s3->new_session->certs) == 0) {
/* No client certificate so the handshake buffer may be discarded. */
- ssl3_free_handshake_buffer(ssl);
+ SSL_TRANSCRIPT_free_buffer(&hs->transcript);
/* In SSL 3.0, sending no certificate is signaled by omitting the
* Certificate message. */
@@ -1517,7 +1535,7 @@ static int ssl3_get_client_key_exchange(SSL_HANDSHAKE *hs) {
}
if (!ssl_check_message_type(ssl, SSL3_MT_CLIENT_KEY_EXCHANGE) ||
- !ssl_hash_current_message(ssl)) {
+ !ssl_hash_current_message(hs)) {
return -1;
}
}
@@ -1693,7 +1711,7 @@ static int ssl3_get_client_key_exchange(SSL_HANDSHAKE *hs) {
}
/* Compute the premaster. */
- uint8_t alert;
+ uint8_t alert = SSL_AD_DECODE_ERROR;
if (!SSL_ECDH_CTX_finish(&hs->ecdh_ctx, &premaster_secret,
&premaster_secret_len, &alert, CBS_data(&peer_key),
CBS_len(&peer_key))) {
@@ -1745,9 +1763,9 @@ static int ssl3_get_client_key_exchange(SSL_HANDSHAKE *hs) {
}
/* Compute the master secret */
- ssl->s3->new_session->master_key_length = tls1_generate_master_secret(
- ssl, ssl->s3->new_session->master_key, premaster_secret,
- premaster_secret_len);
+ ssl->s3->new_session->master_key_length =
+ tls1_generate_master_secret(hs, ssl->s3->new_session->master_key,
+ premaster_secret, premaster_secret_len);
if (ssl->s3->new_session->master_key_length == 0) {
goto err;
}
@@ -1779,7 +1797,7 @@ static int ssl3_get_cert_verify(SSL_HANDSHAKE *hs) {
* CertificateVerify is required if and only if there's a client certificate.
* */
if (hs->peer_pubkey == NULL) {
- ssl3_free_handshake_buffer(ssl);
+ SSL_TRANSCRIPT_free_buffer(&hs->transcript);
return 1;
}
@@ -1828,26 +1846,25 @@ static int ssl3_get_cert_verify(SSL_HANDSHAKE *hs) {
/* The SSL3 construction for CertificateVerify does not decompose into a
* single final digest and signature, and must be special-cased. */
if (ssl3_protocol_version(ssl) == SSL3_VERSION) {
- const EVP_MD *md;
uint8_t digest[EVP_MAX_MD_SIZE];
size_t digest_len;
- if (!ssl3_cert_verify_hash(ssl, &md, digest, &digest_len,
- signature_algorithm)) {
+ if (!SSL_TRANSCRIPT_ssl3_cert_verify_hash(&hs->transcript, digest,
+ &digest_len, ssl->s3->new_session,
+ signature_algorithm)) {
goto err;
}
EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new(hs->peer_pubkey, NULL);
sig_ok = pctx != NULL &&
EVP_PKEY_verify_init(pctx) &&
- EVP_PKEY_CTX_set_signature_md(pctx, md) &&
EVP_PKEY_verify(pctx, CBS_data(&signature), CBS_len(&signature),
digest, digest_len);
EVP_PKEY_CTX_free(pctx);
} else {
sig_ok = ssl_public_key_verify(
ssl, CBS_data(&signature), CBS_len(&signature), signature_algorithm,
- hs->peer_pubkey, (const uint8_t *)ssl->s3->handshake_buffer->data,
- ssl->s3->handshake_buffer->length);
+ hs->peer_pubkey, (const uint8_t *)hs->transcript.buffer->data,
+ hs->transcript.buffer->length);
}
#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
@@ -1862,8 +1879,8 @@ static int ssl3_get_cert_verify(SSL_HANDSHAKE *hs) {
/* The handshake buffer is no longer necessary, and we may hash the current
* message.*/
- ssl3_free_handshake_buffer(ssl);
- if (!ssl_hash_current_message(ssl)) {
+ SSL_TRANSCRIPT_free_buffer(&hs->transcript);
+ if (!ssl_hash_current_message(hs)) {
goto err;
}
@@ -1885,7 +1902,7 @@ static int ssl3_get_next_proto(SSL_HANDSHAKE *hs) {
}
if (!ssl_check_message_type(ssl, SSL3_MT_NEXT_PROTO) ||
- !ssl_hash_current_message(ssl)) {
+ !ssl_hash_current_message(hs)) {
return -1;
}
@@ -1916,8 +1933,8 @@ static int ssl3_get_channel_id(SSL_HANDSHAKE *hs) {
}
if (!ssl_check_message_type(ssl, SSL3_MT_CHANNEL_ID) ||
- !tls1_verify_channel_id(ssl) ||
- !ssl_hash_current_message(ssl)) {
+ !tls1_verify_channel_id(hs) ||
+ !ssl_hash_current_message(hs)) {
return -1;
}
return 1;
diff --git a/src/ssl/internal.h b/src/ssl/internal.h
index a90294e2..5b93f475 100644
--- a/src/ssl/internal.h
+++ b/src/ssl/internal.h
@@ -220,10 +220,9 @@ int ssl_cipher_get_evp_aead(const EVP_AEAD **out_aead,
const SSL_CIPHER *cipher, uint16_t version);
/* ssl_get_handshake_digest returns the |EVP_MD| corresponding to
- * |algorithm_prf|. It returns SHA-1 for |SSL_HANDSHAKE_DEFAULT|. The caller is
- * responsible for maintaining the additional MD5 digest and switching to
- * SHA-256 in TLS 1.2. */
-const EVP_MD *ssl_get_handshake_digest(uint32_t algorithm_prf);
+ * |algorithm_prf| and the |version|. */
+const EVP_MD *ssl_get_handshake_digest(uint32_t algorithm_prf,
+ uint16_t version);
/* ssl_create_cipher_list evaluates |rule_str| according to the ciphers in
* |ssl_method|. It sets |*out_cipher_list| to a newly-allocated
@@ -260,6 +259,87 @@ int ssl_cipher_requires_server_key_exchange(const SSL_CIPHER *cipher);
size_t ssl_cipher_get_record_split_len(const SSL_CIPHER *cipher);
+/* Transcript layer. */
+
+/* SSL_TRANSCRIPT maintains the handshake transcript as a combination of a
+ * buffer and running hash. */
+typedef struct ssl_transcript_st {
+ /* buffer, if non-NULL, contains the handshake transcript. */
+ BUF_MEM *buffer;
+ /* hash, if initialized with an |EVP_MD|, maintains the handshake hash. For
+ * TLS 1.1 and below, it is the SHA-1 half. */
+ EVP_MD_CTX hash;
+ /* md5, if initialized with an |EVP_MD|, maintains the MD5 half of the
+ * handshake hash for TLS 1.1 and below. */
+ EVP_MD_CTX md5;
+} SSL_TRANSCRIPT;
+
+/* SSL_TRANSCRIPT_init initializes the handshake transcript. If called on an
+ * existing transcript, it resets the transcript and hash. It returns one on
+ * success and zero on failure. */
+int SSL_TRANSCRIPT_init(SSL_TRANSCRIPT *transcript);
+
+/* SSL_TRANSCRIPT_init_hash initializes the handshake hash based on the PRF and
+ * contents of the handshake transcript. Subsequent calls to
+ * |SSL_TRANSCRIPT_update| will update the rolling hash. It returns one on
+ * success and zero on failure. It is an error to call this function after the
+ * handshake buffer is released. */
+int SSL_TRANSCRIPT_init_hash(SSL_TRANSCRIPT *transcript, uint16_t version,
+ int algorithm_prf);
+
+/* SSL_TRANSCRIPT_cleanup cleans up the hash and transcript. */
+void SSL_TRANSCRIPT_cleanup(SSL_TRANSCRIPT *transcript);
+
+/* SSL_TRANSCRIPT_free_buffer releases the handshake buffer. Subsequent calls to
+ * |SSL_TRANSCRIPT_update| will not update the handshake buffer. */
+void SSL_TRANSCRIPT_free_buffer(SSL_TRANSCRIPT *transcript);
+
+/* SSL_TRANSCRIPT_digest_len returns the length of the PRF hash. */
+size_t SSL_TRANSCRIPT_digest_len(const SSL_TRANSCRIPT *transcript);
+
+/* SSL_TRANSCRIPT_md returns the PRF hash. For TLS 1.1 and below, this is
+ * |EVP_md5_sha1|. */
+const EVP_MD *SSL_TRANSCRIPT_md(const SSL_TRANSCRIPT *transcript);
+
+/* SSL_TRANSCRIPT_update adds |in| to the handshake buffer and handshake hash,
+ * whichever is enabled. It returns one on success and zero on failure. */
+int SSL_TRANSCRIPT_update(SSL_TRANSCRIPT *transcript, const uint8_t *in,
+ size_t in_len);
+
+/* SSL_TRANSCRIPT_get_hash writes the handshake hash to |out| which must have
+ * room for at least |SSL_TRANSCRIPT_digest_len| bytes. On success, it returns
+ * one and sets |*out_len| to the number of bytes written. Otherwise, it returns
+ * zero. */
+int SSL_TRANSCRIPT_get_hash(const SSL_TRANSCRIPT *transcript, uint8_t *out,
+ size_t *out_len);
+
+/* SSL_TRANSCRIPT_ssl3_cert_verify_hash writes the SSL 3.0 CertificateVerify
+ * hash into the bytes pointed to by |out| and writes the number of bytes to
+ * |*out_len|. |out| must have room for |EVP_MAX_MD_SIZE| bytes. It returns one
+ * on success and zero on failure. */
+int SSL_TRANSCRIPT_ssl3_cert_verify_hash(SSL_TRANSCRIPT *transcript,
+ uint8_t *out, size_t *out_len,
+ const SSL_SESSION *session,
+ int signature_algorithm);
+
+/* SSL_TRANSCRIPT_finish_mac computes the MAC for the Finished message into the
+ * bytes pointed by |out| and writes the number of bytes to |*out_len|. |out|
+ * must have room for |EVP_MAX_MD_SIZE| bytes. It returns one on success and
+ * zero on failure. */
+int SSL_TRANSCRIPT_finish_mac(SSL_TRANSCRIPT *transcript, uint8_t *out,
+ size_t *out_len, const SSL_SESSION *session,
+ int from_server, uint16_t version);
+
+/* tls1_prf computes the PRF function for |ssl|. It writes |out_len| bytes to
+ * |out|, using |secret| as the secret and |label| as the label. |seed1| and
+ * |seed2| are concatenated to form the seed parameter. It returns one on
+ * success and zero on failure. */
+int tls1_prf(const EVP_MD *digest, uint8_t *out, size_t out_len,
+ const uint8_t *secret, size_t secret_len, const char *label,
+ size_t label_len, const uint8_t *seed1, size_t seed1_len,
+ const uint8_t *seed2, size_t seed2_len);
+
+
/* Encryption layer. */
/* SSL_AEAD_CTX contains information about an AEAD that is being used to encrypt
@@ -525,35 +605,6 @@ int custom_ext_parse_clienthello(SSL_HANDSHAKE *hs, int *out_alert,
int custom_ext_add_serverhello(SSL_HANDSHAKE *hs, CBB *extensions);
-/* Handshake hash.
- *
- * The TLS handshake maintains a transcript of all handshake messages. At
- * various points in the protocol, this is either a handshake buffer, a rolling
- * hash (selected by cipher suite) or both. */
-
-/* ssl3_init_handshake_buffer initializes the handshake buffer and resets the
- * handshake hash. It returns one success and zero on failure. */
-int ssl3_init_handshake_buffer(SSL *ssl);
-
-/* ssl3_init_handshake_hash initializes the handshake hash based on the pending
- * cipher and the contents of the handshake buffer. Subsequent calls to
- * |ssl3_update_handshake_hash| will update the rolling hash. It returns one on
- * success and zero on failure. It is an error to call this function after the
- * handshake buffer is released. */
-int ssl3_init_handshake_hash(SSL *ssl);
-
-/* ssl3_free_handshake_buffer releases the handshake buffer. Subsequent calls
- * to |ssl3_update_handshake_hash| will not update the handshake buffer. */
-void ssl3_free_handshake_buffer(SSL *ssl);
-
-/* ssl3_free_handshake_hash releases the handshake hash. */
-void ssl3_free_handshake_hash(SSL *ssl);
-
-/* ssl3_update_handshake_hash adds |in| to the handshake buffer and handshake
- * hash, whichever is enabled. It returns one on success and zero on failure. */
-int ssl3_update_handshake_hash(SSL *ssl, const uint8_t *in, size_t in_len);
-
-
/* ECDH groups. */
typedef struct ssl_ecdh_ctx_st SSL_ECDH_CTX;
@@ -753,12 +804,6 @@ void ssl_write_buffer_clear(SSL *ssl);
* configured and zero otherwise. */
int ssl_has_certificate(const SSL *ssl);
-/* ssl_session_x509_cache_objects fills out |sess->x509_peer| and
- * |sess->x509_chain| from |sess->certs| and erases
- * |sess->x509_chain_without_leaf|. It returns one on success or zero on
- * error. */
-int ssl_session_x509_cache_objects(SSL_SESSION *sess);
-
/* ssl_parse_cert_chain parses a certificate list from |cbs| in the format used
* by a TLS Certificate message. On success, it returns a newly-allocated
* |CRYPTO_BUFFER| list and advances |cbs|. Otherwise, it returns NULL and sets
@@ -827,12 +872,6 @@ int tls13_init_key_schedule(SSL_HANDSHAKE *hs);
int tls13_advance_key_schedule(SSL_HANDSHAKE *hs, const uint8_t *in,
size_t len);
-/* tls13_get_context_hash writes Hash(Handshake Context) to |out| which must
- * have room for at least |EVP_MAX_MD_SIZE| bytes. On success, it returns one
- * and sets |*out_len| to the number of bytes written. Otherwise, it returns
- * zero. */
-int tls13_get_context_hash(SSL *ssl, uint8_t *out, size_t *out_len);
-
/* tls13_set_traffic_key sets the read or write traffic keys to
* |traffic_secret|. It returns one on success and zero on error. */
int tls13_set_traffic_key(SSL *ssl, enum evp_aead_direction_t direction,
@@ -872,12 +911,13 @@ int tls13_finished_mac(SSL_HANDSHAKE *hs, uint8_t *out,
/* tls13_write_psk_binder calculates the PSK binder value and replaces the last
* bytes of |msg| with the resulting value. It returns 1 on success, and 0 on
* failure. */
-int tls13_write_psk_binder(SSL *ssl, uint8_t *msg, size_t len);
+int tls13_write_psk_binder(SSL_HANDSHAKE *hs, uint8_t *msg, size_t len);
/* tls13_verify_psk_binder verifies that the handshake transcript, truncated
* up to the binders has a valid signature using the value of |session|'s
* resumption secret. It returns 1 on success, and 0 on failure. */
-int tls13_verify_psk_binder(SSL *ssl, SSL_SESSION *session, CBS *binders);
+int tls13_verify_psk_binder(SSL_HANDSHAKE *hs, SSL_SESSION *session,
+ CBS *binders);
/* Handshake functions. */
@@ -951,6 +991,9 @@ struct ssl_handshake_st {
/* ecdh_ctx is the current ECDH instance. */
SSL_ECDH_CTX ecdh_ctx;
+ /* transcript is the current handshake transcript. */
+ SSL_TRANSCRIPT transcript;
+
/* cookie is the value of the cookie received from the server, if any. */
uint8_t *cookie;
size_t cookie_len;
@@ -1132,7 +1175,7 @@ enum ssl_cert_verify_context_t {
* containing the result. The caller must free it with |OPENSSL_free| to release
* it. This function returns one on success and zero on failure. */
int tls13_get_cert_verify_signature_input(
- SSL *ssl, uint8_t **out, size_t *out_len,
+ SSL_HANDSHAKE *hs, uint8_t **out, size_t *out_len,
enum ssl_cert_verify_context_t cert_verify_context);
/* ssl_negotiate_alpn negotiates the ALPN extension, if applicable. It returns
@@ -1256,6 +1299,10 @@ typedef struct cert_st {
* operations. */
const SSL_PRIVATE_KEY_METHOD *key_method;
+ /* x509_method contains pointers to functions that might deal with |X509|
+ * compatibility, or might be a no-op, depending on the application. */
+ const SSL_X509_METHOD *x509_method;
+
DH *dh_tmp;
DH *(*dh_tmp_cb)(SSL *ssl, int is_export, int keysize);
@@ -1287,6 +1334,9 @@ struct ssl_method_st {
/* method is the underlying SSL_PROTOCOL_METHOD that initializes the
* SSL_CTX. */
const SSL_PROTOCOL_METHOD *method;
+ /* x509_method contains pointers to functions that might deal with |X509|
+ * compatibility, or might be a no-op, depending on the application. */
+ const SSL_X509_METHOD *x509_method;
};
/* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */
@@ -1368,19 +1418,34 @@ struct ssl_protocol_method_st {
int (*set_write_state)(SSL *ssl, SSL_AEAD_CTX *aead_ctx);
};
-/* This is for the SSLv3/TLSv1.0 differences in crypto/hash stuff It is a bit
- * of a mess of functions, but hell, think of it as an opaque structure. */
-typedef struct ssl3_enc_method {
- /* prf computes the PRF function for |ssl|. It writes |out_len| bytes to
- * |out|, using |secret| as the secret and |label| as the label. |seed1| and
- * |seed2| are concatenated to form the seed parameter. It returns one on
- * success and zero on failure. */
- int (*prf)(const SSL *ssl, uint8_t *out, size_t out_len,
- const uint8_t *secret, size_t secret_len, const char *label,
- size_t label_len, const uint8_t *seed1, size_t seed1_len,
- const uint8_t *seed2, size_t seed2_len);
- int (*final_finish_mac)(SSL *ssl, int from_server, uint8_t *out);
-} SSL3_ENC_METHOD;
+struct ssl_x509_method_st {
+ /* cert_clear frees and NULLs all X509-related state. */
+ void (*cert_clear)(CERT *cert);
+ /* cert_flush_cached_chain drops any cached |X509|-based certificate chain
+ * from |cert|. */
+ void (*cert_flush_cached_chain)(CERT *cert);
+ /* cert_flush_cached_chain drops any cached |X509|-based leaf certificate
+ * from |cert|. */
+ void (*cert_flush_cached_leaf)(CERT *cert);
+
+ /* session_cache_objects fills out |sess->x509_peer| and |sess->x509_chain|
+ * from |sess->certs| and erases |sess->x509_chain_without_leaf|. It returns
+ * one on success or zero on error. */
+ int (*session_cache_objects)(SSL_SESSION *session);
+ /* session_dup duplicates any needed fields from |session| to |new_session|.
+ * It returns one on success or zero on error. */
+ int (*session_dup)(SSL_SESSION *new_session, const SSL_SESSION *session);
+ /* session_clear frees any X509-related state from |session|. */
+ void (*session_clear)(SSL_SESSION *session);
+};
+
+/* ssl_noop_x509_method is implements the |ssl_x509_method_st| functions by
+ * doing nothing. */
+extern const struct ssl_x509_method_st ssl_noop_x509_method;
+
+/* ssl_crypto_x509_method provides the |ssl_x509_method_st| functions using
+ * crypto/x509. */
+extern const struct ssl_x509_method_st ssl_crypto_x509_method;
typedef struct ssl3_record_st {
/* type is the record type. */
@@ -1431,15 +1496,6 @@ typedef struct ssl3_state_st {
int wpend_ret; /* number of bytes submitted */
const uint8_t *wpend_buf;
- /* handshake_buffer, if non-NULL, contains the handshake transcript. */
- BUF_MEM *handshake_buffer;
- /* handshake_hash, if initialized with an |EVP_MD|, maintains the handshake
- * hash. For TLS 1.1 and below, it is the SHA-1 half. */
- EVP_MD_CTX handshake_hash;
- /* handshake_md5, if initialized with an |EVP_MD|, maintains the MD5 half of
- * the handshake hash for TLS 1.1 and below. */
- EVP_MD_CTX handshake_md5;
-
/* recv_shutdown is the shutdown state for the receive half of the
* connection. */
enum ssl_shutdown_t recv_shutdown;
@@ -1516,10 +1572,6 @@ typedef struct ssl3_state_st {
/* aead_write_ctx is the current write cipher state. */
SSL_AEAD_CTX *aead_write_ctx;
- /* enc_method is the method table corresponding to the current protocol
- * version. */
- const SSL3_ENC_METHOD *enc_method;
-
/* hs is the handshake state for the current handshake or NULL if there isn't
* one. */
SSL_HANDSHAKE *hs;
@@ -1836,21 +1888,13 @@ struct ssl_st {
* session space. Only effective on the server side. */
unsigned retain_only_sha256_of_client_certs:1;
- /* session_timeout is the default lifetime in seconds of the session
- * created in this connection at TLS 1.2 and earlier. */
- long session_timeout;
-
- /* session_psk_dhe_timeout is the default lifetime in seconds of sessions
- * created in this connection at TLS 1.3. */
- long session_psk_dhe_timeout;
+ /* Signed certificate timestamp list to be sent to the client, if requested */
+ CRYPTO_BUFFER *signed_cert_timestamp_list;
/* OCSP response to be sent to the client, if requested. */
CRYPTO_BUFFER *ocsp_response;
};
-extern const SSL3_ENC_METHOD TLSv1_enc_data;
-extern const SSL3_ENC_METHOD SSLv3_enc_data;
-
/* From draft-ietf-tls-tls13-18, used in determining PSK modes. */
#define SSL_PSK_KE 0x0
#define SSL_PSK_DHE_KE 0x1
@@ -1860,13 +1904,12 @@ extern const SSL3_ENC_METHOD SSLv3_enc_data;
#define SSL_KEY_UPDATE_NOT_REQUESTED 0
#define SSL_KEY_UPDATE_REQUESTED 1
-CERT *ssl_cert_new(void);
+CERT *ssl_cert_new(const SSL_X509_METHOD *x509_method);
CERT *ssl_cert_dup(CERT *cert);
void ssl_cert_clear_certs(CERT *c);
void ssl_cert_free(CERT *c);
-CRYPTO_BUFFER *x509_to_buffer(X509 *x509);
-void ssl_cert_flush_cached_x509_leaf(CERT *cert);
-int ssl_cert_cache_leaf_cert(CERT *cert);
+int ssl_set_cert(CERT *cert, CRYPTO_BUFFER *buffer);
+int ssl_is_key_type_supported(int key_type);
/* ssl_compare_public_and_private_key returns one if |pubkey| is the public
* counterpart to |privkey|. Otherwise it returns zero and pushes a helpful
* message on the error queue. */
@@ -1876,6 +1919,15 @@ int ssl_cert_check_private_key(const CERT *cert, const EVP_PKEY *privkey);
int ssl_get_new_session(SSL_HANDSHAKE *hs, int is_server);
int ssl_encrypt_ticket(SSL *ssl, CBB *out, const SSL_SESSION *session);
+/* ssl_session_new returns a newly-allocated blank |SSL_SESSION| or NULL on
+ * error. */
+SSL_SESSION *ssl_session_new(const SSL_X509_METHOD *x509_method);
+
+/* SSL_SESSION_parse parses an |SSL_SESSION| from |cbs| and advances |cbs| over
+ * the parsed data. */
+SSL_SESSION *SSL_SESSION_parse(CBS *cbs, const SSL_X509_METHOD *x509_method,
+ CRYPTO_BUFFER_POOL *pool);
+
/* ssl_session_is_context_valid returns one if |session|'s session ID context
* matches the one set on |ssl| and zero otherwise. */
int ssl_session_is_context_valid(const SSL *ssl, const SSL_SESSION *session);
@@ -1888,6 +1940,11 @@ int ssl_session_is_time_valid(const SSL *ssl, const SSL_SESSION *session);
* zero otherwise. */
int ssl_session_is_resumable(const SSL *ssl, const SSL_SESSION *session);
+/* SSL_SESSION_get_digest returns the digest used in |session|. If the digest is
+ * invalid, it returns NULL. */
+const EVP_MD *SSL_SESSION_get_digest(const SSL_SESSION *session,
+ const SSL *ssl);
+
void ssl_set_session(SSL *ssl, SSL_SESSION *session);
enum ssl_session_result_t {
@@ -1936,7 +1993,7 @@ const struct ssl_cipher_preference_list_st *ssl_get_cipher_preferences(
const SSL *ssl);
int ssl_verify_cert_chain(SSL *ssl, long *out_verify_result,
- STACK_OF(X509) * cert_chain);
+ STACK_OF(X509) *cert_chain);
void ssl_update_cache(SSL_HANDSHAKE *hs, int mode);
int ssl_verify_alarm_type(long type);
@@ -1947,13 +2004,6 @@ int ssl3_get_message(SSL *ssl);
void ssl3_get_current_message(const SSL *ssl, CBS *out);
void ssl3_release_current_message(SSL *ssl, int free_buffer);
-/* ssl3_cert_verify_hash writes the SSL 3.0 CertificateVerify hash into the
- * bytes pointed to by |out| and writes the number of bytes to |*out_len|. |out|
- * must have room for |EVP_MAX_MD_SIZE| bytes. It sets |*out_md| to the hash
- * function used. It returns one on success and zero on failure. */
-int ssl3_cert_verify_hash(SSL *ssl, const EVP_MD **out_md, uint8_t *out,
- size_t *out_len, uint16_t signature_algorithm);
-
int ssl3_send_finished(SSL_HANDSHAKE *hs);
int ssl3_dispatch_alert(SSL *ssl);
int ssl3_read_app_data(SSL *ssl, int *out_got_handshake, uint8_t *buf, int len,
@@ -1990,7 +2040,7 @@ int ssl_add_message_cbb(SSL *ssl, CBB *cbb);
/* ssl_hash_current_message incorporates the current handshake message into the
* handshake hash. It returns one on success and zero on allocation failure. */
-int ssl_hash_current_message(SSL *ssl);
+int ssl_hash_current_message(SSL_HANDSHAKE *hs);
/* dtls1_get_record reads a new input record. On success, it places it in
* |ssl->s3->rrec| and returns one. Otherwise it returns <= 0 on error or if
@@ -2034,9 +2084,8 @@ void dtls1_release_current_message(SSL *ssl, int free_buffer);
int dtls1_dispatch_alert(SSL *ssl);
int tls1_change_cipher_state(SSL_HANDSHAKE *hs, int which);
-int tls1_handshake_digest(SSL *ssl, uint8_t *out, size_t out_len);
-int tls1_generate_master_secret(SSL *ssl, uint8_t *out, const uint8_t *premaster,
- size_t premaster_len);
+int tls1_generate_master_secret(SSL_HANDSHAKE *hs, uint8_t *out,
+ const uint8_t *premaster, size_t premaster_len);
/* tls1_get_grouplist sets |*out_group_ids| and |*out_group_ids_len| to the
* locally-configured group preference list. */
@@ -2092,19 +2141,19 @@ int tls_process_ticket(SSL *ssl, SSL_SESSION **out_session,
/* tls1_verify_channel_id processes the current message as a Channel ID message,
* and verifies the signature. If the key is valid, it saves the Channel ID and
* returns one. Otherwise, it returns zero. */
-int tls1_verify_channel_id(SSL *ssl);
+int tls1_verify_channel_id(SSL_HANDSHAKE *hs);
/* tls1_write_channel_id generates a Channel ID message and puts the output in
* |cbb|. |ssl->tlsext_channel_id_private| must already be set before calling.
* This function returns one on success and zero on error. */
-int tls1_write_channel_id(SSL *ssl, CBB *cbb);
+int tls1_write_channel_id(SSL_HANDSHAKE *hs, CBB *cbb);
/* tls1_channel_id_hash computes the hash to be signed by Channel ID and writes
* it to |out|, which must contain at least |EVP_MAX_MD_SIZE| bytes. It returns
* one on success and zero on failure. */
-int tls1_channel_id_hash(SSL *ssl, uint8_t *out, size_t *out_len);
+int tls1_channel_id_hash(SSL_HANDSHAKE *hs, uint8_t *out, size_t *out_len);
-int tls1_record_handshake_hashes_for_channel_id(SSL *ssl);
+int tls1_record_handshake_hashes_for_channel_id(SSL_HANDSHAKE *hs);
/* ssl_do_channel_id_callback checks runs |ssl->ctx->channel_id_cb| if
* necessary. It returns one on success and zero on fatal error. Note that, on
@@ -2116,10 +2165,6 @@ int ssl_do_channel_id_callback(SSL *ssl);
* otherwise. */
int ssl3_can_false_start(const SSL *ssl);
-/* ssl3_get_enc_method returns the SSL3_ENC_METHOD corresponding to
- * |version|. */
-const SSL3_ENC_METHOD *ssl3_get_enc_method(uint16_t version);
-
/* ssl_get_version_range sets |*out_min_version| and |*out_max_version| to the
* minimum and maximum enabled protocol versions, respectively. */
int ssl_get_version_range(const SSL *ssl, uint16_t *out_min_version,
@@ -2129,8 +2174,6 @@ int ssl_get_version_range(const SSL *ssl, uint16_t *out_min_version,
* call this function before the version is determined. */
uint16_t ssl3_protocol_version(const SSL *ssl);
-uint32_t ssl_get_algorithm_prf(const SSL *ssl);
-
void ssl_get_current_time(const SSL *ssl, struct timeval *out_clock);
/* ssl_reset_error_state resets state for |SSL_get_error|. */
diff --git a/src/ssl/s3_both.c b/src/ssl/s3_both.c
index 8d2657fa..d3f9421b 100644
--- a/src/ssl/s3_both.c
+++ b/src/ssl/s3_both.c
@@ -141,6 +141,10 @@ SSL_HANDSHAKE *ssl_handshake_new(SSL *ssl) {
hs->ssl = ssl;
hs->wait = ssl_hs_ok;
hs->state = SSL_ST_INIT;
+ if (!SSL_TRANSCRIPT_init(&hs->transcript)) {
+ ssl_handshake_free(hs);
+ return NULL;
+ }
return hs;
}
@@ -159,6 +163,7 @@ void ssl_handshake_free(SSL_HANDSHAKE *hs) {
OPENSSL_cleanse(hs->server_traffic_secret_0,
sizeof(hs->server_traffic_secret_0));
SSL_ECDH_CTX_cleanup(&hs->ecdh_ctx);
+ SSL_TRANSCRIPT_cleanup(&hs->transcript);
OPENSSL_free(hs->cookie);
OPENSSL_free(hs->key_share_bytes);
OPENSSL_free(hs->public_key);
@@ -264,7 +269,12 @@ int ssl3_add_message(SSL *ssl, uint8_t *msg, size_t len) {
} while (added < len);
ssl_do_msg_callback(ssl, 1 /* write */, SSL3_RT_HANDSHAKE, msg, len);
- ssl3_update_handshake_hash(ssl, msg, len);
+ /* TODO(svaldez): Move this up a layer to fix abstraction for SSL_TRANSCRIPT
+ * on hs. */
+ if (ssl->s3->hs != NULL &&
+ !SSL_TRANSCRIPT_update(&ssl->s3->hs->transcript, msg, len)) {
+ goto err;
+ }
ret = 1;
err:
@@ -353,17 +363,20 @@ int ssl3_flush_flight(SSL *ssl) {
int ssl3_send_finished(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
+ const SSL_SESSION *session = SSL_get_session(ssl);
+
uint8_t finished[EVP_MAX_MD_SIZE];
- size_t finished_len =
- ssl->s3->enc_method->final_finish_mac(ssl, ssl->server, finished);
- if (finished_len == 0) {
+ size_t finished_len;
+ if (!SSL_TRANSCRIPT_finish_mac(&hs->transcript, finished, &finished_len,
+ session, ssl->server,
+ ssl3_protocol_version(ssl))) {
return 0;
}
/* Log the master secret, if logging is enabled. */
if (!ssl_log_secret(ssl, "CLIENT_RANDOM",
- SSL_get_session(ssl)->master_key,
- SSL_get_session(ssl)->master_key_length)) {
+ session->master_key,
+ session->master_key_length)) {
return 0;
}
@@ -409,10 +422,11 @@ int ssl3_get_finished(SSL_HANDSHAKE *hs) {
/* Snapshot the finished hash before incorporating the new message. */
uint8_t finished[EVP_MAX_MD_SIZE];
- size_t finished_len =
- ssl->s3->enc_method->final_finish_mac(ssl, !ssl->server, finished);
- if (finished_len == 0 ||
- !ssl_hash_current_message(ssl)) {
+ size_t finished_len;
+ if (!SSL_TRANSCRIPT_finish_mac(&hs->transcript, finished, &finished_len,
+ SSL_get_session(ssl), !ssl->server,
+ ssl3_protocol_version(ssl)) ||
+ !ssl_hash_current_message(hs)) {
return -1;
}
@@ -482,7 +496,7 @@ size_t ssl_max_handshake_message_len(const SSL *ssl) {
if (ssl->server) {
/* The largest acceptable post-handshake message for a server is a
* KeyUpdate. We will never initiate post-handshake auth. */
- return 0;
+ return 1;
}
/* Clients must accept NewSessionTicket and CertificateRequest, so allow the
@@ -561,9 +575,11 @@ static int read_v2_client_hello(SSL *ssl) {
CBS_init(&v2_client_hello, ssl_read_buffer(ssl) + 2, msg_length);
/* The V2ClientHello without the length is incorporated into the handshake
- * hash. */
- if (!ssl3_update_handshake_hash(ssl, CBS_data(&v2_client_hello),
- CBS_len(&v2_client_hello))) {
+ * hash. This is only ever called at the start of the handshake, so hs is
+ * guaranteed to be non-NULL. */
+ if (!SSL_TRANSCRIPT_update(&ssl->s3->hs->transcript,
+ CBS_data(&v2_client_hello),
+ CBS_len(&v2_client_hello))) {
return -1;
}
@@ -734,15 +750,15 @@ void ssl3_get_current_message(const SSL *ssl, CBS *out) {
CBS_init(out, (uint8_t *)ssl->init_buf->data, ssl->init_buf->length);
}
-int ssl_hash_current_message(SSL *ssl) {
+int ssl_hash_current_message(SSL_HANDSHAKE *hs) {
/* V2ClientHellos are hashed implicitly. */
- if (ssl->s3->is_v2_hello) {
+ if (hs->ssl->s3->is_v2_hello) {
return 1;
}
CBS cbs;
- ssl->method->get_current_message(ssl, &cbs);
- return ssl3_update_handshake_hash(ssl, CBS_data(&cbs), CBS_len(&cbs));
+ hs->ssl->method->get_current_message(hs->ssl, &cbs);
+ return SSL_TRANSCRIPT_update(&hs->transcript, CBS_data(&cbs), CBS_len(&cbs));
}
void ssl3_release_current_message(SSL *ssl, int free_buffer) {
diff --git a/src/ssl/s3_lib.c b/src/ssl/s3_lib.c
index 3f44629c..1c723cd2 100644
--- a/src/ssl/s3_lib.c
+++ b/src/ssl/s3_lib.c
@@ -178,9 +178,6 @@ int ssl3_new(SSL *ssl) {
return 0;
}
- EVP_MD_CTX_init(&s3->handshake_hash);
- EVP_MD_CTX_init(&s3->handshake_md5);
-
ssl->s3 = s3;
/* Set the version to the highest supported version.
@@ -202,8 +199,6 @@ void ssl3_free(SSL *ssl) {
SSL_SESSION_free(ssl->s3->new_session);
SSL_SESSION_free(ssl->s3->established_session);
- ssl3_free_handshake_buffer(ssl);
- ssl3_free_handshake_hash(ssl);
ssl_handshake_free(ssl->s3->hs);
OPENSSL_free(ssl->s3->next_proto_negotiated);
OPENSSL_free(ssl->s3->alpn_selected);
@@ -224,14 +219,3 @@ const struct ssl_cipher_preference_list_st *ssl_get_cipher_preferences(
return ssl->ctx->cipher_list;
}
-
-/* If we are using default SHA1+MD5 algorithms switch to new SHA256 PRF and
- * handshake macs if required. */
-uint32_t ssl_get_algorithm_prf(const SSL *ssl) {
- uint32_t algorithm_prf = ssl->s3->tmp.new_cipher->algorithm_prf;
- if (algorithm_prf == SSL_HANDSHAKE_MAC_DEFAULT &&
- ssl3_protocol_version(ssl) >= TLS1_2_VERSION) {
- return SSL_HANDSHAKE_MAC_SHA256;
- }
- return algorithm_prf;
-}
diff --git a/src/ssl/s3_pkt.c b/src/ssl/s3_pkt.c
index 5d5b7e83..2f919cae 100644
--- a/src/ssl/s3_pkt.c
+++ b/src/ssl/s3_pkt.c
@@ -140,7 +140,7 @@ again:
}
CBS body;
- uint8_t type, alert;
+ uint8_t type, alert = SSL_AD_DECODE_ERROR;
size_t consumed;
enum ssl_open_record_t open_ret =
tls_open_record(ssl, &type, &body, &consumed, &alert,
diff --git a/src/ssl/ssl_asn1.c b/src/ssl/ssl_asn1.c
index 4c1ee89a..3582864e 100644
--- a/src/ssl/ssl_asn1.c
+++ b/src/ssl/ssl_asn1.c
@@ -575,8 +575,9 @@ static int SSL_SESSION_parse_u16(CBS *cbs, uint16_t *out, unsigned tag,
return 1;
}
-static SSL_SESSION *SSL_SESSION_parse(CBS *cbs) {
- SSL_SESSION *ret = SSL_SESSION_new();
+SSL_SESSION *SSL_SESSION_parse(CBS *cbs, const SSL_X509_METHOD *x509_method,
+ CRYPTO_BUFFER_POOL *pool) {
+ SSL_SESSION *ret = ssl_session_new(x509_method);
if (ret == NULL) {
goto err;
}
@@ -738,7 +739,7 @@ static SSL_SESSION *SSL_SESSION_parse(CBS *cbs) {
if (has_peer) {
/* TODO(agl): this should use the |SSL_CTX|'s pool. */
- CRYPTO_BUFFER *buffer = CRYPTO_BUFFER_new_from_CBS(&peer, NULL);
+ CRYPTO_BUFFER *buffer = CRYPTO_BUFFER_new_from_CBS(&peer, pool);
if (buffer == NULL ||
!sk_CRYPTO_BUFFER_push(ret->certs, buffer)) {
CRYPTO_BUFFER_free(buffer);
@@ -756,7 +757,7 @@ static SSL_SESSION *SSL_SESSION_parse(CBS *cbs) {
}
/* TODO(agl): this should use the |SSL_CTX|'s pool. */
- CRYPTO_BUFFER *buffer = CRYPTO_BUFFER_new_from_CBS(&cert, NULL);
+ CRYPTO_BUFFER *buffer = CRYPTO_BUFFER_new_from_CBS(&cert, pool);
if (buffer == NULL ||
!sk_CRYPTO_BUFFER_push(ret->certs, buffer)) {
CRYPTO_BUFFER_free(buffer);
@@ -766,7 +767,7 @@ static SSL_SESSION *SSL_SESSION_parse(CBS *cbs) {
}
}
- if (!ssl_session_x509_cache_objects(ret)) {
+ if (!x509_method->session_cache_objects(ret)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
goto err;
}
@@ -811,10 +812,11 @@ err:
return NULL;
}
-SSL_SESSION *SSL_SESSION_from_bytes(const uint8_t *in, size_t in_len) {
+SSL_SESSION *SSL_SESSION_from_bytes(const uint8_t *in, size_t in_len,
+ const SSL_CTX *ctx) {
CBS cbs;
CBS_init(&cbs, in, in_len);
- SSL_SESSION *ret = SSL_SESSION_parse(&cbs);
+ SSL_SESSION *ret = SSL_SESSION_parse(&cbs, ctx->x509_method, ctx->pool);
if (ret == NULL) {
return NULL;
}
@@ -825,25 +827,3 @@ SSL_SESSION *SSL_SESSION_from_bytes(const uint8_t *in, size_t in_len) {
}
return ret;
}
-
-SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a, const uint8_t **pp, long length) {
- if (length < 0) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
- return NULL;
- }
-
- CBS cbs;
- CBS_init(&cbs, *pp, length);
-
- SSL_SESSION *ret = SSL_SESSION_parse(&cbs);
- if (ret == NULL) {
- return NULL;
- }
-
- if (a) {
- SSL_SESSION_free(*a);
- *a = ret;
- }
- *pp = CBS_data(&cbs);
- return ret;
-}
diff --git a/src/ssl/ssl_cert.c b/src/ssl/ssl_cert.c
index 64526201..4177a482 100644
--- a/src/ssl/ssl_cert.c
+++ b/src/ssl/ssl_cert.c
@@ -141,13 +141,14 @@ int SSL_get_ex_data_X509_STORE_CTX_idx(void) {
return 0;
}
-CERT *ssl_cert_new(void) {
+CERT *ssl_cert_new(const SSL_X509_METHOD *x509_method) {
CERT *ret = OPENSSL_malloc(sizeof(CERT));
if (ret == NULL) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
return NULL;
}
OPENSSL_memset(ret, 0, sizeof(CERT));
+ ret->x509_method = x509_method;
return ret;
}
@@ -174,6 +175,7 @@ CERT *ssl_cert_dup(CERT *cert) {
}
ret->key_method = cert->key_method;
+ ret->x509_method = cert->x509_method;
if (cert->dh_tmp != NULL) {
ret->dh_tmp = DHparams_dup(cert->dh_tmp);
@@ -208,27 +210,13 @@ err:
return NULL;
}
-void ssl_cert_flush_cached_x509_leaf(CERT *cert) {
- X509_free(cert->x509_leaf);
- cert->x509_leaf = NULL;
-}
-
-static void ssl_cert_flush_cached_x509_chain(CERT *cert) {
- sk_X509_pop_free(cert->x509_chain, X509_free);
- cert->x509_chain = NULL;
-}
-
/* Free up and clear all certificates and chains */
void ssl_cert_clear_certs(CERT *cert) {
if (cert == NULL) {
return;
}
- ssl_cert_flush_cached_x509_leaf(cert);
- ssl_cert_flush_cached_x509_chain(cert);
-
- X509_free(cert->x509_stash);
- cert->x509_stash = NULL;
+ cert->x509_method->cert_clear(cert);
sk_CRYPTO_BUFFER_pop_free(cert->chain, CRYPTO_BUFFER_free);
cert->chain = NULL;
@@ -251,155 +239,97 @@ void ssl_cert_free(CERT *c) {
OPENSSL_free(c);
}
-/* new_leafless_chain returns a fresh stack of buffers set to {NULL}. */
-static STACK_OF(CRYPTO_BUFFER) *new_leafless_chain(void) {
- STACK_OF(CRYPTO_BUFFER) *chain = sk_CRYPTO_BUFFER_new_null();
- if (chain == NULL) {
- return NULL;
- }
-
- if (!sk_CRYPTO_BUFFER_push(chain, NULL)) {
- sk_CRYPTO_BUFFER_free(chain);
- return NULL;
- }
-
- return chain;
+static void ssl_cert_set_cert_cb(CERT *c, int (*cb)(SSL *ssl, void *arg),
+ void *arg) {
+ c->cert_cb = cb;
+ c->cert_cb_arg = arg;
}
-/* x509_to_buffer returns a |CRYPTO_BUFFER| that contains the serialised
- * contents of |x509|. */
-CRYPTO_BUFFER *x509_to_buffer(X509 *x509) {
- uint8_t *buf = NULL;
- int cert_len = i2d_X509(x509, &buf);
- if (cert_len <= 0) {
+int ssl_set_cert(CERT *cert, CRYPTO_BUFFER *buffer) {
+ CBS cert_cbs;
+ CRYPTO_BUFFER_init_CBS(buffer, &cert_cbs);
+ EVP_PKEY *pubkey = ssl_cert_parse_pubkey(&cert_cbs);
+ if (pubkey == NULL) {
return 0;
}
- CRYPTO_BUFFER *buffer = CRYPTO_BUFFER_new(buf, cert_len, NULL);
- OPENSSL_free(buf);
-
- return buffer;
-}
-
-/* ssl_cert_set_chain sets elements 1.. of |cert->chain| to the serialised
- * forms of elements of |chain|. It returns one on success or zero on error, in
- * which case no change to |cert->chain| is made. It preverses the existing
- * leaf from |cert->chain|, if any. */
-static int ssl_cert_set_chain(CERT *cert, STACK_OF(X509) *chain) {
- STACK_OF(CRYPTO_BUFFER) *new_chain = NULL;
-
- if (cert->chain != NULL) {
- new_chain = sk_CRYPTO_BUFFER_new_null();
- if (new_chain == NULL) {
- return 0;
- }
-
- CRYPTO_BUFFER *leaf = sk_CRYPTO_BUFFER_value(cert->chain, 0);
- if (!sk_CRYPTO_BUFFER_push(new_chain, leaf)) {
- goto err;
- }
- /* |leaf| might be NULL if it's a “leafless” chain. */
- if (leaf != NULL) {
- CRYPTO_BUFFER_up_ref(leaf);
- }
- }
-
- for (size_t i = 0; i < sk_X509_num(chain); i++) {
- if (new_chain == NULL) {
- new_chain = new_leafless_chain();
- if (new_chain == NULL) {
- goto err;
- }
- }
-
- CRYPTO_BUFFER *buffer = x509_to_buffer(sk_X509_value(chain, i));
- if (buffer == NULL ||
- !sk_CRYPTO_BUFFER_push(new_chain, buffer)) {
- CRYPTO_BUFFER_free(buffer);
- goto err;
- }
+ if (!ssl_is_key_type_supported(pubkey->type)) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_CERTIFICATE_TYPE);
+ EVP_PKEY_free(pubkey);
+ return 0;
}
- sk_CRYPTO_BUFFER_pop_free(cert->chain, CRYPTO_BUFFER_free);
- cert->chain = new_chain;
-
- return 1;
-
-err:
- sk_CRYPTO_BUFFER_pop_free(new_chain, CRYPTO_BUFFER_free);
- return 0;
-}
-
-static int ssl_cert_set0_chain(CERT *cert, STACK_OF(X509) *chain) {
- if (!ssl_cert_set_chain(cert, chain)) {
+ /* An ECC certificate may be usable for ECDH or ECDSA. We only support ECDSA
+ * certificates, so sanity-check the key usage extension. */
+ if (pubkey->type == EVP_PKEY_EC &&
+ !ssl_cert_check_digital_signature_key_usage(&cert_cbs)) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_CERTIFICATE_TYPE);
+ EVP_PKEY_free(pubkey);
return 0;
}
- sk_X509_pop_free(chain, X509_free);
- ssl_cert_flush_cached_x509_chain(cert);
- return 1;
-}
-
-static int ssl_cert_set1_chain(CERT *cert, STACK_OF(X509) *chain) {
- if (!ssl_cert_set_chain(cert, chain)) {
- return 0;
+ if (cert->privatekey != NULL) {
+ /* Sanity-check that the private key and the certificate match, unless the
+ * key is opaque (in case of, say, a smartcard). */
+ if (!EVP_PKEY_is_opaque(cert->privatekey) &&
+ !ssl_compare_public_and_private_key(pubkey, cert->privatekey)) {
+ /* don't fail for a cert/key mismatch, just free current private key
+ * (when switching to a different cert & key, first this function should
+ * be used, then ssl_set_pkey */
+ EVP_PKEY_free(cert->privatekey);
+ cert->privatekey = NULL;
+ /* clear error queue */
+ ERR_clear_error();
+ }
}
- ssl_cert_flush_cached_x509_chain(cert);
- return 1;
-}
+ EVP_PKEY_free(pubkey);
-static int ssl_cert_append_cert(CERT *cert, X509 *x509) {
- CRYPTO_BUFFER *buffer = x509_to_buffer(x509);
- if (buffer == NULL) {
- return 0;
- }
+ cert->x509_method->cert_flush_cached_leaf(cert);
if (cert->chain != NULL) {
- if (!sk_CRYPTO_BUFFER_push(cert->chain, buffer)) {
- CRYPTO_BUFFER_free(buffer);
- return 0;
- }
-
+ CRYPTO_BUFFER_free(sk_CRYPTO_BUFFER_value(cert->chain, 0));
+ sk_CRYPTO_BUFFER_set(cert->chain, 0, buffer);
+ CRYPTO_BUFFER_up_ref(buffer);
return 1;
}
- cert->chain = new_leafless_chain();
- if (cert->chain == NULL ||
- !sk_CRYPTO_BUFFER_push(cert->chain, buffer)) {
- CRYPTO_BUFFER_free(buffer);
+ cert->chain = sk_CRYPTO_BUFFER_new_null();
+ if (cert->chain == NULL) {
+ return 0;
+ }
+
+ if (!sk_CRYPTO_BUFFER_push(cert->chain, buffer)) {
sk_CRYPTO_BUFFER_free(cert->chain);
cert->chain = NULL;
return 0;
}
+ CRYPTO_BUFFER_up_ref(buffer);
return 1;
}
-static int ssl_cert_add0_chain_cert(CERT *cert, X509 *x509) {
- if (!ssl_cert_append_cert(cert, x509)) {
+int SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, size_t der_len,
+ const uint8_t *der) {
+ CRYPTO_BUFFER *buffer = CRYPTO_BUFFER_new(der, der_len, NULL);
+ if (buffer == NULL) {
return 0;
}
- X509_free(cert->x509_stash);
- cert->x509_stash = x509;
- ssl_cert_flush_cached_x509_chain(cert);
- return 1;
+ const int ok = ssl_set_cert(ctx->cert, buffer);
+ CRYPTO_BUFFER_free(buffer);
+ return ok;
}
-static int ssl_cert_add1_chain_cert(CERT *cert, X509 *x509) {
- if (!ssl_cert_append_cert(cert, x509)) {
+int SSL_use_certificate_ASN1(SSL *ssl, const uint8_t *der, size_t der_len) {
+ CRYPTO_BUFFER *buffer = CRYPTO_BUFFER_new(der, der_len, NULL);
+ if (buffer == NULL) {
return 0;
}
- ssl_cert_flush_cached_x509_chain(cert);
- return 1;
-}
-
-static void ssl_cert_set_cert_cb(CERT *c, int (*cb)(SSL *ssl, void *arg),
- void *arg) {
- c->cert_cb = cb;
- c->cert_cb_arg = arg;
+ const int ok = ssl_set_cert(ssl->cert, buffer);
+ CRYPTO_BUFFER_free(buffer);
+ return ok;
}
int ssl_verify_cert_chain(SSL *ssl, long *out_verify_result,
@@ -590,6 +520,7 @@ STACK_OF(CRYPTO_BUFFER) *ssl_parse_cert_chain(uint8_t *out_alert,
if (sk_CRYPTO_BUFFER_num(ret) == 0) {
*out_pubkey = ssl_cert_parse_pubkey(&certificate);
if (*out_pubkey == NULL) {
+ *out_alert = SSL_AD_DECODE_ERROR;
goto err;
}
@@ -652,49 +583,6 @@ err:
return 0;
}
-int ssl_auto_chain_if_needed(SSL *ssl) {
- /* Only build a chain if there are no intermediates configured and the feature
- * isn't disabled. */
- if ((ssl->mode & SSL_MODE_NO_AUTO_CHAIN) ||
- !ssl_has_certificate(ssl) ||
- ssl->cert->chain == NULL ||
- sk_CRYPTO_BUFFER_num(ssl->cert->chain) > 1) {
- return 1;
- }
-
- X509 *leaf =
- X509_parse_from_buffer(sk_CRYPTO_BUFFER_value(ssl->cert->chain, 0));
- if (!leaf) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_X509_LIB);
- return 0;
- }
-
- X509_STORE_CTX ctx;
- if (!X509_STORE_CTX_init(&ctx, ssl->ctx->cert_store, leaf, NULL)) {
- X509_free(leaf);
- OPENSSL_PUT_ERROR(SSL, ERR_R_X509_LIB);
- return 0;
- }
-
- /* Attempt to build a chain, ignoring the result. */
- X509_verify_cert(&ctx);
- X509_free(leaf);
- ERR_clear_error();
-
- /* Remove the leaf from the generated chain. */
- X509_free(sk_X509_shift(ctx.chain));
-
- const int ok = ssl_cert_set_chain(ssl->cert, ctx.chain);
- X509_STORE_CTX_cleanup(&ctx);
- if (!ok) {
- return 0;
- }
-
- ssl_cert_flush_cached_x509_chain(ssl->cert);
-
- return 1;
-}
-
/* ssl_cert_skip_to_spki parses a DER-encoded, X.509 certificate from |in| and
* positions |*out_tbs_cert| to cover the TBSCertificate, starting at the
* subjectPublicKeyInfo. */
@@ -986,54 +874,6 @@ int SSL_set1_verify_cert_store(SSL *ssl, X509_STORE *store) {
return set_cert_store(&ssl->cert->verify_store, store, 1);
}
-int SSL_CTX_set0_chain(SSL_CTX *ctx, STACK_OF(X509) *chain) {
- return ssl_cert_set0_chain(ctx->cert, chain);
-}
-
-int SSL_CTX_set1_chain(SSL_CTX *ctx, STACK_OF(X509) *chain) {
- return ssl_cert_set1_chain(ctx->cert, chain);
-}
-
-int SSL_set0_chain(SSL *ssl, STACK_OF(X509) *chain) {
- return ssl_cert_set0_chain(ssl->cert, chain);
-}
-
-int SSL_set1_chain(SSL *ssl, STACK_OF(X509) *chain) {
- return ssl_cert_set1_chain(ssl->cert, chain);
-}
-
-int SSL_CTX_add0_chain_cert(SSL_CTX *ctx, X509 *x509) {
- return ssl_cert_add0_chain_cert(ctx->cert, x509);
-}
-
-int SSL_CTX_add1_chain_cert(SSL_CTX *ctx, X509 *x509) {
- return ssl_cert_add1_chain_cert(ctx->cert, x509);
-}
-
-int SSL_CTX_add_extra_chain_cert(SSL_CTX *ctx, X509 *x509) {
- return SSL_CTX_add0_chain_cert(ctx, x509);
-}
-
-int SSL_add0_chain_cert(SSL *ssl, X509 *x509) {
- return ssl_cert_add0_chain_cert(ssl->cert, x509);
-}
-
-int SSL_add1_chain_cert(SSL *ssl, X509 *x509) {
- return ssl_cert_add1_chain_cert(ssl->cert, x509);
-}
-
-int SSL_CTX_clear_chain_certs(SSL_CTX *ctx) {
- return SSL_CTX_set0_chain(ctx, NULL);
-}
-
-int SSL_CTX_clear_extra_chain_certs(SSL_CTX *ctx) {
- return SSL_CTX_clear_chain_certs(ctx);
-}
-
-int SSL_clear_chain_certs(SSL *ssl) {
- return SSL_set0_chain(ssl, NULL);
-}
-
void SSL_CTX_set_cert_cb(SSL_CTX *ctx, int (*cb)(SSL *ssl, void *arg),
void *arg) {
ssl_cert_set_cert_cb(ctx->cert, cb, arg);
@@ -1043,80 +883,6 @@ void SSL_set_cert_cb(SSL *ssl, int (*cb)(SSL *ssl, void *arg), void *arg) {
ssl_cert_set_cert_cb(ssl->cert, cb, arg);
}
-/* ssl_cert_cache_leaf_cert sets |cert->x509_leaf|, if currently NULL, from the
- * first element of |cert->chain|. */
-int ssl_cert_cache_leaf_cert(CERT *cert) {
- if (cert->x509_leaf != NULL ||
- cert->chain == NULL) {
- return 1;
- }
-
- CRYPTO_BUFFER *leaf = sk_CRYPTO_BUFFER_value(cert->chain, 0);
- if (!leaf) {
- return 1;
- }
-
- cert->x509_leaf = X509_parse_from_buffer(leaf);
- return cert->x509_leaf != NULL;
-}
-
-/* ssl_cert_cache_chain_certs fills in |cert->x509_chain| from elements 1.. of
- * |cert->chain|. */
-static int ssl_cert_cache_chain_certs(CERT *cert) {
- if (cert->x509_chain != NULL ||
- cert->chain == NULL ||
- sk_CRYPTO_BUFFER_num(cert->chain) < 2) {
- return 1;
- }
-
- STACK_OF(X509) *chain = sk_X509_new_null();
- if (chain == NULL) {
- return 0;
- }
-
- for (size_t i = 1; i < sk_CRYPTO_BUFFER_num(cert->chain); i++) {
- CRYPTO_BUFFER *buffer = sk_CRYPTO_BUFFER_value(cert->chain, i);
- X509 *x509 = X509_parse_from_buffer(buffer);
- if (x509 == NULL ||
- !sk_X509_push(chain, x509)) {
- X509_free(x509);
- goto err;
- }
- }
-
- cert->x509_chain = chain;
- return 1;
-
-err:
- sk_X509_pop_free(chain, X509_free);
- return 0;
-}
-
-int SSL_CTX_get0_chain_certs(const SSL_CTX *ctx, STACK_OF(X509) **out_chain) {
- if (!ssl_cert_cache_chain_certs(ctx->cert)) {
- *out_chain = NULL;
- return 0;
- }
-
- *out_chain = ctx->cert->x509_chain;
- return 1;
-}
-
-int SSL_CTX_get_extra_chain_certs(const SSL_CTX *ctx,
- STACK_OF(X509) **out_chain) {
- return SSL_CTX_get0_chain_certs(ctx, out_chain);
-}
-
-int SSL_get0_chain_certs(const SSL *ssl, STACK_OF(X509) **out_chain) {
- if (!ssl_cert_cache_chain_certs(ssl->cert)) {
- *out_chain = NULL;
- return 0;
- }
-
- *out_chain = ssl->cert->x509_chain;
- return 1;
-}
-
int ssl_check_leaf_certificate(SSL *ssl, EVP_PKEY *pkey,
const CRYPTO_BUFFER *leaf) {
assert(ssl3_protocol_version(ssl) < TLS1_3_VERSION);
diff --git a/src/ssl/ssl_cipher.c b/src/ssl/ssl_cipher.c
index 480304ff..8f1ad734 100644
--- a/src/ssl/ssl_cipher.c
+++ b/src/ssl/ssl_cipher.c
@@ -787,10 +787,11 @@ int ssl_cipher_get_evp_aead(const EVP_AEAD **out_aead,
return 1;
}
-const EVP_MD *ssl_get_handshake_digest(uint32_t algorithm_prf) {
+const EVP_MD *ssl_get_handshake_digest(uint32_t algorithm_prf,
+ uint16_t version) {
switch (algorithm_prf) {
case SSL_HANDSHAKE_MAC_DEFAULT:
- return EVP_sha1();
+ return version >= TLS1_2_VERSION ? EVP_sha256() : EVP_md5_sha1();
case SSL_HANDSHAKE_MAC_SHA256:
return EVP_sha256();
case SSL_HANDSHAKE_MAC_SHA384:
diff --git a/src/ssl/ssl_file.c b/src/ssl/ssl_file.c
index e1ebaa69..59351a32 100644
--- a/src/ssl/ssl_file.c
+++ b/src/ssl/ssl_file.c
@@ -573,14 +573,3 @@ void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx, pem_password_cb *cb) {
void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX *ctx, void *data) {
ctx->default_passwd_callback_userdata = data;
}
-
-SSL_SESSION *d2i_SSL_SESSION_bio(BIO *bio, SSL_SESSION **out) {
- return ASN1_d2i_bio_of(SSL_SESSION, SSL_SESSION_new, d2i_SSL_SESSION, bio,
- out);
-}
-
-int i2d_SSL_SESSION_bio(BIO *bio, const SSL_SESSION *session) {
- return ASN1_i2d_bio_of(SSL_SESSION, i2d_SSL_SESSION, bio, session);
-}
-
-IMPLEMENT_PEM_rw(SSL_SESSION, SSL_SESSION, PEM_STRING_SSL_SESSION, SSL_SESSION)
diff --git a/src/ssl/ssl_lib.c b/src/ssl/ssl_lib.c
index 851c81f5..c946b77b 100644
--- a/src/ssl/ssl_lib.c
+++ b/src/ssl/ssl_lib.c
@@ -248,6 +248,7 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *method) {
OPENSSL_memset(ret, 0, sizeof(SSL_CTX));
ret->method = method->method;
+ ret->x509_method = method->x509_method;
CRYPTO_MUTEX_init(&ret->lock);
@@ -261,7 +262,7 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *method) {
ret->max_cert_list = SSL_MAX_CERT_LIST_DEFAULT;
ret->verify_mode = SSL_VERIFY_NONE;
- ret->cert = ssl_cert_new();
+ ret->cert = ssl_cert_new(method->x509_method);
if (ret->cert == NULL) {
goto err;
}
@@ -362,8 +363,8 @@ void SSL_CTX_free(SSL_CTX *ctx) {
OPENSSL_free(ctx->psk_identity_hint);
OPENSSL_free(ctx->supported_group_list);
OPENSSL_free(ctx->alpn_client_proto_list);
+ CRYPTO_BUFFER_free(ctx->signed_cert_timestamp_list);
CRYPTO_BUFFER_free(ctx->ocsp_response);
- OPENSSL_free(ctx->signed_cert_timestamp_list);
EVP_PKEY_free(ctx->tlsext_channel_id_private);
OPENSSL_free(ctx);
@@ -471,8 +472,11 @@ SSL *SSL_new(SSL_CTX *ctx) {
ssl->signed_cert_timestamps_enabled = ctx->signed_cert_timestamps_enabled;
ssl->ocsp_stapling_enabled = ctx->ocsp_stapling_enabled;
- ssl->session_timeout = ctx->session_timeout;
- ssl->session_psk_dhe_timeout = ctx->session_psk_dhe_timeout;
+ /* If the context has an SCT list, use it. */
+ if (ctx->signed_cert_timestamp_list != NULL) {
+ CRYPTO_BUFFER_up_ref(ctx->signed_cert_timestamp_list);
+ ssl->signed_cert_timestamp_list = ctx->signed_cert_timestamp_list;
+ }
/* If the context has an OCSP response, use it. */
if (ctx->ocsp_response != NULL) {
@@ -518,6 +522,7 @@ void SSL_free(SSL *ssl) {
OPENSSL_free(ssl->psk_identity_hint);
sk_X509_NAME_pop_free(ssl->client_CA, X509_NAME_free);
sk_SRTP_PROTECTION_PROFILE_free(ssl->srtp_profiles);
+ CRYPTO_BUFFER_free(ssl->signed_cert_timestamp_list);
CRYPTO_BUFFER_free(ssl->ocsp_response);
if (ssl->method != NULL) {
@@ -1628,8 +1633,27 @@ int SSL_CTX_set_signed_cert_timestamp_list(SSL_CTX *ctx, const uint8_t *list,
return 0;
}
- return CBS_stow(&sct_list, &ctx->signed_cert_timestamp_list,
- &ctx->signed_cert_timestamp_list_length);
+ CRYPTO_BUFFER_free(ctx->signed_cert_timestamp_list);
+ ctx->signed_cert_timestamp_list = CRYPTO_BUFFER_new(CBS_data(&sct_list),
+ CBS_len(&sct_list),
+ NULL);
+ return ctx->signed_cert_timestamp_list != NULL;
+}
+
+int SSL_set_signed_cert_timestamp_list(SSL *ssl, const uint8_t *list,
+ size_t list_len) {
+ CBS sct_list;
+ CBS_init(&sct_list, list, list_len);
+ if (!ssl_is_sct_list_valid(&sct_list)) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SCT_LIST);
+ return 0;
+ }
+
+ CRYPTO_BUFFER_free(ssl->signed_cert_timestamp_list);
+ ssl->signed_cert_timestamp_list = CRYPTO_BUFFER_new(CBS_data(&sct_list),
+ CBS_len(&sct_list),
+ NULL);
+ return ssl->signed_cert_timestamp_list != NULL;
}
int SSL_CTX_set_ocsp_response(SSL_CTX *ctx, const uint8_t *response,
@@ -2035,6 +2059,12 @@ SSL_CTX *SSL_set_SSL_CTX(SSL *ssl, SSL_CTX *ctx) {
return ssl->ctx;
}
+ /* One cannot change the X.509 callbacks during a connection. */
+ if (ssl->ctx->x509_method != ctx->x509_method) {
+ assert(0);
+ return NULL;
+ }
+
if (ctx == NULL) {
ctx = ssl->initial_ctx;
}
@@ -2353,22 +2383,6 @@ int ssl3_can_false_start(const SSL *ssl) {
cipher->algorithm_mac == SSL_AEAD;
}
-const SSL3_ENC_METHOD *ssl3_get_enc_method(uint16_t version) {
- switch (version) {
- case SSL3_VERSION:
- return &SSLv3_enc_data;
-
- case TLS1_VERSION:
- case TLS1_1_VERSION:
- case TLS1_2_VERSION:
- case TLS1_3_VERSION:
- return &TLSv1_enc_data;
-
- default:
- return NULL;
- }
-}
-
const struct {
uint16_t version;
uint32_t flag;
diff --git a/src/ssl/ssl_rsa.c b/src/ssl/ssl_privkey.c
index 6ad2b71a..79622473 100644
--- a/src/ssl/ssl_rsa.c
+++ b/src/ssl/ssl_privkey.c
@@ -70,38 +70,30 @@
#include "internal.h"
-static int ssl_set_cert(CERT *cert, CRYPTO_BUFFER *buffer);
-static int ssl_set_pkey(CERT *cert, EVP_PKEY *pkey);
-
-static int is_key_type_supported(int key_type) {
+int ssl_is_key_type_supported(int key_type) {
return key_type == EVP_PKEY_RSA || key_type == EVP_PKEY_EC;
}
-int SSL_use_certificate(SSL *ssl, X509 *x) {
- if (x == NULL) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER);
+static int ssl_set_pkey(CERT *cert, EVP_PKEY *pkey) {
+ if (!ssl_is_key_type_supported(pkey->type)) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_CERTIFICATE_TYPE);
return 0;
}
- CRYPTO_BUFFER *buffer = x509_to_buffer(x);
- if (buffer == NULL) {
+ if (cert->chain != NULL &&
+ sk_CRYPTO_BUFFER_value(cert->chain, 0) != NULL &&
+ /* Sanity-check that the private key and the certificate match, unless
+ * the key is opaque (in case of, say, a smartcard). */
+ !EVP_PKEY_is_opaque(pkey) &&
+ !ssl_cert_check_private_key(cert, pkey)) {
return 0;
}
- const int ok = ssl_set_cert(ssl->cert, buffer);
- CRYPTO_BUFFER_free(buffer);
- return ok;
-}
-
-int SSL_use_certificate_ASN1(SSL *ssl, const uint8_t *der, size_t der_len) {
- CRYPTO_BUFFER *buffer = CRYPTO_BUFFER_new(der, der_len, NULL);
- if (buffer == NULL) {
- return 0;
- }
+ EVP_PKEY_free(cert->privatekey);
+ EVP_PKEY_up_ref(pkey);
+ cert->privatekey = pkey;
- const int ok = ssl_set_cert(ssl->cert, buffer);
- CRYPTO_BUFFER_free(buffer);
- return ok;
+ return 1;
}
int SSL_use_RSAPrivateKey(SSL *ssl, RSA *rsa) {
@@ -128,28 +120,6 @@ int SSL_use_RSAPrivateKey(SSL *ssl, RSA *rsa) {
return ret;
}
-static int ssl_set_pkey(CERT *cert, EVP_PKEY *pkey) {
- if (!is_key_type_supported(pkey->type)) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_CERTIFICATE_TYPE);
- return 0;
- }
-
- if (cert->chain != NULL &&
- sk_CRYPTO_BUFFER_value(cert->chain, 0) != NULL &&
- /* Sanity-check that the private key and the certificate match, unless
- * the key is opaque (in case of, say, a smartcard). */
- !EVP_PKEY_is_opaque(pkey) &&
- !ssl_cert_check_private_key(cert, pkey)) {
- return 0;
- }
-
- EVP_PKEY_free(cert->privatekey);
- EVP_PKEY_up_ref(pkey);
- cert->privatekey = pkey;
-
- return 1;
-}
-
int SSL_use_PrivateKey(SSL *ssl, EVP_PKEY *pkey) {
if (pkey == NULL) {
OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER);
@@ -179,98 +149,6 @@ int SSL_use_PrivateKey_ASN1(int type, SSL *ssl, const uint8_t *der,
return ret;
}
-int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x) {
- if (x == NULL) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER);
- return 0;
- }
-
- CRYPTO_BUFFER *buffer = x509_to_buffer(x);
- if (buffer == NULL) {
- return 0;
- }
-
- const int ok = ssl_set_cert(ctx->cert, buffer);
- CRYPTO_BUFFER_free(buffer);
- return ok;
-}
-
-static int ssl_set_cert(CERT *cert, CRYPTO_BUFFER *buffer) {
- CBS cert_cbs;
- CRYPTO_BUFFER_init_CBS(buffer, &cert_cbs);
- EVP_PKEY *pubkey = ssl_cert_parse_pubkey(&cert_cbs);
- if (pubkey == NULL) {
- return 0;
- }
-
- if (!is_key_type_supported(pubkey->type)) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_CERTIFICATE_TYPE);
- EVP_PKEY_free(pubkey);
- return 0;
- }
-
- /* An ECC certificate may be usable for ECDH or ECDSA. We only support ECDSA
- * certificates, so sanity-check the key usage extension. */
- if (pubkey->type == EVP_PKEY_EC &&
- !ssl_cert_check_digital_signature_key_usage(&cert_cbs)) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_CERTIFICATE_TYPE);
- EVP_PKEY_free(pubkey);
- return 0;
- }
-
- if (cert->privatekey != NULL) {
- /* Sanity-check that the private key and the certificate match, unless the
- * key is opaque (in case of, say, a smartcard). */
- if (!EVP_PKEY_is_opaque(cert->privatekey) &&
- !ssl_compare_public_and_private_key(pubkey, cert->privatekey)) {
- /* don't fail for a cert/key mismatch, just free current private key
- * (when switching to a different cert & key, first this function should
- * be used, then ssl_set_pkey */
- EVP_PKEY_free(cert->privatekey);
- cert->privatekey = NULL;
- /* clear error queue */
- ERR_clear_error();
- }
- }
-
- EVP_PKEY_free(pubkey);
-
- ssl_cert_flush_cached_x509_leaf(cert);
-
- if (cert->chain != NULL) {
- CRYPTO_BUFFER_free(sk_CRYPTO_BUFFER_value(cert->chain, 0));
- sk_CRYPTO_BUFFER_set(cert->chain, 0, buffer);
- CRYPTO_BUFFER_up_ref(buffer);
- return 1;
- }
-
- cert->chain = sk_CRYPTO_BUFFER_new_null();
- if (cert->chain == NULL) {
- return 0;
- }
-
- if (!sk_CRYPTO_BUFFER_push(cert->chain, buffer)) {
- sk_CRYPTO_BUFFER_free(cert->chain);
- cert->chain = NULL;
- return 0;
- }
- CRYPTO_BUFFER_up_ref(buffer);
-
- return 1;
-}
-
-int SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, size_t der_len,
- const uint8_t *der) {
- CRYPTO_BUFFER *buffer = CRYPTO_BUFFER_new(der, der_len, NULL);
- if (buffer == NULL) {
- return 0;
- }
-
- const int ok = ssl_set_cert(ctx->cert, buffer);
- CRYPTO_BUFFER_free(buffer);
- return ok;
-}
-
int SSL_CTX_use_RSAPrivateKey(SSL_CTX *ctx, RSA *rsa) {
int ret;
EVP_PKEY *pkey;
diff --git a/src/ssl/ssl_rsa_cc.cc b/src/ssl/ssl_privkey_cc.cc
index 653308c1..653308c1 100644
--- a/src/ssl/ssl_rsa_cc.cc
+++ b/src/ssl/ssl_privkey_cc.cc
diff --git a/src/ssl/ssl_session.c b/src/ssl/ssl_session.c
index 7cddbdff..b71b994c 100644
--- a/src/ssl/ssl_session.c
+++ b/src/ssl/ssl_session.c
@@ -160,7 +160,7 @@ static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *session);
static void SSL_SESSION_list_add(SSL_CTX *ctx, SSL_SESSION *session);
static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *session, int lock);
-SSL_SESSION *SSL_SESSION_new(void) {
+SSL_SESSION *ssl_session_new(const SSL_X509_METHOD *x509_method) {
SSL_SESSION *session = OPENSSL_malloc(sizeof(SSL_SESSION));
if (session == NULL) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
@@ -168,6 +168,7 @@ SSL_SESSION *SSL_SESSION_new(void) {
}
OPENSSL_memset(session, 0, sizeof(SSL_SESSION));
+ session->x509_method = x509_method;
session->verify_result = X509_V_ERR_INVALID_CALL;
session->references = 1;
session->timeout = SSL_DEFAULT_SESSION_TIMEOUT;
@@ -177,8 +178,12 @@ SSL_SESSION *SSL_SESSION_new(void) {
return session;
}
+SSL_SESSION *SSL_SESSION_new(const SSL_CTX *ctx) {
+ return ssl_session_new(ctx->x509_method);
+}
+
SSL_SESSION *SSL_SESSION_dup(SSL_SESSION *session, int dup_flags) {
- SSL_SESSION *new_session = SSL_SESSION_new();
+ SSL_SESSION *new_session = ssl_session_new(session->x509_method);
if (new_session == NULL) {
goto err;
}
@@ -214,16 +219,11 @@ SSL_SESSION *SSL_SESSION_dup(SSL_SESSION *session, int dup_flags) {
CRYPTO_BUFFER_up_ref(buffer);
}
}
- if (session->x509_peer != NULL) {
- X509_up_ref(session->x509_peer);
- new_session->x509_peer = session->x509_peer;
- }
- if (session->x509_chain != NULL) {
- new_session->x509_chain = X509_chain_up_ref(session->x509_chain);
- if (new_session->x509_chain == NULL) {
- goto err;
- }
+
+ if (!session->x509_method->session_dup(new_session, session)) {
+ goto err;
}
+
new_session->verify_result = session->verify_result;
new_session->ocsp_response_length = session->ocsp_response_length;
@@ -367,9 +367,7 @@ void SSL_SESSION_free(SSL_SESSION *session) {
OPENSSL_cleanse(session->master_key, sizeof(session->master_key));
OPENSSL_cleanse(session->session_id, sizeof(session->session_id));
sk_CRYPTO_BUFFER_pop_free(session->certs, CRYPTO_BUFFER_free);
- X509_free(session->x509_peer);
- sk_X509_pop_free(session->x509_chain, X509_free);
- sk_X509_pop_free(session->x509_chain_without_leaf, X509_free);
+ session->x509_method->session_clear(session);
OPENSSL_free(session->tlsext_hostname);
OPENSSL_free(session->tlsext_tick);
OPENSSL_free(session->tlsext_signed_cert_timestamp_list);
@@ -494,6 +492,16 @@ void *SSL_SESSION_get_ex_data(const SSL_SESSION *session, int idx) {
return CRYPTO_get_ex_data(&session->ex_data, idx);
}
+const EVP_MD *SSL_SESSION_get_digest(const SSL_SESSION *session,
+ const SSL *ssl) {
+ uint16_t version;
+ if (!ssl->method->version_from_wire(&version, session->ssl_version)) {
+ return NULL;
+ }
+
+ return ssl_get_handshake_digest(session->cipher->algorithm_prf, version);
+}
+
int ssl_get_new_session(SSL_HANDSHAKE *hs, int is_server) {
SSL *const ssl = hs->ssl;
if (ssl->mode & SSL_MODE_NO_SESSION_CREATION) {
@@ -501,7 +509,7 @@ int ssl_get_new_session(SSL_HANDSHAKE *hs, int is_server) {
return 0;
}
- SSL_SESSION *session = SSL_SESSION_new();
+ SSL_SESSION *session = ssl_session_new(ssl->ctx->x509_method);
if (session == NULL) {
return 0;
}
@@ -518,13 +526,13 @@ int ssl_get_new_session(SSL_HANDSHAKE *hs, int is_server) {
if (version >= TLS1_3_VERSION) {
/* TLS 1.3 uses tickets as authenticators, so we are willing to use them for
* longer. */
- session->timeout = ssl->session_psk_dhe_timeout;
+ session->timeout = ssl->initial_ctx->session_psk_dhe_timeout;
session->auth_timeout = SSL_DEFAULT_SESSION_AUTH_TIMEOUT;
} else {
/* TLS 1.2 resumption does not incorporate new key material, so we use a
* much shorter timeout. */
- session->timeout = ssl->session_timeout;
- session->auth_timeout = ssl->session_timeout;
+ session->timeout = ssl->initial_ctx->session_timeout;
+ session->auth_timeout = ssl->initial_ctx->session_timeout;
}
if (is_server) {
@@ -563,53 +571,6 @@ err:
return 0;
}
-int ssl_session_x509_cache_objects(SSL_SESSION *sess) {
- STACK_OF(X509) *chain = NULL;
- const size_t num_certs = sk_CRYPTO_BUFFER_num(sess->certs);
-
- if (num_certs > 0) {
- chain = sk_X509_new_null();
- if (chain == NULL) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- }
-
- X509 *leaf = NULL;
- for (size_t i = 0; i < num_certs; i++) {
- X509 *x509 = X509_parse_from_buffer(sk_CRYPTO_BUFFER_value(sess->certs, i));
- if (x509 == NULL) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
- goto err;
- }
- if (!sk_X509_push(chain, x509)) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- X509_free(x509);
- goto err;
- }
- if (i == 0) {
- leaf = x509;
- }
- }
-
- sk_X509_pop_free(sess->x509_chain, X509_free);
- sess->x509_chain = chain;
- sk_X509_pop_free(sess->x509_chain_without_leaf, X509_free);
- sess->x509_chain_without_leaf = NULL;
-
- X509_free(sess->x509_peer);
- if (leaf != NULL) {
- X509_up_ref(leaf);
- }
- sess->x509_peer = leaf;
-
- return 1;
-
-err:
- sk_X509_pop_free(chain, X509_free);
- return 0;
-}
-
int ssl_encrypt_ticket(SSL *ssl, CBB *out, const SSL_SESSION *session) {
int ret = 0;
@@ -743,7 +704,8 @@ int ssl_session_is_resumable(const SSL *ssl, const SSL_SESSION *session) {
/* If the session contains a client certificate (either the full
* certificate or just the hash) then require that the form of the
* certificate matches the current configuration. */
- ((session->x509_peer == NULL && !session->peer_sha256_valid) ||
+ ((sk_CRYPTO_BUFFER_num(session->certs) == 0 &&
+ !session->peer_sha256_valid) ||
session->peer_sha256_valid ==
ssl->retain_only_sha256_of_client_certs);
}
@@ -983,16 +945,6 @@ void SSL_CTX_set_session_psk_dhe_timeout(SSL_CTX *ctx, long timeout) {
ctx->session_psk_dhe_timeout = timeout;
}
-long SSL_set_session_timeout(SSL *ssl, long timeout) {
- long old_timeout = ssl->session_timeout;
- ssl->session_timeout = timeout;
- return old_timeout;
-}
-
-void SSL_set_session_psk_dhe_timeout(SSL *ssl, long timeout) {
- ssl->session_psk_dhe_timeout = timeout;
-}
-
typedef struct timeout_param_st {
SSL_CTX *ctx;
long time;
diff --git a/src/ssl/ssl_stat.c b/src/ssl/ssl_stat.c
index 09a43d1c..479288a2 100644
--- a/src/ssl/ssl_stat.c
+++ b/src/ssl/ssl_stat.c
@@ -163,15 +163,6 @@ const char *SSL_state_string_long(const SSL *ssl) {
case SSL3_ST_SR_CLNT_HELLO_C:
return "SSLv3 read client hello C";
- case SSL3_ST_SW_HELLO_REQ_A:
- return "SSLv3 write hello request A";
-
- case SSL3_ST_SW_HELLO_REQ_B:
- return "SSLv3 write hello request B";
-
- case SSL3_ST_SW_HELLO_REQ_C:
- return "SSLv3 write hello request C";
-
case SSL3_ST_SW_SRVR_HELLO_A:
return "SSLv3 write server hello A";
@@ -273,15 +264,6 @@ const char *SSL_state_string(const SSL *ssl) {
case SSL3_ST_CR_FINISHED_A:
return "3RFINA";
- case SSL3_ST_SW_HELLO_REQ_A:
- return "3WHR_A";
-
- case SSL3_ST_SW_HELLO_REQ_B:
- return "3WHR_B";
-
- case SSL3_ST_SW_HELLO_REQ_C:
- return "3WHR_C";
-
case SSL3_ST_SR_CLNT_HELLO_A:
return "3RCH_A";
diff --git a/src/ssl/ssl_test.cc b/src/ssl/ssl_test.cc
index aa265c8f..dfab9769 100644
--- a/src/ssl/ssl_test.cc
+++ b/src/ssl/ssl_test.cc
@@ -634,7 +634,12 @@ static bool TestSSL_SESSIONEncoding(const char *input_b64) {
}
// Verify the SSL_SESSION decodes.
- bssl::UniquePtr<SSL_SESSION> session(SSL_SESSION_from_bytes(input.data(), input.size()));
+ bssl::UniquePtr<SSL_CTX> ssl_ctx(SSL_CTX_new(TLS_method()));
+ if (!ssl_ctx) {
+ return false;
+ }
+ bssl::UniquePtr<SSL_SESSION> session(
+ SSL_SESSION_from_bytes(input.data(), input.size(), ssl_ctx.get()));
if (!session) {
fprintf(stderr, "SSL_SESSION_from_bytes failed\n");
return false;
@@ -703,7 +708,12 @@ static bool TestBadSSL_SESSIONEncoding(const char *input_b64) {
}
// Verify that the SSL_SESSION fails to decode.
- bssl::UniquePtr<SSL_SESSION> session(SSL_SESSION_from_bytes(input.data(), input.size()));
+ bssl::UniquePtr<SSL_CTX> ssl_ctx(SSL_CTX_new(TLS_method()));
+ if (!ssl_ctx) {
+ return false;
+ }
+ bssl::UniquePtr<SSL_SESSION> session(
+ SSL_SESSION_from_bytes(input.data(), input.size(), ssl_ctx.get()));
if (session) {
fprintf(stderr, "SSL_SESSION_from_bytes unexpectedly succeeded\n");
return false;
@@ -795,8 +805,13 @@ static bssl::UniquePtr<SSL_SESSION> CreateSessionWithTicket(uint16_t version,
if (!DecodeBase64(&der, kOpenSSLSession)) {
return nullptr;
}
+
+ bssl::UniquePtr<SSL_CTX> ssl_ctx(SSL_CTX_new(TLS_method()));
+ if (!ssl_ctx) {
+ return nullptr;
+ }
bssl::UniquePtr<SSL_SESSION> session(
- SSL_SESSION_from_bytes(der.data(), der.size()));
+ SSL_SESSION_from_bytes(der.data(), der.size(), ssl_ctx.get()));
if (!session) {
return nullptr;
}
@@ -935,24 +950,18 @@ static bool TestPaddingExtension(uint16_t max_version,
// Test that |SSL_get_client_CA_list| echoes back the configured parameter even
// before configuring as a server.
-static bool TestClientCAList() {
+TEST(SSLTest, ClientCAList) {
bssl::UniquePtr<SSL_CTX> ctx(SSL_CTX_new(TLS_method()));
- if (!ctx) {
- return false;
- }
+ ASSERT_TRUE(ctx);
bssl::UniquePtr<SSL> ssl(SSL_new(ctx.get()));
- if (!ssl) {
- return false;
- }
+ ASSERT_TRUE(ssl);
STACK_OF(X509_NAME) *stack = sk_X509_NAME_new_null();
- if (stack == nullptr) {
- return false;
- }
+ ASSERT_TRUE(stack);
// |SSL_set_client_CA_list| takes ownership.
SSL_set_client_CA_list(ssl.get(), stack);
- return SSL_get_client_CA_list(ssl.get()) == stack;
+ EXPECT_EQ(stack, SSL_get_client_CA_list(ssl.get()));
}
static void AppendSession(SSL_SESSION *session, void *arg) {
@@ -995,7 +1004,11 @@ static bool ExpectCache(SSL_CTX *ctx,
}
static bssl::UniquePtr<SSL_SESSION> CreateTestSession(uint32_t number) {
- bssl::UniquePtr<SSL_SESSION> ret(SSL_SESSION_new());
+ bssl::UniquePtr<SSL_CTX> ssl_ctx(SSL_CTX_new(TLS_method()));
+ if (!ssl_ctx) {
+ return nullptr;
+ }
+ bssl::UniquePtr<SSL_SESSION> ret(SSL_SESSION_new(ssl_ctx.get()));
if (!ret) {
return nullptr;
}
@@ -1456,163 +1469,128 @@ static bool TestOneSidedShutdown(bool is_dtls, const SSL_METHOD *method,
return true;
}
-static bool TestSessionDuplication() {
+TEST(SSLTest, SessionDuplication) {
bssl::UniquePtr<SSL_CTX> client_ctx(SSL_CTX_new(TLS_method()));
bssl::UniquePtr<SSL_CTX> server_ctx(SSL_CTX_new(TLS_method()));
- if (!client_ctx || !server_ctx) {
- return false;
- }
+ ASSERT_TRUE(client_ctx);
+ ASSERT_TRUE(server_ctx);
bssl::UniquePtr<X509> cert = GetTestCertificate();
bssl::UniquePtr<EVP_PKEY> key = GetTestKey();
- if (!cert || !key ||
- !SSL_CTX_use_certificate(server_ctx.get(), cert.get()) ||
- !SSL_CTX_use_PrivateKey(server_ctx.get(), key.get())) {
- return false;
- }
+ ASSERT_TRUE(cert);
+ ASSERT_TRUE(key);
+ ASSERT_TRUE(SSL_CTX_use_certificate(server_ctx.get(), cert.get()));
+ ASSERT_TRUE(SSL_CTX_use_PrivateKey(server_ctx.get(), key.get()));
bssl::UniquePtr<SSL> client, server;
- if (!ConnectClientAndServer(&client, &server, client_ctx.get(),
- server_ctx.get(), nullptr /* no session */)) {
- return false;
- }
+ ASSERT_TRUE(ConnectClientAndServer(&client, &server, client_ctx.get(),
+ server_ctx.get(),
+ nullptr /* no session */));
SSL_SESSION *session0 = SSL_get_session(client.get());
- bssl::UniquePtr<SSL_SESSION> session1(SSL_SESSION_dup(session0, SSL_SESSION_DUP_ALL));
- if (!session1) {
- return false;
- }
+ bssl::UniquePtr<SSL_SESSION> session1(
+ SSL_SESSION_dup(session0, SSL_SESSION_DUP_ALL));
+ ASSERT_TRUE(session1);
session1->not_resumable = 0;
uint8_t *s0_bytes, *s1_bytes;
size_t s0_len, s1_len;
- if (!SSL_SESSION_to_bytes(session0, &s0_bytes, &s0_len)) {
- return false;
- }
+ ASSERT_TRUE(SSL_SESSION_to_bytes(session0, &s0_bytes, &s0_len));
bssl::UniquePtr<uint8_t> free_s0(s0_bytes);
- if (!SSL_SESSION_to_bytes(session1.get(), &s1_bytes, &s1_len)) {
- return false;
- }
+ ASSERT_TRUE(SSL_SESSION_to_bytes(session1.get(), &s1_bytes, &s1_len));
bssl::UniquePtr<uint8_t> free_s1(s1_bytes);
- return s0_len == s1_len && OPENSSL_memcmp(s0_bytes, s1_bytes, s0_len) == 0;
+ EXPECT_EQ(Bytes(s0_bytes, s0_len), Bytes(s1_bytes, s1_len));
}
-static bool ExpectFDs(const SSL *ssl, int rfd, int wfd) {
- if (SSL_get_rfd(ssl) != rfd || SSL_get_wfd(ssl) != wfd) {
- fprintf(stderr, "Got fds %d and %d, wanted %d and %d.\n", SSL_get_rfd(ssl),
- SSL_get_wfd(ssl), rfd, wfd);
- return false;
- }
+static void ExpectFDs(const SSL *ssl, int rfd, int wfd) {
+ EXPECT_EQ(rfd, SSL_get_rfd(ssl));
+ EXPECT_EQ(wfd, SSL_get_wfd(ssl));
// The wrapper BIOs are always equal when fds are equal, even if set
// individually.
- if (rfd == wfd && SSL_get_rbio(ssl) != SSL_get_wbio(ssl)) {
- fprintf(stderr, "rbio and wbio did not match.\n");
- return false;
+ if (rfd == wfd) {
+ EXPECT_EQ(SSL_get_rbio(ssl), SSL_get_wbio(ssl));
}
-
- return true;
}
-static bool TestSetFD() {
+TEST(SSLTest, SetFD) {
bssl::UniquePtr<SSL_CTX> ctx(SSL_CTX_new(TLS_method()));
- if (!ctx) {
- return false;
- }
+ ASSERT_TRUE(ctx);
// Test setting different read and write FDs.
bssl::UniquePtr<SSL> ssl(SSL_new(ctx.get()));
- if (!ssl ||
- !SSL_set_rfd(ssl.get(), 1) ||
- !SSL_set_wfd(ssl.get(), 2) ||
- !ExpectFDs(ssl.get(), 1, 2)) {
- return false;
- }
+ ASSERT_TRUE(ssl);
+ EXPECT_TRUE(SSL_set_rfd(ssl.get(), 1));
+ EXPECT_TRUE(SSL_set_wfd(ssl.get(), 2));
+ ExpectFDs(ssl.get(), 1, 2);
// Test setting the same FD.
ssl.reset(SSL_new(ctx.get()));
- if (!ssl ||
- !SSL_set_fd(ssl.get(), 1) ||
- !ExpectFDs(ssl.get(), 1, 1)) {
- return false;
- }
+ ASSERT_TRUE(ssl);
+ EXPECT_TRUE(SSL_set_fd(ssl.get(), 1));
+ ExpectFDs(ssl.get(), 1, 1);
// Test setting the same FD one side at a time.
ssl.reset(SSL_new(ctx.get()));
- if (!ssl ||
- !SSL_set_rfd(ssl.get(), 1) ||
- !SSL_set_wfd(ssl.get(), 1) ||
- !ExpectFDs(ssl.get(), 1, 1)) {
- return false;
- }
+ ASSERT_TRUE(ssl);
+ EXPECT_TRUE(SSL_set_rfd(ssl.get(), 1));
+ EXPECT_TRUE(SSL_set_wfd(ssl.get(), 1));
+ ExpectFDs(ssl.get(), 1, 1);
// Test setting the same FD in the other order.
ssl.reset(SSL_new(ctx.get()));
- if (!ssl ||
- !SSL_set_wfd(ssl.get(), 1) ||
- !SSL_set_rfd(ssl.get(), 1) ||
- !ExpectFDs(ssl.get(), 1, 1)) {
- return false;
- }
+ ASSERT_TRUE(ssl);
+ EXPECT_TRUE(SSL_set_wfd(ssl.get(), 1));
+ EXPECT_TRUE(SSL_set_rfd(ssl.get(), 1));
+ ExpectFDs(ssl.get(), 1, 1);
// Test changing the read FD partway through.
ssl.reset(SSL_new(ctx.get()));
- if (!ssl ||
- !SSL_set_fd(ssl.get(), 1) ||
- !SSL_set_rfd(ssl.get(), 2) ||
- !ExpectFDs(ssl.get(), 2, 1)) {
- return false;
- }
+ ASSERT_TRUE(ssl);
+ EXPECT_TRUE(SSL_set_fd(ssl.get(), 1));
+ EXPECT_TRUE(SSL_set_rfd(ssl.get(), 2));
+ ExpectFDs(ssl.get(), 2, 1);
// Test changing the write FD partway through.
ssl.reset(SSL_new(ctx.get()));
- if (!ssl ||
- !SSL_set_fd(ssl.get(), 1) ||
- !SSL_set_wfd(ssl.get(), 2) ||
- !ExpectFDs(ssl.get(), 1, 2)) {
- return false;
- }
+ ASSERT_TRUE(ssl);
+ EXPECT_TRUE(SSL_set_fd(ssl.get(), 1));
+ EXPECT_TRUE(SSL_set_wfd(ssl.get(), 2));
+ ExpectFDs(ssl.get(), 1, 2);
// Test a no-op change to the read FD partway through.
ssl.reset(SSL_new(ctx.get()));
- if (!ssl ||
- !SSL_set_fd(ssl.get(), 1) ||
- !SSL_set_rfd(ssl.get(), 1) ||
- !ExpectFDs(ssl.get(), 1, 1)) {
- return false;
- }
+ ASSERT_TRUE(ssl);
+ EXPECT_TRUE(SSL_set_fd(ssl.get(), 1));
+ EXPECT_TRUE(SSL_set_rfd(ssl.get(), 1));
+ ExpectFDs(ssl.get(), 1, 1);
// Test a no-op change to the write FD partway through.
ssl.reset(SSL_new(ctx.get()));
- if (!ssl ||
- !SSL_set_fd(ssl.get(), 1) ||
- !SSL_set_wfd(ssl.get(), 1) ||
- !ExpectFDs(ssl.get(), 1, 1)) {
- return false;
- }
+ ASSERT_TRUE(ssl);
+ EXPECT_TRUE(SSL_set_fd(ssl.get(), 1));
+ EXPECT_TRUE(SSL_set_wfd(ssl.get(), 1));
+ ExpectFDs(ssl.get(), 1, 1);
// ASan builds will implicitly test that the internal |BIO| reference-counting
// is correct.
-
- return true;
}
-static bool TestSetBIO() {
+TEST(SSLTest, SetBIO) {
bssl::UniquePtr<SSL_CTX> ctx(SSL_CTX_new(TLS_method()));
- if (!ctx) {
- return false;
- }
+ ASSERT_TRUE(ctx);
bssl::UniquePtr<SSL> ssl(SSL_new(ctx.get()));
bssl::UniquePtr<BIO> bio1(BIO_new(BIO_s_mem())), bio2(BIO_new(BIO_s_mem())),
bio3(BIO_new(BIO_s_mem()));
- if (!ssl || !bio1 || !bio2 || !bio3) {
- return false;
- }
+ ASSERT_TRUE(ssl);
+ ASSERT_TRUE(bio1);
+ ASSERT_TRUE(bio2);
+ ASSERT_TRUE(bio3);
// SSL_set_bio takes one reference when the parameters are the same.
BIO_up_ref(bio1.get());
@@ -1655,7 +1633,6 @@ static bool TestSetBIO() {
// ASAN builds will implicitly test that the internal |BIO| reference-counting
// is correct.
- return true;
}
static int VerifySucceed(X509_STORE_CTX *store_ctx, void *arg) { return 1; }
@@ -2207,8 +2184,12 @@ static bool GetServerTicketTime(long *out, const SSL_SESSION *session) {
len = static_cast<size_t>(len1 + len2);
#endif
+ bssl::UniquePtr<SSL_CTX> ssl_ctx(SSL_CTX_new(TLS_method()));
+ if (!ssl_ctx) {
+ return false;
+ }
bssl::UniquePtr<SSL_SESSION> server_session(
- SSL_SESSION_from_bytes(plaintext.get(), len));
+ SSL_SESSION_from_bytes(plaintext.get(), len, ssl_ctx.get()));
if (!server_session) {
return false;
}
@@ -2410,151 +2391,6 @@ static bool TestSessionTimeout(bool is_dtls, const SSL_METHOD *method,
return true;
}
-static int SetSessionTimeoutCallback(SSL *ssl, void *arg) {
- long timeout = *(long *) arg;
- SSL_set_session_timeout(ssl, timeout);
- return 1;
-}
-
-static int SetSessionTimeoutCallbackTLS13(SSL *ssl, void *arg) {
- long timeout = *(long *) arg;
- SSL_set_session_psk_dhe_timeout(ssl, timeout);
- return 1;
-}
-
-static bool TestSessionTimeoutCertCallback(bool is_dtls,
- const SSL_METHOD *method,
- uint16_t version) {
- if (version == TLS1_3_VERSION) {
- // |SSL_set_session_timeout| only applies to TLS 1.2 style resumption.
- return true;
- }
-
- static const int kStartTime = 1000;
- g_current_time.tv_sec = kStartTime;
-
- bssl::UniquePtr<X509> cert = GetTestCertificate();
- bssl::UniquePtr<EVP_PKEY> key = GetTestKey();
- if (!cert || !key) {
- return false;
- }
-
- bssl::UniquePtr<SSL_CTX> server_ctx(SSL_CTX_new(method));
- bssl::UniquePtr<SSL_CTX> client_ctx(SSL_CTX_new(method));
- if (!server_ctx || !client_ctx ||
- !SSL_CTX_use_certificate(server_ctx.get(), cert.get()) ||
- !SSL_CTX_use_PrivateKey(server_ctx.get(), key.get()) ||
- !SSL_CTX_set_min_proto_version(client_ctx.get(), version) ||
- !SSL_CTX_set_max_proto_version(client_ctx.get(), version) ||
- !SSL_CTX_set_min_proto_version(server_ctx.get(), version) ||
- !SSL_CTX_set_max_proto_version(server_ctx.get(), version)) {
- return false;
- }
-
- SSL_CTX_set_session_cache_mode(client_ctx.get(), SSL_SESS_CACHE_BOTH);
- SSL_CTX_set_session_cache_mode(server_ctx.get(), SSL_SESS_CACHE_BOTH);
-
- SSL_CTX_set_current_time_cb(server_ctx.get(), CurrentTimeCallback);
-
- long timeout = 25;
- if (version == TLS1_3_VERSION) {
- SSL_CTX_set_cert_cb(server_ctx.get(), SetSessionTimeoutCallbackTLS13,
- &timeout);
- } else {
- SSL_CTX_set_cert_cb(server_ctx.get(), SetSessionTimeoutCallback, &timeout);
- }
-
- bssl::UniquePtr<SSL_SESSION> session =
- CreateClientSession(client_ctx.get(), server_ctx.get());
- if (!session) {
- fprintf(stderr, "Error getting session.\n");
- return false;
- }
-
- // Advance the clock just behind the timeout.
- g_current_time.tv_sec += timeout - 1;
-
- if (!ExpectSessionReused(client_ctx.get(), server_ctx.get(), session.get(),
- true /* expect session reused */)) {
- fprintf(stderr, "Error resuming session.\n");
- return false;
- }
-
- // Advance the clock one more second.
- g_current_time.tv_sec++;
-
- if (!ExpectSessionReused(client_ctx.get(), server_ctx.get(), session.get(),
- false /* expect session not reused */)) {
- fprintf(stderr, "Error resuming session.\n");
- return false;
- }
-
- // Set session timeout to 0 to disable resumption.
- timeout = 0;
- g_current_time.tv_sec = kStartTime;
-
- bssl::UniquePtr<SSL_SESSION> not_resumable_session =
- CreateClientSession(client_ctx.get(), server_ctx.get());
- if (!not_resumable_session) {
- fprintf(stderr, "Error getting session.\n");
- return false;
- }
-
- if (!ExpectSessionReused(client_ctx.get(), server_ctx.get(),
- not_resumable_session.get(),
- false /* expect session not reused */)) {
- fprintf(stderr, "Error resuming session with timeout of 0.\n");
- return false;
- }
-
- // Set both context and connection (via callback) default session timeout.
- // The connection one is the one that ends up being used.
- timeout = 25;
- g_current_time.tv_sec = kStartTime;
-
- if (version == TLS1_3_VERSION) {
- SSL_CTX_set_session_psk_dhe_timeout(server_ctx.get(), timeout - 10);
- } else {
- SSL_CTX_set_timeout(server_ctx.get(), timeout - 10);
- }
-
- bssl::UniquePtr<SSL_SESSION> ctx_and_cb_session =
- CreateClientSession(client_ctx.get(), server_ctx.get());
- if (!ctx_and_cb_session) {
- fprintf(stderr, "Error getting session.\n");
- return false;
- }
-
- if (!ExpectSessionReused(client_ctx.get(), server_ctx.get(),
- ctx_and_cb_session.get(),
- true /* expect session reused */)) {
- fprintf(stderr, "Error resuming session with timeout of 0.\n");
- return false;
- }
-
- // Advance the clock just behind the timeout.
- g_current_time.tv_sec += timeout - 1;
-
- if (!ExpectSessionReused(client_ctx.get(), server_ctx.get(),
- ctx_and_cb_session.get(),
- true /* expect session reused */)) {
- fprintf(stderr, "Error resuming session.\n");
- return false;
- }
-
- // Advance the clock one more second.
- g_current_time.tv_sec++;
-
- if (!ExpectSessionReused(client_ctx.get(), server_ctx.get(),
- ctx_and_cb_session.get(),
- false /* expect session not reused */)) {
- fprintf(stderr, "Error resuming session.\n");
- return false;
- }
-
- return true;
-}
-
static int SwitchContext(SSL *ssl, int *out_alert, void *arg) {
SSL_CTX *ctx = reinterpret_cast<SSL_CTX*>(arg);
SSL_set_SSL_CTX(ssl, ctx);
@@ -2622,121 +2458,81 @@ static bool TestSNICallback(bool is_dtls, const SSL_METHOD *method,
return true;
}
-static int SetMaxVersion(const SSL_CLIENT_HELLO *client_hello) {
- if (!SSL_set_max_proto_version(client_hello->ssl, TLS1_2_VERSION)) {
- return -1;
- }
-
- return 1;
-}
-
-// TestEarlyCallbackVersionSwitch tests that the early callback can swap the
-// maximum version.
-static bool TestEarlyCallbackVersionSwitch() {
+// Test that the early callback can swap the maximum version.
+TEST(SSLTest, EarlyCallbackVersionSwitch) {
bssl::UniquePtr<X509> cert = GetTestCertificate();
bssl::UniquePtr<EVP_PKEY> key = GetTestKey();
bssl::UniquePtr<SSL_CTX> server_ctx(SSL_CTX_new(TLS_method()));
bssl::UniquePtr<SSL_CTX> client_ctx(SSL_CTX_new(TLS_method()));
- if (!cert || !key || !server_ctx || !client_ctx ||
- !SSL_CTX_use_certificate(server_ctx.get(), cert.get()) ||
- !SSL_CTX_use_PrivateKey(server_ctx.get(), key.get()) ||
- !SSL_CTX_set_max_proto_version(client_ctx.get(), TLS1_3_VERSION) ||
- !SSL_CTX_set_max_proto_version(server_ctx.get(), TLS1_3_VERSION)) {
- return false;
- }
+ ASSERT_TRUE(cert);
+ ASSERT_TRUE(key);
+ ASSERT_TRUE(server_ctx);
+ ASSERT_TRUE(client_ctx);
+ ASSERT_TRUE(SSL_CTX_use_certificate(server_ctx.get(), cert.get()));
+ ASSERT_TRUE(SSL_CTX_use_PrivateKey(server_ctx.get(), key.get()));
+ ASSERT_TRUE(SSL_CTX_set_max_proto_version(client_ctx.get(), TLS1_3_VERSION));
+ ASSERT_TRUE(SSL_CTX_set_max_proto_version(server_ctx.get(), TLS1_3_VERSION));
+
+ SSL_CTX_set_select_certificate_cb(
+ server_ctx.get(), [](const SSL_CLIENT_HELLO *client_hello) -> int {
+ if (!SSL_set_max_proto_version(client_hello->ssl, TLS1_2_VERSION)) {
+ return -1;
+ }
- SSL_CTX_set_select_certificate_cb(server_ctx.get(), SetMaxVersion);
+ return 1;
+ });
bssl::UniquePtr<SSL> client, server;
- if (!ConnectClientAndServer(&client, &server, client_ctx.get(),
- server_ctx.get(), nullptr)) {
- return false;
- }
-
- if (SSL_version(client.get()) != TLS1_2_VERSION) {
- fprintf(stderr, "Early callback failed to switch the maximum version.\n");
- return false;
- }
-
- return true;
+ ASSERT_TRUE(ConnectClientAndServer(&client, &server, client_ctx.get(),
+ server_ctx.get(), nullptr));
+ EXPECT_EQ(TLS1_2_VERSION, SSL_version(client.get()));
}
-static bool TestSetVersion() {
+TEST(SSLTest, SetVersion) {
bssl::UniquePtr<SSL_CTX> ctx(SSL_CTX_new(TLS_method()));
- if (!ctx) {
- return false;
- }
-
- if (!SSL_CTX_set_max_proto_version(ctx.get(), TLS1_VERSION) ||
- !SSL_CTX_set_max_proto_version(ctx.get(), TLS1_1_VERSION) ||
- !SSL_CTX_set_min_proto_version(ctx.get(), TLS1_VERSION) ||
- !SSL_CTX_set_min_proto_version(ctx.get(), TLS1_1_VERSION)) {
- fprintf(stderr, "Could not set valid TLS version.\n");
- return false;
- }
-
- if (SSL_CTX_set_max_proto_version(ctx.get(), DTLS1_VERSION) ||
- SSL_CTX_set_max_proto_version(ctx.get(), 0x0200) ||
- SSL_CTX_set_max_proto_version(ctx.get(), 0x1234) ||
- SSL_CTX_set_min_proto_version(ctx.get(), DTLS1_VERSION) ||
- SSL_CTX_set_min_proto_version(ctx.get(), 0x0200) ||
- SSL_CTX_set_min_proto_version(ctx.get(), 0x1234)) {
- fprintf(stderr, "Unexpectedly set invalid TLS version.\n");
- return false;
- }
+ ASSERT_TRUE(ctx);
- if (!SSL_CTX_set_max_proto_version(ctx.get(), 0) ||
- !SSL_CTX_set_min_proto_version(ctx.get(), 0)) {
- fprintf(stderr, "Could not set default TLS version.\n");
- return false;
- }
-
- if (ctx->min_version != SSL3_VERSION ||
- ctx->max_version != TLS1_2_VERSION) {
- fprintf(stderr, "Default TLS versions were incorrect (%04x and %04x).\n",
- ctx->min_version, ctx->max_version);
- return false;
- }
+ // Set valid TLS versions.
+ EXPECT_TRUE(SSL_CTX_set_max_proto_version(ctx.get(), TLS1_VERSION));
+ EXPECT_TRUE(SSL_CTX_set_max_proto_version(ctx.get(), TLS1_1_VERSION));
+ EXPECT_TRUE(SSL_CTX_set_min_proto_version(ctx.get(), TLS1_VERSION));
+ EXPECT_TRUE(SSL_CTX_set_min_proto_version(ctx.get(), TLS1_1_VERSION));
+
+ // Invalid TLS versions are rejected.
+ EXPECT_FALSE(SSL_CTX_set_max_proto_version(ctx.get(), DTLS1_VERSION));
+ EXPECT_FALSE(SSL_CTX_set_max_proto_version(ctx.get(), 0x0200));
+ EXPECT_FALSE(SSL_CTX_set_max_proto_version(ctx.get(), 0x1234));
+ EXPECT_FALSE(SSL_CTX_set_min_proto_version(ctx.get(), DTLS1_VERSION));
+ EXPECT_FALSE(SSL_CTX_set_min_proto_version(ctx.get(), 0x0200));
+ EXPECT_FALSE(SSL_CTX_set_min_proto_version(ctx.get(), 0x1234));
+
+ // Zero is the default version.
+ EXPECT_TRUE(SSL_CTX_set_max_proto_version(ctx.get(), 0));
+ EXPECT_EQ(TLS1_2_VERSION, ctx->max_version);
+ EXPECT_TRUE(SSL_CTX_set_min_proto_version(ctx.get(), 0));
+ EXPECT_EQ(SSL3_VERSION, ctx->min_version);
ctx.reset(SSL_CTX_new(DTLS_method()));
- if (!ctx) {
- return false;
- }
-
- if (!SSL_CTX_set_max_proto_version(ctx.get(), DTLS1_VERSION) ||
- !SSL_CTX_set_max_proto_version(ctx.get(), DTLS1_2_VERSION) ||
- !SSL_CTX_set_min_proto_version(ctx.get(), DTLS1_VERSION) ||
- !SSL_CTX_set_min_proto_version(ctx.get(), DTLS1_2_VERSION)) {
- fprintf(stderr, "Could not set valid DTLS version.\n");
- return false;
- }
-
- if (SSL_CTX_set_max_proto_version(ctx.get(), TLS1_VERSION) ||
- SSL_CTX_set_max_proto_version(ctx.get(), 0xfefe /* DTLS 1.1 */) ||
- SSL_CTX_set_max_proto_version(ctx.get(), 0xfffe /* DTLS 0.1 */) ||
- SSL_CTX_set_max_proto_version(ctx.get(), 0x1234) ||
- SSL_CTX_set_min_proto_version(ctx.get(), TLS1_VERSION) ||
- SSL_CTX_set_min_proto_version(ctx.get(), 0xfefe /* DTLS 1.1 */) ||
- SSL_CTX_set_min_proto_version(ctx.get(), 0xfffe /* DTLS 0.1 */) ||
- SSL_CTX_set_min_proto_version(ctx.get(), 0x1234)) {
- fprintf(stderr, "Unexpectedly set invalid DTLS version.\n");
- return false;
- }
+ ASSERT_TRUE(ctx);
- if (!SSL_CTX_set_max_proto_version(ctx.get(), 0) ||
- !SSL_CTX_set_min_proto_version(ctx.get(), 0)) {
- fprintf(stderr, "Could not set default DTLS version.\n");
- return false;
- }
+ EXPECT_TRUE(SSL_CTX_set_max_proto_version(ctx.get(), DTLS1_VERSION));
+ EXPECT_TRUE(SSL_CTX_set_max_proto_version(ctx.get(), DTLS1_2_VERSION));
+ EXPECT_TRUE(SSL_CTX_set_min_proto_version(ctx.get(), DTLS1_VERSION));
+ EXPECT_TRUE(SSL_CTX_set_min_proto_version(ctx.get(), DTLS1_2_VERSION));
- if (ctx->min_version != TLS1_1_VERSION ||
- ctx->max_version != TLS1_2_VERSION) {
- fprintf(stderr, "Default DTLS versions were incorrect (%04x and %04x).\n",
- ctx->min_version, ctx->max_version);
- return false;
- }
+ EXPECT_FALSE(SSL_CTX_set_max_proto_version(ctx.get(), TLS1_VERSION));
+ EXPECT_FALSE(SSL_CTX_set_max_proto_version(ctx.get(), 0xfefe /* DTLS 1.1 */));
+ EXPECT_FALSE(SSL_CTX_set_max_proto_version(ctx.get(), 0xfffe /* DTLS 0.1 */));
+ EXPECT_FALSE(SSL_CTX_set_max_proto_version(ctx.get(), 0x1234));
+ EXPECT_FALSE(SSL_CTX_set_min_proto_version(ctx.get(), TLS1_VERSION));
+ EXPECT_FALSE(SSL_CTX_set_min_proto_version(ctx.get(), 0xfefe /* DTLS 1.1 */));
+ EXPECT_FALSE(SSL_CTX_set_min_proto_version(ctx.get(), 0xfffe /* DTLS 0.1 */));
+ EXPECT_FALSE(SSL_CTX_set_min_proto_version(ctx.get(), 0x1234));
- return true;
+ EXPECT_TRUE(SSL_CTX_set_max_proto_version(ctx.get(), 0));
+ EXPECT_EQ(TLS1_2_VERSION, ctx->max_version);
+ EXPECT_TRUE(SSL_CTX_set_min_proto_version(ctx.get(), 0));
+ EXPECT_EQ(TLS1_1_VERSION, ctx->min_version);
}
static const char *GetVersionName(uint16_t version) {
@@ -3279,10 +3075,8 @@ TEST(SSLTest, GetCertificate) {
bssl::UniquePtr<uint8_t> free_der3(der3);
// They must also encode identically.
- ASSERT_EQ(der2_len, der_len);
- EXPECT_EQ(0, OPENSSL_memcmp(der, der2, static_cast<size_t>(der_len)));
- ASSERT_EQ(der3_len, der_len);
- EXPECT_EQ(0, OPENSSL_memcmp(der, der3, static_cast<size_t>(der_len)));
+ EXPECT_EQ(Bytes(der, der_len), Bytes(der2, der2_len));
+ EXPECT_EQ(Bytes(der, der_len), Bytes(der3, der3_len));
}
// TODO(davidben): Convert this file to GTest properly.
@@ -3313,28 +3107,20 @@ TEST(SSLTest, AllTests) {
// Test the padding extension at TLS 1.3 with a TLS 1.3 session, so there
// will be a PSK binder after the padding extension.
!TestPaddingExtension(TLS1_3_VERSION, TLS1_3_DRAFT_VERSION) ||
- !TestClientCAList() ||
!TestInternalSessionCache() ||
!ForEachVersion(TestSequenceNumber) ||
!ForEachVersion(TestOneSidedShutdown) ||
- !TestSessionDuplication() ||
- !TestSetFD() ||
- !TestSetBIO() ||
!ForEachVersion(TestGetPeerCertificate) ||
!ForEachVersion(TestRetainOnlySHA256OfCerts) ||
!TestClientHello() ||
!ForEachVersion(TestSessionIDContext) ||
!ForEachVersion(TestSessionTimeout) ||
- !ForEachVersion(TestSessionTimeoutCertCallback) ||
!ForEachVersion(TestSNICallback) ||
- !TestEarlyCallbackVersionSwitch() ||
- !TestSetVersion() ||
!ForEachVersion(TestVersion) ||
!ForEachVersion(TestALPNCipherAvailable) ||
!ForEachVersion(TestSSLClearSessionResumption) ||
!ForEachVersion(TestAutoChain) ||
!ForEachVersion(TestSSLWriteRetry)) {
- ERR_print_errors_fp(stderr);
ADD_FAILURE() << "Tests failed";
}
}
diff --git a/src/ssl/s3_enc.c b/src/ssl/ssl_transcript.c
index bf82e086..9cc37778 100644
--- a/src/ssl/s3_enc.c
+++ b/src/ssl/ssl_transcript.c
@@ -138,84 +138,22 @@
#include <assert.h>
#include <string.h>
+#include <openssl/buf.h>
+#include <openssl/digest.h>
#include <openssl/err.h>
-#include <openssl/evp.h>
#include <openssl/mem.h>
#include <openssl/md5.h>
#include <openssl/nid.h>
+#include <openssl/sha.h>
#include "../crypto/internal.h"
#include "internal.h"
-static int ssl3_prf(const SSL *ssl, uint8_t *out, size_t out_len,
- const uint8_t *secret, size_t secret_len, const char *label,
- size_t label_len, const uint8_t *seed1, size_t seed1_len,
- const uint8_t *seed2, size_t seed2_len) {
- EVP_MD_CTX md5;
- EVP_MD_CTX sha1;
- uint8_t buf[16], smd[SHA_DIGEST_LENGTH];
- uint8_t c = 'A';
- size_t i, j, k;
-
- k = 0;
- EVP_MD_CTX_init(&md5);
- EVP_MD_CTX_init(&sha1);
- for (i = 0; i < out_len; i += MD5_DIGEST_LENGTH) {
- k++;
- if (k > sizeof(buf)) {
- /* bug: 'buf' is too small for this ciphersuite */
- OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
- for (j = 0; j < k; j++) {
- buf[j] = c;
- }
- c++;
- if (!EVP_DigestInit_ex(&sha1, EVP_sha1(), NULL)) {
- OPENSSL_PUT_ERROR(SSL, ERR_LIB_EVP);
- return 0;
- }
- EVP_DigestUpdate(&sha1, buf, k);
- EVP_DigestUpdate(&sha1, secret, secret_len);
- /* |label| is ignored for SSLv3. */
- if (seed1_len) {
- EVP_DigestUpdate(&sha1, seed1, seed1_len);
- }
- if (seed2_len) {
- EVP_DigestUpdate(&sha1, seed2, seed2_len);
- }
- EVP_DigestFinal_ex(&sha1, smd, NULL);
-
- if (!EVP_DigestInit_ex(&md5, EVP_md5(), NULL)) {
- OPENSSL_PUT_ERROR(SSL, ERR_LIB_EVP);
- return 0;
- }
- EVP_DigestUpdate(&md5, secret, secret_len);
- EVP_DigestUpdate(&md5, smd, SHA_DIGEST_LENGTH);
- if (i + MD5_DIGEST_LENGTH > out_len) {
- EVP_DigestFinal_ex(&md5, smd, NULL);
- OPENSSL_memcpy(out, smd, out_len - i);
- } else {
- EVP_DigestFinal_ex(&md5, out, NULL);
- }
-
- out += MD5_DIGEST_LENGTH;
- }
-
- OPENSSL_cleanse(smd, SHA_DIGEST_LENGTH);
- EVP_MD_CTX_cleanup(&md5);
- EVP_MD_CTX_cleanup(&sha1);
-
- return 1;
-}
-
-int ssl3_init_handshake_buffer(SSL *ssl) {
- ssl3_free_handshake_buffer(ssl);
- ssl3_free_handshake_hash(ssl);
- ssl->s3->handshake_buffer = BUF_MEM_new();
- return ssl->s3->handshake_buffer != NULL;
+int SSL_TRANSCRIPT_init(SSL_TRANSCRIPT *transcript) {
+ SSL_TRANSCRIPT_cleanup(transcript);
+ transcript->buffer = BUF_MEM_new();
+ return transcript->buffer != NULL;
}
/* init_digest_with_data calls |EVP_DigestInit_ex| on |ctx| with |md| and then
@@ -229,78 +167,113 @@ static int init_digest_with_data(EVP_MD_CTX *ctx, const EVP_MD *md,
return 1;
}
-int ssl3_init_handshake_hash(SSL *ssl) {
- ssl3_free_handshake_hash(ssl);
+int SSL_TRANSCRIPT_init_hash(SSL_TRANSCRIPT *transcript, uint16_t version,
+ int algorithm_prf) {
+ const EVP_MD *md = ssl_get_handshake_digest(algorithm_prf, version);
- uint32_t algorithm_prf = ssl_get_algorithm_prf(ssl);
- if (!init_digest_with_data(&ssl->s3->handshake_hash,
- ssl_get_handshake_digest(algorithm_prf),
- ssl->s3->handshake_buffer)) {
- return 0;
+ /* To support SSL 3.0's Finished and CertificateVerify constructions,
+ * EVP_md5_sha1() is split into MD5 and SHA-1 halves. When SSL 3.0 is removed,
+ * we can simplify this. */
+ if (md == EVP_md5_sha1()) {
+ if (!init_digest_with_data(&transcript->md5, EVP_md5(),
+ transcript->buffer)) {
+ return 0;
+ }
+ md = EVP_sha1();
}
- if (algorithm_prf == SSL_HANDSHAKE_MAC_DEFAULT &&
- !init_digest_with_data(&ssl->s3->handshake_md5, EVP_md5(),
- ssl->s3->handshake_buffer)) {
+ if (!init_digest_with_data(&transcript->hash, md, transcript->buffer)) {
return 0;
}
return 1;
}
-void ssl3_free_handshake_hash(SSL *ssl) {
- EVP_MD_CTX_cleanup(&ssl->s3->handshake_hash);
- EVP_MD_CTX_cleanup(&ssl->s3->handshake_md5);
+void SSL_TRANSCRIPT_cleanup(SSL_TRANSCRIPT *transcript) {
+ SSL_TRANSCRIPT_free_buffer(transcript);
+ EVP_MD_CTX_cleanup(&transcript->hash);
+ EVP_MD_CTX_cleanup(&transcript->md5);
}
-void ssl3_free_handshake_buffer(SSL *ssl) {
- BUF_MEM_free(ssl->s3->handshake_buffer);
- ssl->s3->handshake_buffer = NULL;
+void SSL_TRANSCRIPT_free_buffer(SSL_TRANSCRIPT *transcript) {
+ BUF_MEM_free(transcript->buffer);
+ transcript->buffer = NULL;
}
-int ssl3_update_handshake_hash(SSL *ssl, const uint8_t *in, size_t in_len) {
+size_t SSL_TRANSCRIPT_digest_len(const SSL_TRANSCRIPT *transcript) {
+ return EVP_MD_size(SSL_TRANSCRIPT_md(transcript));
+}
+
+const EVP_MD *SSL_TRANSCRIPT_md(const SSL_TRANSCRIPT *transcript) {
+ if (EVP_MD_CTX_md(&transcript->md5) != NULL) {
+ return EVP_md5_sha1();
+ }
+ return EVP_MD_CTX_md(&transcript->hash);
+}
+
+int SSL_TRANSCRIPT_update(SSL_TRANSCRIPT *transcript, const uint8_t *in,
+ size_t in_len) {
/* Depending on the state of the handshake, either the handshake buffer may be
* active, the rolling hash, or both. */
-
- if (ssl->s3->handshake_buffer != NULL) {
- size_t new_len = ssl->s3->handshake_buffer->length + in_len;
+ if (transcript->buffer != NULL) {
+ size_t new_len = transcript->buffer->length + in_len;
if (new_len < in_len) {
OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
return 0;
}
- if (!BUF_MEM_grow(ssl->s3->handshake_buffer, new_len)) {
+ if (!BUF_MEM_grow(transcript->buffer, new_len)) {
return 0;
}
- OPENSSL_memcpy(ssl->s3->handshake_buffer->data + new_len - in_len, in,
- in_len);
+ OPENSSL_memcpy(transcript->buffer->data + new_len - in_len, in, in_len);
}
- if (EVP_MD_CTX_md(&ssl->s3->handshake_hash) != NULL) {
- EVP_DigestUpdate(&ssl->s3->handshake_hash, in, in_len);
+ if (EVP_MD_CTX_md(&transcript->hash) != NULL) {
+ EVP_DigestUpdate(&transcript->hash, in, in_len);
}
- if (EVP_MD_CTX_md(&ssl->s3->handshake_md5) != NULL) {
- EVP_DigestUpdate(&ssl->s3->handshake_md5, in, in_len);
+ if (EVP_MD_CTX_md(&transcript->md5) != NULL) {
+ EVP_DigestUpdate(&transcript->md5, in, in_len);
}
+
return 1;
}
-static int ssl3_handshake_mac(SSL *ssl, int md_nid, const char *sender,
- size_t sender_len, uint8_t *p) {
- unsigned int ret;
+int SSL_TRANSCRIPT_get_hash(const SSL_TRANSCRIPT *transcript, uint8_t *out,
+ size_t *out_len) {
+ int ret = 0;
+ EVP_MD_CTX ctx;
+ EVP_MD_CTX_init(&ctx);
+ unsigned md5_len = 0;
+ if (EVP_MD_CTX_md(&transcript->md5) != NULL) {
+ if (!EVP_MD_CTX_copy_ex(&ctx, &transcript->md5) ||
+ !EVP_DigestFinal_ex(&ctx, out, &md5_len)) {
+ goto err;
+ }
+ }
+
+ unsigned len;
+ if (!EVP_MD_CTX_copy_ex(&ctx, &transcript->hash) ||
+ !EVP_DigestFinal_ex(&ctx, out + md5_len, &len)) {
+ goto err;
+ }
+
+ *out_len = md5_len + len;
+ ret = 1;
+
+err:
+ EVP_MD_CTX_cleanup(&ctx);
+ return ret;
+}
+
+static int ssl3_handshake_mac(SSL_TRANSCRIPT *transcript,
+ const SSL_SESSION *session,
+ const EVP_MD_CTX *ctx_template,
+ const char *sender, size_t sender_len,
+ uint8_t *p, size_t *out_len) {
+ unsigned int len;
size_t npad, n;
unsigned int i;
uint8_t md_buf[EVP_MAX_MD_SIZE];
EVP_MD_CTX ctx;
- const EVP_MD_CTX *ctx_template;
-
- if (md_nid == NID_md5) {
- ctx_template = &ssl->s3->handshake_md5;
- } else if (md_nid == EVP_MD_CTX_type(&ssl->s3->handshake_hash)) {
- ctx_template = &ssl->s3->handshake_hash;
- } else {
- OPENSSL_PUT_ERROR(SSL, SSL_R_NO_REQUIRED_DIGEST);
- return 0;
- }
EVP_MD_CTX_init(&ctx);
if (!EVP_MD_CTX_copy_ex(&ctx, ctx_template)) {
@@ -325,11 +298,6 @@ static int ssl3_handshake_mac(SSL *ssl, int md_nid, const char *sender,
n = EVP_MD_CTX_size(&ctx);
- SSL_SESSION *session = ssl->session;
- if (ssl->s3->new_session != NULL) {
- session = ssl->s3->new_session;
- }
-
npad = (48 / n) * n;
if (sender != NULL) {
EVP_DigestUpdate(&ctx, sender, sender_len);
@@ -346,61 +314,92 @@ static int ssl3_handshake_mac(SSL *ssl, int md_nid, const char *sender,
EVP_DigestUpdate(&ctx, session->master_key, session->master_key_length);
EVP_DigestUpdate(&ctx, kPad2, npad);
EVP_DigestUpdate(&ctx, md_buf, i);
- EVP_DigestFinal_ex(&ctx, p, &ret);
+ EVP_DigestFinal_ex(&ctx, p, &len);
EVP_MD_CTX_cleanup(&ctx);
- return ret;
+ *out_len = len;
+ return 1;
}
-static int ssl3_final_finish_mac(SSL *ssl, int from_server, uint8_t *out) {
- const char *sender = from_server ? SSL3_MD_SERVER_FINISHED_CONST
- : SSL3_MD_CLIENT_FINISHED_CONST;
- const size_t sender_len = 4;
- int ret, sha1len;
- ret = ssl3_handshake_mac(ssl, NID_md5, sender, sender_len, out);
- if (ret == 0) {
+int SSL_TRANSCRIPT_ssl3_cert_verify_hash(SSL_TRANSCRIPT *transcript,
+ uint8_t *out, size_t *out_len,
+ const SSL_SESSION *session,
+ int signature_algorithm) {
+ if (SSL_TRANSCRIPT_md(transcript) != EVP_md5_sha1()) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
return 0;
}
- out += ret;
+ if (signature_algorithm == SSL_SIGN_RSA_PKCS1_MD5_SHA1) {
+ size_t md5_len, len;
+ if (!ssl3_handshake_mac(transcript, session, &transcript->md5, NULL, 0, out,
+ &md5_len) ||
+ !ssl3_handshake_mac(transcript, session, &transcript->hash, NULL, 0,
+ out + md5_len, &len)) {
+ return 0;
+ }
+ *out_len = md5_len + len;
+ return 1;
+ }
- sha1len = ssl3_handshake_mac(ssl, NID_sha1, sender, sender_len, out);
- if (sha1len == 0) {
- return 0;
+ if (signature_algorithm == SSL_SIGN_ECDSA_SHA1) {
+ return ssl3_handshake_mac(transcript, session, &transcript->hash, NULL, 0,
+ out, out_len);
}
- ret += sha1len;
- return ret;
+ OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+ return 0;
}
-int ssl3_cert_verify_hash(SSL *ssl, const EVP_MD **out_md, uint8_t *out,
- size_t *out_len, uint16_t signature_algorithm) {
- assert(ssl3_protocol_version(ssl) == SSL3_VERSION);
-
- if (signature_algorithm == SSL_SIGN_RSA_PKCS1_MD5_SHA1) {
- if (ssl3_handshake_mac(ssl, NID_md5, NULL, 0, out) == 0 ||
- ssl3_handshake_mac(ssl, NID_sha1, NULL, 0,
- out + MD5_DIGEST_LENGTH) == 0) {
+int SSL_TRANSCRIPT_finish_mac(SSL_TRANSCRIPT *transcript, uint8_t *out,
+ size_t *out_len, const SSL_SESSION *session,
+ int from_server, uint16_t version) {
+ if (version == SSL3_VERSION) {
+ if (SSL_TRANSCRIPT_md(transcript) != EVP_md5_sha1()) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
return 0;
}
- *out_md = EVP_md5_sha1();
- *out_len = MD5_DIGEST_LENGTH + SHA_DIGEST_LENGTH;
- } else if (signature_algorithm == SSL_SIGN_ECDSA_SHA1) {
- if (ssl3_handshake_mac(ssl, NID_sha1, NULL, 0, out) == 0) {
+
+ const char *sender = from_server ? SSL3_MD_SERVER_FINISHED_CONST
+ : SSL3_MD_CLIENT_FINISHED_CONST;
+ const size_t sender_len = 4;
+ size_t md5_len, len;
+ if (!ssl3_handshake_mac(transcript, session, &transcript->md5, sender,
+ sender_len, out, &md5_len) ||
+ !ssl3_handshake_mac(transcript, session, &transcript->hash, sender,
+ sender_len, out + md5_len, &len)) {
return 0;
}
- *out_md = EVP_sha1();
- *out_len = SHA_DIGEST_LENGTH;
- } else {
- OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+
+ *out_len = md5_len + len;
+ return 1;
+ }
+
+ /* At this point, the handshake should have released the handshake buffer on
+ * its own. */
+ assert(transcript->buffer == NULL);
+
+ const char *label = TLS_MD_CLIENT_FINISH_CONST;
+ size_t label_len = TLS_MD_SERVER_FINISH_CONST_SIZE;
+ if (from_server) {
+ label = TLS_MD_SERVER_FINISH_CONST;
+ label_len = TLS_MD_SERVER_FINISH_CONST_SIZE;
+ }
+
+ uint8_t digests[EVP_MAX_MD_SIZE];
+ size_t digests_len;
+ if (!SSL_TRANSCRIPT_get_hash(transcript, digests, &digests_len)) {
return 0;
}
+ static const size_t kFinishedLen = 12;
+ if (!tls1_prf(SSL_TRANSCRIPT_md(transcript), out, kFinishedLen,
+ session->master_key, session->master_key_length, label,
+ label_len, digests, digests_len, NULL, 0)) {
+ return 0;
+ }
+
+ *out_len = kFinishedLen;
return 1;
}
-
-const SSL3_ENC_METHOD SSLv3_enc_data = {
- ssl3_prf,
- ssl3_final_finish_mac,
-};
diff --git a/src/ssl/ssl_x509.c b/src/ssl/ssl_x509.c
index 5d78deb2..2955c213 100644
--- a/src/ssl/ssl_x509.c
+++ b/src/ssl/ssl_x509.c
@@ -140,8 +140,15 @@
#include <openssl/ssl.h>
+#include <assert.h>
+
+#include <openssl/asn1.h>
+#include <openssl/bytestring.h>
+#include <openssl/err.h>
+#include <openssl/pem.h>
#include <openssl/stack.h>
#include <openssl/x509.h>
+#include <openssl/x509v3.h>
#include <openssl/x509_vfy.h>
#include "internal.h"
@@ -281,23 +288,6 @@ void SSL_CTX_set_verify_depth(SSL_CTX *ctx, int depth) {
X509_VERIFY_PARAM_set_depth(ctx->param, depth);
}
-static X509 *ssl_cert_get0_leaf(CERT *cert) {
- if (cert->x509_leaf == NULL &&
- !ssl_cert_cache_leaf_cert(cert)) {
- return NULL;
- }
-
- return cert->x509_leaf;
-}
-
-X509 *SSL_get_certificate(const SSL *ssl) {
- return ssl_cert_get0_leaf(ssl->cert);
-}
-
-X509 *SSL_CTX_get0_certificate(const SSL_CTX *ctx) {
- return ssl_cert_get0_leaf(ctx->cert);
-}
-
int SSL_CTX_set_default_verify_paths(SSL_CTX *ctx) {
return X509_STORE_set_default_paths(ctx->cert_store);
}
@@ -329,3 +319,497 @@ void SSL_CTX_set_cert_store(SSL_CTX *ctx, X509_STORE *store) {
X509_STORE_free(ctx->cert_store);
ctx->cert_store = store;
}
+
+static void ssl_crypto_x509_flush_cached_leaf(CERT *cert) {
+ X509_free(cert->x509_leaf);
+ cert->x509_leaf = NULL;
+}
+
+static void ssl_crypto_x509_flush_cached_chain(CERT *cert) {
+ sk_X509_pop_free(cert->x509_chain, X509_free);
+ cert->x509_chain = NULL;
+}
+
+static void ssl_crypto_x509_clear(CERT *cert) {
+ ssl_crypto_x509_flush_cached_leaf(cert);
+ ssl_crypto_x509_flush_cached_chain(cert);
+
+ X509_free(cert->x509_stash);
+ cert->x509_stash = NULL;
+}
+
+static int ssl_crypto_x509_session_cache_objects(SSL_SESSION *sess) {
+ STACK_OF(X509) *chain = NULL;
+ const size_t num_certs = sk_CRYPTO_BUFFER_num(sess->certs);
+
+ if (num_certs > 0) {
+ chain = sk_X509_new_null();
+ if (chain == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ }
+
+ X509 *leaf = NULL;
+ for (size_t i = 0; i < num_certs; i++) {
+ X509 *x509 = X509_parse_from_buffer(sk_CRYPTO_BUFFER_value(sess->certs, i));
+ if (x509 == NULL) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+ goto err;
+ }
+ if (!sk_X509_push(chain, x509)) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+ X509_free(x509);
+ goto err;
+ }
+ if (i == 0) {
+ leaf = x509;
+ }
+ }
+
+ sk_X509_pop_free(sess->x509_chain, X509_free);
+ sess->x509_chain = chain;
+ sk_X509_pop_free(sess->x509_chain_without_leaf, X509_free);
+ sess->x509_chain_without_leaf = NULL;
+
+ X509_free(sess->x509_peer);
+ if (leaf != NULL) {
+ X509_up_ref(leaf);
+ }
+ sess->x509_peer = leaf;
+
+ return 1;
+
+err:
+ sk_X509_pop_free(chain, X509_free);
+ return 0;
+}
+
+static int ssl_crypto_x509_session_dup(SSL_SESSION *new_session,
+ const SSL_SESSION *session) {
+ if (session->x509_peer != NULL) {
+ X509_up_ref(session->x509_peer);
+ new_session->x509_peer = session->x509_peer;
+ }
+ if (session->x509_chain != NULL) {
+ new_session->x509_chain = X509_chain_up_ref(session->x509_chain);
+ if (new_session->x509_chain == NULL) {
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+static void ssl_crypto_x509_session_clear(SSL_SESSION *session) {
+ X509_free(session->x509_peer);
+ session->x509_peer = NULL;
+ sk_X509_pop_free(session->x509_chain, X509_free);
+ session->x509_chain = NULL;
+ sk_X509_pop_free(session->x509_chain_without_leaf, X509_free);
+ session->x509_chain_without_leaf = NULL;
+}
+
+const SSL_X509_METHOD ssl_crypto_x509_method = {
+ ssl_crypto_x509_clear,
+ ssl_crypto_x509_flush_cached_chain,
+ ssl_crypto_x509_flush_cached_leaf,
+ ssl_crypto_x509_session_cache_objects,
+ ssl_crypto_x509_session_dup,
+ ssl_crypto_x509_session_clear,
+};
+
+/* x509_to_buffer returns a |CRYPTO_BUFFER| that contains the serialised
+ * contents of |x509|. */
+static CRYPTO_BUFFER *x509_to_buffer(X509 *x509) {
+ uint8_t *buf = NULL;
+ int cert_len = i2d_X509(x509, &buf);
+ if (cert_len <= 0) {
+ return 0;
+ }
+
+ CRYPTO_BUFFER *buffer = CRYPTO_BUFFER_new(buf, cert_len, NULL);
+ OPENSSL_free(buf);
+
+ return buffer;
+}
+
+static int ssl_use_certificate(CERT *cert, X509 *x) {
+ if (x == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
+ CRYPTO_BUFFER *buffer = x509_to_buffer(x);
+ if (buffer == NULL) {
+ return 0;
+ }
+
+ const int ok = ssl_set_cert(cert, buffer);
+ CRYPTO_BUFFER_free(buffer);
+ return ok;
+}
+
+int SSL_use_certificate(SSL *ssl, X509 *x) {
+ return ssl_use_certificate(ssl->cert, x);
+}
+
+int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x) {
+ return ssl_use_certificate(ctx->cert, x);
+}
+
+/* ssl_cert_cache_leaf_cert sets |cert->x509_leaf|, if currently NULL, from the
+ * first element of |cert->chain|. */
+static int ssl_cert_cache_leaf_cert(CERT *cert) {
+ assert(cert->x509_method);
+
+ if (cert->x509_leaf != NULL ||
+ cert->chain == NULL) {
+ return 1;
+ }
+
+ CRYPTO_BUFFER *leaf = sk_CRYPTO_BUFFER_value(cert->chain, 0);
+ if (!leaf) {
+ return 1;
+ }
+
+ cert->x509_leaf = X509_parse_from_buffer(leaf);
+ return cert->x509_leaf != NULL;
+}
+
+static X509 *ssl_cert_get0_leaf(CERT *cert) {
+ if (cert->x509_leaf == NULL &&
+ !ssl_cert_cache_leaf_cert(cert)) {
+ return NULL;
+ }
+
+ return cert->x509_leaf;
+}
+
+X509 *SSL_get_certificate(const SSL *ssl) {
+ return ssl_cert_get0_leaf(ssl->cert);
+}
+
+X509 *SSL_CTX_get0_certificate(const SSL_CTX *ctx) {
+ return ssl_cert_get0_leaf(ctx->cert);
+}
+
+/* new_leafless_chain returns a fresh stack of buffers set to {NULL}. */
+static STACK_OF(CRYPTO_BUFFER) *new_leafless_chain(void) {
+ STACK_OF(CRYPTO_BUFFER) *chain = sk_CRYPTO_BUFFER_new_null();
+ if (chain == NULL) {
+ return NULL;
+ }
+
+ if (!sk_CRYPTO_BUFFER_push(chain, NULL)) {
+ sk_CRYPTO_BUFFER_free(chain);
+ return NULL;
+ }
+
+ return chain;
+}
+
+/* ssl_cert_set_chain sets elements 1.. of |cert->chain| to the serialised
+ * forms of elements of |chain|. It returns one on success or zero on error, in
+ * which case no change to |cert->chain| is made. It preverses the existing
+ * leaf from |cert->chain|, if any. */
+static int ssl_cert_set_chain(CERT *cert, STACK_OF(X509) *chain) {
+ STACK_OF(CRYPTO_BUFFER) *new_chain = NULL;
+
+ if (cert->chain != NULL) {
+ new_chain = sk_CRYPTO_BUFFER_new_null();
+ if (new_chain == NULL) {
+ return 0;
+ }
+
+ CRYPTO_BUFFER *leaf = sk_CRYPTO_BUFFER_value(cert->chain, 0);
+ if (!sk_CRYPTO_BUFFER_push(new_chain, leaf)) {
+ goto err;
+ }
+ /* |leaf| might be NULL if it's a “leafless” chain. */
+ if (leaf != NULL) {
+ CRYPTO_BUFFER_up_ref(leaf);
+ }
+ }
+
+ for (size_t i = 0; i < sk_X509_num(chain); i++) {
+ if (new_chain == NULL) {
+ new_chain = new_leafless_chain();
+ if (new_chain == NULL) {
+ goto err;
+ }
+ }
+
+ CRYPTO_BUFFER *buffer = x509_to_buffer(sk_X509_value(chain, i));
+ if (buffer == NULL ||
+ !sk_CRYPTO_BUFFER_push(new_chain, buffer)) {
+ CRYPTO_BUFFER_free(buffer);
+ goto err;
+ }
+ }
+
+ sk_CRYPTO_BUFFER_pop_free(cert->chain, CRYPTO_BUFFER_free);
+ cert->chain = new_chain;
+
+ return 1;
+
+err:
+ sk_CRYPTO_BUFFER_pop_free(new_chain, CRYPTO_BUFFER_free);
+ return 0;
+}
+
+static int ssl_cert_set0_chain(CERT *cert, STACK_OF(X509) *chain) {
+ if (!ssl_cert_set_chain(cert, chain)) {
+ return 0;
+ }
+
+ sk_X509_pop_free(chain, X509_free);
+ ssl_crypto_x509_flush_cached_chain(cert);
+ return 1;
+}
+
+static int ssl_cert_set1_chain(CERT *cert, STACK_OF(X509) *chain) {
+ if (!ssl_cert_set_chain(cert, chain)) {
+ return 0;
+ }
+
+ ssl_crypto_x509_flush_cached_chain(cert);
+ return 1;
+}
+
+static int ssl_cert_append_cert(CERT *cert, X509 *x509) {
+ assert(cert->x509_method);
+
+ CRYPTO_BUFFER *buffer = x509_to_buffer(x509);
+ if (buffer == NULL) {
+ return 0;
+ }
+
+ if (cert->chain != NULL) {
+ if (!sk_CRYPTO_BUFFER_push(cert->chain, buffer)) {
+ CRYPTO_BUFFER_free(buffer);
+ return 0;
+ }
+
+ return 1;
+ }
+
+ cert->chain = new_leafless_chain();
+ if (cert->chain == NULL ||
+ !sk_CRYPTO_BUFFER_push(cert->chain, buffer)) {
+ CRYPTO_BUFFER_free(buffer);
+ sk_CRYPTO_BUFFER_free(cert->chain);
+ cert->chain = NULL;
+ return 0;
+ }
+
+ return 1;
+}
+
+static int ssl_cert_add0_chain_cert(CERT *cert, X509 *x509) {
+ if (!ssl_cert_append_cert(cert, x509)) {
+ return 0;
+ }
+
+ X509_free(cert->x509_stash);
+ cert->x509_stash = x509;
+ ssl_crypto_x509_flush_cached_chain(cert);
+ return 1;
+}
+
+static int ssl_cert_add1_chain_cert(CERT *cert, X509 *x509) {
+ if (!ssl_cert_append_cert(cert, x509)) {
+ return 0;
+ }
+
+ ssl_crypto_x509_flush_cached_chain(cert);
+ return 1;
+}
+
+int SSL_CTX_set0_chain(SSL_CTX *ctx, STACK_OF(X509) *chain) {
+ return ssl_cert_set0_chain(ctx->cert, chain);
+}
+
+int SSL_CTX_set1_chain(SSL_CTX *ctx, STACK_OF(X509) *chain) {
+ return ssl_cert_set1_chain(ctx->cert, chain);
+}
+
+int SSL_set0_chain(SSL *ssl, STACK_OF(X509) *chain) {
+ return ssl_cert_set0_chain(ssl->cert, chain);
+}
+
+int SSL_set1_chain(SSL *ssl, STACK_OF(X509) *chain) {
+ return ssl_cert_set1_chain(ssl->cert, chain);
+}
+
+int SSL_CTX_add0_chain_cert(SSL_CTX *ctx, X509 *x509) {
+ return ssl_cert_add0_chain_cert(ctx->cert, x509);
+}
+
+int SSL_CTX_add1_chain_cert(SSL_CTX *ctx, X509 *x509) {
+ return ssl_cert_add1_chain_cert(ctx->cert, x509);
+}
+
+int SSL_CTX_add_extra_chain_cert(SSL_CTX *ctx, X509 *x509) {
+ return SSL_CTX_add0_chain_cert(ctx, x509);
+}
+
+int SSL_add0_chain_cert(SSL *ssl, X509 *x509) {
+ return ssl_cert_add0_chain_cert(ssl->cert, x509);
+}
+
+int SSL_add1_chain_cert(SSL *ssl, X509 *x509) {
+ return ssl_cert_add1_chain_cert(ssl->cert, x509);
+}
+
+int SSL_CTX_clear_chain_certs(SSL_CTX *ctx) {
+ return SSL_CTX_set0_chain(ctx, NULL);
+}
+
+int SSL_CTX_clear_extra_chain_certs(SSL_CTX *ctx) {
+ return SSL_CTX_clear_chain_certs(ctx);
+}
+
+int SSL_clear_chain_certs(SSL *ssl) {
+ return SSL_set0_chain(ssl, NULL);
+}
+
+int ssl_auto_chain_if_needed(SSL *ssl) {
+ /* Only build a chain if there are no intermediates configured and the feature
+ * isn't disabled. */
+ if ((ssl->mode & SSL_MODE_NO_AUTO_CHAIN) ||
+ !ssl_has_certificate(ssl) ||
+ ssl->cert->chain == NULL ||
+ sk_CRYPTO_BUFFER_num(ssl->cert->chain) > 1) {
+ return 1;
+ }
+
+ X509 *leaf =
+ X509_parse_from_buffer(sk_CRYPTO_BUFFER_value(ssl->cert->chain, 0));
+ if (!leaf) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_X509_LIB);
+ return 0;
+ }
+
+ X509_STORE_CTX ctx;
+ if (!X509_STORE_CTX_init(&ctx, ssl->ctx->cert_store, leaf, NULL)) {
+ X509_free(leaf);
+ OPENSSL_PUT_ERROR(SSL, ERR_R_X509_LIB);
+ return 0;
+ }
+
+ /* Attempt to build a chain, ignoring the result. */
+ X509_verify_cert(&ctx);
+ X509_free(leaf);
+ ERR_clear_error();
+
+ /* Remove the leaf from the generated chain. */
+ X509_free(sk_X509_shift(ctx.chain));
+
+ const int ok = ssl_cert_set_chain(ssl->cert, ctx.chain);
+ X509_STORE_CTX_cleanup(&ctx);
+ if (!ok) {
+ return 0;
+ }
+
+ ssl_crypto_x509_flush_cached_chain(ssl->cert);
+
+ return 1;
+}
+
+/* ssl_cert_cache_chain_certs fills in |cert->x509_chain| from elements 1.. of
+ * |cert->chain|. */
+static int ssl_cert_cache_chain_certs(CERT *cert) {
+ assert(cert->x509_method);
+
+ if (cert->x509_chain != NULL ||
+ cert->chain == NULL ||
+ sk_CRYPTO_BUFFER_num(cert->chain) < 2) {
+ return 1;
+ }
+
+ STACK_OF(X509) *chain = sk_X509_new_null();
+ if (chain == NULL) {
+ return 0;
+ }
+
+ for (size_t i = 1; i < sk_CRYPTO_BUFFER_num(cert->chain); i++) {
+ CRYPTO_BUFFER *buffer = sk_CRYPTO_BUFFER_value(cert->chain, i);
+ X509 *x509 = X509_parse_from_buffer(buffer);
+ if (x509 == NULL ||
+ !sk_X509_push(chain, x509)) {
+ X509_free(x509);
+ goto err;
+ }
+ }
+
+ cert->x509_chain = chain;
+ return 1;
+
+err:
+ sk_X509_pop_free(chain, X509_free);
+ return 0;
+}
+
+int SSL_CTX_get0_chain_certs(const SSL_CTX *ctx, STACK_OF(X509) **out_chain) {
+ if (!ssl_cert_cache_chain_certs(ctx->cert)) {
+ *out_chain = NULL;
+ return 0;
+ }
+
+ *out_chain = ctx->cert->x509_chain;
+ return 1;
+}
+
+int SSL_CTX_get_extra_chain_certs(const SSL_CTX *ctx,
+ STACK_OF(X509) **out_chain) {
+ return SSL_CTX_get0_chain_certs(ctx, out_chain);
+}
+
+int SSL_get0_chain_certs(const SSL *ssl, STACK_OF(X509) **out_chain) {
+ if (!ssl_cert_cache_chain_certs(ssl->cert)) {
+ *out_chain = NULL;
+ return 0;
+ }
+
+ *out_chain = ssl->cert->x509_chain;
+ return 1;
+}
+
+static SSL_SESSION *ssl_session_new_with_crypto_x509(void) {
+ return ssl_session_new(&ssl_crypto_x509_method);
+}
+
+SSL_SESSION *d2i_SSL_SESSION_bio(BIO *bio, SSL_SESSION **out) {
+ return ASN1_d2i_bio_of(SSL_SESSION, ssl_session_new_with_crypto_x509,
+ d2i_SSL_SESSION, bio, out);
+}
+
+int i2d_SSL_SESSION_bio(BIO *bio, const SSL_SESSION *session) {
+ return ASN1_i2d_bio_of(SSL_SESSION, i2d_SSL_SESSION, bio, session);
+}
+
+IMPLEMENT_PEM_rw(SSL_SESSION, SSL_SESSION, PEM_STRING_SSL_SESSION, SSL_SESSION)
+
+SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a, const uint8_t **pp, long length) {
+ if (length < 0) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+ return NULL;
+ }
+
+ CBS cbs;
+ CBS_init(&cbs, *pp, length);
+
+ SSL_SESSION *ret = SSL_SESSION_parse(&cbs, &ssl_crypto_x509_method,
+ NULL /* no buffer pool */);
+ if (ret == NULL) {
+ return NULL;
+ }
+
+ if (a) {
+ SSL_SESSION_free(*a);
+ *a = ret;
+ }
+ *pp = CBS_data(&cbs);
+ return ret;
+}
diff --git a/src/ssl/t1_enc.c b/src/ssl/t1_enc.c
index 5e5c3483..d01992e7 100644
--- a/src/ssl/t1_enc.c
+++ b/src/ssl/t1_enc.c
@@ -224,18 +224,17 @@ err:
return ret;
}
-static int tls1_prf(const SSL *ssl, uint8_t *out, size_t out_len,
- const uint8_t *secret, size_t secret_len, const char *label,
- size_t label_len, const uint8_t *seed1, size_t seed1_len,
- const uint8_t *seed2, size_t seed2_len) {
+int tls1_prf(const EVP_MD *digest, uint8_t *out, size_t out_len,
+ const uint8_t *secret, size_t secret_len, const char *label,
+ size_t label_len, const uint8_t *seed1, size_t seed1_len,
+ const uint8_t *seed2, size_t seed2_len) {
if (out_len == 0) {
return 1;
}
OPENSSL_memset(out, 0, out_len);
- uint32_t algorithm_prf = ssl_get_algorithm_prf(ssl);
- if (algorithm_prf == SSL_HANDSHAKE_MAC_DEFAULT) {
+ if (digest == EVP_md5_sha1()) {
/* If using the MD5/SHA1 PRF, |secret| is partitioned between SHA-1 and
* MD5, MD5 first. */
size_t secret_half = secret_len - (secret_len / 2);
@@ -248,17 +247,82 @@ static int tls1_prf(const SSL *ssl, uint8_t *out, size_t out_len,
/* Note that, if |secret_len| is odd, the two halves share a byte. */
secret = secret + (secret_len - secret_half);
secret_len = secret_half;
+
+ digest = EVP_sha1();
}
- if (!tls1_P_hash(out, out_len, ssl_get_handshake_digest(algorithm_prf),
- secret, secret_len, (const uint8_t *)label, label_len,
- seed1, seed1_len, seed2, seed2_len)) {
+ if (!tls1_P_hash(out, out_len, digest, secret, secret_len,
+ (const uint8_t *)label, label_len, seed1, seed1_len, seed2,
+ seed2_len)) {
return 0;
}
return 1;
}
+static int ssl3_prf(uint8_t *out, size_t out_len, const uint8_t *secret,
+ size_t secret_len, const char *label, size_t label_len,
+ const uint8_t *seed1, size_t seed1_len,
+ const uint8_t *seed2, size_t seed2_len) {
+ EVP_MD_CTX md5;
+ EVP_MD_CTX sha1;
+ uint8_t buf[16], smd[SHA_DIGEST_LENGTH];
+ uint8_t c = 'A';
+ size_t i, j, k;
+
+ k = 0;
+ EVP_MD_CTX_init(&md5);
+ EVP_MD_CTX_init(&sha1);
+ for (i = 0; i < out_len; i += MD5_DIGEST_LENGTH) {
+ k++;
+ if (k > sizeof(buf)) {
+ /* bug: 'buf' is too small for this ciphersuite */
+ OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ for (j = 0; j < k; j++) {
+ buf[j] = c;
+ }
+ c++;
+ if (!EVP_DigestInit_ex(&sha1, EVP_sha1(), NULL)) {
+ OPENSSL_PUT_ERROR(SSL, ERR_LIB_EVP);
+ return 0;
+ }
+ EVP_DigestUpdate(&sha1, buf, k);
+ EVP_DigestUpdate(&sha1, secret, secret_len);
+ /* |label| is ignored for SSLv3. */
+ if (seed1_len) {
+ EVP_DigestUpdate(&sha1, seed1, seed1_len);
+ }
+ if (seed2_len) {
+ EVP_DigestUpdate(&sha1, seed2, seed2_len);
+ }
+ EVP_DigestFinal_ex(&sha1, smd, NULL);
+
+ if (!EVP_DigestInit_ex(&md5, EVP_md5(), NULL)) {
+ OPENSSL_PUT_ERROR(SSL, ERR_LIB_EVP);
+ return 0;
+ }
+ EVP_DigestUpdate(&md5, secret, secret_len);
+ EVP_DigestUpdate(&md5, smd, SHA_DIGEST_LENGTH);
+ if (i + MD5_DIGEST_LENGTH > out_len) {
+ EVP_DigestFinal_ex(&md5, smd, NULL);
+ OPENSSL_memcpy(out, smd, out_len - i);
+ } else {
+ EVP_DigestFinal_ex(&md5, out, NULL);
+ }
+
+ out += MD5_DIGEST_LENGTH;
+ }
+
+ OPENSSL_cleanse(smd, SHA_DIGEST_LENGTH);
+ EVP_MD_CTX_cleanup(&md5);
+ EVP_MD_CTX_cleanup(&sha1);
+
+ return 1;
+}
+
static int tls1_setup_key_block(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
if (hs->key_block_len != 0) {
@@ -385,112 +449,58 @@ size_t SSL_get_key_block_len(const SSL *ssl) {
}
int SSL_generate_key_block(const SSL *ssl, uint8_t *out, size_t out_len) {
- return ssl->s3->enc_method->prf(
- ssl, out, out_len, SSL_get_session(ssl)->master_key,
- SSL_get_session(ssl)->master_key_length, TLS_MD_KEY_EXPANSION_CONST,
- TLS_MD_KEY_EXPANSION_CONST_SIZE, ssl->s3->server_random, SSL3_RANDOM_SIZE,
- ssl->s3->client_random, SSL3_RANDOM_SIZE);
-}
-
-static int append_digest(const EVP_MD_CTX *ctx, uint8_t *out, size_t *out_len,
- size_t max_out) {
- int ret = 0;
- EVP_MD_CTX ctx_copy;
- EVP_MD_CTX_init(&ctx_copy);
-
- if (EVP_MD_CTX_size(ctx) > max_out) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_BUFFER_TOO_SMALL);
- goto err;
+ if (ssl3_protocol_version(ssl) == SSL3_VERSION) {
+ return ssl3_prf(out, out_len, SSL_get_session(ssl)->master_key,
+ SSL_get_session(ssl)->master_key_length,
+ TLS_MD_KEY_EXPANSION_CONST, TLS_MD_KEY_EXPANSION_CONST_SIZE,
+ ssl->s3->server_random, SSL3_RANDOM_SIZE,
+ ssl->s3->client_random, SSL3_RANDOM_SIZE);
}
- unsigned len;
- if (!EVP_MD_CTX_copy_ex(&ctx_copy, ctx) ||
- !EVP_DigestFinal_ex(&ctx_copy, out, &len)) {
- goto err;
- }
- assert(len == EVP_MD_CTX_size(ctx));
-
- *out_len = len;
- ret = 1;
-
-err:
- EVP_MD_CTX_cleanup(&ctx_copy);
- return ret;
-}
-
-/* tls1_handshake_digest calculates the current handshake hash and writes it to
- * |out|, which has space for |out_len| bytes. It returns the number of bytes
- * written or -1 in the event of an error. This function works on a copy of the
- * underlying digests so can be called multiple times and prior to the final
- * update etc. */
-int tls1_handshake_digest(SSL *ssl, uint8_t *out, size_t out_len) {
- size_t md5_len = 0;
- if (EVP_MD_CTX_md(&ssl->s3->handshake_md5) != NULL &&
- !append_digest(&ssl->s3->handshake_md5, out, &md5_len, out_len)) {
- return -1;
- }
-
- size_t len;
- if (!append_digest(&ssl->s3->handshake_hash, out + md5_len, &len,
- out_len - md5_len)) {
- return -1;
- }
-
- return (int)(md5_len + len);
-}
-static int tls1_final_finish_mac(SSL *ssl, int from_server, uint8_t *out) {
- /* At this point, the handshake should have released the handshake buffer on
- * its own. */
- assert(ssl->s3->handshake_buffer == NULL);
-
- const char *label = TLS_MD_CLIENT_FINISH_CONST;
- size_t label_len = TLS_MD_SERVER_FINISH_CONST_SIZE;
- if (from_server) {
- label = TLS_MD_SERVER_FINISH_CONST;
- label_len = TLS_MD_SERVER_FINISH_CONST_SIZE;
- }
-
- uint8_t buf[EVP_MAX_MD_SIZE];
- int digests_len = tls1_handshake_digest(ssl, buf, sizeof(buf));
- if (digests_len < 0) {
+ const EVP_MD *digest = ssl_get_handshake_digest(
+ SSL_get_session(ssl)->cipher->algorithm_prf, ssl3_protocol_version(ssl));
+ if (digest == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
return 0;
}
-
- static const size_t kFinishedLen = 12;
- if (!ssl->s3->enc_method->prf(ssl, out, kFinishedLen,
- SSL_get_session(ssl)->master_key,
- SSL_get_session(ssl)->master_key_length, label,
- label_len, buf, digests_len, NULL, 0)) {
- return 0;
- }
-
- return (int)kFinishedLen;
+ return tls1_prf(digest, out, out_len, SSL_get_session(ssl)->master_key,
+ SSL_get_session(ssl)->master_key_length,
+ TLS_MD_KEY_EXPANSION_CONST, TLS_MD_KEY_EXPANSION_CONST_SIZE,
+ ssl->s3->server_random, SSL3_RANDOM_SIZE,
+ ssl->s3->client_random, SSL3_RANDOM_SIZE);
}
-int tls1_generate_master_secret(SSL *ssl, uint8_t *out,
+int tls1_generate_master_secret(SSL_HANDSHAKE *hs, uint8_t *out,
const uint8_t *premaster,
size_t premaster_len) {
+ const SSL *ssl = hs->ssl;
if (ssl->s3->tmp.extended_master_secret) {
uint8_t digests[EVP_MAX_MD_SIZE];
- int digests_len = tls1_handshake_digest(ssl, digests, sizeof(digests));
- if (digests_len == -1) {
- return 0;
- }
-
- if (!ssl->s3->enc_method->prf(ssl, out, SSL3_MASTER_SECRET_SIZE, premaster,
- premaster_len,
- TLS_MD_EXTENDED_MASTER_SECRET_CONST,
- TLS_MD_EXTENDED_MASTER_SECRET_CONST_SIZE,
- digests, digests_len, NULL, 0)) {
+ size_t digests_len;
+ if (!SSL_TRANSCRIPT_get_hash(&hs->transcript, digests, &digests_len) ||
+ !tls1_prf(SSL_TRANSCRIPT_md(&hs->transcript), out,
+ SSL3_MASTER_SECRET_SIZE, premaster, premaster_len,
+ TLS_MD_EXTENDED_MASTER_SECRET_CONST,
+ TLS_MD_EXTENDED_MASTER_SECRET_CONST_SIZE, digests,
+ digests_len, NULL, 0)) {
return 0;
}
} else {
- if (!ssl->s3->enc_method->prf(ssl, out, SSL3_MASTER_SECRET_SIZE, premaster,
- premaster_len, TLS_MD_MASTER_SECRET_CONST,
- TLS_MD_MASTER_SECRET_CONST_SIZE,
- ssl->s3->client_random, SSL3_RANDOM_SIZE,
- ssl->s3->server_random, SSL3_RANDOM_SIZE)) {
- return 0;
+ if (ssl3_protocol_version(ssl) == SSL3_VERSION) {
+ if (!ssl3_prf(out, SSL3_MASTER_SECRET_SIZE, premaster, premaster_len,
+ TLS_MD_MASTER_SECRET_CONST, TLS_MD_MASTER_SECRET_CONST_SIZE,
+ ssl->s3->client_random, SSL3_RANDOM_SIZE,
+ ssl->s3->server_random, SSL3_RANDOM_SIZE)) {
+ return 0;
+ }
+ } else {
+ if (!tls1_prf(SSL_TRANSCRIPT_md(&hs->transcript), out,
+ SSL3_MASTER_SECRET_SIZE, premaster, premaster_len,
+ TLS_MD_MASTER_SECRET_CONST, TLS_MD_MASTER_SECRET_CONST_SIZE,
+ ssl->s3->client_random, SSL3_RANDOM_SIZE,
+ ssl->s3->server_random, SSL3_RANDOM_SIZE)) {
+ return 0;
+ }
}
}
@@ -538,16 +548,15 @@ int SSL_export_keying_material(SSL *ssl, uint8_t *out, size_t out_len,
OPENSSL_memcpy(seed + 2 * SSL3_RANDOM_SIZE + 2, context, context_len);
}
- int ret =
- ssl->s3->enc_method->prf(ssl, out, out_len,
- SSL_get_session(ssl)->master_key,
- SSL_get_session(ssl)->master_key_length, label,
- label_len, seed, seed_len, NULL, 0);
+ const EVP_MD *digest = ssl_get_handshake_digest(
+ SSL_get_session(ssl)->cipher->algorithm_prf, ssl3_protocol_version(ssl));
+ if (digest == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ int ret = tls1_prf(digest, out, out_len, SSL_get_session(ssl)->master_key,
+ SSL_get_session(ssl)->master_key_length, label, label_len,
+ seed, seed_len, NULL, 0);
OPENSSL_free(seed);
return ret;
}
-
-const SSL3_ENC_METHOD TLSv1_enc_data = {
- tls1_prf,
- tls1_final_finish_mac,
-};
diff --git a/src/ssl/t1_lib.c b/src/ssl/t1_lib.c
index 8091787a..7723ccd3 100644
--- a/src/ssl/t1_lib.c
+++ b/src/ssl/t1_lib.c
@@ -1371,15 +1371,16 @@ static int ext_sct_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
/* The extension shouldn't be sent when resuming sessions. */
if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION ||
ssl->s3->session_reused ||
- ssl->ctx->signed_cert_timestamp_list_length == 0) {
+ ssl->signed_cert_timestamp_list == NULL) {
return 1;
}
CBB contents;
return CBB_add_u16(out, TLSEXT_TYPE_certificate_timestamp) &&
CBB_add_u16_length_prefixed(out, &contents) &&
- CBB_add_bytes(&contents, ssl->ctx->signed_cert_timestamp_list,
- ssl->ctx->signed_cert_timestamp_list_length) &&
+ CBB_add_bytes(&contents,
+ CRYPTO_BUFFER_data(ssl->signed_cert_timestamp_list),
+ CRYPTO_BUFFER_len(ssl->signed_cert_timestamp_list)) &&
CBB_flush(out);
}
@@ -1882,8 +1883,12 @@ static size_t ext_pre_shared_key_clienthello_length(SSL_HANDSHAKE *hs) {
return 0;
}
- const EVP_MD *digest =
- ssl_get_handshake_digest(ssl->session->cipher->algorithm_prf);
+ const EVP_MD *digest = SSL_SESSION_get_digest(ssl->session, ssl);
+ if (digest == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
size_t binder_len = EVP_MD_size(digest);
return 15 + ssl->session->tlsext_ticklen + binder_len;
}
@@ -1911,8 +1916,13 @@ static int ext_pre_shared_key_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) {
/* Fill in a placeholder zero binder of the appropriate length. It will be
* computed and filled in later after length prefixes are computed. */
uint8_t zero_binder[EVP_MAX_MD_SIZE] = {0};
- const EVP_MD *digest =
- ssl_get_handshake_digest(ssl->session->cipher->algorithm_prf);
+
+ const EVP_MD *digest = SSL_SESSION_get_digest(ssl->session, ssl);
+ if (digest == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
size_t binder_len = EVP_MD_size(digest);
CBB contents, identity, ticket, binders, binder;
@@ -2961,7 +2971,7 @@ static int ssl_scan_clienthello_tlsext(SSL_HANDSHAKE *hs,
int ssl_parse_clienthello_tlsext(SSL_HANDSHAKE *hs,
const SSL_CLIENT_HELLO *client_hello) {
SSL *const ssl = hs->ssl;
- int alert = -1;
+ int alert = SSL_AD_DECODE_ERROR;
if (ssl_scan_clienthello_tlsext(hs, client_hello, &alert) <= 0) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
return 0;
@@ -3084,7 +3094,7 @@ static int ssl_check_clienthello_tlsext(SSL_HANDSHAKE *hs) {
int ssl_parse_serverhello_tlsext(SSL_HANDSHAKE *hs, CBS *cbs) {
SSL *const ssl = hs->ssl;
- int alert = -1;
+ int alert = SSL_AD_DECODE_ERROR;
if (ssl_scan_serverhello_tlsext(hs, cbs, &alert) <= 0) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
return 0;
@@ -3203,7 +3213,8 @@ int tls_process_ticket(SSL *ssl, SSL_SESSION **out_session,
#endif
/* Decode the session. */
- SSL_SESSION *session = SSL_SESSION_from_bytes(plaintext, plaintext_len);
+ SSL_SESSION *session =
+ SSL_SESSION_from_bytes(plaintext, plaintext_len, ssl->ctx);
if (session == NULL) {
ERR_clear_error(); /* Don't leave an error on the queue. */
goto done;
@@ -3324,7 +3335,8 @@ int tls1_choose_signature_algorithm(SSL_HANDSHAKE *hs, uint16_t *out) {
return 0;
}
-int tls1_verify_channel_id(SSL *ssl) {
+int tls1_verify_channel_id(SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
int ret = 0;
uint16_t extension_type;
CBS extension, channel_id;
@@ -3383,7 +3395,7 @@ int tls1_verify_channel_id(SSL *ssl) {
uint8_t digest[EVP_MAX_MD_SIZE];
size_t digest_len;
- if (!tls1_channel_id_hash(ssl, digest, &digest_len)) {
+ if (!tls1_channel_id_hash(hs, digest, &digest_len)) {
goto err;
}
@@ -3412,10 +3424,11 @@ err:
return ret;
}
-int tls1_write_channel_id(SSL *ssl, CBB *cbb) {
+int tls1_write_channel_id(SSL_HANDSHAKE *hs, CBB *cbb) {
+ SSL *const ssl = hs->ssl;
uint8_t digest[EVP_MAX_MD_SIZE];
size_t digest_len;
- if (!tls1_channel_id_hash(ssl, digest, &digest_len)) {
+ if (!tls1_channel_id_hash(hs, digest, &digest_len)) {
return 0;
}
@@ -3461,11 +3474,12 @@ err:
return ret;
}
-int tls1_channel_id_hash(SSL *ssl, uint8_t *out, size_t *out_len) {
+int tls1_channel_id_hash(SSL_HANDSHAKE *hs, uint8_t *out, size_t *out_len) {
+ SSL *const ssl = hs->ssl;
if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION) {
uint8_t *msg;
size_t msg_len;
- if (!tls13_get_cert_verify_signature_input(ssl, &msg, &msg_len,
+ if (!tls13_get_cert_verify_signature_input(hs, &msg, &msg_len,
ssl_cert_verify_channel_id)) {
return 0;
}
@@ -3492,13 +3506,12 @@ int tls1_channel_id_hash(SSL *ssl, uint8_t *out, size_t *out_len) {
ssl->session->original_handshake_hash_len);
}
- uint8_t handshake_hash[EVP_MAX_MD_SIZE];
- int handshake_hash_len = tls1_handshake_digest(ssl, handshake_hash,
- sizeof(handshake_hash));
- if (handshake_hash_len < 0) {
+ uint8_t hs_hash[EVP_MAX_MD_SIZE];
+ size_t hs_hash_len;
+ if (!SSL_TRANSCRIPT_get_hash(&hs->transcript, hs_hash, &hs_hash_len)) {
return 0;
}
- SHA256_Update(&ctx, handshake_hash, (size_t)handshake_hash_len);
+ SHA256_Update(&ctx, hs_hash, (size_t)hs_hash_len);
SHA256_Final(out, &ctx);
*out_len = SHA256_DIGEST_LENGTH;
return 1;
@@ -3507,8 +3520,8 @@ int tls1_channel_id_hash(SSL *ssl, uint8_t *out, size_t *out_len) {
/* tls1_record_handshake_hashes_for_channel_id records the current handshake
* hashes in |ssl->s3->new_session| so that Channel ID resumptions can sign that
* data. */
-int tls1_record_handshake_hashes_for_channel_id(SSL *ssl) {
- int digest_len;
+int tls1_record_handshake_hashes_for_channel_id(SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
/* This function should never be called for a resumed session because the
* handshake hashes that we wish to record are for the original, full
* handshake. */
@@ -3516,15 +3529,18 @@ int tls1_record_handshake_hashes_for_channel_id(SSL *ssl) {
return -1;
}
- digest_len =
- tls1_handshake_digest(
- ssl, ssl->s3->new_session->original_handshake_hash,
- sizeof(ssl->s3->new_session->original_handshake_hash));
- if (digest_len < 0) {
+ OPENSSL_COMPILE_ASSERT(
+ sizeof(ssl->s3->new_session->original_handshake_hash) == EVP_MAX_MD_SIZE,
+ original_handshake_hash_is_too_small);
+
+ size_t digest_len;
+ if (!SSL_TRANSCRIPT_get_hash(&hs->transcript,
+ ssl->s3->new_session->original_handshake_hash,
+ &digest_len)) {
return -1;
}
- assert(sizeof(ssl->s3->new_session->original_handshake_hash) < 256);
+ OPENSSL_COMPILE_ASSERT(EVP_MAX_MD_SIZE <= 0xff, max_md_size_is_too_large);
ssl->s3->new_session->original_handshake_hash_len = (uint8_t)digest_len;
return 1;
diff --git a/src/ssl/test/bssl_shim.cc b/src/ssl/test/bssl_shim.cc
index 66a71a0a..381f4c2f 100644
--- a/src/ssl/test/bssl_shim.cc
+++ b/src/ssl/test/bssl_shim.cc
@@ -1477,7 +1477,7 @@ static bool CheckHandshakeProperties(SSL *ssl, bool is_resume) {
}
if (expected_sha256_client_cert &&
- SSL_get_session(ssl)->x509_peer != nullptr) {
+ SSL_get_session(ssl)->certs != nullptr) {
fprintf(stderr, "Have both client cert and SHA-256 hash: is_resume:%d.\n",
is_resume);
return false;
diff --git a/src/ssl/test/runner/common.go b/src/ssl/test/runner/common.go
index 668f78ce..2e7b0537 100644
--- a/src/ssl/test/runner/common.go
+++ b/src/ssl/test/runner/common.go
@@ -668,9 +668,16 @@ type ProtocolBugs struct {
// ticket before sending it in a resume handshake.
FilterTicket func([]byte) ([]byte, error)
- // OversizedSessionId causes the session id that is sent with a ticket
- // resumption attempt to be too large (33 bytes).
- OversizedSessionId bool
+ // TicketSessionIDLength, if non-zero, is the length of the session ID
+ // to send with a ticket resumption offer.
+ TicketSessionIDLength int
+
+ // EmptyTicketSessionID, if true, causes the client to send an empty
+ // session ID with a ticket resumption offer. For simplicity, this will
+ // also cause the client to interpret a ServerHello with empty session
+ // ID as a resumption. (A client which sends empty session ID is
+ // normally expected to look ahead for ChangeCipherSpec.)
+ EmptyTicketSessionID bool
// ExpectNoTLS12Session, if true, causes the server to fail the
// connection if either a session ID or TLS 1.2 ticket is offered.
@@ -1291,6 +1298,10 @@ type ProtocolBugs struct {
// SendTicketLifetime, if non-zero, is the ticket lifetime to send in
// NewSessionTicket messages.
SendTicketLifetime time.Duration
+
+ // SendServerNameAck, if true, causes the server to acknowledge the SNI
+ // extension.
+ SendServerNameAck bool
}
func (c *Config) serverInit() {
diff --git a/src/ssl/test/runner/handshake_client.go b/src/ssl/test/runner/handshake_client.go
index afc19582..162302e8 100644
--- a/src/ssl/test/runner/handshake_client.go
+++ b/src/ssl/test/runner/handshake_client.go
@@ -289,8 +289,11 @@ NextCipherSuite:
// server accepted the ticket and is resuming a session
// (see RFC 5077).
sessionIdLen := 16
- if c.config.Bugs.OversizedSessionId {
- sessionIdLen = 33
+ if c.config.Bugs.TicketSessionIDLength != 0 {
+ sessionIdLen = c.config.Bugs.TicketSessionIDLength
+ }
+ if c.config.Bugs.EmptyTicketSessionID {
+ sessionIdLen = 0
}
hello.sessionId = make([]byte, sessionIdLen)
if _, err := io.ReadFull(c.config.rand(), hello.sessionId); err != nil {
@@ -860,6 +863,10 @@ func (hs *clientHandshakeState) doTLS13Handshake() error {
hs.finishedHash.addEntropy(zeroSecret)
clientTrafficSecret := hs.finishedHash.deriveSecret(clientApplicationTrafficLabel)
serverTrafficSecret := hs.finishedHash.deriveSecret(serverApplicationTrafficLabel)
+ c.exporterSecret = hs.finishedHash.deriveSecret(exporterLabel)
+
+ // Switch to application data keys on read. In particular, any alerts
+ // from the client certificate are read over these keys.
c.in.useTrafficSecret(c.vers, hs.suite, serverTrafficSecret, serverWrite)
// If we're expecting 0.5-RTT messages from the server, read them
@@ -966,7 +973,6 @@ func (hs *clientHandshakeState) doTLS13Handshake() error {
// Switch to application data keys.
c.out.useTrafficSecret(c.vers, hs.suite, clientTrafficSecret, clientWrite)
- c.exporterSecret = hs.finishedHash.deriveSecret(exporterLabel)
c.resumptionSecret = hs.finishedHash.deriveSecret(resumptionLabel)
return nil
}
@@ -1346,6 +1352,10 @@ func (hs *clientHandshakeState) processServerExtensions(serverExtensions *server
func (hs *clientHandshakeState) serverResumedSession() bool {
// If the server responded with the same sessionId then it means the
// sessionTicket is being used to resume a TLS session.
+ //
+ // Note that, if hs.hello.sessionId is a non-nil empty array, this will
+ // accept an empty session ID from the server as resumption. See
+ // EmptyTicketSessionID.
return hs.session != nil && hs.hello.sessionId != nil &&
bytes.Equal(hs.serverHello.sessionId, hs.hello.sessionId)
}
diff --git a/src/ssl/test/runner/handshake_messages.go b/src/ssl/test/runner/handshake_messages.go
index 1141797c..4ecb3cb2 100644
--- a/src/ssl/test/runner/handshake_messages.go
+++ b/src/ssl/test/runner/handshake_messages.go
@@ -1082,6 +1082,7 @@ type serverExtensions struct {
hasEarlyData bool
keyShare keyShareEntry
supportedPoints []uint8
+ serverNameAck bool
}
func (m *serverExtensions) marshal(extensions *byteBuilder) {
@@ -1187,6 +1188,10 @@ func (m *serverExtensions) marshal(extensions *byteBuilder) {
extensions.addU16(extensionEarlyData)
extensions.addBytes([]byte{0, 0})
}
+ if m.serverNameAck {
+ extensions.addU16(extensionServerName)
+ extensions.addU16(0) // zero length
+ }
}
func (m *serverExtensions) unmarshal(data []byte, version uint16) bool {
@@ -1281,7 +1286,7 @@ func (m *serverExtensions) unmarshal(data []byte, version uint16) bool {
if length != 0 {
return false
}
- // Ignore this extension from the server.
+ m.serverNameAck = true
case extensionSupportedPoints:
// supported_points is illegal in TLS 1.3.
if version >= VersionTLS13 {
diff --git a/src/ssl/test/runner/handshake_server.go b/src/ssl/test/runner/handshake_server.go
index d8ab1a5c..8aa15879 100644
--- a/src/ssl/test/runner/handshake_server.go
+++ b/src/ssl/test/runner/handshake_server.go
@@ -1244,6 +1244,8 @@ func (hs *serverHandshakeState) processClientExtensions(serverExtensions *server
return errors.New("tls: no GREASE extension found")
}
+ serverExtensions.serverNameAck = c.config.Bugs.SendServerNameAck
+
return nil
}
diff --git a/src/ssl/test/runner/runner.go b/src/ssl/test/runner/runner.go
index 8c9278e3..d6e984a0 100644
--- a/src/ssl/test/runner/runner.go
+++ b/src/ssl/test/runner/runner.go
@@ -2290,7 +2290,16 @@ func addBasicTests() {
expectedError: ":WRONG_VERSION_NUMBER:",
},
{
- name: "KeyUpdate",
+ name: "KeyUpdate-Client",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ },
+ sendKeyUpdates: 1,
+ keyUpdateRequest: keyUpdateNotRequested,
+ },
+ {
+ testType: serverTest,
+ name: "KeyUpdate-Server",
config: Config{
MaxVersion: VersionTLS13,
},
@@ -2514,11 +2523,6 @@ func addTestForCipherSuite(suite testCipherSuite, ver tlsVersion, protocol proto
// NULL ciphers must be explicitly enabled.
flags = append(flags, "-cipher", "DEFAULT:NULL-SHA")
}
- if hasComponent(suite.name, "ECDHE-PSK") && hasComponent(suite.name, "GCM") {
- // ECDHE_PSK AES_GCM ciphers must be explicitly enabled
- // for now.
- flags = append(flags, "-cipher", suite.name)
- }
var shouldServerFail, shouldClientFail bool
if hasComponent(suite.name, "ECDHE") && ver.version == VersionSSL30 {
@@ -2558,6 +2562,13 @@ func addTestForCipherSuite(suite testCipherSuite, ver tlsVersion, protocol proto
sendCipherSuite = suite.id
}
+ // For cipher suites and versions where exporters are defined, verify
+ // that they interoperate.
+ var exportKeyingMaterial int
+ if ver.version > VersionSSL30 {
+ exportKeyingMaterial = 1024
+ }
+
testCases = append(testCases, testCase{
testType: serverTest,
protocol: protocol,
@@ -2573,12 +2584,13 @@ func addTestForCipherSuite(suite testCipherSuite, ver tlsVersion, protocol proto
AdvertiseAllConfiguredCiphers: true,
},
},
- certFile: certFile,
- keyFile: keyFile,
- flags: flags,
- resumeSession: true,
- shouldFail: shouldServerFail,
- expectedError: expectedServerError,
+ certFile: certFile,
+ keyFile: keyFile,
+ flags: flags,
+ resumeSession: true,
+ shouldFail: shouldServerFail,
+ expectedError: expectedServerError,
+ exportKeyingMaterial: exportKeyingMaterial,
})
testCases = append(testCases, testCase{
@@ -2597,10 +2609,11 @@ func addTestForCipherSuite(suite testCipherSuite, ver tlsVersion, protocol proto
SendCipherSuite: sendCipherSuite,
},
},
- flags: flags,
- resumeSession: true,
- shouldFail: shouldClientFail,
- expectedError: expectedClientError,
+ flags: flags,
+ resumeSession: true,
+ shouldFail: shouldClientFail,
+ expectedError: expectedClientError,
+ exportKeyingMaterial: exportKeyingMaterial,
})
if shouldClientFail {
@@ -4751,6 +4764,31 @@ func addExtensionTests() {
expectedLocalError: "tls: unexpected server name",
})
testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: "TolerateServerNameAck-" + ver.name,
+ config: Config{
+ MaxVersion: ver.version,
+ Bugs: ProtocolBugs{
+ SendServerNameAck: true,
+ },
+ },
+ flags: []string{"-host-name", "example.com"},
+ resumeSession: true,
+ })
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: "UnsolicitedServerNameAck-" + ver.name,
+ config: Config{
+ MaxVersion: ver.version,
+ Bugs: ProtocolBugs{
+ SendServerNameAck: true,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":UNEXPECTED_EXTENSION:",
+ expectedLocalError: "remote error: unsupported extension",
+ })
+ testCases = append(testCases, testCase{
testType: serverTest,
name: "ServerNameExtensionServer-" + ver.name,
config: Config{
@@ -5015,19 +5053,53 @@ func addExtensionTests() {
},
})
- // Resume with an oversized session id.
+ // Resume with various lengths of ticket session id.
if ver.version < VersionTLS13 {
testCases = append(testCases, testCase{
testType: serverTest,
- name: "OversizedSessionId-" + ver.name,
+ name: "TicketSessionIDLength-0-" + ver.name,
+ config: Config{
+ MaxVersion: ver.version,
+ Bugs: ProtocolBugs{
+ EmptyTicketSessionID: true,
+ },
+ },
+ resumeSession: true,
+ })
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "TicketSessionIDLength-16-" + ver.name,
config: Config{
MaxVersion: ver.version,
Bugs: ProtocolBugs{
- OversizedSessionId: true,
+ TicketSessionIDLength: 16,
+ },
+ },
+ resumeSession: true,
+ })
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "TicketSessionIDLength-32-" + ver.name,
+ config: Config{
+ MaxVersion: ver.version,
+ Bugs: ProtocolBugs{
+ TicketSessionIDLength: 32,
+ },
+ },
+ resumeSession: true,
+ })
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "TicketSessionIDLength-33-" + ver.name,
+ config: Config{
+ MaxVersion: ver.version,
+ Bugs: ProtocolBugs{
+ TicketSessionIDLength: 33,
},
},
resumeSession: true,
shouldFail: true,
+ // The maximum session ID length is 32.
expectedError: ":DECODE_ERROR:",
})
}
@@ -8520,7 +8592,7 @@ func addSessionTicketTests() {
flags: []string{
"-resumption-delay", "21",
},
- resumeSession: true,
+ resumeSession: true,
expectResumeRejected: true,
})
}
diff --git a/src/ssl/tls13_both.c b/src/ssl/tls13_both.c
index a49ee141..19dd555b 100644
--- a/src/ssl/tls13_both.c
+++ b/src/ssl/tls13_both.c
@@ -102,7 +102,7 @@ int tls13_handshake(SSL_HANDSHAKE *hs) {
}
int tls13_get_cert_verify_signature_input(
- SSL *ssl, uint8_t **out, size_t *out_len,
+ SSL_HANDSHAKE *hs, uint8_t **out, size_t *out_len,
enum ssl_cert_verify_context_t cert_verify_context) {
CBB cbb;
if (!CBB_init(&cbb, 64 + 33 + 1 + 2 * EVP_MAX_MD_SIZE)) {
@@ -140,7 +140,8 @@ int tls13_get_cert_verify_signature_input(
uint8_t context_hash[EVP_MAX_MD_SIZE];
size_t context_hash_len;
- if (!tls13_get_context_hash(ssl, context_hash, &context_hash_len) ||
+ if (!SSL_TRANSCRIPT_get_hash(&hs->transcript, context_hash,
+ &context_hash_len) ||
!CBB_add_bytes(&cbb, context_hash, context_hash_len) ||
!CBB_finish(&cbb, out, out_len)) {
goto err;
@@ -232,7 +233,7 @@ int tls13_process_certificate(SSL_HANDSHAKE *hs, int allow_anonymous) {
{TLSEXT_TYPE_certificate_timestamp, &have_sct, &sct},
};
- uint8_t alert;
+ uint8_t alert = SSL_AD_DECODE_ERROR;
if (!ssl_parse_extensions(&extensions, &alert, ext_types,
OPENSSL_ARRAY_SIZE(ext_types),
0 /* reject unknown */)) {
@@ -306,7 +307,7 @@ int tls13_process_certificate(SSL_HANDSHAKE *hs, int allow_anonymous) {
ssl->s3->new_session->certs = certs;
certs = NULL;
- if (!ssl_session_x509_cache_objects(ssl->s3->new_session)) {
+ if (!ssl->ctx->x509_method->session_cache_objects(ssl->s3->new_session)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
goto err;
@@ -372,7 +373,7 @@ int tls13_process_certificate_verify(SSL_HANDSHAKE *hs) {
ssl->s3->new_session->peer_signature_algorithm = signature_algorithm;
if (!tls13_get_cert_verify_signature_input(
- ssl, &msg, &msg_len,
+ hs, &msg, &msg_len,
ssl->server ? ssl_cert_verify_client : ssl_cert_verify_server)) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
goto err;
@@ -451,13 +452,13 @@ int tls13_add_certificate(SSL_HANDSHAKE *hs) {
goto err;
}
- if (hs->scts_requested &&
- ssl->ctx->signed_cert_timestamp_list_length != 0) {
+ if (hs->scts_requested && ssl->signed_cert_timestamp_list != NULL) {
CBB contents;
if (!CBB_add_u16(&extensions, TLSEXT_TYPE_certificate_timestamp) ||
!CBB_add_u16_length_prefixed(&extensions, &contents) ||
- !CBB_add_bytes(&contents, ssl->ctx->signed_cert_timestamp_list,
- ssl->ctx->signed_cert_timestamp_list_length) ||
+ !CBB_add_bytes(&contents,
+ CRYPTO_BUFFER_data(ssl->signed_cert_timestamp_list),
+ CRYPTO_BUFFER_len(ssl->signed_cert_timestamp_list)) ||
!CBB_flush(&extensions)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
goto err;
@@ -536,7 +537,7 @@ enum ssl_private_key_result_t tls13_add_certificate_verify(SSL_HANDSHAKE *hs,
enum ssl_private_key_result_t sign_result;
if (is_first_run) {
if (!tls13_get_cert_verify_signature_input(
- ssl, &msg, &msg_len,
+ hs, &msg, &msg_len,
ssl->server ? ssl_cert_verify_server : ssl_cert_verify_client)) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
goto err;
diff --git a/src/ssl/tls13_client.c b/src/ssl/tls13_client.c
index 74d3646e..50f7e5a6 100644
--- a/src/ssl/tls13_client.c
+++ b/src/ssl/tls13_client.c
@@ -74,7 +74,7 @@ static enum ssl_hs_wait_t do_process_hello_retry_request(SSL_HANDSHAKE *hs) {
{TLSEXT_TYPE_cookie, &have_cookie, &cookie},
};
- uint8_t alert;
+ uint8_t alert = SSL_AD_DECODE_ERROR;
if (!ssl_parse_extensions(&extensions, &alert, ext_types,
OPENSSL_ARRAY_SIZE(ext_types),
0 /* reject unknown */)) {
@@ -135,7 +135,7 @@ static enum ssl_hs_wait_t do_process_hello_retry_request(SSL_HANDSHAKE *hs) {
hs->retry_group = group_id;
}
- if (!ssl_hash_current_message(ssl)) {
+ if (!ssl_hash_current_message(hs)) {
return ssl_hs_error;
}
@@ -207,7 +207,7 @@ static enum ssl_hs_wait_t do_process_server_hello(SSL_HANDSHAKE *hs) {
{TLSEXT_TYPE_short_header, &have_short_header, &short_header},
};
- uint8_t alert;
+ uint8_t alert = SSL_AD_DECODE_ERROR;
if (!ssl_parse_extensions(&extensions, &alert, ext_types,
OPENSSL_ARRAY_SIZE(ext_types),
0 /* reject unknown */)) {
@@ -261,7 +261,7 @@ static enum ssl_hs_wait_t do_process_server_hello(SSL_HANDSHAKE *hs) {
/* Resumption incorporates fresh key material, so refresh the timeout. */
ssl_session_renew_timeout(ssl, ssl->s3->new_session,
- ssl->session_psk_dhe_timeout);
+ ssl->initial_ctx->session_psk_dhe_timeout);
} else if (!ssl_get_new_session(hs, 0)) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
return ssl_hs_error;
@@ -271,8 +271,6 @@ static enum ssl_hs_wait_t do_process_server_hello(SSL_HANDSHAKE *hs) {
ssl->s3->tmp.new_cipher = cipher;
/* The PRF hash is now known. Set up the key schedule. */
- size_t hash_len =
- EVP_MD_size(ssl_get_handshake_digest(ssl_get_algorithm_prf(ssl)));
if (!tls13_init_key_schedule(hs)) {
return ssl_hs_error;
}
@@ -283,7 +281,7 @@ static enum ssl_hs_wait_t do_process_server_hello(SSL_HANDSHAKE *hs) {
ssl->s3->new_session->master_key_length)) {
return ssl_hs_error;
}
- } else if (!tls13_advance_key_schedule(hs, kZeroes, hash_len)) {
+ } else if (!tls13_advance_key_schedule(hs, kZeroes, hs->hash_len)) {
return ssl_hs_error;
}
@@ -297,6 +295,7 @@ static enum ssl_hs_wait_t do_process_server_hello(SSL_HANDSHAKE *hs) {
/* Resolve ECDHE and incorporate it into the secret. */
uint8_t *dhe_secret;
size_t dhe_secret_len;
+ alert = SSL_AD_DECODE_ERROR;
if (!ssl_ext_key_share_parse_serverhello(hs, &dhe_secret, &dhe_secret_len,
&alert, &key_share)) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
@@ -326,7 +325,7 @@ static enum ssl_hs_wait_t do_process_server_hello(SSL_HANDSHAKE *hs) {
ssl->s3->short_header = 1;
}
- if (!ssl_hash_current_message(ssl) ||
+ if (!ssl_hash_current_message(hs) ||
!tls13_derive_handshake_secrets(hs) ||
!tls13_set_traffic_key(ssl, evp_aead_open, hs->server_handshake_secret,
hs->hash_len) ||
@@ -357,7 +356,7 @@ static enum ssl_hs_wait_t do_process_encrypted_extensions(SSL_HANDSHAKE *hs) {
return ssl_hs_error;
}
- if (!ssl_hash_current_message(ssl)) {
+ if (!ssl_hash_current_message(hs)) {
return ssl_hs_error;
}
@@ -392,7 +391,7 @@ static enum ssl_hs_wait_t do_process_certificate_request(SSL_HANDSHAKE *hs) {
return ssl_hs_error;
}
- uint8_t alert;
+ uint8_t alert = SSL_AD_DECODE_ERROR;
STACK_OF(X509_NAME) *ca_sk = ssl_parse_client_CA_list(ssl, &alert, &cbs);
if (ca_sk == NULL) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
@@ -413,7 +412,7 @@ static enum ssl_hs_wait_t do_process_certificate_request(SSL_HANDSHAKE *hs) {
sk_X509_NAME_pop_free(hs->ca_names, X509_NAME_free);
hs->ca_names = ca_sk;
- if (!ssl_hash_current_message(ssl)) {
+ if (!ssl_hash_current_message(hs)) {
return ssl_hs_error;
}
@@ -425,7 +424,7 @@ static enum ssl_hs_wait_t do_process_server_certificate(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
if (!ssl_check_message_type(ssl, SSL3_MT_CERTIFICATE) ||
!tls13_process_certificate(hs, 0 /* certificate required */) ||
- !ssl_hash_current_message(ssl)) {
+ !ssl_hash_current_message(hs)) {
return ssl_hs_error;
}
@@ -438,7 +437,7 @@ static enum ssl_hs_wait_t do_process_server_certificate_verify(
SSL *const ssl = hs->ssl;
if (!ssl_check_message_type(ssl, SSL3_MT_CERTIFICATE_VERIFY) ||
!tls13_process_certificate_verify(hs) ||
- !ssl_hash_current_message(ssl)) {
+ !ssl_hash_current_message(hs)) {
return ssl_hs_error;
}
@@ -450,7 +449,7 @@ static enum ssl_hs_wait_t do_process_server_finished(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
if (!ssl_check_message_type(ssl, SSL3_MT_FINISHED) ||
!tls13_process_finished(hs) ||
- !ssl_hash_current_message(ssl) ||
+ !ssl_hash_current_message(hs) ||
/* Update the secret to the master secret and derive traffic keys. */
!tls13_advance_key_schedule(hs, kZeroes, hs->hash_len) ||
!tls13_derive_application_secrets(hs)) {
@@ -535,7 +534,7 @@ static enum ssl_hs_wait_t do_complete_second_flight(SSL_HANDSHAKE *hs) {
CBB cbb, body;
if (!ssl->method->init_message(ssl, &cbb, &body, SSL3_MT_CHANNEL_ID) ||
- !tls1_write_channel_id(ssl, &body) ||
+ !tls1_write_channel_id(hs, &body) ||
!ssl_add_message_cbb(ssl, &cbb)) {
CBB_cleanup(&cbb);
return ssl_hs_error;
@@ -616,9 +615,8 @@ enum ssl_hs_wait_t tls13_client_handshake(SSL_HANDSHAKE *hs) {
int tls13_process_new_session_ticket(SSL *ssl) {
int ret = 0;
- SSL_SESSION *session =
- SSL_SESSION_dup(ssl->s3->established_session,
- SSL_SESSION_INCLUDE_NONAUTH);
+ SSL_SESSION *session = SSL_SESSION_dup(ssl->s3->established_session,
+ SSL_SESSION_INCLUDE_NONAUTH);
if (session == NULL) {
return 0;
}
@@ -662,7 +660,7 @@ int tls13_process_new_session_ticket(SSL *ssl) {
&early_data_info},
};
- uint8_t alert;
+ uint8_t alert = SSL_AD_DECODE_ERROR;
if (!ssl_parse_extensions(&extensions, &alert, ext_types,
OPENSSL_ARRAY_SIZE(ext_types),
1 /* ignore unknown */)) {
diff --git a/src/ssl/tls13_enc.c b/src/ssl/tls13_enc.c
index ea9dce84..4d140e3c 100644
--- a/src/ssl/tls13_enc.c
+++ b/src/ssl/tls13_enc.c
@@ -29,28 +29,25 @@
int tls13_init_key_schedule(SSL_HANDSHAKE *hs) {
- SSL *const ssl = hs->ssl;
- const EVP_MD *digest = ssl_get_handshake_digest(ssl_get_algorithm_prf(ssl));
+ if (!SSL_TRANSCRIPT_init_hash(&hs->transcript, ssl3_protocol_version(hs->ssl),
+ hs->ssl->s3->tmp.new_cipher->algorithm_prf)) {
+ return 0;
+ }
- hs->hash_len = EVP_MD_size(digest);
+
+ hs->hash_len = SSL_TRANSCRIPT_digest_len(&hs->transcript);
/* Initialize the secret to the zero key. */
OPENSSL_memset(hs->secret, 0, hs->hash_len);
- /* Initialize the rolling hashes and release the handshake buffer. */
- if (!ssl3_init_handshake_hash(ssl)) {
- return 0;
- }
- ssl3_free_handshake_buffer(ssl);
+ SSL_TRANSCRIPT_free_buffer(&hs->transcript);
return 1;
}
int tls13_advance_key_schedule(SSL_HANDSHAKE *hs, const uint8_t *in,
size_t len) {
- const EVP_MD *digest =
- ssl_get_handshake_digest(ssl_get_algorithm_prf(hs->ssl));
-
- return HKDF_extract(hs->secret, &hs->hash_len, digest, in, len, hs->secret,
+ return HKDF_extract(hs->secret, &hs->hash_len,
+ SSL_TRANSCRIPT_md(&hs->transcript), in, len, hs->secret,
hs->hash_len);
}
@@ -83,35 +80,21 @@ static int hkdf_expand_label(uint8_t *out, const EVP_MD *digest,
return ret;
}
-int tls13_get_context_hash(SSL *ssl, uint8_t *out, size_t *out_len) {
- EVP_MD_CTX ctx;
- EVP_MD_CTX_init(&ctx);
- unsigned handshake_len = 0;
- int ok = EVP_MD_CTX_copy_ex(&ctx, &ssl->s3->handshake_hash) &&
- EVP_DigestFinal_ex(&ctx, out, &handshake_len);
- EVP_MD_CTX_cleanup(&ctx);
- if (ok) {
- *out_len = handshake_len;
- }
- return ok;
-}
-
/* derive_secret derives a secret of length |len| and writes the result in |out|
* with the given label and the current base secret and most recently-saved
* handshake context. It returns one on success and zero on error. */
static int derive_secret(SSL_HANDSHAKE *hs, uint8_t *out, size_t len,
const uint8_t *label, size_t label_len) {
- SSL *const ssl = hs->ssl;
- const EVP_MD *digest = ssl_get_handshake_digest(ssl_get_algorithm_prf(ssl));
-
uint8_t context_hash[EVP_MAX_MD_SIZE];
size_t context_hash_len;
- if (!tls13_get_context_hash(ssl, context_hash, &context_hash_len)) {
+ if (!SSL_TRANSCRIPT_get_hash(&hs->transcript, context_hash,
+ &context_hash_len)) {
return 0;
}
- return hkdf_expand_label(out, digest, hs->secret, hs->hash_len, label,
- label_len, context_hash, context_hash_len, len);
+ return hkdf_expand_label(out, SSL_TRANSCRIPT_md(&hs->transcript), hs->secret,
+ hs->hash_len, label, label_len, context_hash,
+ context_hash_len, len);
}
int tls13_set_traffic_key(SSL *ssl, enum evp_aead_direction_t direction,
@@ -124,7 +107,6 @@ int tls13_set_traffic_key(SSL *ssl, enum evp_aead_direction_t direction,
/* Look up cipher suite properties. */
const EVP_AEAD *aead;
- const EVP_MD *digest = ssl_get_handshake_digest(ssl_get_algorithm_prf(ssl));
size_t discard;
if (!ssl_cipher_get_evp_aead(&aead, &discard, &discard,
SSL_get_session(ssl)->cipher,
@@ -132,6 +114,9 @@ int tls13_set_traffic_key(SSL *ssl, enum evp_aead_direction_t direction,
return 0;
}
+ const EVP_MD *digest = ssl_get_handshake_digest(
+ SSL_get_session(ssl)->cipher->algorithm_prf, ssl3_protocol_version(ssl));
+
/* Derive the key. */
size_t key_len = EVP_AEAD_key_length(aead);
uint8_t key[EVP_AEAD_MAX_KEY_LENGTH];
@@ -226,7 +211,8 @@ static const char kTLS13LabelApplicationTraffic[] =
"application traffic secret";
int tls13_rotate_traffic_key(SSL *ssl, enum evp_aead_direction_t direction) {
- const EVP_MD *digest = ssl_get_handshake_digest(ssl_get_algorithm_prf(ssl));
+ const EVP_MD *digest = ssl_get_handshake_digest(
+ SSL_get_session(ssl)->cipher->algorithm_prf, ssl3_protocol_version(ssl));
uint8_t *secret;
size_t secret_len;
@@ -287,7 +273,6 @@ static int tls13_verify_data(const EVP_MD *digest, uint8_t *out,
int tls13_finished_mac(SSL_HANDSHAKE *hs, uint8_t *out, size_t *out_len,
int is_server) {
SSL *const ssl = hs->ssl;
- const EVP_MD *digest = ssl_get_handshake_digest(ssl_get_algorithm_prf(ssl));
const uint8_t *traffic_secret;
if (is_server == ssl->server) {
@@ -298,9 +283,11 @@ int tls13_finished_mac(SSL_HANDSHAKE *hs, uint8_t *out, size_t *out_len,
uint8_t context_hash[EVP_MAX_MD_SIZE];
size_t context_hash_len;
- if (!tls13_get_context_hash(ssl, context_hash, &context_hash_len) ||
- !tls13_verify_data(digest, out, out_len, traffic_secret, hs->hash_len,
- context_hash, context_hash_len)) {
+ if (!SSL_TRANSCRIPT_get_hash(&hs->transcript, context_hash,
+ &context_hash_len) ||
+ !tls13_verify_data(SSL_TRANSCRIPT_md(&hs->transcript), out, out_len,
+ traffic_secret, hs->hash_len, context_hash,
+ context_hash_len)) {
return 0;
}
return 1;
@@ -310,7 +297,8 @@ int tls13_export_keying_material(SSL *ssl, uint8_t *out, size_t out_len,
const char *label, size_t label_len,
const uint8_t *context, size_t context_len,
int use_context) {
- const EVP_MD *digest = ssl_get_handshake_digest(ssl_get_algorithm_prf(ssl));
+ const EVP_MD *digest = ssl_get_handshake_digest(
+ SSL_get_session(ssl)->cipher->algorithm_prf, ssl3_protocol_version(ssl));
const uint8_t *hash = NULL;
size_t hash_len = 0;
@@ -325,8 +313,8 @@ int tls13_export_keying_material(SSL *ssl, uint8_t *out, size_t out_len,
static const char kTLS13LabelPSKBinder[] = "resumption psk binder key";
-static int tls13_psk_binder(SSL *ssl, uint8_t *out, const EVP_MD *digest,
- uint8_t *psk, size_t psk_len, uint8_t *context,
+static int tls13_psk_binder(uint8_t *out, const EVP_MD *digest, uint8_t *psk,
+ size_t psk_len, uint8_t *context,
size_t context_len, size_t hash_len) {
uint8_t binder_context[EVP_MAX_MD_SIZE];
unsigned binder_context_len;
@@ -355,9 +343,13 @@ static int tls13_psk_binder(SSL *ssl, uint8_t *out, const EVP_MD *digest,
return 1;
}
-int tls13_write_psk_binder(SSL *ssl, uint8_t *msg, size_t len) {
- const EVP_MD *digest =
- ssl_get_handshake_digest(ssl->session->cipher->algorithm_prf);
+int tls13_write_psk_binder(SSL_HANDSHAKE *hs, uint8_t *msg, size_t len) {
+ SSL *const ssl = hs->ssl;
+ const EVP_MD *digest = SSL_SESSION_get_digest(ssl->session, ssl);
+ if (digest == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
size_t hash_len = EVP_MD_size(digest);
if (len < hash_len + 3) {
@@ -370,8 +362,8 @@ int tls13_write_psk_binder(SSL *ssl, uint8_t *msg, size_t len) {
uint8_t context[EVP_MAX_MD_SIZE];
unsigned context_len;
if (!EVP_DigestInit_ex(&ctx, digest, NULL) ||
- !EVP_DigestUpdate(&ctx, ssl->s3->handshake_buffer->data,
- ssl->s3->handshake_buffer->length) ||
+ !EVP_DigestUpdate(&ctx, hs->transcript.buffer->data,
+ hs->transcript.buffer->length) ||
!EVP_DigestUpdate(&ctx, msg, len - hash_len - 3) ||
!EVP_DigestFinal_ex(&ctx, context, &context_len)) {
EVP_MD_CTX_cleanup(&ctx);
@@ -381,9 +373,9 @@ int tls13_write_psk_binder(SSL *ssl, uint8_t *msg, size_t len) {
EVP_MD_CTX_cleanup(&ctx);
uint8_t verify_data[EVP_MAX_MD_SIZE] = {0};
- if (!tls13_psk_binder(ssl, verify_data, digest, ssl->session->master_key,
- ssl->session->master_key_length, context,
- context_len, hash_len)) {
+ if (!tls13_psk_binder(verify_data, digest, ssl->session->master_key,
+ ssl->session->master_key_length, context, context_len,
+ hash_len)) {
return 0;
}
@@ -391,16 +383,14 @@ int tls13_write_psk_binder(SSL *ssl, uint8_t *msg, size_t len) {
return 1;
}
-int tls13_verify_psk_binder(SSL *ssl, SSL_SESSION *session,
+int tls13_verify_psk_binder(SSL_HANDSHAKE *hs, SSL_SESSION *session,
CBS *binders) {
- const EVP_MD *digest =
- ssl_get_handshake_digest(session->cipher->algorithm_prf);
- size_t hash_len = EVP_MD_size(digest);
+ size_t hash_len = SSL_TRANSCRIPT_digest_len(&hs->transcript);
/* Get the full ClientHello, including message header. It must be large enough
* to exclude the binders. */
CBS message;
- ssl->method->get_current_message(ssl, &message);
+ hs->ssl->method->get_current_message(hs->ssl, &message);
if (CBS_len(&message) < CBS_len(binders) + 2) {
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
return 0;
@@ -411,23 +401,25 @@ int tls13_verify_psk_binder(SSL *ssl, SSL_SESSION *session,
uint8_t context[EVP_MAX_MD_SIZE];
unsigned context_len;
if (!EVP_Digest(CBS_data(&message), CBS_len(&message) - CBS_len(binders) - 2,
- context, &context_len, digest, NULL)) {
+ context, &context_len, SSL_TRANSCRIPT_md(&hs->transcript),
+ NULL)) {
return 0;
}
uint8_t verify_data[EVP_MAX_MD_SIZE] = {0};
CBS binder;
- if (!tls13_psk_binder(ssl, verify_data, digest, session->master_key,
- session->master_key_length, context, context_len,
- hash_len) ||
+ if (!tls13_psk_binder(verify_data, SSL_TRANSCRIPT_md(&hs->transcript),
+ session->master_key, session->master_key_length,
+ context, context_len, hash_len) ||
/* We only consider the first PSK, so compare against the first binder. */
!CBS_get_u8_length_prefixed(binders, &binder)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
return 0;
}
- int binder_ok = CBS_len(&binder) == hash_len &&
- CRYPTO_memcmp(CBS_data(&binder), verify_data, hash_len) == 0;
+ int binder_ok =
+ CBS_len(&binder) == hash_len &&
+ CRYPTO_memcmp(CBS_data(&binder), verify_data, hash_len) == 0;
#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
binder_ok = 1;
#endif
diff --git a/src/ssl/tls13_server.c b/src/ssl/tls13_server.c
index 319fe4c2..0278b500 100644
--- a/src/ssl/tls13_server.c
+++ b/src/ssl/tls13_server.c
@@ -157,6 +157,14 @@ static enum ssl_hs_wait_t do_select_parameters(SSL_HANDSHAKE *hs) {
return ssl_hs_error;
}
+ /* The PRF hash is now known. Set up the key schedule and hash the
+ * ClientHello. */
+ if (!tls13_init_key_schedule(hs) ||
+ !ssl_hash_current_message(hs)) {
+ return ssl_hs_error;
+ }
+
+
/* Decode the ticket if we agree on a PSK key exchange mode. */
uint8_t alert = SSL_AD_DECODE_ERROR;
SSL_SESSION *session = NULL;
@@ -207,7 +215,7 @@ static enum ssl_hs_wait_t do_select_parameters(SSL_HANDSHAKE *hs) {
}
} else {
/* Check the PSK binder. */
- if (!tls13_verify_psk_binder(ssl, session, &binders)) {
+ if (!tls13_verify_psk_binder(hs, session, &binders)) {
SSL_SESSION_free(session);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECRYPT_ERROR);
return ssl_hs_error;
@@ -224,7 +232,7 @@ static enum ssl_hs_wait_t do_select_parameters(SSL_HANDSHAKE *hs) {
/* Resumption incorporates fresh key material, so refresh the timeout. */
ssl_session_renew_timeout(ssl, ssl->s3->new_session,
- ssl->session_psk_dhe_timeout);
+ ssl->initial_ctx->session_psk_dhe_timeout);
}
if (ssl->ctx->dos_protection_cb != NULL &&
@@ -237,27 +245,19 @@ static enum ssl_hs_wait_t do_select_parameters(SSL_HANDSHAKE *hs) {
/* HTTP/2 negotiation depends on the cipher suite, so ALPN negotiation was
* deferred. Complete it now. */
+ alert = SSL_AD_DECODE_ERROR;
if (!ssl_negotiate_alpn(hs, &alert, &client_hello)) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
return ssl_hs_error;
}
- /* The PRF hash is now known. Set up the key schedule and hash the
- * ClientHello. */
- size_t hash_len =
- EVP_MD_size(ssl_get_handshake_digest(ssl_get_algorithm_prf(ssl)));
- if (!tls13_init_key_schedule(hs) ||
- !ssl_hash_current_message(ssl)) {
- return ssl_hs_error;
- }
-
/* Incorporate the PSK into the running secret. */
if (ssl->s3->session_reused) {
if (!tls13_advance_key_schedule(hs, ssl->s3->new_session->master_key,
ssl->s3->new_session->master_key_length)) {
return ssl_hs_error;
}
- } else if (!tls13_advance_key_schedule(hs, kZeroes, hash_len)) {
+ } else if (!tls13_advance_key_schedule(hs, kZeroes, hs->hash_len)) {
return ssl_hs_error;
}
@@ -322,7 +322,7 @@ static enum ssl_hs_wait_t do_process_second_client_hello(SSL_HANDSHAKE *hs) {
return ssl_hs_error;
}
- if (!ssl_hash_current_message(ssl)) {
+ if (!ssl_hash_current_message(hs)) {
return ssl_hs_error;
}
@@ -484,7 +484,7 @@ static enum ssl_hs_wait_t do_process_client_certificate(SSL_HANDSHAKE *hs) {
if (!ssl_check_message_type(ssl, SSL3_MT_CERTIFICATE) ||
!tls13_process_certificate(hs, allow_anonymous) ||
- !ssl_hash_current_message(ssl)) {
+ !ssl_hash_current_message(hs)) {
return ssl_hs_error;
}
@@ -495,7 +495,7 @@ static enum ssl_hs_wait_t do_process_client_certificate(SSL_HANDSHAKE *hs) {
static enum ssl_hs_wait_t do_process_client_certificate_verify(
SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
- if (ssl->s3->new_session->x509_peer == NULL) {
+ if (sk_CRYPTO_BUFFER_num(ssl->s3->new_session->certs) == 0) {
/* Skip this state. */
hs->tls13_state = state_process_channel_id;
return ssl_hs_ok;
@@ -503,7 +503,7 @@ static enum ssl_hs_wait_t do_process_client_certificate_verify(
if (!ssl_check_message_type(ssl, SSL3_MT_CERTIFICATE_VERIFY) ||
!tls13_process_certificate_verify(hs) ||
- !ssl_hash_current_message(ssl)) {
+ !ssl_hash_current_message(hs)) {
return ssl_hs_error;
}
@@ -512,15 +512,14 @@ static enum ssl_hs_wait_t do_process_client_certificate_verify(
}
static enum ssl_hs_wait_t do_process_channel_id(SSL_HANDSHAKE *hs) {
- SSL *const ssl = hs->ssl;
- if (!ssl->s3->tlsext_channel_id_valid) {
+ if (!hs->ssl->s3->tlsext_channel_id_valid) {
hs->tls13_state = state_process_client_finished;
return ssl_hs_ok;
}
- if (!ssl_check_message_type(ssl, SSL3_MT_CHANNEL_ID) ||
- !tls1_verify_channel_id(ssl) ||
- !ssl_hash_current_message(ssl)) {
+ if (!ssl_check_message_type(hs->ssl, SSL3_MT_CHANNEL_ID) ||
+ !tls1_verify_channel_id(hs) ||
+ !ssl_hash_current_message(hs)) {
return ssl_hs_error;
}
@@ -532,7 +531,7 @@ static enum ssl_hs_wait_t do_process_client_finished(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
if (!ssl_check_message_type(ssl, SSL3_MT_FINISHED) ||
!tls13_process_finished(hs) ||
- !ssl_hash_current_message(ssl) ||
+ !ssl_hash_current_message(hs) ||
/* evp_aead_seal keys have already been switched. */
!tls13_set_traffic_key(ssl, evp_aead_open, hs->client_traffic_secret_0,
hs->hash_len) ||
diff --git a/src/ssl/tls_method.c b/src/ssl/tls_method.c
index 70683e47..eaad2caf 100644
--- a/src/ssl/tls_method.c
+++ b/src/ssl/tls_method.c
@@ -161,6 +161,7 @@ const SSL_METHOD *TLS_method(void) {
static const SSL_METHOD kMethod = {
0,
&kTLSProtocolMethod,
+ &ssl_crypto_x509_method,
};
return &kMethod;
}
@@ -175,6 +176,7 @@ const SSL_METHOD *TLSv1_2_method(void) {
static const SSL_METHOD kMethod = {
TLS1_2_VERSION,
&kTLSProtocolMethod,
+ &ssl_crypto_x509_method,
};
return &kMethod;
}
@@ -183,6 +185,7 @@ const SSL_METHOD *TLSv1_1_method(void) {
static const SSL_METHOD kMethod = {
TLS1_1_VERSION,
&kTLSProtocolMethod,
+ &ssl_crypto_x509_method,
};
return &kMethod;
}
@@ -191,6 +194,7 @@ const SSL_METHOD *TLSv1_method(void) {
static const SSL_METHOD kMethod = {
TLS1_VERSION,
&kTLSProtocolMethod,
+ &ssl_crypto_x509_method,
};
return &kMethod;
}
@@ -199,6 +203,7 @@ const SSL_METHOD *SSLv3_method(void) {
static const SSL_METHOD kMethod = {
SSL3_VERSION,
&kTLSProtocolMethod,
+ &ssl_crypto_x509_method,
};
return &kMethod;
}
@@ -252,3 +257,24 @@ const SSL_METHOD *TLS_server_method(void) {
const SSL_METHOD *TLS_client_method(void) {
return TLS_method();
}
+
+static void ssl_noop_x509_clear(CERT *cert) {}
+static void ssl_noop_x509_flush_cached_leaf(CERT *cert) {}
+static void ssl_noop_x509_flush_cached_chain(CERT *cert) {}
+static int ssl_noop_x509_session_cache_objects(SSL_SESSION *sess) {
+ return 1;
+}
+static int ssl_noop_x509_session_dup(SSL_SESSION *new_session,
+ const SSL_SESSION *session) {
+ return 1;
+}
+static void ssl_noop_x509_session_clear(SSL_SESSION *session) {}
+
+const SSL_X509_METHOD ssl_noop_x509_method = {
+ ssl_noop_x509_clear,
+ ssl_noop_x509_flush_cached_chain,
+ ssl_noop_x509_flush_cached_leaf,
+ ssl_noop_x509_session_cache_objects,
+ ssl_noop_x509_session_dup,
+ ssl_noop_x509_session_clear,
+};
diff --git a/src/tool/client.cc b/src/tool/client.cc
index 0301a816..8e0ef2d0 100644
--- a/src/tool/client.cc
+++ b/src/tool/client.cc
@@ -282,16 +282,16 @@ bool Client(const std::vector<std::string> &args) {
return false;
}
- if (args_map.count("-max-version") != 0) {
- uint16_t version;
- if (!VersionFromString(&version, args_map["-max-version"])) {
- fprintf(stderr, "Unknown protocol version: '%s'\n",
- args_map["-max-version"].c_str());
- return false;
- }
- if (!SSL_CTX_set_max_proto_version(ctx.get(), version)) {
- return false;
- }
+ uint16_t max_version = TLS1_3_VERSION;
+ if (args_map.count("-max-version") != 0 &&
+ !VersionFromString(&max_version, args_map["-max-version"])) {
+ fprintf(stderr, "Unknown protocol version: '%s'\n",
+ args_map["-max-version"].c_str());
+ return false;
+ }
+
+ if (!SSL_CTX_set_max_proto_version(ctx.get(), max_version)) {
+ return false;
}
if (args_map.count("-min-version") != 0) {
diff --git a/src/tool/server.cc b/src/tool/server.cc
index 94abbbd9..f203df12 100644
--- a/src/tool/server.cc
+++ b/src/tool/server.cc
@@ -193,16 +193,16 @@ bool Server(const std::vector<std::string> &args) {
return false;
}
- if (args_map.count("-max-version") != 0) {
- uint16_t version;
- if (!VersionFromString(&version, args_map["-max-version"])) {
- fprintf(stderr, "Unknown protocol version: '%s'\n",
- args_map["-max-version"].c_str());
- return false;
- }
- if (!SSL_CTX_set_max_proto_version(ctx.get(), version)) {
- return false;
- }
+ uint16_t max_version = TLS1_3_VERSION;
+ if (args_map.count("-max-version") != 0 &&
+ !VersionFromString(&max_version, args_map["-max-version"])) {
+ fprintf(stderr, "Unknown protocol version: '%s'\n",
+ args_map["-max-version"].c_str());
+ return false;
+ }
+
+ if (!SSL_CTX_set_max_proto_version(ctx.get(), max_version)) {
+ return false;
}
if (args_map.count("-min-version") != 0) {
diff --git a/src/util/all_tests.go b/src/util/all_tests.go
index d4bb8023..3cf23206 100644
--- a/src/util/all_tests.go
+++ b/src/util/all_tests.go
@@ -186,10 +186,9 @@ func runTestOnce(test test, mallocNumToFail int64) (passed bool, err error) {
} else {
cmd = exec.Command(prog, args...)
}
- var stdoutBuf bytes.Buffer
- var stderrBuf bytes.Buffer
- cmd.Stdout = &stdoutBuf
- cmd.Stderr = &stderrBuf
+ var outBuf bytes.Buffer
+ cmd.Stdout = &outBuf
+ cmd.Stderr = &outBuf
if mallocNumToFail >= 0 {
cmd.Env = os.Environ()
cmd.Env = append(cmd.Env, "MALLOC_NUMBER_TO_FAIL="+strconv.FormatInt(mallocNumToFail, 10))
@@ -208,13 +207,12 @@ func runTestOnce(test test, mallocNumToFail int64) (passed bool, err error) {
return false, errMoreMallocs
}
}
- fmt.Print(string(stderrBuf.Bytes()))
+ fmt.Print(string(outBuf.Bytes()))
return false, err
}
- fmt.Print(string(stderrBuf.Bytes()))
// Account for Windows line-endings.
- stdout := bytes.Replace(stdoutBuf.Bytes(), []byte("\r\n"), []byte("\n"), -1)
+ stdout := bytes.Replace(outBuf.Bytes(), []byte("\r\n"), []byte("\n"), -1)
if bytes.HasSuffix(stdout, []byte("PASS\n")) &&
(len(stdout) == 5 || stdout[len(stdout)-6] == '\n') {
@@ -228,6 +226,7 @@ func runTestOnce(test test, mallocNumToFail int64) (passed bool, err error) {
return true, nil
}
+ fmt.Print(string(outBuf.Bytes()))
return false, nil
}
diff --git a/src/util/all_tests.json b/src/util/all_tests.json
index 4589ee76..76637b2c 100644
--- a/src/util/all_tests.json
+++ b/src/util/all_tests.json
@@ -40,7 +40,6 @@
["crypto/ecdsa/ecdsa_sign_test", "crypto/ecdsa/ecdsa_sign_tests.txt"],
["crypto/ecdsa/ecdsa_test"],
["crypto/ecdsa/ecdsa_verify_test", "crypto/ecdsa/ecdsa_verify_tests.txt"],
- ["crypto/err/err_test"],
["crypto/evp/evp_extra_test"],
["crypto/evp/evp_test", "crypto/evp/evp_tests.txt"],
["crypto/evp/pbkdf_test"],