summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTorne (Richard Coles) <torne@google.com>2014-11-06 11:12:36 +0000
committerTorne (Richard Coles) <torne@google.com>2014-11-06 11:12:36 +0000
commitda0d1461616a796a3ec17ab0bde246e5620204d6 (patch)
tree30766ced8c56a5366f45459127f3c5901c95d367
parente0833bdba5638aea2a64fc7cbada60f29ccf8aae (diff)
parent03d1abe83d2d93223668f4de58a32ee4cc484ed5 (diff)
downloadsrc-master-soong.tar.gz
Merge from Chromium at DEPS revision db3f05efe0f9android-m-previewmaster-soong
This commit was generated by merge_to_master.py. Change-Id: Ia542726d5df7935b2f79e8de6880d101853bb4c9
-rw-r--r--BUILDING5
-rw-r--r--CMakeLists.txt1
-rw-r--r--crypto/CMakeLists.txt13
-rw-r--r--crypto/asn1/asn1_locl.h22
-rw-r--r--crypto/bio/CMakeLists.txt3
-rw-r--r--crypto/bn/asm/x86_64-gcc.c2
-rw-r--r--crypto/bn/generic.c25
-rw-r--r--crypto/bn/internal.h2
-rw-r--r--crypto/bytestring/bytestring_test.c190
-rw-r--r--crypto/bytestring/cbb.c36
-rw-r--r--crypto/bytestring/cbs.c88
-rw-r--r--crypto/err/err.c1
-rw-r--r--crypto/evp/CMakeLists.txt6
-rw-r--r--crypto/evp/asn1.c3
-rw-r--r--crypto/evp/digestsign.c15
-rw-r--r--crypto/evp/evp_test.c (renamed from crypto/evp/example_sign.c)181
-rw-r--r--crypto/evp/internal.h4
-rw-r--r--crypto/evp/p_rsa_asn1.c6
-rw-r--r--crypto/evp/sign.c11
-rw-r--r--crypto/perlasm/x86asm.pl4
-rw-r--r--crypto/perlasm/x86masm.pl7
-rw-r--r--crypto/perlasm/x86nasm.pl8
-rw-r--r--crypto/rand/windows.c57
-rw-r--r--crypto/x509/x_crl.c18
-rw-r--r--crypto/x509v3/v3nametest.c4
-rw-r--r--include/openssl/base.h1
-rw-r--r--include/openssl/bytestring.h39
-rw-r--r--include/openssl/dtls1.h9
-rw-r--r--include/openssl/err.h2
-rw-r--r--include/openssl/evp.h9
-rw-r--r--include/openssl/srtp.h56
-rw-r--r--include/openssl/ssl.h91
-rw-r--r--include/openssl/ssl3.h9
-rw-r--r--include/openssl/tls1.h5
-rw-r--r--include/openssl/x509.h4
-rw-r--r--ssl/d1_both.c24
-rw-r--r--ssl/d1_enc.c31
-rw-r--r--ssl/d1_lib.c31
-rw-r--r--ssl/d1_pkt.c90
-rw-r--r--ssl/d1_srtp.c30
-rw-r--r--ssl/d1_srvr.c2
-rw-r--r--ssl/s3_both.c20
-rw-r--r--ssl/s3_clnt.c295
-rw-r--r--ssl/s3_enc.c14
-rw-r--r--ssl/s3_lib.c18
-rw-r--r--ssl/s3_pkt.c37
-rw-r--r--ssl/s3_srvr.c124
-rw-r--r--ssl/ssl_asn1.c1050
-rw-r--r--ssl/ssl_ciph.c17
-rw-r--r--ssl/ssl_error.c7
-rw-r--r--ssl/ssl_lib.c48
-rw-r--r--ssl/ssl_locl.h29
-rw-r--r--ssl/ssl_test.c55
-rw-r--r--ssl/t1_enc.c147
-rw-r--r--ssl/t1_lib.c56
-rw-r--r--ssl/test/bssl_shim.cc84
-rw-r--r--ssl/test/runner/cipher_suites.go35
-rw-r--r--ssl/test/runner/common.go66
-rw-r--r--ssl/test/runner/conn.go78
-rw-r--r--ssl/test/runner/handshake_client.go162
-rw-r--r--ssl/test/runner/handshake_messages.go160
-rw-r--r--ssl/test/runner/handshake_server.go47
-rw-r--r--ssl/test/runner/key_agreement.go198
-rw-r--r--ssl/test/runner/prf.go48
-rw-r--r--ssl/test/runner/recordingconn.go130
-rw-r--r--ssl/test/runner/runner.go257
-rw-r--r--ssl/test/runner/ticket.go30
-rw-r--r--ssl/test/test_config.cc9
-rw-r--r--ssl/test/test_config.h4
-rw-r--r--tool/CMakeLists.txt2
-rw-r--r--tool/client.cc13
-rw-r--r--tool/pkcs12.cc14
-rw-r--r--tool/tool.cc4
-rw-r--r--util/all_tests.sh2
74 files changed, 2823 insertions, 1582 deletions
diff --git a/BUILDING b/BUILDING
index ee6b0ab..cf239e9 100644
--- a/BUILDING
+++ b/BUILDING
@@ -25,4 +25,9 @@ BORINGSSL_IMPLEMENTATION. On Windows, where functions need to be tagged with
BORINGSSL_SHARED_LIBRARY defined in the code which #includes the BoringSSL
headers.
+To build on Windows, Yasm[2] is required for assembly. Either ensure yasm.exe
+is in %PATH% or configure CMAKE_ASM_NASM_COMPILER appropriately. Note that
+full Windows support is still in progress.
+
[1] http://martine.github.io/ninja/
+[2] http://yasm.tortall.net/
diff --git a/CMakeLists.txt b/CMakeLists.txt
index add0c1a..bdfaee4 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -8,6 +8,7 @@ if(CMAKE_COMPILER_IS_GNUCXX OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
elseif(MSVC)
# Disable warnings for implicit integer narrowing.
set(CMAKE_C_FLAGS "/wd4267")
+ set(CMAKE_CXX_FLAGS "/wd4267")
endif()
add_definitions(-DBORINGSSL_IMPLEMENTATION)
diff --git a/crypto/CMakeLists.txt b/crypto/CMakeLists.txt
index 5d656ec..d820e82 100644
--- a/crypto/CMakeLists.txt
+++ b/crypto/CMakeLists.txt
@@ -10,14 +10,16 @@ elseif(UNIX)
enable_language(ASM)
else()
if (CMAKE_CL_64)
- message("Using masm")
- set(PERLASM_STYLE masm)
+ message("Using nasm")
+ set(PERLASM_STYLE nasm)
else()
message("Using win32n")
set(PERLASM_STYLE win32n)
endif()
+
+ # On Windows, we use the NASM output, specifically built with Yasm.
set(ASM_EXT asm)
- enable_language(ASM_MASM)
+ enable_language(ASM_NASM)
endif()
function(perlasm dest src)
@@ -27,9 +29,10 @@ function(perlasm dest src)
DEPENDS
${src}
${PROJECT_SOURCE_DIR}/crypto/perlasm/x86_64-xlate.pl
- ${PROJECT_SOURCE_DIR}/crypto/perlasm/x86gas.pl
- ${PROJECT_SOURCE_DIR}/crypto/perlasm/x86asm.pl
${PROJECT_SOURCE_DIR}/crypto/perlasm/x86asm.pl
+ ${PROJECT_SOURCE_DIR}/crypto/perlasm/x86gas.pl
+ ${PROJECT_SOURCE_DIR}/crypto/perlasm/x86masm.pl
+ ${PROJECT_SOURCE_DIR}/crypto/perlasm/x86nasm.pl
WORKING_DIRECTORY .
)
endfunction()
diff --git a/crypto/asn1/asn1_locl.h b/crypto/asn1/asn1_locl.h
index 1444390..ca5f612 100644
--- a/crypto/asn1/asn1_locl.h
+++ b/crypto/asn1/asn1_locl.h
@@ -71,25 +71,3 @@ struct asn1_pctx_st
unsigned long oid_flags;
unsigned long str_flags;
} /* ASN1_PCTX */;
-
-/* ASN1 public key method structure */
-
-
-/* Method to handle CRL access.
- * In general a CRL could be very large (several Mb) and can consume large
- * amounts of resources if stored in memory by multiple processes.
- * This method allows general CRL operations to be redirected to more
- * efficient callbacks: for example a CRL entry database.
- */
-
-#define X509_CRL_METHOD_DYNAMIC 1
-
-struct x509_crl_method_st
- {
- int flags;
- int (*crl_init)(X509_CRL *crl);
- int (*crl_free)(X509_CRL *crl);
- int (*crl_lookup)(X509_CRL *crl, X509_REVOKED **ret,
- ASN1_INTEGER *ser, X509_NAME *issuer);
- int (*crl_verify)(X509_CRL *crl, EVP_PKEY *pk);
- };
diff --git a/crypto/bio/CMakeLists.txt b/crypto/bio/CMakeLists.txt
index 86092f0..9178931 100644
--- a/crypto/bio/CMakeLists.txt
+++ b/crypto/bio/CMakeLists.txt
@@ -26,3 +26,6 @@ add_executable(
)
target_link_libraries(bio_test crypto)
+if (WIN32)
+ target_link_libraries(bio_test ws2_32)
+endif()
diff --git a/crypto/bn/asm/x86_64-gcc.c b/crypto/bn/asm/x86_64-gcc.c
index be119aa..1de0f42 100644
--- a/crypto/bn/asm/x86_64-gcc.c
+++ b/crypto/bn/asm/x86_64-gcc.c
@@ -56,6 +56,8 @@
* machine.
*/
+ /* TODO(davidben): Get this file working on Windows x64. */
+
#undef mul
#undef mul_add
diff --git a/crypto/bn/generic.c b/crypto/bn/generic.c
index b745750..53b5ce1 100644
--- a/crypto/bn/generic.c
+++ b/crypto/bn/generic.c
@@ -61,8 +61,13 @@
#include "internal.h"
-#if defined(OPENSSL_WINDOWS) || defined(OPENSSL_NO_ASM) || \
- (!defined(OPENSSL_X86_64) && !defined(OPENSSL_X86))
+/* Generic implementations of most operations are needed for:
+ * - Configurations without inline assembly.
+ * - Architectures other than x86 or x86_64.
+ * - Windows x84_64; x86_64-gcc.c does not build on MSVC. */
+#if defined(OPENSSL_NO_ASM) || \
+ (!defined(OPENSSL_X86_64) && !defined(OPENSSL_X86)) || \
+ (defined(OPENSSL_X86_64) && defined(OPENSSL_WINDOWS))
#if defined(OPENSSL_WINDOWS)
#define alloca _alloca
@@ -817,9 +822,9 @@ BN_ULONG bn_sub_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
#endif /* !BN_LLONG */
void bn_mul_comba8(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b) {
-#ifdef BN_LLONG
+#if defined(BN_LLONG)
BN_ULLONG t;
-#else
+#elif !defined(BN_UMULT_LOHI) && !defined(BN_UMULT_HIGH)
BN_ULONG bl, bh;
#endif
BN_ULONG t1, t2;
@@ -925,9 +930,9 @@ void bn_mul_comba8(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b) {
}
void bn_mul_comba4(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b) {
-#ifdef BN_LLONG
+#if defined(BN_LLONG)
BN_ULLONG t;
-#else
+#elif !defined(BN_UMULT_LOHI) && !defined(BN_UMULT_HIGH)
BN_ULONG bl, bh;
#endif
BN_ULONG t1, t2;
@@ -969,9 +974,9 @@ void bn_mul_comba4(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b) {
}
void bn_sqr_comba8(BN_ULONG *r, const BN_ULONG *a) {
-#ifdef BN_LLONG
+#if defined(BN_LLONG)
BN_ULLONG t, tt;
-#else
+#elif !defined(BN_UMULT_LOHI) && !defined(BN_UMULT_HIGH)
BN_ULONG bl, bh;
#endif
BN_ULONG t1, t2;
@@ -1049,9 +1054,9 @@ void bn_sqr_comba8(BN_ULONG *r, const BN_ULONG *a) {
}
void bn_sqr_comba4(BN_ULONG *r, const BN_ULONG *a) {
-#ifdef BN_LLONG
+#if defined(BN_LLONG)
BN_ULLONG t, tt;
-#else
+#elif !defined(BN_UMULT_LOHI) && !defined(BN_UMULT_HIGH)
BN_ULONG bl, bh;
#endif
BN_ULONG t1, t2;
diff --git a/crypto/bn/internal.h b/crypto/bn/internal.h
index 88ab547..ab09c6e 100644
--- a/crypto/bn/internal.h
+++ b/crypto/bn/internal.h
@@ -138,7 +138,6 @@ BIGNUM *bn_expand(BIGNUM *bn, unsigned bits);
#if defined(OPENSSL_64_BIT)
#define BN_ULLONG unsigned long long
-#define BN_LONG long
#define BN_BITS 128
#define BN_BYTES 8
#define BN_BITS4 32
@@ -158,7 +157,6 @@ BIGNUM *bn_expand(BIGNUM *bn, unsigned bits);
#define BN_ULLONG unsigned long long
#define BN_MASK (0xffffffffffffffffLL)
-#define BN_LONG int32_t
#define BN_BITS 64
#define BN_BYTES 4
#define BN_BITS4 16
diff --git a/crypto/bytestring/bytestring_test.c b/crypto/bytestring/bytestring_test.c
index f30179d..ba70bcf 100644
--- a/crypto/bytestring/bytestring_test.c
+++ b/crypto/bytestring/bytestring_test.c
@@ -19,6 +19,7 @@
#include <openssl/bytestring.h>
#include "internal.h"
+#include "../internal.h"
static int test_skip(void) {
@@ -105,8 +106,14 @@ static int test_get_asn1(void) {
static const uint8_t kData3[] = {0x30, 0x80};
static const uint8_t kData4[] = {0x30, 0x81, 1, 1};
static const uint8_t kData5[] = {0x30, 0x82, 0, 1, 1};
+ static const uint8_t kData6[] = {0xa1, 3, 0x4, 1, 1};
+ static const uint8_t kData7[] = {0xa1, 3, 0x4, 2, 1};
+ static const uint8_t kData8[] = {0xa1, 3, 0x2, 1, 1};
+ static const uint8_t kData9[] = {0xa1, 3, 0x2, 1, 0xff};
CBS data, contents;
+ int present;
+ uint64_t value;
CBS_init(&data, kData1, sizeof(kData1));
if (CBS_peek_asn1_tag(&data, 0x1) ||
@@ -150,10 +157,106 @@ static int test_get_asn1(void) {
}
CBS_init(&data, NULL, 0);
+ /* peek at empty data. */
if (CBS_peek_asn1_tag(&data, 0x30)) {
return 0;
}
+ CBS_init(&data, NULL, 0);
+ /* optional elements at empty data. */
+ if (!CBS_get_optional_asn1(&data, &contents, &present, 0xa0) ||
+ present ||
+ !CBS_get_optional_asn1_octet_string(&data, &contents, &present, 0xa0) ||
+ present ||
+ CBS_len(&contents) != 0 ||
+ !CBS_get_optional_asn1_octet_string(&data, &contents, NULL, 0xa0) ||
+ CBS_len(&contents) != 0 ||
+ !CBS_get_optional_asn1_uint64(&data, &value, 0xa0, 42) ||
+ value != 42) {
+ return 0;
+ }
+
+ CBS_init(&data, kData6, sizeof(kData6));
+ /* optional element. */
+ if (!CBS_get_optional_asn1(&data, &contents, &present, 0xa0) ||
+ present ||
+ !CBS_get_optional_asn1(&data, &contents, &present, 0xa1) ||
+ !present ||
+ CBS_len(&contents) != 3 ||
+ memcmp(CBS_data(&contents), "\x04\x01\x01", 3) != 0) {
+ return 0;
+ }
+
+ CBS_init(&data, kData6, sizeof(kData6));
+ /* optional octet string. */
+ if (!CBS_get_optional_asn1_octet_string(&data, &contents, &present, 0xa0) ||
+ present ||
+ CBS_len(&contents) != 0 ||
+ !CBS_get_optional_asn1_octet_string(&data, &contents, &present, 0xa1) ||
+ !present ||
+ CBS_len(&contents) != 1 ||
+ CBS_data(&contents)[0] != 1) {
+ return 0;
+ }
+
+ CBS_init(&data, kData7, sizeof(kData7));
+ /* invalid optional octet string. */
+ if (CBS_get_optional_asn1_octet_string(&data, &contents, &present, 0xa1)) {
+ return 0;
+ }
+
+ CBS_init(&data, kData8, sizeof(kData8));
+ /* optional octet string. */
+ if (!CBS_get_optional_asn1_uint64(&data, &value, 0xa0, 42) ||
+ value != 42 ||
+ !CBS_get_optional_asn1_uint64(&data, &value, 0xa1, 42) ||
+ value != 1) {
+ return 0;
+ }
+
+ CBS_init(&data, kData9, sizeof(kData9));
+ /* invalid optional integer. */
+ if (CBS_get_optional_asn1_uint64(&data, &value, 0xa1, 42)) {
+ return 0;
+ }
+
+ return 1;
+}
+
+static int test_get_optional_asn1_bool(void) {
+ CBS data;
+ int val;
+
+ static const uint8_t kTrue[] = {0x0a, 3, CBS_ASN1_BOOLEAN, 1, 0xff};
+ static const uint8_t kFalse[] = {0x0a, 3, CBS_ASN1_BOOLEAN, 1, 0x00};
+ static const uint8_t kInvalid[] = {0x0a, 3, CBS_ASN1_BOOLEAN, 1, 0x01};
+
+ CBS_init(&data, NULL, 0);
+ val = 2;
+ if (!CBS_get_optional_asn1_bool(&data, &val, 0x0a, 0) ||
+ val != 0) {
+ return 0;
+ }
+
+ CBS_init(&data, kTrue, sizeof(kTrue));
+ val = 2;
+ if (!CBS_get_optional_asn1_bool(&data, &val, 0x0a, 0) ||
+ val != 1) {
+ return 0;
+ }
+
+ CBS_init(&data, kFalse, sizeof(kFalse));
+ val = 2;
+ if (!CBS_get_optional_asn1_bool(&data, &val, 0x0a, 1) ||
+ val != 0) {
+ return 0;
+ }
+
+ CBS_init(&data, kInvalid, sizeof(kInvalid));
+ if (CBS_get_optional_asn1_bool(&data, &val, 0x0a, 1)) {
+ return 0;
+ }
+
return 1;
}
@@ -443,6 +546,89 @@ static int test_ber_convert(void) {
sizeof(kNSSBER));
}
+typedef struct {
+ uint64_t value;
+ const char *encoding;
+ size_t encoding_len;
+} ASN1_UINT64_TEST;
+
+static const ASN1_UINT64_TEST kAsn1Uint64Tests[] = {
+ {0, "\x02\x01\x00", 3},
+ {1, "\x02\x01\x01", 3},
+ {127, "\x02\x01\x7f", 3},
+ {128, "\x02\x02\x00\x80", 4},
+ {0xdeadbeef, "\x02\x05\x00\xde\xad\xbe\xef", 7},
+ {OPENSSL_U64(0x0102030405060708),
+ "\x02\x08\x01\x02\x03\x04\x05\x06\x07\x08", 10},
+ {OPENSSL_U64(0xffffffffffffffff),
+ "\x02\x09\x00\xff\xff\xff\xff\xff\xff\xff\xff", 11},
+};
+
+typedef struct {
+ const char *encoding;
+ size_t encoding_len;
+} ASN1_INVALID_UINT64_TEST;
+
+static const ASN1_INVALID_UINT64_TEST kAsn1InvalidUint64Tests[] = {
+ /* Bad tag. */
+ {"\x03\x01\x00", 3},
+ /* Empty contents. */
+ {"\x02\x00", 2},
+ /* Negative number. */
+ {"\x02\x01\x80", 3},
+ /* Overflow */
+ {"\x02\x09\x01\x00\x00\x00\x00\x00\x00\x00\x00", 11},
+};
+
+static int test_asn1_uint64(void) {
+ size_t i;
+
+ for (i = 0; i < sizeof(kAsn1Uint64Tests) / sizeof(kAsn1Uint64Tests[0]); i++) {
+ const ASN1_UINT64_TEST *test = &kAsn1Uint64Tests[i];
+ CBS cbs;
+ uint64_t value;
+ CBB cbb;
+ uint8_t *out;
+ size_t len;
+
+ CBS_init(&cbs, (const uint8_t *)test->encoding, test->encoding_len);
+ if (!CBS_get_asn1_uint64(&cbs, &value) ||
+ CBS_len(&cbs) != 0 ||
+ value != test->value) {
+ return 0;
+ }
+
+ if (!CBB_init(&cbb, 0)) {
+ return 0;
+ }
+ if (!CBB_add_asn1_uint64(&cbb, test->value) ||
+ !CBB_finish(&cbb, &out, &len)) {
+ CBB_cleanup(&cbb);
+ return 0;
+ }
+ if (len != test->encoding_len || memcmp(out, test->encoding, len) != 0) {
+ free(out);
+ return 0;
+ }
+ free(out);
+ }
+
+ for (i = 0;
+ i < sizeof(kAsn1InvalidUint64Tests) / sizeof(kAsn1InvalidUint64Tests[0]);
+ i++) {
+ const ASN1_INVALID_UINT64_TEST *test = &kAsn1InvalidUint64Tests[i];
+ CBS cbs;
+ uint64_t value;
+
+ CBS_init(&cbs, (const uint8_t *)test->encoding, test->encoding_len);
+ if (CBS_get_asn1_uint64(&cbs, &value)) {
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
int main(void) {
CRYPTO_library_init();
@@ -457,7 +643,9 @@ int main(void) {
!test_cbb_misuse() ||
!test_cbb_prefixed() ||
!test_cbb_asn1() ||
- !test_ber_convert()) {
+ !test_ber_convert() ||
+ !test_asn1_uint64() ||
+ !test_get_optional_asn1_bool()) {
return 1;
}
diff --git a/crypto/bytestring/cbb.c b/crypto/bytestring/cbb.c
index 6767b9d..f8e1070 100644
--- a/crypto/bytestring/cbb.c
+++ b/crypto/bytestring/cbb.c
@@ -336,3 +336,39 @@ int CBB_add_u24(CBB *cbb, uint32_t value) {
return cbb_buffer_add_u(cbb->base, value, 3);
}
+
+int CBB_add_asn1_uint64(CBB *cbb, uint64_t value) {
+ CBB child;
+ size_t i;
+ int started = 0;
+
+ if (!CBB_add_asn1(cbb, &child, CBS_ASN1_INTEGER)) {
+ return 0;
+ }
+
+ for (i = 0; i < 8; i++) {
+ uint8_t byte = (value >> 8*(7-i)) & 0xff;
+ if (!started) {
+ if (byte == 0) {
+ /* Don't encode leading zeros. */
+ continue;
+ }
+ /* If the high bit is set, add a padding byte to make it
+ * unsigned. */
+ if ((byte & 0x80) && !CBB_add_u8(&child, 0)) {
+ return 0;
+ }
+ started = 1;
+ }
+ if (!CBB_add_u8(&child, byte)) {
+ return 0;
+ }
+ }
+
+ /* 0 is encoded as a single 0, not the empty string. */
+ if (!started && !CBB_add_u8(&child, 0)) {
+ return 0;
+ }
+
+ return CBB_flush(cbb);
+}
diff --git a/crypto/bytestring/cbs.c b/crypto/bytestring/cbs.c
index 07cc126..b417716 100644
--- a/crypto/bytestring/cbs.c
+++ b/crypto/bytestring/cbs.c
@@ -284,7 +284,12 @@ int CBS_get_asn1_uint64(CBS *cbs, uint64_t *out) {
data = CBS_data(&bytes);
len = CBS_len(&bytes);
- if (len > 0 && (data[0] & 0x80) != 0) {
+ if (len == 0) {
+ /* An INTEGER is encoded with at least one octet. */
+ return 0;
+ }
+
+ if ((data[0] & 0x80) != 0) {
/* negative number */
return 0;
}
@@ -300,3 +305,84 @@ int CBS_get_asn1_uint64(CBS *cbs, uint64_t *out) {
return 1;
}
+
+int CBS_get_optional_asn1(CBS *cbs, CBS *out, int *out_present, unsigned tag) {
+ if (CBS_peek_asn1_tag(cbs, tag)) {
+ if (!CBS_get_asn1(cbs, out, tag)) {
+ return 0;
+ }
+ *out_present = 1;
+ } else {
+ *out_present = 0;
+ }
+ return 1;
+}
+
+int CBS_get_optional_asn1_octet_string(CBS *cbs, CBS *out, int *out_present,
+ unsigned tag) {
+ CBS child;
+ int present;
+ if (!CBS_get_optional_asn1(cbs, &child, &present, tag)) {
+ return 0;
+ }
+ if (present) {
+ if (!CBS_get_asn1(&child, out, CBS_ASN1_OCTETSTRING) ||
+ CBS_len(&child) != 0) {
+ return 0;
+ }
+ } else {
+ CBS_init(out, NULL, 0);
+ }
+ if (out_present) {
+ *out_present = present;
+ }
+ return 1;
+}
+
+int CBS_get_optional_asn1_uint64(CBS *cbs, uint64_t *out, unsigned tag,
+ uint64_t default_value) {
+ CBS child;
+ int present;
+ if (!CBS_get_optional_asn1(cbs, &child, &present, tag)) {
+ return 0;
+ }
+ if (present) {
+ if (!CBS_get_asn1_uint64(&child, out) ||
+ CBS_len(&child) != 0) {
+ return 0;
+ }
+ } else {
+ *out = default_value;
+ }
+ return 1;
+}
+
+int CBS_get_optional_asn1_bool(CBS *cbs, int *out, unsigned tag,
+ int default_value) {
+ CBS child, child2;
+ int present;
+ if (!CBS_get_optional_asn1(cbs, &child, &present, tag)) {
+ return 0;
+ }
+ if (present) {
+ uint8_t boolean;
+
+ if (!CBS_get_asn1(&child, &child2, CBS_ASN1_BOOLEAN) ||
+ CBS_len(&child2) != 1 ||
+ CBS_len(&child) != 0) {
+ return 0;
+ }
+
+ boolean = CBS_data(&child2)[0];
+ if (boolean == 0) {
+ *out = 0;
+ } else if (boolean == 0xff) {
+ *out = 1;
+ } else {
+ return 0;
+ }
+ } else {
+ *out = default_value;
+ }
+ return 1;
+}
diff --git a/crypto/err/err.c b/crypto/err/err.c
index 3c5ea99..d0425d8 100644
--- a/crypto/err/err.c
+++ b/crypto/err/err.c
@@ -645,7 +645,6 @@ static const char *const kLibraryNames[ERR_NUM_LIBS] = {
"PKCS7 routines", /* ERR_LIB_PKCS7 */
"PKCS8 routines", /* ERR_LIB_PKCS8 */
"X509 V3 routines", /* ERR_LIB_X509V3 */
- "PKCS12 routines", /* ERR_LIB_PKCS12 */
"random number generator", /* ERR_LIB_RAND */
"ENGINE routines", /* ERR_LIB_ENGINE */
"OCSP routines", /* ERR_LIB_OCSP */
diff --git a/crypto/evp/CMakeLists.txt b/crypto/evp/CMakeLists.txt
index 43e351a..dc1734c 100644
--- a/crypto/evp/CMakeLists.txt
+++ b/crypto/evp/CMakeLists.txt
@@ -23,9 +23,9 @@ add_library(
add_executable(
- example_sign
+ evp_test
- example_sign.c
+ evp_test.c
)
-target_link_libraries(example_sign crypto)
+target_link_libraries(evp_test crypto)
diff --git a/crypto/evp/asn1.c b/crypto/evp/asn1.c
index 50bdb06..27ae017 100644
--- a/crypto/evp/asn1.c
+++ b/crypto/evp/asn1.c
@@ -128,9 +128,6 @@ EVP_PKEY *d2i_AutoPrivateKey(EVP_PKEY **out, const uint8_t **inp, long len) {
} else if (sk_ASN1_TYPE_num(inkey) == 4) {
keytype = EVP_PKEY_EC;
} else if (sk_ASN1_TYPE_num(inkey) == 3) {
- OPENSSL_PUT_ERROR(EVP, d2i_AutoPrivateKey, EVP_R_UNSUPPORTED_PUBLIC_KEY_TYPE);
- return 0;
-
/* This seems to be PKCS8, not traditional format */
PKCS8_PRIV_KEY_INFO *p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, inp, len);
EVP_PKEY *ret;
diff --git a/crypto/evp/digestsign.c b/crypto/evp/digestsign.c
index 08968ed..c86b805 100644
--- a/crypto/evp/digestsign.c
+++ b/crypto/evp/digestsign.c
@@ -168,22 +168,15 @@ int EVP_DigestSignFinal(EVP_MD_CTX *ctx, uint8_t *out_sig,
if (has_signctx || !r) {
return r;
}
- if (EVP_PKEY_sign(ctx->pctx, out_sig, out_sig_len, md, mdlen) <= 0) {
- return 0;
- }
+ return EVP_PKEY_sign(ctx->pctx, out_sig, out_sig_len, md, mdlen);
} else {
if (has_signctx) {
- if (ctx->pctx->pmeth->signctx(ctx->pctx, out_sig, out_sig_len, ctx) <= 0) {
- return 0;
- }
+ return ctx->pctx->pmeth->signctx(ctx->pctx, out_sig, out_sig_len, ctx);
} else {
size_t s = EVP_MD_size(ctx->digest);
- if (EVP_PKEY_sign(ctx->pctx, out_sig, out_sig_len, NULL, s) <= 0) {
- return 0;
- }
+ return EVP_PKEY_sign(ctx->pctx, out_sig, out_sig_len, NULL, s);
}
}
- return 1;
}
int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const uint8_t *sig,
@@ -196,7 +189,7 @@ int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const uint8_t *sig,
EVP_MD_CTX_init(&tmp_ctx);
if (!EVP_MD_CTX_copy_ex(&tmp_ctx, ctx)) {
- return -1;
+ return 0;
}
if (has_verifyctx) {
r = tmp_ctx.pctx->pmeth->verifyctx(tmp_ctx.pctx, sig, sig_len, &tmp_ctx);
diff --git a/crypto/evp/example_sign.c b/crypto/evp/evp_test.c
index 42a19ec..670df37 100644
--- a/crypto/evp/example_sign.c
+++ b/crypto/evp/evp_test.c
@@ -155,6 +155,80 @@ static const uint8_t kExamplePSSCert[] = {
0x8c, 0x16,
};
+/* kExampleRSAKeyPKCS8 is kExampleRSAKeyDER encoded in a PKCS #8
+ * PrivateKeyInfo. */
+static const uint8_t kExampleRSAKeyPKCS8[] = {
+ 0x30, 0x82, 0x02, 0x76, 0x02, 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a,
+ 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82,
+ 0x02, 0x60, 0x30, 0x82, 0x02, 0x5c, 0x02, 0x01, 0x00, 0x02, 0x81, 0x81,
+ 0x00, 0xf8, 0xb8, 0x6c, 0x83, 0xb4, 0xbc, 0xd9, 0xa8, 0x57, 0xc0, 0xa5,
+ 0xb4, 0x59, 0x76, 0x8c, 0x54, 0x1d, 0x79, 0xeb, 0x22, 0x52, 0x04, 0x7e,
+ 0xd3, 0x37, 0xeb, 0x41, 0xfd, 0x83, 0xf9, 0xf0, 0xa6, 0x85, 0x15, 0x34,
+ 0x75, 0x71, 0x5a, 0x84, 0xa8, 0x3c, 0xd2, 0xef, 0x5a, 0x4e, 0xd3, 0xde,
+ 0x97, 0x8a, 0xdd, 0xff, 0xbb, 0xcf, 0x0a, 0xaa, 0x86, 0x92, 0xbe, 0xb8,
+ 0x50, 0xe4, 0xcd, 0x6f, 0x80, 0x33, 0x30, 0x76, 0x13, 0x8f, 0xca, 0x7b,
+ 0xdc, 0xec, 0x5a, 0xca, 0x63, 0xc7, 0x03, 0x25, 0xef, 0xa8, 0x8a, 0x83,
+ 0x58, 0x76, 0x20, 0xfa, 0x16, 0x77, 0xd7, 0x79, 0x92, 0x63, 0x01, 0x48,
+ 0x1a, 0xd8, 0x7b, 0x67, 0xf1, 0x52, 0x55, 0x49, 0x4e, 0xd6, 0x6e, 0x4a,
+ 0x5c, 0xd7, 0x7a, 0x37, 0x36, 0x0c, 0xde, 0xdd, 0x8f, 0x44, 0xe8, 0xc2,
+ 0xa7, 0x2c, 0x2b, 0xb5, 0xaf, 0x64, 0x4b, 0x61, 0x07, 0x02, 0x03, 0x01,
+ 0x00, 0x01, 0x02, 0x81, 0x80, 0x74, 0x88, 0x64, 0x3f, 0x69, 0x45, 0x3a,
+ 0x6d, 0xc7, 0x7f, 0xb9, 0xa3, 0xc0, 0x6e, 0xec, 0xdc, 0xd4, 0x5a, 0xb5,
+ 0x32, 0x85, 0x5f, 0x19, 0xd4, 0xf8, 0xd4, 0x3f, 0x3c, 0xfa, 0xc2, 0xf6,
+ 0x5f, 0xee, 0xe6, 0xba, 0x87, 0x74, 0x2e, 0xc7, 0x0c, 0xd4, 0x42, 0xb8,
+ 0x66, 0x85, 0x9c, 0x7b, 0x24, 0x61, 0xaa, 0x16, 0x11, 0xf6, 0xb5, 0xb6,
+ 0xa4, 0x0a, 0xc9, 0x55, 0x2e, 0x81, 0xa5, 0x47, 0x61, 0xcb, 0x25, 0x8f,
+ 0xc2, 0x15, 0x7b, 0x0e, 0x7c, 0x36, 0x9f, 0x3a, 0xda, 0x58, 0x86, 0x1c,
+ 0x5b, 0x83, 0x79, 0xe6, 0x2b, 0xcc, 0xe6, 0xfa, 0x2c, 0x61, 0xf2, 0x78,
+ 0x80, 0x1b, 0xe2, 0xf3, 0x9d, 0x39, 0x2b, 0x65, 0x57, 0x91, 0x3d, 0x71,
+ 0x99, 0x73, 0xa5, 0xc2, 0x79, 0x20, 0x8c, 0x07, 0x4f, 0xe5, 0xb4, 0x60,
+ 0x1f, 0x99, 0xa2, 0xb1, 0x4f, 0x0c, 0xef, 0xbc, 0x59, 0x53, 0x00, 0x7d,
+ 0xb1, 0x02, 0x41, 0x00, 0xfc, 0x7e, 0x23, 0x65, 0x70, 0xf8, 0xce, 0xd3,
+ 0x40, 0x41, 0x80, 0x6a, 0x1d, 0x01, 0xd6, 0x01, 0xff, 0xb6, 0x1b, 0x3d,
+ 0x3d, 0x59, 0x09, 0x33, 0x79, 0xc0, 0x4f, 0xde, 0x96, 0x27, 0x4b, 0x18,
+ 0xc6, 0xd9, 0x78, 0xf1, 0xf4, 0x35, 0x46, 0xe9, 0x7c, 0x42, 0x7a, 0x5d,
+ 0x9f, 0xef, 0x54, 0xb8, 0xf7, 0x9f, 0xc4, 0x33, 0x6c, 0xf3, 0x8c, 0x32,
+ 0x46, 0x87, 0x67, 0x30, 0x7b, 0xa7, 0xac, 0xe3, 0x02, 0x41, 0x00, 0xfc,
+ 0x2c, 0xdf, 0x0c, 0x0d, 0x88, 0xf5, 0xb1, 0x92, 0xa8, 0x93, 0x47, 0x63,
+ 0x55, 0xf5, 0xca, 0x58, 0x43, 0xba, 0x1c, 0xe5, 0x9e, 0xb6, 0x95, 0x05,
+ 0xcd, 0xb5, 0x82, 0xdf, 0xeb, 0x04, 0x53, 0x9d, 0xbd, 0xc2, 0x38, 0x16,
+ 0xb3, 0x62, 0xdd, 0xa1, 0x46, 0xdb, 0x6d, 0x97, 0x93, 0x9f, 0x8a, 0xc3,
+ 0x9b, 0x64, 0x7e, 0x42, 0xe3, 0x32, 0x57, 0x19, 0x1b, 0xd5, 0x6e, 0x85,
+ 0xfa, 0xb8, 0x8d, 0x02, 0x41, 0x00, 0xbc, 0x3d, 0xde, 0x6d, 0xd6, 0x97,
+ 0xe8, 0xba, 0x9e, 0x81, 0x37, 0x17, 0xe5, 0xa0, 0x64, 0xc9, 0x00, 0xb7,
+ 0xe7, 0xfe, 0xf4, 0x29, 0xd9, 0x2e, 0x43, 0x6b, 0x19, 0x20, 0xbd, 0x99,
+ 0x75, 0xe7, 0x76, 0xf8, 0xd3, 0xae, 0xaf, 0x7e, 0xb8, 0xeb, 0x81, 0xf4,
+ 0x9d, 0xfe, 0x07, 0x2b, 0x0b, 0x63, 0x0b, 0x5a, 0x55, 0x90, 0x71, 0x7d,
+ 0xf1, 0xdb, 0xd9, 0xb1, 0x41, 0x41, 0x68, 0x2f, 0x4e, 0x39, 0x02, 0x40,
+ 0x5a, 0x34, 0x66, 0xd8, 0xf5, 0xe2, 0x7f, 0x18, 0xb5, 0x00, 0x6e, 0x26,
+ 0x84, 0x27, 0x14, 0x93, 0xfb, 0xfc, 0xc6, 0x0f, 0x5e, 0x27, 0xe6, 0xe1,
+ 0xe9, 0xc0, 0x8a, 0xe4, 0x34, 0xda, 0xe9, 0xa2, 0x4b, 0x73, 0xbc, 0x8c,
+ 0xb9, 0xba, 0x13, 0x6c, 0x7a, 0x2b, 0x51, 0x84, 0xa3, 0x4a, 0xe0, 0x30,
+ 0x10, 0x06, 0x7e, 0xed, 0x17, 0x5a, 0x14, 0x00, 0xc9, 0xef, 0x85, 0xea,
+ 0x52, 0x2c, 0xbc, 0x65, 0x02, 0x40, 0x51, 0xe3, 0xf2, 0x83, 0x19, 0x9b,
+ 0xc4, 0x1e, 0x2f, 0x50, 0x3d, 0xdf, 0x5a, 0xa2, 0x18, 0xca, 0x5f, 0x2e,
+ 0x49, 0xaf, 0x6f, 0xcc, 0xfa, 0x65, 0x77, 0x94, 0xb5, 0xa1, 0x0a, 0xa9,
+ 0xd1, 0x8a, 0x39, 0x37, 0xf4, 0x0b, 0xa0, 0xd7, 0x82, 0x27, 0x5e, 0xae,
+ 0x17, 0x17, 0xa1, 0x1e, 0x54, 0x34, 0xbf, 0x6e, 0xc4, 0x8e, 0x99, 0x5d,
+ 0x08, 0xf1, 0x2d, 0x86, 0x9d, 0xa5, 0x20, 0x1b, 0xe5, 0xdf,
+};
+
+/* kExampleECKeyDER is a sample EC private key encoded as an ECPrivateKey
+ * structure. */
+static const uint8_t kExampleECKeyDER[] = {
+ 0x30, 0x77, 0x02, 0x01, 0x01, 0x04, 0x20, 0x07, 0x0f, 0x08, 0x72, 0x7a,
+ 0xd4, 0xa0, 0x4a, 0x9c, 0xdd, 0x59, 0xc9, 0x4d, 0x89, 0x68, 0x77, 0x08,
+ 0xb5, 0x6f, 0xc9, 0x5d, 0x30, 0x77, 0x0e, 0xe8, 0xd1, 0xc9, 0xce, 0x0a,
+ 0x8b, 0xb4, 0x6a, 0xa0, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d,
+ 0x03, 0x01, 0x07, 0xa1, 0x44, 0x03, 0x42, 0x00, 0x04, 0xe6, 0x2b, 0x69,
+ 0xe2, 0xbf, 0x65, 0x9f, 0x97, 0xbe, 0x2f, 0x1e, 0x0d, 0x94, 0x8a, 0x4c,
+ 0xd5, 0x97, 0x6b, 0xb7, 0xa9, 0x1e, 0x0d, 0x46, 0xfb, 0xdd, 0xa9, 0xa9,
+ 0x1e, 0x9d, 0xdc, 0xba, 0x5a, 0x01, 0xe7, 0xd6, 0x97, 0xa8, 0x0a, 0x18,
+ 0xf9, 0xc3, 0xc4, 0xa3, 0x1e, 0x56, 0xe2, 0x7c, 0x83, 0x48, 0xdb, 0x16,
+ 0x1a, 0x1c, 0xf5, 0x1d, 0x7e, 0xf1, 0x94, 0x2d, 0x4b, 0xcf, 0x72, 0x22,
+ 0xc1,
+};
+
static EVP_PKEY *load_example_rsa_key(void) {
EVP_PKEY *ret = NULL;
const uint8_t *derp = kExampleRSAKeyDER;
@@ -184,7 +258,7 @@ out:
return ret;
}
-static int example_EVP_DigestSignInit(void) {
+static int test_EVP_DigestSignInit(void) {
int ret = 0;
EVP_PKEY *pkey = NULL;
uint8_t *sig = NULL;
@@ -196,12 +270,12 @@ static int example_EVP_DigestSignInit(void) {
pkey = load_example_rsa_key();
if (pkey == NULL ||
- EVP_DigestSignInit(&md_ctx, NULL, EVP_sha256(), NULL, pkey) != 1 ||
- EVP_DigestSignUpdate(&md_ctx, kMsg, sizeof(kMsg)) != 1) {
+ !EVP_DigestSignInit(&md_ctx, NULL, EVP_sha256(), NULL, pkey) ||
+ !EVP_DigestSignUpdate(&md_ctx, kMsg, sizeof(kMsg))) {
goto out;
}
/* Determine the size of the signature. */
- if (EVP_DigestSignFinal(&md_ctx, NULL, &sig_len) != 1) {
+ if (!EVP_DigestSignFinal(&md_ctx, NULL, &sig_len)) {
goto out;
}
/* Sanity check for testing. */
@@ -211,14 +285,14 @@ static int example_EVP_DigestSignInit(void) {
}
sig = malloc(sig_len);
- if (sig == NULL || EVP_DigestSignFinal(&md_ctx, sig, &sig_len) != 1) {
+ if (sig == NULL || !EVP_DigestSignFinal(&md_ctx, sig, &sig_len)) {
goto out;
}
/* Ensure that the signature round-trips. */
- if (EVP_DigestVerifyInit(&md_ctx_verify, NULL, EVP_sha256(), NULL, pkey) != 1 ||
- EVP_DigestVerifyUpdate(&md_ctx_verify, kMsg, sizeof(kMsg)) != 1 ||
- EVP_DigestVerifyFinal(&md_ctx_verify, sig, sig_len) != 1) {
+ if (!EVP_DigestVerifyInit(&md_ctx_verify, NULL, EVP_sha256(), NULL, pkey) ||
+ !EVP_DigestVerifyUpdate(&md_ctx_verify, kMsg, sizeof(kMsg)) ||
+ !EVP_DigestVerifyFinal(&md_ctx_verify, sig, sig_len)) {
goto out;
}
@@ -241,7 +315,7 @@ out:
return ret;
}
-static int example_EVP_DigestVerifyInit(void) {
+static int test_EVP_DigestVerifyInit(void) {
int ret = 0;
EVP_PKEY *pkey = NULL;
EVP_MD_CTX md_ctx;
@@ -250,9 +324,9 @@ static int example_EVP_DigestVerifyInit(void) {
pkey = load_example_rsa_key();
if (pkey == NULL ||
- EVP_DigestVerifyInit(&md_ctx, NULL, EVP_sha256(), NULL, pkey) != 1 ||
- EVP_DigestVerifyUpdate(&md_ctx, kMsg, sizeof(kMsg)) != 1 ||
- EVP_DigestVerifyFinal(&md_ctx, kSignature, sizeof(kSignature)) != 1) {
+ !EVP_DigestVerifyInit(&md_ctx, NULL, EVP_sha256(), NULL, pkey) ||
+ !EVP_DigestVerifyUpdate(&md_ctx, kMsg, sizeof(kMsg)) ||
+ !EVP_DigestVerifyFinal(&md_ctx, kSignature, sizeof(kSignature))) {
goto out;
}
ret = 1;
@@ -282,7 +356,7 @@ static int test_algorithm_roundtrip(EVP_MD_CTX *md_ctx, EVP_PKEY *pkey) {
EVP_MD_CTX_init(&md_ctx_verify);
- if (EVP_DigestSignUpdate(md_ctx, kMsg, sizeof(kMsg)) != 1) {
+ if (!EVP_DigestSignUpdate(md_ctx, kMsg, sizeof(kMsg))) {
goto out;
}
@@ -293,7 +367,7 @@ static int test_algorithm_roundtrip(EVP_MD_CTX *md_ctx, EVP_PKEY *pkey) {
}
/* Determine the size of the signature. */
- if (EVP_DigestSignFinal(md_ctx, NULL, &sig_len) != 1) {
+ if (!EVP_DigestSignFinal(md_ctx, NULL, &sig_len)) {
goto out;
}
/* Sanity check for testing. */
@@ -303,14 +377,14 @@ static int test_algorithm_roundtrip(EVP_MD_CTX *md_ctx, EVP_PKEY *pkey) {
}
sig = malloc(sig_len);
- if (sig == NULL || EVP_DigestSignFinal(md_ctx, sig, &sig_len) != 1) {
+ if (sig == NULL || !EVP_DigestSignFinal(md_ctx, sig, &sig_len)) {
goto out;
}
/* Ensure that the signature round-trips. */
- if (EVP_DigestVerifyInitFromAlgorithm(&md_ctx_verify, algor, pkey) != 1 ||
- EVP_DigestVerifyUpdate(&md_ctx_verify, kMsg, sizeof(kMsg)) != 1 ||
- EVP_DigestVerifyFinal(&md_ctx_verify, sig, sig_len) != 1) {
+ if (!EVP_DigestVerifyInitFromAlgorithm(&md_ctx_verify, algor, pkey) ||
+ !EVP_DigestVerifyUpdate(&md_ctx_verify, kMsg, sizeof(kMsg)) ||
+ !EVP_DigestVerifyFinal(&md_ctx_verify, sig, sig_len)) {
goto out;
}
@@ -342,7 +416,7 @@ static int test_EVP_DigestSignAlgorithm(void) {
}
/* Test a simple AlgorithmIdentifier. */
- if (EVP_DigestSignInit(&md_ctx, &pkey_ctx, EVP_sha256(), NULL, pkey) != 1 ||
+ if (!EVP_DigestSignInit(&md_ctx, &pkey_ctx, EVP_sha256(), NULL, pkey) ||
!test_algorithm_roundtrip(&md_ctx, pkey)) {
fprintf(stderr, "RSA with SHA-256 failed\n");
goto out;
@@ -352,7 +426,7 @@ static int test_EVP_DigestSignAlgorithm(void) {
EVP_MD_CTX_init(&md_ctx);
/* Test RSA-PSS with custom parameters. */
- if (EVP_DigestSignInit(&md_ctx, &pkey_ctx, EVP_sha256(), NULL, pkey) != 1 ||
+ if (!EVP_DigestSignInit(&md_ctx, &pkey_ctx, EVP_sha256(), NULL, pkey) ||
EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING) != 1 ||
EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, EVP_sha512()) != 1 ||
!test_algorithm_roundtrip(&md_ctx, pkey)) {
@@ -375,7 +449,7 @@ out:
return ret;
}
-static int example_EVP_DigestVerifyInitFromAlgorithm(void) {
+static int test_EVP_DigestVerifyInitFromAlgorithm(void) {
int ret = 0;
CBS cert, cert_body, tbs_cert, algorithm, signature;
uint8_t padding;
@@ -412,11 +486,11 @@ static int example_EVP_DigestVerifyInitFromAlgorithm(void) {
pkey = load_example_rsa_key();
if (pkey == NULL ||
- EVP_DigestVerifyInitFromAlgorithm(&md_ctx, algor, pkey) != 1||
- EVP_DigestVerifyUpdate(&md_ctx, CBS_data(&tbs_cert),
- CBS_len(&tbs_cert)) != 1 ||
- EVP_DigestVerifyFinal(&md_ctx, CBS_data(&signature),
- CBS_len(&signature)) != 1) {
+ !EVP_DigestVerifyInitFromAlgorithm(&md_ctx, algor, pkey) ||
+ !EVP_DigestVerifyUpdate(&md_ctx, CBS_data(&tbs_cert),
+ CBS_len(&tbs_cert)) ||
+ !EVP_DigestVerifyFinal(&md_ctx, CBS_data(&signature),
+ CBS_len(&signature))) {
goto out;
}
ret = 1;
@@ -434,16 +508,47 @@ out:
return ret;
}
+static int test_d2i_AutoPrivateKey(const uint8_t *input, size_t input_len,
+ int expected_id) {
+ int ret = 0;
+ const uint8_t *p;
+ EVP_PKEY *pkey = NULL;
+
+ p = input;
+ pkey = d2i_AutoPrivateKey(NULL, &p, input_len);
+ if (pkey == NULL || p != input + input_len) {
+ fprintf(stderr, "d2i_AutoPrivateKey failed\n");
+ goto done;
+ }
+
+ if (EVP_PKEY_id(pkey) != expected_id) {
+ fprintf(stderr, "Did not decode expected type\n");
+ goto done;
+ }
+
+ ret = 1;
+
+done:
+ if (!ret) {
+ BIO_print_errors_fp(stderr);
+ }
+
+ if (pkey != NULL) {
+ EVP_PKEY_free(pkey);
+ }
+ return ret;
+}
+
int main(void) {
CRYPTO_library_init();
ERR_load_crypto_strings();
- if (!example_EVP_DigestSignInit()) {
+ if (!test_EVP_DigestSignInit()) {
fprintf(stderr, "EVP_DigestSignInit failed\n");
return 1;
}
- if (!example_EVP_DigestVerifyInit()) {
+ if (!test_EVP_DigestVerifyInit()) {
fprintf(stderr, "EVP_DigestVerifyInit failed\n");
return 1;
}
@@ -453,11 +558,29 @@ int main(void) {
return 1;
}
- if (!example_EVP_DigestVerifyInitFromAlgorithm()) {
+ if (!test_EVP_DigestVerifyInitFromAlgorithm()) {
fprintf(stderr, "EVP_DigestVerifyInitFromAlgorithm failed\n");
return 1;
}
+ if (!test_d2i_AutoPrivateKey(kExampleRSAKeyDER, sizeof(kExampleRSAKeyDER),
+ EVP_PKEY_RSA)) {
+ fprintf(stderr, "d2i_AutoPrivateKey(kExampleRSAKeyDER) failed\n");
+ return 1;
+ }
+
+ if (!test_d2i_AutoPrivateKey(kExampleRSAKeyPKCS8, sizeof(kExampleRSAKeyPKCS8),
+ EVP_PKEY_RSA)) {
+ fprintf(stderr, "d2i_AutoPrivateKey(kExampleRSAKeyPKCS8) failed\n");
+ return 1;
+ }
+
+ if (!test_d2i_AutoPrivateKey(kExampleECKeyDER, sizeof(kExampleECKeyDER),
+ EVP_PKEY_EC)) {
+ fprintf(stderr, "d2i_AutoPrivateKey(kExampleECKeyDER) failed\n");
+ return 1;
+ }
+
printf("PASS\n");
return 0;
}
diff --git a/crypto/evp/internal.h b/crypto/evp/internal.h
index d92c9e5..0e9dfb2 100644
--- a/crypto/evp/internal.h
+++ b/crypto/evp/internal.h
@@ -65,13 +65,11 @@ extern "C" {
/* These values are flags for EVP_PKEY_ASN1_METHOD.flags. */
-#define ASN1_PKEY_ALIAS 0x1
-#define ASN1_PKEY_DYNAMIC 0x2
/* ASN1_PKEY_SIGPARAM_NULL controls whether the default behavior of
* EVP_DigestSignAlgorithm writes an explicit NULL parameter in the
* AlgorithmIdentifier. */
-#define ASN1_PKEY_SIGPARAM_NULL 0x4
+#define ASN1_PKEY_SIGPARAM_NULL 0x1
/* evp_digest_sign_algorithm_result_t is the return value of the
* digest_sign_algorithm function in EVP_PKEY_ASN1_METHOD. */
diff --git a/crypto/evp/p_rsa_asn1.c b/crypto/evp/p_rsa_asn1.c
index 40012b3..179d96b 100644
--- a/crypto/evp/p_rsa_asn1.c
+++ b/crypto/evp/p_rsa_asn1.c
@@ -717,9 +717,3 @@ const EVP_PKEY_ASN1_METHOD rsa_asn1_meth = {
rsa_digest_verify_init_from_algorithm,
rsa_digest_sign_algorithm,
};
-
-const EVP_PKEY_ASN1_METHOD rsa_asn1_meth_2 = {
- EVP_PKEY_RSA2,
- EVP_PKEY_RSA,
- ASN1_PKEY_ALIAS,
-};
diff --git a/crypto/evp/sign.c b/crypto/evp/sign.c
index c32e5ce..1faf7c6 100644
--- a/crypto/evp/sign.c
+++ b/crypto/evp/sign.c
@@ -91,12 +91,6 @@ int EVP_SignFinal(const EVP_MD_CTX *ctx, uint8_t *sig,
}
EVP_MD_CTX_cleanup(&tmp_ctx);
-/* TODO(fork): this used to be used only with SHA-family hashes. Now we've
- * removed the flag completely. Why was it added for just those hashes? */
-#if 0
- if (ctx->digest->flags & EVP_MD_FLAG_PKEY_METHOD_SIGNATURE) {
-#endif
-
pkctx = EVP_PKEY_CTX_new(pkey, NULL);
if (!pkctx || EVP_PKEY_sign_init(pkctx) <= 0 ||
EVP_PKEY_CTX_set_signature_md(pkctx, ctx->digest) <= 0 ||
@@ -142,11 +136,6 @@ int EVP_VerifyFinal(EVP_MD_CTX *ctx, const uint8_t *sig, size_t sig_len,
}
EVP_MD_CTX_cleanup(&tmp_ctx);
-/* TODO(fork): this used to be used only with SHA-family hashes. Now we've
- * removed the flag completely. Why was it added for just those hashes? */
-#if 0
- if (ctx->digest->flags & EVP_MD_FLAG_PKEY_METHOD_SIGNATURE) {
-#endif
pkctx = EVP_PKEY_CTX_new(pkey, NULL);
if (!pkctx ||
EVP_PKEY_verify_init(pkctx) <= 0 ||
diff --git a/crypto/perlasm/x86asm.pl b/crypto/perlasm/x86asm.pl
index bab15e7..3c7be40 100644
--- a/crypto/perlasm/x86asm.pl
+++ b/crypto/perlasm/x86asm.pl
@@ -235,9 +235,9 @@ sub ::asciz
sub ::asm_finish
{ &file_end();
- print "#if defined(__i386__)\n";
+ print "#if defined(__i386__)\n" unless $win32;
print @out;
- print "#endif\n";
+ print "#endif\n" unless $win32;
}
sub ::asm_init
diff --git a/crypto/perlasm/x86masm.pl b/crypto/perlasm/x86masm.pl
index 1741342..a491529 100644
--- a/crypto/perlasm/x86masm.pl
+++ b/crypto/perlasm/x86masm.pl
@@ -82,7 +82,7 @@ TITLE $_[0].asm
IF \@Version LT 800
ECHO MASM version 8.00 or later is strongly recommended.
ENDIF
-.486
+.686
.MODEL FLAT
OPTION DOTNAME
IF \@Version LT 800
@@ -166,7 +166,10 @@ sub ::data_short
{ push(@out,("DW\t").join(',',@_)."\n"); }
sub ::data_word
-{ push(@out,("DD\t").join(',',@_)."\n"); }
+{ # MASM can't handle long lines, so emit one word at a time.
+ foreach(@_)
+ { push(@out,"DD\t$_\n"); }
+}
sub ::align
{ push(@out,"ALIGN\t$_[0]\n"); }
diff --git a/crypto/perlasm/x86nasm.pl b/crypto/perlasm/x86nasm.pl
index 5d92f60..f8332bb 100644
--- a/crypto/perlasm/x86nasm.pl
+++ b/crypto/perlasm/x86nasm.pl
@@ -83,7 +83,15 @@ sub ::file
%ifidn __OUTPUT_FORMAT__,obj
section code use32 class=code align=64
%elifidn __OUTPUT_FORMAT__,win32
+%ifdef __YASM_VERSION_ID__
+%if __YASM_VERSION_ID__ < 01010000h
+%error yasm version 1.1.0 or later needed.
+%endif
+; Yasm automatically includes @feat.00 and complains about redefining it.
+; https://www.tortall.net/projects/yasm/manual/html/objfmt-win32-safeseh.html
+%else
\$\@feat.00 equ 1
+%endif
section .text code align=64
%else
section .text code
diff --git a/crypto/rand/windows.c b/crypto/rand/windows.c
index 967dd9b..ed6e5e9 100644
--- a/crypto/rand/windows.c
+++ b/crypto/rand/windows.c
@@ -14,57 +14,36 @@
#include <openssl/rand.h>
-#include <openssl/thread.h>
-
-
#if defined(OPENSSL_WINDOWS)
+#include <limits.h>
#include <stdlib.h>
#include <Windows.h>
-#include <Wincrypt.h>
-static char global_provider_init;
-static HCRYPTPROV global_provider;
+/* #define needed to link in RtlGenRandom(), a.k.a. SystemFunction036. See the
+ * "Community Additions" comment on MSDN here:
+ * http://msdn.microsoft.com/en-us/library/windows/desktop/aa387694.aspx */
+#define SystemFunction036 NTAPI SystemFunction036
+#include <NTSecAPI.h>
+#undef SystemFunction036
+
void RAND_cleanup(void) {
- CRYPTO_w_lock(CRYPTO_LOCK_RAND);
- CryptReleaseContext(global_provider, 0);
- global_provider_init = 0;
- CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
}
int RAND_bytes(uint8_t *out, size_t requested) {
- HCRYPTPROV provider = 0;
- int ok;
-
- CRYPTO_r_lock(CRYPTO_LOCK_RAND);
- if (!global_provider_init) {
- CRYPTO_r_unlock(CRYPTO_LOCK_RAND);
- CRYPTO_w_lock(CRYPTO_LOCK_RAND);
- if (!global_provider_init) {
- if (CryptAcquireContext(&global_provider, NULL, NULL, PROV_RSA_FULL,
- CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) {
- global_provider_init = 1;
- }
+ while (requested > 0) {
+ ULONG output_bytes_this_pass = ULONG_MAX;
+ if (requested < output_bytes_this_pass) {
+ output_bytes_this_pass = requested;
}
- CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
- CRYPTO_r_lock(CRYPTO_LOCK_RAND);
- }
-
- ok = global_provider_init;
- provider = global_provider;
- CRYPTO_r_unlock(CRYPTO_LOCK_RAND);
-
- if (!ok) {
- abort();
- return ok;
- }
-
- if (TRUE != CryptGenRandom(provider, requested, out)) {
- abort();
- return 0;
+ if (RtlGenRandom(out, output_bytes_this_pass) == FALSE) {
+ abort();
+ return 0;
+ }
+ requested -= output_bytes_this_pass;
+ out += output_bytes_this_pass;
}
-
return 1;
}
diff --git a/crypto/x509/x_crl.c b/crypto/x509/x_crl.c
index 21785dc..8e64f76 100644
--- a/crypto/x509/x_crl.c
+++ b/crypto/x509/x_crl.c
@@ -64,8 +64,24 @@
#include <openssl/x509.h>
#include <openssl/x509v3.h>
-#include "../asn1/asn1_locl.h"
+/* Method to handle CRL access.
+ * In general a CRL could be very large (several Mb) and can consume large
+ * amounts of resources if stored in memory by multiple processes.
+ * This method allows general CRL operations to be redirected to more
+ * efficient callbacks: for example a CRL entry database.
+ */
+
+#define X509_CRL_METHOD_DYNAMIC 1
+struct x509_crl_method_st
+ {
+ int flags;
+ int (*crl_init)(X509_CRL *crl);
+ int (*crl_free)(X509_CRL *crl);
+ int (*crl_lookup)(X509_CRL *crl, X509_REVOKED **ret,
+ ASN1_INTEGER *ser, X509_NAME *issuer);
+ int (*crl_verify)(X509_CRL *crl, EVP_PKEY *pk);
+ };
static int X509_REVOKED_cmp(const X509_REVOKED **a,
const X509_REVOKED **b);
diff --git a/crypto/x509v3/v3nametest.c b/crypto/x509v3/v3nametest.c
index 6a2ea85..b2e9c09 100644
--- a/crypto/x509v3/v3nametest.c
+++ b/crypto/x509v3/v3nametest.c
@@ -53,9 +53,9 @@
* Hudson (tjh@cryptsoft.com). */
#include <string.h>
-#include <strings.h>
#include <openssl/crypto.h>
+#include <openssl/mem.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
@@ -326,7 +326,7 @@ static void run_cert(X509 *crt, const char *nameincert,
const char *const *pname = names;
while (*pname)
{
- int samename = strcasecmp(nameincert, *pname) == 0;
+ int samename = OPENSSL_strcasecmp(nameincert, *pname) == 0;
size_t namelen = strlen(*pname);
char *name = malloc(namelen);
int match, ret;
diff --git a/include/openssl/base.h b/include/openssl/base.h
index 52cb1e9..6207c54 100644
--- a/include/openssl/base.h
+++ b/include/openssl/base.h
@@ -159,7 +159,6 @@ typedef struct X509_POLICY_NODE_st X509_POLICY_NODE;
typedef struct X509_POLICY_TREE_st X509_POLICY_TREE;
typedef struct X509_algor_st X509_ALGOR;
typedef struct X509_crl_st X509_CRL;
-typedef struct X509_name_st X509_NAME;
typedef struct X509_pubkey_st X509_PUBKEY;
typedef struct bignum_ctx BN_CTX;
typedef struct bignum_st BIGNUM;
diff --git a/include/openssl/bytestring.h b/include/openssl/bytestring.h
index acaba8e..d5e6cf9 100644
--- a/include/openssl/bytestring.h
+++ b/include/openssl/bytestring.h
@@ -166,6 +166,41 @@ OPENSSL_EXPORT int CBS_get_any_asn1_element(CBS *cbs, CBS *out,
* in 64 bits. */
OPENSSL_EXPORT int CBS_get_asn1_uint64(CBS *cbs, uint64_t *out);
+/* CBS_get_optional_asn1 gets an optional explicitly-tagged element
+ * from |cbs| tagged with |tag| and sets |*out| to its contents. If
+ * present, it sets |*out_present| to one, otherwise zero. It returns
+ * one on success, whether or not the element was present, and zero on
+ * decode failure. */
+OPENSSL_EXPORT int CBS_get_optional_asn1(CBS *cbs, CBS *out, int *out_present,
+ unsigned tag);
+
+/* CBS_get_optional_asn1_octet_string gets an optional
+ * explicitly-tagged OCTET STRING from |cbs|. If present, it sets
+ * |*out| to the string and |*out_present| to one. Otherwise, it sets
+ * |*out| to empty and |*out_present| to zero. |out_present| may be
+ * NULL. It returns one on success, whether or not the element was
+ * present, and zero on decode failure. */
+OPENSSL_EXPORT int CBS_get_optional_asn1_octet_string(CBS *cbs, CBS *out,
+ int *out_present,
+ unsigned tag);
+
+/* CBS_get_optional_asn1_uint64 gets an optional explicitly-tagged
+ * INTEGER from |cbs|. If present, it sets |*out| to the
+ * value. Otherwise, it sets |*out| to |default_value|. It returns one
+ * on success, whether or not the element was present, and zero on
+ * decode failure. */
+OPENSSL_EXPORT int CBS_get_optional_asn1_uint64(CBS *cbs, uint64_t *out,
+ unsigned tag,
+ uint64_t default_value);
+
+/* CBS_get_optional_asn1_bool gets an optional, explicitly-tagged BOOLEAN from
+ * |cbs|. If present, it sets |*out| to either zero or one, based on the
+ * boolean. Otherwise, it sets |*out| to |default_value|. It returns one on
+ * success, whether or not the element was present, and zero on decode
+ * failure. */
+OPENSSL_EXPORT int CBS_get_optional_asn1_bool(CBS *cbs, int *out, unsigned tag,
+ int default_value);
+
/* CRYPTO ByteBuilder.
*
@@ -277,6 +312,10 @@ OPENSSL_EXPORT int CBB_add_u16(CBB *cbb, uint16_t value);
* returns one on success and zero otherwise. */
OPENSSL_EXPORT int CBB_add_u24(CBB *cbb, uint32_t value);
+/* CBB_add_asn1_uint64 writes an ASN.1 INTEGER into |cbb| using |CBB_add_asn1|
+ * and writes |value| in its contents. It returns one on success and zero on
+ * error. */
+OPENSSL_EXPORT int CBB_add_asn1_uint64(CBB *cbb, uint64_t value);
#if defined(__cplusplus)
} /* extern C */
diff --git a/include/openssl/dtls1.h b/include/openssl/dtls1.h
index 5aef0c4..a9e3ada 100644
--- a/include/openssl/dtls1.h
+++ b/include/openssl/dtls1.h
@@ -72,11 +72,6 @@ extern "C" {
/* Special value for method supporting multiple versions */
#define DTLS_ANY_VERSION 0x1FFFF
-#if 0
-/* this alert description is not specified anywhere... */
-#define DTLS1_AD_MISSING_HANDSHAKE_MESSAGE 110
-#endif
-
/* lengths of messages */
#define DTLS1_COOKIE_LENGTH 256
@@ -89,11 +84,7 @@ extern "C" {
#define DTLS1_CCS_HEADER_LENGTH 1
-#ifdef DTLS1_AD_MISSING_HANDSHAKE_MESSAGE
-#define DTLS1_AL_HEADER_LENGTH 7
-#else
#define DTLS1_AL_HEADER_LENGTH 2
-#endif
#ifndef OPENSSL_NO_SSL_INTERN
diff --git a/include/openssl/err.h b/include/openssl/err.h
index a7f30c7..b9c48c3 100644
--- a/include/openssl/err.h
+++ b/include/openssl/err.h
@@ -392,7 +392,6 @@ enum {
ERR_LIB_PKCS7,
ERR_LIB_PKCS8,
ERR_LIB_X509V3,
- ERR_LIB_PKCS12,
ERR_LIB_RAND,
ERR_LIB_ENGINE,
ERR_LIB_OCSP,
@@ -426,7 +425,6 @@ enum {
#define ERR_R_PKCS7_LIB ERR_LIB_PKCS7
#define ERR_R_PKCS8_LIB ERR_LIB_PKCS8
#define ERR_R_X509V3_LIB ERR_LIB_X509V3
-#define ERR_R_PKCS12_LIB ERR_LIB_PKCS12
#define ERR_R_RAND_LIB ERR_LIB_RAND
#define ERR_R_DSO_LIB ERR_LIB_DSO
#define ERR_R_ENGINE_LIB ERR_LIB_ENGINE
diff --git a/include/openssl/evp.h b/include/openssl/evp.h
index e3922a3..1f60145 100644
--- a/include/openssl/evp.h
+++ b/include/openssl/evp.h
@@ -290,10 +290,7 @@ OPENSSL_EXPORT int EVP_DigestVerifyUpdate(EVP_MD_CTX *ctx, const void *data,
/* EVP_DigestVerifyFinal verifies that |sig_len| bytes of |sig| are a valid
* signature for the data that has been included by one or more calls to
- * |EVP_DigestVerifyUpdate|.
- *
- * It returns one on success and <= 0 on error. WARNING: this differs from the
- * usual return value convention. */
+ * |EVP_DigestVerifyUpdate|. It returns one on success and zero otherwise. */
OPENSSL_EXPORT int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const uint8_t *sig,
size_t sig_len);
@@ -462,8 +459,8 @@ OPENSSL_EXPORT int EVP_PKEY_sign_init(EVP_PKEY_CTX *ctx);
* space available at |sig|. If sufficient, the signature will be written to
* |sig| and |*sig_len| updated with the true length.
*
- * WARNING: Setting |out| to NULL only gives the maximum size of the
- * plaintext. The actual plaintext may be smaller.
+ * WARNING: Setting |sig| to NULL only gives the maximum size of the
+ * signature. The actual signature may be smaller.
*
* It returns one on success or zero on error. (Note: this differs from
* OpenSSL, which can also return negative values to indicate an error. ) */
diff --git a/include/openssl/srtp.h b/include/openssl/srtp.h
index c11608e..860362b 100644
--- a/include/openssl/srtp.h
+++ b/include/openssl/srtp.h
@@ -115,14 +115,15 @@
Copyright (C) 2011, RTFM, Inc.
*/
-#ifndef HEADER_D1_SRTP_H
-#define HEADER_D1_SRTP_H
+#ifndef OPENSSL_HEADER_SRTP_H
+#define OPENSSL_HEADER_SRTP_H
#ifdef __cplusplus
extern "C" {
#endif
-
+
+/* Constants for SRTP profiles */
#define SRTP_AES128_CM_SHA1_80 0x0001
#define SRTP_AES128_CM_SHA1_32 0x0002
#define SRTP_AES128_F8_SHA1_80 0x0003
@@ -130,32 +131,47 @@ extern "C" {
#define SRTP_NULL_SHA1_80 0x0005
#define SRTP_NULL_SHA1_32 0x0006
-/* SSL_CTX_set_tlsext_use_srtp enables SRTP for all SSL objects
- * created from |ctx|. |profile| contains a colon-separated list of
- * profile names. It returns zero on success and one on failure.
+/* SSL_CTX_set_srtp_profiles enables SRTP for all SSL objects created from
+ * |ctx|. |profile| contains a colon-separated list of profile names. It returns
+ * one on success and zero on failure. */
+OPENSSL_EXPORT int SSL_CTX_set_srtp_profiles(SSL_CTX *ctx,
+ const char *profiles);
+
+/* SSL_set_srtp_profiles enables SRTP for |ssl|. |profile| contains a
+ * colon-separated list of profile names. It returns one on success and zero on
+ * failure. */
+OPENSSL_EXPORT int SSL_set_srtp_profiles(SSL *ctx, const char *profiles);
+
+/* SSL_get_srtp_profiles returns the SRTP profiles supported by |ssl|. */
+OPENSSL_EXPORT STACK_OF(SRTP_PROTECTION_PROFILE) *SSL_get_srtp_profiles(
+ SSL *ssl);
+
+/* SSL_get_selected_srtp_profile returns the selected SRTP profile, or NULL if
+ * SRTP was not negotiated. */
+OPENSSL_EXPORT SRTP_PROTECTION_PROFILE *SSL_get_selected_srtp_profile(SSL *s);
+
+
+/* Deprecated functions */
+
+/* SSL_CTX_set_tlsext_use_srtp calls SSL_CTX_set_srtp_profiles. It returns zero
+ * on success and one on failure.
*
- * WARNING: this function is dangerous because it breaks the usual
- * return value convention. */
+ * WARNING: this function is dangerous because it breaks the usual return value
+ * convention. Use SSL_CTX_set_srtp_profiles instead. */
OPENSSL_EXPORT int SSL_CTX_set_tlsext_use_srtp(SSL_CTX *ctx,
const char *profiles);
-/* SSL_set_tlsext_use_srtp enables SRTP for |ssl| with a profile list.
- * |profile| contains a colon-separated list of profile names. It
- * returns zero on success and one on failure.
+/* SSL_set_tlsext_use_srtp calls SSL_set_srtp_profiles. It returns zero on
+ * success and one on failure.
*
- * WARNING: this function is dangerous because it breaks the usual
- * return value convention. */
+ * WARNING: this function is dangerous because it breaks the usual return value
+ * convention. Use SSL_set_srtp_profiles instead. */
OPENSSL_EXPORT int SSL_set_tlsext_use_srtp(SSL *ctx, const char *profiles);
-OPENSSL_EXPORT SRTP_PROTECTION_PROFILE *SSL_get_selected_srtp_profile(SSL *s);
-
-OPENSSL_EXPORT STACK_OF(SRTP_PROTECTION_PROFILE) *
- SSL_get_srtp_profiles(SSL *ssl);
-OPENSSL_EXPORT SRTP_PROTECTION_PROFILE *SSL_get_selected_srtp_profile(SSL *s);
#ifdef __cplusplus
-}
+} /* extern C */
#endif
-#endif
+#endif /* OPENSSL_HEADER_SRTP_H */
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
index 2168613..31ff5db 100644
--- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h
@@ -359,34 +359,8 @@ struct ssl_method_st
long (*ssl_ctx_callback_ctrl)(SSL_CTX *s, int cb_id, void (*fp)(void));
};
-/* Lets make this into an ASN.1 type structure as follows
- * SSL_SESSION_ID ::= SEQUENCE {
- * version INTEGER, -- structure version number
- * SSLversion INTEGER, -- SSL version number
- * Cipher OCTET STRING, -- the 3 byte cipher ID
- * Session_ID OCTET STRING, -- the Session ID
- * Master_key OCTET STRING, -- the master key
- * Key_Arg [ 0 ] IMPLICIT OCTET STRING, -- the optional Key argument
- * Time [ 1 ] EXPLICIT INTEGER, -- optional Start Time
- * Timeout [ 2 ] EXPLICIT INTEGER, -- optional Timeout ins seconds
- * Peer [ 3 ] EXPLICIT X509, -- optional Peer Certificate
- * Session_ID_context [ 4 ] EXPLICIT OCTET STRING, -- the Session ID context
- * Verify_result [ 5 ] EXPLICIT INTEGER, -- X509_V_... code for `Peer'
- * HostName [ 6 ] EXPLICIT OCTET STRING, -- optional HostName from servername TLS extension
- * PSK_identity_hint [ 7 ] EXPLICIT OCTET STRING, -- optional PSK identity hint
- * PSK_identity [ 8 ] EXPLICIT OCTET STRING, -- optional PSK identity
- * Ticket_lifetime_hint [9] EXPLICIT INTEGER, -- server's lifetime hint for session ticket
- * Ticket [10] EXPLICIT OCTET STRING, -- session ticket (clients only)
- * Compression_meth [11] EXPLICIT OCTET STRING, -- optional compression method
- * SRP_username [ 12 ] EXPLICIT OCTET STRING -- optional SRP username
- * Peer SHA256 [13] EXPLICIT OCTET STRING, -- optional SHA256 hash of Peer certifiate
- * original handshake hash [14] EXPLICIT OCTET STRING, -- optional original handshake hash
- * tlsext_signed_cert_timestamp_list [15] EXPLICIT OCTET STRING, -- optional signed cert timestamp list extension
- * ocsp_response [16] EXPLICIT OCTET STRING, -- optional saved OCSP response from the server
- * }
- * Look in ssl/ssl_asn1.c for more details
- * I'm using EXPLICIT tags so I can read the damn things using asn1parse :-).
- */
+/* An SSL_SESSION represents an SSL session that may be resumed in an
+ * abbreviated handshake. */
struct ssl_session_st
{
int ssl_version; /* what ssl version session info is
@@ -458,6 +432,11 @@ struct ssl_session_st
* resumption. */
unsigned char original_handshake_hash[EVP_MAX_MD_SIZE];
unsigned int original_handshake_hash_len;
+
+ /* extended_master_secret is true if the master secret in this session
+ * was generated using EMS and thus isn't vulnerable to the Triple
+ * Handshake attack. */
+ char extended_master_secret;
};
#endif
@@ -529,9 +508,6 @@ struct ssl_session_st
* the misconception that non-blocking SSL_write() behaves like
* non-blocking write(): */
#define SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER 0x00000002L
-/* Never bother the application with retries if the transport
- * is blocking: */
-#define SSL_MODE_AUTO_RETRY 0x00000004L
/* Don't attempt to automatically build certificate chain */
#define SSL_MODE_NO_AUTO_CHAIN 0x00000008L
/* Save RAM by releasing read and write buffers when they're empty. (SSL3 and
@@ -539,6 +515,10 @@ struct ssl_session_st
* just freed (depending on the context's setting for freelist_max_len). */
#define SSL_MODE_RELEASE_BUFFERS 0x00000010L
+/* The following flags do nothing and are included only to make it easier to
+ * compile code with BoringSSL. */
+#define SSL_MODE_AUTO_RETRY 0
+
/* Send the current time in the Random fields of the ClientHello and
* ServerHello records for compatibility with hypothetical implementations
* that require it.
@@ -1978,18 +1958,52 @@ OPENSSL_EXPORT int SSL_SESSION_print_fp(FILE *fp,const SSL_SESSION *ses);
OPENSSL_EXPORT int SSL_SESSION_print(BIO *fp,const SSL_SESSION *ses);
#endif
OPENSSL_EXPORT void SSL_SESSION_free(SSL_SESSION *ses);
-OPENSSL_EXPORT int i2d_SSL_SESSION(SSL_SESSION *in,unsigned char **pp);
OPENSSL_EXPORT int SSL_set_session(SSL *to, SSL_SESSION *session);
OPENSSL_EXPORT int SSL_CTX_add_session(SSL_CTX *s, SSL_SESSION *c);
OPENSSL_EXPORT int SSL_CTX_remove_session(SSL_CTX *,SSL_SESSION *c);
OPENSSL_EXPORT int SSL_CTX_set_generate_session_id(SSL_CTX *, GEN_SESSION_CB);
OPENSSL_EXPORT int SSL_set_generate_session_id(SSL *, GEN_SESSION_CB);
OPENSSL_EXPORT int SSL_has_matching_session_id(const SSL *ssl, const unsigned char *id, unsigned int id_len);
-OPENSSL_EXPORT SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a,const unsigned char **pp, long length);
-#ifdef HEADER_X509_H
+/* SSL_SESSION_to_bytes serializes |in| into a newly allocated buffer
+ * and sets |*out_data| to that buffer and |*out_len| to its
+ * length. The caller takes ownership of the buffer and must call
+ * |OPENSSL_free| when done. It returns one on success and zero on
+ * error. */
+OPENSSL_EXPORT int SSL_SESSION_to_bytes(SSL_SESSION *in, uint8_t **out_data,
+ size_t *out_len);
+
+/* SSL_SESSION_to_bytes_for_ticket serializes |in|, but excludes the
+ * session ID which is not necessary in a session ticket. */
+OPENSSL_EXPORT int SSL_SESSION_to_bytes_for_ticket(SSL_SESSION *in,
+ uint8_t **out_data,
+ size_t *out_len);
+
+/* Deprecated: i2d_SSL_SESSION serializes |in| to the bytes pointed to
+ * by |*pp|. On success, it returns the number of bytes written and
+ * advances |*pp| by that many bytes. On failure, it returns -1. If
+ * |pp| is NULL, no bytes are written and only the length is
+ * returned.
+ *
+ * Use SSL_SESSION_to_bytes instead. */
+OPENSSL_EXPORT int i2d_SSL_SESSION(SSL_SESSION *in, uint8_t **pp);
+
+/* d2i_SSL_SESSION deserializes a serialized buffer contained in the
+ * |length| bytes pointed to by |*pp|. It returns the new SSL_SESSION
+ * and advances |*pp| by the number of bytes consumed on success and
+ * NULL on failure. If |a| is NULL, the caller takes ownership of the
+ * new session and must call |SSL_SESSION_free| when done.
+ *
+ * If |a| and |*a| are not NULL, the SSL_SESSION at |*a| is overridden
+ * with the deserialized session rather than allocating a new one. In
+ * addition, |a| is not NULL, but |*a| is, |*a| is set to the new
+ * SSL_SESSION.
+ *
+ * Passing a value other than NULL to |a| is deprecated. */
+OPENSSL_EXPORT SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a, const uint8_t **pp,
+ long length);
+
OPENSSL_EXPORT X509 * SSL_get_peer_certificate(const SSL *s);
-#endif
OPENSSL_EXPORT STACK_OF(X509) *SSL_get_peer_cert_chain(const SSL *s);
@@ -2461,6 +2475,12 @@ OPENSSL_EXPORT void ERR_load_SSL_strings(void);
#define SSL_F_ssl3_cert_verify_hash 284
#define SSL_F_ssl_ctx_log_rsa_client_key_exchange 285
#define SSL_F_ssl_ctx_log_master_secret 286
+#define SSL_F_d2i_SSL_SESSION 287
+#define SSL_F_i2d_SSL_SESSION 288
+#define SSL_F_d2i_SSL_SESSION_get_octet_string 289
+#define SSL_F_d2i_SSL_SESSION_get_string 290
+#define SSL_F_ssl3_send_new_session_ticket 291
+#define SSL_F_SSL_SESSION_to_bytes_full 292
#define SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS 100
#define SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC 101
#define SSL_R_INVALID_NULL_CMD_NAME 102
@@ -2774,6 +2794,7 @@ OPENSSL_EXPORT void ERR_load_SSL_strings(void);
#define SSL_R_UNPROCESSED_HANDSHAKE_DATA 440
#define SSL_R_HANDSHAKE_RECORD_BEFORE_CCS 441
#define SSL_R_SESSION_MAY_NOT_BE_CREATED 442
+#define SSL_R_INVALID_SSL_SESSION 443
#define SSL_R_SSLV3_ALERT_CLOSE_NOTIFY 1000
#define SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE 1010
#define SSL_R_SSLV3_ALERT_BAD_RECORD_MAC 1020
diff --git a/include/openssl/ssl3.h b/include/openssl/ssl3.h
index 2a201aa..3d62763 100644
--- a/include/openssl/ssl3.h
+++ b/include/openssl/ssl3.h
@@ -485,6 +485,15 @@ typedef struct ssl3_state_st
* this extension to the client. */
uint16_t *peer_ellipticcurvelist;
size_t peer_ellipticcurvelist_length;
+
+ /* extended_master_secret indicates whether the extended master
+ * secret computation is used in this handshake. Note that this
+ * is different from whether it was used for the current
+ * session. If this is a resumption handshake then EMS might be
+ * negotiated in the client and server hello messages, but it
+ * doesn't matter if the session that's being resumed didn't
+ * use it to create the master secret initially. */
+ char extended_master_secret;
} tmp;
/* Connection binding to prevent renegotiation attacks */
diff --git a/include/openssl/tls1.h b/include/openssl/tls1.h
index 08ad8e8..d2682dd 100644
--- a/include/openssl/tls1.h
+++ b/include/openssl/tls1.h
@@ -240,6 +240,9 @@ extern "C" {
*/
#define TLSEXT_TYPE_padding 21
+/* https://tools.ietf.org/html/draft-ietf-tls-session-hash-01 */
+#define TLSEXT_TYPE_extended_master_secret 23
+
/* ExtensionType value from RFC4507 */
#define TLSEXT_TYPE_session_ticket 35
@@ -704,6 +707,8 @@ SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB,(void (*)(void))cb)
#define TLS_MD_IV_BLOCK_CONST_SIZE 8
#define TLS_MD_MASTER_SECRET_CONST "master secret"
#define TLS_MD_MASTER_SECRET_CONST_SIZE 13
+#define TLS_MD_EXTENDED_MASTER_SECRET_CONST "extended master secret"
+#define TLS_MD_EXTENDED_MASTER_SECRET_CONST_SIZE 22
/* TLS Session Ticket extension struct */
diff --git a/include/openssl/x509.h b/include/openssl/x509.h
index 398bec7..9766f74 100644
--- a/include/openssl/x509.h
+++ b/include/openssl/x509.h
@@ -143,7 +143,7 @@ DECLARE_STACK_OF(X509_NAME_ENTRY)
DECLARE_ASN1_SET_OF(X509_NAME_ENTRY)
/* we always keep X509_NAMEs in 2 forms. */
-struct X509_name_st
+typedef struct X509_name_st
{
STACK_OF(X509_NAME_ENTRY) *entries;
int modified; /* true if 'bytes' needs to be built */
@@ -155,7 +155,7 @@ struct X509_name_st
/* unsigned long hash; Keep the hash around for lookups */
unsigned char *canon_enc;
int canon_enclen;
- } /* X509_NAME */;
+ } X509_NAME;
DECLARE_STACK_OF(X509_NAME)
diff --git a/ssl/d1_both.c b/ssl/d1_both.c
index 2d944d8..82d4a86 100644
--- a/ssl/d1_both.c
+++ b/ssl/d1_both.c
@@ -229,7 +229,7 @@ dtls1_hm_fragment_free(hm_fragment *frag)
}
/* send s->init_buf in records of type 'type' (SSL3_RT_HANDSHAKE or SSL3_RT_CHANGE_CIPHER_SPEC) */
-int dtls1_do_write(SSL *s, int type)
+int dtls1_do_write(SSL *s, int type, enum should_add_to_finished_hash should_add_to_finished_hash)
{
int ret;
int curr_mtu;
@@ -365,7 +365,8 @@ int dtls1_do_write(SSL *s, int type)
* message got sent. but why would this happen? */
assert(len == (unsigned int)ret);
- if (type == SSL3_RT_HANDSHAKE && ! s->d1->retransmitting)
+ if (type == SSL3_RT_HANDSHAKE && !s->d1->retransmitting &&
+ should_add_to_finished_hash == add_to_finished_hash)
{
/* should not be done for 'Hello Request's, but in that case
* we'll ignore the result anyway */
@@ -967,7 +968,7 @@ int dtls1_send_change_cipher_spec(SSL *s, int a, int b)
}
/* SSL3_ST_CW_CHANGE_B */
- return(dtls1_do_write(s,SSL3_RT_CHANGE_CIPHER_SPEC));
+ return(dtls1_do_write(s,SSL3_RT_CHANGE_CIPHER_SPEC, dont_add_to_finished_hash));
}
int dtls1_read_failed(SSL *s, int code)
@@ -991,21 +992,6 @@ int dtls1_read_failed(SSL *s, int code)
return code;
}
-#if 0 /* for now, each alert contains only one record number */
- item = pqueue_peek(state->rcvd_records);
- if ( item )
- {
- /* send an alert immediately for all the missing records */
- }
- else
-#endif
-
-#if 0 /* no more alert sending, just retransmit the last set of messages */
- if ( state->timeout.read_timeouts >= DTLS1_TMO_READ_COUNT)
- ssl3_send_alert(s,SSL3_AL_WARNING,
- DTLS1_AD_MISSING_HANDSHAKE_MESSAGE);
-#endif
-
return dtls1_handle_timeout(s);
}
@@ -1181,7 +1167,7 @@ dtls1_retransmit_message(SSL *s, unsigned short seq, unsigned long frag_off,
}
ret = dtls1_do_write(s, frag->msg_header.is_ccs ?
- SSL3_RT_CHANGE_CIPHER_SPEC : SSL3_RT_HANDSHAKE);
+ SSL3_RT_CHANGE_CIPHER_SPEC : SSL3_RT_HANDSHAKE, add_to_finished_hash);
/* restore current state */
s->enc_write_ctx = saved_state.enc_write_ctx;
diff --git a/ssl/d1_enc.c b/ssl/d1_enc.c
index dec0ea5..11d06cb 100644
--- a/ssl/d1_enc.c
+++ b/ssl/d1_enc.c
@@ -179,10 +179,6 @@ int dtls1_enc(SSL *s, int send)
enc=EVP_CIPHER_CTX_cipher(s->enc_read_ctx);
}
-#ifdef KSSL_DEBUG
- printf("dtls1_enc(%d)\n", send);
-#endif /* KSSL_DEBUG */
-
if ((s->session == NULL) || (ds == NULL) ||
(enc == NULL))
{
@@ -208,24 +204,6 @@ int dtls1_enc(SSL *s, int send)
rec->length+=i;
}
-#ifdef KSSL_DEBUG
- {
- unsigned long ui;
- printf("EVP_Cipher(ds=%p,rec->data=%p,rec->input=%p,l=%ld) ==>\n",
- ds,rec->data,rec->input,l);
- printf("\tEVP_CIPHER_CTX: %d buf_len, %d key_len [%d %d], %d iv_len\n",
- ds->buf_len, ds->cipher->key_len,
- DES_KEY_SZ, DES_SCHEDULE_SZ,
- ds->cipher->iv_len);
- printf("\t\tIV: ");
- for (i=0; i<ds->cipher->iv_len; i++) printf("%02X", ds->iv[i]);
- printf("\n");
- printf("\trec->input=");
- for (ui=0; ui<l; ui++) printf(" %02x", rec->input[ui]);
- printf("\n");
- }
-#endif /* KSSL_DEBUG */
-
if (!send)
{
if (l == 0 || l%bs != 0)
@@ -234,15 +212,6 @@ int dtls1_enc(SSL *s, int send)
EVP_Cipher(ds,rec->data,rec->input,l);
-#ifdef KSSL_DEBUG
- {
- unsigned long i;
- printf("\trec->data=");
- for (i=0; i<l; i++)
- printf(" %02x", rec->data[i]); printf("\n");
- }
-#endif /* KSSL_DEBUG */
-
if ((bs != 1) && !send)
return tls1_cbc_remove_padding(s, rec, bs, mac_size);
}
diff --git a/ssl/d1_lib.c b/ssl/d1_lib.c
index 96ce496..650d8e7 100644
--- a/ssl/d1_lib.c
+++ b/ssl/d1_lib.c
@@ -74,8 +74,9 @@
static void get_current_time(OPENSSL_timeval *t);
static OPENSSL_timeval* dtls1_get_timeout(SSL *s, OPENSSL_timeval* timeleft);
static void dtls1_set_handshake_header(SSL *s, int type, unsigned long len);
-static int dtls1_handshake_write(SSL *s);
+static int dtls1_handshake_write(SSL *s, enum should_add_to_finished_hash should_add_to_finished_hash);
int dtls1_listen(SSL *s, struct sockaddr *client);
+static void dtls1_add_to_finished_hash(SSL *s);
SSL3_ENC_METHOD DTLSv1_enc_data={
tls1_enc,
@@ -93,7 +94,8 @@ SSL3_ENC_METHOD DTLSv1_enc_data={
SSL_ENC_FLAG_DTLS|SSL_ENC_FLAG_EXPLICIT_IV,
DTLS1_HM_HEADER_LENGTH,
dtls1_set_handshake_header,
- dtls1_handshake_write
+ dtls1_handshake_write,
+ dtls1_add_to_finished_hash,
};
SSL3_ENC_METHOD DTLSv1_2_enc_data={
@@ -113,7 +115,8 @@ SSL3_ENC_METHOD DTLSv1_2_enc_data={
|SSL_ENC_FLAG_SHA256_PRF|SSL_ENC_FLAG_TLS1_2_CIPHERS,
DTLS1_HM_HEADER_LENGTH,
dtls1_set_handshake_header,
- dtls1_handshake_write
+ dtls1_handshake_write,
+ dtls1_add_to_finished_hash,
};
int dtls1_new(SSL *s)
@@ -502,7 +505,25 @@ static void dtls1_set_handshake_header(SSL *s, int htype, unsigned long len)
dtls1_buffer_message(s, 0);
}
-static int dtls1_handshake_write(SSL *s)
+static int dtls1_handshake_write(SSL *s, enum should_add_to_finished_hash should_add_to_finished_hash)
{
- return dtls1_do_write(s, SSL3_RT_HANDSHAKE);
+ return dtls1_do_write(s, SSL3_RT_HANDSHAKE, should_add_to_finished_hash);
+ }
+
+static void dtls1_add_to_finished_hash(SSL *s)
+ {
+ uint8_t *record = (uint8_t *) &s->init_buf->data[s->init_off];
+ const struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr;
+ uint8_t serialised_header[DTLS1_HM_HEADER_LENGTH];
+ uint8_t *p = serialised_header;
+
+ /* Construct the message header as if it were a single fragment. */
+ *p++ = msg_hdr->type;
+ l2n3(msg_hdr->msg_len, p);
+ s2n (msg_hdr->seq, p);
+ l2n3(0, p);
+ l2n3(msg_hdr->msg_len, p);
+ ssl3_finish_mac(s, serialised_header, sizeof(serialised_header));
+ ssl3_finish_mac(s, record + DTLS1_HM_HEADER_LENGTH,
+ s->init_num - DTLS1_HM_HEADER_LENGTH);
}
diff --git a/ssl/d1_pkt.c b/ssl/d1_pkt.c
index e2855b8..0ecbb2e 100644
--- a/ssl/d1_pkt.c
+++ b/ssl/d1_pkt.c
@@ -918,14 +918,6 @@ start:
* may be fragmented--don't always expect dest_maxlen bytes */
if ( rr->length < dest_maxlen)
{
-#ifdef DTLS1_AD_MISSING_HANDSHAKE_MESSAGE
- /*
- * for normal alerts rr->length is 2, while
- * dest_maxlen is 7 if we were to handle this
- * non-existing alert...
- */
- FIX ME
-#endif
s->rstate=SSL_ST_READ_HEADER;
rr->length = 0;
goto start;
@@ -984,23 +976,6 @@ start:
OPENSSL_PUT_ERROR(SSL, dtls1_read_bytes, SSL_R_SSL_HANDSHAKE_FAILURE);
return(-1);
}
-
- if (!(s->mode & SSL_MODE_AUTO_RETRY))
- {
- if (s->s3->rbuf.left == 0) /* no read-ahead left? */
- {
- BIO *bio;
- /* In the case where we try to read application data,
- * but we trigger an SSL handshake, we return -1 with
- * the retry option set. Otherwise renegotiation may
- * cause nasty problems in the blocking world */
- s->rwstate=SSL_READING;
- bio=SSL_get_rbio(s);
- BIO_clear_retry_flags(bio);
- BIO_set_retry_read(bio);
- return(-1);
- }
- }
}
}
/* we either finished a handshake or ignored the request,
@@ -1038,31 +1013,6 @@ start:
s->shutdown |= SSL_RECEIVED_SHUTDOWN;
return(0);
}
-#if 0
- /* XXX: this is a possible improvement in the future */
- /* now check if it's a missing record */
- if (alert_descr == DTLS1_AD_MISSING_HANDSHAKE_MESSAGE)
- {
- unsigned short seq;
- unsigned int frag_off;
- unsigned char *p = &(s->d1->alert_fragment[2]);
-
- n2s(p, seq);
- n2l3(p, frag_off);
-
- dtls1_retransmit_message(s,
- dtls1_get_queue_priority(frag->msg_header.seq, 0),
- frag_off, &found);
- if ( ! found && SSL_in_init(s))
- {
- /* fprintf( stderr,"in init = %d\n", SSL_in_init(s)); */
- /* requested a message not yet sent,
- send an alert ourselves */
- ssl3_send_alert(s,SSL3_AL_WARNING,
- DTLS1_AD_MISSING_HANDSHAKE_MESSAGE);
- }
- }
-#endif
}
else if (alert_level == 2) /* fatal */
{
@@ -1188,22 +1138,6 @@ start:
return(-1);
}
- if (!(s->mode & SSL_MODE_AUTO_RETRY))
- {
- if (s->s3->rbuf.left == 0) /* no read-ahead left? */
- {
- BIO *bio;
- /* In the case where we try to read application data,
- * but we trigger an SSL handshake, we return -1 with
- * the retry option set. Otherwise renegotiation may
- * cause nasty problems in the blocking world */
- s->rwstate=SSL_READING;
- bio=SSL_get_rbio(s);
- BIO_clear_retry_flags(bio);
- BIO_set_retry_read(bio);
- return(-1);
- }
- }
goto start;
}
@@ -1577,24 +1511,6 @@ int dtls1_dispatch_alert(SSL *s)
*ptr++ = s->s3->send_alert[0];
*ptr++ = s->s3->send_alert[1];
-#ifdef DTLS1_AD_MISSING_HANDSHAKE_MESSAGE
- if (s->s3->send_alert[1] == DTLS1_AD_MISSING_HANDSHAKE_MESSAGE)
- {
- s2n(s->d1->handshake_read_seq, ptr);
-#if 0
- if ( s->d1->r_msg_hdr.frag_off == 0) /* waiting for a new msg */
-
- else
- s2n(s->d1->r_msg_hdr.seq, ptr); /* partial msg read */
-#endif
-
-#if 0
- fprintf(stderr, "s->d1->handshake_read_seq = %d, s->d1->r_msg_hdr.seq = %d\n",s->d1->handshake_read_seq,s->d1->r_msg_hdr.seq);
-#endif
- l2n3(s->d1->r_msg_hdr.frag_off, ptr);
- }
-#endif
-
i = do_dtls1_write(s, SSL3_RT_ALERT, &buf[0], sizeof(buf));
if (i <= 0)
{
@@ -1603,11 +1519,7 @@ int dtls1_dispatch_alert(SSL *s)
}
else
{
- if (s->s3->send_alert[0] == SSL3_AL_FATAL
-#ifdef DTLS1_AD_MISSING_HANDSHAKE_MESSAGE
- || s->s3->send_alert[1] == DTLS1_AD_MISSING_HANDSHAKE_MESSAGE
-#endif
- )
+ if (s->s3->send_alert[0] == SSL3_AL_FATAL)
(void)BIO_flush(s->wbio);
if (s->msg_callback)
diff --git a/ssl/d1_srtp.c b/ssl/d1_srtp.c
index bc278c3..69b11ad 100644
--- a/ssl/d1_srtp.c
+++ b/ssl/d1_srtp.c
@@ -114,8 +114,6 @@
Copyright (C) 2011, RTFM, Inc.
*/
-#ifndef OPENSSL_NO_SRTP
-
#include <stdio.h>
#include <openssl/bytestring.h>
@@ -226,20 +224,17 @@ static int ssl_ctx_make_profiles(const char *profiles_string,STACK_OF(SRTP_PROTE
return 1;
}
-
-int SSL_CTX_set_tlsext_use_srtp(SSL_CTX *ctx,const char *profiles)
+
+int SSL_CTX_set_srtp_profiles(SSL_CTX *ctx, const char *profiles)
{
- /* This API inverts its return value. */
- return !ssl_ctx_make_profiles(profiles,&ctx->srtp_profiles);
+ return ssl_ctx_make_profiles(profiles, &ctx->srtp_profiles);
}
-int SSL_set_tlsext_use_srtp(SSL *s,const char *profiles)
+int SSL_set_srtp_profiles(SSL *s, const char *profiles)
{
- /* This API inverts its return value. */
- return !ssl_ctx_make_profiles(profiles,&s->srtp_profiles);
+ return ssl_ctx_make_profiles(profiles, &s->srtp_profiles);
}
-
STACK_OF(SRTP_PROTECTION_PROFILE) *SSL_get_srtp_profiles(SSL *s)
{
if(s != NULL)
@@ -263,6 +258,18 @@ SRTP_PROTECTION_PROFILE *SSL_get_selected_srtp_profile(SSL *s)
return s->srtp_profile;
}
+int SSL_CTX_set_tlsext_use_srtp(SSL_CTX *ctx, const char *profiles)
+ {
+ /* This API inverts its return value. */
+ return !SSL_CTX_set_srtp_profiles(ctx, profiles);
+ }
+
+int SSL_set_tlsext_use_srtp(SSL *s, const char *profiles)
+ {
+ /* This API inverts its return value. */
+ return !SSL_set_srtp_profiles(s, profiles);
+ }
+
/* Note: this function returns 0 length if there are no
profiles specified */
int ssl_add_clienthello_use_srtp_ext(SSL *s, unsigned char *p, int *len, int maxlen)
@@ -464,6 +471,3 @@ int ssl_parse_serverhello_use_srtp_ext(SSL *s, CBS *cbs, int *out_alert)
*out_alert = SSL_AD_ILLEGAL_PARAMETER;
return 0;
}
-
-
-#endif
diff --git a/ssl/d1_srvr.c b/ssl/d1_srvr.c
index 79da484..e1c5616 100644
--- a/ssl/d1_srvr.c
+++ b/ssl/d1_srvr.c
@@ -687,5 +687,5 @@ int dtls1_send_hello_verify_request(SSL *s)
}
/* s->state = DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B */
- return(dtls1_do_write(s,SSL3_RT_HANDSHAKE));
+ return(dtls1_do_write(s,SSL3_RT_HANDSHAKE, add_to_finished_hash));
}
diff --git a/ssl/s3_both.c b/ssl/s3_both.c
index 6604fc7..65eb3ba 100644
--- a/ssl/s3_both.c
+++ b/ssl/s3_both.c
@@ -127,17 +127,19 @@
#include "ssl_locl.h"
/* send s->init_buf in records of type 'type' (SSL3_RT_HANDSHAKE or SSL3_RT_CHANGE_CIPHER_SPEC) */
-int ssl3_do_write(SSL *s, int type)
+int ssl3_do_write(SSL *s, int type, enum should_add_to_finished_hash should_add_to_finished_hash)
{
int ret;
ret=ssl3_write_bytes(s,type,&s->init_buf->data[s->init_off],
s->init_num);
if (ret < 0) return(-1);
- if (type == SSL3_RT_HANDSHAKE)
+ if (type == SSL3_RT_HANDSHAKE && should_add_to_finished_hash == add_to_finished_hash)
+ {
/* should not be done for 'Hello Request's, but in that case
* we'll ignore the result anyway */
ssl3_finish_mac(s,(unsigned char *)&s->init_buf->data[s->init_off],ret);
+ }
if (ret == s->init_num)
{
@@ -320,7 +322,7 @@ int ssl3_send_change_cipher_spec(SSL *s, int a, int b)
}
/* SSL3_ST_CW_CHANGE_B */
- return(ssl3_do_write(s,SSL3_RT_CHANGE_CIPHER_SPEC));
+ return(ssl3_do_write(s,SSL3_RT_CHANGE_CIPHER_SPEC, dont_add_to_finished_hash));
}
unsigned long ssl3_output_cert_chain(SSL *s, CERT_PKEY *cpk)
@@ -417,18 +419,6 @@ long ssl3_get_message(SSL *s, int st1, int stn, int mt, long max, int hash_messa
OPENSSL_PUT_ERROR(SSL, ssl3_get_message, SSL_R_UNEXPECTED_MESSAGE);
goto f_err;
}
- if ((mt < 0) && (*p == SSL3_MT_CLIENT_HELLO) &&
- (st1 == SSL3_ST_SR_CERT_A) &&
- (stn == SSL3_ST_SR_CERT_B))
- {
- /* At this point we have got an MS SGC second client
- * hello (maybe we should always allow the client to
- * start a new handshake?). We need to restart the mac.
- * Don't increment {num,total}_renegotiations because
- * we have not completed the handshake. */
- ssl3_init_finished_mac(s);
- }
-
s->s3->tmp.message_type= *(p++);
n2l3(p,l);
diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c
index 6574f5a..64bccfa 100644
--- a/ssl/s3_clnt.c
+++ b/ssl/s3_clnt.c
@@ -982,7 +982,7 @@ int ssl3_get_server_hello(SSL *s)
/* Don't digest cached records if no sigalgs: we may need them for
* client authentication.
*/
- if (!SSL_USE_SIGALGS(s) && !ssl3_digest_cached_records(s))
+ if (!SSL_USE_SIGALGS(s) && !ssl3_digest_cached_records(s, free_handshake_buffer))
goto f_err;
/* Only the NULL compression algorithm is supported. */
@@ -1550,11 +1550,11 @@ int ssl3_get_server_key_exchange(SSL *s)
}
else
{
- EVP_VerifyInit_ex(&md_ctx, md, NULL);
- EVP_VerifyUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE);
- EVP_VerifyUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE);
- EVP_VerifyUpdate(&md_ctx, CBS_data(&parameter), CBS_len(&parameter));
- if (EVP_VerifyFinal(&md_ctx, CBS_data(&signature), CBS_len(&signature), pkey) <= 0)
+ if (!EVP_DigestVerifyInit(&md_ctx, NULL, md, NULL, pkey) ||
+ !EVP_DigestVerifyUpdate(&md_ctx, s->s3->client_random, SSL3_RANDOM_SIZE) ||
+ !EVP_DigestVerifyUpdate(&md_ctx, s->s3->server_random, SSL3_RANDOM_SIZE) ||
+ !EVP_DigestVerifyUpdate(&md_ctx, CBS_data(&parameter), CBS_len(&parameter)) ||
+ !EVP_DigestVerifyFinal(&md_ctx, CBS_data(&signature), CBS_len(&signature)))
{
/* bad signature */
al=SSL_AD_DECRYPT_ERROR;
@@ -1637,7 +1637,7 @@ int ssl3_get_certificate_request(SSL *s)
*/
if (s->s3->handshake_buffer)
{
- if (!ssl3_digest_cached_records(s))
+ if (!ssl3_digest_cached_records(s, free_handshake_buffer))
goto err;
}
return(1);
@@ -1909,6 +1909,8 @@ int ssl3_send_client_key_exchange(SSL *s)
BN_CTX * bn_ctx = NULL;
unsigned int psk_len = 0;
unsigned char psk[PSK_MAX_PSK_LEN];
+ uint8_t *pms = NULL;
+ size_t pms_len = 0;
if (s->state == SSL3_ST_CW_KEY_EXCH_A)
{
@@ -1917,16 +1919,12 @@ int ssl3_send_client_key_exchange(SSL *s)
alg_k=s->s3->tmp.new_cipher->algorithm_mkey;
alg_a=s->s3->tmp.new_cipher->algorithm_auth;
+ /* If using a PSK key exchange, prepare the pre-shared key. */
if (alg_a & SSL_aPSK)
{
char identity[PSK_MAX_IDENTITY_LEN + 1];
size_t identity_len;
- unsigned char *t = NULL;
- unsigned char pre_ms[PSK_MAX_PSK_LEN*2+4];
- unsigned int pre_ms_len = 0;
- int psk_err = 1;
- n = 0;
if (s->psk_client_callback == NULL)
{
OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, SSL_R_PSK_NO_CLIENT_CB);
@@ -1939,40 +1937,19 @@ int ssl3_send_client_key_exchange(SSL *s)
if (psk_len > PSK_MAX_PSK_LEN)
{
OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_INTERNAL_ERROR);
- goto psk_err;
+ goto err;
}
else if (psk_len == 0)
{
OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, SSL_R_PSK_IDENTITY_NOT_FOUND);
- goto psk_err;
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
+ goto err;
}
identity_len = OPENSSL_strnlen(identity, sizeof(identity));
if (identity_len > PSK_MAX_IDENTITY_LEN)
{
OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_INTERNAL_ERROR);
- goto psk_err;
- }
-
- if (!(alg_k & SSL_kEECDH))
- {
- /* Create the shared secret now if we're not using ECDHE-PSK.
- * TODO(davidben): Refactor this logic similarly
- * to ssl3_get_client_key_exchange. */
- pre_ms_len = 2+psk_len+2+psk_len;
- t = pre_ms;
- s2n(psk_len, t);
- memset(t, 0, psk_len);
- t+=psk_len;
- s2n(psk_len, t);
- memcpy(t, psk, psk_len);
-
- s->session->master_key_length =
- s->method->ssl3_enc->generate_master_secret(s,
- s->session->master_key,
- pre_ms, pre_ms_len);
- s2n(identity_len, p);
- memcpy(p, identity, identity_len);
- n = 2 + identity_len;
+ goto err;
}
if (s->session->psk_identity != NULL)
@@ -1981,23 +1958,30 @@ int ssl3_send_client_key_exchange(SSL *s)
if (s->session->psk_identity == NULL)
{
OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_MALLOC_FAILURE);
- goto psk_err;
- }
- psk_err = 0;
- psk_err:
- OPENSSL_cleanse(identity, sizeof(identity));
- OPENSSL_cleanse(pre_ms, sizeof(pre_ms));
- if (psk_err != 0)
- {
- ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
goto err;
}
+
+ /* Write out psk_identity. */
+ s2n(identity_len, p);
+ memcpy(p, identity, identity_len);
+ p += identity_len;
+ n = 2 + identity_len;
}
+ /* Depending on the key exchange method, compute |pms|
+ * and |pms_len|. */
if (alg_k & SSL_kRSA)
{
RSA *rsa;
- unsigned char tmp_buf[SSL_MAX_MASTER_KEY_LENGTH];
+ size_t enc_pms_len;
+
+ pms_len = SSL_MAX_MASTER_KEY_LENGTH;
+ pms = OPENSSL_malloc(pms_len);
+ if (pms == NULL)
+ {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
if (s->session->sess_cert == NULL)
{
@@ -2022,49 +2006,47 @@ int ssl3_send_client_key_exchange(SSL *s)
EVP_PKEY_free(pkey);
}
- tmp_buf[0]=s->client_version>>8;
- tmp_buf[1]=s->client_version&0xff;
- if (RAND_bytes(&(tmp_buf[2]),sizeof tmp_buf-2) <= 0)
+ pms[0]=s->client_version>>8;
+ pms[1]=s->client_version&0xff;
+ if (RAND_bytes(&pms[2],SSL_MAX_MASTER_KEY_LENGTH-2) <= 0)
goto err;
- s->session->master_key_length=sizeof tmp_buf;
+ s->session->master_key_length=SSL_MAX_MASTER_KEY_LENGTH;
q=p;
- /* Fix buf for TLS and beyond */
+ /* In TLS and beyond, reserve space for the length prefix. */
if (s->version > SSL3_VERSION)
- p+=2;
- n=RSA_public_encrypt(sizeof tmp_buf,
- tmp_buf,p,rsa,RSA_PKCS1_PADDING);
- if (n <= 0)
+ {
+ p += 2;
+ n += 2;
+ }
+ if (!RSA_encrypt(rsa, &enc_pms_len, p, RSA_size(rsa),
+ pms, pms_len, RSA_PKCS1_PADDING))
{
OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, SSL_R_BAD_RSA_ENCRYPT);
goto err;
}
+ n += enc_pms_len;
/* Log the premaster secret, if logging is enabled. */
if (!ssl_ctx_log_rsa_client_key_exchange(s->ctx,
- p, n, tmp_buf, sizeof(tmp_buf)))
+ p, enc_pms_len, pms, pms_len))
{
goto err;
}
- /* Fix buf for TLS and beyond */
+ /* Fill in the length prefix. */
if (s->version > SSL3_VERSION)
{
- s2n(n,q);
- n+=2;
+ s2n(enc_pms_len, q);
}
-
- s->session->master_key_length=
- s->method->ssl3_enc->generate_master_secret(s,
- s->session->master_key,
- tmp_buf,sizeof tmp_buf);
- OPENSSL_cleanse(tmp_buf,sizeof tmp_buf);
}
else if (alg_k & SSL_kEDH)
{
- DH *dh_srvr,*dh_clnt;
+ DH *dh_srvr, *dh_clnt;
SESS_CERT *scert = s->session->sess_cert;
+ int dh_len;
+ size_t pub_len;
if (scert == NULL)
{
@@ -2093,44 +2075,38 @@ int ssl3_send_client_key_exchange(SSL *s)
goto err;
}
- /* use the 'p' output buffer for the DH key, but
- * make sure to clear it out afterwards */
+ pms_len = DH_size(dh_clnt);
+ pms = OPENSSL_malloc(pms_len);
+ if (pms == NULL)
+ {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_MALLOC_FAILURE);
+ DH_free(dh_clnt);
+ goto err;
+ }
- n=DH_compute_key(p,dh_srvr->pub_key,dh_clnt);
- if (n <= 0)
+ dh_len = DH_compute_key(pms, dh_srvr->pub_key, dh_clnt);
+ if (dh_len <= 0)
{
OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_DH_LIB);
DH_free(dh_clnt);
goto err;
}
-
- /* generate master key from the result */
- s->session->master_key_length=
- s->method->ssl3_enc->generate_master_secret(s,
- s->session->master_key,p,n);
- /* clean up */
- memset(p,0,n);
+ pms_len = dh_len;
/* send off the data */
- n=BN_num_bytes(dh_clnt->pub_key);
- s2n(n,p);
- BN_bn2bin(dh_clnt->pub_key,p);
- n+=2;
+ pub_len = BN_num_bytes(dh_clnt->pub_key);
+ s2n(pub_len, p);
+ BN_bn2bin(dh_clnt->pub_key, p);
+ n += 2 + pub_len;
DH_free(dh_clnt);
-
- /* perhaps clean things up a bit EAY EAY EAY EAY*/
}
else if (alg_k & SSL_kEECDH)
{
const EC_GROUP *srvr_group = NULL;
EC_KEY *tkey;
- int field_size = 0;
- unsigned char *pre_ms;
- unsigned char *t;
- unsigned int pre_ms_len;
- unsigned int i;
+ int field_size = 0, ecdh_len;
if (s->session->sess_cert == NULL)
{
@@ -2173,54 +2149,28 @@ int ssl3_send_client_key_exchange(SSL *s)
goto err;
}
- /* use the 'p' output buffer for the ECDH key, but
- * make sure to clear it out afterwards
- */
-
field_size = EC_GROUP_get_degree(srvr_group);
if (field_size <= 0)
{
OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_ECDH_LIB);
goto err;
}
- n=ECDH_compute_key(p, (field_size+7)/8, srvr_ecpoint, clnt_ecdh, NULL);
- if (n <= 0)
+
+ pms_len = (field_size + 7) / 8;
+ pms = OPENSSL_malloc(pms_len);
+ if (pms == NULL)
{
- OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_ECDH_LIB);
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_MALLOC_FAILURE);
goto err;
}
- /* ECDHE PSK ciphersuites from RFC 5489 */
- if ((alg_a & SSL_aPSK) && psk_len != 0)
- {
- pre_ms_len = 2+psk_len+2+n;
- pre_ms = OPENSSL_malloc(pre_ms_len);
- if (pre_ms == NULL)
- {
- OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- memset(pre_ms, 0, pre_ms_len);
- t = pre_ms;
- s2n(psk_len, t);
- memcpy(t, psk, psk_len);
- t += psk_len;
- s2n(n, t);
- memcpy(t, p, n);
- s->session->master_key_length = s->method->ssl3_enc \
- -> generate_master_secret(s,
- s->session->master_key, pre_ms, pre_ms_len);
- OPENSSL_cleanse(pre_ms, pre_ms_len);
- OPENSSL_free(pre_ms);
- }
- if (!(alg_a & SSL_aPSK))
+ ecdh_len = ECDH_compute_key(pms, pms_len, srvr_ecpoint, clnt_ecdh, NULL);
+ if (ecdh_len <= 0)
{
- /* generate master key from the result */
- s->session->master_key_length = s->method->ssl3_enc \
- -> generate_master_secret(s,
- s->session->master_key, p, n);
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_ECDH_LIB);
+ goto err;
}
- memset(p, 0, n); /* clean up */
+ pms_len = ecdh_len;
/* First check the size of encoding and
* allocate memory accordingly.
@@ -2248,32 +2198,39 @@ int ssl3_send_client_key_exchange(SSL *s)
POINT_CONVERSION_UNCOMPRESSED,
encodedPoint, encoded_pt_len, bn_ctx);
- n = 0;
- if ((alg_a & SSL_aPSK) && psk_len != 0)
- {
- i = strlen(s->session->psk_identity);
- s2n(i, p);
- memcpy(p, s->session->psk_identity, i);
- p += i;
- n = i + 2;
- }
-
*p = encoded_pt_len; /* length of encoded point */
/* Encoded point will be copied here */
p += 1;
n += 1;
/* copy the point */
- memcpy((unsigned char *)p, encodedPoint, encoded_pt_len);
+ memcpy(p, encodedPoint, encoded_pt_len);
/* increment n to account for length field */
n += encoded_pt_len;
/* Free allocated memory */
BN_CTX_free(bn_ctx);
+ bn_ctx = NULL;
OPENSSL_free(encodedPoint);
+ encodedPoint = NULL;
EC_KEY_free(clnt_ecdh);
+ clnt_ecdh = NULL;
EVP_PKEY_free(srvr_pub_pkey);
+ srvr_pub_pkey = NULL;
+ }
+ else if (alg_k & SSL_kPSK)
+ {
+ /* For plain PSK, other_secret is a block of 0s with the same
+ * length as the pre-shared key. */
+ pms_len = psk_len;
+ pms = OPENSSL_malloc(pms_len);
+ if (pms == NULL)
+ {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ memset(pms, 0, pms_len);
}
- else if (!(alg_k & SSL_kPSK) || ((alg_k & SSL_kPSK) && !(alg_a & SSL_aPSK)))
+ else
{
ssl3_send_alert(s, SSL3_AL_FATAL,
SSL_AD_HANDSHAKE_FAILURE);
@@ -2281,19 +2238,71 @@ int ssl3_send_client_key_exchange(SSL *s)
goto err;
}
+ /* For a PSK cipher suite, other_secret is combined
+ * with the pre-shared key. */
+ if ((alg_a & SSL_aPSK) && psk_len != 0)
+ {
+ CBB cbb, child;
+ uint8_t *new_pms;
+ size_t new_pms_len;
+
+ if (!CBB_init(&cbb, 2 + psk_len + 2 + pms_len))
+ {
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ if (!CBB_add_u16_length_prefixed(&cbb, &child) ||
+ !CBB_add_bytes(&child, pms, pms_len) ||
+ !CBB_add_u16_length_prefixed(&cbb, &child) ||
+ !CBB_add_bytes(&child, psk, psk_len) ||
+ !CBB_finish(&cbb, &new_pms, &new_pms_len))
+ {
+ CBB_cleanup(&cbb);
+ OPENSSL_PUT_ERROR(SSL, ssl3_send_client_key_exchange, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ OPENSSL_cleanse(pms, pms_len);
+ OPENSSL_free(pms);
+ pms = new_pms;
+ pms_len = new_pms_len;
+ }
+
ssl_set_handshake_header(s, SSL3_MT_CLIENT_KEY_EXCHANGE, n);
s->state=SSL3_ST_CW_KEY_EXCH_B;
+
+ /* The message must be added to the finished hash before
+ * calculating the master secret. */
+ s->method->ssl3_enc->add_to_finished_hash(s);
+
+ s->session->master_key_length =
+ s->method->ssl3_enc->generate_master_secret(s,
+ s->session->master_key,
+ pms, pms_len);
+ if (s->session->master_key_length == 0)
+ {
+ goto err;
+ }
+ s->session->extended_master_secret = s->s3->tmp.extended_master_secret;
+ OPENSSL_cleanse(pms, pms_len);
+ OPENSSL_free(pms);
}
/* SSL3_ST_CW_KEY_EXCH_B */
- return ssl_do_write(s);
+ /* The message has already been added to the finished hash. */
+ return s->method->ssl3_enc->do_write(s, dont_add_to_finished_hash);
+
err:
BN_CTX_free(bn_ctx);
if (encodedPoint != NULL) OPENSSL_free(encodedPoint);
if (clnt_ecdh != NULL)
EC_KEY_free(clnt_ecdh);
EVP_PKEY_free(srvr_pub_pkey);
- return(-1);
+ if (pms)
+ {
+ OPENSSL_cleanse(pms, pms_len);
+ OPENSSL_free(pms);
+ }
+ return -1;
}
int ssl3_send_cert_verify(SSL *s)
@@ -2332,7 +2341,7 @@ int ssl3_send_cert_verify(SSL *s)
goto err;
/* The handshake buffer is no longer necessary. */
- if (s->s3->handshake_buffer && !ssl3_digest_cached_records(s))
+ if (s->s3->handshake_buffer && !ssl3_digest_cached_records(s, free_handshake_buffer))
goto err;
/* Sign the digest. */
@@ -2583,7 +2592,7 @@ int ssl3_send_next_proto(SSL *s)
s->init_off = 0;
}
- return ssl3_do_write(s, SSL3_RT_HANDSHAKE);
+ return ssl3_do_write(s, SSL3_RT_HANDSHAKE, add_to_finished_hash);
}
@@ -2597,7 +2606,7 @@ int ssl3_send_channel_id(SSL *s)
unsigned char *public_key = NULL, *derp, *der_sig = NULL;
if (s->state != SSL3_ST_CW_CHANNEL_ID_A)
- return ssl3_do_write(s, SSL3_RT_HANDSHAKE);
+ return ssl3_do_write(s, SSL3_RT_HANDSHAKE, add_to_finished_hash);
if (!s->tlsext_channel_id_private && s->ctx->channel_id_cb)
{
@@ -2700,7 +2709,7 @@ int ssl3_send_channel_id(SSL *s)
s->init_num = 4 + 2 + 2 + TLSEXT_CHANNEL_ID_SIZE;
s->init_off = 0;
- ret = ssl3_do_write(s, SSL3_RT_HANDSHAKE);
+ ret = ssl3_do_write(s, SSL3_RT_HANDSHAKE, add_to_finished_hash);
err:
EVP_MD_CTX_cleanup(&md_ctx);
diff --git a/ssl/s3_enc.c b/ssl/s3_enc.c
index b0ca507..fc94a94 100644
--- a/ssl/s3_enc.c
+++ b/ssl/s3_enc.c
@@ -510,7 +510,7 @@ void ssl3_finish_mac(SSL *s, const unsigned char *buf, int len)
}
}
-int ssl3_digest_cached_records(SSL *s)
+int ssl3_digest_cached_records(SSL *s, enum should_free_handshake_buffer_t should_free_handshake_buffer)
{
int i;
long mask;
@@ -542,9 +542,13 @@ int ssl3_digest_cached_records(SSL *s)
s->s3->handshake_dgst[i]=NULL;
}
}
- /* Free handshake_buffer BIO */
- BIO_free(s->s3->handshake_buffer);
- s->s3->handshake_buffer = NULL;
+
+ if (should_free_handshake_buffer == free_handshake_buffer)
+ {
+ /* Free handshake_buffer BIO */
+ BIO_free(s->s3->handshake_buffer);
+ s->s3->handshake_buffer = NULL;
+ }
return 1;
}
@@ -581,7 +585,7 @@ static int ssl3_handshake_mac(SSL *s, int md_nid,
EVP_MD_CTX ctx,*d=NULL;
if (s->s3->handshake_buffer)
- if (!ssl3_digest_cached_records(s))
+ if (!ssl3_digest_cached_records(s, free_handshake_buffer))
return 0;
/* Search for digest of specified type in the handshake_dgst
diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c
index 215b3f6..3060684 100644
--- a/ssl/s3_lib.c
+++ b/ssl/s3_lib.c
@@ -942,7 +942,8 @@ SSL3_ENC_METHOD SSLv3_enc_data={
0,
SSL3_HM_HEADER_LENGTH,
ssl3_set_handshake_header,
- ssl3_handshake_write
+ ssl3_handshake_write,
+ ssl3_add_to_finished_hash,
};
int ssl3_num_ciphers(void)
@@ -975,9 +976,14 @@ void ssl3_set_handshake_header(SSL *s, int htype, unsigned long len)
s->init_off = 0;
}
-int ssl3_handshake_write(SSL *s)
+int ssl3_handshake_write(SSL *s, enum should_add_to_finished_hash should_add_to_finished_hash)
{
- return ssl3_do_write(s, SSL3_RT_HANDSHAKE);
+ return ssl3_do_write(s, SSL3_RT_HANDSHAKE, should_add_to_finished_hash);
+ }
+
+void ssl3_add_to_finished_hash(SSL *s)
+ {
+ ssl3_finish_mac(s, (uint8_t*) s->init_buf->data, s->init_num);
}
int ssl3_new(SSL *s)
@@ -1385,9 +1391,9 @@ long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg)
}
case SSL_CTRL_GET_EC_POINT_FORMATS:
{
+ const uint8_t **pformat = parg;
if (!s->s3->tmp.peer_ecpointformatlist)
return 0;
- const uint8_t **pformat = parg;
*pformat = s->s3->tmp.peer_ecpointformatlist;
return (int)s->s3->tmp.peer_ecpointformatlist_length;
}
@@ -1850,10 +1856,6 @@ const SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
ssl_set_cert_masks(cert,c);
mask_k = cert->mask_k;
mask_a = cert->mask_a;
-
-#ifdef KSSL_DEBUG
-/* printf("ssl3_choose_cipher %d alg= %lx\n", i,c->algorithms);*/
-#endif /* KSSL_DEBUG */
alg_k=c->algorithm_mkey;
alg_a=c->algorithm_auth;
diff --git a/ssl/s3_pkt.c b/ssl/s3_pkt.c
index 0df6a3c..d0e1856 100644
--- a/ssl/s3_pkt.c
+++ b/ssl/s3_pkt.c
@@ -1151,23 +1151,6 @@ start:
OPENSSL_PUT_ERROR(SSL, ssl3_read_bytes, SSL_R_SSL_HANDSHAKE_FAILURE);
return(-1);
}
-
- if (!(s->mode & SSL_MODE_AUTO_RETRY))
- {
- if (s->s3->rbuf.left == 0) /* no read-ahead left? */
- {
- BIO *bio;
- /* In the case where we try to read application data,
- * but we trigger an SSL handshake, we return -1 with
- * the retry option set. Otherwise renegotiation may
- * cause nasty problems in the blocking world */
- s->rwstate=SSL_READING;
- bio=SSL_get_rbio(s);
- BIO_clear_retry_flags(bio);
- BIO_set_retry_read(bio);
- return(-1);
- }
- }
}
}
/* we either finished a handshake or ignored the request,
@@ -1237,10 +1220,6 @@ start:
OPENSSL_PUT_ERROR(SSL, ssl3_read_bytes, SSL_R_NO_RENEGOTIATION);
goto f_err;
}
-#ifdef SSL_AD_MISSING_SRP_USERNAME
- else if (alert_descr == SSL_AD_MISSING_SRP_USERNAME)
- return(0);
-#endif
}
else if (alert_level == 2) /* fatal */
{
@@ -1339,22 +1318,6 @@ start:
return(-1);
}
- if (!(s->mode & SSL_MODE_AUTO_RETRY))
- {
- if (s->s3->rbuf.left == 0) /* no read-ahead left? */
- {
- BIO *bio;
- /* In the case where we try to read application data,
- * but we trigger an SSL handshake, we return -1 with
- * the retry option set. Otherwise renegotiation may
- * cause nasty problems in the blocking world */
- s->rwstate=SSL_READING;
- bio=SSL_get_rbio(s);
- BIO_clear_retry_flags(bio);
- BIO_set_retry_read(bio);
- return(-1);
- }
- }
goto start;
}
diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c
index 149d9e7..29448db 100644
--- a/ssl/s3_srvr.c
+++ b/ssl/s3_srvr.c
@@ -444,7 +444,7 @@ int ssl3_accept(SSL *s)
s->s3->tmp.cert_request=0;
s->state=SSL3_ST_SW_SRVR_DONE_A;
if (s->s3->handshake_buffer)
- if (!ssl3_digest_cached_records(s))
+ if (!ssl3_digest_cached_records(s, free_handshake_buffer))
return -1;
}
else
@@ -993,7 +993,8 @@ int ssl3_get_client_hello(SSL *s)
goto f_err;
}
- if (ssl_bytes_to_cipher_list(s, &cipher_suites, &ciphers) == NULL)
+ ciphers = ssl_bytes_to_cipher_list(s, &cipher_suites);
+ if (ciphers == NULL)
{
goto err;
}
@@ -1143,7 +1144,7 @@ int ssl3_get_client_hello(SSL *s)
if (!SSL_USE_SIGALGS(s) || !(s->verify_mode & SSL_VERIFY_PEER))
{
- if (!ssl3_digest_cached_records(s))
+ if (!ssl3_digest_cached_records(s, free_handshake_buffer))
goto f_err;
}
@@ -1608,6 +1609,8 @@ int ssl3_send_server_key_exchange(SSL *s)
else
if (md)
{
+ size_t sig_len = EVP_PKEY_size(pkey);
+
/* send signature algorithm */
if (SSL_USE_SIGALGS(s))
{
@@ -1620,24 +1623,19 @@ int ssl3_send_server_key_exchange(SSL *s)
}
p+=2;
}
-#ifdef SSL_DEBUG
- fprintf(stderr, "Using hash %s\n",
- EVP_MD_name(md));
-#endif
- EVP_SignInit_ex(&md_ctx, md, NULL);
- EVP_SignUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE);
- EVP_SignUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE);
- EVP_SignUpdate(&md_ctx,d,n);
- if (!EVP_SignFinal(&md_ctx,&(p[2]),
- (unsigned int *)&i,pkey))
+ if (!EVP_DigestSignInit(&md_ctx, NULL, md, NULL, pkey) ||
+ !EVP_DigestSignUpdate(&md_ctx, s->s3->client_random, SSL3_RANDOM_SIZE) ||
+ !EVP_DigestSignUpdate(&md_ctx, s->s3->server_random, SSL3_RANDOM_SIZE) ||
+ !EVP_DigestSignUpdate(&md_ctx, d, n) ||
+ !EVP_DigestSignFinal(&md_ctx, &p[2], &sig_len))
{
OPENSSL_PUT_ERROR(SSL, ssl3_send_server_key_exchange, ERR_LIB_EVP);
goto err;
}
- s2n(i,p);
- n+=i+2;
+ s2n(sig_len, p);
+ n += sig_len + 2;
if (SSL_USE_SIGALGS(s))
- n+= 2;
+ n += 2;
}
else
{
@@ -2140,9 +2138,13 @@ int ssl3_get_client_key_exchange(SSL *s)
}
EVP_PKEY_free(clnt_pub_pkey);
+ clnt_pub_pkey = NULL;
EC_POINT_free(clnt_ecpoint);
+ clnt_ecpoint = NULL;
EC_KEY_free(srvr_ecdh);
+ srvr_ecdh = NULL;
BN_CTX_free(bn_ctx);
+ bn_ctx = NULL;
EC_KEY_free(s->s3->tmp.ecdh);
s->s3->tmp.ecdh = NULL;
@@ -2202,6 +2204,9 @@ int ssl3_get_client_key_exchange(SSL *s)
s->session->master_key_length = s->method->ssl3_enc
->generate_master_secret(s,
s->session->master_key, premaster_secret, premaster_secret_len);
+ if (s->session->master_key_length == 0)
+ goto err;
+ s->session->extended_master_secret = s->s3->tmp.extended_master_secret;
OPENSSL_cleanse(premaster_secret, premaster_secret_len);
OPENSSL_free(premaster_secret);
@@ -2242,7 +2247,7 @@ int ssl3_get_cert_verify(SSL *s)
* client certificate. */
if (peer == NULL)
{
- if (s->s3->handshake_buffer && !ssl3_digest_cached_records(s))
+ if (s->s3->handshake_buffer && !ssl3_digest_cached_records(s, free_handshake_buffer))
return -1;
return 1;
}
@@ -2283,7 +2288,7 @@ int ssl3_get_cert_verify(SSL *s)
/* The handshake buffer is no longer necessary, and we may hash the
* current message.*/
- if (s->s3->handshake_buffer && !ssl3_digest_cached_records(s))
+ if (s->s3->handshake_buffer && !ssl3_digest_cached_records(s, free_handshake_buffer))
goto err;
ssl3_hash_current_message(s);
@@ -2452,7 +2457,7 @@ int ssl3_get_client_certificate(SSL *s)
goto f_err;
}
/* No client certificate so digest cached records */
- if (s->s3->handshake_buffer && !ssl3_digest_cached_records(s))
+ if (s->s3->handshake_buffer && !ssl3_digest_cached_records(s, free_handshake_buffer))
{
al=SSL_AD_INTERNAL_ERROR;
goto f_err;
@@ -2531,61 +2536,62 @@ int ssl3_send_new_session_ticket(SSL *s)
{
if (s->state == SSL3_ST_SW_SESSION_TICKET_A)
{
- unsigned char *p, *senc, *macstart;
- const unsigned char *const_p;
- int len, slen_full, slen;
- SSL_SESSION *sess;
+ uint8_t *session;
+ size_t session_len;
+ uint8_t *p, *macstart;
+ int len;
unsigned int hlen;
EVP_CIPHER_CTX ctx;
HMAC_CTX hctx;
SSL_CTX *tctx = s->initial_ctx;
unsigned char iv[EVP_MAX_IV_LENGTH];
unsigned char key_name[16];
+ /* The maximum overhead of encrypting the session is 16 (key
+ * name) + IV + one block of encryption overhead + HMAC. */
+ const size_t max_ticket_overhead = 16 + EVP_MAX_IV_LENGTH +
+ EVP_MAX_BLOCK_LENGTH + EVP_MAX_MD_SIZE;
- /* get session encoding length */
- slen_full = i2d_SSL_SESSION(s->session, NULL);
- /* Some length values are 16 bits, so forget it if session is
- * too long
- */
- if (slen_full > 0xFF00)
- return -1;
- senc = OPENSSL_malloc(slen_full);
- if (!senc)
- return -1;
- p = senc;
- i2d_SSL_SESSION(s->session, &p);
-
- /* create a fresh copy (not shared with other threads) to clean up */
- const_p = senc;
- sess = d2i_SSL_SESSION(NULL, &const_p, slen_full);
- if (sess == NULL)
+ /* Serialize the SSL_SESSION to be encoded into the ticket. */
+ if (!SSL_SESSION_to_bytes_for_ticket(s->session, &session,
+ &session_len))
{
- OPENSSL_free(senc);
return -1;
}
- sess->session_id_length = 0; /* ID is irrelevant for the ticket */
- slen = i2d_SSL_SESSION(sess, NULL);
- if (slen > slen_full) /* shouldn't ever happen */
+ /* If the session is too long, emit a dummy value rather than
+ * abort the connection. */
+ if (session_len > 0xFFFF - max_ticket_overhead)
{
- OPENSSL_free(senc);
- return -1;
+ const char kTicketPlaceholder[] = "TICKET TOO LARGE";
+ size_t placeholder_len = strlen(kTicketPlaceholder);
+
+ OPENSSL_free(session);
+
+ p = ssl_handshake_start(s);
+ /* Emit ticket_lifetime_hint. */
+ l2n(0, p);
+ /* Emit ticket. */
+ s2n(placeholder_len, p);
+ memcpy(p, kTicketPlaceholder, placeholder_len);
+ p += placeholder_len;
+
+ len = p - ssl_handshake_start(s);
+ ssl_set_handshake_header(s, SSL3_MT_NEWSESSION_TICKET, len);
+ s->state = SSL3_ST_SW_SESSION_TICKET_B;
+ return ssl_do_write(s);
}
- p = senc;
- i2d_SSL_SESSION(sess, &p);
- SSL_SESSION_free(sess);
/* Grow buffer if need be: the length calculation is as
- * follows handshake_header_length +
+ * follows: handshake_header_length +
* 4 (ticket lifetime hint) + 2 (ticket length) +
- * 16 (key name) + max_iv_len (iv length) +
- * session_length + max_enc_block_size (max encrypted session
- * length) + max_md_size (HMAC).
- */
+ * max_ticket_overhead + * session_length */
if (!BUF_MEM_grow(s->init_buf,
- SSL_HM_HEADER_LENGTH(s) + 22 + EVP_MAX_IV_LENGTH +
- EVP_MAX_BLOCK_LENGTH + EVP_MAX_MD_SIZE + slen))
+ SSL_HM_HEADER_LENGTH(s) + 6 +
+ max_ticket_overhead + session_len))
+ {
+ OPENSSL_free(session);
return -1;
+ }
p = ssl_handshake_start(s);
EVP_CIPHER_CTX_init(&ctx);
HMAC_CTX_init(&hctx);
@@ -2598,7 +2604,7 @@ int ssl3_send_new_session_ticket(SSL *s)
if (tctx->tlsext_ticket_key_cb(s, key_name, iv, &ctx,
&hctx, 1) < 0)
{
- OPENSSL_free(senc);
+ OPENSSL_free(session);
return -1;
}
}
@@ -2628,7 +2634,7 @@ int ssl3_send_new_session_ticket(SSL *s)
memcpy(p, iv, EVP_CIPHER_CTX_iv_length(&ctx));
p += EVP_CIPHER_CTX_iv_length(&ctx);
/* Encrypt session data */
- EVP_EncryptUpdate(&ctx, p, &len, senc, slen);
+ EVP_EncryptUpdate(&ctx, p, &len, session, session_len);
p += len;
EVP_EncryptFinal_ex(&ctx, p, &len);
p += len;
@@ -2647,7 +2653,7 @@ int ssl3_send_new_session_ticket(SSL *s)
p = ssl_handshake_start(s) + 4;
s2n(len - 6, p);
s->state=SSL3_ST_SW_SESSION_TICKET_B;
- OPENSSL_free(senc);
+ OPENSSL_free(session);
}
/* SSL3_ST_SW_SESSION_TICKET_B */
diff --git a/ssl/ssl_asn1.c b/ssl/ssl_asn1.c
index 5e86017..ef7ebdc 100644
--- a/ssl/ssl_asn1.c
+++ b/ssl/ssl_asn1.c
@@ -80,538 +80,530 @@
* OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
* OTHERWISE. */
-#include <assert.h>
-#include <stdio.h>
-#include <stdlib.h>
+#include <limits.h>
+#include <string.h>
-#include <openssl/asn1.h>
-#include <openssl/asn1_mac.h>
+#include <openssl/bytestring.h>
#include <openssl/err.h>
-#include <openssl/mem.h>
-#include <openssl/obj.h>
#include <openssl/x509.h>
#include "ssl_locl.h"
-OPENSSL_DECLARE_ERROR_REASON(SSL, CIPHER_CODE_WRONG_LENGTH);
-OPENSSL_DECLARE_ERROR_REASON(SSL, UNKNOWN_SSL_VERSION);
-OPENSSL_DECLARE_ERROR_REASON(SSL, BAD_LENGTH);
-OPENSSL_DECLARE_ERROR_FUNCTION(SSL, D2I_SSL_SESSION);
-
-
-typedef struct ssl_session_asn1_st
- {
- ASN1_INTEGER version;
- ASN1_INTEGER ssl_version;
- ASN1_OCTET_STRING cipher;
- ASN1_OCTET_STRING comp_id;
- ASN1_OCTET_STRING master_key;
- ASN1_OCTET_STRING session_id;
- ASN1_OCTET_STRING session_id_context;
- ASN1_INTEGER time;
- ASN1_INTEGER timeout;
- ASN1_INTEGER verify_result;
- ASN1_OCTET_STRING tlsext_hostname;
- ASN1_INTEGER tlsext_tick_lifetime;
- ASN1_OCTET_STRING tlsext_tick;
- ASN1_OCTET_STRING psk_identity_hint;
- ASN1_OCTET_STRING psk_identity;
- ASN1_OCTET_STRING peer_sha256;
- ASN1_OCTET_STRING original_handshake_hash;
- ASN1_OCTET_STRING tlsext_signed_cert_timestamp_list;
- ASN1_OCTET_STRING ocsp_response;
- } SSL_SESSION_ASN1;
-
-int i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp)
- {
-#define LSIZE2 (sizeof(long)*2)
- int v1=0,v2=0,v3=0,v4=0,v5=0,v7=0,v8=0,v13=0,v14=0,v15=0,v16=0;
- unsigned char buf[4],ibuf1[LSIZE2],ibuf2[LSIZE2];
- unsigned char ibuf3[LSIZE2],ibuf4[LSIZE2],ibuf5[LSIZE2];
- int v6=0,v9=0,v10=0;
- unsigned char ibuf6[LSIZE2];
- long l;
- SSL_SESSION_ASN1 a;
- M_ASN1_I2D_vars(in);
-
- if ((in == NULL) || ((in->cipher == NULL) && (in->cipher_id == 0)))
- return(0);
-
- /* Note that I cheat in the following 2 assignments. I know
- * that if the ASN1_INTEGER passed to ASN1_INTEGER_set
- * is > sizeof(long)+1, the buffer will not be re-OPENSSL_malloc()ed.
- * This is a bit evil but makes things simple, no dynamic allocation
- * to clean up :-) */
- a.version.length=LSIZE2;
- a.version.type=V_ASN1_INTEGER;
- a.version.data=ibuf1;
- ASN1_INTEGER_set(&(a.version),SSL_SESSION_ASN1_VERSION);
-
- a.ssl_version.length=LSIZE2;
- a.ssl_version.type=V_ASN1_INTEGER;
- a.ssl_version.data=ibuf2;
- ASN1_INTEGER_set(&(a.ssl_version),in->ssl_version);
-
- a.cipher.type=V_ASN1_OCTET_STRING;
- a.cipher.data=buf;
-
- if (in->cipher == NULL)
- l=in->cipher_id;
- else
- l=in->cipher->id;
- if (in->ssl_version == SSL2_VERSION)
- {
- a.cipher.length=3;
- buf[0]=((unsigned char)(l>>16L))&0xff;
- buf[1]=((unsigned char)(l>> 8L))&0xff;
- buf[2]=((unsigned char)(l ))&0xff;
- }
- else
- {
- a.cipher.length=2;
- buf[0]=((unsigned char)(l>>8L))&0xff;
- buf[1]=((unsigned char)(l ))&0xff;
- }
-
-
- a.master_key.length=in->master_key_length;
- a.master_key.type=V_ASN1_OCTET_STRING;
- a.master_key.data=in->master_key;
-
- a.session_id.length=in->session_id_length;
- a.session_id.type=V_ASN1_OCTET_STRING;
- a.session_id.data=in->session_id;
-
- a.session_id_context.length=in->sid_ctx_length;
- a.session_id_context.type=V_ASN1_OCTET_STRING;
- a.session_id_context.data=in->sid_ctx;
-
- if (in->time != 0L)
- {
- a.time.length=LSIZE2;
- a.time.type=V_ASN1_INTEGER;
- a.time.data=ibuf3;
- ASN1_INTEGER_set(&(a.time),in->time);
- }
-
- if (in->timeout != 0L)
- {
- a.timeout.length=LSIZE2;
- a.timeout.type=V_ASN1_INTEGER;
- a.timeout.data=ibuf4;
- ASN1_INTEGER_set(&(a.timeout),in->timeout);
- }
-
- if (in->verify_result != X509_V_OK)
- {
- a.verify_result.length=LSIZE2;
- a.verify_result.type=V_ASN1_INTEGER;
- a.verify_result.data=ibuf5;
- ASN1_INTEGER_set(&a.verify_result,in->verify_result);
- }
-
- if (in->tlsext_hostname)
- {
- a.tlsext_hostname.length=strlen(in->tlsext_hostname);
- a.tlsext_hostname.type=V_ASN1_OCTET_STRING;
- a.tlsext_hostname.data=(unsigned char *)in->tlsext_hostname;
- }
- if (in->tlsext_tick)
- {
- a.tlsext_tick.length= in->tlsext_ticklen;
- a.tlsext_tick.type=V_ASN1_OCTET_STRING;
- a.tlsext_tick.data=(unsigned char *)in->tlsext_tick;
- }
- if (in->tlsext_tick_lifetime_hint > 0)
- {
- a.tlsext_tick_lifetime.length=LSIZE2;
- a.tlsext_tick_lifetime.type=V_ASN1_INTEGER;
- a.tlsext_tick_lifetime.data=ibuf6;
- ASN1_INTEGER_set(&a.tlsext_tick_lifetime,in->tlsext_tick_lifetime_hint);
- }
- if (in->psk_identity_hint)
- {
- a.psk_identity_hint.length=strlen(in->psk_identity_hint);
- a.psk_identity_hint.type=V_ASN1_OCTET_STRING;
- a.psk_identity_hint.data=(unsigned char *)(in->psk_identity_hint);
- }
- if (in->psk_identity)
- {
- a.psk_identity.length=strlen(in->psk_identity);
- a.psk_identity.type=V_ASN1_OCTET_STRING;
- a.psk_identity.data=(unsigned char *)(in->psk_identity);
- }
-
- if (in->peer_sha256_valid)
- {
- a.peer_sha256.length = sizeof(in->peer_sha256);
- a.peer_sha256.type = V_ASN1_OCTET_STRING;
- a.peer_sha256.data = in->peer_sha256;
- }
-
- if (in->original_handshake_hash_len > 0)
- {
- a.original_handshake_hash.length = in->original_handshake_hash_len;
- a.original_handshake_hash.type = V_ASN1_OCTET_STRING;
- a.original_handshake_hash.data = in->original_handshake_hash;
- }
-
- if (in->tlsext_signed_cert_timestamp_list_length > 0)
- {
- a.tlsext_signed_cert_timestamp_list.length =
- in->tlsext_signed_cert_timestamp_list_length;
- a.tlsext_signed_cert_timestamp_list.type = V_ASN1_OCTET_STRING;
- a.tlsext_signed_cert_timestamp_list.data =
- in->tlsext_signed_cert_timestamp_list;
- }
-
- if (in->ocsp_response_length > 0)
- {
- a.ocsp_response.length = in->ocsp_response_length;
- a.ocsp_response.type = V_ASN1_OCTET_STRING;
- a.ocsp_response.data = in->ocsp_response;
- }
-
- M_ASN1_I2D_len(&(a.version), i2d_ASN1_INTEGER);
- M_ASN1_I2D_len(&(a.ssl_version), i2d_ASN1_INTEGER);
- M_ASN1_I2D_len(&(a.cipher), i2d_ASN1_OCTET_STRING);
- M_ASN1_I2D_len(&(a.session_id), i2d_ASN1_OCTET_STRING);
- M_ASN1_I2D_len(&(a.master_key), i2d_ASN1_OCTET_STRING);
- if (in->time != 0L)
- M_ASN1_I2D_len_EXP_opt(&(a.time),i2d_ASN1_INTEGER,1,v1);
- if (in->timeout != 0L)
- M_ASN1_I2D_len_EXP_opt(&(a.timeout),i2d_ASN1_INTEGER,2,v2);
- if (in->peer != NULL && in->peer_sha256_valid == 0)
- M_ASN1_I2D_len_EXP_opt(in->peer,i2d_X509,3,v3);
- M_ASN1_I2D_len_EXP_opt(&a.session_id_context,i2d_ASN1_OCTET_STRING,4,v4);
- if (in->verify_result != X509_V_OK)
- M_ASN1_I2D_len_EXP_opt(&(a.verify_result),i2d_ASN1_INTEGER,5,v5);
-
- if (in->tlsext_tick_lifetime_hint > 0)
- M_ASN1_I2D_len_EXP_opt(&a.tlsext_tick_lifetime, i2d_ASN1_INTEGER,9,v9);
- if (in->tlsext_tick)
- M_ASN1_I2D_len_EXP_opt(&(a.tlsext_tick), i2d_ASN1_OCTET_STRING,10,v10);
- if (in->tlsext_hostname)
- M_ASN1_I2D_len_EXP_opt(&(a.tlsext_hostname), i2d_ASN1_OCTET_STRING,6,v6);
- if (in->psk_identity_hint)
- M_ASN1_I2D_len_EXP_opt(&(a.psk_identity_hint), i2d_ASN1_OCTET_STRING,7,v7);
- if (in->psk_identity)
- M_ASN1_I2D_len_EXP_opt(&(a.psk_identity), i2d_ASN1_OCTET_STRING,8,v8);
- if (in->peer_sha256_valid)
- M_ASN1_I2D_len_EXP_opt(&(a.peer_sha256),i2d_ASN1_OCTET_STRING,13,v13);
- if (in->original_handshake_hash_len > 0)
- M_ASN1_I2D_len_EXP_opt(&(a.original_handshake_hash),i2d_ASN1_OCTET_STRING,14,v14);
- if (in->tlsext_signed_cert_timestamp_list_length > 0)
- M_ASN1_I2D_len_EXP_opt(&(a.tlsext_signed_cert_timestamp_list),
- i2d_ASN1_OCTET_STRING, 15, v15);
- if (in->ocsp_response_length > 0)
- M_ASN1_I2D_len_EXP_opt(&(a.ocsp_response), i2d_ASN1_OCTET_STRING, 16, v16);
-
- M_ASN1_I2D_seq_total();
-
- M_ASN1_I2D_put(&(a.version), i2d_ASN1_INTEGER);
- M_ASN1_I2D_put(&(a.ssl_version), i2d_ASN1_INTEGER);
- M_ASN1_I2D_put(&(a.cipher), i2d_ASN1_OCTET_STRING);
- M_ASN1_I2D_put(&(a.session_id), i2d_ASN1_OCTET_STRING);
- M_ASN1_I2D_put(&(a.master_key), i2d_ASN1_OCTET_STRING);
- if (in->time != 0L)
- M_ASN1_I2D_put_EXP_opt(&(a.time),i2d_ASN1_INTEGER,1,v1);
- if (in->timeout != 0L)
- M_ASN1_I2D_put_EXP_opt(&(a.timeout),i2d_ASN1_INTEGER,2,v2);
- if (in->peer != NULL && in->peer_sha256_valid == 0)
- M_ASN1_I2D_put_EXP_opt(in->peer,i2d_X509,3,v3);
- M_ASN1_I2D_put_EXP_opt(&a.session_id_context,i2d_ASN1_OCTET_STRING,4,
- v4);
- if (in->verify_result != X509_V_OK)
- M_ASN1_I2D_put_EXP_opt(&a.verify_result,i2d_ASN1_INTEGER,5,v5);
- if (in->tlsext_hostname)
- M_ASN1_I2D_put_EXP_opt(&(a.tlsext_hostname), i2d_ASN1_OCTET_STRING,6,v6);
- if (in->psk_identity_hint)
- M_ASN1_I2D_put_EXP_opt(&(a.psk_identity_hint), i2d_ASN1_OCTET_STRING,7,v7);
- if (in->psk_identity)
- M_ASN1_I2D_put_EXP_opt(&(a.psk_identity), i2d_ASN1_OCTET_STRING,8,v8);
- if (in->tlsext_tick_lifetime_hint > 0)
- M_ASN1_I2D_put_EXP_opt(&a.tlsext_tick_lifetime, i2d_ASN1_INTEGER,9,v9);
- if (in->tlsext_tick)
- M_ASN1_I2D_put_EXP_opt(&(a.tlsext_tick), i2d_ASN1_OCTET_STRING,10,v10);
- if (in->peer_sha256_valid)
- M_ASN1_I2D_put_EXP_opt(&(a.peer_sha256),i2d_ASN1_OCTET_STRING,13,v13);
- if (in->original_handshake_hash_len > 0)
- M_ASN1_I2D_put_EXP_opt(&(a.original_handshake_hash),i2d_ASN1_OCTET_STRING,14,v14);
- if (in->tlsext_signed_cert_timestamp_list_length > 0)
- M_ASN1_I2D_put_EXP_opt(&(a.tlsext_signed_cert_timestamp_list),
- i2d_ASN1_OCTET_STRING, 15, v15);
- if (in->ocsp_response > 0)
- M_ASN1_I2D_put_EXP_opt(&(a.ocsp_response), i2d_ASN1_OCTET_STRING, 16, v16);
-
- M_ASN1_I2D_finish();
- }
-
-SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a, const unsigned char **pp,
- long length)
- {
- int ssl_version=0,i;
- long id;
- ASN1_INTEGER ai,*aip;
- ASN1_OCTET_STRING os,*osp;
- M_ASN1_D2I_vars(a,SSL_SESSION *,SSL_SESSION_new);
-
- aip= &ai;
- osp= &os;
-
- M_ASN1_D2I_Init();
- M_ASN1_D2I_start_sequence();
-
- ai.data=NULL; ai.length=0;
- M_ASN1_D2I_get_x(ASN1_INTEGER,aip,d2i_ASN1_INTEGER);
- if (ai.data != NULL) { OPENSSL_free(ai.data); ai.data=NULL; ai.length=0; }
-
- /* we don't care about the version right now :-) */
- M_ASN1_D2I_get_x(ASN1_INTEGER,aip,d2i_ASN1_INTEGER);
- ssl_version=(int)ASN1_INTEGER_get(aip);
- ret->ssl_version=ssl_version;
- if (ai.data != NULL) { OPENSSL_free(ai.data); ai.data=NULL; ai.length=0; }
-
- os.data=NULL; os.length=0;
- M_ASN1_D2I_get_x(ASN1_OCTET_STRING,osp,d2i_ASN1_OCTET_STRING);
- if (ssl_version == SSL2_VERSION)
- {
- if (os.length != 3)
- {
- c.error=SSL_R_CIPHER_CODE_WRONG_LENGTH;
- c.line=__LINE__;
- goto err;
- }
- id=0x02000000L|
- ((unsigned long)os.data[0]<<16L)|
- ((unsigned long)os.data[1]<< 8L)|
- (unsigned long)os.data[2];
- }
- else if ((ssl_version>>8) >= SSL3_VERSION_MAJOR)
- {
- if (os.length != 2)
- {
- c.error=SSL_R_CIPHER_CODE_WRONG_LENGTH;
- c.line=__LINE__;
- goto err;
- }
- id=0x03000000L|
- ((unsigned long)os.data[0]<<8L)|
- (unsigned long)os.data[1];
- }
- else
- {
- c.error=SSL_R_UNKNOWN_SSL_VERSION;
- c.line=__LINE__;
- goto err;
- }
-
- ret->cipher_id=id;
- ret->cipher = ssl3_get_cipher_by_value(ret->cipher_id & 0xffff);
- if (ret->cipher == NULL)
- {
- c.error=SSL_R_UNSUPPORTED_CIPHER;
- c.line = __LINE__;
- goto err;
- }
-
- M_ASN1_D2I_get_x(ASN1_OCTET_STRING,osp,d2i_ASN1_OCTET_STRING);
- if ((ssl_version>>8) >= SSL3_VERSION_MAJOR)
- i=SSL3_MAX_SSL_SESSION_ID_LENGTH;
- else /* if (ssl_version>>8 == SSL2_VERSION_MAJOR) */
- i=SSL2_MAX_SSL_SESSION_ID_LENGTH;
-
- if (os.length > i)
- os.length = i;
- if (os.length > (int)sizeof(ret->session_id)) /* can't happen */
- os.length = sizeof(ret->session_id);
-
- ret->session_id_length=os.length;
- assert(os.length <= (int)sizeof(ret->session_id));
- memcpy(ret->session_id,os.data,os.length);
-
- M_ASN1_D2I_get_x(ASN1_OCTET_STRING,osp,d2i_ASN1_OCTET_STRING);
- if (os.length > SSL_MAX_MASTER_KEY_LENGTH)
- ret->master_key_length=SSL_MAX_MASTER_KEY_LENGTH;
- else
- ret->master_key_length=os.length;
- memcpy(ret->master_key,os.data,ret->master_key_length);
-
- os.length=0;
-
- /* [0] is the tag for key_arg, a no longer used remnant of
- * SSLv2. */
- M_ASN1_D2I_get_IMP_opt(osp,d2i_ASN1_OCTET_STRING,0,V_ASN1_OCTET_STRING);
- if (os.data != NULL) OPENSSL_free(os.data);
-
- ai.length=0;
- M_ASN1_D2I_get_EXP_opt(aip,d2i_ASN1_INTEGER,1);
- if (ai.data != NULL)
- {
- ret->time=ASN1_INTEGER_get(aip);
- OPENSSL_free(ai.data); ai.data=NULL; ai.length=0;
- }
- else
- ret->time=(unsigned long)time(NULL);
-
- ai.length=0;
- M_ASN1_D2I_get_EXP_opt(aip,d2i_ASN1_INTEGER,2);
- if (ai.data != NULL)
- {
- ret->timeout=ASN1_INTEGER_get(aip);
- OPENSSL_free(ai.data); ai.data=NULL; ai.length=0;
- }
- else
- ret->timeout=3;
-
- if (ret->peer != NULL)
- {
- X509_free(ret->peer);
- ret->peer=NULL;
- }
- M_ASN1_D2I_get_EXP_opt(ret->peer,d2i_X509,3);
-
- os.length=0;
- os.data=NULL;
- M_ASN1_D2I_get_EXP_opt(osp,d2i_ASN1_OCTET_STRING,4);
-
- if(os.data != NULL)
- {
- if (os.length > SSL_MAX_SID_CTX_LENGTH)
- {
- c.error=SSL_R_BAD_LENGTH;
- c.line=__LINE__;
- goto err;
- }
- else
- {
- ret->sid_ctx_length=os.length;
- memcpy(ret->sid_ctx,os.data,os.length);
- }
- OPENSSL_free(os.data); os.data=NULL; os.length=0;
- }
- else
- ret->sid_ctx_length=0;
-
- ai.length=0;
- M_ASN1_D2I_get_EXP_opt(aip,d2i_ASN1_INTEGER,5);
- if (ai.data != NULL)
- {
- ret->verify_result=ASN1_INTEGER_get(aip);
- OPENSSL_free(ai.data); ai.data=NULL; ai.length=0;
- }
- else
- ret->verify_result=X509_V_OK;
-
- os.length=0;
- os.data=NULL;
- M_ASN1_D2I_get_EXP_opt(osp,d2i_ASN1_OCTET_STRING,6);
- if (os.data)
- {
- ret->tlsext_hostname = BUF_strndup((char *)os.data, os.length);
- OPENSSL_free(os.data);
- os.data = NULL;
- os.length = 0;
- }
- else
- ret->tlsext_hostname=NULL;
-
- os.length=0;
- os.data=NULL;
- M_ASN1_D2I_get_EXP_opt(osp,d2i_ASN1_OCTET_STRING,7);
- if (os.data)
- {
- ret->psk_identity_hint = BUF_strndup((char *)os.data, os.length);
- OPENSSL_free(os.data);
- os.data = NULL;
- os.length = 0;
- }
- else
- ret->psk_identity_hint=NULL;
-
- os.length=0;
- os.data=NULL;
- M_ASN1_D2I_get_EXP_opt(osp,d2i_ASN1_OCTET_STRING,8);
- if (os.data)
- {
- ret->psk_identity = BUF_strndup((char *)os.data, os.length);
- OPENSSL_free(os.data);
- os.data = NULL;
- os.length = 0;
- }
- else
- ret->psk_identity=NULL;
-
- ai.length=0;
- M_ASN1_D2I_get_EXP_opt(aip,d2i_ASN1_INTEGER,9);
- if (ai.data != NULL)
- {
- ret->tlsext_tick_lifetime_hint=ASN1_INTEGER_get(aip);
- OPENSSL_free(ai.data); ai.data=NULL; ai.length=0;
- }
- else if (ret->tlsext_ticklen && ret->session_id_length)
- ret->tlsext_tick_lifetime_hint = -1;
- else
- ret->tlsext_tick_lifetime_hint=0;
- os.length=0;
- os.data=NULL;
- M_ASN1_D2I_get_EXP_opt(osp,d2i_ASN1_OCTET_STRING,10);
- if (os.data)
- {
- ret->tlsext_tick = os.data;
- ret->tlsext_ticklen = os.length;
- os.data = NULL;
- os.length = 0;
- }
- else
- ret->tlsext_tick=NULL;
-
- os.length=0;
- os.data=NULL;
- M_ASN1_D2I_get_EXP_opt(osp,d2i_ASN1_OCTET_STRING,13);
- if (os.data && os.length == sizeof(ret->peer_sha256))
- {
- memcpy(ret->peer_sha256, os.data, sizeof(ret->peer_sha256));
- ret->peer_sha256_valid = 1;
- OPENSSL_free(os.data);
- os.data = NULL;
- }
-
- os.length=0;
- os.data=NULL;
- M_ASN1_D2I_get_EXP_opt(osp,d2i_ASN1_OCTET_STRING,14);
- if (os.data && os.length < (int)sizeof(ret->original_handshake_hash))
- {
- memcpy(ret->original_handshake_hash, os.data, os.length);
- ret->original_handshake_hash_len = os.length;
- OPENSSL_free(os.data);
- os.data = NULL;
- }
-
- os.length = 0;
- os.data = NULL;
- M_ASN1_D2I_get_EXP_opt(osp, d2i_ASN1_OCTET_STRING, 15);
- if (os.data)
- {
- if (ret->tlsext_signed_cert_timestamp_list)
- OPENSSL_free(ret->tlsext_signed_cert_timestamp_list);
- ret->tlsext_signed_cert_timestamp_list = os.data;
- ret->tlsext_signed_cert_timestamp_list_length = os.length;
- os.data = NULL;
- }
-
- os.length = 0;
- os.data = NULL;
- M_ASN1_D2I_get_EXP_opt(osp, d2i_ASN1_OCTET_STRING, 16);
- if (os.data)
- {
- if (ret->ocsp_response)
- OPENSSL_free(ret->ocsp_response);
- ret->ocsp_response = os.data;
- ret->ocsp_response_length = os.length;
- os.data = NULL;
- }
-
-
- M_ASN1_D2I_Finish(a,SSL_SESSION_free,SSL_F_D2I_SSL_SESSION);
- }
+
+/* An SSL_SESSION is serialized as the following ASN.1 structure:
+ *
+ * SSLSession ::= SEQUENCE {
+ * version INTEGER (1), -- ignored
+ * sslVersion INTEGER, -- protocol version number
+ * cipher OCTET STRING, -- two bytes long
+ * sessionID OCTET STRING,
+ * masterKey OCTET STRING,
+ * time [1] INTEGER OPTIONAL, -- seconds since UNIX epoch
+ * timeout [2] INTEGER OPTIONAL, -- in seconds
+ * peer [3] Certificate OPTIONAL,
+ * sessionIDContext [4] OCTET STRING OPTIONAL,
+ * verifyResult [5] INTEGER OPTIONAL, -- one of X509_V_* codes
+ * hostName [6] OCTET STRING OPTIONAL,
+ * -- from server_name extension
+ * pskIdentityHint [7] OCTET STRING OPTIONAL,
+ * pskIdentity [8] OCTET STRING OPTIONAL,
+ * ticketLifetimeHint [9] INTEGER OPTIONAL, -- client-only
+ * ticket [10] OCTET STRING OPTIONAL, -- client-only
+ * peerSHA256 [13] OCTET STRING OPTIONAL,
+ * originalHandshakeHash [14] OCTET STRING OPTIONAL,
+ * signedCertTimestampList [15] OCTET STRING OPTIONAL,
+ * -- contents of SCT extension
+ * ocspResponse [16] OCTET STRING OPTIONAL,
+ * -- stapled OCSP response from the server
+ * extendedMasterSecret [17] BOOLEAN OPTIONAL,
+ * }
+ *
+ * Note: When the relevant features were #ifdef'd out, support for
+ * parsing compressionMethod [11] and srpUsername [12] was lost. */
+
+static const int kTimeTag =
+ CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 1;
+static const int kTimeoutTag =
+ CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 2;
+static const int kPeerTag =
+ CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 3;
+ static const int kSessionIDContextTag =
+ CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 4;
+static const int kVerifyResultTag =
+ CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 5;
+static const int kHostNameTag =
+ CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 6;
+static const int kPSKIdentityHintTag =
+ CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 7;
+static const int kPSKIdentityTag =
+ CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 8;
+static const int kTicketLifetimeHintTag =
+ CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 9;
+static const int kTicketTag =
+ CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 10;
+static const int kPeerSHA256Tag =
+ CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 13;
+static const int kOriginalHandshakeHashTag =
+ CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 14;
+static const int kSignedCertTimestampListTag =
+ CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 15;
+static const int kOCSPResponseTag =
+ CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 16;
+static const int kExtendedMasterSecretTag =
+ CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 17;
+
+static int SSL_SESSION_to_bytes_full(SSL_SESSION *in, uint8_t **out_data,
+ size_t *out_len, int for_ticket) {
+ CBB cbb, session, child, child2;
+ uint16_t cipher_id;
+
+ if (in == NULL || (in->cipher == NULL && in->cipher_id == 0)) {
+ return 0;
+ }
+
+ if (!CBB_init(&cbb, 0)) {
+ return 0;
+ }
+
+ if (in->cipher == NULL) {
+ cipher_id = in->cipher_id & 0xffff;
+ } else {
+ cipher_id = in->cipher->id & 0xffff;
+ }
+
+ if (!CBB_add_asn1(&cbb, &session, CBS_ASN1_SEQUENCE) ||
+ !CBB_add_asn1_uint64(&session, SSL_SESSION_ASN1_VERSION) ||
+ !CBB_add_asn1_uint64(&session, in->ssl_version) ||
+ !CBB_add_asn1(&session, &child, CBS_ASN1_OCTETSTRING) ||
+ !CBB_add_u16(&child, cipher_id) ||
+ !CBB_add_asn1(&session, &child, CBS_ASN1_OCTETSTRING) ||
+ /* The session ID is irrelevant for a session ticket. */
+ !CBB_add_bytes(&child, in->session_id,
+ for_ticket ? 0 : in->session_id_length) ||
+ !CBB_add_asn1(&session, &child, CBS_ASN1_OCTETSTRING) ||
+ !CBB_add_bytes(&child, in->master_key, in->master_key_length)) {
+ OPENSSL_PUT_ERROR(SSL, i2d_SSL_SESSION, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (in->time != 0) {
+ if (!CBB_add_asn1(&session, &child, kTimeTag) ||
+ !CBB_add_asn1_uint64(&child, in->time)) {
+ OPENSSL_PUT_ERROR(SSL, i2d_SSL_SESSION, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ }
+
+ if (in->timeout != 0) {
+ if (!CBB_add_asn1(&session, &child, kTimeoutTag) ||
+ !CBB_add_asn1_uint64(&child, in->timeout)) {
+ OPENSSL_PUT_ERROR(SSL, i2d_SSL_SESSION, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ }
+
+ /* The peer certificate is only serialized if the SHA-256 isn't
+ * serialized instead. */
+ if (in->peer && !in->peer_sha256_valid) {
+ uint8_t *buf;
+ int len = i2d_X509(in->peer, NULL);
+ if (len < 0) {
+ goto err;
+ }
+ if (!CBB_add_asn1(&session, &child, kPeerTag) ||
+ !CBB_add_space(&child, &buf, len)) {
+ OPENSSL_PUT_ERROR(SSL, i2d_SSL_SESSION, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ if (buf != NULL && i2d_X509(in->peer, &buf) < 0) {
+ goto err;
+ }
+ }
+
+ /* Although it is OPTIONAL and usually empty, OpenSSL has
+ * historically always encoded the sid_ctx. */
+ if (!CBB_add_asn1(&session, &child, kSessionIDContextTag) ||
+ !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) ||
+ !CBB_add_bytes(&child2, in->sid_ctx, in->sid_ctx_length)) {
+ OPENSSL_PUT_ERROR(SSL, i2d_SSL_SESSION, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (in->verify_result != X509_V_OK) {
+ if (!CBB_add_asn1(&session, &child, kVerifyResultTag) ||
+ !CBB_add_asn1_uint64(&child, in->verify_result)) {
+ OPENSSL_PUT_ERROR(SSL, i2d_SSL_SESSION, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ }
+
+ if (in->tlsext_hostname) {
+ if (!CBB_add_asn1(&session, &child, kHostNameTag) ||
+ !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) ||
+ !CBB_add_bytes(&child2, (const uint8_t *)in->tlsext_hostname,
+ strlen(in->tlsext_hostname))) {
+ OPENSSL_PUT_ERROR(SSL, i2d_SSL_SESSION, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ }
+
+ if (in->psk_identity_hint) {
+ if (!CBB_add_asn1(&session, &child, kPSKIdentityHintTag) ||
+ !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) ||
+ !CBB_add_bytes(&child2, (const uint8_t *)in->psk_identity_hint,
+ strlen(in->psk_identity_hint))) {
+ OPENSSL_PUT_ERROR(SSL, i2d_SSL_SESSION, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ }
+
+ if (in->psk_identity) {
+ if (!CBB_add_asn1(&session, &child, kPSKIdentityTag) ||
+ !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) ||
+ !CBB_add_bytes(&child2, (const uint8_t *)in->psk_identity,
+ strlen(in->psk_identity))) {
+ OPENSSL_PUT_ERROR(SSL, i2d_SSL_SESSION, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ }
+
+ if (in->tlsext_tick_lifetime_hint > 0) {
+ if (!CBB_add_asn1(&session, &child, kTicketLifetimeHintTag) ||
+ !CBB_add_asn1_uint64(&child, in->tlsext_tick_lifetime_hint)) {
+ OPENSSL_PUT_ERROR(SSL, i2d_SSL_SESSION, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ }
+
+ if (in->tlsext_tick) {
+ if (!CBB_add_asn1(&session, &child, kTicketTag) ||
+ !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) ||
+ !CBB_add_bytes(&child2, in->tlsext_tick, in->tlsext_ticklen)) {
+ OPENSSL_PUT_ERROR(SSL, i2d_SSL_SESSION, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ }
+
+ if (in->peer_sha256_valid) {
+ if (!CBB_add_asn1(&session, &child, kPeerSHA256Tag) ||
+ !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) ||
+ !CBB_add_bytes(&child2, in->peer_sha256, sizeof(in->peer_sha256))) {
+ OPENSSL_PUT_ERROR(SSL, i2d_SSL_SESSION, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ }
+
+ if (in->original_handshake_hash_len > 0) {
+ if (!CBB_add_asn1(&session, &child, kOriginalHandshakeHashTag) ||
+ !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) ||
+ !CBB_add_bytes(&child2, in->original_handshake_hash,
+ in->original_handshake_hash_len)) {
+ OPENSSL_PUT_ERROR(SSL, i2d_SSL_SESSION, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ }
+
+ if (in->tlsext_signed_cert_timestamp_list_length > 0) {
+ if (!CBB_add_asn1(&session, &child, kSignedCertTimestampListTag) ||
+ !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) ||
+ !CBB_add_bytes(&child2, in->tlsext_signed_cert_timestamp_list,
+ in->tlsext_signed_cert_timestamp_list_length)) {
+ OPENSSL_PUT_ERROR(SSL, i2d_SSL_SESSION, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ }
+
+ if (in->ocsp_response_length > 0) {
+ if (!CBB_add_asn1(&session, &child, kOCSPResponseTag) ||
+ !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) ||
+ !CBB_add_bytes(&child2, in->ocsp_response, in->ocsp_response_length)) {
+ OPENSSL_PUT_ERROR(SSL, i2d_SSL_SESSION, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ }
+
+ if (in->extended_master_secret) {
+ if (!CBB_add_asn1(&session, &child, kExtendedMasterSecretTag) ||
+ !CBB_add_asn1(&child, &child2, CBS_ASN1_BOOLEAN) ||
+ !CBB_add_u8(&child2, 0xff)) {
+ OPENSSL_PUT_ERROR(SSL, i2d_SSL_SESSION, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ }
+
+ if (!CBB_finish(&cbb, out_data, out_len)) {
+ OPENSSL_PUT_ERROR(SSL, i2d_SSL_SESSION, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ return 1;
+
+ err:
+ CBB_cleanup(&cbb);
+ return 0;
+}
+
+int SSL_SESSION_to_bytes(SSL_SESSION *in, uint8_t **out_data, size_t *out_len) {
+ return SSL_SESSION_to_bytes_full(in, out_data, out_len, 0);
+}
+
+int SSL_SESSION_to_bytes_for_ticket(SSL_SESSION *in, uint8_t **out_data,
+ size_t *out_len) {
+ return SSL_SESSION_to_bytes_full(in, out_data, out_len, 1);
+}
+
+int i2d_SSL_SESSION(SSL_SESSION *in, uint8_t **pp) {
+ uint8_t *out;
+ size_t len;
+
+ if (!SSL_SESSION_to_bytes(in, &out, &len)) {
+ return -1;
+ }
+
+ if (len > INT_MAX) {
+ OPENSSL_free(out);
+ OPENSSL_PUT_ERROR(SSL, i2d_SSL_SESSION, ERR_R_OVERFLOW);
+ return -1;
+ }
+
+ if (pp) {
+ memcpy(*pp, out, len);
+ *pp += len;
+ }
+ OPENSSL_free(out);
+
+ return len;
+}
+
+/* d2i_SSL_SESSION_get_string gets an optional ASN.1 OCTET STRING
+ * explicitly tagged with |tag| from |cbs| and saves it in |*out|. On
+ * entry, if |*out| is not NULL, it frees the existing contents. If
+ * the element was not found, it sets |*out| to NULL. It returns one
+ * on success, whether or not the element was found, and zero on
+ * decode error. */
+static int d2i_SSL_SESSION_get_string(CBS *cbs, char **out, unsigned tag) {
+ CBS value;
+ int present;
+ if (!CBS_get_optional_asn1_octet_string(cbs, &value, &present, tag)) {
+ OPENSSL_PUT_ERROR(SSL, d2i_SSL_SESSION, SSL_R_INVALID_SSL_SESSION);
+ return 0;
+ }
+ if (present) {
+ if (CBS_contains_zero_byte(&value)) {
+ OPENSSL_PUT_ERROR(SSL, d2i_SSL_SESSION, SSL_R_INVALID_SSL_SESSION);
+ return 0;
+ }
+ if (!CBS_strdup(&value, out)) {
+ OPENSSL_PUT_ERROR(SSL, d2i_SSL_SESSION, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ } else if (*out) {
+ OPENSSL_free(*out);
+ *out = NULL;
+ }
+ return 1;
+}
+
+/* d2i_SSL_SESSION_get_string gets an optional ASN.1 OCTET STRING
+ * explicitly tagged with |tag| from |cbs| and stows it in |*out_ptr|
+ * and |*out_len|. If |*out_ptr| is not NULL, it frees the existing
+ * contents. On entry, if the element was not found, it sets
+ * |*out_ptr| to NULL. It returns one on success, whether or not the
+ * element was found, and zero on decode error. */
+static int d2i_SSL_SESSION_get_octet_string(CBS *cbs, uint8_t **out_ptr,
+ size_t *out_len, unsigned tag) {
+ CBS value;
+ if (!CBS_get_optional_asn1_octet_string(cbs, &value, NULL, tag)) {
+ OPENSSL_PUT_ERROR(SSL, d2i_SSL_SESSION, SSL_R_INVALID_SSL_SESSION);
+ return 0;
+ }
+ if (!CBS_stow(&value, out_ptr, out_len)) {
+ OPENSSL_PUT_ERROR(SSL, d2i_SSL_SESSION, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ return 1;
+}
+
+SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a, const uint8_t **pp, long length) {
+ SSL_SESSION *ret = NULL;
+ CBS cbs, session, cipher, session_id, master_key;
+ CBS peer, sid_ctx, peer_sha256, original_handshake_hash;
+ int has_peer, has_peer_sha256, extended_master_secret;
+ uint64_t version, ssl_version;
+ uint64_t session_time, timeout, verify_result, ticket_lifetime_hint;
+
+ if (a && *a) {
+ ret = *a;
+ } else {
+ ret = SSL_SESSION_new();
+ if (ret == NULL) {
+ goto err;
+ }
+ }
+
+ CBS_init(&cbs, *pp, length);
+ if (!CBS_get_asn1(&cbs, &session, CBS_ASN1_SEQUENCE) ||
+ !CBS_get_asn1_uint64(&session, &version) ||
+ !CBS_get_asn1_uint64(&session, &ssl_version) ||
+ !CBS_get_asn1(&session, &cipher, CBS_ASN1_OCTETSTRING) ||
+ !CBS_get_asn1(&session, &session_id, CBS_ASN1_OCTETSTRING) ||
+ !CBS_get_asn1(&session, &master_key, CBS_ASN1_OCTETSTRING) ||
+ !CBS_get_optional_asn1_uint64(&session, &session_time, kTimeTag,
+ time(NULL)) ||
+ !CBS_get_optional_asn1_uint64(&session, &timeout, kTimeoutTag, 3) ||
+ !CBS_get_optional_asn1(&session, &peer, &has_peer, kPeerTag) ||
+ !CBS_get_optional_asn1_octet_string(&session, &sid_ctx, NULL,
+ kSessionIDContextTag) ||
+ !CBS_get_optional_asn1_uint64(&session, &verify_result, kVerifyResultTag,
+ X509_V_OK)) {
+ OPENSSL_PUT_ERROR(SSL, d2i_SSL_SESSION, SSL_R_INVALID_SSL_SESSION);
+ goto err;
+ }
+ if (!d2i_SSL_SESSION_get_string(&session, &ret->tlsext_hostname,
+ kHostNameTag) ||
+ !d2i_SSL_SESSION_get_string(&session, &ret->psk_identity_hint,
+ kPSKIdentityHintTag) ||
+ !d2i_SSL_SESSION_get_string(&session, &ret->psk_identity,
+ kPSKIdentityTag)) {
+ goto err;
+ }
+ if (!CBS_get_optional_asn1_uint64(&session, &ticket_lifetime_hint,
+ kTicketLifetimeHintTag, 0)) {
+ OPENSSL_PUT_ERROR(SSL, d2i_SSL_SESSION, SSL_R_INVALID_SSL_SESSION);
+ goto err;
+ }
+ if (!d2i_SSL_SESSION_get_octet_string(&session, &ret->tlsext_tick,
+ &ret->tlsext_ticklen, kTicketTag)) {
+ goto err;
+ }
+ if (!CBS_get_optional_asn1_octet_string(&session, &peer_sha256,
+ &has_peer_sha256, kPeerSHA256Tag) ||
+ !CBS_get_optional_asn1_octet_string(&session, &original_handshake_hash,
+ NULL, kOriginalHandshakeHashTag)) {
+ OPENSSL_PUT_ERROR(SSL, d2i_SSL_SESSION, SSL_R_INVALID_SSL_SESSION);
+ goto err;
+ }
+ if (!d2i_SSL_SESSION_get_octet_string(
+ &session, &ret->tlsext_signed_cert_timestamp_list,
+ &ret->tlsext_signed_cert_timestamp_list_length,
+ kSignedCertTimestampListTag) ||
+ !d2i_SSL_SESSION_get_octet_string(
+ &session, &ret->ocsp_response, &ret->ocsp_response_length,
+ kOCSPResponseTag)) {
+ goto err;
+ }
+ if (!CBS_get_optional_asn1_bool(&session, &extended_master_secret,
+ kExtendedMasterSecretTag,
+ 0 /* default to false */)) {
+ OPENSSL_PUT_ERROR(SSL, d2i_SSL_SESSION, SSL_R_INVALID_SSL_SESSION);
+ goto err;
+ }
+ ret->extended_master_secret = extended_master_secret;
+
+ /* Ignore |version|. The structure version number is ignored. */
+
+ /* Only support SSLv3/TLS and DTLS. */
+ if ((ssl_version >> 8) != SSL3_VERSION_MAJOR &&
+ (ssl_version >> 8) != (DTLS1_VERSION >> 8)) {
+ OPENSSL_PUT_ERROR(SSL, d2i_SSL_SESSION, SSL_R_UNKNOWN_SSL_VERSION);
+ goto err;
+ }
+ ret->ssl_version = ssl_version;
+
+ if (CBS_len(&cipher) != 2) {
+ OPENSSL_PUT_ERROR(SSL, d2i_SSL_SESSION, SSL_R_CIPHER_CODE_WRONG_LENGTH);
+ goto err;
+ }
+ ret->cipher_id =
+ 0x03000000L | (CBS_data(&cipher)[0] << 8L) | CBS_data(&cipher)[1];
+ ret->cipher = ssl3_get_cipher_by_value(ret->cipher_id & 0xffff);
+ if (ret->cipher == NULL) {
+ OPENSSL_PUT_ERROR(SSL, d2i_SSL_SESSION, SSL_R_UNSUPPORTED_CIPHER);
+ goto err;
+ }
+
+ if (CBS_len(&session_id) > SSL3_MAX_SSL_SESSION_ID_LENGTH) {
+ OPENSSL_PUT_ERROR(SSL, d2i_SSL_SESSION, SSL_R_INVALID_SSL_SESSION);
+ goto err;
+ }
+ memcpy(ret->session_id, CBS_data(&session_id), CBS_len(&session_id));
+ ret->session_id_length = CBS_len(&session_id);
+
+ if (CBS_len(&master_key) > SSL_MAX_MASTER_KEY_LENGTH) {
+ OPENSSL_PUT_ERROR(SSL, d2i_SSL_SESSION, SSL_R_INVALID_SSL_SESSION);
+ goto err;
+ }
+ memcpy(ret->master_key, CBS_data(&master_key), CBS_len(&master_key));
+ ret->master_key_length = CBS_len(&master_key);
+
+ if (session_time > LONG_MAX ||
+ timeout > LONG_MAX) {
+ OPENSSL_PUT_ERROR(SSL, d2i_SSL_SESSION, SSL_R_INVALID_SSL_SESSION);
+ goto err;
+ }
+ ret->time = session_time;
+ ret->timeout = timeout;
+
+ if (ret->peer != NULL) {
+ X509_free(ret->peer);
+ ret->peer = NULL;
+ }
+ if (has_peer) {
+ const uint8_t *ptr;
+ ptr = CBS_data(&peer);
+ ret->peer = d2i_X509(NULL, &ptr, CBS_len(&peer));
+ if (ret->peer == NULL) {
+ goto err;
+ }
+ if (ptr != CBS_data(&peer) + CBS_len(&peer)) {
+ OPENSSL_PUT_ERROR(SSL, d2i_SSL_SESSION, SSL_R_INVALID_SSL_SESSION);
+ goto err;
+ }
+ }
+
+ if (CBS_len(&sid_ctx) > sizeof(ret->sid_ctx)) {
+ OPENSSL_PUT_ERROR(SSL, d2i_SSL_SESSION, SSL_R_INVALID_SSL_SESSION);
+ goto err;
+ }
+ memcpy(ret->sid_ctx, CBS_data(&sid_ctx), CBS_len(&sid_ctx));
+ ret->sid_ctx_length = CBS_len(&sid_ctx);
+
+ if (verify_result > LONG_MAX ||
+ ticket_lifetime_hint > 0xffffffff) {
+ OPENSSL_PUT_ERROR(SSL, d2i_SSL_SESSION, SSL_R_INVALID_SSL_SESSION);
+ goto err;
+ }
+ ret->verify_result = verify_result;
+ ret->tlsext_tick_lifetime_hint = ticket_lifetime_hint;
+
+ if (has_peer_sha256) {
+ if (CBS_len(&peer_sha256) != sizeof(ret->peer_sha256)) {
+ OPENSSL_PUT_ERROR(SSL, d2i_SSL_SESSION, SSL_R_INVALID_SSL_SESSION);
+ goto err;
+ }
+ memcpy(ret->peer_sha256, CBS_data(&peer_sha256), sizeof(ret->peer_sha256));
+ ret->peer_sha256_valid = 1;
+ } else {
+ ret->peer_sha256_valid = 0;
+ }
+
+ if (CBS_len(&original_handshake_hash) >
+ sizeof(ret->original_handshake_hash)) {
+ OPENSSL_PUT_ERROR(SSL, d2i_SSL_SESSION, SSL_R_INVALID_SSL_SESSION);
+ goto err;
+ }
+ memcpy(ret->original_handshake_hash, CBS_data(&original_handshake_hash),
+ CBS_len(&original_handshake_hash));
+ ret->original_handshake_hash_len = CBS_len(&original_handshake_hash);
+
+ if (a) {
+ *a = ret;
+ }
+ *pp = CBS_data(&cbs);
+ return ret;
+
+err:
+ if (a && *a != ret) {
+ SSL_SESSION_free(ret);
+ }
+ return NULL;
+}
diff --git a/ssl/ssl_ciph.c b/ssl/ssl_ciph.c
index 040a2db..97169f2 100644
--- a/ssl/ssl_ciph.c
+++ b/ssl/ssl_ciph.c
@@ -447,12 +447,6 @@ static void ssl_cipher_collect_ciphers(const SSL_METHOD *ssl_method,
co_list[co_list_num].active = 0;
co_list[co_list_num].in_group = 0;
co_list_num++;
-#ifdef KSSL_DEBUG
- printf("\t%d: %s %lx %lx %lx\n",i,c->name,c->id,c->algorithm_mkey,c->algorithm_auth);
-#endif /* KSSL_DEBUG */
- /*
- if (!sk_push(ca_list,(char *)c)) goto err;
- */
}
}
@@ -1023,9 +1017,6 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
* it is used for allocation.
*/
num_of_ciphers = ssl_method->num_ciphers();
-#ifdef KSSL_DEBUG
- printf("ssl_create_cipher_list() for %d ciphers\n", num_of_ciphers);
-#endif /* KSSL_DEBUG */
co_list = (CIPHER_ORDER *)OPENSSL_malloc(sizeof(CIPHER_ORDER) * num_of_ciphers);
if (co_list == NULL)
{
@@ -1209,11 +1200,7 @@ const char *SSL_CIPHER_description(const SSL_CIPHER *cipher, char *buf, int len)
const char *ver;
const char *kx,*au,*enc,*mac;
unsigned long alg_mkey,alg_auth,alg_enc,alg_mac,alg_ssl;
-#ifdef KSSL_DEBUG
- static const char *format="%-23s %s Kx=%-8s Au=%-4s Enc=%-9s Mac=%-4s AL=%lx/%lx/%lx/%lx/%lx\n";
-#else
static const char *format="%-23s %s Kx=%-8s Au=%-4s Enc=%-9s Mac=%-4s\n";
-#endif /* KSSL_DEBUG */
alg_mkey = cipher->algorithm_mkey;
alg_auth = cipher->algorithm_auth;
@@ -1324,11 +1311,7 @@ const char *SSL_CIPHER_description(const SSL_CIPHER *cipher, char *buf, int len)
else if (len < 128)
return("Buffer too small");
-#ifdef KSSL_DEBUG
- BIO_snprintf(buf,len,format,cipher->name,ver,kx,au,enc,mac,alg_mkey,alg_auth,alg_enc,alg_mac,alg_ssl);
-#else
BIO_snprintf(buf,len,format,cipher->name,ver,kx,au,enc,mac);
-#endif /* KSSL_DEBUG */
return(buf);
}
diff --git a/ssl/ssl_error.c b/ssl/ssl_error.c
index 0ba125b..b070b5f 100644
--- a/ssl/ssl_error.c
+++ b/ssl/ssl_error.c
@@ -39,6 +39,7 @@ const ERR_STRING_DATA SSL_error_string_data[] = {
{ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SESSION_new, 0), "SSL_SESSION_new"},
{ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SESSION_print_fp, 0), "SSL_SESSION_print_fp"},
{ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SESSION_set1_id_context, 0), "SSL_SESSION_set1_id_context"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SESSION_to_bytes_full, 0), "SSL_SESSION_to_bytes_full"},
{ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_add_dir_cert_subjects_to_stack, 0), "SSL_add_dir_cert_subjects_to_stack"},
{ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_add_file_cert_subjects_to_stack, 0), "SSL_add_file_cert_subjects_to_stack"},
{ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_check_private_key, 0), "SSL_check_private_key"},
@@ -70,6 +71,9 @@ const ERR_STRING_DATA SSL_error_string_data[] = {
{ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_write, 0), "SSL_write"},
{ERR_PACK(ERR_LIB_SSL, SSL_F_authz_find_data, 0), "authz_find_data"},
{ERR_PACK(ERR_LIB_SSL, SSL_F_check_suiteb_cipher_list, 0), "check_suiteb_cipher_list"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_d2i_SSL_SESSION, 0), "d2i_SSL_SESSION"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_d2i_SSL_SESSION_get_octet_string, 0), "d2i_SSL_SESSION_get_octet_string"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_d2i_SSL_SESSION_get_string, 0), "d2i_SSL_SESSION_get_string"},
{ERR_PACK(ERR_LIB_SSL, SSL_F_do_dtls1_write, 0), "do_dtls1_write"},
{ERR_PACK(ERR_LIB_SSL, SSL_F_do_ssl3_write, 0), "do_ssl3_write"},
{ERR_PACK(ERR_LIB_SSL, SSL_F_dtls1_accept, 0), "dtls1_accept"},
@@ -87,6 +91,7 @@ const ERR_STRING_DATA SSL_error_string_data[] = {
{ERR_PACK(ERR_LIB_SSL, SSL_F_dtls1_write_app_data_bytes, 0), "dtls1_write_app_data_bytes"},
{ERR_PACK(ERR_LIB_SSL, SSL_F_fclose, 0), "fclose"},
{ERR_PACK(ERR_LIB_SSL, SSL_F_fprintf, 0), "fprintf"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_i2d_SSL_SESSION, 0), "i2d_SSL_SESSION"},
{ERR_PACK(ERR_LIB_SSL, SSL_F_printf, 0), "printf"},
{ERR_PACK(ERR_LIB_SSL, SSL_F_read_authz, 0), "read_authz"},
{ERR_PACK(ERR_LIB_SSL, SSL_F_ssl23_accept, 0), "ssl23_accept"},
@@ -136,6 +141,7 @@ const ERR_STRING_DATA SSL_error_string_data[] = {
{ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_send_client_certificate, 0), "ssl3_send_client_certificate"},
{ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_send_client_hello, 0), "ssl3_send_client_hello"},
{ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_send_client_key_exchange, 0), "ssl3_send_client_key_exchange"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_send_new_session_ticket, 0), "ssl3_send_new_session_ticket"},
{ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_send_server_certificate, 0), "ssl3_send_server_certificate"},
{ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_send_server_hello, 0), "ssl3_send_server_hello"},
{ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_send_server_key_exchange, 0), "ssl3_send_server_key_exchange"},
@@ -320,6 +326,7 @@ const ERR_STRING_DATA SSL_error_string_data[] = {
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INVALID_PURPOSE), "INVALID_PURPOSE"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INVALID_SERVERINFO_DATA), "INVALID_SERVERINFO_DATA"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INVALID_SRP_USERNAME), "INVALID_SRP_USERNAME"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INVALID_SSL_SESSION), "INVALID_SSL_SESSION"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INVALID_STATUS_RESPONSE), "INVALID_STATUS_RESPONSE"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INVALID_TICKET_KEYS_LENGTH), "INVALID_TICKET_KEYS_LENGTH"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_INVALID_TRUST), "INVALID_TRUST"},
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index f7818ed..8357ff9 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -1495,8 +1495,7 @@ int ssl_cipher_list_to_bytes(SSL *s, STACK_OF(SSL_CIPHER) *sk, uint8_t *p)
return(p-q);
}
-STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s, const CBS *cbs,
- STACK_OF(SSL_CIPHER) **skp)
+STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s, const CBS *cbs)
{
CBS cipher_suites = *cbs;
const SSL_CIPHER *c;
@@ -1508,14 +1507,14 @@ STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s, const CBS *cbs,
if (CBS_len(&cipher_suites) % 2 != 0)
{
OPENSSL_PUT_ERROR(SSL, ssl_bytes_to_cipher_list, SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST);
- return(NULL);
+ return NULL;
}
- if ((skp == NULL) || (*skp == NULL))
- sk=sk_SSL_CIPHER_new_null(); /* change perhaps later */
- else
+
+ sk = sk_SSL_CIPHER_new_null();
+ if (sk == NULL)
{
- sk= *skp;
- sk_SSL_CIPHER_zero(sk);
+ OPENSSL_PUT_ERROR(SSL, ssl_bytes_to_cipher_list, ERR_R_MALLOC_FAILURE);
+ goto err;
}
if (!CBS_stow(&cipher_suites,
@@ -1535,10 +1534,10 @@ STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s, const CBS *cbs,
goto err;
}
- /* Check for SCSV */
+ /* Check for SCSV. */
if (s->s3 && cipher_suite == (SSL3_CK_SCSV & 0xffff))
{
- /* SCSV fatal if renegotiating */
+ /* SCSV is fatal if renegotiating. */
if (s->renegotiate)
{
OPENSSL_PUT_ERROR(SSL, ssl_bytes_to_cipher_list, SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING);
@@ -1546,25 +1545,25 @@ STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s, const CBS *cbs,
goto err;
}
s->s3->send_connection_binding = 1;
-#ifdef OPENSSL_RI_DEBUG
- fprintf(stderr, "SCSV received by server\n");
-#endif
continue;
}
- /* Check for FALLBACK_SCSV */
- if (s->s3 && cipher_suite == (SSL3_CK_FALLBACK_SCSV & 0xffff) &&
- s->version < ssl_get_max_version(s))
+ /* Check for FALLBACK_SCSV. */
+ if (s->s3 && cipher_suite == (SSL3_CK_FALLBACK_SCSV & 0xffff))
{
- OPENSSL_PUT_ERROR(SSL, ssl_bytes_to_cipher_list, SSL_R_INAPPROPRIATE_FALLBACK);
- ssl3_send_alert(s,SSL3_AL_FATAL,SSL3_AD_INAPPROPRIATE_FALLBACK);
- goto err;
+ if (s->version < ssl_get_max_version(s))
+ {
+ OPENSSL_PUT_ERROR(SSL, ssl_bytes_to_cipher_list, SSL_R_INAPPROPRIATE_FALLBACK);
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL3_AD_INAPPROPRIATE_FALLBACK);
+ goto err;
+ }
+ continue;
}
c = ssl3_get_cipher_by_value(cipher_suite);
if (c != NULL)
{
- if (!sk_SSL_CIPHER_push(sk,c))
+ if (!sk_SSL_CIPHER_push(sk, c))
{
OPENSSL_PUT_ERROR(SSL, ssl_bytes_to_cipher_list, ERR_R_MALLOC_FAILURE);
goto err;
@@ -1572,13 +1571,12 @@ STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s, const CBS *cbs,
}
}
- if (skp != NULL)
- *skp=sk;
- return(sk);
+ return sk;
+
err:
- if ((skp == NULL) || (*skp == NULL))
+ if (sk != NULL)
sk_SSL_CIPHER_free(sk);
- return(NULL);
+ return NULL;
}
diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h
index 75c0ba8..c214b91 100644
--- a/ssl/ssl_locl.h
+++ b/ssl/ssl_locl.h
@@ -568,6 +568,11 @@ struct tls_sigalgs_st
#define FP_ICC (int (*)(const void *,const void *))
+enum should_add_to_finished_hash {
+ add_to_finished_hash,
+ dont_add_to_finished_hash,
+};
+
/* 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 :-) */
@@ -597,7 +602,9 @@ typedef struct ssl3_enc_method
/* Set the handshake header */
void (*set_handshake_header)(SSL *s, int type, unsigned long len);
/* Write out handshake message */
- int (*do_write)(SSL *s);
+ int (*do_write)(SSL *s, enum should_add_to_finished_hash should_add_to_finished_hash);
+ /* Add the current handshake message to the finished hash. */
+ void (*add_to_finished_hash)(SSL *s);
} SSL3_ENC_METHOD;
#define SSL_HM_HEADER_LENGTH(s) s->method->ssl3_enc->hhlen
@@ -605,7 +612,7 @@ typedef struct ssl3_enc_method
(((unsigned char *)s->init_buf->data) + s->method->ssl3_enc->hhlen)
#define ssl_set_handshake_header(s, htype, len) \
s->method->ssl3_enc->set_handshake_header(s, htype, len)
-#define ssl_do_write(s) s->method->ssl3_enc->do_write(s)
+#define ssl_do_write(s) s->method->ssl3_enc->do_write(s, add_to_finished_hash)
/* Values for enc_flags */
@@ -768,8 +775,7 @@ int ssl_set_peer_cert_type(SESS_CERT *c, int type);
int ssl_get_prev_session(SSL *s, const struct ssl_early_callback_ctx *ctx);
int ssl_cipher_id_cmp(const void *in_a, const void *in_b);
int ssl_cipher_ptr_id_cmp(const SSL_CIPHER **ap, const SSL_CIPHER **bp);
-STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s, const CBS *cbs,
- STACK_OF(SSL_CIPHER) **skp);
+STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s, const CBS *cbs);
int ssl_cipher_list_to_bytes(SSL *s, STACK_OF(SSL_CIPHER) *sk, uint8_t *p);
STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *meth,
struct ssl_cipher_preference_list_st **pref,
@@ -824,7 +830,7 @@ int ssl3_setup_key_block(SSL *s);
int ssl3_send_change_cipher_spec(SSL *s,int state_a,int state_b);
int ssl3_change_cipher_state(SSL *s,int which);
void ssl3_cleanup_key_block(SSL *s);
-int ssl3_do_write(SSL *s,int type);
+int ssl3_do_write(SSL *s,int type, enum should_add_to_finished_hash should_add_to_finished_hash);
int ssl3_send_alert(SSL *s,int level, int desc);
int ssl3_generate_master_secret(SSL *s, unsigned char *out,
unsigned char *p, int len);
@@ -866,7 +872,13 @@ int ssl3_setup_read_buffer(SSL *s);
int ssl3_setup_write_buffer(SSL *s);
int ssl3_release_read_buffer(SSL *s);
int ssl3_release_write_buffer(SSL *s);
-int ssl3_digest_cached_records(SSL *s);
+
+enum should_free_handshake_buffer_t {
+ free_handshake_buffer,
+ dont_free_handshake_buffer,
+};
+int ssl3_digest_cached_records(SSL *s, enum should_free_handshake_buffer_t);
+
int ssl3_new(SSL *s);
void ssl3_free(SSL *s);
int ssl3_accept(SSL *s);
@@ -886,13 +898,14 @@ void ssl3_record_sequence_update(unsigned char *seq);
int ssl3_do_change_cipher_spec(SSL *ssl);
void ssl3_set_handshake_header(SSL *s, int htype, unsigned long len);
-int ssl3_handshake_write(SSL *s);
+int ssl3_handshake_write(SSL *s, enum should_add_to_finished_hash should_add_to_finished_hash);
+void ssl3_add_to_finished_hash(SSL *s);
int ssl23_read(SSL *s, void *buf, int len);
int ssl23_peek(SSL *s, void *buf, int len);
int ssl23_write(SSL *s, const void *buf, int len);
-int dtls1_do_write(SSL *s,int type);
+int dtls1_do_write(SSL *s,int type, enum should_add_to_finished_hash should_add_to_finished_hash);
int ssl3_read_n(SSL *s, int n, int max, int extend);
int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek);
int ssl3_write_pending(SSL *s, int type, const unsigned char *buf,
diff --git a/ssl/ssl_test.c b/ssl/ssl_test.c
index a202273..da9ba4b 100644
--- a/ssl/ssl_test.c
+++ b/ssl/ssl_test.c
@@ -307,20 +307,6 @@ static const char kOpenSSLSession[] =
* filling in missing fields from |kOpenSSLSession|. This includes
* providing |peer_sha256|, so |peer| is not serialized. */
static const char kCustomSession[] =
- "MIIBggIBAQICAwMEAsAvBCAG5Q1ndq4Yfmbeo1zwLkNRKmCXGdNgWvGT3cskV0yQ"
- "kAQwJlrlzkAWBOWiLj/jJ76D7l+UXoizP2KI2C7I2FccqMmIfFmmkUy32nIJ0mZH"
- "IWoJgAEBoQYCBFRDO46iBAICASykAwQBAqUDAgEUphAEDnd3dy5nb29nbGUuY29t"
- "pwcEBWhlbGxvqAcEBXdvcmxkqQUCAwGJwKqBpwSBpBwUQvoeOk0Kg36SYTcLEkXq"
- "KwOBfF9vE4KX0NxeLwjcDTpsuh3qXEaZ992r1N38VDcyS6P7I6HBYN9BsNHM362z"
- "ZnY27GpTw+Kwd751CLoXFPoaMOe57dbBpXoro6Pd3BTbf/Tzr88K06yEOTDKPNj3"
- "+inbMaVigtK4PLyPq+Topyzvx9USFgRvyuoxn0Hgb+R0A3j6SLRuyOdAi4gv7Y5o"
- "liynrSIEIAYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGrgMEAQevAwQB"
- "BLADBAEF";
-
-/* kCustomSession2 is kCustomSession with the old SSLv2-only key_arg
- * field removed. Encoding the decoded version of kCustomSession
- * should not preserve key_arg. */
-static const char kCustomSession2[] =
"MIIBfwIBAQICAwMEAsAvBCAG5Q1ndq4Yfmbeo1zwLkNRKmCXGdNgWvGT3cskV0yQ"
"kAQwJlrlzkAWBOWiLj/jJ76D7l+UXoizP2KI2C7I2FccqMmIfFmmkUy32nIJ0mZH"
"IWoJoQYCBFRDO46iBAICASykAwQBAqUDAgEUphAEDnd3dy5nb29nbGUuY29tpwcE"
@@ -355,18 +341,16 @@ static int decode_base64(uint8_t **out, size_t *out_len, const char *in) {
return 1;
}
-static int test_ssl_session_asn1(const char *input_b64,
- const char *expected_b64) {
+static int test_ssl_session_asn1(const char *input_b64) {
int ret = 0, len;
- size_t input_len, expected_len;
- uint8_t *input = NULL, *expected = NULL, *encoded = NULL;
+ size_t input_len, encoded_len;
+ uint8_t *input = NULL, *encoded = NULL;
const uint8_t *cptr;
uint8_t *ptr;
SSL_SESSION *session = NULL;
/* Decode the input. */
- if (!decode_base64(&input, &input_len, input_b64) ||
- !decode_base64(&expected, &expected_len, expected_b64)) {
+ if (!decode_base64(&input, &input_len, input_b64)) {
goto done;
}
@@ -379,28 +363,41 @@ static int test_ssl_session_asn1(const char *input_b64,
}
/* Verify the SSL_SESSION encoding round-trips. */
+ if (!SSL_SESSION_to_bytes(session, &encoded, &encoded_len)) {
+ fprintf(stderr, "SSL_SESSION_to_bytes failed\n");
+ goto done;
+ }
+ if (encoded_len != input_len ||
+ memcmp(input, encoded, input_len) != 0) {
+ fprintf(stderr, "SSL_SESSION_to_bytes did not round-trip\n");
+ goto done;
+ }
+ OPENSSL_free(encoded);
+ encoded = NULL;
+
+ /* Verify the SSL_SESSION encoding round-trips via the legacy API. */
len = i2d_SSL_SESSION(session, NULL);
- if (len < 0 || (size_t)len != expected_len) {
+ if (len < 0 || (size_t)len != input_len) {
fprintf(stderr, "i2d_SSL_SESSION(NULL) returned invalid length\n");
goto done;
}
- encoded = OPENSSL_malloc(expected_len);
+ encoded = OPENSSL_malloc(input_len);
if (encoded == NULL) {
fprintf(stderr, "malloc failed\n");
goto done;
}
ptr = encoded;
len = i2d_SSL_SESSION(session, &ptr);
- if (len < 0 || (size_t)len != expected_len) {
+ if (len < 0 || (size_t)len != input_len) {
fprintf(stderr, "i2d_SSL_SESSION returned invalid length\n");
goto done;
}
- if (ptr != encoded + expected_len) {
+ if (ptr != encoded + input_len) {
fprintf(stderr, "i2d_SSL_SESSION did not advance ptr correctly\n");
goto done;
}
- if (memcmp(expected, encoded, expected_len) != 0) {
+ if (memcmp(input, encoded, input_len) != 0) {
fprintf(stderr, "i2d_SSL_SESSION did not round-trip\n");
goto done;
}
@@ -418,9 +415,6 @@ static int test_ssl_session_asn1(const char *input_b64,
if (input) {
OPENSSL_free(input);
}
- if (expected) {
- OPENSSL_free(expected);
- }
if (encoded) {
OPENSSL_free(encoded);
}
@@ -431,9 +425,8 @@ int main(void) {
SSL_library_init();
if (!test_cipher_rules() ||
- !test_ssl_session_asn1(kOpenSSLSession, kOpenSSLSession) ||
- !test_ssl_session_asn1(kCustomSession, kCustomSession2) ||
- !test_ssl_session_asn1(kCustomSession2, kCustomSession2)) {
+ !test_ssl_session_asn1(kOpenSSLSession) ||
+ !test_ssl_session_asn1(kCustomSession)) {
return 1;
}
diff --git a/ssl/t1_enc.c b/ssl/t1_enc.c
index dd00d0a..6803e9b 100644
--- a/ssl/t1_enc.c
+++ b/ssl/t1_enc.c
@@ -152,8 +152,6 @@ static int tls1_P_hash(const EVP_MD *md, const unsigned char *sec,
const void *seed1, int seed1_len,
const void *seed2, int seed2_len,
const void *seed3, int seed3_len,
- const void *seed4, int seed4_len,
- const void *seed5, int seed5_len,
unsigned char *out, int olen)
{
int chunk;
@@ -182,10 +180,6 @@ static int tls1_P_hash(const EVP_MD *md, const unsigned char *sec,
goto err;
if (seed3 && !EVP_DigestSignUpdate(&ctx,seed3,seed3_len))
goto err;
- if (seed4 && !EVP_DigestSignUpdate(&ctx,seed4,seed4_len))
- goto err;
- if (seed5 && !EVP_DigestSignUpdate(&ctx,seed5,seed5_len))
- goto err;
A1_len = EVP_MAX_MD_SIZE;
if (!EVP_DigestSignFinal(&ctx,A1,&A1_len))
goto err;
@@ -205,10 +199,6 @@ static int tls1_P_hash(const EVP_MD *md, const unsigned char *sec,
goto err;
if (seed3 && !EVP_DigestSignUpdate(&ctx,seed3,seed3_len))
goto err;
- if (seed4 && !EVP_DigestSignUpdate(&ctx,seed4,seed4_len))
- goto err;
- if (seed5 && !EVP_DigestSignUpdate(&ctx,seed5,seed5_len))
- goto err;
if (olen > chunk)
{
@@ -246,8 +236,6 @@ static int tls1_PRF(long digest_mask,
const void *seed1, int seed1_len,
const void *seed2, int seed2_len,
const void *seed3, int seed3_len,
- const void *seed4, int seed4_len,
- const void *seed5, int seed5_len,
const unsigned char *sec, int slen,
unsigned char *out1,
unsigned char *out2, int olen)
@@ -275,7 +263,7 @@ static int tls1_PRF(long digest_mask,
goto err;
}
if (!tls1_P_hash(md ,S1,len+(slen&1),
- seed1,seed1_len,seed2,seed2_len,seed3,seed3_len,seed4,seed4_len,seed5,seed5_len,
+ seed1,seed1_len,seed2,seed2_len,seed3,seed3_len,
out2,olen))
goto err;
S1+=len;
@@ -298,20 +286,8 @@ static int tls1_generate_key_block(SSL *s, unsigned char *km,
TLS_MD_KEY_EXPANSION_CONST,TLS_MD_KEY_EXPANSION_CONST_SIZE,
s->s3->server_random,SSL3_RANDOM_SIZE,
s->s3->client_random,SSL3_RANDOM_SIZE,
- NULL,0,NULL,0,
s->session->master_key,s->session->master_key_length,
km,tmp,num);
-#ifdef KSSL_DEBUG
- printf("tls1_generate_key_block() ==> %d byte master_key =\n\t",
- s->session->master_key_length);
- {
- int i;
- for (i=0; i < s->session->master_key_length; i++)
- {
- printf("%02X", s->session->master_key[i]);
- }
- printf("\n"); }
-#endif /* KSSL_DEBUG */
return ret;
}
@@ -625,9 +601,6 @@ int tls1_setup_key_block(SSL *s)
int ret=0;
unsigned key_len, iv_len;
-#ifdef KSSL_DEBUG
- printf ("tls1_setup_key_block()\n");
-#endif /* KSSL_DEBUG */
if (s->s3->tmp.key_block_length != 0)
return(1);
@@ -926,10 +899,6 @@ int tls1_enc(SSL *s, int send)
enc=EVP_CIPHER_CTX_cipher(s->enc_read_ctx);
}
-#ifdef KSSL_DEBUG
- printf("tls1_enc(%d)\n", send);
-#endif /* KSSL_DEBUG */
-
if ((s->session == NULL) || (ds == NULL) || (enc == NULL))
{
memmove(rec->data,rec->input,rec->length);
@@ -955,24 +924,6 @@ int tls1_enc(SSL *s, int send)
rec->length+=i;
}
-#ifdef KSSL_DEBUG
- {
- unsigned long ui;
- printf("EVP_Cipher(ds=%p,rec->data=%p,rec->input=%p,l=%ld) ==>\n",
- ds,rec->data,rec->input,l);
- printf("\tEVP_CIPHER_CTX: %d buf_len, %d key_len [%d %d], %d iv_len\n",
- ds->buf_len, ds->cipher->key_len,
- DES_KEY_SZ, DES_SCHEDULE_SZ,
- ds->cipher->iv_len);
- printf("\t\tIV: ");
- for (i=0; i<ds->cipher->iv_len; i++) printf("%02X", ds->iv[i]);
- printf("\n");
- printf("\trec->input=");
- for (ui=0; ui<l; ui++) printf(" %02x", rec->input[ui]);
- printf("\n");
- }
-#endif /* KSSL_DEBUG */
-
if (!send)
{
if (l == 0 || l%bs != 0)
@@ -985,15 +936,6 @@ int tls1_enc(SSL *s, int send)
:(i==0))
return -1; /* AEAD can fail to verify MAC */
-#ifdef KSSL_DEBUG
- {
- unsigned long i;
- printf("\trec->data=");
- for (i=0; i<l; i++)
- printf(" %02x", rec->data[i]); printf("\n");
- }
-#endif /* KSSL_DEBUG */
-
ret = 1;
if (EVP_MD_CTX_md(s->read_hash) != NULL)
mac_size = EVP_MD_CTX_size(s->read_hash);
@@ -1011,8 +953,8 @@ int tls1_cert_verify_mac(SSL *s, int md_nid, unsigned char *out)
EVP_MD_CTX ctx, *d=NULL;
int i;
- if (s->s3->handshake_buffer)
- if (!ssl3_digest_cached_records(s))
+ if (s->s3->handshake_buffer)
+ if (!ssl3_digest_cached_records(s, free_handshake_buffer))
return 0;
for (i=0;i<SSL_MAX_DIGEST;i++)
@@ -1093,7 +1035,7 @@ int tls1_final_finish_mac(SSL *s,
int digests_len;
if (s->s3->handshake_buffer)
- if (!ssl3_digest_cached_records(s))
+ if (!ssl3_digest_cached_records(s, free_handshake_buffer))
return 0;
digests_len = tls1_handshake_digest(s, buf, sizeof(buf));
@@ -1104,7 +1046,7 @@ int tls1_final_finish_mac(SSL *s,
}
if (!tls1_PRF(ssl_get_algorithm2(s),
- str,slen, buf, digests_len, NULL,0, NULL,0, NULL,0,
+ str,slen, buf, digests_len, NULL,0,
s->session->master_key,s->session->master_key_length,
out,buf2,sizeof buf2))
err = 1;
@@ -1212,22 +1154,53 @@ int tls1_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p,
int len)
{
unsigned char buff[SSL_MAX_MASTER_KEY_LENGTH];
- const void *co = NULL, *so = NULL;
- int col = 0, sol = 0;
-
-
-#ifdef KSSL_DEBUG
- printf ("tls1_generate_master_secret(%p,%p, %p, %d)\n", s,out, p,len);
-#endif /* KSSL_DEBUG */
-
- tls1_PRF(ssl_get_algorithm2(s),
- TLS_MD_MASTER_SECRET_CONST,TLS_MD_MASTER_SECRET_CONST_SIZE,
- s->s3->client_random,SSL3_RANDOM_SIZE,
- co, col,
- s->s3->server_random,SSL3_RANDOM_SIZE,
- so, sol,
- p,len,
- s->session->master_key,buff,sizeof buff);
+
+ if (s->s3->tmp.extended_master_secret)
+ {
+ uint8_t digests[2*EVP_MAX_MD_SIZE];
+ int digests_len;
+
+ if (s->s3->handshake_buffer)
+ {
+ /* The master secret is based on the handshake hash
+ * just after sending the ClientKeyExchange. However,
+ * we might have a client certificate to send, in which
+ * case we might need different hashes for the
+ * verification and thus still need the handshake
+ * buffer around. Keeping both a handshake buffer *and*
+ * running hashes isn't yet supported so, when it comes
+ * to calculating the Finished hash, we'll have to hash
+ * the handshake buffer again. */
+ if (!ssl3_digest_cached_records(s, dont_free_handshake_buffer))
+ return 0;
+ }
+
+ digests_len = tls1_handshake_digest(s, digests, sizeof(digests));
+
+ if (digests_len == -1)
+ {
+ return 0;
+ }
+
+ tls1_PRF(ssl_get_algorithm2(s),
+ TLS_MD_EXTENDED_MASTER_SECRET_CONST,
+ TLS_MD_EXTENDED_MASTER_SECRET_CONST_SIZE,
+ digests, digests_len,
+ NULL, 0,
+ p, len,
+ s->session->master_key,
+ buff, sizeof(buff));
+ }
+ else
+ {
+ tls1_PRF(ssl_get_algorithm2(s),
+ TLS_MD_MASTER_SECRET_CONST,TLS_MD_MASTER_SECRET_CONST_SIZE,
+ s->s3->client_random,SSL3_RANDOM_SIZE,
+ s->s3->server_random,SSL3_RANDOM_SIZE,
+ p, len,
+ s->session->master_key,buff,sizeof buff);
+ }
+
#ifdef SSL_DEBUG
fprintf(stderr, "Premaster Secret:\n");
BIO_dump_fp(stderr, (char *)p, len);
@@ -1257,9 +1230,6 @@ int tls1_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p,
}
#endif
-#ifdef KSSL_DEBUG
- printf ("tls1_generate_master_secret() complete\n");
-#endif /* KSSL_DEBUG */
return(SSL3_MASTER_SECRET_SIZE);
}
@@ -1272,10 +1242,6 @@ int tls1_export_keying_material(SSL *s, unsigned char *out, size_t olen,
size_t vallen, currentvalpos;
int rv;
-#ifdef KSSL_DEBUG
- printf ("tls1_export_keying_material(%p,%p,%d,%s,%d,%p,%d)\n", s, out, olen, label, llen, p, plen);
-#endif /* KSSL_DEBUG */
-
buff = OPENSSL_malloc(olen);
if (buff == NULL) goto err2;
@@ -1330,14 +1296,9 @@ int tls1_export_keying_material(SSL *s, unsigned char *out, size_t olen,
val, vallen,
NULL, 0,
NULL, 0,
- NULL, 0,
- NULL, 0,
s->session->master_key,s->session->master_key_length,
out,buff,olen);
-#ifdef KSSL_DEBUG
- printf ("tls1_export_keying_material() complete\n");
-#endif /* KSSL_DEBUG */
goto ret;
err1:
OPENSSL_PUT_ERROR(SSL, tls1_export_keying_material, SSL_R_TLS_ILLEGAL_EXPORTER_LABEL);
@@ -1387,10 +1348,6 @@ int tls1_alert_code(int code)
case SSL_AD_BAD_CERTIFICATE_HASH_VALUE: return(TLS1_AD_BAD_CERTIFICATE_HASH_VALUE);
case SSL_AD_UNKNOWN_PSK_IDENTITY:return(TLS1_AD_UNKNOWN_PSK_IDENTITY);
case SSL_AD_INAPPROPRIATE_FALLBACK:return(SSL3_AD_INAPPROPRIATE_FALLBACK);
-#if 0 /* not appropriate for TLS, not used for DTLS */
- case DTLS1_AD_MISSING_HANDSHAKE_MESSAGE: return
- (DTLS1_AD_MISSING_HANDSHAKE_MESSAGE);
-#endif
default: return(-1);
}
}
diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c
index 4b13cfe..0972515 100644
--- a/ssl/t1_lib.c
+++ b/ssl/t1_lib.c
@@ -140,7 +140,8 @@ SSL3_ENC_METHOD TLSv1_enc_data={
0,
SSL3_HM_HEADER_LENGTH,
ssl3_set_handshake_header,
- ssl3_handshake_write
+ ssl3_handshake_write,
+ ssl3_add_to_finished_hash,
};
SSL3_ENC_METHOD TLSv1_1_enc_data={
@@ -159,7 +160,8 @@ SSL3_ENC_METHOD TLSv1_1_enc_data={
SSL_ENC_FLAG_EXPLICIT_IV,
SSL3_HM_HEADER_LENGTH,
ssl3_set_handshake_header,
- ssl3_handshake_write
+ ssl3_handshake_write,
+ ssl3_add_to_finished_hash,
};
SSL3_ENC_METHOD TLSv1_2_enc_data={
@@ -179,7 +181,8 @@ SSL3_ENC_METHOD TLSv1_2_enc_data={
|SSL_ENC_FLAG_TLS1_2_CIPHERS,
SSL3_HM_HEADER_LENGTH,
ssl3_set_handshake_header,
- ssl3_handshake_write
+ ssl3_handshake_write,
+ ssl3_add_to_finished_hash,
};
static int compare_uint16_t(const void *p1, const void *p2)
@@ -978,6 +981,15 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *buf, unsigned c
ret += el;
}
+ /* Add extended master secret. */
+ if (s->version != SSL3_VERSION)
+ {
+ if (limit - ret - 4 < 0)
+ return NULL;
+ s2n(TLSEXT_TYPE_extended_master_secret,ret);
+ s2n(0,ret);
+ }
+
if (!(SSL_get_options(s) & SSL_OP_NO_TICKET))
{
int ticklen;
@@ -1246,6 +1258,14 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *buf, unsigned c
ret += el;
}
+ if (s->s3->tmp.extended_master_secret)
+ {
+ if ((long)(limit - ret - 4) < 0) return NULL;
+
+ s2n(TLSEXT_TYPE_extended_master_secret,ret);
+ s2n(0,ret);
+ }
+
if (using_ecc)
{
const unsigned char *plist;
@@ -1423,6 +1443,7 @@ static int ssl_scan_clienthello_tlsext(SSL *s, CBS *cbs, int *out_alert)
s->should_ack_sni = 0;
s->s3->next_proto_neg_seen = 0;
s->s3->tmp.certificate_status_expected = 0;
+ s->s3->tmp.extended_master_secret = 0;
if (s->s3->alpn_selected)
{
@@ -1782,6 +1803,18 @@ static int ssl_scan_clienthello_tlsext(SSL *s, CBS *cbs, int *out_alert)
if (!ssl_parse_clienthello_use_srtp_ext(s, &extension, out_alert))
return 0;
}
+
+ else if (type == TLSEXT_TYPE_extended_master_secret &&
+ s->version != SSL3_VERSION)
+ {
+ if (CBS_len(&extension) != 0)
+ {
+ *out_alert = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+
+ s->s3->tmp.extended_master_secret = 1;
+ }
}
ri_check:
@@ -1851,6 +1884,7 @@ static int ssl_scan_serverhello_tlsext(SSL *s, CBS *cbs, int *out_alert)
s->tlsext_ticket_expected = 0;
s->s3->tmp.certificate_status_expected = 0;
+ s->s3->tmp.extended_master_secret = 0;
if (s->s3->alpn_selected)
{
@@ -2086,6 +2120,20 @@ static int ssl_scan_serverhello_tlsext(SSL *s, CBS *cbs, int *out_alert)
if (!ssl_parse_serverhello_use_srtp_ext(s, &extension, out_alert))
return 0;
}
+
+ else if (type == TLSEXT_TYPE_extended_master_secret)
+ {
+ if (/* It is invalid for the server to select EMS and
+ SSLv3. */
+ s->version == SSL3_VERSION ||
+ CBS_len(&extension) != 0)
+ {
+ *out_alert = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+
+ s->s3->tmp.extended_master_secret = 1;
+ }
}
if (!s->hit && tlsext_servername == 1)
@@ -2779,7 +2827,7 @@ tls1_channel_id_hash(EVP_MD_CTX *md, SSL *s)
static const char kClientIDMagic[] = "TLS Channel ID signature";
if (s->s3->handshake_buffer)
- if (!ssl3_digest_cached_records(s))
+ if (!ssl3_digest_cached_records(s, free_handshake_buffer))
return 0;
EVP_DigestUpdate(md, kClientIDMagic, sizeof(kClientIDMagic));
diff --git a/ssl/test/bssl_shim.cc b/ssl/test/bssl_shim.cc
index 6b27e26..ce2a3da 100644
--- a/ssl/test/bssl_shim.cc
+++ b/ssl/test/bssl_shim.cc
@@ -25,6 +25,7 @@
#include <sys/types.h>
#include <openssl/bio.h>
+#include <openssl/buf.h>
#include <openssl/bytestring.h>
#include <openssl/ssl.h>
@@ -180,6 +181,48 @@ static int cookie_verify_callback(SSL *ssl, const uint8_t *cookie, size_t cookie
return 1;
}
+static unsigned psk_client_callback(SSL *ssl, const char *hint,
+ char *out_identity,
+ unsigned max_identity_len,
+ uint8_t *out_psk, unsigned max_psk_len) {
+ const TestConfig *config = GetConfigPtr(ssl);
+
+ if (strcmp(hint ? hint : "", config->psk_identity.c_str()) != 0) {
+ fprintf(stderr, "Server PSK hint did not match.\n");
+ return 0;
+ }
+
+ // Account for the trailing '\0' for the identity.
+ if (config->psk_identity.size() >= max_identity_len ||
+ config->psk.size() > max_psk_len) {
+ fprintf(stderr, "PSK buffers too small\n");
+ return 0;
+ }
+
+ BUF_strlcpy(out_identity, config->psk_identity.c_str(),
+ max_identity_len);
+ memcpy(out_psk, config->psk.data(), config->psk.size());
+ return config->psk.size();
+}
+
+static unsigned psk_server_callback(SSL *ssl, const char *identity,
+ uint8_t *out_psk, unsigned max_psk_len) {
+ const TestConfig *config = GetConfigPtr(ssl);
+
+ if (strcmp(identity, config->psk_identity.c_str()) != 0) {
+ fprintf(stderr, "Client PSK identity did not match.\n");
+ return 0;
+ }
+
+ if (config->psk.size() > max_psk_len) {
+ fprintf(stderr, "PSK buffers too small\n");
+ return 0;
+ }
+
+ memcpy(out_psk, config->psk.data(), config->psk.size());
+ return config->psk.size();
+}
+
static SSL_CTX *setup_ctx(const TestConfig *config) {
SSL_CTX *ssl_ctx = NULL;
DH *dh = NULL;
@@ -369,6 +412,16 @@ static int do_exchange(SSL_SESSION **out_session,
SSL_set_alpn_protos(ssl, (const uint8_t *)config->advertise_alpn.data(),
config->advertise_alpn.size());
}
+ if (!config->psk.empty()) {
+ SSL_set_psk_client_callback(ssl, psk_client_callback);
+ SSL_set_psk_server_callback(ssl, psk_server_callback);
+ }
+ if (!config->psk_identity.empty()) {
+ if (!SSL_use_psk_identity_hint(ssl, config->psk_identity.c_str())) {
+ BIO_print_errors_fp(stdout);
+ return 1;
+ }
+ }
BIO *bio = BIO_new_fd(fd, 1 /* take ownership */);
if (bio == NULL) {
@@ -482,6 +535,37 @@ static int do_exchange(SSL_SESSION **out_session,
}
}
+ if (config->expect_extended_master_secret) {
+ if (!ssl->session->extended_master_secret) {
+ fprintf(stderr, "No EMS for session when expected");
+ return 2;
+ }
+ }
+
+ if (config->renegotiate) {
+ if (config->async) {
+ fprintf(stderr, "--renegotiate is not supported with --async.\n");
+ return 2;
+ }
+
+ SSL_renegotiate(ssl);
+
+ ret = SSL_do_handshake(ssl);
+ if (ret != 1) {
+ SSL_free(ssl);
+ BIO_print_errors_fp(stdout);
+ return 2;
+ }
+
+ SSL_set_state(ssl, SSL_ST_ACCEPT);
+ ret = SSL_do_handshake(ssl);
+ if (ret != 1) {
+ SSL_free(ssl);
+ BIO_print_errors_fp(stdout);
+ return 2;
+ }
+ }
+
if (config->write_different_record_sizes) {
if (config->is_dtls) {
fprintf(stderr, "write_different_record_sizes not supported for DTLS\n");
diff --git a/ssl/test/runner/cipher_suites.go b/ssl/test/runner/cipher_suites.go
index 6cd0de9..5a3ac80 100644
--- a/ssl/test/runner/cipher_suites.go
+++ b/ssl/test/runner/cipher_suites.go
@@ -57,6 +57,9 @@ const (
// suiteNoDTLS indicates that the cipher suite cannot be used
// in DTLS.
suiteNoDTLS
+ // suitePSK indicates that the cipher suite authenticates with
+ // a pre-shared key rather than a server private key.
+ suitePSK
)
// A cipherSuite is a specific combination of key agreement, cipher and MAC
@@ -109,6 +112,10 @@ var cipherSuites = []*cipherSuite{
{TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, 8, ecdheRSAKA, suiteECDHE, cipher3DES, macSHA1, nil},
{TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, 8, dheRSAKA, 0, cipher3DES, macSHA1, nil},
{TLS_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, 8, rsaKA, 0, cipher3DES, macSHA1, nil},
+ {TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256, 16, 0, 4, ecdhePSKKA, suiteECDHE | suiteTLS12 | suitePSK, nil, nil, aeadAESGCM},
+ {TLS_PSK_WITH_RC4_128_SHA, 16, 20, 0, pskKA, suiteNoDTLS | suitePSK, cipherRC4, macSHA1, nil},
+ {TLS_PSK_WITH_AES_128_CBC_SHA, 16, 20, 16, pskKA, suitePSK, cipherAES, macSHA1, nil},
+ {TLS_PSK_WITH_AES_256_CBC_SHA, 32, 20, 16, pskKA, suitePSK, cipherAES, macSHA1, nil},
}
func cipherRC4(key, iv []byte, isRead bool) interface{} {
@@ -287,7 +294,7 @@ func rsaKA(version uint16) keyAgreement {
func ecdheECDSAKA(version uint16) keyAgreement {
return &ecdheKeyAgreement{
- signedKeyAgreement: signedKeyAgreement{
+ auth: &signedKeyAgreement{
sigType: signatureECDSA,
version: version,
},
@@ -296,7 +303,7 @@ func ecdheECDSAKA(version uint16) keyAgreement {
func ecdheRSAKA(version uint16) keyAgreement {
return &ecdheKeyAgreement{
- signedKeyAgreement: signedKeyAgreement{
+ auth: &signedKeyAgreement{
sigType: signatureRSA,
version: version,
},
@@ -305,13 +312,27 @@ func ecdheRSAKA(version uint16) keyAgreement {
func dheRSAKA(version uint16) keyAgreement {
return &dheKeyAgreement{
- signedKeyAgreement: signedKeyAgreement{
+ auth: &signedKeyAgreement{
sigType: signatureRSA,
version: version,
},
}
}
+func pskKA(version uint16) keyAgreement {
+ return &pskKeyAgreement{
+ base: &nilKeyAgreement{},
+ }
+}
+
+func ecdhePSKKA(version uint16) keyAgreement {
+ return &pskKeyAgreement{
+ base: &ecdheKeyAgreement{
+ auth: &nilKeyAgreementAuthentication{},
+ },
+ }
+}
+
// mutualCipherSuite returns a cipherSuite given a list of supported
// ciphersuites and the id requested by the peer.
func mutualCipherSuite(have []uint16, want uint16) *cipherSuite {
@@ -343,6 +364,9 @@ const (
TLS_RSA_WITH_AES_256_CBC_SHA256 uint16 = 0x003d
TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 uint16 = 0x0067
TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 uint16 = 0x006b
+ TLS_PSK_WITH_RC4_128_SHA uint16 = 0x008a
+ TLS_PSK_WITH_AES_128_CBC_SHA uint16 = 0x008c
+ TLS_PSK_WITH_AES_256_CBC_SHA uint16 = 0x008d
TLS_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0x009c
TLS_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0x009d
TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0x009e
@@ -364,3 +388,8 @@ const (
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0xc030
fallbackSCSV uint16 = 0x5600
)
+
+// Additional cipher suite IDs, not IANA-assigned.
+const (
+ TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256 uint16 = 0xcafe
+)
diff --git a/ssl/test/runner/common.go b/ssl/test/runner/common.go
index 8b2c750..6f146af 100644
--- a/ssl/test/runner/common.go
+++ b/ssl/test/runner/common.go
@@ -48,6 +48,7 @@ const (
// TLS handshake message types.
const (
+ typeHelloRequest uint8 = 0
typeClientHello uint8 = 1
typeServerHello uint8 = 2
typeHelloVerifyRequest uint8 = 3
@@ -71,16 +72,17 @@ const (
// TLS extension numbers
const (
- extensionServerName uint16 = 0
- extensionStatusRequest uint16 = 5
- extensionSupportedCurves uint16 = 10
- extensionSupportedPoints uint16 = 11
- extensionSignatureAlgorithms uint16 = 13
- extensionALPN uint16 = 16
- extensionSessionTicket uint16 = 35
- extensionNextProtoNeg uint16 = 13172 // not IANA assigned
- extensionRenegotiationInfo uint16 = 0xff01
- extensionChannelID uint16 = 30032 // not IANA assigned
+ extensionServerName uint16 = 0
+ extensionStatusRequest uint16 = 5
+ extensionSupportedCurves uint16 = 10
+ extensionSupportedPoints uint16 = 11
+ extensionSignatureAlgorithms uint16 = 13
+ extensionALPN uint16 = 16
+ extensionExtendedMasterSecret uint16 = 23
+ extensionSessionTicket uint16 = 35
+ extensionNextProtoNeg uint16 = 13172 // not IANA assigned
+ extensionRenegotiationInfo uint16 = 0xff01
+ extensionChannelID uint16 = 30032 // not IANA assigned
)
// TLS signaling cipher suite values
@@ -189,12 +191,13 @@ const (
// ClientSessionState contains the state needed by clients to resume TLS
// sessions.
type ClientSessionState struct {
- sessionTicket []uint8 // Encrypted ticket used for session resumption with server
- vers uint16 // SSL/TLS version negotiated for the session
- cipherSuite uint16 // Ciphersuite negotiated for the session
- masterSecret []byte // MasterSecret generated by client on a full handshake
- handshakeHash []byte // Handshake hash for Channel ID purposes.
- serverCertificates []*x509.Certificate // Certificate chain presented by the server
+ sessionTicket []uint8 // Encrypted ticket used for session resumption with server
+ vers uint16 // SSL/TLS version negotiated for the session
+ cipherSuite uint16 // Ciphersuite negotiated for the session
+ masterSecret []byte // MasterSecret generated by client on a full handshake
+ handshakeHash []byte // Handshake hash for Channel ID purposes.
+ serverCertificates []*x509.Certificate // Certificate chain presented by the server
+ extendedMasterSecret bool // Whether an extended master secret was used to generate the session
}
// ClientSessionCache is a cache of ClientSessionState objects that can be used
@@ -323,6 +326,14 @@ type Config struct {
// returned in the ConnectionState.
RequestChannelID bool
+ // PreSharedKey, if not nil, is the pre-shared key to use with
+ // the PSK cipher suites.
+ PreSharedKey []byte
+
+ // PreSharedKeyIdentity, if not empty, is the identity to use
+ // with the PSK cipher suites.
+ PreSharedKeyIdentity string
+
// Bugs specifies optional misbehaviour to be used for testing other
// implementations.
Bugs ProtocolBugs
@@ -472,6 +483,22 @@ type ProtocolBugs struct {
// OversizedSessionId causes the session id that is sent with a ticket
// resumption attempt to be too large (33 bytes).
OversizedSessionId bool
+
+ // RequireExtendedMasterSecret, if true, requires that the peer support
+ // the extended master secret option.
+ RequireExtendedMasterSecret bool
+
+ // NoExtendedMasterSecret causes the client and server to behave is if
+ // they didn't support an extended master secret.
+ NoExtendedMasterSecret bool
+
+ // EmptyRenegotiationInfo causes the renegotiation extension to be
+ // empty in a renegotiation handshake.
+ EmptyRenegotiationInfo bool
+
+ // BadRenegotiationInfo causes the renegotiation extension value in a
+ // renegotiation handshake to be incorrect.
+ BadRenegotiationInfo bool
}
func (c *Config) serverInit() {
@@ -727,9 +754,10 @@ func defaultCipherSuites() []uint16 {
}
func initDefaultCipherSuites() {
- varDefaultCipherSuites = make([]uint16, len(cipherSuites))
- for i, suite := range cipherSuites {
- varDefaultCipherSuites[i] = suite.id
+ for _, suite := range cipherSuites {
+ if suite.flags&suitePSK == 0 {
+ varDefaultCipherSuites = append(varDefaultCipherSuites, suite.id)
+ }
}
}
diff --git a/ssl/test/runner/conn.go b/ssl/test/runner/conn.go
index 9f0c328..e76f9d1 100644
--- a/ssl/test/runner/conn.go
+++ b/ssl/test/runner/conn.go
@@ -29,16 +29,17 @@ type Conn struct {
isClient bool
// constant after handshake; protected by handshakeMutex
- handshakeMutex sync.Mutex // handshakeMutex < in.Mutex, out.Mutex, errMutex
- handshakeErr error // error resulting from handshake
- vers uint16 // TLS version
- haveVers bool // version has been negotiated
- config *Config // configuration passed to constructor
- handshakeComplete bool
- didResume bool // whether this connection was a session resumption
- cipherSuite uint16
- ocspResponse []byte // stapled OCSP response
- peerCertificates []*x509.Certificate
+ handshakeMutex sync.Mutex // handshakeMutex < in.Mutex, out.Mutex, errMutex
+ handshakeErr error // error resulting from handshake
+ vers uint16 // TLS version
+ haveVers bool // version has been negotiated
+ config *Config // configuration passed to constructor
+ handshakeComplete bool
+ didResume bool // whether this connection was a session resumption
+ extendedMasterSecret bool // whether this session used an extended master secret
+ cipherSuite uint16
+ ocspResponse []byte // stapled OCSP response
+ peerCertificates []*x509.Certificate
// verifiedChains contains the certificate chains that we built, as
// opposed to the ones presented by the server.
verifiedChains [][]*x509.Certificate
@@ -49,6 +50,10 @@ type Conn struct {
clientProtocolFallback bool
usedALPN bool
+ // verify_data values for the renegotiation extension.
+ clientVerify []byte
+ serverVerify []byte
+
channelID *ecdsa.PublicKey
// input/output
@@ -128,9 +133,10 @@ func (hc *halfConn) setErrorLocked(err error) error {
}
func (hc *halfConn) error() error {
- hc.Lock()
+ // This should be locked, but I've removed it for the renegotiation
+ // tests since we don't concurrently read and write the same tls.Conn
+ // in any case during testing.
err := hc.err
- hc.Unlock()
return err
}
@@ -650,7 +656,7 @@ func (c *Conn) doReadRecord(want recordType) (recordType, *block, error) {
func (c *Conn) readRecord(want recordType) error {
// Caller must be in sync with connection:
// handshake data if handshake not yet completed,
- // else application data. (We don't support renegotiation.)
+ // else application data.
switch want {
default:
c.sendAlert(alertInternalError)
@@ -724,7 +730,12 @@ Again:
case recordTypeHandshake:
// TODO(rsc): Should at least pick off connection close.
if typ != want {
- return c.in.setErrorLocked(c.sendAlert(alertNoRenegotiation))
+ // A client might need to process a HelloRequest from
+ // the server, thus receiving a handshake message when
+ // application data is expected is ok.
+ if !c.isClient {
+ return c.in.setErrorLocked(c.sendAlert(alertNoRenegotiation))
+ }
}
c.hand.Write(data)
}
@@ -907,6 +918,8 @@ func (c *Conn) readHandshake() (interface{}, error) {
var m handshakeMessage
switch data[0] {
+ case typeHelloRequest:
+ m = new(helloRequestMsg)
case typeClientHello:
m = &clientHelloMsg{
isDTLS: c.isDTLS,
@@ -999,6 +1012,35 @@ func (c *Conn) Write(b []byte) (int, error) {
return n + m, c.out.setErrorLocked(err)
}
+func (c *Conn) handleRenegotiation() error {
+ c.handshakeComplete = false
+ if !c.isClient {
+ panic("renegotiation should only happen for a client")
+ }
+
+ msg, err := c.readHandshake()
+ if err != nil {
+ return err
+ }
+ _, ok := msg.(*helloRequestMsg)
+ if !ok {
+ c.sendAlert(alertUnexpectedMessage)
+ return alertUnexpectedMessage
+ }
+
+ return c.Handshake()
+}
+
+func (c *Conn) Renegotiate() error {
+ if !c.isClient {
+ helloReq := new(helloRequestMsg)
+ c.writeRecord(recordTypeHandshake, helloReq.marshal())
+ }
+
+ c.handshakeComplete = false
+ return c.Handshake()
+}
+
// Read can be made to time out and return a net.Error with Timeout() == true
// after a fixed time limit; see SetDeadline and SetReadDeadline.
func (c *Conn) Read(b []byte) (n int, err error) {
@@ -1018,6 +1060,14 @@ func (c *Conn) Read(b []byte) (n int, err error) {
// Soft error, like EAGAIN
return 0, err
}
+ if c.hand.Len() > 0 {
+ // We received handshake bytes, indicating the
+ // start of a renegotiation.
+ if err := c.handleRenegotiation(); err != nil {
+ return 0, err
+ }
+ continue
+ }
}
if err := c.in.err; err != nil {
return 0, err
diff --git a/ssl/test/runner/handshake_client.go b/ssl/test/runner/handshake_client.go
index f4cadc2..0c5192f 100644
--- a/ssl/test/runner/handshake_client.go
+++ b/ssl/test/runner/handshake_client.go
@@ -56,26 +56,40 @@ func (c *Conn) clientHandshake() error {
}
hello := &clientHelloMsg{
- isDTLS: c.isDTLS,
- vers: c.config.maxVersion(),
- compressionMethods: []uint8{compressionNone},
- random: make([]byte, 32),
- ocspStapling: true,
- serverName: c.config.ServerName,
- supportedCurves: c.config.curvePreferences(),
- supportedPoints: []uint8{pointFormatUncompressed},
- nextProtoNeg: len(c.config.NextProtos) > 0,
- secureRenegotiation: true,
- alpnProtocols: c.config.NextProtos,
- duplicateExtension: c.config.Bugs.DuplicateExtension,
- channelIDSupported: c.config.ChannelID != nil,
- npnLast: c.config.Bugs.SwapNPNAndALPN,
+ isDTLS: c.isDTLS,
+ vers: c.config.maxVersion(),
+ compressionMethods: []uint8{compressionNone},
+ random: make([]byte, 32),
+ ocspStapling: true,
+ serverName: c.config.ServerName,
+ supportedCurves: c.config.curvePreferences(),
+ supportedPoints: []uint8{pointFormatUncompressed},
+ nextProtoNeg: len(c.config.NextProtos) > 0,
+ secureRenegotiation: []byte{},
+ alpnProtocols: c.config.NextProtos,
+ duplicateExtension: c.config.Bugs.DuplicateExtension,
+ channelIDSupported: c.config.ChannelID != nil,
+ npnLast: c.config.Bugs.SwapNPNAndALPN,
+ extendedMasterSecret: c.config.maxVersion() >= VersionTLS10,
}
if c.config.Bugs.SendClientVersion != 0 {
hello.vers = c.config.Bugs.SendClientVersion
}
+ if c.config.Bugs.NoExtendedMasterSecret {
+ hello.extendedMasterSecret = false
+ }
+
+ if len(c.clientVerify) > 0 && !c.config.Bugs.EmptyRenegotiationInfo {
+ if c.config.Bugs.BadRenegotiationInfo {
+ hello.secureRenegotiation = append(hello.secureRenegotiation, c.clientVerify...)
+ hello.secureRenegotiation[0] ^= 0x80
+ } else {
+ hello.secureRenegotiation = c.clientVerify
+ }
+ }
+
possibleCipherSuites := c.config.cipherSuites()
hello.cipherSuites = make([]uint16, 0, len(possibleCipherSuites))
@@ -235,6 +249,16 @@ NextCipherSuite:
return fmt.Errorf("tls: server selected an unsupported cipher suite")
}
+ if len(c.clientVerify) > 0 {
+ var expectedRenegInfo []byte
+ expectedRenegInfo = append(expectedRenegInfo, c.clientVerify...)
+ expectedRenegInfo = append(expectedRenegInfo, c.serverVerify...)
+ if !bytes.Equal(serverHello.secureRenegotiation, expectedRenegInfo) {
+ c.sendAlert(alertHandshakeFailure)
+ return fmt.Errorf("tls: renegotiation mismatch")
+ }
+ }
+
hs := &clientHandshakeState{
c: c,
serverHello: serverHello,
@@ -303,60 +327,65 @@ NextCipherSuite:
func (hs *clientHandshakeState) doFullHandshake() error {
c := hs.c
- msg, err := c.readHandshake()
- if err != nil {
- return err
- }
- certMsg, ok := msg.(*certificateMsg)
- if !ok || len(certMsg.certificates) == 0 {
- c.sendAlert(alertUnexpectedMessage)
- return unexpectedMessageError(certMsg, msg)
- }
- hs.writeServerHash(certMsg.marshal())
-
- certs := make([]*x509.Certificate, len(certMsg.certificates))
- for i, asn1Data := range certMsg.certificates {
- cert, err := x509.ParseCertificate(asn1Data)
+ var leaf *x509.Certificate
+ if hs.suite.flags&suitePSK == 0 {
+ msg, err := c.readHandshake()
if err != nil {
- c.sendAlert(alertBadCertificate)
- return errors.New("tls: failed to parse certificate from server: " + err.Error())
+ return err
}
- certs[i] = cert
- }
- if !c.config.InsecureSkipVerify {
- opts := x509.VerifyOptions{
- Roots: c.config.RootCAs,
- CurrentTime: c.config.time(),
- DNSName: c.config.ServerName,
- Intermediates: x509.NewCertPool(),
+ certMsg, ok := msg.(*certificateMsg)
+ if !ok || len(certMsg.certificates) == 0 {
+ c.sendAlert(alertUnexpectedMessage)
+ return unexpectedMessageError(certMsg, msg)
}
+ hs.writeServerHash(certMsg.marshal())
- for i, cert := range certs {
- if i == 0 {
- continue
+ certs := make([]*x509.Certificate, len(certMsg.certificates))
+ for i, asn1Data := range certMsg.certificates {
+ cert, err := x509.ParseCertificate(asn1Data)
+ if err != nil {
+ c.sendAlert(alertBadCertificate)
+ return errors.New("tls: failed to parse certificate from server: " + err.Error())
}
- opts.Intermediates.AddCert(cert)
+ certs[i] = cert
}
- c.verifiedChains, err = certs[0].Verify(opts)
- if err != nil {
- c.sendAlert(alertBadCertificate)
- return err
+ leaf = certs[0]
+
+ if !c.config.InsecureSkipVerify {
+ opts := x509.VerifyOptions{
+ Roots: c.config.RootCAs,
+ CurrentTime: c.config.time(),
+ DNSName: c.config.ServerName,
+ Intermediates: x509.NewCertPool(),
+ }
+
+ for i, cert := range certs {
+ if i == 0 {
+ continue
+ }
+ opts.Intermediates.AddCert(cert)
+ }
+ c.verifiedChains, err = leaf.Verify(opts)
+ if err != nil {
+ c.sendAlert(alertBadCertificate)
+ return err
+ }
}
- }
- switch certs[0].PublicKey.(type) {
- case *rsa.PublicKey, *ecdsa.PublicKey:
- break
- default:
- c.sendAlert(alertUnsupportedCertificate)
- return fmt.Errorf("tls: server's certificate contains an unsupported type of public key: %T", certs[0].PublicKey)
- }
+ switch leaf.PublicKey.(type) {
+ case *rsa.PublicKey, *ecdsa.PublicKey:
+ break
+ default:
+ c.sendAlert(alertUnsupportedCertificate)
+ return fmt.Errorf("tls: server's certificate contains an unsupported type of public key: %T", leaf.PublicKey)
+ }
- c.peerCertificates = certs
+ c.peerCertificates = certs
+ }
if hs.serverHello.ocspStapling {
- msg, err = c.readHandshake()
+ msg, err := c.readHandshake()
if err != nil {
return err
}
@@ -372,7 +401,7 @@ func (hs *clientHandshakeState) doFullHandshake() error {
}
}
- msg, err = c.readHandshake()
+ msg, err := c.readHandshake()
if err != nil {
return err
}
@@ -382,7 +411,7 @@ func (hs *clientHandshakeState) doFullHandshake() error {
skx, ok := msg.(*serverKeyExchangeMsg)
if ok {
hs.writeServerHash(skx.marshal())
- err = keyAgreement.processServerKeyExchange(c.config, hs.hello, hs.serverHello, certs[0], skx)
+ err = keyAgreement.processServerKeyExchange(c.config, hs.hello, hs.serverHello, leaf, skx)
if err != nil {
c.sendAlert(alertUnexpectedMessage)
return err
@@ -483,7 +512,7 @@ func (hs *clientHandshakeState) doFullHandshake() error {
// Certificate message, even if it's empty because we don't have a
// certificate to send.
if certRequested {
- certMsg = new(certificateMsg)
+ certMsg := new(certificateMsg)
if chainToSend != nil {
certMsg.certificates = chainToSend.Certificate
}
@@ -491,7 +520,7 @@ func (hs *clientHandshakeState) doFullHandshake() error {
c.writeRecord(recordTypeHandshake, certMsg.marshal())
}
- preMasterSecret, ckx, err := keyAgreement.generateClientKeyExchange(c.config, hs.hello, certs[0])
+ preMasterSecret, ckx, err := keyAgreement.generateClientKeyExchange(c.config, hs.hello, leaf)
if err != nil {
c.sendAlert(alertInternalError)
return err
@@ -503,7 +532,15 @@ func (hs *clientHandshakeState) doFullHandshake() error {
c.writeRecord(recordTypeHandshake, ckx.marshal())
}
- hs.masterSecret = masterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.hello.random, hs.serverHello.random)
+ if hs.serverHello.extendedMasterSecret && c.vers >= VersionTLS10 {
+ hs.masterSecret = extendedMasterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.finishedHash)
+ c.extendedMasterSecret = true
+ } else {
+ if c.config.Bugs.RequireExtendedMasterSecret {
+ return errors.New("tls: extended master secret required but not supported by peer")
+ }
+ hs.masterSecret = masterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.hello.random, hs.serverHello.random)
+ }
if chainToSend != nil {
var signed []byte
@@ -629,6 +666,7 @@ func (hs *clientHandshakeState) processServerHello() (bool, error) {
// Restore masterSecret and peerCerts from previous state
hs.masterSecret = hs.session.masterSecret
c.peerCertificates = hs.session.serverCertificates
+ c.extendedMasterSecret = hs.session.extendedMasterSecret
hs.finishedHash.discardHandshakeBuffer()
return true, nil
}
@@ -661,6 +699,7 @@ func (hs *clientHandshakeState) readFinished() error {
return errors.New("tls: server's Finished message was incorrect")
}
}
+ c.serverVerify = append(c.serverVerify[:0], serverFinished.verifyData...)
hs.writeServerHash(serverFinished.marshal())
return nil
}
@@ -747,6 +786,7 @@ func (hs *clientHandshakeState) sendFinished(isResume bool) error {
} else {
finished.verifyData = hs.finishedHash.clientSum(hs.masterSecret)
}
+ c.clientVerify = append(c.clientVerify[:0], finished.verifyData...)
finishedBytes := finished.marshal()
hs.writeHash(finishedBytes, seqno)
postCCSBytes = append(postCCSBytes, finishedBytes...)
diff --git a/ssl/test/runner/handshake_messages.go b/ssl/test/runner/handshake_messages.go
index 136360d..12a9f3d 100644
--- a/ssl/test/runner/handshake_messages.go
+++ b/ssl/test/runner/handshake_messages.go
@@ -7,27 +7,28 @@ package main
import "bytes"
type clientHelloMsg struct {
- raw []byte
- isDTLS bool
- vers uint16
- random []byte
- sessionId []byte
- cookie []byte
- cipherSuites []uint16
- compressionMethods []uint8
- nextProtoNeg bool
- serverName string
- ocspStapling bool
- supportedCurves []CurveID
- supportedPoints []uint8
- ticketSupported bool
- sessionTicket []uint8
- signatureAndHashes []signatureAndHash
- secureRenegotiation bool
- alpnProtocols []string
- duplicateExtension bool
- channelIDSupported bool
- npnLast bool
+ raw []byte
+ isDTLS bool
+ vers uint16
+ random []byte
+ sessionId []byte
+ cookie []byte
+ cipherSuites []uint16
+ compressionMethods []uint8
+ nextProtoNeg bool
+ serverName string
+ ocspStapling bool
+ supportedCurves []CurveID
+ supportedPoints []uint8
+ ticketSupported bool
+ sessionTicket []uint8
+ signatureAndHashes []signatureAndHash
+ secureRenegotiation []byte
+ alpnProtocols []string
+ duplicateExtension bool
+ channelIDSupported bool
+ npnLast bool
+ extendedMasterSecret bool
}
func (m *clientHelloMsg) equal(i interface{}) bool {
@@ -52,11 +53,13 @@ func (m *clientHelloMsg) equal(i interface{}) bool {
m.ticketSupported == m1.ticketSupported &&
bytes.Equal(m.sessionTicket, m1.sessionTicket) &&
eqSignatureAndHashes(m.signatureAndHashes, m1.signatureAndHashes) &&
- m.secureRenegotiation == m1.secureRenegotiation &&
+ bytes.Equal(m.secureRenegotiation, m1.secureRenegotiation) &&
+ (m.secureRenegotiation == nil) == (m1.secureRenegotiation == nil) &&
eqStrings(m.alpnProtocols, m1.alpnProtocols) &&
m.duplicateExtension == m1.duplicateExtension &&
m.channelIDSupported == m1.channelIDSupported &&
- m.npnLast == m1.npnLast
+ m.npnLast == m1.npnLast &&
+ m.extendedMasterSecret == m1.extendedMasterSecret
}
func (m *clientHelloMsg) marshal() []byte {
@@ -97,8 +100,8 @@ func (m *clientHelloMsg) marshal() []byte {
extensionsLength += 2 + 2*len(m.signatureAndHashes)
numExtensions++
}
- if m.secureRenegotiation {
- extensionsLength += 1
+ if m.secureRenegotiation != nil {
+ extensionsLength += 1 + len(m.secureRenegotiation)
numExtensions++
}
if m.duplicateExtension {
@@ -118,6 +121,9 @@ func (m *clientHelloMsg) marshal() []byte {
}
numExtensions++
}
+ if m.extendedMasterSecret {
+ numExtensions++
+ }
if numExtensions > 0 {
extensionsLength += 4 * numExtensions
length += 2 + extensionsLength
@@ -274,12 +280,15 @@ func (m *clientHelloMsg) marshal() []byte {
z = z[2:]
}
}
- if m.secureRenegotiation {
+ if m.secureRenegotiation != nil {
z[0] = byte(extensionRenegotiationInfo >> 8)
z[1] = byte(extensionRenegotiationInfo & 0xff)
z[2] = 0
- z[3] = 1
+ z[3] = byte(1 + len(m.secureRenegotiation))
+ z[4] = byte(len(m.secureRenegotiation))
z = z[5:]
+ copy(z, m.secureRenegotiation)
+ z = z[len(m.secureRenegotiation):]
}
if len(m.alpnProtocols) > 0 {
z[0] = byte(extensionALPN >> 8)
@@ -319,6 +328,12 @@ func (m *clientHelloMsg) marshal() []byte {
z[1] = 0xff
z = z[4:]
}
+ if m.extendedMasterSecret {
+ // https://tools.ietf.org/html/draft-ietf-tls-session-hash-01
+ z[0] = byte(extensionExtendedMasterSecret >> 8)
+ z[1] = byte(extensionExtendedMasterSecret & 0xff)
+ z = z[4:]
+ }
m.raw = x
@@ -363,7 +378,7 @@ func (m *clientHelloMsg) unmarshal(data []byte) bool {
for i := 0; i < numCipherSuites; i++ {
m.cipherSuites[i] = uint16(data[2+2*i])<<8 | uint16(data[3+2*i])
if m.cipherSuites[i] == scsvRenegotiation {
- m.secureRenegotiation = true
+ m.secureRenegotiation = []byte{}
}
}
data = data[2+cipherSuiteLen:]
@@ -385,6 +400,7 @@ func (m *clientHelloMsg) unmarshal(data []byte) bool {
m.sessionTicket = nil
m.signatureAndHashes = nil
m.alpnProtocols = nil
+ m.extendedMasterSecret = false
if len(data) == 0 {
// ClientHello is optionally followed by extension data
@@ -489,11 +505,11 @@ func (m *clientHelloMsg) unmarshal(data []byte) bool {
m.signatureAndHashes[i].signature = d[1]
d = d[2:]
}
- case extensionRenegotiationInfo + 1:
- if length != 1 || data[0] != 0 {
+ case extensionRenegotiationInfo:
+ if length < 1 || length != int(data[0])+1 {
return false
}
- m.secureRenegotiation = true
+ m.secureRenegotiation = data[1:length]
case extensionALPN:
if length < 2 {
return false
@@ -517,6 +533,11 @@ func (m *clientHelloMsg) unmarshal(data []byte) bool {
return false
}
m.channelIDSupported = true
+ case extensionExtendedMasterSecret:
+ if length != 0 {
+ return false
+ }
+ m.extendedMasterSecret = true
}
data = data[length:]
}
@@ -525,21 +546,22 @@ func (m *clientHelloMsg) unmarshal(data []byte) bool {
}
type serverHelloMsg struct {
- raw []byte
- isDTLS bool
- vers uint16
- random []byte
- sessionId []byte
- cipherSuite uint16
- compressionMethod uint8
- nextProtoNeg bool
- nextProtos []string
- ocspStapling bool
- ticketSupported bool
- secureRenegotiation bool
- alpnProtocol string
- duplicateExtension bool
- channelIDRequested bool
+ raw []byte
+ isDTLS bool
+ vers uint16
+ random []byte
+ sessionId []byte
+ cipherSuite uint16
+ compressionMethod uint8
+ nextProtoNeg bool
+ nextProtos []string
+ ocspStapling bool
+ ticketSupported bool
+ secureRenegotiation []byte
+ alpnProtocol string
+ duplicateExtension bool
+ channelIDRequested bool
+ extendedMasterSecret bool
}
func (m *serverHelloMsg) equal(i interface{}) bool {
@@ -559,10 +581,12 @@ func (m *serverHelloMsg) equal(i interface{}) bool {
eqStrings(m.nextProtos, m1.nextProtos) &&
m.ocspStapling == m1.ocspStapling &&
m.ticketSupported == m1.ticketSupported &&
- m.secureRenegotiation == m1.secureRenegotiation &&
+ bytes.Equal(m.secureRenegotiation, m1.secureRenegotiation) &&
+ (m.secureRenegotiation == nil) == (m1.secureRenegotiation == nil) &&
m.alpnProtocol == m1.alpnProtocol &&
m.duplicateExtension == m1.duplicateExtension &&
- m.channelIDRequested == m1.channelIDRequested
+ m.channelIDRequested == m1.channelIDRequested &&
+ m.extendedMasterSecret == m1.extendedMasterSecret
}
func (m *serverHelloMsg) marshal() []byte {
@@ -589,8 +613,8 @@ func (m *serverHelloMsg) marshal() []byte {
if m.ticketSupported {
numExtensions++
}
- if m.secureRenegotiation {
- extensionsLength += 1
+ if m.secureRenegotiation != nil {
+ extensionsLength += 1 + len(m.secureRenegotiation)
numExtensions++
}
if m.duplicateExtension {
@@ -606,6 +630,9 @@ func (m *serverHelloMsg) marshal() []byte {
extensionsLength += 2 + 1 + alpnLen
numExtensions++
}
+ if m.extendedMasterSecret {
+ numExtensions++
+ }
if numExtensions > 0 {
extensionsLength += 4 * numExtensions
@@ -667,12 +694,15 @@ func (m *serverHelloMsg) marshal() []byte {
z[1] = byte(extensionSessionTicket)
z = z[4:]
}
- if m.secureRenegotiation {
+ if m.secureRenegotiation != nil {
z[0] = byte(extensionRenegotiationInfo >> 8)
z[1] = byte(extensionRenegotiationInfo & 0xff)
z[2] = 0
- z[3] = 1
+ z[3] = byte(1 + len(m.secureRenegotiation))
+ z[4] = byte(len(m.secureRenegotiation))
z = z[5:]
+ copy(z, m.secureRenegotiation)
+ z = z[len(m.secureRenegotiation):]
}
if alpnLen := len(m.alpnProtocol); alpnLen > 0 {
z[0] = byte(extensionALPN >> 8)
@@ -699,6 +729,11 @@ func (m *serverHelloMsg) marshal() []byte {
z[1] = 0xff
z = z[4:]
}
+ if m.extendedMasterSecret {
+ z[0] = byte(extensionExtendedMasterSecret >> 8)
+ z[1] = byte(extensionExtendedMasterSecret & 0xff)
+ z = z[4:]
+ }
m.raw = x
@@ -730,6 +765,7 @@ func (m *serverHelloMsg) unmarshal(data []byte) bool {
m.ocspStapling = false
m.ticketSupported = false
m.alpnProtocol = ""
+ m.extendedMasterSecret = false
if len(data) == 0 {
// ServerHello is optionally followed by extension data
@@ -780,10 +816,10 @@ func (m *serverHelloMsg) unmarshal(data []byte) bool {
}
m.ticketSupported = true
case extensionRenegotiationInfo:
- if length != 1 || data[0] != 0 {
+ if length < 1 || length != int(data[0])+1 {
return false
}
- m.secureRenegotiation = true
+ m.secureRenegotiation = data[1:length]
case extensionALPN:
d := data[:length]
if len(d) < 3 {
@@ -805,6 +841,11 @@ func (m *serverHelloMsg) unmarshal(data []byte) bool {
return false
}
m.channelIDRequested = true
+ case extensionExtendedMasterSecret:
+ if length != 0 {
+ return false
+ }
+ m.extendedMasterSecret = true
}
data = data[length:]
}
@@ -1634,6 +1675,17 @@ func (m *encryptedExtensionsMsg) unmarshal(data []byte) bool {
return true
}
+type helloRequestMsg struct {
+}
+
+func (*helloRequestMsg) marshal() []byte {
+ return []byte{typeHelloRequest, 0, 0, 0}
+}
+
+func (*helloRequestMsg) unmarshal(data []byte) bool {
+ return len(data) == 4
+}
+
func eqUint16s(x, y []uint16) bool {
if len(x) != len(y) {
return false
diff --git a/ssl/test/runner/handshake_server.go b/ssl/test/runner/handshake_server.go
index 1eb3f11..41d588a 100644
--- a/ssl/test/runner/handshake_server.go
+++ b/ssl/test/runner/handshake_server.go
@@ -214,7 +214,22 @@ Curves:
c.sendAlert(alertInternalError)
return false, err
}
- hs.hello.secureRenegotiation = hs.clientHello.secureRenegotiation
+
+ if !bytes.Equal(c.clientVerify, hs.clientHello.secureRenegotiation) {
+ c.sendAlert(alertHandshakeFailure)
+ return false, errors.New("tls: renegotiation mismatch")
+ }
+
+ if len(c.clientVerify) > 0 && !c.config.Bugs.EmptyRenegotiationInfo {
+ hs.hello.secureRenegotiation = append(hs.hello.secureRenegotiation, c.clientVerify...)
+ hs.hello.secureRenegotiation = append(hs.hello.secureRenegotiation, c.serverVerify...)
+ if c.config.Bugs.BadRenegotiationInfo {
+ hs.hello.secureRenegotiation[0] ^= 0x80
+ }
+ } else {
+ hs.hello.secureRenegotiation = hs.clientHello.secureRenegotiation
+ }
+
hs.hello.compressionMethod = compressionNone
hs.hello.duplicateExtension = c.config.Bugs.DuplicateExtension
if len(hs.clientHello.serverName) > 0 {
@@ -237,6 +252,7 @@ Curves:
hs.hello.nextProtos = config.NextProtos
}
}
+ hs.hello.extendedMasterSecret = c.vers >= VersionTLS10 && hs.clientHello.extendedMasterSecret && !c.config.Bugs.NoExtendedMasterSecret
if len(config.Certificates) == 0 {
c.sendAlert(alertInternalError)
@@ -373,6 +389,7 @@ func (hs *serverHandshakeState) doResumeHandshake() error {
}
hs.masterSecret = hs.sessionState.masterSecret
+ c.extendedMasterSecret = hs.sessionState.extendedMasterSecret
return nil
}
@@ -381,12 +398,14 @@ func (hs *serverHandshakeState) doFullHandshake() error {
config := hs.c.config
c := hs.c
- if hs.clientHello.ocspStapling && len(hs.cert.OCSPStaple) > 0 {
+ isPSK := hs.suite.flags&suitePSK != 0
+ if !isPSK && hs.clientHello.ocspStapling && len(hs.cert.OCSPStaple) > 0 {
hs.hello.ocspStapling = true
}
hs.hello.ticketSupported = hs.clientHello.ticketSupported && !config.SessionTicketsDisabled
hs.hello.cipherSuite = hs.suite.id
+ c.extendedMasterSecret = hs.hello.extendedMasterSecret
hs.finishedHash = newFinishedHash(c.vers, hs.suite)
hs.writeClientHash(hs.clientHello.marshal())
@@ -394,11 +413,13 @@ func (hs *serverHandshakeState) doFullHandshake() error {
c.writeRecord(recordTypeHandshake, hs.hello.marshal())
- certMsg := new(certificateMsg)
- certMsg.certificates = hs.cert.Certificate
- if !config.Bugs.UnauthenticatedECDH {
- hs.writeServerHash(certMsg.marshal())
- c.writeRecord(recordTypeHandshake, certMsg.marshal())
+ if !isPSK {
+ certMsg := new(certificateMsg)
+ certMsg.certificates = hs.cert.Certificate
+ if !config.Bugs.UnauthenticatedECDH {
+ hs.writeServerHash(certMsg.marshal())
+ c.writeRecord(recordTypeHandshake, certMsg.marshal())
+ }
}
if hs.hello.ocspStapling {
@@ -463,6 +484,7 @@ func (hs *serverHandshakeState) doFullHandshake() error {
// If we requested a client certificate, then the client must send a
// certificate message, even if it's empty.
if config.ClientAuth >= RequestClientCert {
+ var certMsg *certificateMsg
if certMsg, ok = msg.(*certificateMsg); !ok {
c.sendAlert(alertUnexpectedMessage)
return unexpectedMessageError(certMsg, msg)
@@ -502,7 +524,14 @@ func (hs *serverHandshakeState) doFullHandshake() error {
c.sendAlert(alertHandshakeFailure)
return err
}
- hs.masterSecret = masterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.clientHello.random, hs.hello.random)
+ if c.extendedMasterSecret {
+ hs.masterSecret = extendedMasterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.finishedHash)
+ } else {
+ if c.config.Bugs.RequireExtendedMasterSecret {
+ return errors.New("tls: extended master secret required but not supported by peer")
+ }
+ hs.masterSecret = masterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.clientHello.random, hs.hello.random)
+ }
// If we received a client cert in response to our certificate request message,
// the client will send us a certificateVerifyMsg immediately after the
@@ -679,6 +708,7 @@ func (hs *serverHandshakeState) readFinished(isResume bool) error {
c.sendAlert(alertHandshakeFailure)
return errors.New("tls: client's Finished message is incorrect")
}
+ c.clientVerify = append(c.clientVerify[:0], clientFinished.verifyData...)
hs.writeClientHash(clientFinished.marshal())
return nil
@@ -716,6 +746,7 @@ func (hs *serverHandshakeState) sendFinished() error {
finished := new(finishedMsg)
finished.verifyData = hs.finishedHash.serverSum(hs.masterSecret)
+ c.serverVerify = append(c.serverVerify[:0], finished.verifyData...)
postCCSBytes := finished.marshal()
hs.writeServerHash(postCCSBytes)
diff --git a/ssl/test/runner/key_agreement.go b/ssl/test/runner/key_agreement.go
index f8ba1f8..af54a8f 100644
--- a/ssl/test/runner/key_agreement.go
+++ b/ssl/test/runner/key_agreement.go
@@ -187,8 +187,29 @@ func curveForCurveID(id CurveID) (elliptic.Curve, bool) {
}
-// signedKeyAgreement implements helper functions for key agreement
-// methods that involve signed parameters in the ServerKeyExchange.
+// keyAgreementAuthentication is a helper interface that specifies how
+// to authenticate the ServerKeyExchange parameters.
+type keyAgreementAuthentication interface {
+ signParameters(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg, params []byte) (*serverKeyExchangeMsg, error)
+ verifyParameters(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, params []byte, sig []byte) error
+}
+
+// nilKeyAgreementAuthentication does not authenticate the key
+// agreement parameters.
+type nilKeyAgreementAuthentication struct{}
+
+func (ka *nilKeyAgreementAuthentication) signParameters(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg, params []byte) (*serverKeyExchangeMsg, error) {
+ skx := new(serverKeyExchangeMsg)
+ skx.key = params
+ return skx, nil
+}
+
+func (ka *nilKeyAgreementAuthentication) verifyParameters(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, params []byte, sig []byte) error {
+ return nil
+}
+
+// signedKeyAgreement signs the ServerKeyExchange parameters with the
+// server's private key.
type signedKeyAgreement struct {
version uint16
sigType uint8
@@ -328,7 +349,7 @@ func (ka *signedKeyAgreement) verifyParameters(config *Config, clientHello *clie
// pre-master secret is then calculated using ECDH. The signature may
// either be ECDSA or RSA.
type ecdheKeyAgreement struct {
- signedKeyAgreement
+ auth keyAgreementAuthentication
privateKey []byte
curve elliptic.Curve
x, y *big.Int
@@ -394,7 +415,7 @@ NextCandidate:
serverECDHParams[3] = byte(len(ecdhePublic))
copy(serverECDHParams[4:], ecdhePublic)
- return ka.signParameters(config, cert, clientHello, hello, serverECDHParams)
+ return ka.auth.signParameters(config, cert, clientHello, hello, serverECDHParams)
}
func (ka *ecdheKeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) {
@@ -438,7 +459,7 @@ func (ka *ecdheKeyAgreement) processServerKeyExchange(config *Config, clientHell
serverECDHParams := skx.key[:4+publicLen]
sig := skx.key[4+publicLen:]
- return ka.verifyParameters(config, clientHello, serverHello, cert, serverECDHParams, sig)
+ return ka.auth.verifyParameters(config, clientHello, serverHello, cert, serverECDHParams, sig)
}
func (ka *ecdheKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) {
@@ -468,7 +489,7 @@ func (ka *ecdheKeyAgreement) generateClientKeyExchange(config *Config, clientHel
// an ephemeral Diffie-Hellman public/private key pair and signs it. The
// pre-master secret is then calculated using Diffie-Hellman.
type dheKeyAgreement struct {
- signedKeyAgreement
+ auth keyAgreementAuthentication
p, g *big.Int
yTheirs *big.Int
xOurs *big.Int
@@ -500,7 +521,7 @@ func (ka *dheKeyAgreement) generateServerKeyExchange(config *Config, cert *Certi
serverDHParams = append(serverDHParams, byte(len(yBytes)>>8), byte(len(yBytes)))
serverDHParams = append(serverDHParams, yBytes...)
- return ka.signParameters(config, cert, clientHello, hello, serverDHParams)
+ return ka.auth.signParameters(config, cert, clientHello, hello, serverDHParams)
}
func (ka *dheKeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) {
@@ -562,7 +583,7 @@ func (ka *dheKeyAgreement) processServerKeyExchange(config *Config, clientHello
sig := k
serverDHParams := skx.key[:len(skx.key)-len(sig)]
- return ka.verifyParameters(config, clientHello, serverHello, cert, serverDHParams, sig)
+ return ka.auth.verifyParameters(config, clientHello, serverHello, cert, serverDHParams, sig)
}
func (ka *dheKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) {
@@ -586,3 +607,164 @@ func (ka *dheKeyAgreement) generateClientKeyExchange(config *Config, clientHello
return preMasterSecret, ckx, nil
}
+
+// nilKeyAgreement is a fake key agreement used to implement the plain PSK key
+// exchange.
+type nilKeyAgreement struct{}
+
+func (ka *nilKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) {
+ return nil, nil
+}
+
+func (ka *nilKeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) {
+ if len(ckx.ciphertext) != 0 {
+ return nil, errClientKeyExchange
+ }
+
+ // Although in plain PSK, otherSecret is all zeros, the base key
+ // agreement does not access to the length of the pre-shared
+ // key. pskKeyAgreement instead interprets nil to mean to use all zeros
+ // of the appropriate length.
+ return nil, nil
+}
+
+func (ka *nilKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error {
+ if len(skx.key) != 0 {
+ return errServerKeyExchange
+ }
+ return nil
+}
+
+func (ka *nilKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) {
+ // Although in plain PSK, otherSecret is all zeros, the base key
+ // agreement does not access to the length of the pre-shared
+ // key. pskKeyAgreement instead interprets nil to mean to use all zeros
+ // of the appropriate length.
+ return nil, &clientKeyExchangeMsg{}, nil
+}
+
+// makePSKPremaster formats a PSK pre-master secret based on otherSecret from
+// the base key exchange and psk.
+func makePSKPremaster(otherSecret, psk []byte) []byte {
+ out := make([]byte, 0, 2+len(otherSecret)+2+len(psk))
+ out = append(out, byte(len(otherSecret)>>8), byte(len(otherSecret)))
+ out = append(out, otherSecret...)
+ out = append(out, byte(len(psk)>>8), byte(len(psk)))
+ out = append(out, psk...)
+ return out
+}
+
+// pskKeyAgreement implements the PSK key agreement.
+type pskKeyAgreement struct {
+ base keyAgreement
+ identityHint string
+}
+
+func (ka *pskKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) {
+ // Assemble the identity hint.
+ bytes := make([]byte, 2+len(config.PreSharedKeyIdentity))
+ bytes[0] = byte(len(config.PreSharedKeyIdentity) >> 8)
+ bytes[1] = byte(len(config.PreSharedKeyIdentity))
+ copy(bytes[2:], []byte(config.PreSharedKeyIdentity))
+
+ // If there is one, append the base key agreement's
+ // ServerKeyExchange.
+ baseSkx, err := ka.base.generateServerKeyExchange(config, cert, clientHello, hello)
+ if err != nil {
+ return nil, err
+ }
+
+ if baseSkx != nil {
+ bytes = append(bytes, baseSkx.key...)
+ } else if config.PreSharedKeyIdentity == "" {
+ // ServerKeyExchange is optional if the identity hint is empty
+ // and there would otherwise be no ServerKeyExchange.
+ return nil, nil
+ }
+
+ skx := new(serverKeyExchangeMsg)
+ skx.key = bytes
+ return skx, nil
+}
+
+func (ka *pskKeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) {
+ // First, process the PSK identity.
+ if len(ckx.ciphertext) < 2 {
+ return nil, errClientKeyExchange
+ }
+ identityLen := (int(ckx.ciphertext[0]) << 8) | int(ckx.ciphertext[1])
+ if 2+identityLen > len(ckx.ciphertext) {
+ return nil, errClientKeyExchange
+ }
+ identity := string(ckx.ciphertext[2 : 2+identityLen])
+
+ if identity != config.PreSharedKeyIdentity {
+ return nil, errors.New("tls: unexpected identity")
+ }
+
+ if config.PreSharedKey == nil {
+ return nil, errors.New("tls: pre-shared key not configured")
+ }
+
+ // Process the remainder of the ClientKeyExchange to compute the base
+ // pre-master secret.
+ newCkx := new(clientKeyExchangeMsg)
+ newCkx.ciphertext = ckx.ciphertext[2+identityLen:]
+ otherSecret, err := ka.base.processClientKeyExchange(config, cert, newCkx, version)
+ if err != nil {
+ return nil, err
+ }
+
+ if otherSecret == nil {
+ // Special-case for the plain PSK key exchanges.
+ otherSecret = make([]byte, len(config.PreSharedKey))
+ }
+ return makePSKPremaster(otherSecret, config.PreSharedKey), nil
+}
+
+func (ka *pskKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error {
+ if len(skx.key) < 2 {
+ return errServerKeyExchange
+ }
+ identityLen := (int(skx.key[0]) << 8) | int(skx.key[1])
+ if 2+identityLen > len(skx.key) {
+ return errServerKeyExchange
+ }
+ ka.identityHint = string(skx.key[2 : 2+identityLen])
+
+ // Process the remainder of the ServerKeyExchange.
+ newSkx := new(serverKeyExchangeMsg)
+ newSkx.key = skx.key[2+identityLen:]
+ return ka.base.processServerKeyExchange(config, clientHello, serverHello, cert, newSkx)
+}
+
+func (ka *pskKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) {
+ // The server only sends an identity hint but, for purposes of
+ // test code, the server always sends the hint and it is
+ // required to match.
+ if ka.identityHint != config.PreSharedKeyIdentity {
+ return nil, nil, errors.New("tls: unexpected identity")
+ }
+
+ // Serialize the identity.
+ bytes := make([]byte, 2+len(config.PreSharedKeyIdentity))
+ bytes[0] = byte(len(config.PreSharedKeyIdentity) >> 8)
+ bytes[1] = byte(len(config.PreSharedKeyIdentity))
+ copy(bytes[2:], []byte(config.PreSharedKeyIdentity))
+
+ // Append the base key exchange's ClientKeyExchange.
+ otherSecret, baseCkx, err := ka.base.generateClientKeyExchange(config, clientHello, cert)
+ if err != nil {
+ return nil, nil, err
+ }
+ ckx := new(clientKeyExchangeMsg)
+ ckx.ciphertext = append(bytes, baseCkx.ciphertext...)
+
+ if config.PreSharedKey == nil {
+ return nil, nil, errors.New("tls: pre-shared key not configured")
+ }
+ if otherSecret == nil {
+ otherSecret = make([]byte, len(config.PreSharedKey))
+ }
+ return makePSKPremaster(otherSecret, config.PreSharedKey), ckx, nil
+}
diff --git a/ssl/test/runner/prf.go b/ssl/test/runner/prf.go
index 6d0db97..d45c080 100644
--- a/ssl/test/runner/prf.go
+++ b/ssl/test/runner/prf.go
@@ -117,6 +117,7 @@ const (
)
var masterSecretLabel = []byte("master secret")
+var extendedMasterSecretLabel = []byte("extended master secret")
var keyExpansionLabel = []byte("key expansion")
var clientFinishedLabel = []byte("client finished")
var serverFinishedLabel = []byte("server finished")
@@ -150,6 +151,15 @@ func masterFromPreMasterSecret(version uint16, suite *cipherSuite, preMasterSecr
return masterSecret
}
+// extendedMasterFromPreMasterSecret generates the master secret from the
+// pre-master secret when the Triple Handshake fix is in effect. See
+// https://tools.ietf.org/html/draft-ietf-tls-session-hash-01
+func extendedMasterFromPreMasterSecret(version uint16, suite *cipherSuite, preMasterSecret []byte, h finishedHash) []byte {
+ masterSecret := make([]byte, masterSecretLength)
+ prfForVersion(version, suite)(masterSecret, preMasterSecret, extendedMasterSecretLabel, h.Sum())
+ return masterSecret
+}
+
// keysFromMasterSecret generates the connection keys from the master
// secret, given the lengths of the MAC key, cipher key and IV, as defined in
// RFC 2246, section 6.3.
@@ -221,6 +231,16 @@ func (h *finishedHash) Write(msg []byte) (n int, err error) {
return len(msg), nil
}
+func (h finishedHash) Sum() []byte {
+ if h.version >= VersionTLS12 {
+ return h.client.Sum(nil)
+ }
+
+ out := make([]byte, 0, md5.Size+sha1.Size)
+ out = h.clientMD5.Sum(out)
+ return h.client.Sum(out)
+}
+
// finishedSum30 calculates the contents of the verify_data member of a SSLv3
// Finished message given the MD5 and SHA1 hashes of a set of handshake
// messages.
@@ -264,15 +284,7 @@ func (h finishedHash) clientSum(masterSecret []byte) []byte {
}
out := make([]byte, finishedVerifyLength)
- if h.version >= VersionTLS12 {
- seed := h.client.Sum(nil)
- h.prf(out, masterSecret, clientFinishedLabel, seed)
- } else {
- seed := make([]byte, 0, md5.Size+sha1.Size)
- seed = h.clientMD5.Sum(seed)
- seed = h.client.Sum(seed)
- h.prf(out, masterSecret, clientFinishedLabel, seed)
- }
+ h.prf(out, masterSecret, clientFinishedLabel, h.Sum())
return out
}
@@ -284,15 +296,7 @@ func (h finishedHash) serverSum(masterSecret []byte) []byte {
}
out := make([]byte, finishedVerifyLength)
- if h.version >= VersionTLS12 {
- seed := h.server.Sum(nil)
- h.prf(out, masterSecret, serverFinishedLabel, seed)
- } else {
- seed := make([]byte, 0, md5.Size+sha1.Size)
- seed = h.serverMD5.Sum(seed)
- seed = h.server.Sum(seed)
- h.prf(out, masterSecret, serverFinishedLabel, seed)
- }
+ h.prf(out, masterSecret, serverFinishedLabel, h.Sum())
return out
}
@@ -334,14 +338,10 @@ func (h finishedHash) hashForClientCertificate(signatureAndHash signatureAndHash
return digest[:], crypto.SHA256, nil
}
if signatureAndHash.signature == signatureECDSA {
- digest := h.server.Sum(nil)
- return digest, crypto.SHA1, nil
+ return h.server.Sum(nil), crypto.SHA1, nil
}
- digest := make([]byte, 0, 36)
- digest = h.serverMD5.Sum(digest)
- digest = h.server.Sum(digest)
- return digest, crypto.MD5SHA1, nil
+ return h.Sum(), crypto.MD5SHA1, nil
}
// hashForChannelID returns the hash to be signed for TLS Channel
diff --git a/ssl/test/runner/recordingconn.go b/ssl/test/runner/recordingconn.go
new file mode 100644
index 0000000..a67fa48
--- /dev/null
+++ b/ssl/test/runner/recordingconn.go
@@ -0,0 +1,130 @@
+package main
+
+import (
+ "bufio"
+ "encoding/hex"
+ "errors"
+ "fmt"
+ "io"
+ "net"
+ "strconv"
+ "strings"
+ "sync"
+)
+
+// recordingConn is a net.Conn that records the traffic that passes through it.
+// WriteTo can be used to produce output that can be later be loaded with
+// ParseTestData.
+type recordingConn struct {
+ net.Conn
+ sync.Mutex
+ flows [][]byte
+ reading bool
+}
+
+func (r *recordingConn) Read(b []byte) (n int, err error) {
+ if n, err = r.Conn.Read(b); n == 0 {
+ return
+ }
+ b = b[:n]
+
+ r.Lock()
+ defer r.Unlock()
+
+ if l := len(r.flows); l == 0 || !r.reading {
+ buf := make([]byte, len(b))
+ copy(buf, b)
+ r.flows = append(r.flows, buf)
+ } else {
+ r.flows[l-1] = append(r.flows[l-1], b[:n]...)
+ }
+ r.reading = true
+ return
+}
+
+func (r *recordingConn) Write(b []byte) (n int, err error) {
+ if n, err = r.Conn.Write(b); n == 0 {
+ return
+ }
+ b = b[:n]
+
+ r.Lock()
+ defer r.Unlock()
+
+ if l := len(r.flows); l == 0 || r.reading {
+ buf := make([]byte, len(b))
+ copy(buf, b)
+ r.flows = append(r.flows, buf)
+ } else {
+ r.flows[l-1] = append(r.flows[l-1], b[:n]...)
+ }
+ r.reading = false
+ return
+}
+
+// WriteTo writes hex dumps to w that contains the recorded traffic.
+func (r *recordingConn) WriteTo(w io.Writer) {
+ // TLS always starts with a client to server flow.
+ clientToServer := true
+
+ for i, flow := range r.flows {
+ source, dest := "client", "server"
+ if !clientToServer {
+ source, dest = dest, source
+ }
+ fmt.Fprintf(w, ">>> Flow %d (%s to %s)\n", i+1, source, dest)
+ dumper := hex.Dumper(w)
+ dumper.Write(flow)
+ dumper.Close()
+ clientToServer = !clientToServer
+ }
+}
+
+func parseTestData(r io.Reader) (flows [][]byte, err error) {
+ var currentFlow []byte
+
+ scanner := bufio.NewScanner(r)
+ for scanner.Scan() {
+ line := scanner.Text()
+ // If the line starts with ">>> " then it marks the beginning
+ // of a new flow.
+ if strings.HasPrefix(line, ">>> ") {
+ if len(currentFlow) > 0 || len(flows) > 0 {
+ flows = append(flows, currentFlow)
+ currentFlow = nil
+ }
+ continue
+ }
+
+ // Otherwise the line is a line of hex dump that looks like:
+ // 00000170 fc f5 06 bf (...) |.....X{&?......!|
+ // (Some bytes have been omitted from the middle section.)
+
+ if i := strings.IndexByte(line, ' '); i >= 0 {
+ line = line[i:]
+ } else {
+ return nil, errors.New("invalid test data")
+ }
+
+ if i := strings.IndexByte(line, '|'); i >= 0 {
+ line = line[:i]
+ } else {
+ return nil, errors.New("invalid test data")
+ }
+
+ hexBytes := strings.Fields(line)
+ for _, hexByte := range hexBytes {
+ val, err := strconv.ParseUint(hexByte, 16, 8)
+ if err != nil {
+ return nil, errors.New("invalid hex byte in test data: " + err.Error())
+ }
+ currentFlow = append(currentFlow, byte(val))
+ }
+ }
+
+ if len(currentFlow) > 0 {
+ flows = append(flows, currentFlow)
+ }
+
+ return flows, nil
+}
diff --git a/ssl/test/runner/runner.go b/ssl/test/runner/runner.go
index b4c2e61..4b43481 100644
--- a/ssl/test/runner/runner.go
+++ b/ssl/test/runner/runner.go
@@ -22,6 +22,8 @@ import (
)
var useValgrind = flag.Bool("valgrind", false, "If true, run code under valgrind")
+var useGDB = flag.Bool("gdb", false, "If true, run BoringSSL code under gdb")
+var flagDebug *bool = flag.Bool("debug", false, "Hexdump the contents of the connection")
const (
rsaCertificateFile = "cert.pem"
@@ -148,6 +150,12 @@ type testCase struct {
// shimWritesFirst controls whether the shim sends an initial "hello"
// message before doing a roundtrip with the runner.
shimWritesFirst bool
+ // renegotiate indicates the the connection should be renegotiated
+ // during the exchange.
+ renegotiate bool
+ // renegotiateCiphers is a list of ciphersuite ids that will be
+ // switched in just before renegotiation.
+ renegotiateCiphers []uint16
// flags, if not empty, contains a list of command-line flags that will
// be passed to the shim program.
flags []string
@@ -563,6 +571,17 @@ func doExchange(test *testCase, config *Config, conn net.Conn, messageLen int, i
}
}
+ if test.renegotiate {
+ if test.renegotiateCiphers != nil {
+ config.CipherSuites = test.renegotiateCiphers
+ }
+ if err := tlsConn.Renegotiate(); err != nil {
+ return err
+ }
+ } else if test.renegotiateCiphers != nil {
+ panic("renegotiateCiphers without renegotiate")
+ }
+
if messageLen < 0 {
if test.protocol == dtls {
return fmt.Errorf("messageLen < 0 not supported for DTLS tests")
@@ -693,10 +712,11 @@ func runTest(test *testCase, buildDir string) error {
var shim *exec.Cmd
if *useValgrind {
shim = valgrindOf(false, shim_path, flags...)
+ } else if *useGDB {
+ shim = gdbOf(shim_path, flags...)
} else {
shim = exec.Command(shim_path, flags...)
}
- // shim = gdbOf(shim_path, flags...)
shim.ExtraFiles = []*os.File{shimEnd, shimEndResume}
shim.Stdin = os.Stdin
var stdoutBuf, stderrBuf bytes.Buffer
@@ -717,8 +737,19 @@ func runTest(test *testCase, buildDir string) error {
}
}
+ var connDebug *recordingConn
+ if *flagDebug {
+ connDebug = &recordingConn{Conn: conn}
+ conn = connDebug
+ }
+
err := doExchange(test, &config, conn, test.messageLen,
false /* not a resumption */)
+
+ if *flagDebug {
+ connDebug.WriteTo(os.Stdout)
+ }
+
conn.Close()
if err == nil && test.resumeSession {
var resumeConfig Config
@@ -814,6 +845,7 @@ var testCipherSuites = []struct {
{"ECDHE-ECDSA-AES256-SHA", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA},
{"ECDHE-ECDSA-AES256-SHA384", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384},
{"ECDHE-ECDSA-RC4-SHA", TLS_ECDHE_ECDSA_WITH_RC4_128_SHA},
+ {"ECDHE-PSK-WITH-AES-128-GCM-SHA256", TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256},
{"ECDHE-RSA-AES128-GCM", TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
{"ECDHE-RSA-AES128-SHA", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
{"ECDHE-RSA-AES128-SHA256", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256},
@@ -821,6 +853,9 @@ var testCipherSuites = []struct {
{"ECDHE-RSA-AES256-SHA", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA},
{"ECDHE-RSA-AES256-SHA384", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384},
{"ECDHE-RSA-RC4-SHA", TLS_ECDHE_RSA_WITH_RC4_128_SHA},
+ {"PSK-AES128-CBC-SHA", TLS_PSK_WITH_AES_128_CBC_SHA},
+ {"PSK-AES256-CBC-SHA", TLS_PSK_WITH_AES_256_CBC_SHA},
+ {"PSK-RC4-SHA", TLS_PSK_WITH_RC4_128_SHA},
{"RC4-MD5", TLS_RSA_WITH_RC4_128_MD5},
{"RC4-SHA", TLS_RSA_WITH_RC4_128_SHA},
}
@@ -833,6 +868,9 @@ func isTLS12Only(suiteName string) bool {
func addCipherSuiteTests() {
for _, suite := range testCipherSuites {
+ const psk = "12345"
+ const pskIdentity = "luggage combo"
+
var cert Certificate
var certFile string
var keyFile string
@@ -846,6 +884,13 @@ func addCipherSuiteTests() {
keyFile = rsaKeyFile
}
+ var flags []string
+ if strings.HasPrefix(suite.name, "PSK-") || strings.Contains(suite.name, "-PSK-") {
+ flags = append(flags,
+ "-psk", psk,
+ "-psk-identity", pskIdentity)
+ }
+
for _, ver := range tlsVersions {
if ver.version < VersionTLS12 && isTLS12Only(suite.name) {
continue
@@ -860,11 +905,14 @@ func addCipherSuiteTests() {
testType: clientTest,
name: ver.name + "-" + suite.name + "-client",
config: Config{
- MinVersion: ver.version,
- MaxVersion: ver.version,
- CipherSuites: []uint16{suite.id},
- Certificates: []Certificate{cert},
+ MinVersion: ver.version,
+ MaxVersion: ver.version,
+ CipherSuites: []uint16{suite.id},
+ Certificates: []Certificate{cert},
+ PreSharedKey: []byte(psk),
+ PreSharedKeyIdentity: pskIdentity,
},
+ flags: flags,
resumeSession: resumeSession,
})
@@ -872,13 +920,16 @@ func addCipherSuiteTests() {
testType: serverTest,
name: ver.name + "-" + suite.name + "-server",
config: Config{
- MinVersion: ver.version,
- MaxVersion: ver.version,
- CipherSuites: []uint16{suite.id},
- Certificates: []Certificate{cert},
+ MinVersion: ver.version,
+ MaxVersion: ver.version,
+ CipherSuites: []uint16{suite.id},
+ Certificates: []Certificate{cert},
+ PreSharedKey: []byte(psk),
+ PreSharedKeyIdentity: pskIdentity,
},
certFile: certFile,
keyFile: keyFile,
+ flags: flags,
resumeSession: resumeSession,
})
@@ -889,11 +940,14 @@ func addCipherSuiteTests() {
protocol: dtls,
name: "D" + ver.name + "-" + suite.name + "-client",
config: Config{
- MinVersion: ver.version,
- MaxVersion: ver.version,
- CipherSuites: []uint16{suite.id},
- Certificates: []Certificate{cert},
+ MinVersion: ver.version,
+ MaxVersion: ver.version,
+ CipherSuites: []uint16{suite.id},
+ Certificates: []Certificate{cert},
+ PreSharedKey: []byte(psk),
+ PreSharedKeyIdentity: pskIdentity,
},
+ flags: flags,
resumeSession: resumeSession,
})
testCases = append(testCases, testCase{
@@ -901,13 +955,16 @@ func addCipherSuiteTests() {
protocol: dtls,
name: "D" + ver.name + "-" + suite.name + "-server",
config: Config{
- MinVersion: ver.version,
- MaxVersion: ver.version,
- CipherSuites: []uint16{suite.id},
- Certificates: []Certificate{cert},
+ MinVersion: ver.version,
+ MaxVersion: ver.version,
+ CipherSuites: []uint16{suite.id},
+ Certificates: []Certificate{cert},
+ PreSharedKey: []byte(psk),
+ PreSharedKeyIdentity: pskIdentity,
},
certFile: certFile,
keyFile: keyFile,
+ flags: flags,
resumeSession: resumeSession,
})
}
@@ -1070,6 +1127,62 @@ func addClientAuthTests() {
}
}
+func addExtendedMasterSecretTests() {
+ const expectEMSFlag = "-expect-extended-master-secret"
+
+ for _, with := range []bool{false, true} {
+ prefix := "No"
+ var flags []string
+ if with {
+ prefix = ""
+ flags = []string{expectEMSFlag}
+ }
+
+ for _, isClient := range []bool{false, true} {
+ suffix := "-Server"
+ testType := serverTest
+ if isClient {
+ suffix = "-Client"
+ testType = clientTest
+ }
+
+ for _, ver := range tlsVersions {
+ test := testCase{
+ testType: testType,
+ name: prefix + "ExtendedMasterSecret-" + ver.name + suffix,
+ config: Config{
+ MinVersion: ver.version,
+ MaxVersion: ver.version,
+ Bugs: ProtocolBugs{
+ NoExtendedMasterSecret: !with,
+ RequireExtendedMasterSecret: with,
+ },
+ },
+ flags: flags,
+ shouldFail: ver.version == VersionSSL30 && with,
+ }
+ if test.shouldFail {
+ test.expectedLocalError = "extended master secret required but not supported by peer"
+ }
+ testCases = append(testCases, test)
+ }
+ }
+ }
+
+ // When a session is resumed, it should still be aware that its master
+ // secret was generated via EMS and thus it's safe to use tls-unique.
+ testCases = append(testCases, testCase{
+ name: "ExtendedMasterSecret-Resume",
+ config: Config{
+ Bugs: ProtocolBugs{
+ RequireExtendedMasterSecret: true,
+ },
+ },
+ flags: []string{expectEMSFlag},
+ resumeSession: true,
+ })
+}
+
// Adds tests that try to cover the range of the handshake state machine, under
// various conditions. Some of these are redundant with other tests, but they
// only cover the synchronous case.
@@ -1178,6 +1291,34 @@ func addStateMachineCoverageTests(async, splitHandshake bool, protocol protocol)
flags: flags,
})
+ // Skip ServerKeyExchange in PSK key exchange if there's no
+ // identity hint.
+ testCases = append(testCases, testCase{
+ protocol: protocol,
+ name: "EmptyPSKHint-Client" + suffix,
+ config: Config{
+ CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
+ PreSharedKey: []byte("secret"),
+ Bugs: ProtocolBugs{
+ MaxHandshakeRecordLength: maxHandshakeRecordLength,
+ },
+ },
+ flags: append(flags, "-psk", "secret"),
+ })
+ testCases = append(testCases, testCase{
+ protocol: protocol,
+ testType: serverTest,
+ name: "EmptyPSKHint-Server" + suffix,
+ config: Config{
+ CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
+ PreSharedKey: []byte("secret"),
+ Bugs: ProtocolBugs{
+ MaxHandshakeRecordLength: maxHandshakeRecordLength,
+ },
+ },
+ flags: append(flags, "-psk", "secret"),
+ })
+
if protocol == tls {
// NPN on client and server; results in post-handshake message.
testCases = append(testCases, testCase{
@@ -1568,7 +1709,7 @@ func addExtensionTests() {
},
},
resumeSession: true,
- shouldFail: true,
+ shouldFail: true,
expectedError: ":DECODE_ERROR:",
})
}
@@ -1635,6 +1776,84 @@ func addResumptionVersionTests() {
}
}
+func addRenegotiationTests() {
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "Renegotiate-Server",
+ flags: []string{"-renegotiate"},
+ shimWritesFirst: true,
+ })
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "Renegotiate-Server-EmptyExt",
+ config: Config{
+ Bugs: ProtocolBugs{
+ EmptyRenegotiationInfo: true,
+ },
+ },
+ flags: []string{"-renegotiate"},
+ shimWritesFirst: true,
+ shouldFail: true,
+ expectedError: ":RENEGOTIATION_MISMATCH:",
+ })
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "Renegotiate-Server-BadExt",
+ config: Config{
+ Bugs: ProtocolBugs{
+ BadRenegotiationInfo: true,
+ },
+ },
+ flags: []string{"-renegotiate"},
+ shimWritesFirst: true,
+ shouldFail: true,
+ expectedError: ":RENEGOTIATION_MISMATCH:",
+ })
+ // TODO(agl): test the renegotiation info SCSV.
+ testCases = append(testCases, testCase{
+ name: "Renegotiate-Client",
+ renegotiate: true,
+ })
+ testCases = append(testCases, testCase{
+ name: "Renegotiate-Client-EmptyExt",
+ renegotiate: true,
+ config: Config{
+ Bugs: ProtocolBugs{
+ EmptyRenegotiationInfo: true,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":RENEGOTIATION_MISMATCH:",
+ })
+ testCases = append(testCases, testCase{
+ name: "Renegotiate-Client-BadExt",
+ renegotiate: true,
+ config: Config{
+ Bugs: ProtocolBugs{
+ BadRenegotiationInfo: true,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":RENEGOTIATION_MISMATCH:",
+ })
+ testCases = append(testCases, testCase{
+ name: "Renegotiate-Client-SwitchCiphers",
+ renegotiate: true,
+ config: Config{
+ CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
+ },
+ renegotiateCiphers: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+ })
+ testCases = append(testCases, testCase{
+ name: "Renegotiate-Client-SwitchCiphers2",
+ renegotiate: true,
+ config: Config{
+ CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+ },
+ renegotiateCiphers: []uint16{TLS_RSA_WITH_RC4_128_SHA},
+ })
+}
+
func worker(statusChan chan statusMsg, c chan *testCase, buildDir string, wg *sync.WaitGroup) {
defer wg.Done()
@@ -1690,6 +1909,8 @@ func main() {
addD5BugTests()
addExtensionTests()
addResumptionVersionTests()
+ addExtendedMasterSecretTests()
+ addRenegotiationTests()
for _, async := range []bool{false, true} {
for _, splitHandshake := range []bool{false, true} {
for _, protocol := range []protocol{tls, dtls} {
diff --git a/ssl/test/runner/ticket.go b/ssl/test/runner/ticket.go
index 74791d6..8355822 100644
--- a/ssl/test/runner/ticket.go
+++ b/ssl/test/runner/ticket.go
@@ -18,11 +18,12 @@ import (
// sessionState contains the information that is serialized into a session
// ticket in order to later resume a connection.
type sessionState struct {
- vers uint16
- cipherSuite uint16
- masterSecret []byte
- handshakeHash []byte
- certificates [][]byte
+ vers uint16
+ cipherSuite uint16
+ masterSecret []byte
+ handshakeHash []byte
+ certificates [][]byte
+ extendedMasterSecret bool
}
func (s *sessionState) equal(i interface{}) bool {
@@ -34,7 +35,8 @@ func (s *sessionState) equal(i interface{}) bool {
if s.vers != s1.vers ||
s.cipherSuite != s1.cipherSuite ||
!bytes.Equal(s.masterSecret, s1.masterSecret) ||
- !bytes.Equal(s.handshakeHash, s1.handshakeHash) {
+ !bytes.Equal(s.handshakeHash, s1.handshakeHash) ||
+ s.extendedMasterSecret != s1.extendedMasterSecret {
return false
}
@@ -56,6 +58,7 @@ func (s *sessionState) marshal() []byte {
for _, cert := range s.certificates {
length += 4 + len(cert)
}
+ length++
ret := make([]byte, length)
x := ret
@@ -88,6 +91,11 @@ func (s *sessionState) marshal() []byte {
x = x[4+len(cert):]
}
+ if s.extendedMasterSecret {
+ x[0] = 1
+ }
+ x = x[1:]
+
return ret
}
@@ -144,6 +152,16 @@ func (s *sessionState) unmarshal(data []byte) bool {
data = data[certLen:]
}
+ if len(data) < 1 {
+ return false
+ }
+
+ s.extendedMasterSecret = false
+ if data[0] == 1 {
+ s.extendedMasterSecret = true
+ }
+ data = data[1:]
+
if len(data) > 0 {
return false
}
diff --git a/ssl/test/test_config.cc b/ssl/test/test_config.cc
index 270fbfb..b717bd3 100644
--- a/ssl/test/test_config.cc
+++ b/ssl/test/test_config.cc
@@ -57,6 +57,9 @@ const BoolFlag kBoolFlags[] = {
{ "-shim-writes-first", &TestConfig::shim_writes_first },
{ "-tls-d5-bug", &TestConfig::tls_d5_bug },
{ "-expect-session-miss", &TestConfig::expect_session_miss },
+ { "-expect-extended-master-secret",
+ &TestConfig::expect_extended_master_secret },
+ { "-renegotiate", &TestConfig::renegotiate },
};
const size_t kNumBoolFlags = sizeof(kBoolFlags) / sizeof(kBoolFlags[0]);
@@ -74,6 +77,8 @@ const StringFlag kStringFlags[] = {
{ "-expect-alpn", &TestConfig::expected_alpn },
{ "-expect-advertised-alpn", &TestConfig::expected_advertised_alpn },
{ "-select-alpn", &TestConfig::select_alpn },
+ { "-psk", &TestConfig::psk },
+ { "-psk-identity", &TestConfig::psk_identity },
};
const size_t kNumStringFlags = sizeof(kStringFlags) / sizeof(kStringFlags[0]);
@@ -105,7 +110,9 @@ TestConfig::TestConfig()
cookie_exchange(false),
shim_writes_first(false),
tls_d5_bug(false),
- expect_session_miss(false) {
+ expect_session_miss(false),
+ expect_extended_master_secret(false),
+ renegotiate(false) {
}
bool ParseConfig(int argc, char **argv, TestConfig *out_config) {
diff --git a/ssl/test/test_config.h b/ssl/test/test_config.h
index acce504..2dc4dc1 100644
--- a/ssl/test/test_config.h
+++ b/ssl/test/test_config.h
@@ -53,6 +53,10 @@ struct TestConfig {
std::string expected_advertised_alpn;
std::string select_alpn;
bool expect_session_miss;
+ bool expect_extended_master_secret;
+ std::string psk;
+ std::string psk_identity;
+ bool renegotiate;
};
bool ParseConfig(int argc, char **argv, TestConfig *out_config);
diff --git a/tool/CMakeLists.txt b/tool/CMakeLists.txt
index e513c8b..e504838 100644
--- a/tool/CMakeLists.txt
+++ b/tool/CMakeLists.txt
@@ -11,7 +11,7 @@ add_executable(
tool.cc
)
-if (APPLE)
+if (APPLE OR WIN32)
target_link_libraries(bssl ssl crypto)
else()
target_link_libraries(bssl ssl crypto -lrt)
diff --git a/tool/client.cc b/tool/client.cc
index d7d9e22..21ea8ba 100644
--- a/tool/client.cc
+++ b/tool/client.cc
@@ -14,6 +14,9 @@
#include <openssl/base.h>
+// TODO(davidben): bssl client does not work on Windows.
+#if !defined(OPENSSL_WINDOWS)
+
#include <string>
#include <vector>
@@ -47,6 +50,10 @@ static const struct argument kArguments[] = {
"The hostname and port of the server to connect to, e.g. foo.com:443",
},
{
+ "-cipher", false,
+ "An OpenSSL-style cipher suite string that configures the offered ciphers",
+ },
+ {
"", false, "",
},
};
@@ -265,6 +272,10 @@ bool Client(const std::vector<std::string> &args) {
SSL_CTX_set_keylog_bio(ctx, keylog_bio);
}
+ if (args_map.count("-cipher") != 0) {
+ SSL_CTX_set_cipher_list(ctx, args_map["-cipher"].c_str());
+ }
+
int sock = -1;
if (!Connect(&sock, args_map["-connect"])) {
return false;
@@ -291,3 +302,5 @@ bool Client(const std::vector<std::string> &args) {
SSL_CTX_free(ctx);
return ok;
}
+
+#endif // !OPENSSL_WINDOWS \ No newline at end of file
diff --git a/tool/pkcs12.cc b/tool/pkcs12.cc
index d35ba0b..fca8bb2 100644
--- a/tool/pkcs12.cc
+++ b/tool/pkcs12.cc
@@ -12,6 +12,8 @@
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+#include <openssl/base.h>
+
#include <memory>
#include <string>
#include <vector>
@@ -21,7 +23,11 @@
#include <stdint.h>
#include <sys/stat.h>
#include <sys/types.h>
+#if defined(OPENSSL_WINDOWS)
+#include <io.h>
+#else
#include <unistd.h>
+#endif
#include <openssl/bytestring.h>
#include <openssl/pem.h>
@@ -31,6 +37,12 @@
#include "internal.h"
+#if defined(OPENSSL_WINDOWS)
+typedef int read_result_t;
+#else
+typedef ssize_t read_result_t;
+#endif
+
static const struct argument kArguments[] = {
{
"-dump", false, "Dump the key and contents of the given file to stdout",
@@ -64,7 +76,7 @@ bool DoPKCS12(const std::vector<std::string> &args) {
const size_t size = st.st_size;
std::unique_ptr<uint8_t[]> contents(new uint8_t[size]);
- ssize_t n;
+ read_result_t n;
size_t off = 0;
do {
n = read(fd, &contents[off], size - off);
diff --git a/tool/tool.cc b/tool/tool.cc
index a0866d7..f35cc7c 100644
--- a/tool/tool.cc
+++ b/tool/tool.cc
@@ -19,7 +19,9 @@
#include <openssl/ssl.h>
+#if !defined(OPENSSL_WINDOWS)
bool Client(const std::vector<std::string> &args);
+#endif
bool DoPKCS12(const std::vector<std::string> &args);
bool Speed(const std::vector<std::string> &args);
@@ -42,8 +44,10 @@ int main(int argc, char **argv) {
if (tool == "speed") {
return !Speed(args);
+#if !defined(OPENSSL_WINDOWS)
} else if (tool == "s_client" || tool == "client") {
return !Client(args);
+#endif
} else if (tool == "pkcs12") {
return !DoPKCS12(args);
} else {
diff --git a/util/all_tests.sh b/util/all_tests.sh
index de6800f..f6188d1 100644
--- a/util/all_tests.sh
+++ b/util/all_tests.sh
@@ -36,7 +36,7 @@ TESTS="
./crypto/ec/example_mul
./crypto/ecdsa/ecdsa_test
./crypto/err/err_test
-./crypto/evp/example_sign
+./crypto/evp/evp_test
./crypto/hmac/hmac_test
./crypto/lhash/lhash_test
./crypto/md5/md5_test