summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRobert Sloan <varomodt@google.com>2017-07-24 08:40:01 -0700
committerRobert Sloan <varomodt@google.com>2017-07-24 08:42:03 -0700
commitb6d070c5081ba0ca11545eb50870817d6d72d926 (patch)
tree707f1e4d159e58912d448a90714557bae8154325 /src
parent682d4e9e966a91cfdd932e78c2d322294a48f4ba (diff)
downloadboringssl-b6d070c5081ba0ca11545eb50870817d6d72d926.tar.gz
external/boringssl: Sync to c642aca28feb7e18f244658559f4042286aed0c8.
This includes the following changes: https://boringssl.googlesource.com/boringssl/+log/14308731e5446a73ac2258688a9688b524483cb6..c642aca28feb7e18f244658559f4042286aed0c8 Test: BoringSSL CTS Presubmits Change-Id: Ia0b5b2cdd64eb2b54ec5335d48da9001e9d6dafa
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt4
-rw-r--r--src/crypto/fipsmodule/FIPS.md10
-rw-r--r--src/crypto/fipsmodule/policydocs/BoringCrypto-Security-Policy-20170615.docxbin0 -> 105579 bytes
-rw-r--r--src/crypto/fipsmodule/rand/urandom.c44
-rw-r--r--src/include/openssl/base.h12
-rw-r--r--src/include/openssl/bn.h3
-rw-r--r--src/include/openssl/pool.h2
-rw-r--r--src/include/openssl/ssl.h78
-rw-r--r--src/include/openssl/ssl3.h1
-rw-r--r--src/include/openssl/type_check.h6
-rw-r--r--src/ssl/CMakeLists.txt2
-rw-r--r--src/ssl/custom_extensions.cc6
-rw-r--r--src/ssl/d1_both.cc58
-rw-r--r--src/ssl/d1_lib.cc114
-rw-r--r--src/ssl/d1_pkt.cc4
-rw-r--r--src/ssl/d1_srtp.cc6
-rw-r--r--src/ssl/dtls_method.cc16
-rw-r--r--src/ssl/dtls_record.cc38
-rw-r--r--src/ssl/handshake_client.cc248
-rw-r--r--src/ssl/handshake_server.cc218
-rw-r--r--src/ssl/internal.h1020
-rw-r--r--src/ssl/s3_both.cc217
-rw-r--r--src/ssl/s3_lib.cc16
-rw-r--r--src/ssl/s3_pkt.cc12
-rw-r--r--src/ssl/ssl_aead_ctx.cc326
-rw-r--r--src/ssl/ssl_asn1.cc230
-rw-r--r--src/ssl/ssl_buffer.cc4
-rw-r--r--src/ssl/ssl_cert.cc255
-rw-r--r--src/ssl/ssl_cipher.cc122
-rw-r--r--src/ssl/ssl_ecdh.cc342
-rw-r--r--src/ssl/ssl_key_share.cc245
-rw-r--r--src/ssl/ssl_lib.cc477
-rw-r--r--src/ssl/ssl_privkey.cc450
-rw-r--r--src/ssl/ssl_session.cc545
-rw-r--r--src/ssl/ssl_test.cc83
-rw-r--r--src/ssl/ssl_transcript.cc237
-rw-r--r--src/ssl/ssl_versions.cc77
-rw-r--r--src/ssl/ssl_x509.cc425
-rw-r--r--src/ssl/t1_enc.cc165
-rw-r--r--src/ssl/t1_lib.cc120
-rw-r--r--src/ssl/test/bssl_shim.cc74
-rw-r--r--src/ssl/test/runner/common.go27
-rw-r--r--src/ssl/test/runner/conn.go8
-rw-r--r--src/ssl/test/runner/fuzzer_mode.json4
-rw-r--r--src/ssl/test/runner/handshake_client.go7
-rw-r--r--src/ssl/test/runner/handshake_server.go7
-rw-r--r--src/ssl/test/runner/runner.go191
-rw-r--r--src/ssl/test/test_config.cc1
-rw-r--r--src/ssl/test/test_config.h1
-rw-r--r--src/ssl/tls13_both.cc159
-rw-r--r--src/ssl/tls13_client.cc51
-rw-r--r--src/ssl/tls13_enc.cc81
-rw-r--r--src/ssl/tls13_server.cc110
-rw-r--r--src/ssl/tls_method.cc151
-rw-r--r--src/ssl/tls_record.cc104
-rw-r--r--src/util/all_tests.go11
56 files changed, 3795 insertions, 3430 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 7b7f9343..3c2d5562 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -42,7 +42,7 @@ if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
set(C_CXX_FLAGS "${C_CXX_FLAGS} -Wno-free-nonheap-object")
endif()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_CXX_FLAGS} -Wmissing-prototypes -Wold-style-definition -Wstrict-prototypes")
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 ${C_CXX_FLAGS} -Wmissing-declarations")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 ${C_CXX_FLAGS} -Wmissing-declarations -fno-exceptions")
# In GCC, -Wmissing-declarations is the C++ spelling of -Wmissing-prototypes
# and using the wrong one is an error. In Clang, -Wmissing-prototypes is the
# spelling for both and -Wmissing-declarations is some other warning.
@@ -51,7 +51,7 @@ if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
# https://clang.llvm.org/docs/DiagnosticsReference.html#wmissing-prototypes
# https://clang.llvm.org/docs/DiagnosticsReference.html#wmissing-declarations
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wmissing-prototypes")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wmissing-prototypes -Wimplicit-fallthrough")
endif()
elseif(MSVC)
set(MSVC_DISABLED_WARNINGS_LIST
diff --git a/src/crypto/fipsmodule/FIPS.md b/src/crypto/fipsmodule/FIPS.md
index 30c44874..8378f1b1 100644
--- a/src/crypto/fipsmodule/FIPS.md
+++ b/src/crypto/fipsmodule/FIPS.md
@@ -1,6 +1,14 @@
# FIPS 140-2
-BoringSSL as a whole is not FIPS validated. However, there is a core library (called BoringCrypto) that is undergoing validation at time of writing. This document contains some notes about the design of the FIPS module and some documentation on performing FIPS-related tasks. This is not a substitute for reading the offical Security Policy (which, at the time of writing, has not yet been published).
+BoringSSL as a whole is not FIPS validated. However, there is a core library (called BoringCrypto) that has been FIPS validated. This document contains some notes about the design of the FIPS module and some documentation on performing FIPS-related tasks. This is not a substitute for reading the offical Security Policy.
+
+Please note that we cannot answer questions about FIPS, nor about using BoringSSL in a FIPS-compliant manner. Please consult with an [accredited CMVP lab](http://csrc.nist.gov/groups/STM/testing_labs/) on these subjects.
+
+## Validations
+
+BoringCrypto has undergone the following validations:
+
+1. 2017-06-15: certificate [#2964](http://csrc.nist.gov/groups/STM/cmvp/documents/140-1/1401val2017.htm#2964), [security policy](/crypto/fipsmodule/policydocs/BoringCrypto-Security-Policy-20170615.docx) (in docx format).
## Running CAVP tests
diff --git a/src/crypto/fipsmodule/policydocs/BoringCrypto-Security-Policy-20170615.docx b/src/crypto/fipsmodule/policydocs/BoringCrypto-Security-Policy-20170615.docx
new file mode 100644
index 00000000..272713b2
--- /dev/null
+++ b/src/crypto/fipsmodule/policydocs/BoringCrypto-Security-Policy-20170615.docx
Binary files differ
diff --git a/src/crypto/fipsmodule/rand/urandom.c b/src/crypto/fipsmodule/rand/urandom.c
index 2ea8730c..8cbf7278 100644
--- a/src/crypto/fipsmodule/rand/urandom.c
+++ b/src/crypto/fipsmodule/rand/urandom.c
@@ -45,33 +45,33 @@
#if defined(OPENSSL_LINUX)
#if defined(OPENSSL_X86_64)
-#define EXPECTED_SYS_getrandom 318
+#define EXPECTED_NR_getrandom 318
#elif defined(OPENSSL_X86)
-#define EXPECTED_SYS_getrandom 355
+#define EXPECTED_NR_getrandom 355
#elif defined(OPENSSL_AARCH64)
-#define EXPECTED_SYS_getrandom 278
+#define EXPECTED_NR_getrandom 278
#elif defined(OPENSSL_ARM)
-#define EXPECTED_SYS_getrandom 384
+#define EXPECTED_NR_getrandom 384
#elif defined(OPENSSL_PPC64LE)
-#define EXPECTED_SYS_getrandom 359
+#define EXPECTED_NR_getrandom 359
#endif
-#if defined(EXPECTED_SYS_getrandom)
-#define USE_SYS_getrandom
+#if defined(EXPECTED_NR_getrandom)
+#define USE_NR_getrandom
-#if defined(SYS_getrandom)
+#if defined(__NR_getrandom)
-#if SYS_getrandom != EXPECTED_SYS_getrandom
+#if __NR_getrandom != EXPECTED_NR_getrandom
#error "system call number for getrandom is not the expected value"
#endif
-#else /* SYS_getrandom */
+#else /* __NR_getrandom */
-#define SYS_getrandom EXPECTED_SYS_getrandom
+#define __NR_getrandom EXPECTED_NR_getrandom
-#endif /* SYS_getrandom */
+#endif /* __NR_getrandom */
-#endif /* EXPECTED_SYS_getrandom */
+#endif /* EXPECTED_NR_getrandom */
#if !defined(GRND_NONBLOCK)
#define GRND_NONBLOCK 1
@@ -95,7 +95,7 @@ DEFINE_BSS_GET(int, urandom_fd);
DEFINE_STATIC_ONCE(rand_once);
-#if defined(USE_SYS_getrandom) || defined(BORINGSSL_FIPS)
+#if defined(USE_NR_getrandom) || defined(BORINGSSL_FIPS)
/* message writes |msg| to stderr. We use this because referencing |stderr|
* with |fprintf| generates relocations, which is a problem inside the FIPS
* module. */
@@ -116,10 +116,10 @@ static void init_once(void) {
int fd = *urandom_fd_requested_bss_get();
CRYPTO_STATIC_MUTEX_unlock_read(rand_lock_bss_get());
-#if defined(USE_SYS_getrandom)
+#if defined(USE_NR_getrandom)
uint8_t dummy;
long getrandom_ret =
- syscall(SYS_getrandom, &dummy, sizeof(dummy), GRND_NONBLOCK);
+ syscall(__NR_getrandom, &dummy, sizeof(dummy), GRND_NONBLOCK);
if (getrandom_ret == 1) {
*urandom_fd_bss_get() = kHaveGetrandom;
@@ -132,7 +132,7 @@ static void init_once(void) {
do {
getrandom_ret =
- syscall(SYS_getrandom, &dummy, sizeof(dummy), 0 /* no flags */);
+ syscall(__NR_getrandom, &dummy, sizeof(dummy), 0 /* no flags */);
} while (getrandom_ret == -1 && errno == EINTR);
if (getrandom_ret == 1) {
@@ -140,7 +140,7 @@ static void init_once(void) {
return;
}
}
-#endif /* USE_SYS_getrandom */
+#endif /* USE_NR_getrandom */
if (fd == kUnset) {
do {
@@ -234,7 +234,7 @@ void RAND_set_urandom_fd(int fd) {
}
}
-#if defined(USE_SYS_getrandom) && defined(OPENSSL_MSAN)
+#if defined(USE_NR_getrandom) && defined(OPENSSL_MSAN)
void __msan_unpoison(void *, size_t);
#endif
@@ -245,9 +245,9 @@ static char fill_with_entropy(uint8_t *out, size_t len) {
ssize_t r;
if (*urandom_fd_bss_get() == kHaveGetrandom) {
-#if defined(USE_SYS_getrandom)
+#if defined(USE_NR_getrandom)
do {
- r = syscall(SYS_getrandom, out, len, 0 /* no flags */);
+ r = syscall(__NR_getrandom, out, len, 0 /* no flags */);
} while (r == -1 && errno == EINTR);
#if defined(OPENSSL_MSAN)
@@ -258,7 +258,7 @@ static char fill_with_entropy(uint8_t *out, size_t len) {
}
#endif /* OPENSSL_MSAN */
-#else /* USE_SYS_getrandom */
+#else /* USE_NR_getrandom */
abort();
#endif
} else {
diff --git a/src/include/openssl/base.h b/src/include/openssl/base.h
index 460c1e0f..42ead4d2 100644
--- a/src/include/openssl/base.h
+++ b/src/include/openssl/base.h
@@ -317,7 +317,6 @@ typedef struct spake2_ctx_st SPAKE2_CTX;
typedef struct srtp_protection_profile_st SRTP_PROTECTION_PROFILE;
typedef struct ssl_cipher_st SSL_CIPHER;
typedef struct ssl_ctx_st SSL_CTX;
-typedef struct ssl_custom_extension SSL_CUSTOM_EXTENSION;
typedef struct ssl_method_st SSL_METHOD;
typedef struct ssl_private_key_method_st SSL_PRIVATE_KEY_METHOD;
typedef struct ssl_session_st SSL_SESSION;
@@ -341,6 +340,9 @@ typedef void *OPENSSL_BLOCK;
#if defined(__cplusplus)
} /* extern C */
+#elif !defined(BORINGSSL_NO_CXX)
+#define BORINGSSL_NO_CXX
+#endif
// MSVC doesn't set __cplusplus to 201103 to indicate C++11 support (see
// https://connect.microsoft.com/VisualStudio/feedback/details/763051/a-value-of-predefined-macro-cplusplus-is-still-199711l)
@@ -371,13 +373,13 @@ extern "C++" {
extern "C++" {
-#include <memory>
-
namespace bssl {
namespace internal {
-template <typename T>
+// The Enable parameter is ignored and only exists so specializations can use
+// SFINAE.
+template <typename T, typename Enable = void>
struct DeleterImpl {};
template <typename T>
@@ -451,6 +453,4 @@ using UniquePtr = std::unique_ptr<T, internal::Deleter<T>>;
#endif // !BORINGSSL_NO_CXX
-#endif
-
#endif /* OPENSSL_HEADER_BASE_H */
diff --git a/src/include/openssl/bn.h b/src/include/openssl/bn.h
index ee331669..bdd41bab 100644
--- a/src/include/openssl/bn.h
+++ b/src/include/openssl/bn.h
@@ -938,8 +938,7 @@ OPENSSL_EXPORT unsigned BN_num_bits_word(BN_ULONG l);
#if defined(__cplusplus)
} /* extern C */
-#if (__cplusplus >= 201103L || (__cplusplus < 200000 && __cplusplus > 199711L)) && !defined(OPENSSL_NO_CXX)
-
+#if !defined(BORINGSSL_NO_CXX)
extern "C++" {
namespace bssl {
diff --git a/src/include/openssl/pool.h b/src/include/openssl/pool.h
index 8a07af53..4972b93c 100644
--- a/src/include/openssl/pool.h
+++ b/src/include/openssl/pool.h
@@ -82,6 +82,8 @@ namespace bssl {
BORINGSSL_MAKE_DELETER(CRYPTO_BUFFER_POOL, CRYPTO_BUFFER_POOL_free)
BORINGSSL_MAKE_DELETER(CRYPTO_BUFFER, CRYPTO_BUFFER_free)
+BORINGSSL_MAKE_STACK_DELETER(CRYPTO_BUFFER, CRYPTO_BUFFER_free)
+
} // namespace bssl
} /* extern C++ */
diff --git a/src/include/openssl/ssl.h b/src/include/openssl/ssl.h
index 16aeaff0..04ec4b83 100644
--- a/src/include/openssl/ssl.h
+++ b/src/include/openssl/ssl.h
@@ -517,6 +517,13 @@ OPENSSL_EXPORT int SSL_get_error(const SSL *ssl, int ret_code);
* used to reuse the underlying connection for the retry. */
#define SSL_ERROR_EARLY_DATA_REJECTED 15
+/* SSL_ERROR_WANT_CERTIFICATE_VERIFY indicates the operation failed because
+ * certificate verification was incomplete. The caller may retry the operation
+ * when certificate verification is complete.
+ *
+ * See also |SSL_CTX_set_custom_verify|. */
+#define SSL_ERROR_WANT_CERTIFICATE_VERIFY 16
+
/* SSL_set_mtu sets the |ssl|'s MTU in DTLS to |mtu|. It returns one on success
* and zero on failure. */
OPENSSL_EXPORT int SSL_set_mtu(SSL *ssl, unsigned mtu);
@@ -2201,6 +2208,39 @@ OPENSSL_EXPORT void SSL_set_verify(SSL *ssl, int mode,
int (*callback)(int ok,
X509_STORE_CTX *store_ctx));
+enum ssl_verify_result_t {
+ ssl_verify_ok,
+ ssl_verify_invalid,
+ ssl_verify_retry,
+};
+
+/* SSL_CTX_set_custom_verify configures certificate verification. |mode| is one
+ * of the |SSL_VERIFY_*| values defined above. |callback| performs the
+ * certificate verification.
+ *
+ * The callback may call |SSL_get0_peer_certificates| for the certificate chain
+ * to validate. The callback should return |ssl_verify_ok| if the certificate is
+ * valid. If the certificate is invalid, the callback should return
+ * |ssl_verify_invalid| and optionally set |*out_alert| to an alert to send to
+ * the peer. Some useful alerts include |SSL_AD_CERTIFICATE_EXPIRED|,
+ * |SSL_AD_CERTIFICATE_REVOKED|, |SSL_AD_UNKNOWN_CA|, |SSL_AD_BAD_CERTIFICATE|,
+ * |SSL_AD_CERTIFICATE_UNKNOWN|, and |SSL_AD_INTERNAL_ERROR|. See RFC 5246
+ * section 7.2.2 for their precise meanings. If unspecified,
+ * |SSL_AD_CERTIFICATE_UNKNOWN| will be sent by default.
+ *
+ * To verify a certificate asynchronously, the callback may return
+ * |ssl_verify_retry|. The handshake will then pause with |SSL_get_error|
+ * returning |SSL_ERROR_WANT_CERTIFICATE_VERIFY|. */
+OPENSSL_EXPORT void SSL_CTX_set_custom_verify(
+ SSL_CTX *ctx, int mode,
+ enum ssl_verify_result_t (*callback)(SSL *ssl, uint8_t *out_alert));
+
+/* SSL_set_custom_verify behaves like |SSL_CTX_set_custom_verify| but configures
+ * an individual |SSL|. */
+OPENSSL_EXPORT void SSL_set_custom_verify(
+ SSL *ssl, int mode,
+ enum ssl_verify_result_t (*callback)(SSL *ssl, uint8_t *out_alert));
+
/* SSL_CTX_get_verify_mode returns |ctx|'s verify mode, set by
* |SSL_CTX_set_verify|. */
OPENSSL_EXPORT int SSL_CTX_get_verify_mode(const SSL_CTX *ctx);
@@ -2320,13 +2360,6 @@ OPENSSL_EXPORT void SSL_CTX_set_cert_verify_callback(
SSL_CTX *ctx, int (*callback)(X509_STORE_CTX *store_ctx, void *arg),
void *arg);
-/* SSL_CTX_i_promise_to_verify_certs_after_the_handshake indicates that the
- * caller understands that the |CRYPTO_BUFFER|-based methods currently require
- * post-handshake verification of certificates and thus it's ok to accept any
- * certificates during the handshake. */
-OPENSSL_EXPORT void SSL_CTX_i_promise_to_verify_certs_after_the_handshake(
- SSL_CTX *ctx);
-
/* SSL_enable_signed_cert_timestamps causes |ssl| (which must be the client end
* of a connection) to request SCTs from the server. See
* https://tools.ietf.org/html/rfc6962.
@@ -2407,6 +2440,18 @@ OPENSSL_EXPORT void SSL_set_client_CA_list(SSL *ssl,
OPENSSL_EXPORT void SSL_CTX_set_client_CA_list(SSL_CTX *ctx,
STACK_OF(X509_NAME) *name_list);
+/* SSL_set0_client_CAs sets |ssl|'s client certificate CA list to |name_list|,
+ * which should contain DER-encoded distinguished names (RFC 5280). It takes
+ * ownership of |name_list|. */
+OPENSSL_EXPORT void SSL_set0_client_CAs(SSL *ssl,
+ STACK_OF(CRYPTO_BUFFER) *name_list);
+
+/* SSL_CTX_set0_client_CAs sets |ctx|'s client certificate CA list to
+ * |name_list|, which should contain DER-encoded distinguished names (RFC 5280).
+ * It takes ownership of |name_list|. */
+OPENSSL_EXPORT void SSL_CTX_set0_client_CAs(SSL_CTX *ctx,
+ STACK_OF(CRYPTO_BUFFER) *name_list);
+
/* SSL_get_client_CA_list returns |ssl|'s client certificate CA list. If |ssl|
* has not been configured as a client, this is the list configured by
* |SSL_CTX_set_client_CA_list|.
@@ -3141,6 +3186,7 @@ enum tls13_variant_t {
tls13_default = 0,
tls13_experiment = 1,
tls13_record_type_experiment = 2,
+ tls13_no_session_id_experiment = 3,
};
/* SSL_CTX_set_tls13_variant sets which variant of TLS 1.3 we negotiate. On the
@@ -3748,6 +3794,7 @@ OPENSSL_EXPORT void SSL_CTX_set_client_cert_cb(
#define SSL_PRIVATE_KEY_OPERATION 9
#define SSL_PENDING_TICKET 10
#define SSL_EARLY_DATA_REJECTED 11
+#define SSL_CERTIFICATE_VERIFY 12
/* SSL_want returns one of the above values to determine what the most recent
* operation on |ssl| was blocked on. Use |SSL_get_error| instead. */
@@ -3936,9 +3983,13 @@ OPENSSL_EXPORT SSL_SESSION *SSL_get1_session(SSL *ssl);
* This structures are exposed for historical reasons, but access to them is
* deprecated. */
+/* TODO(davidben): Opaquify most or all of |SSL_CTX| and |SSL_SESSION| so these
+ * forward declarations are not needed. */
typedef struct ssl_protocol_method_st SSL_PROTOCOL_METHOD;
typedef struct ssl_x509_method_st SSL_X509_METHOD;
+DECLARE_STACK_OF(SSL_CUSTOM_EXTENSION)
+
struct ssl_cipher_st {
/* name is the OpenSSL name for the cipher. */
const char *name;
@@ -4122,8 +4173,6 @@ struct ssl_cipher_preference_list_st {
uint8_t *in_group_flags;
};
-DECLARE_STACK_OF(SSL_CUSTOM_EXTENSION)
-
/* ssl_ctx_st (aka |SSL_CTX|) contains configuration common to several SSL
* connections. */
struct ssl_ctx_st {
@@ -4194,6 +4243,9 @@ struct ssl_ctx_st {
int (*app_verify_callback)(X509_STORE_CTX *store_ctx, void *arg);
void *app_verify_arg;
+ enum ssl_verify_result_t (*custom_verify_callback)(SSL *ssl,
+ uint8_t *out_alert);
+
/* Default password callback. */
pem_password_cb *default_passwd_callback;
@@ -4232,7 +4284,7 @@ struct ssl_ctx_st {
uint32_t mode;
uint32_t max_cert_list;
- struct cert_st /* CERT */ *cert;
+ struct cert_st *cert;
/* callback that allows applications to peek at protocol messages */
void (*msg_callback)(int write_p, int version, int content_type,
@@ -4374,12 +4426,6 @@ struct ssl_ctx_st {
* otherwise. */
unsigned grease_enabled:1;
- /* i_promise_to_verify_certs_after_the_handshake indicates that the
- * application is using the |CRYPTO_BUFFER|-based methods and understands
- * that this currently requires post-handshake verification of
- * certificates. */
- unsigned i_promise_to_verify_certs_after_the_handshake:1;
-
/* allow_unknown_alpn_protos is one if the client allows unsolicited ALPN
* protocols from the peer. */
unsigned allow_unknown_alpn_protos:1;
diff --git a/src/include/openssl/ssl3.h b/src/include/openssl/ssl3.h
index 2b241ba8..39cd07b9 100644
--- a/src/include/openssl/ssl3.h
+++ b/src/include/openssl/ssl3.h
@@ -334,6 +334,7 @@ OPENSSL_COMPILE_ASSERT(
/* server */
/* extra state */
#define SSL3_ST_SW_FLUSH (0x100 | SSL_ST_ACCEPT)
+#define SSL3_ST_VERIFY_CLIENT_CERT (0x101 | SSL_ST_ACCEPT)
/* read from client */
#define SSL3_ST_SR_CLNT_HELLO_A (0x110 | SSL_ST_ACCEPT)
#define SSL3_ST_SR_CLNT_HELLO_B (0x111 | SSL_ST_ACCEPT)
diff --git a/src/include/openssl/type_check.h b/src/include/openssl/type_check.h
index 7e70918b..a6f8284f 100644
--- a/src/include/openssl/type_check.h
+++ b/src/include/openssl/type_check.h
@@ -78,13 +78,9 @@ extern "C" {
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
#define OPENSSL_COMPILE_ASSERT(cond, msg) _Static_assert(cond, #msg)
-#elif defined(__GNUC__)
-#define OPENSSL_COMPILE_ASSERT(cond, msg) \
- typedef char OPENSSL_COMPILE_ASSERT_##msg[((cond) ? 1 : -1)] \
- __attribute__((unused))
#else
#define OPENSSL_COMPILE_ASSERT(cond, msg) \
- typedef char OPENSSL_COMPILE_ASSERT_##msg[((cond) ? 1 : -1)]
+ typedef char OPENSSL_COMPILE_ASSERT_##msg[((cond) ? 1 : -1)] OPENSSL_UNUSED
#endif
diff --git a/src/ssl/CMakeLists.txt b/src/ssl/CMakeLists.txt
index b6f4451c..c228f4a6 100644
--- a/src/ssl/CMakeLists.txt
+++ b/src/ssl/CMakeLists.txt
@@ -21,8 +21,8 @@ add_library(
ssl_buffer.cc
ssl_cert.cc
ssl_cipher.cc
- ssl_ecdh.cc
ssl_file.cc
+ ssl_key_share.cc
ssl_lib.cc
ssl_privkey.cc
ssl_session.cc
diff --git a/src/ssl/custom_extensions.cc b/src/ssl/custom_extensions.cc
index f438f739..d86bd484 100644
--- a/src/ssl/custom_extensions.cc
+++ b/src/ssl/custom_extensions.cc
@@ -25,6 +25,8 @@
#include "internal.h"
+namespace bssl {
+
void SSL_CUSTOM_EXTENSION_free(SSL_CUSTOM_EXTENSION *custom_extension) {
OPENSSL_free(custom_extension);
}
@@ -246,6 +248,10 @@ static int custom_ext_append(STACK_OF(SSL_CUSTOM_EXTENSION) **stack,
return 1;
}
+} // namespace bssl
+
+using namespace bssl;
+
int SSL_CTX_add_client_custom_ext(SSL_CTX *ctx, unsigned extension_value,
SSL_custom_ext_add_cb add_cb,
SSL_custom_ext_free_cb free_cb, void *add_arg,
diff --git a/src/ssl/d1_both.cc b/src/ssl/d1_both.cc
index ee0ec4fd..50cca832 100644
--- a/src/ssl/d1_both.cc
+++ b/src/ssl/d1_both.cc
@@ -127,6 +127,8 @@
#include "internal.h"
+namespace bssl {
+
/* TODO(davidben): 28 comes from the size of IP + UDP header. Is this reasonable
* for these values? Notably, why is kMinMTU a function of the transport
* protocol's overhead rather than, say, what's needed to hold a minimally-sized
@@ -152,6 +154,7 @@ static void dtls1_hm_fragment_free(hm_fragment *frag) {
}
static hm_fragment *dtls1_hm_fragment_new(const struct hm_header_st *msg_hdr) {
+ ScopedCBB cbb;
hm_fragment *frag = (hm_fragment *)OPENSSL_malloc(sizeof(hm_fragment));
if (frag == NULL) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
@@ -170,15 +173,13 @@ static hm_fragment *dtls1_hm_fragment_new(const struct hm_header_st *msg_hdr) {
goto err;
}
- CBB cbb;
- if (!CBB_init_fixed(&cbb, frag->data, DTLS1_HM_HEADER_LENGTH) ||
- !CBB_add_u8(&cbb, msg_hdr->type) ||
- !CBB_add_u24(&cbb, msg_hdr->msg_len) ||
- !CBB_add_u16(&cbb, msg_hdr->seq) ||
- !CBB_add_u24(&cbb, 0 /* frag_off */) ||
- !CBB_add_u24(&cbb, msg_hdr->msg_len) ||
- !CBB_finish(&cbb, NULL, NULL)) {
- CBB_cleanup(&cbb);
+ if (!CBB_init_fixed(cbb.get(), frag->data, DTLS1_HM_HEADER_LENGTH) ||
+ !CBB_add_u8(cbb.get(), msg_hdr->type) ||
+ !CBB_add_u24(cbb.get(), msg_hdr->msg_len) ||
+ !CBB_add_u16(cbb.get(), msg_hdr->seq) ||
+ !CBB_add_u24(cbb.get(), 0 /* frag_off */) ||
+ !CBB_add_u24(cbb.get(), msg_hdr->msg_len) ||
+ !CBB_finish(cbb.get(), NULL, NULL)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
goto err;
}
@@ -320,9 +321,9 @@ start:
* the unencrypted epoch (we never renegotiate). Other cases fall through and
* fail with a fatal error. */
if ((rr->type == SSL3_RT_APPLICATION_DATA &&
- ssl->s3->aead_read_ctx != NULL) ||
+ !ssl->s3->aead_read_ctx->is_null_cipher()) ||
(rr->type == SSL3_RT_CHANGE_CIPHER_SPEC &&
- ssl->s3->aead_read_ctx == NULL)) {
+ ssl->s3->aead_read_ctx->is_null_cipher())) {
rr->length = 0;
goto start;
}
@@ -548,10 +549,10 @@ static int add_outgoing(SSL *ssl, int is_ccs, uint8_t *data, size_t len) {
}
if (!is_ccs) {
- /* TODO(svaldez): Move this up a layer to fix abstraction for SSL_TRANSCRIPT
+ /* TODO(svaldez): Move this up a layer to fix abstraction for SSLTranscript
* on hs. */
if (ssl->s3->hs != NULL &&
- !SSL_TRANSCRIPT_update(&ssl->s3->hs->transcript, data, len)) {
+ !ssl->s3->hs->transcript.Update(data, len)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
OPENSSL_free(data);
return 0;
@@ -624,14 +625,14 @@ static enum seal_result_t seal_next_message(SSL *ssl, uint8_t *out,
assert(ssl->d1->outgoing_written < ssl->d1->outgoing_messages_len);
assert(msg == &ssl->d1->outgoing_messages[ssl->d1->outgoing_written]);
- /* DTLS renegotiation is unsupported, so only epochs 0 (NULL cipher) and 1
- * (negotiated cipher) exist. */
- assert(ssl->d1->w_epoch == 0 || ssl->d1->w_epoch == 1);
- assert(msg->epoch <= ssl->d1->w_epoch);
enum dtls1_use_epoch_t use_epoch = dtls1_use_current_epoch;
- if (ssl->d1->w_epoch == 1 && msg->epoch == 0) {
+ if (ssl->d1->w_epoch >= 1 && msg->epoch == ssl->d1->w_epoch - 1) {
use_epoch = dtls1_use_previous_epoch;
+ } else if (msg->epoch != ssl->d1->w_epoch) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+ return seal_error;
}
+
size_t overhead = dtls_max_seal_overhead(ssl, use_epoch);
size_t prefix = dtls_seal_prefix_len(ssl, use_epoch);
@@ -677,18 +678,17 @@ static enum seal_result_t seal_next_message(SSL *ssl, uint8_t *out,
}
/* Assemble a fragment, to be sealed in-place. */
- CBB cbb;
+ ScopedCBB cbb;
uint8_t *frag = out + prefix;
size_t max_frag = max_out - prefix, frag_len;
- if (!CBB_init_fixed(&cbb, frag, max_frag) ||
- !CBB_add_u8(&cbb, hdr.type) ||
- !CBB_add_u24(&cbb, hdr.msg_len) ||
- !CBB_add_u16(&cbb, hdr.seq) ||
- !CBB_add_u24(&cbb, ssl->d1->outgoing_offset) ||
- !CBB_add_u24(&cbb, todo) ||
- !CBB_add_bytes(&cbb, CBS_data(&body), todo) ||
- !CBB_finish(&cbb, NULL, &frag_len)) {
- CBB_cleanup(&cbb);
+ if (!CBB_init_fixed(cbb.get(), frag, max_frag) ||
+ !CBB_add_u8(cbb.get(), hdr.type) ||
+ !CBB_add_u24(cbb.get(), hdr.msg_len) ||
+ !CBB_add_u16(cbb.get(), hdr.seq) ||
+ !CBB_add_u24(cbb.get(), ssl->d1->outgoing_offset) ||
+ !CBB_add_u24(cbb.get(), todo) ||
+ !CBB_add_bytes(cbb.get(), CBS_data(&body), todo) ||
+ !CBB_finish(cbb.get(), NULL, &frag_len)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
return seal_error;
}
@@ -812,3 +812,5 @@ int dtls1_retransmit_outgoing_messages(SSL *ssl) {
unsigned int dtls1_min_mtu(void) {
return kMinMTU;
}
+
+} // namespace bssl
diff --git a/src/ssl/d1_lib.cc b/src/ssl/d1_lib.cc
index 0074855b..8ef1aa22 100644
--- a/src/ssl/d1_lib.cc
+++ b/src/ssl/d1_lib.cc
@@ -68,6 +68,7 @@
#include "internal.h"
+namespace bssl {
/* DTLS1_MTU_TIMEOUTS is the maximum number of timeouts to expire
* before starting to decrease the MTU. */
@@ -108,15 +109,12 @@ void dtls1_free(SSL *ssl) {
dtls_clear_incoming_messages(ssl);
dtls_clear_outgoing_messages(ssl);
+ Delete(ssl->d1->last_aead_write_ctx);
OPENSSL_free(ssl->d1);
ssl->d1 = NULL;
}
-void DTLSv1_set_initial_timeout_duration(SSL *ssl, unsigned int duration_ms) {
- ssl->initial_timeout_duration_ms = duration_ms;
-}
-
void dtls1_start_timer(SSL *ssl) {
/* If timer is not set, initialize duration (by default, 1 second) */
if (ssl->d1->next_timeout.tv_sec == 0 && ssl->d1->next_timeout.tv_usec == 0) {
@@ -135,56 +133,6 @@ void dtls1_start_timer(SSL *ssl) {
}
}
-int DTLSv1_get_timeout(const SSL *ssl, struct timeval *out) {
- if (!SSL_is_dtls(ssl)) {
- return 0;
- }
-
- /* If no timeout is set, just return NULL */
- if (ssl->d1->next_timeout.tv_sec == 0 && ssl->d1->next_timeout.tv_usec == 0) {
- return 0;
- }
-
- struct OPENSSL_timeval timenow;
- ssl_get_current_time(ssl, &timenow);
-
- /* If timer already expired, set remaining time to 0 */
- if (ssl->d1->next_timeout.tv_sec < timenow.tv_sec ||
- (ssl->d1->next_timeout.tv_sec == timenow.tv_sec &&
- ssl->d1->next_timeout.tv_usec <= timenow.tv_usec)) {
- OPENSSL_memset(out, 0, sizeof(*out));
- return 1;
- }
-
- /* Calculate time left until timer expires */
- struct OPENSSL_timeval ret;
- OPENSSL_memcpy(&ret, &ssl->d1->next_timeout, sizeof(ret));
- ret.tv_sec -= timenow.tv_sec;
- if (ret.tv_usec >= timenow.tv_usec) {
- ret.tv_usec -= timenow.tv_usec;
- } else {
- ret.tv_usec = 1000000 + ret.tv_usec - timenow.tv_usec;
- ret.tv_sec--;
- }
-
- /* If remaining time is less than 15 ms, set it to 0 to prevent issues
- * because of small divergences with socket timeouts. */
- if (ret.tv_sec == 0 && ret.tv_usec < 15000) {
- OPENSSL_memset(&ret, 0, sizeof(ret));
- }
-
- /* Clamp the result in case of overflow. */
- if (ret.tv_sec > INT_MAX) {
- assert(0);
- out->tv_sec = INT_MAX;
- } else {
- out->tv_sec = ret.tv_sec;
- }
-
- out->tv_usec = ret.tv_usec;
- return 1;
-}
-
int dtls1_is_timer_expired(SSL *ssl) {
struct timeval timeleft;
@@ -241,6 +189,64 @@ int dtls1_check_timeout_num(SSL *ssl) {
return 0;
}
+} // namespace bssl
+
+using namespace bssl;
+
+void DTLSv1_set_initial_timeout_duration(SSL *ssl, unsigned int duration_ms) {
+ ssl->initial_timeout_duration_ms = duration_ms;
+}
+
+int DTLSv1_get_timeout(const SSL *ssl, struct timeval *out) {
+ if (!SSL_is_dtls(ssl)) {
+ return 0;
+ }
+
+ /* If no timeout is set, just return NULL */
+ if (ssl->d1->next_timeout.tv_sec == 0 && ssl->d1->next_timeout.tv_usec == 0) {
+ return 0;
+ }
+
+ struct OPENSSL_timeval timenow;
+ ssl_get_current_time(ssl, &timenow);
+
+ /* If timer already expired, set remaining time to 0 */
+ if (ssl->d1->next_timeout.tv_sec < timenow.tv_sec ||
+ (ssl->d1->next_timeout.tv_sec == timenow.tv_sec &&
+ ssl->d1->next_timeout.tv_usec <= timenow.tv_usec)) {
+ OPENSSL_memset(out, 0, sizeof(*out));
+ return 1;
+ }
+
+ /* Calculate time left until timer expires */
+ struct OPENSSL_timeval ret;
+ OPENSSL_memcpy(&ret, &ssl->d1->next_timeout, sizeof(ret));
+ ret.tv_sec -= timenow.tv_sec;
+ if (ret.tv_usec >= timenow.tv_usec) {
+ ret.tv_usec -= timenow.tv_usec;
+ } else {
+ ret.tv_usec = 1000000 + ret.tv_usec - timenow.tv_usec;
+ ret.tv_sec--;
+ }
+
+ /* If remaining time is less than 15 ms, set it to 0 to prevent issues
+ * because of small divergences with socket timeouts. */
+ if (ret.tv_sec == 0 && ret.tv_usec < 15000) {
+ OPENSSL_memset(&ret, 0, sizeof(ret));
+ }
+
+ /* Clamp the result in case of overflow. */
+ if (ret.tv_sec > INT_MAX) {
+ assert(0);
+ out->tv_sec = INT_MAX;
+ } else {
+ out->tv_sec = ret.tv_sec;
+ }
+
+ out->tv_usec = ret.tv_usec;
+ return 1;
+}
+
int DTLSv1_handle_timeout(SSL *ssl) {
ssl_reset_error_state(ssl);
diff --git a/src/ssl/d1_pkt.cc b/src/ssl/d1_pkt.cc
index 1ae55ebb..52e81115 100644
--- a/src/ssl/d1_pkt.cc
+++ b/src/ssl/d1_pkt.cc
@@ -126,6 +126,8 @@
#include "internal.h"
+namespace bssl {
+
int dtls1_get_record(SSL *ssl) {
again:
switch (ssl->s3->recv_shutdown) {
@@ -415,3 +417,5 @@ int dtls1_dispatch_alert(SSL *ssl) {
return 1;
}
+
+} // namespace bssl
diff --git a/src/ssl/d1_srtp.cc b/src/ssl/d1_srtp.cc
index 10853777..2d94bd24 100644
--- a/src/ssl/d1_srtp.cc
+++ b/src/ssl/d1_srtp.cc
@@ -124,6 +124,8 @@
#include "internal.h"
+using namespace bssl;
+
static const SRTP_PROTECTION_PROFILE kSRTPProfiles[] = {
{
"SRTP_AES128_CM_SHA1_80", SRTP_AES128_CM_SHA1_80,
@@ -143,9 +145,7 @@ static const SRTP_PROTECTION_PROFILE kSRTPProfiles[] = {
static int find_profile_by_name(const char *profile_name,
const SRTP_PROTECTION_PROFILE **pptr,
size_t len) {
- const SRTP_PROTECTION_PROFILE *p;
-
- p = kSRTPProfiles;
+ const SRTP_PROTECTION_PROFILE *p = kSRTPProfiles;
while (p->name) {
if (len == strlen(p->name) && !strncmp(p->name, profile_name, len)) {
*pptr = p;
diff --git a/src/ssl/dtls_method.cc b/src/ssl/dtls_method.cc
index dd8d7865..15c46083 100644
--- a/src/ssl/dtls_method.cc
+++ b/src/ssl/dtls_method.cc
@@ -66,6 +66,8 @@
#include "internal.h"
+using namespace bssl;
+
static int dtls1_supports_cipher(const SSL_CIPHER *cipher) {
return cipher->algorithm_enc != SSL_eNULL;
}
@@ -74,12 +76,11 @@ static void dtls1_expect_flight(SSL *ssl) { dtls1_start_timer(ssl); }
static void dtls1_received_flight(SSL *ssl) { dtls1_stop_timer(ssl); }
-static int dtls1_set_read_state(SSL *ssl, SSL_AEAD_CTX *aead_ctx) {
+static int dtls1_set_read_state(SSL *ssl, UniquePtr<SSLAEADContext> aead_ctx) {
/* Cipher changes are illegal when there are buffered incoming messages. */
if (dtls_has_incoming_messages(ssl)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_BUFFERED_MESSAGES_ON_CIPHER_CHANGE);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
- SSL_AEAD_CTX_free(aead_ctx);
return 0;
}
@@ -87,19 +88,20 @@ static int dtls1_set_read_state(SSL *ssl, SSL_AEAD_CTX *aead_ctx) {
OPENSSL_memset(&ssl->d1->bitmap, 0, sizeof(ssl->d1->bitmap));
OPENSSL_memset(ssl->s3->read_sequence, 0, sizeof(ssl->s3->read_sequence));
- SSL_AEAD_CTX_free(ssl->s3->aead_read_ctx);
- ssl->s3->aead_read_ctx = aead_ctx;
+ Delete(ssl->s3->aead_read_ctx);
+ ssl->s3->aead_read_ctx = aead_ctx.release();
return 1;
}
-static int dtls1_set_write_state(SSL *ssl, SSL_AEAD_CTX *aead_ctx) {
+static int dtls1_set_write_state(SSL *ssl, UniquePtr<SSLAEADContext> aead_ctx) {
ssl->d1->w_epoch++;
OPENSSL_memcpy(ssl->d1->last_write_sequence, ssl->s3->write_sequence,
sizeof(ssl->s3->write_sequence));
OPENSSL_memset(ssl->s3->write_sequence, 0, sizeof(ssl->s3->write_sequence));
- SSL_AEAD_CTX_free(ssl->s3->aead_write_ctx);
- ssl->s3->aead_write_ctx = aead_ctx;
+ Delete(ssl->d1->last_aead_write_ctx);
+ ssl->d1->last_aead_write_ctx = ssl->s3->aead_write_ctx;
+ ssl->s3->aead_write_ctx = aead_ctx.release();
return 1;
}
diff --git a/src/ssl/dtls_record.cc b/src/ssl/dtls_record.cc
index 879706df..c7ee6463 100644
--- a/src/ssl/dtls_record.cc
+++ b/src/ssl/dtls_record.cc
@@ -121,6 +121,8 @@
#include "../crypto/internal.h"
+namespace bssl {
+
/* to_u64_be treats |in| as a 8-byte big-endian integer and returns the value as
* a |uint64_t|. */
static uint64_t to_u64_be(const uint8_t in[8]) {
@@ -213,8 +215,9 @@ enum ssl_open_record_t dtls_open_record(SSL *ssl, uint8_t *out_type, CBS *out,
}
/* Decrypt the body in-place. */
- if (!SSL_AEAD_CTX_open(ssl->s3->aead_read_ctx, out, type, version, sequence,
- (uint8_t *)CBS_data(&body), CBS_len(&body))) {
+ if (!ssl->s3->aead_read_ctx->Open(out, type, version, sequence,
+ (uint8_t *)CBS_data(&body),
+ CBS_len(&body))) {
/* Bad packets are silently dropped in DTLS. See section 4.2.1 of RFC 6347.
* Clear the error queue of any errors decryption may have added. Drop the
* entire packet as it must not have come from the peer.
@@ -249,13 +252,11 @@ enum ssl_open_record_t dtls_open_record(SSL *ssl, uint8_t *out_type, CBS *out,
return ssl_open_record_success;
}
-static const SSL_AEAD_CTX *get_write_aead(const SSL *ssl,
- enum dtls1_use_epoch_t use_epoch) {
+static const SSLAEADContext *get_write_aead(const SSL *ssl,
+ enum dtls1_use_epoch_t use_epoch) {
if (use_epoch == dtls1_use_previous_epoch) {
- /* DTLS renegotiation is unsupported, so only epochs 0 (NULL cipher) and 1
- * (negotiated cipher) exist. */
- assert(ssl->d1->w_epoch == 1);
- return NULL;
+ assert(ssl->d1->w_epoch >= 1);
+ return ssl->d1->last_aead_write_ctx;
}
return ssl->s3->aead_write_ctx;
@@ -263,13 +264,12 @@ static const SSL_AEAD_CTX *get_write_aead(const SSL *ssl,
size_t dtls_max_seal_overhead(const SSL *ssl,
enum dtls1_use_epoch_t use_epoch) {
- return DTLS1_RT_HEADER_LENGTH +
- SSL_AEAD_CTX_max_overhead(get_write_aead(ssl, use_epoch));
+ return DTLS1_RT_HEADER_LENGTH + get_write_aead(ssl, use_epoch)->MaxOverhead();
}
size_t dtls_seal_prefix_len(const SSL *ssl, enum dtls1_use_epoch_t use_epoch) {
return DTLS1_RT_HEADER_LENGTH +
- SSL_AEAD_CTX_explicit_nonce_len(get_write_aead(ssl, use_epoch));
+ get_write_aead(ssl, use_epoch)->ExplicitNonceLen();
}
int dtls_seal_record(SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out,
@@ -284,14 +284,12 @@ int dtls_seal_record(SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out,
/* Determine the parameters for the current epoch. */
uint16_t epoch = ssl->d1->w_epoch;
- SSL_AEAD_CTX *aead = ssl->s3->aead_write_ctx;
+ SSLAEADContext *aead = ssl->s3->aead_write_ctx;
uint8_t *seq = ssl->s3->write_sequence;
if (use_epoch == dtls1_use_previous_epoch) {
- /* DTLS renegotiation is unsupported, so only epochs 0 (NULL cipher) and 1
- * (negotiated cipher) exist. */
- assert(ssl->d1->w_epoch == 1);
+ assert(ssl->d1->w_epoch >= 1);
epoch = ssl->d1->w_epoch - 1;
- aead = NULL;
+ aead = ssl->d1->last_aead_write_ctx;
seq = ssl->d1->last_write_sequence;
}
@@ -311,9 +309,9 @@ int dtls_seal_record(SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out,
OPENSSL_memcpy(&out[5], &seq[2], 6);
size_t ciphertext_len;
- if (!SSL_AEAD_CTX_seal(aead, out + DTLS1_RT_HEADER_LENGTH, &ciphertext_len,
- max_out - DTLS1_RT_HEADER_LENGTH, type, wire_version,
- &out[3] /* seq */, in, in_len) ||
+ if (!aead->Seal(out + DTLS1_RT_HEADER_LENGTH, &ciphertext_len,
+ max_out - DTLS1_RT_HEADER_LENGTH, type, wire_version,
+ &out[3] /* seq */, in, in_len) ||
!ssl_record_sequence_update(&seq[2], 6)) {
return 0;
}
@@ -332,3 +330,5 @@ int dtls_seal_record(SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out,
return 1;
}
+
+} // namespace bssl
diff --git a/src/ssl/handshake_client.cc b/src/ssl/handshake_client.cc
index 9efbf0ad..260d3cd0 100644
--- a/src/ssl/handshake_client.cc
+++ b/src/ssl/handshake_client.cc
@@ -152,6 +152,8 @@
#include <assert.h>
#include <string.h>
+#include <utility>
+
#include <openssl/aead.h>
#include <openssl/bn.h>
#include <openssl/buf.h>
@@ -168,12 +170,13 @@
#include "internal.h"
+namespace bssl {
+
static int ssl3_send_client_hello(SSL_HANDSHAKE *hs);
static int dtls1_get_hello_verify_request(SSL_HANDSHAKE *hs);
static int ssl3_get_server_hello(SSL_HANDSHAKE *hs);
static int ssl3_get_server_certificate(SSL_HANDSHAKE *hs);
static int ssl3_get_cert_status(SSL_HANDSHAKE *hs);
-static int ssl3_verify_server_cert(SSL_HANDSHAKE *hs);
static int ssl3_get_server_key_exchange(SSL_HANDSHAKE *hs);
static int ssl3_get_certificate_request(SSL_HANDSHAKE *hs);
static int ssl3_get_server_hello_done(SSL_HANDSHAKE *hs);
@@ -246,8 +249,8 @@ int ssl3_connect(SSL_HANDSHAKE *hs) {
/* Stash the early data session, so connection properties may be queried
* out of it. */
hs->in_early_data = 1;
- hs->early_session = ssl->session;
SSL_SESSION_up_ref(ssl->session);
+ hs->early_session.reset(ssl->session);
hs->state = SSL3_ST_CR_SRVR_HELLO_A;
hs->can_early_write = 1;
@@ -292,9 +295,16 @@ int ssl3_connect(SSL_HANDSHAKE *hs) {
case SSL3_ST_VERIFY_SERVER_CERT:
if (ssl_cipher_uses_certificate_auth(hs->new_cipher)) {
- ret = ssl3_verify_server_cert(hs);
- if (ret <= 0) {
- goto end;
+ switch (ssl_verify_peer_cert(hs)) {
+ case ssl_verify_ok:
+ break;
+ case ssl_verify_invalid:
+ ret = -1;
+ goto end;
+ case ssl_verify_retry:
+ ssl->rwstate = SSL_CERTIFICATE_VERIFY;
+ ret = -1;
+ goto end;
}
}
hs->state = SSL3_ST_CR_KEY_EXCH_A;
@@ -498,15 +508,15 @@ int ssl3_connect(SSL_HANDSHAKE *hs) {
* of the new established_session due to False Start. The caller may
* have taken a reference to the temporary session. */
ssl->s3->established_session =
- SSL_SESSION_dup(hs->new_session, SSL_SESSION_DUP_ALL);
+ SSL_SESSION_dup(hs->new_session.get(), SSL_SESSION_DUP_ALL)
+ .release();
if (ssl->s3->established_session == NULL) {
ret = -1;
goto end;
}
ssl->s3->established_session->not_resumable = 0;
- SSL_SESSION_free(hs->new_session);
- hs->new_session = NULL;
+ hs->new_session.reset();
}
hs->state = SSL_ST_OK;
@@ -541,18 +551,6 @@ end:
return ret;
}
-uint16_t ssl_get_grease_value(const SSL *ssl, enum ssl_grease_index_t index) {
- /* Use the client_random for entropy. This both avoids calling |RAND_bytes| on
- * a single byte repeatedly and ensures the values are deterministic. This
- * allows the same ClientHello be sent twice for a HelloRetryRequest or the
- * same group be advertised in both supported_groups and key_shares. */
- uint16_t ret = ssl->s3->client_random[index];
- /* This generates a random value of the form 0xωaωa, for all 0 ≤ ω < 16. */
- ret = (ret & 0xf0) | 0x0a;
- ret |= ret << 8;
- return ret;
-}
-
/* ssl_get_client_disabled sets |*out_mask_a| and |*out_mask_k| to masks of
* disabled algorithms. */
static void ssl_get_client_disabled(SSL *ssl, uint32_t *out_mask_a,
@@ -647,7 +645,7 @@ static int ssl_write_client_cipher_list(SSL_HANDSHAKE *hs, CBB *out) {
int ssl_write_client_hello(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
- bssl::ScopedCBB cbb;
+ ScopedCBB cbb;
CBB body;
if (!ssl->method->init_message(ssl, cbb.get(), &body, SSL3_MT_CLIENT_HELLO)) {
return 0;
@@ -717,7 +715,7 @@ static int ssl3_send_client_hello(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
/* The handshake buffer is reset on every ClientHello. Notably, in DTLS, we
* may send multiple ClientHellos if we receive HelloVerifyRequest. */
- if (!SSL_TRANSCRIPT_init(&hs->transcript)) {
+ if (!hs->transcript.Init()) {
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
return -1;
}
@@ -758,7 +756,8 @@ static int ssl3_send_client_hello(SSL_HANDSHAKE *hs) {
return -1;
}
- /* Initialize a random session ID for the experimental TLS 1.3 variant. */
+ /* Initialize a random session ID for the experimental TLS 1.3 variant
+ * requiring a session id. */
if (ssl->tls13_variant == tls13_experiment) {
hs->session_id_len = sizeof(hs->session_id);
if (!RAND_bytes(hs->session_id, hs->session_id_len)) {
@@ -1023,8 +1022,7 @@ static int ssl3_get_server_hello(SSL_HANDSHAKE *hs) {
/* Now that the cipher is known, initialize the handshake hash and hash the
* ServerHello. */
- if (!SSL_TRANSCRIPT_init_hash(&hs->transcript, ssl3_protocol_version(ssl),
- c->algorithm_prf) ||
+ if (!hs->transcript.InitHash(ssl3_protocol_version(ssl), c->algorithm_prf) ||
!ssl_hash_current_message(hs)) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
return -1;
@@ -1035,7 +1033,7 @@ static int ssl3_get_server_hello(SSL_HANDSHAKE *hs) {
* buffer may be released. */
if (ssl->session != NULL ||
!ssl_cipher_uses_certificate_auth(hs->new_cipher)) {
- SSL_TRANSCRIPT_free_buffer(&hs->transcript);
+ hs->transcript.FreeBuffer();
}
/* Only the NULL compression algorithm is supported. */
@@ -1090,10 +1088,10 @@ static int ssl3_get_server_certificate(SSL_HANDSHAKE *hs) {
uint8_t alert = SSL_AD_DECODE_ERROR;
sk_CRYPTO_BUFFER_pop_free(hs->new_session->certs, CRYPTO_BUFFER_free);
- EVP_PKEY_free(hs->peer_pubkey);
- hs->peer_pubkey = NULL;
- hs->new_session->certs = ssl_parse_cert_chain(&alert, &hs->peer_pubkey, NULL,
- &cbs, ssl->ctx->pool);
+ hs->peer_pubkey.reset();
+ hs->new_session->certs =
+ ssl_parse_cert_chain(&alert, &hs->peer_pubkey, NULL, &cbs, ssl->ctx->pool)
+ .release();
if (hs->new_session->certs == NULL) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
return -1;
@@ -1101,14 +1099,14 @@ static int ssl3_get_server_certificate(SSL_HANDSHAKE *hs) {
if (sk_CRYPTO_BUFFER_num(hs->new_session->certs) == 0 ||
CBS_len(&cbs) != 0 ||
- !ssl->ctx->x509_method->session_cache_objects(hs->new_session)) {
+ !ssl->ctx->x509_method->session_cache_objects(hs->new_session.get())) {
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
return -1;
}
if (!ssl_check_leaf_certificate(
- hs, hs->peer_pubkey,
+ hs, hs->peer_pubkey.get(),
sk_CRYPTO_BUFFER_value(hs->new_session->certs, 0))) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
return -1;
@@ -1185,20 +1183,8 @@ static int ssl3_get_cert_status(SSL_HANDSHAKE *hs) {
return 1;
}
-static int ssl3_verify_server_cert(SSL_HANDSHAKE *hs) {
- SSL *const ssl = hs->ssl;
- if (!ssl->ctx->x509_method->session_verify_cert_chain(hs->new_session, ssl)) {
- return -1;
- }
-
- return 1;
-}
-
static int ssl3_get_server_key_exchange(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
- EC_KEY *ecdh = NULL;
- EC_POINT *srvr_ecpoint = NULL;
-
int ret = ssl->method->ssl_get_message(ssl);
if (ret <= 0) {
return ret;
@@ -1236,7 +1222,7 @@ static int ssl3_get_server_key_exchange(SSL_HANDSHAKE *hs) {
&psk_identity_hint)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
- goto err;
+ return -1;
}
/* Store PSK identity hint for later use, hint is used in
@@ -1250,7 +1236,7 @@ static int ssl3_get_server_key_exchange(SSL_HANDSHAKE *hs) {
CBS_contains_zero_byte(&psk_identity_hint)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_DATA_LENGTH_TOO_LONG);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
- goto err;
+ return -1;
}
/* Save non-empty identity hints as a C string. Empty identity hints we
@@ -1258,12 +1244,14 @@ static int ssl3_get_server_key_exchange(SSL_HANDSHAKE *hs) {
* (omit ServerKeyExchange) or an empty hint, while ECDHE_PSK can only spell
* empty hint. Having different capabilities is odd, so we interpret empty
* and missing as identical. */
+ char *raw = nullptr;
if (CBS_len(&psk_identity_hint) != 0 &&
- !CBS_strdup(&psk_identity_hint, &hs->peer_psk_identity_hint)) {
+ !CBS_strdup(&psk_identity_hint, &raw)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
- goto err;
+ return -1;
}
+ hs->peer_psk_identity_hint.reset(raw);
}
if (alg_k & SSL_kECDHE) {
@@ -1277,7 +1265,7 @@ static int ssl3_get_server_key_exchange(SSL_HANDSHAKE *hs) {
!CBS_get_u8_length_prefixed(&server_key_exchange, &point)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
- goto err;
+ return -1;
}
hs->new_session->group_id = group_id;
@@ -1285,18 +1273,19 @@ static int ssl3_get_server_key_exchange(SSL_HANDSHAKE *hs) {
if (!tls1_check_group_id(ssl, group_id)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CURVE);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
- goto err;
+ return -1;
}
/* Initialize ECDH and save the peer public key for later. */
- if (!SSL_ECDH_CTX_init(&hs->ecdh_ctx, group_id) ||
+ hs->key_share = SSLKeyShare::Create(group_id);
+ if (!hs->key_share ||
!CBS_stow(&point, &hs->peer_key, &hs->peer_key_len)) {
- goto err;
+ return -1;
}
} else if (!(alg_k & SSL_kPSK)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_MESSAGE);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
- goto err;
+ return -1;
}
/* At this point, |server_key_exchange| contains the signature, if any, while
@@ -1313,19 +1302,19 @@ static int ssl3_get_server_key_exchange(SSL_HANDSHAKE *hs) {
if (!CBS_get_u16(&server_key_exchange, &signature_algorithm)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
- goto err;
+ return -1;
}
uint8_t alert = SSL_AD_DECODE_ERROR;
if (!tls12_check_peer_sigalg(ssl, &alert, signature_algorithm)) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
- goto err;
+ return -1;
}
hs->new_session->peer_signature_algorithm = signature_algorithm;
} else if (!tls1_get_legacy_signature_algorithm(&signature_algorithm,
- hs->peer_pubkey)) {
+ hs->peer_pubkey.get())) {
OPENSSL_PUT_ERROR(SSL, SSL_R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNSUPPORTED_CERTIFICATE);
- goto err;
+ return -1;
}
/* The last field in |server_key_exchange| is the signature. */
@@ -1334,26 +1323,29 @@ static int ssl3_get_server_key_exchange(SSL_HANDSHAKE *hs) {
CBS_len(&server_key_exchange) != 0) {
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
- goto err;
+ return -1;
}
- CBB transcript;
+ ScopedCBB transcript;
uint8_t *transcript_data;
size_t transcript_len;
- if (!CBB_init(&transcript, 2*SSL3_RANDOM_SIZE + CBS_len(&parameter)) ||
- !CBB_add_bytes(&transcript, ssl->s3->client_random, SSL3_RANDOM_SIZE) ||
- !CBB_add_bytes(&transcript, ssl->s3->server_random, SSL3_RANDOM_SIZE) ||
- !CBB_add_bytes(&transcript, CBS_data(&parameter), CBS_len(&parameter)) ||
- !CBB_finish(&transcript, &transcript_data, &transcript_len)) {
- CBB_cleanup(&transcript);
+ if (!CBB_init(transcript.get(),
+ 2 * SSL3_RANDOM_SIZE + CBS_len(&parameter)) ||
+ !CBB_add_bytes(transcript.get(), ssl->s3->client_random,
+ SSL3_RANDOM_SIZE) ||
+ !CBB_add_bytes(transcript.get(), ssl->s3->server_random,
+ SSL3_RANDOM_SIZE) ||
+ !CBB_add_bytes(transcript.get(), CBS_data(&parameter),
+ CBS_len(&parameter)) ||
+ !CBB_finish(transcript.get(), &transcript_data, &transcript_len)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
- goto err;
+ return -1;
}
int sig_ok = ssl_public_key_verify(
ssl, CBS_data(&signature), CBS_len(&signature), signature_algorithm,
- hs->peer_pubkey, transcript_data, transcript_len);
+ hs->peer_pubkey.get(), transcript_data, transcript_len);
OPENSSL_free(transcript_data);
#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
@@ -1364,7 +1356,7 @@ static int ssl3_get_server_key_exchange(SSL_HANDSHAKE *hs) {
/* bad signature */
OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_SIGNATURE);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECRYPT_ERROR);
- goto err;
+ return -1;
}
} else {
/* PSK ciphers are the only supported certificate-less ciphers. */
@@ -1373,15 +1365,10 @@ static int ssl3_get_server_key_exchange(SSL_HANDSHAKE *hs) {
if (CBS_len(&server_key_exchange) > 0) {
OPENSSL_PUT_ERROR(SSL, SSL_R_EXTRA_DATA_IN_MESSAGE);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
- goto err;
+ return -1;
}
}
return 1;
-
-err:
- EC_POINT_free(srvr_ecpoint);
- EC_KEY_free(ecdh);
- return -1;
}
static int ssl3_get_certificate_request(SSL_HANDSHAKE *hs) {
@@ -1395,7 +1382,7 @@ static int ssl3_get_certificate_request(SSL_HANDSHAKE *hs) {
ssl->s3->tmp.reuse_message = 1;
/* If we get here we don't need the handshake buffer as we won't be doing
* client auth. */
- SSL_TRANSCRIPT_free_buffer(&hs->transcript);
+ hs->transcript.FreeBuffer();
return 1;
}
@@ -1432,23 +1419,21 @@ static int ssl3_get_certificate_request(SSL_HANDSHAKE *hs) {
}
uint8_t alert = SSL_AD_DECODE_ERROR;
- STACK_OF(CRYPTO_BUFFER) *ca_names =
+ UniquePtr<STACK_OF(CRYPTO_BUFFER)> ca_names =
ssl_parse_client_CA_list(ssl, &alert, &cbs);
- if (ca_names == NULL) {
+ if (!ca_names) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
return -1;
}
if (CBS_len(&cbs) != 0) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
- sk_CRYPTO_BUFFER_pop_free(ca_names, CRYPTO_BUFFER_free);
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
return -1;
}
hs->cert_request = 1;
- sk_CRYPTO_BUFFER_pop_free(hs->ca_names, CRYPTO_BUFFER_free);
- hs->ca_names = ca_names;
+ hs->ca_names = std::move(ca_names);
ssl->ctx->x509_method->hs_flush_cached_ca_names(hs);
return 1;
}
@@ -1493,7 +1478,7 @@ static int ssl3_send_client_certificate(SSL_HANDSHAKE *hs) {
if (!ssl_has_certificate(ssl)) {
/* Without a client certificate, the handshake buffer may be released. */
- SSL_TRANSCRIPT_free_buffer(&hs->transcript);
+ hs->transcript.FreeBuffer();
/* In SSL 3.0, the Certificate message is replaced with a warning alert. */
if (ssl->version == SSL3_VERSION) {
@@ -1517,7 +1502,7 @@ static_assert(sizeof(size_t) >= sizeof(unsigned),
static int ssl3_send_client_key_exchange(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
- bssl::ScopedCBB cbb;
+ ScopedCBB cbb;
CBB body;
if (!ssl->method->init_message(ssl, cbb.get(), &body,
SSL3_MT_CLIENT_KEY_EXCHANGE)) {
@@ -1541,8 +1526,8 @@ static int ssl3_send_client_key_exchange(SSL_HANDSHAKE *hs) {
char identity[PSK_MAX_IDENTITY_LEN + 1];
OPENSSL_memset(identity, 0, sizeof(identity));
psk_len =
- ssl->psk_client_callback(ssl, hs->peer_psk_identity_hint, identity,
- sizeof(identity), psk, sizeof(psk));
+ ssl->psk_client_callback(ssl, hs->peer_psk_identity_hint.get(),
+ identity, sizeof(identity), psk, sizeof(psk));
if (psk_len == 0) {
OPENSSL_PUT_ERROR(SSL, SSL_R_PSK_IDENTITY_NOT_FOUND);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
@@ -1576,7 +1561,7 @@ static int ssl3_send_client_key_exchange(SSL_HANDSHAKE *hs) {
goto err;
}
- RSA *rsa = EVP_PKEY_get0_RSA(hs->peer_pubkey);
+ RSA *rsa = EVP_PKEY_get0_RSA(hs->peer_pubkey.get());
if (rsa == NULL) {
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
goto err;
@@ -1615,8 +1600,8 @@ static int ssl3_send_client_key_exchange(SSL_HANDSHAKE *hs) {
/* Compute the premaster. */
uint8_t alert = SSL_AD_DECODE_ERROR;
- if (!SSL_ECDH_CTX_accept(&hs->ecdh_ctx, &child, &pms, &pms_len, &alert,
- hs->peer_key, hs->peer_key_len)) {
+ if (!hs->key_share->Accept(&child, &pms, &pms_len, &alert, hs->peer_key,
+ hs->peer_key_len)) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
goto err;
}
@@ -1625,7 +1610,7 @@ static int ssl3_send_client_key_exchange(SSL_HANDSHAKE *hs) {
}
/* The key exchange state may now be discarded. */
- SSL_ECDH_CTX_cleanup(&hs->ecdh_ctx);
+ hs->key_share.reset();
OPENSSL_free(hs->peer_key);
hs->peer_key = NULL;
hs->peer_key_len = 0;
@@ -1648,18 +1633,17 @@ static int ssl3_send_client_key_exchange(SSL_HANDSHAKE *hs) {
/* For a PSK cipher suite, other_secret is combined with the pre-shared
* key. */
if (alg_a & SSL_aPSK) {
- CBB pms_cbb, child;
+ ScopedCBB pms_cbb;
+ CBB child;
uint8_t *new_pms;
size_t new_pms_len;
- CBB_zero(&pms_cbb);
- if (!CBB_init(&pms_cbb, 2 + psk_len + 2 + pms_len) ||
- !CBB_add_u16_length_prefixed(&pms_cbb, &child) ||
+ if (!CBB_init(pms_cbb.get(), 2 + psk_len + 2 + pms_len) ||
+ !CBB_add_u16_length_prefixed(pms_cbb.get(), &child) ||
!CBB_add_bytes(&child, pms, pms_len) ||
- !CBB_add_u16_length_prefixed(&pms_cbb, &child) ||
+ !CBB_add_u16_length_prefixed(pms_cbb.get(), &child) ||
!CBB_add_bytes(&child, psk, psk_len) ||
- !CBB_finish(&pms_cbb, &new_pms, &new_pms_len)) {
- CBB_cleanup(&pms_cbb);
+ !CBB_finish(pms_cbb.get(), &new_pms, &new_pms_len)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
goto err;
}
@@ -1698,7 +1682,7 @@ static int ssl3_send_cert_verify(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
assert(ssl_has_private_key(ssl));
- bssl::ScopedCBB cbb;
+ ScopedCBB cbb;
CBB body, child;
if (!ssl->method->init_message(ssl, cbb.get(), &body,
SSL3_MT_CERTIFICATE_VERIFY)) {
@@ -1718,7 +1702,7 @@ static int ssl3_send_cert_verify(SSL_HANDSHAKE *hs) {
}
/* Set aside space for the signature. */
- const size_t max_sig_len = EVP_PKEY_size(hs->local_pubkey);
+ const size_t max_sig_len = EVP_PKEY_size(hs->local_pubkey.get());
uint8_t *ptr;
if (!CBB_add_u16_length_prefixed(&body, &child) ||
!CBB_reserve(&child, &ptr, max_sig_len)) {
@@ -1736,25 +1720,21 @@ static int ssl3_send_cert_verify(SSL_HANDSHAKE *hs) {
uint8_t digest[EVP_MAX_MD_SIZE];
size_t digest_len;
- if (!SSL_TRANSCRIPT_ssl3_cert_verify_hash(&hs->transcript, digest,
- &digest_len, hs->new_session,
- signature_algorithm)) {
+ if (!hs->transcript.GetSSL3CertVerifyHash(
+ digest, &digest_len, hs->new_session.get(), signature_algorithm)) {
return -1;
}
- EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new(ssl->cert->privatekey, NULL);
- int ok = pctx != NULL &&
- EVP_PKEY_sign_init(pctx) &&
- EVP_PKEY_sign(pctx, ptr, &sig_len, digest, digest_len);
- EVP_PKEY_CTX_free(pctx);
- if (!ok) {
+ UniquePtr<EVP_PKEY_CTX> pctx(EVP_PKEY_CTX_new(ssl->cert->privatekey, NULL));
+ if (!pctx ||
+ !EVP_PKEY_sign_init(pctx.get()) ||
+ !EVP_PKEY_sign(pctx.get(), ptr, &sig_len, digest, digest_len)) {
return -1;
}
} else {
- switch (ssl_private_key_sign(hs, ptr, &sig_len, max_sig_len,
- signature_algorithm,
- (const uint8_t *)hs->transcript.buffer->data,
- hs->transcript.buffer->length)) {
+ switch (ssl_private_key_sign(
+ hs, ptr, &sig_len, max_sig_len, signature_algorithm,
+ hs->transcript.buffer_data(), hs->transcript.buffer_len())) {
case ssl_private_key_success:
break;
case ssl_private_key_failure:
@@ -1771,7 +1751,7 @@ static int ssl3_send_cert_verify(SSL_HANDSHAKE *hs) {
}
/* The handshake buffer is no longer necessary. */
- SSL_TRANSCRIPT_free_buffer(&hs->transcript);
+ hs->transcript.FreeBuffer();
return 1;
}
@@ -1780,16 +1760,16 @@ static int ssl3_send_next_proto(SSL_HANDSHAKE *hs) {
static const uint8_t kZero[32] = {0};
size_t padding_len = 32 - ((ssl->s3->next_proto_negotiated_len + 2) % 32);
- CBB cbb, body, child;
- if (!ssl->method->init_message(ssl, &cbb, &body, SSL3_MT_NEXT_PROTO) ||
+ ScopedCBB cbb;
+ CBB body, child;
+ if (!ssl->method->init_message(ssl, cbb.get(), &body, SSL3_MT_NEXT_PROTO) ||
!CBB_add_u8_length_prefixed(&body, &child) ||
!CBB_add_bytes(&child, ssl->s3->next_proto_negotiated,
ssl->s3->next_proto_negotiated_len) ||
!CBB_add_u8_length_prefixed(&body, &child) ||
!CBB_add_bytes(&child, kZero, padding_len) ||
- !ssl_add_message_cbb(ssl, &cbb)) {
+ !ssl_add_message_cbb(ssl, cbb.get())) {
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
- CBB_cleanup(&cbb);
return -1;
}
@@ -1807,12 +1787,12 @@ static int ssl3_send_channel_id(SSL_HANDSHAKE *hs) {
return -1;
}
- CBB cbb, body;
- if (!ssl->method->init_message(ssl, &cbb, &body, SSL3_MT_CHANNEL_ID) ||
+ ScopedCBB cbb;
+ CBB body;
+ if (!ssl->method->init_message(ssl, cbb.get(), &body, SSL3_MT_CHANNEL_ID) ||
!tls1_write_channel_id(hs, &body) ||
- !ssl_add_message_cbb(ssl, &cbb)) {
+ !ssl_add_message_cbb(ssl, cbb.get())) {
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
- CBB_cleanup(&cbb);
return -1;
}
@@ -1850,18 +1830,20 @@ static int ssl3_get_new_session_ticket(SSL_HANDSHAKE *hs) {
return 1;
}
- int session_renewed = ssl->session != NULL;
- SSL_SESSION *session = hs->new_session;
- if (session_renewed) {
+ SSL_SESSION *session = hs->new_session.get();
+ UniquePtr<SSL_SESSION> renewed_session;
+ if (ssl->session != NULL) {
/* The server is sending a new ticket for an existing session. Sessions are
* immutable once established, so duplicate all but the ticket of the
* existing session. */
- session = SSL_SESSION_dup(ssl->session, SSL_SESSION_INCLUDE_NONAUTH);
- if (session == NULL) {
+ renewed_session =
+ SSL_SESSION_dup(ssl->session, SSL_SESSION_INCLUDE_NONAUTH);
+ if (!renewed_session) {
/* This should never happen. */
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
- goto err;
+ return -1;
}
+ session = renewed_session.get();
}
/* |tlsext_tick_lifetime_hint| is measured from when the ticket was issued. */
@@ -1869,7 +1851,7 @@ static int ssl3_get_new_session_ticket(SSL_HANDSHAKE *hs) {
if (!CBS_stow(&ticket, &session->tlsext_tick, &session->tlsext_ticklen)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- goto err;
+ return -1;
}
session->tlsext_tick_lifetime_hint = tlsext_tick_lifetime_hint;
@@ -1879,20 +1861,16 @@ static int ssl3_get_new_session_ticket(SSL_HANDSHAKE *hs) {
if (!EVP_Digest(CBS_data(&ticket), CBS_len(&ticket),
session->session_id, &session->session_id_length,
EVP_sha256(), NULL)) {
- goto err;
+ return -1;
}
- if (session_renewed) {
+ if (renewed_session) {
session->not_resumable = 0;
SSL_SESSION_free(ssl->session);
- ssl->session = session;
+ ssl->session = renewed_session.release();
}
return 1;
-
-err:
- if (session_renewed) {
- SSL_SESSION_free(session);
- }
- return -1;
}
+
+} // namespace bssl
diff --git a/src/ssl/handshake_server.cc b/src/ssl/handshake_server.cc
index ee5358c4..38fbef4b 100644
--- a/src/ssl/handshake_server.cc
+++ b/src/ssl/handshake_server.cc
@@ -170,6 +170,8 @@
#include "../crypto/internal.h"
+namespace bssl {
+
static int ssl3_process_client_hello(SSL_HANDSHAKE *hs);
static int ssl3_select_certificate(SSL_HANDSHAKE *hs);
static int ssl3_select_parameters(SSL_HANDSHAKE *hs);
@@ -282,6 +284,23 @@ int ssl3_accept(SSL_HANDSHAKE *hs) {
goto end;
}
}
+ hs->state = SSL3_ST_VERIFY_CLIENT_CERT;
+ break;
+
+ case SSL3_ST_VERIFY_CLIENT_CERT:
+ if (sk_CRYPTO_BUFFER_num(hs->new_session->certs) > 0) {
+ switch (ssl_verify_peer_cert(hs)) {
+ case ssl_verify_ok:
+ break;
+ case ssl_verify_invalid:
+ ret = -1;
+ goto end;
+ case ssl_verify_retry:
+ ssl->rwstate = SSL_CERTIFICATE_VERIFY;
+ ret = -1;
+ goto end;
+ }
+ }
hs->state = SSL3_ST_SR_KEY_EXCH_A;
break;
@@ -411,7 +430,7 @@ int ssl3_accept(SSL_HANDSHAKE *hs) {
ssl->retain_only_sha256_of_client_certs) {
sk_CRYPTO_BUFFER_pop_free(hs->new_session->certs, CRYPTO_BUFFER_free);
hs->new_session->certs = NULL;
- ssl->ctx->x509_method->session_clear(hs->new_session);
+ ssl->ctx->x509_method->session_clear(hs->new_session.get());
}
SSL_SESSION_free(ssl->s3->established_session);
@@ -419,9 +438,8 @@ int ssl3_accept(SSL_HANDSHAKE *hs) {
SSL_SESSION_up_ref(ssl->session);
ssl->s3->established_session = ssl->session;
} else {
- ssl->s3->established_session = hs->new_session;
+ ssl->s3->established_session = hs->new_session.release();
ssl->s3->established_session->not_resumable = 0;
- hs->new_session = NULL;
}
ssl->s3->initial_handshake_complete = 1;
@@ -586,8 +604,8 @@ static void ssl_get_compatible_server_ciphers(SSL_HANDSHAKE *hs,
uint32_t mask_a = 0;
if (ssl_has_certificate(ssl)) {
- mask_a |= ssl_cipher_auth_mask_for_key(hs->local_pubkey);
- if (EVP_PKEY_id(hs->local_pubkey) == EVP_PKEY_RSA) {
+ mask_a |= ssl_cipher_auth_mask_for_key(hs->local_pubkey.get());
+ if (EVP_PKEY_id(hs->local_pubkey.get()) == EVP_PKEY_RSA) {
mask_k |= SSL_kRSA;
}
}
@@ -808,12 +826,12 @@ static int ssl3_select_parameters(SSL_HANDSHAKE *hs) {
/* Determine whether we are doing session resumption. */
int tickets_supported = 0, renew_ticket = 0;
- /* TODO(davidben): Switch |ssl_get_prev_session| to take a |bssl::UniquePtr|
+ /* TODO(davidben): Switch |ssl_get_prev_session| to take a |UniquePtr|
* output and simplify this. */
SSL_SESSION *session_raw = nullptr;
auto session_ret = ssl_get_prev_session(ssl, &session_raw, &tickets_supported,
&renew_ticket, &client_hello);
- bssl::UniquePtr<SSL_SESSION> session(session_raw);
+ UniquePtr<SSL_SESSION> session(session_raw);
switch (session_ret) {
case ssl_session_success:
break;
@@ -876,7 +894,7 @@ static int ssl3_select_parameters(SSL_HANDSHAKE *hs) {
/* On new sessions, stash the SNI value in the session. */
if (hs->hostname != NULL) {
OPENSSL_free(hs->new_session->tlsext_hostname);
- hs->new_session->tlsext_hostname = BUF_strdup(hs->hostname);
+ hs->new_session->tlsext_hostname = BUF_strdup(hs->hostname.get());
if (hs->new_session->tlsext_hostname == NULL) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
return -1;
@@ -912,8 +930,8 @@ static int ssl3_select_parameters(SSL_HANDSHAKE *hs) {
/* Now that all parameters are known, initialize the handshake hash and hash
* the ClientHello. */
- if (!SSL_TRANSCRIPT_init_hash(&hs->transcript, ssl3_protocol_version(ssl),
- hs->new_cipher->algorithm_prf) ||
+ if (!hs->transcript.InitHash(ssl3_protocol_version(ssl),
+ hs->new_cipher->algorithm_prf) ||
!ssl_hash_current_message(hs)) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
return -1;
@@ -921,7 +939,7 @@ static int ssl3_select_parameters(SSL_HANDSHAKE *hs) {
/* Release the handshake buffer if client authentication isn't required. */
if (!hs->cert_request) {
- SSL_TRANSCRIPT_free_buffer(&hs->transcript);
+ hs->transcript.FreeBuffer();
}
return 1;
@@ -958,13 +976,14 @@ static int ssl3_send_server_hello(SSL_HANDSHAKE *hs) {
/* TODO(davidben): Implement the TLS 1.1 and 1.2 downgrade sentinels once TLS
* 1.3 is finalized and we are not implementing a draft version. */
- const SSL_SESSION *session = hs->new_session;
+ const SSL_SESSION *session = hs->new_session.get();
if (ssl->session != NULL) {
session = ssl->session;
}
- CBB cbb, body, session_id;
- if (!ssl->method->init_message(ssl, &cbb, &body, SSL3_MT_SERVER_HELLO) ||
+ ScopedCBB cbb;
+ CBB body, session_id;
+ if (!ssl->method->init_message(ssl, cbb.get(), &body, SSL3_MT_SERVER_HELLO) ||
!CBB_add_u16(&body, ssl->version) ||
!CBB_add_bytes(&body, ssl->s3->server_random, SSL3_RANDOM_SIZE) ||
!CBB_add_u8_length_prefixed(&body, &session_id) ||
@@ -973,9 +992,8 @@ static int ssl3_send_server_hello(SSL_HANDSHAKE *hs) {
!CBB_add_u16(&body, ssl_cipher_get_value(hs->new_cipher)) ||
!CBB_add_u8(&body, 0 /* no compression */) ||
!ssl_add_serverhello_tlsext(hs, &body) ||
- !ssl_add_message_cbb(ssl, &cbb)) {
+ !ssl_add_message_cbb(ssl, cbb.get())) {
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
- CBB_cleanup(&cbb);
return -1;
}
@@ -984,7 +1002,7 @@ static int ssl3_send_server_hello(SSL_HANDSHAKE *hs) {
static int ssl3_send_server_certificate(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
- bssl::ScopedCBB cbb;
+ ScopedCBB cbb;
if (ssl_cipher_uses_certificate_auth(hs->new_cipher)) {
if (!ssl_has_certificate(ssl)) {
@@ -1049,11 +1067,12 @@ static int ssl3_send_server_certificate(SSL_HANDSHAKE *hs) {
hs->new_session->group_id = group_id;
/* Set up ECDH, generate a key, and emit the public half. */
- if (!SSL_ECDH_CTX_init(&hs->ecdh_ctx, group_id) ||
+ hs->key_share = SSLKeyShare::Create(group_id);
+ if (!hs->key_share ||
!CBB_add_u8(cbb.get(), NAMED_CURVE_TYPE) ||
!CBB_add_u16(cbb.get(), group_id) ||
!CBB_add_u8_length_prefixed(cbb.get(), &child) ||
- !SSL_ECDH_CTX_offer(&hs->ecdh_ctx, &child)) {
+ !hs->key_share->Offer(&child)) {
return -1;
}
} else {
@@ -1070,42 +1089,43 @@ static int ssl3_send_server_certificate(SSL_HANDSHAKE *hs) {
static int ssl3_send_server_key_exchange(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
- CBB cbb, body, child;
- if (!ssl->method->init_message(ssl, &cbb, &body,
+ ScopedCBB cbb;
+ CBB body, child;
+ if (!ssl->method->init_message(ssl, cbb.get(), &body,
SSL3_MT_SERVER_KEY_EXCHANGE) ||
/* |hs->server_params| contains a prefix for signing. */
hs->server_params_len < 2 * SSL3_RANDOM_SIZE ||
!CBB_add_bytes(&body, hs->server_params + 2 * SSL3_RANDOM_SIZE,
hs->server_params_len - 2 * SSL3_RANDOM_SIZE)) {
- goto err;
+ return -1;
}
/* Add a signature. */
if (ssl_cipher_uses_certificate_auth(hs->new_cipher)) {
if (!ssl_has_private_key(ssl)) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
- goto err;
+ return -1;
}
/* Determine the signature algorithm. */
uint16_t signature_algorithm;
if (!tls1_choose_signature_algorithm(hs, &signature_algorithm)) {
- goto err;
+ return -1;
}
if (ssl3_protocol_version(ssl) >= TLS1_2_VERSION) {
if (!CBB_add_u16(&body, signature_algorithm)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
- goto err;
+ return -1;
}
}
/* Add space for the signature. */
- const size_t max_sig_len = EVP_PKEY_size(hs->local_pubkey);
+ const size_t max_sig_len = EVP_PKEY_size(hs->local_pubkey.get());
uint8_t *ptr;
if (!CBB_add_u16_length_prefixed(&body, &child) ||
!CBB_reserve(&child, &ptr, max_sig_len)) {
- goto err;
+ return -1;
}
size_t sig_len;
@@ -1114,19 +1134,19 @@ static int ssl3_send_server_key_exchange(SSL_HANDSHAKE *hs) {
hs->server_params_len)) {
case ssl_private_key_success:
if (!CBB_did_write(&child, sig_len)) {
- goto err;
+ return -1;
}
break;
case ssl_private_key_failure:
- goto err;
+ return -1;
case ssl_private_key_retry:
ssl->rwstate = SSL_PRIVATE_KEY_OPERATION;
- goto err;
+ return -1;
}
}
- if (!ssl_add_message_cbb(ssl, &cbb)) {
- goto err;
+ if (!ssl_add_message_cbb(ssl, cbb.get())) {
+ return -1;
}
OPENSSL_free(hs->server_params);
@@ -1134,19 +1154,16 @@ static int ssl3_send_server_key_exchange(SSL_HANDSHAKE *hs) {
hs->server_params_len = 0;
return 1;
-
-err:
- CBB_cleanup(&cbb);
- return -1;
}
static int ssl3_send_server_hello_done(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
- CBB cbb, body;
+ ScopedCBB cbb;
+ CBB body;
if (hs->cert_request) {
CBB cert_types, sigalgs_cbb;
- if (!ssl->method->init_message(ssl, &cbb, &body,
+ if (!ssl->method->init_message(ssl, cbb.get(), &body,
SSL3_MT_CERTIFICATE_REQUEST) ||
!CBB_add_u8_length_prefixed(&body, &cert_types) ||
!CBB_add_u8(&cert_types, SSL3_CT_RSA_SIGN) ||
@@ -1156,22 +1173,20 @@ static int ssl3_send_server_hello_done(SSL_HANDSHAKE *hs) {
(!CBB_add_u16_length_prefixed(&body, &sigalgs_cbb) ||
!tls12_add_verify_sigalgs(ssl, &sigalgs_cbb))) ||
!ssl_add_client_CA_list(ssl, &body) ||
- !ssl_add_message_cbb(ssl, &cbb)) {
- goto err;
+ !ssl_add_message_cbb(ssl, cbb.get())) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+ return -1;
}
}
- if (!ssl->method->init_message(ssl, &cbb, &body, SSL3_MT_SERVER_HELLO_DONE) ||
- !ssl_add_message_cbb(ssl, &cbb)) {
- goto err;
+ if (!ssl->method->init_message(ssl, cbb.get(), &body,
+ SSL3_MT_SERVER_HELLO_DONE) ||
+ !ssl_add_message_cbb(ssl, cbb.get())) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+ return -1;
}
return 1;
-
-err:
- OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
- CBB_cleanup(&cbb);
- return -1;
}
static int ssl3_get_client_certificate(SSL_HANDSHAKE *hs) {
@@ -1214,21 +1229,22 @@ static int ssl3_get_client_certificate(SSL_HANDSHAKE *hs) {
CBS_init(&certificate_msg, ssl->init_msg, ssl->init_num);
sk_CRYPTO_BUFFER_pop_free(hs->new_session->certs, CRYPTO_BUFFER_free);
- EVP_PKEY_free(hs->peer_pubkey);
- hs->peer_pubkey = NULL;
+ hs->peer_pubkey.reset();
uint8_t alert = SSL_AD_DECODE_ERROR;
- hs->new_session->certs = ssl_parse_cert_chain(
- &alert, &hs->peer_pubkey,
- ssl->retain_only_sha256_of_client_certs ? hs->new_session->peer_sha256
- : NULL,
- &certificate_msg, ssl->ctx->pool);
+ hs->new_session->certs =
+ ssl_parse_cert_chain(&alert, &hs->peer_pubkey,
+ ssl->retain_only_sha256_of_client_certs
+ ? hs->new_session->peer_sha256
+ : NULL,
+ &certificate_msg, ssl->ctx->pool)
+ .release();
if (hs->new_session->certs == NULL) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
return -1;
}
if (CBS_len(&certificate_msg) != 0 ||
- !ssl->ctx->x509_method->session_cache_objects(hs->new_session)) {
+ !ssl->ctx->x509_method->session_cache_objects(hs->new_session.get())) {
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
return -1;
@@ -1236,7 +1252,7 @@ static int ssl3_get_client_certificate(SSL_HANDSHAKE *hs) {
if (sk_CRYPTO_BUFFER_num(hs->new_session->certs) == 0) {
/* No client certificate so the handshake buffer may be discarded. */
- SSL_TRANSCRIPT_free_buffer(&hs->transcript);
+ hs->transcript.FreeBuffer();
/* In SSL 3.0, sending no certificate is signaled by omitting the
* Certificate message. */
@@ -1264,10 +1280,6 @@ static int ssl3_get_client_certificate(SSL_HANDSHAKE *hs) {
hs->new_session->peer_sha256_valid = 1;
}
- if (!ssl->ctx->x509_method->session_verify_cert_chain(hs->new_session, ssl)) {
- return -1;
- }
-
return 1;
}
@@ -1337,7 +1349,7 @@ static int ssl3_get_client_key_exchange(SSL_HANDSHAKE *hs) {
}
/* Allocate a buffer large enough for an RSA decryption. */
- const size_t rsa_size = EVP_PKEY_size(hs->local_pubkey);
+ const size_t rsa_size = EVP_PKEY_size(hs->local_pubkey.get());
decrypt_buf = (uint8_t *)OPENSSL_malloc(rsa_size);
if (decrypt_buf == NULL) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
@@ -1423,15 +1435,14 @@ static int ssl3_get_client_key_exchange(SSL_HANDSHAKE *hs) {
/* Compute the premaster. */
uint8_t alert = SSL_AD_DECODE_ERROR;
- if (!SSL_ECDH_CTX_finish(&hs->ecdh_ctx, &premaster_secret,
- &premaster_secret_len, &alert, CBS_data(&peer_key),
- CBS_len(&peer_key))) {
+ if (!hs->key_share->Finish(&premaster_secret, &premaster_secret_len, &alert,
+ CBS_data(&peer_key), CBS_len(&peer_key))) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
goto err;
}
/* The key exchange state may now be discarded. */
- SSL_ECDH_CTX_cleanup(&hs->ecdh_ctx);
+ hs->key_share.reset();
} else if (!(alg_k & SSL_kPSK)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
@@ -1474,18 +1485,18 @@ static int ssl3_get_client_key_exchange(SSL_HANDSHAKE *hs) {
OPENSSL_memset(premaster_secret, 0, premaster_secret_len);
}
- CBB new_premaster, child;
+ ScopedCBB new_premaster;
+ CBB child;
uint8_t *new_data;
size_t new_len;
- CBB_zero(&new_premaster);
- if (!CBB_init(&new_premaster, 2 + psk_len + 2 + premaster_secret_len) ||
- !CBB_add_u16_length_prefixed(&new_premaster, &child) ||
+ if (!CBB_init(new_premaster.get(),
+ 2 + psk_len + 2 + premaster_secret_len) ||
+ !CBB_add_u16_length_prefixed(new_premaster.get(), &child) ||
!CBB_add_bytes(&child, premaster_secret, premaster_secret_len) ||
- !CBB_add_u16_length_prefixed(&new_premaster, &child) ||
+ !CBB_add_u16_length_prefixed(new_premaster.get(), &child) ||
!CBB_add_bytes(&child, psk, psk_len) ||
- !CBB_finish(&new_premaster, &new_data, &new_len)) {
+ !CBB_finish(new_premaster.get(), &new_data, &new_len)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- CBB_cleanup(&new_premaster);
goto err;
}
@@ -1528,8 +1539,8 @@ static int ssl3_get_cert_verify(SSL_HANDSHAKE *hs) {
/* Only RSA and ECDSA client certificates are supported, so a
* CertificateVerify is required if and only if there's a client certificate.
* */
- if (hs->peer_pubkey == NULL) {
- SSL_TRANSCRIPT_free_buffer(&hs->transcript);
+ if (!hs->peer_pubkey) {
+ hs->transcript.FreeBuffer();
return 1;
}
@@ -1559,7 +1570,7 @@ static int ssl3_get_cert_verify(SSL_HANDSHAKE *hs) {
}
hs->new_session->peer_signature_algorithm = signature_algorithm;
} else if (!tls1_get_legacy_signature_algorithm(&signature_algorithm,
- hs->peer_pubkey)) {
+ hs->peer_pubkey.get())) {
OPENSSL_PUT_ERROR(SSL, SSL_R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNSUPPORTED_CERTIFICATE);
return -1;
@@ -1579,23 +1590,22 @@ static int ssl3_get_cert_verify(SSL_HANDSHAKE *hs) {
if (ssl3_protocol_version(ssl) == SSL3_VERSION) {
uint8_t digest[EVP_MAX_MD_SIZE];
size_t digest_len;
- if (!SSL_TRANSCRIPT_ssl3_cert_verify_hash(&hs->transcript, digest,
- &digest_len, hs->new_session,
- signature_algorithm)) {
+ if (!hs->transcript.GetSSL3CertVerifyHash(
+ digest, &digest_len, hs->new_session.get(), signature_algorithm)) {
return -1;
}
- EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new(hs->peer_pubkey, NULL);
- sig_ok = pctx != NULL &&
- EVP_PKEY_verify_init(pctx) &&
- EVP_PKEY_verify(pctx, CBS_data(&signature), CBS_len(&signature),
- digest, digest_len);
- EVP_PKEY_CTX_free(pctx);
+ UniquePtr<EVP_PKEY_CTX> pctx(
+ EVP_PKEY_CTX_new(hs->peer_pubkey.get(), nullptr));
+ sig_ok = pctx &&
+ EVP_PKEY_verify_init(pctx.get()) &&
+ EVP_PKEY_verify(pctx.get(), CBS_data(&signature),
+ CBS_len(&signature), digest, digest_len);
} else {
sig_ok = ssl_public_key_verify(
ssl, CBS_data(&signature), CBS_len(&signature), signature_algorithm,
- hs->peer_pubkey, (const uint8_t *)hs->transcript.buffer->data,
- hs->transcript.buffer->length);
+ hs->peer_pubkey.get(), hs->transcript.buffer_data(),
+ hs->transcript.buffer_len());
}
#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
@@ -1610,7 +1620,7 @@ static int ssl3_get_cert_verify(SSL_HANDSHAKE *hs) {
/* The handshake buffer is no longer necessary, and we may hash the current
* message.*/
- SSL_TRANSCRIPT_free_buffer(&hs->transcript);
+ hs->transcript.FreeBuffer();
if (!ssl_hash_current_message(hs)) {
return -1;
}
@@ -1671,33 +1681,31 @@ static int ssl3_send_server_finished(SSL_HANDSHAKE *hs) {
if (hs->ticket_expected) {
const SSL_SESSION *session;
- SSL_SESSION *session_copy = NULL;
+ UniquePtr<SSL_SESSION> session_copy;
if (ssl->session == NULL) {
/* Fix the timeout to measure from the ticket issuance time. */
- ssl_session_rebase_time(ssl, hs->new_session);
- session = hs->new_session;
+ ssl_session_rebase_time(ssl, hs->new_session.get());
+ session = hs->new_session.get();
} else {
/* We are renewing an existing session. Duplicate the session to adjust
* the timeout. */
session_copy = SSL_SESSION_dup(ssl->session, SSL_SESSION_INCLUDE_NONAUTH);
- if (session_copy == NULL) {
+ if (!session_copy) {
return -1;
}
- ssl_session_rebase_time(ssl, session_copy);
- session = session_copy;
+ ssl_session_rebase_time(ssl, session_copy.get());
+ session = session_copy.get();
}
- CBB cbb, body, ticket;
- int ok = ssl->method->init_message(ssl, &cbb, &body,
- SSL3_MT_NEW_SESSION_TICKET) &&
- CBB_add_u32(&body, session->timeout) &&
- CBB_add_u16_length_prefixed(&body, &ticket) &&
- ssl_encrypt_ticket(ssl, &ticket, session) &&
- ssl_add_message_cbb(ssl, &cbb);
- SSL_SESSION_free(session_copy);
- CBB_cleanup(&cbb);
- if (!ok) {
+ ScopedCBB cbb;
+ CBB body, ticket;
+ if (!ssl->method->init_message(ssl, cbb.get(), &body,
+ SSL3_MT_NEW_SESSION_TICKET) ||
+ !CBB_add_u32(&body, session->timeout) ||
+ !CBB_add_u16_length_prefixed(&body, &ticket) ||
+ !ssl_encrypt_ticket(ssl, &ticket, session) ||
+ !ssl_add_message_cbb(ssl, cbb.get())) {
return -1;
}
}
@@ -1709,3 +1717,5 @@ static int ssl3_send_server_finished(SSL_HANDSHAKE *hs) {
return ssl3_send_finished(hs);
}
+
+} // namespace bssl
diff --git a/src/ssl/internal.h b/src/ssl/internal.h
index 6b880701..fb02d35f 100644
--- a/src/ssl/internal.h
+++ b/src/ssl/internal.h
@@ -144,7 +144,12 @@
#include <openssl/base.h>
+#include <type_traits>
+#include <utility>
+
#include <openssl/aead.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
#include <openssl/ssl.h>
#include <openssl/stack.h>
@@ -158,12 +163,60 @@ OPENSSL_MSVC_PRAGMA(warning(pop))
#include <sys/time.h>
#endif
-#if defined(__cplusplus)
-extern "C" {
-#endif
+typedef struct cert_st CERT;
+
+namespace bssl {
+
+struct SSL_HANDSHAKE;
+
+/* C++ utilities. */
+
+/* New behaves like |new| but uses |OPENSSL_malloc| for memory allocation. It
+ * returns nullptr on allocation error. It only implements single-object
+ * allocation and not new T[n].
+ *
+ * Note: unlike |new|, this does not support non-public constructors. */
+template <typename T, typename... Args>
+T *New(Args &&... args) {
+ T *t = reinterpret_cast<T *>(OPENSSL_malloc(sizeof(T)));
+ if (t == nullptr) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+ return nullptr;
+ }
+ new (t) T(std::forward<Args>(args)...);
+ return t;
+}
+
+/* Delete behaves like |delete| but uses |OPENSSL_free| to release memory.
+ *
+ * Note: unlike |delete| this does not support non-public destructors. */
+template <typename T>
+void Delete(T *t) {
+ if (t != nullptr) {
+ t->~T();
+ OPENSSL_free(t);
+ }
+}
+
+/* Register all types with non-trivial destructors with |UniquePtr|. Types with
+ * trivial destructors may be C structs which require a |BORINGSSL_MAKE_DELETER|
+ * registration. */
+namespace internal {
+template <typename T>
+struct DeleterImpl<T, typename std::enable_if<
+ !std::is_trivially_destructible<T>::value>::type> {
+ static void Free(T *t) { Delete(t); }
+};
+}
+
+/* MakeUnique behaves like |std::make_unique| but returns nullptr on allocation
+ * error. */
+template <typename T, typename... Args>
+UniquePtr<T> MakeUnique(Args &&... args) {
+ return UniquePtr<T>(New<T>(std::forward<Args>(args)...));
+}
-typedef struct ssl_handshake_st SSL_HANDSHAKE;
/* Protocol versions.
*
@@ -312,74 +365,74 @@ size_t ssl_cipher_get_record_split_len(const SSL_CIPHER *cipher);
/* Transcript layer. */
-/* SSL_TRANSCRIPT maintains the handshake transcript as a combination of a
+/* SSLTranscript maintains the handshake transcript as a combination of a
* buffer and running hash. */
-typedef struct ssl_transcript_st {
- /* buffer, if non-NULL, contains the handshake transcript. */
- BUF_MEM *buffer;
+class SSLTranscript {
+ public:
+ SSLTranscript();
+ ~SSLTranscript();
+
+ /* Init initializes the handshake transcript. If called on an existing
+ * transcript, it resets the transcript and hash. It returns true on success
+ * and false on failure. */
+ bool Init();
+
+ /* InitHash initializes the handshake hash based on the PRF and contents of
+ * the handshake transcript. Subsequent calls to |Update| will update the
+ * rolling hash. It returns one on success and zero on failure. It is an error
+ * to call this function after the handshake buffer is released. */
+ bool InitHash(uint16_t version, int algorithm_prf);
+
+ const uint8_t *buffer_data() const {
+ return reinterpret_cast<const uint8_t *>(buffer_->data);
+ }
+ size_t buffer_len() const { return buffer_->length; }
+
+ /* FreeBuffer releases the handshake buffer. Subsequent calls to
+ * |Update| will not update the handshake buffer. */
+ void FreeBuffer();
+
+ /* DigestLen returns the length of the PRF hash. */
+ size_t DigestLen() const;
+
+ /* Digest returns the PRF hash. For TLS 1.1 and below, this is
+ * |EVP_md5_sha1|. */
+ const EVP_MD *Digest() const;
+
+ /* Update adds |in| to the handshake buffer and handshake hash, whichever is
+ * enabled. It returns true on success and false on failure. */
+ bool Update(const uint8_t *in, size_t in_len);
+
+ /* GetHash writes the handshake hash to |out| which must have room for at
+ * least |DigestLen| bytes. On success, it returns true and sets |*out_len| to
+ * the number of bytes written. Otherwise, it returns false. */
+ bool GetHash(uint8_t *out, size_t *out_len);
+
+ /* GetSSL3CertVerifyHash writes the SSL 3.0 CertificateVerify hash into the
+ * bytes pointed to by |out| and writes the number of bytes to
+ * |*out_len|. |out| must have room for |EVP_MAX_MD_SIZE| bytes. It returns
+ * one on success and zero on failure. */
+ bool GetSSL3CertVerifyHash(uint8_t *out, size_t *out_len,
+ const SSL_SESSION *session,
+ uint16_t signature_algorithm);
+
+ /* GetFinishedMAC computes the MAC for the Finished message into the bytes
+ * pointed by |out| and writes the number of bytes to |*out_len|. |out| must
+ * have room for |EVP_MAX_MD_SIZE| bytes. It returns true on success and false
+ * on failure. */
+ bool GetFinishedMAC(uint8_t *out, size_t *out_len, const SSL_SESSION *session,
+ bool from_server, uint16_t version);
+
+ private:
+ /* buffer_, if non-null, contains the handshake transcript. */
+ UniquePtr<BUF_MEM> buffer_;
/* hash, if initialized with an |EVP_MD|, maintains the handshake hash. For
* TLS 1.1 and below, it is the SHA-1 half. */
- EVP_MD_CTX hash;
+ ScopedEVP_MD_CTX hash_;
/* md5, if initialized with an |EVP_MD|, maintains the MD5 half of the
* handshake hash for TLS 1.1 and below. */
- EVP_MD_CTX md5;
-} SSL_TRANSCRIPT;
-
-/* SSL_TRANSCRIPT_init initializes the handshake transcript. If called on an
- * existing transcript, it resets the transcript and hash. It returns one on
- * success and zero on failure. */
-int SSL_TRANSCRIPT_init(SSL_TRANSCRIPT *transcript);
-
-/* SSL_TRANSCRIPT_init_hash initializes the handshake hash based on the PRF and
- * contents of the handshake transcript. Subsequent calls to
- * |SSL_TRANSCRIPT_update| will update the rolling hash. It returns one on
- * success and zero on failure. It is an error to call this function after the
- * handshake buffer is released. */
-int SSL_TRANSCRIPT_init_hash(SSL_TRANSCRIPT *transcript, uint16_t version,
- int algorithm_prf);
-
-/* SSL_TRANSCRIPT_cleanup cleans up the hash and transcript. */
-void SSL_TRANSCRIPT_cleanup(SSL_TRANSCRIPT *transcript);
-
-/* SSL_TRANSCRIPT_free_buffer releases the handshake buffer. Subsequent calls to
- * |SSL_TRANSCRIPT_update| will not update the handshake buffer. */
-void SSL_TRANSCRIPT_free_buffer(SSL_TRANSCRIPT *transcript);
-
-/* SSL_TRANSCRIPT_digest_len returns the length of the PRF hash. */
-size_t SSL_TRANSCRIPT_digest_len(const SSL_TRANSCRIPT *transcript);
-
-/* SSL_TRANSCRIPT_md returns the PRF hash. For TLS 1.1 and below, this is
- * |EVP_md5_sha1|. */
-const EVP_MD *SSL_TRANSCRIPT_md(const SSL_TRANSCRIPT *transcript);
-
-/* SSL_TRANSCRIPT_update adds |in| to the handshake buffer and handshake hash,
- * whichever is enabled. It returns one on success and zero on failure. */
-int SSL_TRANSCRIPT_update(SSL_TRANSCRIPT *transcript, const uint8_t *in,
- size_t in_len);
-
-/* SSL_TRANSCRIPT_get_hash writes the handshake hash to |out| which must have
- * room for at least |SSL_TRANSCRIPT_digest_len| bytes. On success, it returns
- * one and sets |*out_len| to the number of bytes written. Otherwise, it returns
- * zero. */
-int SSL_TRANSCRIPT_get_hash(const SSL_TRANSCRIPT *transcript, uint8_t *out,
- size_t *out_len);
-
-/* SSL_TRANSCRIPT_ssl3_cert_verify_hash writes the SSL 3.0 CertificateVerify
- * hash into the bytes pointed to by |out| and writes the number of bytes to
- * |*out_len|. |out| must have room for |EVP_MAX_MD_SIZE| bytes. It returns one
- * on success and zero on failure. */
-int SSL_TRANSCRIPT_ssl3_cert_verify_hash(SSL_TRANSCRIPT *transcript,
- uint8_t *out, size_t *out_len,
- const SSL_SESSION *session,
- int signature_algorithm);
-
-/* SSL_TRANSCRIPT_finish_mac computes the MAC for the Finished message into the
- * bytes pointed by |out| and writes the number of bytes to |*out_len|. |out|
- * must have room for |EVP_MAX_MD_SIZE| bytes. It returns one on success and
- * zero on failure. */
-int SSL_TRANSCRIPT_finish_mac(SSL_TRANSCRIPT *transcript, uint8_t *out,
- size_t *out_len, const SSL_SESSION *session,
- int from_server, uint16_t version);
+ ScopedEVP_MD_CTX md5_;
+};
/* tls1_prf computes the PRF function for |ssl|. It writes |out_len| bytes to
* |out|, using |secret| as the secret and |label| as the label. |seed1| and
@@ -393,123 +446,131 @@ int tls1_prf(const EVP_MD *digest, uint8_t *out, size_t out_len,
/* Encryption layer. */
-/* SSL_AEAD_CTX contains information about an AEAD that is being used to encrypt
- * an SSL connection. */
-typedef struct ssl_aead_ctx_st {
- const SSL_CIPHER *cipher;
- EVP_AEAD_CTX ctx;
- /* fixed_nonce contains any bytes of the nonce that are fixed for all
+/* SSLAEADContext contains information about an AEAD that is being used to
+ * encrypt an SSL connection. */
+class SSLAEADContext {
+ public:
+ SSLAEADContext(uint16_t version, const SSL_CIPHER *cipher);
+ ~SSLAEADContext();
+ SSLAEADContext(const SSLAEADContext &&) = delete;
+ SSLAEADContext &operator=(const SSLAEADContext &&) = delete;
+
+ /* CreateNullCipher creates an |SSLAEADContext| for the null cipher. */
+ static UniquePtr<SSLAEADContext> CreateNullCipher();
+
+ /* Create creates an |SSLAEADContext| using the supplied key material. It
+ * returns nullptr on error. Only one of |Open| or |Seal| may be used with the
+ * resulting object, depending on |direction|. |version| is the normalized
+ * protocol version, so DTLS 1.0 is represented as 0x0301, not 0xffef. */
+ static UniquePtr<SSLAEADContext> Create(
+ enum evp_aead_direction_t direction, uint16_t version, int is_dtls,
+ const SSL_CIPHER *cipher, const uint8_t *enc_key, size_t enc_key_len,
+ const uint8_t *mac_key, size_t mac_key_len, const uint8_t *fixed_iv,
+ size_t fixed_iv_len);
+
+ uint16_t version() const { return version_; }
+ const SSL_CIPHER *cipher() const { return cipher_; }
+
+ /* is_null_cipher returns true if this is the null cipher. */
+ bool is_null_cipher() const { return !cipher_; }
+
+ /* ExplicitNonceLen returns the length of the explicit nonce. */
+ size_t ExplicitNonceLen() const;
+
+ /* MaxOverhead returns the maximum overhead of calling |Seal|. */
+ size_t MaxOverhead() const;
+
+ /* MaxSuffixLen returns the maximum suffix length written by |SealScatter|.
+ * |extra_in_len| should equal the argument of the same name passed to
+ * |SealScatter|. */
+ size_t MaxSuffixLen(size_t extra_in_len) const;
+
+ /* Open authenticates and decrypts |in_len| bytes from |in| in-place. On
+ * success, it sets |*out| to the plaintext in |in| and returns true.
+ * Otherwise, it returns false. The output will always be |ExplicitNonceLen|
+ * bytes ahead of |in|. */
+ bool Open(CBS *out, uint8_t type, uint16_t wire_version,
+ const uint8_t seqnum[8], uint8_t *in, size_t in_len);
+
+ /* Seal encrypts and authenticates |in_len| bytes from |in| and writes the
+ * result to |out|. It returns true on success and false on error.
+ *
+ * If |in| and |out| alias then |out| + |ExplicitNonceLen| must be == |in|. */
+ bool Seal(uint8_t *out, size_t *out_len, size_t max_out, uint8_t type,
+ uint16_t wire_version, const uint8_t seqnum[8], const uint8_t *in,
+ size_t in_len);
+
+ /* SealScatter encrypts and authenticates |in_len| bytes from |in| and splits
+ * the result between |out_prefix|, |out| and |out_suffix|. It returns one on
+ * success and zero on error.
+ *
+ * On successful return, exactly |ExplicitNonceLen| bytes are written to
+ * |out_prefix|, |in_len| bytes to |out|, and up to |MaxSuffixLen| bytes to
+ * |out_suffix|. |*out_suffix_len| is set to the actual number of bytes
+ * written to |out_suffix|.
+ *
+ * |extra_in| may point to an additional plaintext buffer. If present,
+ * |extra_in_len| additional bytes are encrypted and authenticated, and the
+ * ciphertext is written to the beginning of |out_suffix|. |MaxSuffixLen|
+ * may be used to size |out_suffix| accordingly.
+ *
+ * If |in| and |out| alias then |out| must be == |in|. Other arguments may not
+ * alias anything. */
+ bool SealScatter(uint8_t *out_prefix, uint8_t *out, uint8_t *out_suffix,
+ size_t *out_suffix_len, size_t max_out_suffix_len,
+ uint8_t type, uint16_t wire_version, const uint8_t seqnum[8],
+ const uint8_t *in, size_t in_len, const uint8_t *extra_in,
+ size_t extra_in_len);
+
+ bool GetIV(const uint8_t **out_iv, size_t *out_iv_len) const;
+
+ private:
+ /* GetAdditionalData writes the additional data into |out| and returns the
+ * number of bytes written. */
+ size_t GetAdditionalData(uint8_t out[13], uint8_t type, uint16_t wire_version,
+ const uint8_t seqnum[8], size_t plaintext_len);
+
+ const SSL_CIPHER *cipher_;
+ ScopedEVP_AEAD_CTX ctx_;
+ /* fixed_nonce_ contains any bytes of the nonce that are fixed for all
* records. */
- uint8_t fixed_nonce[12];
- uint8_t fixed_nonce_len, variable_nonce_len;
- /* version is the protocol version that should be used with this AEAD. */
- uint16_t version;
- /* variable_nonce_included_in_record is non-zero if the variable nonce
+ uint8_t fixed_nonce_[12];
+ uint8_t fixed_nonce_len_ = 0, variable_nonce_len_ = 0;
+ /* version_ is the protocol version that should be used with this AEAD. */
+ uint16_t version_;
+ /* variable_nonce_included_in_record_ is true if the variable nonce
* for a record is included as a prefix before the ciphertext. */
- unsigned variable_nonce_included_in_record : 1;
- /* random_variable_nonce is non-zero if the variable nonce is
+ bool variable_nonce_included_in_record_ : 1;
+ /* random_variable_nonce_ is true if the variable nonce is
* randomly generated, rather than derived from the sequence
* number. */
- unsigned random_variable_nonce : 1;
- /* omit_length_in_ad is non-zero if the length should be omitted in the
+ bool random_variable_nonce_ : 1;
+ /* omit_length_in_ad_ is true if the length should be omitted in the
* AEAD's ad parameter. */
- unsigned omit_length_in_ad : 1;
- /* omit_version_in_ad is non-zero if the version should be omitted
+ bool omit_length_in_ad_ : 1;
+ /* omit_version_in_ad_ is true if the version should be omitted
* in the AEAD's ad parameter. */
- unsigned omit_version_in_ad : 1;
- /* omit_ad is non-zero if the AEAD's ad parameter should be omitted. */
- unsigned omit_ad : 1;
- /* xor_fixed_nonce is non-zero if the fixed nonce should be XOR'd into the
+ bool omit_version_in_ad_ : 1;
+ /* omit_ad_ is true if the AEAD's ad parameter should be omitted. */
+ bool omit_ad_ : 1;
+ /* xor_fixed_nonce_ is true if the fixed nonce should be XOR'd into the
* variable nonce rather than prepended. */
- unsigned xor_fixed_nonce : 1;
-} SSL_AEAD_CTX;
-
-/* SSL_AEAD_CTX_new creates a newly-allocated |SSL_AEAD_CTX| using the supplied
- * key material. It returns NULL on error. Only one of |SSL_AEAD_CTX_open| or
- * |SSL_AEAD_CTX_seal| may be used with the resulting object, depending on
- * |direction|. |version| is the normalized protocol version, so DTLS 1.0 is
- * represented as 0x0301, not 0xffef. */
-SSL_AEAD_CTX *SSL_AEAD_CTX_new(enum evp_aead_direction_t direction,
- uint16_t version, int is_dtls,
- const SSL_CIPHER *cipher, const uint8_t *enc_key,
- size_t enc_key_len, const uint8_t *mac_key,
- size_t mac_key_len, const uint8_t *fixed_iv,
- size_t fixed_iv_len);
-
-/* SSL_AEAD_CTX_free frees |ctx|. */
-void SSL_AEAD_CTX_free(SSL_AEAD_CTX *ctx);
-
-/* SSL_AEAD_CTX_explicit_nonce_len returns the length of the explicit nonce for
- * |ctx|, if any. |ctx| may be NULL to denote the null cipher. */
-size_t SSL_AEAD_CTX_explicit_nonce_len(const SSL_AEAD_CTX *ctx);
-
-/* SSL_AEAD_CTX_max_overhead returns the maximum overhead of calling
- * |SSL_AEAD_CTX_seal|. |ctx| may be NULL to denote the null cipher. */
-size_t SSL_AEAD_CTX_max_overhead(const SSL_AEAD_CTX *ctx);
-
-/* SSL_AEAD_CTX_max_suffix_len returns the maximum suffix length written by
- * |SSL_AEAD_CTX_seal_scatter|. |ctx| may be NULL to denote the null cipher.
- * |extra_in_len| should equal the argument of the same name passed to
- * |SSL_AEAD_CTX_seal_scatter|. */
-size_t SSL_AEAD_CTX_max_suffix_len(const SSL_AEAD_CTX *ctx,
- size_t extra_in_len);
-
-/* SSL_AEAD_CTX_open authenticates and decrypts |in_len| bytes from |in|
- * in-place. On success, it sets |*out| to the plaintext in |in| and returns
- * one. Otherwise, it returns zero. |ctx| may be NULL to denote the null cipher.
- * The output will always be |explicit_nonce_len| bytes ahead of |in|. */
-int SSL_AEAD_CTX_open(SSL_AEAD_CTX *ctx, CBS *out, uint8_t type,
- uint16_t wire_version, const uint8_t seqnum[8],
- uint8_t *in, size_t in_len);
-
-/* SSL_AEAD_CTX_seal encrypts and authenticates |in_len| bytes from |in| and
- * writes the result to |out|. It returns one on success and zero on
- * error. |ctx| may be NULL to denote the null cipher.
- *
- * If |in| and |out| alias then |out| + |explicit_nonce_len| must be == |in|. */
-int SSL_AEAD_CTX_seal(SSL_AEAD_CTX *ctx, uint8_t *out, size_t *out_len,
- size_t max_out, uint8_t type, uint16_t wire_version,
- const uint8_t seqnum[8], const uint8_t *in,
- size_t in_len);
-
-/* SSL_AEAD_CTX_seal_scatter encrypts and authenticates |in_len| bytes from |in|
- * and splits the result between |out_prefix|, |out| and |out_suffix|. It
- * returns one on success and zero on error. |ctx| may be NULL to denote the
- * null cipher.
- *
- * On successful return, exactly |SSL_AEAD_CTX_explicit_nonce_len| bytes are
- * written to |out_prefix|, |in_len| bytes to |out|, and up to
- * |SSL_AEAD_CTX_max_suffix_len| bytes to |out_suffix|. |*out_suffix_len| is set
- * to the actual number of bytes written to |out_suffix|.
- *
- * |extra_in| may point to an additional plaintext buffer. If present,
- * |extra_in_len| additional bytes are encrypted and authenticated, and the
- * ciphertext is written to the beginning of |out_suffix|.
- * |SSL_AEAD_CTX_max_suffix_len| may be used to size |out_suffix| accordingly.
- *
- * If |in| and |out| alias then |out| must be == |in|. Other arguments may not
- * alias anything. */
-int SSL_AEAD_CTX_seal_scatter(SSL_AEAD_CTX *aead, uint8_t *out_prefix,
- uint8_t *out, uint8_t *out_suffix,
- size_t *out_suffix_len, size_t max_out_suffix_len,
- uint8_t type, uint16_t wire_version,
- const uint8_t seqnum[8], const uint8_t *in,
- size_t in_len, const uint8_t *extra_in,
- size_t extra_in_len);
+ bool xor_fixed_nonce_ : 1;
+};
/* DTLS replay bitmap. */
/* DTLS1_BITMAP maintains a sliding window of 64 sequence numbers to detect
* replayed packets. It should be initialized by zeroing every field. */
-typedef struct dtls1_bitmap_st {
+struct DTLS1_BITMAP {
/* map is a bit mask of the last 64 sequence numbers. Bit
* |1<<i| corresponds to |max_seq_num - i|. */
uint64_t map;
/* max_seq_num is the largest sequence number seen so far as a 64-bit
* integer. */
uint64_t max_seq_num;
-} DTLS1_BITMAP;
+};
/* Record layer. */
@@ -658,21 +719,26 @@ int ssl_public_key_verify(
/* Custom extensions */
-/* ssl_custom_extension (a.k.a. SSL_CUSTOM_EXTENSION) is a structure that
- * contains information about custom-extension callbacks. */
-struct ssl_custom_extension {
+} // namespace bssl
+
+/* |SSL_CUSTOM_EXTENSION| is a structure that contains information about
+ * custom-extension callbacks. It is defined unnamespaced for compatibility with
+ * |STACK_OF(SSL_CUSTOM_EXTENSION)|. */
+typedef struct ssl_custom_extension {
SSL_custom_ext_add_cb add_callback;
void *add_arg;
SSL_custom_ext_free_cb free_callback;
SSL_custom_ext_parse_cb parse_callback;
void *parse_arg;
uint16_t value;
-};
-
-void SSL_CUSTOM_EXTENSION_free(SSL_CUSTOM_EXTENSION *custom_extension);
+} SSL_CUSTOM_EXTENSION;
DEFINE_STACK_OF(SSL_CUSTOM_EXTENSION)
+namespace bssl {
+
+void SSL_CUSTOM_EXTENSION_free(SSL_CUSTOM_EXTENSION *custom_extension);
+
int custom_ext_add_clienthello(SSL_HANDSHAKE *hs, CBB *extensions);
int custom_ext_parse_serverhello(SSL_HANDSHAKE *hs, int *out_alert,
uint16_t value, const CBS *extension);
@@ -681,48 +747,50 @@ int custom_ext_parse_clienthello(SSL_HANDSHAKE *hs, int *out_alert,
int custom_ext_add_serverhello(SSL_HANDSHAKE *hs, CBB *extensions);
-/* ECDH groups. */
+/* Key shares. */
-typedef struct ssl_ecdh_ctx_st SSL_ECDH_CTX;
+/* SSLKeyShare abstracts over Diffie-Hellman-like key exchanges. */
+class SSLKeyShare {
+ public:
+ virtual ~SSLKeyShare() {}
-/* An SSL_ECDH_METHOD is an implementation of ECDH-like key exchanges for
- * TLS. */
-typedef struct ssl_ecdh_method_st {
- int nid;
- uint16_t group_id;
- const char name[8];
+ /* Create returns a SSLKeyShare instance for use with group |group_id| or
+ * nullptr on error. */
+ static UniquePtr<SSLKeyShare> Create(uint16_t group_id);
- /* cleanup releases state in |ctx|. */
- void (*cleanup)(SSL_ECDH_CTX *ctx);
+ /* GroupID returns the group ID. */
+ virtual uint16_t GroupID() const = 0;
- /* offer generates a keypair and writes the public value to
- * |out_public_key|. It returns one on success and zero on error. */
- int (*offer)(SSL_ECDH_CTX *ctx, CBB *out_public_key);
+ /* Offer generates a keypair and writes the public value to
+ * |out_public_key|. It returns true on success and false on error. */
+ virtual bool Offer(CBB *out_public_key) = 0;
- /* accept performs a key exchange against the |peer_key| generated by |offer|.
- * On success, it returns one, writes the public value to |out_public_key|,
+ /* Accept performs a key exchange against the |peer_key| generated by |offer|.
+ * On success, it returns true, writes the public value to |out_public_key|,
* and sets |*out_secret| and |*out_secret_len| to a newly-allocated buffer
* containing the shared secret. The caller must release this buffer with
- * |OPENSSL_free|. On failure, it returns zero and sets |*out_alert| to an
- * alert to send to the peer. */
- int (*accept)(SSL_ECDH_CTX *ctx, CBB *out_public_key, uint8_t **out_secret,
- size_t *out_secret_len, uint8_t *out_alert,
- const uint8_t *peer_key, size_t peer_key_len);
-
- /* finish performs a key exchange against the |peer_key| generated by
- * |accept|. On success, it returns one and sets |*out_secret| and
+ * |OPENSSL_free|. On failure, it returns false and sets |*out_alert| to an
+ * alert to send to the peer.
+ *
+ * The default implementation calls |Offer| and then |Finish|, assuming a key
+ * exchange protocol where the peers are symmetric.
+ *
+ * TODO(davidben): out_secret should be a smart pointer. */
+ virtual bool Accept(CBB *out_public_key, uint8_t **out_secret,
+ size_t *out_secret_len, uint8_t *out_alert,
+ const uint8_t *peer_key, size_t peer_key_len);
+
+ /* Finish performs a key exchange against the |peer_key| generated by
+ * |Accept|. On success, it returns true and sets |*out_secret| and
* |*out_secret_len| to a newly-allocated buffer containing the shared
* secret. The caller must release this buffer with |OPENSSL_free|. On
* failure, it returns zero and sets |*out_alert| to an alert to send to the
- * peer. */
- int (*finish)(SSL_ECDH_CTX *ctx, uint8_t **out_secret, size_t *out_secret_len,
- uint8_t *out_alert, const uint8_t *peer_key,
- size_t peer_key_len);
-} SSL_ECDH_METHOD;
-
-struct ssl_ecdh_ctx_st {
- const SSL_ECDH_METHOD *method;
- void *data;
+ * peer.
+ *
+ * TODO(davidben): out_secret should be a smart pointer. */
+ virtual bool Finish(uint8_t **out_secret, size_t *out_secret_len,
+ uint8_t *out_alert, const uint8_t *peer_key,
+ size_t peer_key_len) = 0;
};
/* ssl_nid_to_group_id looks up the group corresponding to |nid|. On success, it
@@ -735,36 +803,6 @@ int ssl_nid_to_group_id(uint16_t *out_group_id, int nid);
* returns one. Otherwise, it returns zero. */
int ssl_name_to_group_id(uint16_t *out_group_id, const char *name, size_t len);
-/* SSL_ECDH_CTX_init sets up |ctx| for use with curve |group_id|. It returns one
- * on success and zero on error. */
-int SSL_ECDH_CTX_init(SSL_ECDH_CTX *ctx, uint16_t group_id);
-
-/* SSL_ECDH_CTX_cleanup releases memory associated with |ctx|. It is legal to
- * call it in the zero state. */
-void SSL_ECDH_CTX_cleanup(SSL_ECDH_CTX *ctx);
-
-/* SSL_ECDH_CTX_get_id returns the group ID for |ctx|. */
-uint16_t SSL_ECDH_CTX_get_id(const SSL_ECDH_CTX *ctx);
-
-/* SSL_ECDH_CTX_get_key calls the |get_key| method of |SSL_ECDH_METHOD|. */
-int SSL_ECDH_CTX_get_key(SSL_ECDH_CTX *ctx, CBS *cbs, CBS *out);
-
-/* SSL_ECDH_CTX_add_key calls the |add_key| method of |SSL_ECDH_METHOD|. */
-int SSL_ECDH_CTX_add_key(SSL_ECDH_CTX *ctx, CBB *cbb, CBB *out_contents);
-
-/* SSL_ECDH_CTX_offer calls the |offer| method of |SSL_ECDH_METHOD|. */
-int SSL_ECDH_CTX_offer(SSL_ECDH_CTX *ctx, CBB *out_public_key);
-
-/* SSL_ECDH_CTX_accept calls the |accept| method of |SSL_ECDH_METHOD|. */
-int SSL_ECDH_CTX_accept(SSL_ECDH_CTX *ctx, CBB *out_public_key,
- uint8_t **out_secret, size_t *out_secret_len,
- uint8_t *out_alert, const uint8_t *peer_key,
- size_t peer_key_len);
-
-/* SSL_ECDH_CTX_finish the |finish| method of |SSL_ECDH_METHOD|. */
-int SSL_ECDH_CTX_finish(SSL_ECDH_CTX *ctx, uint8_t **out_secret,
- size_t *out_secret_len, uint8_t *out_alert,
- const uint8_t *peer_key, size_t peer_key_len);
/* Handshake messages. */
@@ -785,12 +823,12 @@ void dtls_clear_incoming_messages(SSL *ssl);
* messages ahead of the current message and zero otherwise. */
int dtls_has_incoming_messages(const SSL *ssl);
-typedef struct dtls_outgoing_message_st {
+struct DTLS_OUTGOING_MESSAGE {
uint8_t *data;
uint32_t len;
uint16_t epoch;
char is_ccs;
-} DTLS_OUTGOING_MESSAGE;
+};
/* dtls_clear_outgoing_messages releases all buffered outgoing messages. */
void dtls_clear_outgoing_messages(SSL *ssl);
@@ -869,19 +907,17 @@ int ssl_has_certificate(const SSL *ssl);
/* ssl_parse_cert_chain parses a certificate list from |cbs| in the format used
* by a TLS Certificate message. On success, it returns a newly-allocated
- * |CRYPTO_BUFFER| list and advances |cbs|. Otherwise, it returns NULL and sets
- * |*out_alert| to an alert to send to the peer.
+ * |CRYPTO_BUFFER| list and advances |cbs|. Otherwise, it returns nullptr and
+ * sets |*out_alert| to an alert to send to the peer.
*
* If the list is non-empty then |*out_pubkey| will be set to a freshly
* allocated public-key from the leaf certificate.
*
* If the list is non-empty and |out_leaf_sha256| is non-NULL, it writes the
* SHA-256 hash of the leaf to |out_leaf_sha256|. */
-STACK_OF(CRYPTO_BUFFER) *ssl_parse_cert_chain(uint8_t *out_alert,
- EVP_PKEY **out_pubkey,
- uint8_t *out_leaf_sha256,
- CBS *cbs,
- CRYPTO_BUFFER_POOL *pool);
+UniquePtr<STACK_OF(CRYPTO_BUFFER)> ssl_parse_cert_chain(
+ uint8_t *out_alert, UniquePtr<EVP_PKEY> *out_pubkey,
+ uint8_t *out_leaf_sha256, CBS *cbs, CRYPTO_BUFFER_POOL *pool);
/* ssl_add_cert_chain adds |ssl|'s certificate chain to |cbb| in the format used
* by a TLS Certificate message. If there is no certificate chain, it emits an
@@ -895,16 +931,17 @@ int ssl_add_cert_chain(SSL *ssl, CBB *cbb);
int ssl_cert_check_digital_signature_key_usage(const CBS *in);
/* ssl_cert_parse_pubkey extracts the public key from the DER-encoded, X.509
- * certificate in |in|. It returns an allocated |EVP_PKEY| or else returns NULL
- * and pushes to the error queue. */
-EVP_PKEY *ssl_cert_parse_pubkey(const CBS *in);
+ * certificate in |in|. It returns an allocated |EVP_PKEY| or else returns
+ * nullptr and pushes to the error queue. */
+UniquePtr<EVP_PKEY> ssl_cert_parse_pubkey(const CBS *in);
/* ssl_parse_client_CA_list parses a CA list from |cbs| in the format used by a
* TLS CertificateRequest message. On success, it returns a newly-allocated
- * |CRYPTO_BUFFER| list and advances |cbs|. Otherwise, it returns NULL and sets
- * |*out_alert| to an alert to send to the peer. */
-STACK_OF(CRYPTO_BUFFER) *
- ssl_parse_client_CA_list(SSL *ssl, uint8_t *out_alert, CBS *cbs);
+ * |CRYPTO_BUFFER| list and advances |cbs|. Otherwise, it returns nullptr and
+ * sets |*out_alert| to an alert to send to the peer. */
+UniquePtr<STACK_OF(CRYPTO_BUFFER)> ssl_parse_client_CA_list(SSL *ssl,
+ uint8_t *out_alert,
+ CBS *cbs);
/* ssl_add_client_CA_list adds the configured CA list to |cbb| in the format
* used by a TLS CertificateRequest message. It returns one on success and zero
@@ -1007,9 +1044,13 @@ enum ssl_hs_wait_t {
ssl_hs_early_data_rejected,
ssl_hs_read_end_of_early_data,
ssl_hs_read_change_cipher_spec,
+ ssl_hs_certificate_verify,
};
-struct ssl_handshake_st {
+struct SSL_HANDSHAKE {
+ explicit SSL_HANDSHAKE(SSL *ssl);
+ ~SSL_HANDSHAKE();
+
/* ssl is a non-owning pointer to the parent |SSL| object. */
SSL *ssl;
@@ -1020,45 +1061,45 @@ struct ssl_handshake_st {
/* wait contains the operation |do_tls13_handshake| is currently blocking on
* or |ssl_hs_ok| if none. */
- enum ssl_hs_wait_t wait;
+ enum ssl_hs_wait_t wait = ssl_hs_ok;
/* state contains one of the SSL3_ST_* values. */
- int state;
+ int state = SSL_ST_INIT;
/* next_state is used when SSL_ST_FLUSH_DATA is entered */
- int next_state;
+ int next_state = 0;
/* tls13_state is the internal state for the TLS 1.3 handshake. Its values
* depend on |do_tls13_handshake| but the starting state is always zero. */
- int tls13_state;
+ int tls13_state = 0;
/* min_version is the minimum accepted protocol version, taking account both
* |SSL_OP_NO_*| and |SSL_CTX_set_min_proto_version| APIs. */
- uint16_t min_version;
+ uint16_t min_version = 0;
/* max_version is the maximum accepted protocol version, taking account both
* |SSL_OP_NO_*| and |SSL_CTX_set_max_proto_version| APIs. */
- uint16_t max_version;
+ uint16_t max_version = 0;
/* session_id is the session ID in the ClientHello, used for the experimental
* TLS 1.3 variant. */
- uint8_t session_id[SSL_MAX_SSL_SESSION_ID_LENGTH];
- uint8_t session_id_len;
-
- size_t hash_len;
- uint8_t secret[EVP_MAX_MD_SIZE];
- uint8_t early_traffic_secret[EVP_MAX_MD_SIZE];
- uint8_t client_handshake_secret[EVP_MAX_MD_SIZE];
- uint8_t server_handshake_secret[EVP_MAX_MD_SIZE];
- uint8_t client_traffic_secret_0[EVP_MAX_MD_SIZE];
- uint8_t server_traffic_secret_0[EVP_MAX_MD_SIZE];
- uint8_t expected_client_finished[EVP_MAX_MD_SIZE];
+ uint8_t session_id[SSL_MAX_SSL_SESSION_ID_LENGTH] = {0};
+ uint8_t session_id_len = 0;
+
+ size_t hash_len = 0;
+ uint8_t secret[EVP_MAX_MD_SIZE] = {0};
+ uint8_t early_traffic_secret[EVP_MAX_MD_SIZE] = {0};
+ uint8_t client_handshake_secret[EVP_MAX_MD_SIZE] = {0};
+ uint8_t server_handshake_secret[EVP_MAX_MD_SIZE] = {0};
+ uint8_t client_traffic_secret_0[EVP_MAX_MD_SIZE] = {0};
+ uint8_t server_traffic_secret_0[EVP_MAX_MD_SIZE] = {0};
+ uint8_t expected_client_finished[EVP_MAX_MD_SIZE] = {0};
union {
/* sent is a bitset where the bits correspond to elements of kExtensions
* in t1_lib.c. Each bit is set if that extension was sent in a
* ClientHello. It's not used by servers. */
- uint32_t sent;
+ uint32_t sent = 0;
/* received is a bitset, like |sent|, but is used by servers to record
* which extensions were received from a client. */
uint32_t received;
@@ -1068,7 +1109,7 @@ struct ssl_handshake_st {
/* sent is a bitset where the bits correspond to elements of
* |client_custom_extensions| in the |SSL_CTX|. Each bit is set if that
* extension was sent in a ClientHello. It's not used by servers. */
- uint16_t sent;
+ uint16_t sent = 0;
/* received is a bitset, like |sent|, but is used by servers to record
* which custom extensions were received from a client. The bits here
* correspond to |server_custom_extensions|. */
@@ -1077,91 +1118,91 @@ struct ssl_handshake_st {
/* retry_group is the group ID selected by the server in HelloRetryRequest in
* TLS 1.3. */
- uint16_t retry_group;
+ uint16_t retry_group = 0;
- /* ecdh_ctx is the current ECDH instance. */
- SSL_ECDH_CTX ecdh_ctx;
+ /* key_share is the current key exchange instance. */
+ UniquePtr<SSLKeyShare> key_share;
/* transcript is the current handshake transcript. */
- SSL_TRANSCRIPT transcript;
+ SSLTranscript transcript;
/* cookie is the value of the cookie received from the server, if any. */
- uint8_t *cookie;
- size_t cookie_len;
+ uint8_t *cookie = nullptr;
+ size_t cookie_len = 0;
/* key_share_bytes is the value of the previously sent KeyShare extension by
* the client in TLS 1.3. */
- uint8_t *key_share_bytes;
- size_t key_share_bytes_len;
+ uint8_t *key_share_bytes = nullptr;
+ size_t key_share_bytes_len = 0;
/* ecdh_public_key, for servers, is the key share to be sent to the client in
* TLS 1.3. */
- uint8_t *ecdh_public_key;
- size_t ecdh_public_key_len;
+ uint8_t *ecdh_public_key = nullptr;
+ size_t ecdh_public_key_len = 0;
/* peer_sigalgs are the signature algorithms that the peer supports. These are
* taken from the contents of the signature algorithms extension for a server
* or from the CertificateRequest for a client. */
- uint16_t *peer_sigalgs;
+ uint16_t *peer_sigalgs = nullptr;
/* num_peer_sigalgs is the number of entries in |peer_sigalgs|. */
- size_t num_peer_sigalgs;
+ size_t num_peer_sigalgs = 0;
/* peer_supported_group_list contains the supported group IDs advertised by
* the peer. This is only set on the server's end. The server does not
* advertise this extension to the client. */
- uint16_t *peer_supported_group_list;
- size_t peer_supported_group_list_len;
+ uint16_t *peer_supported_group_list = nullptr;
+ size_t peer_supported_group_list_len = 0;
/* peer_key is the peer's ECDH key for a TLS 1.2 client. */
- uint8_t *peer_key;
- size_t peer_key_len;
+ uint8_t *peer_key = nullptr;
+ size_t peer_key_len = 0;
/* server_params, in a TLS 1.2 server, stores the ServerKeyExchange
* parameters. It has client and server randoms prepended for signing
* convenience. */
- uint8_t *server_params;
- size_t server_params_len;
+ uint8_t *server_params = nullptr;
+ size_t server_params_len = 0;
/* peer_psk_identity_hint, on the client, is the psk_identity_hint sent by the
* server when using a TLS 1.2 PSK key exchange. */
- char *peer_psk_identity_hint;
+ UniquePtr<char> peer_psk_identity_hint;
/* ca_names, on the client, contains the list of CAs received in a
* CertificateRequest message. */
- STACK_OF(CRYPTO_BUFFER) *ca_names;
+ UniquePtr<STACK_OF(CRYPTO_BUFFER)> ca_names;
/* cached_x509_ca_names contains a cache of parsed versions of the elements
* of |ca_names|. */
- STACK_OF(X509_NAME) *cached_x509_ca_names;
+ STACK_OF(X509_NAME) *cached_x509_ca_names = nullptr;
/* certificate_types, on the client, contains the set of certificate types
* received in a CertificateRequest message. */
- uint8_t *certificate_types;
- size_t num_certificate_types;
+ uint8_t *certificate_types = nullptr;
+ size_t num_certificate_types = 0;
/* hostname, on the server, is the value of the SNI extension. */
- char *hostname;
+ UniquePtr<char> hostname;
/* local_pubkey is the public key we are authenticating as. */
- EVP_PKEY *local_pubkey;
+ UniquePtr<EVP_PKEY> local_pubkey;
/* peer_pubkey is the public key parsed from the peer's leaf certificate. */
- EVP_PKEY *peer_pubkey;
+ UniquePtr<EVP_PKEY> peer_pubkey;
/* new_session is the new mutable session being established by the current
* handshake. It should not be cached. */
- SSL_SESSION *new_session;
+ UniquePtr<SSL_SESSION> new_session;
/* early_session is the session corresponding to the current 0-RTT state on
* the client if |in_early_data| is true. */
- SSL_SESSION *early_session;
+ UniquePtr<SSL_SESSION> early_session;
/* new_cipher is the cipher being negotiated in this handshake. */
- const SSL_CIPHER *new_cipher;
+ const SSL_CIPHER *new_cipher = nullptr;
/* key_block is the record-layer key block for TLS 1.2 and earlier. */
- uint8_t *key_block;
- uint8_t key_block_len;
+ uint8_t *key_block = nullptr;
+ uint8_t key_block_len = 0;
/* scts_requested is one if the SCT extension is in the ClientHello. */
unsigned scts_requested:1;
@@ -1227,16 +1268,16 @@ struct ssl_handshake_st {
unsigned pending_private_key_op:1;
/* client_version is the value sent or received in the ClientHello version. */
- uint16_t client_version;
+ uint16_t client_version = 0;
/* early_data_read is the amount of early data that has been read by the
* record layer. */
- uint16_t early_data_read;
+ uint16_t early_data_read = 0;
/* early_data_written is the amount of early data that has been written by the
* record layer. */
- uint16_t early_data_written;
-} /* SSL_HANDSHAKE */;
+ uint16_t early_data_written = 0;
+};
SSL_HANDSHAKE *ssl_handshake_new(SSL *ssl);
@@ -1326,11 +1367,11 @@ int tls13_get_cert_verify_signature_input(
int ssl_negotiate_alpn(SSL_HANDSHAKE *hs, uint8_t *out_alert,
const SSL_CLIENT_HELLO *client_hello);
-typedef struct {
+struct SSL_EXTENSION_TYPE {
uint16_t type;
int *out_present;
CBS *out_data;
-} SSL_EXTENSION_TYPE;
+};
/* ssl_parse_extensions parses a TLS extensions block out of |cbs| and advances
* it. It writes the parsed extensions to pointers denoted by |ext_types|. On
@@ -1341,6 +1382,9 @@ int ssl_parse_extensions(const CBS *cbs, uint8_t *out_alert,
const SSL_EXTENSION_TYPE *ext_types,
size_t num_ext_types, int ignore_unknown);
+/* ssl_verify_peer_cert verifies the peer certificate for |hs|. */
+enum ssl_verify_result_t ssl_verify_peer_cert(SSL_HANDSHAKE *hs);
+
/* SSLKEYLOGFILE functions. */
@@ -1416,7 +1460,7 @@ int tls12_check_peer_sigalg(SSL *ssl, uint8_t *out_alert, uint16_t sigalg);
/* From RFC4492, used in encoding the curve type in ECParameters */
#define NAMED_CURVE_TYPE 3
-typedef struct cert_st {
+struct SSLCertConfig {
EVP_PKEY *privatekey;
/* chain contains the certificate chain, with the leaf at the beginning. The
@@ -1481,160 +1525,22 @@ typedef struct cert_st {
/* If enable_early_data is non-zero, early data can be sent and accepted. */
unsigned enable_early_data:1;
-} CERT;
-
-/* SSL_METHOD is a compatibility structure to support the legacy version-locked
- * methods. */
-struct ssl_method_st {
- /* version, if non-zero, is the only protocol version acceptable to an
- * SSL_CTX initialized from this method. */
- uint16_t version;
- /* method is the underlying SSL_PROTOCOL_METHOD that initializes the
- * SSL_CTX. */
- const SSL_PROTOCOL_METHOD *method;
- /* x509_method contains pointers to functions that might deal with |X509|
- * compatibility, or might be a no-op, depending on the application. */
- const SSL_X509_METHOD *x509_method;
-};
-
-/* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */
-struct ssl_protocol_method_st {
- /* is_dtls is one if the protocol is DTLS and zero otherwise. */
- char is_dtls;
- int (*ssl_new)(SSL *ssl);
- void (*ssl_free)(SSL *ssl);
- /* ssl_get_message reads the next handshake message. On success, it returns
- * one and sets |ssl->s3->tmp.message_type|, |ssl->init_msg|, and
- * |ssl->init_num|. Otherwise, it returns <= 0. */
- int (*ssl_get_message)(SSL *ssl);
- /* get_current_message sets |*out| to the current handshake message. This
- * includes the protocol-specific message header. */
- void (*get_current_message)(const SSL *ssl, CBS *out);
- /* release_current_message is called to release the current handshake message.
- * If |free_buffer| is one, buffers will also be released. */
- void (*release_current_message)(SSL *ssl, int free_buffer);
- /* read_app_data reads up to |len| bytes of application data into |buf|. On
- * success, it returns the number of bytes read. Otherwise, it returns <= 0
- * and sets |*out_got_handshake| to whether the failure was due to a
- * post-handshake handshake message. If so, it fills in the current message as
- * in |ssl_get_message|. */
- int (*read_app_data)(SSL *ssl, int *out_got_handshake, uint8_t *buf, int len,
- int peek);
- int (*read_change_cipher_spec)(SSL *ssl);
- void (*read_close_notify)(SSL *ssl);
- int (*write_app_data)(SSL *ssl, int *out_needs_handshake, const uint8_t *buf,
- int len);
- int (*dispatch_alert)(SSL *ssl);
- /* supports_cipher returns one if |cipher| is supported by this protocol and
- * zero otherwise. */
- int (*supports_cipher)(const SSL_CIPHER *cipher);
- /* init_message begins a new handshake message of type |type|. |cbb| is the
- * root CBB to be passed into |finish_message|. |*body| is set to a child CBB
- * the caller should write to. It returns one on success and zero on error. */
- int (*init_message)(SSL *ssl, CBB *cbb, CBB *body, uint8_t type);
- /* finish_message finishes a handshake message. It sets |*out_msg| to a
- * newly-allocated buffer with the serialized message. The caller must
- * release it with |OPENSSL_free| when done. It returns one on success and
- * zero on error. */
- int (*finish_message)(SSL *ssl, CBB *cbb, uint8_t **out_msg, size_t *out_len);
- /* add_message adds a handshake message to the pending flight. It returns one
- * on success and zero on error. In either case, it takes ownership of |msg|
- * and releases it with |OPENSSL_free| when done. */
- int (*add_message)(SSL *ssl, uint8_t *msg, size_t len);
- /* add_change_cipher_spec adds a ChangeCipherSpec record to the pending
- * flight. It returns one on success and zero on error. */
- int (*add_change_cipher_spec)(SSL *ssl);
- /* add_alert adds an alert to the pending flight. It returns one on success
- * and zero on error. */
- int (*add_alert)(SSL *ssl, uint8_t level, uint8_t desc);
- /* flush_flight flushes the pending flight to the transport. It returns one on
- * success and <= 0 on error. */
- int (*flush_flight)(SSL *ssl);
- /* expect_flight is called when the handshake expects a flight of messages from
- * the peer. */
- void (*expect_flight)(SSL *ssl);
- /* received_flight is called when the handshake has received a flight of
- * messages from the peer. */
- void (*received_flight)(SSL *ssl);
- /* set_read_state sets |ssl|'s read cipher state to |aead_ctx|. It takes
- * ownership of |aead_ctx|. It returns one on success and zero if changing the
- * read state is forbidden at this point. */
- int (*set_read_state)(SSL *ssl, SSL_AEAD_CTX *aead_ctx);
- /* set_write_state sets |ssl|'s write cipher state to |aead_ctx|. It takes
- * ownership of |aead_ctx|. It returns one on success and zero if changing the
- * write state is forbidden at this point. */
- int (*set_write_state)(SSL *ssl, SSL_AEAD_CTX *aead_ctx);
};
-struct ssl_x509_method_st {
- /* check_client_CA_list returns one if |names| is a good list of X.509
- * distinguished names and zero otherwise. This is used to ensure that we can
- * reject unparsable values at handshake time when using crypto/x509. */
- int (*check_client_CA_list)(STACK_OF(CRYPTO_BUFFER) *names);
-
- /* cert_clear frees and NULLs all X509 certificate-related state. */
- void (*cert_clear)(CERT *cert);
- /* cert_free frees all X509-related state. */
- void (*cert_free)(CERT *cert);
- /* cert_flush_cached_chain drops any cached |X509|-based certificate chain
- * from |cert|. */
- /* cert_dup duplicates any needed fields from |cert| to |new_cert|. */
- void (*cert_dup)(CERT *new_cert, const CERT *cert);
- void (*cert_flush_cached_chain)(CERT *cert);
- /* cert_flush_cached_chain drops any cached |X509|-based leaf certificate
- * from |cert|. */
- void (*cert_flush_cached_leaf)(CERT *cert);
-
- /* session_cache_objects fills out |sess->x509_peer| and |sess->x509_chain|
- * from |sess->certs| and erases |sess->x509_chain_without_leaf|. It returns
- * one on success or zero on error. */
- int (*session_cache_objects)(SSL_SESSION *session);
- /* session_dup duplicates any needed fields from |session| to |new_session|.
- * It returns one on success or zero on error. */
- int (*session_dup)(SSL_SESSION *new_session, const SSL_SESSION *session);
- /* session_clear frees any X509-related state from |session|. */
- void (*session_clear)(SSL_SESSION *session);
- /* session_verify_cert_chain verifies the certificate chain in |session|,
- * sets |session->verify_result| and returns one on success or zero on
- * error. */
- int (*session_verify_cert_chain)(SSL_SESSION *session, SSL *ssl);
-
- /* hs_flush_cached_ca_names drops any cached |X509_NAME|s from |hs|. */
- void (*hs_flush_cached_ca_names)(SSL_HANDSHAKE *hs);
- /* ssl_new does any neccessary initialisation of |ssl|. It returns one on
- * success or zero on error. */
- int (*ssl_new)(SSL *ssl);
- /* ssl_free frees anything created by |ssl_new|. */
- void (*ssl_free)(SSL *ssl);
- /* ssl_flush_cached_client_CA drops any cached |X509_NAME|s from |ssl|. */
- void (*ssl_flush_cached_client_CA)(SSL *ssl);
- /* ssl_auto_chain_if_needed runs the deprecated auto-chaining logic if
- * necessary. On success, it updates |ssl|'s certificate configuration as
- * needed and returns one. Otherwise, it returns zero. */
- int (*ssl_auto_chain_if_needed)(SSL *ssl);
- /* ssl_ctx_new does any neccessary initialisation of |ctx|. It returns one on
- * success or zero on error. */
- int (*ssl_ctx_new)(SSL_CTX *ctx);
- /* ssl_ctx_free frees anything created by |ssl_ctx_new|. */
- void (*ssl_ctx_free)(SSL_CTX *ctx);
- /* ssl_ctx_flush_cached_client_CA drops any cached |X509_NAME|s from |ctx|. */
- void (*ssl_ctx_flush_cached_client_CA)(SSL_CTX *ssl);
-};
-
-/* ssl_crypto_x509_method provides the |ssl_x509_method_st| functions using
+/* ssl_crypto_x509_method provides the |SSL_X509_METHOD| functions using
* crypto/x509. */
-extern const struct ssl_x509_method_st ssl_crypto_x509_method;
+extern const SSL_X509_METHOD ssl_crypto_x509_method;
-typedef struct ssl3_record_st {
+struct SSL3_RECORD {
/* type is the record type. */
uint8_t type;
/* length is the number of unconsumed bytes in the record. */
uint16_t length;
/* data is a non-owning pointer to the first unconsumed byte of the record. */
uint8_t *data;
-} SSL3_RECORD;
+};
-typedef struct ssl3_buffer_st {
+struct SSL3_BUFFER {
/* buf is the memory allocated for this buffer. */
uint8_t *buf;
/* offset is the offset into |buf| which the buffer contents start at. */
@@ -1643,7 +1549,7 @@ typedef struct ssl3_buffer_st {
uint16_t len;
/* cap is how much memory beyond |buf| + |offset| is available. */
uint16_t cap;
-} SSL3_BUFFER;
+};
/* An ssl_shutdown_t describes the shutdown state of one end of the connection,
* whether it is alive or has been shutdown via close_notify or fatal alert. */
@@ -1653,7 +1559,7 @@ enum ssl_shutdown_t {
ssl_shutdown_fatal_alert = 2,
};
-typedef struct ssl3_state_st {
+struct SSL3_STATE {
uint8_t read_sequence[8];
uint8_t write_sequence[8];
@@ -1749,10 +1655,10 @@ typedef struct ssl3_state_st {
uint32_t pending_flight_offset;
/* aead_read_ctx is the current read cipher state. */
- SSL_AEAD_CTX *aead_read_ctx;
+ SSLAEADContext *aead_read_ctx;
/* aead_write_ctx is the current write cipher state. */
- SSL_AEAD_CTX *aead_write_ctx;
+ SSLAEADContext *aead_write_ctx;
/* hs is the handshake state for the current handshake or NULL if there isn't
* one. */
@@ -1820,7 +1726,7 @@ typedef struct ssl3_state_st {
* ticket age and the server-computed value in TLS 1.3 server connections
* which resumed a session. */
int32_t ticket_age_skew;
-} SSL3_STATE;
+};
/* lengths of messages */
#define DTLS1_COOKIE_LENGTH 256
@@ -1842,7 +1748,7 @@ struct hm_header_st {
};
/* An hm_fragment is an incoming DTLS message, possibly not yet assembled. */
-typedef struct hm_fragment_st {
+struct hm_fragment {
/* type is the type of the message. */
uint8_t type;
/* seq is the sequence number of this message. */
@@ -1855,14 +1761,14 @@ typedef struct hm_fragment_st {
/* reassembly is a bitmask of |msg_len| bits corresponding to which parts of
* the message have been received. It is NULL if the message is complete. */
uint8_t *reassembly;
-} hm_fragment;
+};
struct OPENSSL_timeval {
uint64_t tv_sec;
uint32_t tv_usec;
};
-typedef struct dtls1_state_st {
+struct DTLS1_STATE {
/* send_cookie is true if we are resending the ClientHello
* with a cookie from a HelloVerifyRequest. */
unsigned int send_cookie;
@@ -1883,6 +1789,7 @@ typedef struct dtls1_state_st {
/* save last sequence number for retransmissions */
uint8_t last_write_sequence[8];
+ SSLAEADContext *last_aead_write_ctx;
/* incoming_messages is a ring buffer of incoming handshake messages that have
* yet to be processed. The front of the ring buffer is message number
@@ -1914,9 +1821,11 @@ typedef struct dtls1_state_st {
/* timeout_duration_ms is the timeout duration in milliseconds. */
unsigned timeout_duration_ms;
-} DTLS1_STATE;
+};
-struct ssl_st {
+/* SSLConnection backs the public |SSL| type. Due to compatibility constraints,
+ * it is a base class for |ssl_st|. */
+struct SSLConnection {
/* method is the method table corresponding to the current protocol (DTLS or
* TLS). */
const SSL_PROTOCOL_METHOD *method;
@@ -1955,8 +1864,8 @@ struct ssl_st {
/* init_num is the length of the current handshake message body. */
uint32_t init_num;
- struct ssl3_state_st *s3; /* SSLv3 variables */
- struct dtls1_state_st *d1; /* DTLSv1 variables */
+ SSL3_STATE *s3; /* SSLv3 variables */
+ DTLS1_STATE *d1; /* DTLSv1 variables */
/* callback that allows applications to peek at protocol messages */
void (*msg_callback)(int write_p, int version, int content_type,
@@ -1972,7 +1881,7 @@ struct ssl_st {
/* client cert? */
/* This is used to hold the server certificate used */
- struct cert_st /* CERT */ *cert;
+ CERT *cert;
/* This holds a variable that indicates what we were doing when a 0 or -1 is
* returned. This is needed for non-blocking IO so we know what request
@@ -1990,6 +1899,9 @@ struct ssl_st {
int (*verify_callback)(int ok,
X509_STORE_CTX *ctx); /* fail if callback returns 0 */
+ enum ssl_verify_result_t (*custom_verify_callback)(SSL *ssl,
+ uint8_t *out_alert);
+
void (*info_callback)(const SSL *ssl, int type, int value);
/* Server-only: psk_identity_hint is the identity hint to send in
@@ -2107,14 +2019,15 @@ int ssl_cert_check_private_key(const CERT *cert, const EVP_PKEY *privkey);
int ssl_get_new_session(SSL_HANDSHAKE *hs, int is_server);
int ssl_encrypt_ticket(SSL *ssl, CBB *out, const SSL_SESSION *session);
-/* ssl_session_new returns a newly-allocated blank |SSL_SESSION| or NULL on
+/* ssl_session_new returns a newly-allocated blank |SSL_SESSION| or nullptr on
* error. */
-SSL_SESSION *ssl_session_new(const SSL_X509_METHOD *x509_method);
+UniquePtr<SSL_SESSION> ssl_session_new(const SSL_X509_METHOD *x509_method);
/* SSL_SESSION_parse parses an |SSL_SESSION| from |cbs| and advances |cbs| over
* the parsed data. */
-SSL_SESSION *SSL_SESSION_parse(CBS *cbs, const SSL_X509_METHOD *x509_method,
- CRYPTO_BUFFER_POOL *pool);
+UniquePtr<SSL_SESSION> SSL_SESSION_parse(CBS *cbs,
+ const SSL_X509_METHOD *x509_method,
+ CRYPTO_BUFFER_POOL *pool);
/* ssl_session_is_context_valid returns one if |session|'s session ID context
* matches the one set on |ssl| and zero otherwise. */
@@ -2163,10 +2076,10 @@ enum ssl_session_result_t ssl_get_prev_session(
(SSL_SESSION_INCLUDE_TICKET | SSL_SESSION_INCLUDE_NONAUTH)
/* SSL_SESSION_dup returns a newly-allocated |SSL_SESSION| with a copy of the
- * fields in |session| or NULL on error. The new session is non-resumable and
+ * fields in |session| or nullptr on error. The new session is non-resumable and
* must be explicitly marked resumable once it has been filled in. */
-OPENSSL_EXPORT SSL_SESSION *SSL_SESSION_dup(SSL_SESSION *session,
- int dup_flags);
+OPENSSL_EXPORT UniquePtr<SSL_SESSION> SSL_SESSION_dup(SSL_SESSION *session,
+ int dup_flags);
/* ssl_session_rebase_time updates |session|'s start time to the current time,
* adjusting the timeout so the expiration time is unchanged. */
@@ -2373,8 +2286,171 @@ void ssl_get_current_time(const SSL *ssl, struct OPENSSL_timeval *out_clock);
void ssl_reset_error_state(SSL *ssl);
-#if defined(__cplusplus)
-} /* extern C */
+/* Utility macros */
+
+#if defined(__clang__)
+/* SSL_FALLTHROUGH annotates a fallthough case in a switch statement. */
+#define SSL_FALLTHROUGH [[clang::fallthrough]]
+#else
+#define SSL_FALLTHROUGH
#endif
+} // namespace bssl
+
+
+/* Opaque C types.
+ *
+ * The following types are exported to C code as public typedefs, so they must
+ * be defined outside of the namespace. */
+
+/* ssl_method_st backs the public |SSL_METHOD| type. It is a compatibility
+ * structure to support the legacy version-locked methods. */
+struct ssl_method_st {
+ /* version, if non-zero, is the only protocol version acceptable to an
+ * SSL_CTX initialized from this method. */
+ uint16_t version;
+ /* method is the underlying SSL_PROTOCOL_METHOD that initializes the
+ * SSL_CTX. */
+ const SSL_PROTOCOL_METHOD *method;
+ /* x509_method contains pointers to functions that might deal with |X509|
+ * compatibility, or might be a no-op, depending on the application. */
+ const SSL_X509_METHOD *x509_method;
+};
+
+/* ssl_protocol_method_st, aka |SSL_PROTOCOL_METHOD| abstracts between TLS and
+ * DTLS. */
+struct ssl_protocol_method_st {
+ /* is_dtls is one if the protocol is DTLS and zero otherwise. */
+ char is_dtls;
+ int (*ssl_new)(SSL *ssl);
+ void (*ssl_free)(SSL *ssl);
+ /* ssl_get_message reads the next handshake message. On success, it returns
+ * one and sets |ssl->s3->tmp.message_type|, |ssl->init_msg|, and
+ * |ssl->init_num|. Otherwise, it returns <= 0. */
+ int (*ssl_get_message)(SSL *ssl);
+ /* get_current_message sets |*out| to the current handshake message. This
+ * includes the protocol-specific message header. */
+ void (*get_current_message)(const SSL *ssl, CBS *out);
+ /* release_current_message is called to release the current handshake message.
+ * If |free_buffer| is one, buffers will also be released. */
+ void (*release_current_message)(SSL *ssl, int free_buffer);
+ /* read_app_data reads up to |len| bytes of application data into |buf|. On
+ * success, it returns the number of bytes read. Otherwise, it returns <= 0
+ * and sets |*out_got_handshake| to whether the failure was due to a
+ * post-handshake handshake message. If so, it fills in the current message as
+ * in |ssl_get_message|. */
+ int (*read_app_data)(SSL *ssl, int *out_got_handshake, uint8_t *buf, int len,
+ int peek);
+ int (*read_change_cipher_spec)(SSL *ssl);
+ void (*read_close_notify)(SSL *ssl);
+ int (*write_app_data)(SSL *ssl, int *out_needs_handshake, const uint8_t *buf,
+ int len);
+ int (*dispatch_alert)(SSL *ssl);
+ /* supports_cipher returns one if |cipher| is supported by this protocol and
+ * zero otherwise. */
+ int (*supports_cipher)(const SSL_CIPHER *cipher);
+ /* init_message begins a new handshake message of type |type|. |cbb| is the
+ * root CBB to be passed into |finish_message|. |*body| is set to a child CBB
+ * the caller should write to. It returns one on success and zero on error. */
+ int (*init_message)(SSL *ssl, CBB *cbb, CBB *body, uint8_t type);
+ /* finish_message finishes a handshake message. It sets |*out_msg| to a
+ * newly-allocated buffer with the serialized message. The caller must
+ * release it with |OPENSSL_free| when done. It returns one on success and
+ * zero on error. */
+ int (*finish_message)(SSL *ssl, CBB *cbb, uint8_t **out_msg, size_t *out_len);
+ /* add_message adds a handshake message to the pending flight. It returns one
+ * on success and zero on error. In either case, it takes ownership of |msg|
+ * and releases it with |OPENSSL_free| when done. */
+ int (*add_message)(SSL *ssl, uint8_t *msg, size_t len);
+ /* add_change_cipher_spec adds a ChangeCipherSpec record to the pending
+ * flight. It returns one on success and zero on error. */
+ int (*add_change_cipher_spec)(SSL *ssl);
+ /* add_alert adds an alert to the pending flight. It returns one on success
+ * and zero on error. */
+ int (*add_alert)(SSL *ssl, uint8_t level, uint8_t desc);
+ /* flush_flight flushes the pending flight to the transport. It returns one on
+ * success and <= 0 on error. */
+ int (*flush_flight)(SSL *ssl);
+ /* expect_flight is called when the handshake expects a flight of messages from
+ * the peer. */
+ void (*expect_flight)(SSL *ssl);
+ /* received_flight is called when the handshake has received a flight of
+ * messages from the peer. */
+ void (*received_flight)(SSL *ssl);
+ /* set_read_state sets |ssl|'s read cipher state to |aead_ctx|. It returns
+ * one on success and zero if changing the read state is forbidden at this
+ * point. */
+ int (*set_read_state)(SSL *ssl,
+ bssl::UniquePtr<bssl::SSLAEADContext> aead_ctx);
+ /* set_write_state sets |ssl|'s write cipher state to |aead_ctx|. It returns
+ * one on success and zero if changing the write state is forbidden at this
+ * point. */
+ int (*set_write_state)(SSL *ssl,
+ bssl::UniquePtr<bssl::SSLAEADContext> aead_ctx);
+};
+
+struct ssl_x509_method_st {
+ /* check_client_CA_list returns one if |names| is a good list of X.509
+ * distinguished names and zero otherwise. This is used to ensure that we can
+ * reject unparsable values at handshake time when using crypto/x509. */
+ int (*check_client_CA_list)(STACK_OF(CRYPTO_BUFFER) *names);
+
+ /* cert_clear frees and NULLs all X509 certificate-related state. */
+ void (*cert_clear)(CERT *cert);
+ /* cert_free frees all X509-related state. */
+ void (*cert_free)(CERT *cert);
+ /* cert_flush_cached_chain drops any cached |X509|-based certificate chain
+ * from |cert|. */
+ /* cert_dup duplicates any needed fields from |cert| to |new_cert|. */
+ void (*cert_dup)(CERT *new_cert, const CERT *cert);
+ void (*cert_flush_cached_chain)(CERT *cert);
+ /* cert_flush_cached_chain drops any cached |X509|-based leaf certificate
+ * from |cert|. */
+ void (*cert_flush_cached_leaf)(CERT *cert);
+
+ /* session_cache_objects fills out |sess->x509_peer| and |sess->x509_chain|
+ * from |sess->certs| and erases |sess->x509_chain_without_leaf|. It returns
+ * one on success or zero on error. */
+ int (*session_cache_objects)(SSL_SESSION *session);
+ /* session_dup duplicates any needed fields from |session| to |new_session|.
+ * It returns one on success or zero on error. */
+ int (*session_dup)(SSL_SESSION *new_session, const SSL_SESSION *session);
+ /* session_clear frees any X509-related state from |session|. */
+ void (*session_clear)(SSL_SESSION *session);
+ /* session_verify_cert_chain verifies the certificate chain in |session|,
+ * sets |session->verify_result| and returns one on success or zero on
+ * error. */
+ int (*session_verify_cert_chain)(SSL_SESSION *session, SSL *ssl,
+ uint8_t *out_alert);
+
+ /* hs_flush_cached_ca_names drops any cached |X509_NAME|s from |hs|. */
+ void (*hs_flush_cached_ca_names)(bssl::SSL_HANDSHAKE *hs);
+ /* ssl_new does any neccessary initialisation of |ssl|. It returns one on
+ * success or zero on error. */
+ int (*ssl_new)(SSL *ssl);
+ /* ssl_free frees anything created by |ssl_new|. */
+ void (*ssl_free)(SSL *ssl);
+ /* ssl_flush_cached_client_CA drops any cached |X509_NAME|s from |ssl|. */
+ void (*ssl_flush_cached_client_CA)(SSL *ssl);
+ /* ssl_auto_chain_if_needed runs the deprecated auto-chaining logic if
+ * necessary. On success, it updates |ssl|'s certificate configuration as
+ * needed and returns one. Otherwise, it returns zero. */
+ int (*ssl_auto_chain_if_needed)(SSL *ssl);
+ /* ssl_ctx_new does any neccessary initialisation of |ctx|. It returns one on
+ * success or zero on error. */
+ int (*ssl_ctx_new)(SSL_CTX *ctx);
+ /* ssl_ctx_free frees anything created by |ssl_ctx_new|. */
+ void (*ssl_ctx_free)(SSL_CTX *ctx);
+ /* ssl_ctx_flush_cached_client_CA drops any cached |X509_NAME|s from |ctx|. */
+ void (*ssl_ctx_flush_cached_client_CA)(SSL_CTX *ssl);
+};
+
+/* ssl_st backs the public |SSL| type. It subclasses the true type so that
+ * SSLConnection may be a C++ type with methods and destructor without
+ * polluting the global namespace. */
+struct ssl_st : public bssl::SSLConnection {};
+
+struct cert_st : public bssl::SSLCertConfig {};
+
+
#endif /* OPENSSL_HEADER_SSL_INTERNAL_H */
diff --git a/src/ssl/s3_both.cc b/src/ssl/s3_both.cc
index 79f71faf..b9aa3bc7 100644
--- a/src/ssl/s3_both.cc
+++ b/src/ssl/s3_both.cc
@@ -130,65 +130,63 @@
#include "internal.h"
-SSL_HANDSHAKE *ssl_handshake_new(SSL *ssl) {
- SSL_HANDSHAKE *hs = (SSL_HANDSHAKE *)OPENSSL_malloc(sizeof(SSL_HANDSHAKE));
- if (hs == NULL) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- return NULL;
- }
- OPENSSL_memset(hs, 0, sizeof(SSL_HANDSHAKE));
- hs->ssl = ssl;
- hs->wait = ssl_hs_ok;
- hs->state = SSL_ST_INIT;
- if (!SSL_TRANSCRIPT_init(&hs->transcript)) {
- ssl_handshake_free(hs);
- return NULL;
+namespace bssl {
+
+SSL_HANDSHAKE::SSL_HANDSHAKE(SSL *ssl_arg)
+ : ssl(ssl_arg),
+ scts_requested(0),
+ needs_psk_binder(0),
+ received_hello_retry_request(0),
+ accept_psk_mode(0),
+ cert_request(0),
+ certificate_status_expected(0),
+ ocsp_stapling_requested(0),
+ should_ack_sni(0),
+ in_false_start(0),
+ in_early_data(0),
+ early_data_offered(0),
+ can_early_read(0),
+ can_early_write(0),
+ next_proto_neg_seen(0),
+ ticket_expected(0),
+ extended_master_secret(0),
+ pending_private_key_op(0) {
+}
+
+SSL_HANDSHAKE::~SSL_HANDSHAKE() {
+ OPENSSL_cleanse(secret, sizeof(secret));
+ OPENSSL_cleanse(early_traffic_secret, sizeof(early_traffic_secret));
+ OPENSSL_cleanse(client_handshake_secret, sizeof(client_handshake_secret));
+ OPENSSL_cleanse(server_handshake_secret, sizeof(server_handshake_secret));
+ OPENSSL_cleanse(client_traffic_secret_0, sizeof(client_traffic_secret_0));
+ OPENSSL_cleanse(server_traffic_secret_0, sizeof(server_traffic_secret_0));
+ OPENSSL_free(cookie);
+ OPENSSL_free(key_share_bytes);
+ OPENSSL_free(ecdh_public_key);
+ OPENSSL_free(peer_sigalgs);
+ OPENSSL_free(peer_supported_group_list);
+ OPENSSL_free(peer_key);
+ OPENSSL_free(server_params);
+ ssl->ctx->x509_method->hs_flush_cached_ca_names(this);
+ OPENSSL_free(certificate_types);
+
+ if (key_block != NULL) {
+ OPENSSL_cleanse(key_block, key_block_len);
+ OPENSSL_free(key_block);
}
- return hs;
}
-void ssl_handshake_free(SSL_HANDSHAKE *hs) {
- if (hs == NULL) {
- return;
- }
-
- OPENSSL_cleanse(hs->secret, sizeof(hs->secret));
- OPENSSL_cleanse(hs->early_traffic_secret, sizeof(hs->early_traffic_secret));
- OPENSSL_cleanse(hs->client_handshake_secret,
- sizeof(hs->client_handshake_secret));
- OPENSSL_cleanse(hs->server_handshake_secret,
- sizeof(hs->server_handshake_secret));
- OPENSSL_cleanse(hs->client_traffic_secret_0,
- sizeof(hs->client_traffic_secret_0));
- OPENSSL_cleanse(hs->server_traffic_secret_0,
- sizeof(hs->server_traffic_secret_0));
- SSL_ECDH_CTX_cleanup(&hs->ecdh_ctx);
- SSL_TRANSCRIPT_cleanup(&hs->transcript);
- OPENSSL_free(hs->cookie);
- OPENSSL_free(hs->key_share_bytes);
- OPENSSL_free(hs->ecdh_public_key);
- SSL_SESSION_free(hs->new_session);
- SSL_SESSION_free(hs->early_session);
- OPENSSL_free(hs->peer_sigalgs);
- OPENSSL_free(hs->peer_supported_group_list);
- OPENSSL_free(hs->peer_key);
- OPENSSL_free(hs->server_params);
- OPENSSL_free(hs->peer_psk_identity_hint);
- sk_CRYPTO_BUFFER_pop_free(hs->ca_names, CRYPTO_BUFFER_free);
- hs->ssl->ctx->x509_method->hs_flush_cached_ca_names(hs);
- OPENSSL_free(hs->certificate_types);
-
- if (hs->key_block != NULL) {
- OPENSSL_cleanse(hs->key_block, hs->key_block_len);
- OPENSSL_free(hs->key_block);
- }
-
- OPENSSL_free(hs->hostname);
- EVP_PKEY_free(hs->peer_pubkey);
- EVP_PKEY_free(hs->local_pubkey);
- OPENSSL_free(hs);
+SSL_HANDSHAKE *ssl_handshake_new(SSL *ssl) {
+ UniquePtr<SSL_HANDSHAKE> hs = MakeUnique<SSL_HANDSHAKE>(ssl);
+ if (!hs ||
+ !hs->transcript.Init()) {
+ return nullptr;
+ }
+ return hs.release();
}
+void ssl_handshake_free(SSL_HANDSHAKE *hs) { Delete(hs); }
+
int ssl_check_message_type(SSL *ssl, int type) {
if (ssl->s3->tmp.message_type != type) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
@@ -270,7 +268,7 @@ int ssl3_add_message(SSL *ssl, uint8_t *msg, size_t len) {
if (ssl->server &&
ssl->s3->have_version &&
ssl->version == TLS1_3_RECORD_TYPE_EXPERIMENT_VERSION &&
- ssl->s3->aead_write_ctx == NULL) {
+ ssl->s3->aead_write_ctx->is_null_cipher()) {
type = SSL3_RT_PLAINTEXT_HANDSHAKE;
}
@@ -281,10 +279,10 @@ int ssl3_add_message(SSL *ssl, uint8_t *msg, size_t len) {
} while (added < len);
ssl_do_msg_callback(ssl, 1 /* write */, SSL3_RT_HANDSHAKE, msg, len);
- /* TODO(svaldez): Move this up a layer to fix abstraction for SSL_TRANSCRIPT
- * on hs. */
+ /* TODO(svaldez): Move this up a layer to fix abstraction for SSLTranscript on
+ * hs. */
if (ssl->s3->hs != NULL &&
- !SSL_TRANSCRIPT_update(&ssl->s3->hs->transcript, msg, len)) {
+ !ssl->s3->hs->transcript.Update(msg, len)) {
goto err;
}
ret = 1;
@@ -381,9 +379,8 @@ int ssl3_send_finished(SSL_HANDSHAKE *hs) {
uint8_t finished[EVP_MAX_MD_SIZE];
size_t finished_len;
- if (!SSL_TRANSCRIPT_finish_mac(&hs->transcript, finished, &finished_len,
- session, ssl->server,
- ssl3_protocol_version(ssl))) {
+ if (!hs->transcript.GetFinishedMAC(finished, &finished_len, session,
+ ssl->server, ssl3_protocol_version(ssl))) {
return 0;
}
@@ -411,12 +408,12 @@ int ssl3_send_finished(SSL_HANDSHAKE *hs) {
}
}
- CBB cbb, body;
- if (!ssl->method->init_message(ssl, &cbb, &body, SSL3_MT_FINISHED) ||
+ ScopedCBB cbb;
+ CBB body;
+ if (!ssl->method->init_message(ssl, cbb.get(), &body, SSL3_MT_FINISHED) ||
!CBB_add_bytes(&body, finished, finished_len) ||
- !ssl_add_message_cbb(ssl, &cbb)) {
+ !ssl_add_message_cbb(ssl, cbb.get())) {
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
- CBB_cleanup(&cbb);
return -1;
}
@@ -437,9 +434,9 @@ int ssl3_get_finished(SSL_HANDSHAKE *hs) {
/* Snapshot the finished hash before incorporating the new message. */
uint8_t finished[EVP_MAX_MD_SIZE];
size_t finished_len;
- if (!SSL_TRANSCRIPT_finish_mac(&hs->transcript, finished, &finished_len,
- SSL_get_session(ssl), !ssl->server,
- ssl3_protocol_version(ssl)) ||
+ if (!hs->transcript.GetFinishedMAC(finished, &finished_len,
+ SSL_get_session(ssl), !ssl->server,
+ ssl3_protocol_version(ssl)) ||
!ssl_hash_current_message(hs)) {
return -1;
}
@@ -476,12 +473,12 @@ int ssl3_get_finished(SSL_HANDSHAKE *hs) {
}
int ssl3_output_cert_chain(SSL *ssl) {
- CBB cbb, body;
- if (!ssl->method->init_message(ssl, &cbb, &body, SSL3_MT_CERTIFICATE) ||
+ ScopedCBB cbb;
+ CBB body;
+ if (!ssl->method->init_message(ssl, cbb.get(), &body, SSL3_MT_CERTIFICATE) ||
!ssl_add_cert_chain(ssl, &body) ||
- !ssl_add_message_cbb(ssl, &cbb)) {
+ !ssl_add_message_cbb(ssl, cbb.get())) {
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
- CBB_cleanup(&cbb);
return 0;
}
@@ -591,9 +588,8 @@ static int read_v2_client_hello(SSL *ssl) {
/* The V2ClientHello without the length is incorporated into the handshake
* hash. This is only ever called at the start of the handshake, so hs is
* guaranteed to be non-NULL. */
- if (!SSL_TRANSCRIPT_update(&ssl->s3->hs->transcript,
- CBS_data(&v2_client_hello),
- CBS_len(&v2_client_hello))) {
+ if (!ssl->s3->hs->transcript.Update(CBS_data(&v2_client_hello),
+ CBS_len(&v2_client_hello))) {
return -1;
}
@@ -636,19 +632,18 @@ static int read_v2_client_hello(SSL *ssl) {
2 /* cipher list length */ +
CBS_len(&cipher_specs) / 3 * 2 +
1 /* compression length */ + 1 /* compression */;
- CBB client_hello, hello_body, cipher_suites;
- CBB_zero(&client_hello);
+ ScopedCBB client_hello;
+ CBB hello_body, cipher_suites;
if (!BUF_MEM_reserve(ssl->init_buf, max_v3_client_hello) ||
- !CBB_init_fixed(&client_hello, (uint8_t *)ssl->init_buf->data,
+ !CBB_init_fixed(client_hello.get(), (uint8_t *)ssl->init_buf->data,
ssl->init_buf->max) ||
- !CBB_add_u8(&client_hello, SSL3_MT_CLIENT_HELLO) ||
- !CBB_add_u24_length_prefixed(&client_hello, &hello_body) ||
+ !CBB_add_u8(client_hello.get(), SSL3_MT_CLIENT_HELLO) ||
+ !CBB_add_u24_length_prefixed(client_hello.get(), &hello_body) ||
!CBB_add_u16(&hello_body, version) ||
!CBB_add_bytes(&hello_body, random, SSL3_RANDOM_SIZE) ||
/* No session id. */
!CBB_add_u8(&hello_body, 0) ||
!CBB_add_u16_length_prefixed(&hello_body, &cipher_suites)) {
- CBB_cleanup(&client_hello);
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
return -1;
}
@@ -657,7 +652,6 @@ static int read_v2_client_hello(SSL *ssl) {
while (CBS_len(&cipher_specs) > 0) {
uint32_t cipher_spec;
if (!CBS_get_u24(&cipher_specs, &cipher_spec)) {
- CBB_cleanup(&client_hello);
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
return -1;
}
@@ -667,16 +661,15 @@ static int read_v2_client_hello(SSL *ssl) {
continue;
}
if (!CBB_add_u16(&cipher_suites, cipher_spec)) {
- CBB_cleanup(&client_hello);
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
return -1;
}
}
/* Add the null compression scheme and finish. */
- if (!CBB_add_u8(&hello_body, 1) || !CBB_add_u8(&hello_body, 0) ||
- !CBB_finish(&client_hello, NULL, &ssl->init_buf->length)) {
- CBB_cleanup(&client_hello);
+ if (!CBB_add_u8(&hello_body, 1) ||
+ !CBB_add_u8(&hello_body, 0) ||
+ !CBB_finish(client_hello.get(), NULL, &ssl->init_buf->length)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
return -1;
}
@@ -759,7 +752,7 @@ int ssl_hash_current_message(SSL_HANDSHAKE *hs) {
CBS cbs;
hs->ssl->method->get_current_message(hs->ssl, &cbs);
- return SSL_TRANSCRIPT_update(&hs->transcript, CBS_data(&cbs), CBS_len(&cbs));
+ return hs->transcript.Update(CBS_data(&cbs), CBS_len(&cbs));
}
void ssl3_release_current_message(SSL *ssl, int free_buffer) {
@@ -830,3 +823,53 @@ int ssl_parse_extensions(const CBS *cbs, uint8_t *out_alert,
return 1;
}
+
+enum ssl_verify_result_t ssl_verify_peer_cert(SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
+ uint8_t alert = SSL_AD_CERTIFICATE_UNKNOWN;
+ enum ssl_verify_result_t ret;
+ if (ssl->custom_verify_callback != nullptr) {
+ ret = ssl->custom_verify_callback(ssl, &alert);
+ switch (ret) {
+ case ssl_verify_ok:
+ hs->new_session->verify_result = X509_V_OK;
+ break;
+ case ssl_verify_invalid:
+ hs->new_session->verify_result = X509_V_ERR_APPLICATION_VERIFICATION;
+ break;
+ case ssl_verify_retry:
+ break;
+ }
+ } else {
+ ret = ssl->ctx->x509_method->session_verify_cert_chain(
+ hs->new_session.get(), ssl, &alert)
+ ? ssl_verify_ok
+ : ssl_verify_invalid;
+ }
+
+ if (ret == ssl_verify_invalid) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_CERTIFICATE_VERIFY_FAILED);
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
+ }
+
+ return ret;
+}
+
+uint16_t ssl_get_grease_value(const SSL *ssl, enum ssl_grease_index_t index) {
+ /* Use the client_random or server_random for entropy. This both avoids
+ * calling |RAND_bytes| on a single byte repeatedly and ensures the values are
+ * deterministic. This allows the same ClientHello be sent twice for a
+ * HelloRetryRequest or the same group be advertised in both supported_groups
+ * and key_shares. */
+ uint16_t ret = ssl->server ? ssl->s3->server_random[index]
+ : ssl->s3->client_random[index];
+ /* The first four bytes of server_random are a timestamp prior to TLS 1.3, but
+ * servers have no fields to GREASE until TLS 1.3. */
+ assert(!ssl->server || ssl3_protocol_version(ssl) >= TLS1_3_VERSION);
+ /* This generates a random value of the form 0xωaωa, for all 0 ≤ ω < 16. */
+ ret = (ret & 0xf0) | 0x0a;
+ ret |= ret << 8;
+ return ret;
+}
+
+} // namespace bssl
diff --git a/src/ssl/s3_lib.cc b/src/ssl/s3_lib.cc
index 9548bbd4..cc9be2db 100644
--- a/src/ssl/s3_lib.cc
+++ b/src/ssl/s3_lib.cc
@@ -162,7 +162,15 @@
#include "internal.h"
+namespace bssl {
+
int ssl3_new(SSL *ssl) {
+ UniquePtr<SSLAEADContext> aead_read_ctx = SSLAEADContext::CreateNullCipher();
+ UniquePtr<SSLAEADContext> aead_write_ctx = SSLAEADContext::CreateNullCipher();
+ if (!aead_read_ctx || !aead_write_ctx) {
+ return 0;
+ }
+
SSL3_STATE *s3 = (SSL3_STATE *)OPENSSL_malloc(sizeof *s3);
if (s3 == NULL) {
return 0;
@@ -175,6 +183,8 @@ int ssl3_new(SSL *ssl) {
return 0;
}
+ s3->aead_read_ctx = aead_read_ctx.release();
+ s3->aead_write_ctx = aead_write_ctx.release();
ssl->s3 = s3;
/* Set the version to the highest supported version.
@@ -198,8 +208,8 @@ void ssl3_free(SSL *ssl) {
ssl_handshake_free(ssl->s3->hs);
OPENSSL_free(ssl->s3->next_proto_negotiated);
OPENSSL_free(ssl->s3->alpn_selected);
- SSL_AEAD_CTX_free(ssl->s3->aead_read_ctx);
- SSL_AEAD_CTX_free(ssl->s3->aead_write_ctx);
+ Delete(ssl->s3->aead_read_ctx);
+ Delete(ssl->s3->aead_write_ctx);
BUF_MEM_free(ssl->s3->pending_flight);
OPENSSL_cleanse(ssl->s3, sizeof *ssl->s3);
@@ -215,3 +225,5 @@ const struct ssl_cipher_preference_list_st *ssl_get_cipher_preferences(
return ssl->ctx->cipher_list;
}
+
+} // namespace bssl
diff --git a/src/ssl/s3_pkt.cc b/src/ssl/s3_pkt.cc
index 4ae2e34c..262df6df 100644
--- a/src/ssl/s3_pkt.cc
+++ b/src/ssl/s3_pkt.cc
@@ -122,6 +122,8 @@
#include "internal.h"
+namespace bssl {
+
static int do_ssl3_write(SSL *ssl, int type, const uint8_t *buf, unsigned len);
/* ssl3_get_record reads a new input record. On success, it places it in
@@ -192,7 +194,7 @@ again:
int ssl3_write_app_data(SSL *ssl, int *out_needs_handshake, const uint8_t *buf,
int len) {
assert(ssl_can_write(ssl));
- assert(ssl->s3->aead_write_ctx != NULL);
+ assert(!ssl->s3->aead_write_ctx->is_null_cipher());
*out_needs_handshake = 0;
@@ -372,7 +374,7 @@ static int consume_record(SSL *ssl, uint8_t *out, int len, int peek) {
int ssl3_read_app_data(SSL *ssl, int *out_got_handshake, uint8_t *buf, int len,
int peek) {
assert(ssl_can_read(ssl));
- assert(ssl->s3->aead_read_ctx != NULL);
+ assert(!ssl->s3->aead_read_ctx->is_null_cipher());
*out_got_handshake = 0;
ssl->method->release_current_message(ssl, 0 /* don't free buffer */);
@@ -517,7 +519,7 @@ int ssl3_read_handshake_bytes(SSL *ssl, uint8_t *buf, int len) {
* as-is. This manifests as an application data record when we expect
* handshake. Report a dedicated error code for this case. */
if (!ssl->server && rr->type == SSL3_RT_APPLICATION_DATA &&
- ssl->s3->aead_read_ctx == NULL) {
+ ssl->s3->aead_read_ctx->is_null_cipher()) {
OPENSSL_PUT_ERROR(SSL, SSL_R_APPLICATION_DATA_INSTEAD_OF_HANDSHAKE);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
return -1;
@@ -528,7 +530,7 @@ int ssl3_read_handshake_bytes(SSL *ssl, uint8_t *buf, int len) {
if (rr->type != SSL3_RT_HANDSHAKE &&
!(!ssl->server &&
ssl->tls13_variant == tls13_record_type_experiment &&
- ssl->s3->aead_read_ctx == NULL &&
+ ssl->s3->aead_read_ctx->is_null_cipher() &&
rr->type == SSL3_RT_PLAINTEXT_HANDSHAKE)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_RECORD);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
@@ -590,3 +592,5 @@ int ssl3_dispatch_alert(SSL *ssl) {
return 1;
}
+
+} // namespace bssl
diff --git a/src/ssl/ssl_aead_ctx.cc b/src/ssl/ssl_aead_ctx.cc
index 5264a653..3b8d1b25 100644
--- a/src/ssl/ssl_aead_ctx.cc
+++ b/src/ssl/ssl_aead_ctx.cc
@@ -25,12 +25,38 @@
#include "internal.h"
-SSL_AEAD_CTX *SSL_AEAD_CTX_new(enum evp_aead_direction_t direction,
- uint16_t version, int is_dtls,
- const SSL_CIPHER *cipher, const uint8_t *enc_key,
- size_t enc_key_len, const uint8_t *mac_key,
- size_t mac_key_len, const uint8_t *fixed_iv,
- size_t fixed_iv_len) {
+#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
+#define FUZZER_MODE true
+#else
+#define FUZZER_MODE false
+#endif
+
+namespace bssl {
+
+SSLAEADContext::SSLAEADContext(uint16_t version_arg,
+ const SSL_CIPHER *cipher_arg)
+ : cipher_(cipher_arg),
+ version_(version_arg),
+ variable_nonce_included_in_record_(false),
+ random_variable_nonce_(false),
+ omit_length_in_ad_(false),
+ omit_version_in_ad_(false),
+ omit_ad_(false),
+ xor_fixed_nonce_(false) {
+ OPENSSL_memset(fixed_nonce_, 0, sizeof(fixed_nonce_));
+}
+
+SSLAEADContext::~SSLAEADContext() {}
+
+UniquePtr<SSLAEADContext> SSLAEADContext::CreateNullCipher() {
+ return MakeUnique<SSLAEADContext>(0 /* version */, nullptr /* cipher */);
+}
+
+UniquePtr<SSLAEADContext> SSLAEADContext::Create(
+ enum evp_aead_direction_t direction, uint16_t version, int is_dtls,
+ const SSL_CIPHER *cipher, const uint8_t *enc_key, size_t enc_key_len,
+ const uint8_t *mac_key, size_t mac_key_len, const uint8_t *fixed_iv,
+ size_t fixed_iv_len) {
const EVP_AEAD *aead;
size_t expected_mac_key_len, expected_fixed_iv_len;
if (!ssl_cipher_get_evp_aead(&aead, &expected_mac_key_len,
@@ -40,7 +66,7 @@ SSL_AEAD_CTX *SSL_AEAD_CTX_new(enum evp_aead_direction_t direction,
expected_fixed_iv_len != fixed_iv_len ||
expected_mac_key_len != mac_key_len) {
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
- return 0;
+ return nullptr;
}
uint8_t merged_key[EVP_AEAD_MAX_KEY_LENGTH];
@@ -49,7 +75,7 @@ SSL_AEAD_CTX *SSL_AEAD_CTX_new(enum evp_aead_direction_t direction,
* suites). */
if (mac_key_len + enc_key_len + fixed_iv_len > sizeof(merged_key)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
- return 0;
+ return nullptr;
}
OPENSSL_memcpy(merged_key, mac_key, mac_key_len);
OPENSSL_memcpy(merged_key + mac_key_len, enc_key, enc_key_len);
@@ -60,306 +86,280 @@ SSL_AEAD_CTX *SSL_AEAD_CTX_new(enum evp_aead_direction_t direction,
enc_key_len += fixed_iv_len;
}
- SSL_AEAD_CTX *aead_ctx = (SSL_AEAD_CTX *)OPENSSL_malloc(sizeof(SSL_AEAD_CTX));
- if (aead_ctx == NULL) {
+ UniquePtr<SSLAEADContext> aead_ctx =
+ MakeUnique<SSLAEADContext>(version, cipher);
+ if (!aead_ctx) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- return NULL;
+ return nullptr;
}
- OPENSSL_memset(aead_ctx, 0, sizeof(SSL_AEAD_CTX));
- aead_ctx->cipher = cipher;
- aead_ctx->version = version;
if (!EVP_AEAD_CTX_init_with_direction(
- &aead_ctx->ctx, aead, enc_key, enc_key_len,
+ aead_ctx->ctx_.get(), aead, enc_key, enc_key_len,
EVP_AEAD_DEFAULT_TAG_LENGTH, direction)) {
- OPENSSL_free(aead_ctx);
- return NULL;
+ return nullptr;
}
assert(EVP_AEAD_nonce_length(aead) <= EVP_AEAD_MAX_NONCE_LENGTH);
static_assert(EVP_AEAD_MAX_NONCE_LENGTH < 256,
"variable_nonce_len doesn't fit in uint8_t");
- aead_ctx->variable_nonce_len = (uint8_t)EVP_AEAD_nonce_length(aead);
+ aead_ctx->variable_nonce_len_ = (uint8_t)EVP_AEAD_nonce_length(aead);
if (mac_key_len == 0) {
- assert(fixed_iv_len <= sizeof(aead_ctx->fixed_nonce));
- OPENSSL_memcpy(aead_ctx->fixed_nonce, fixed_iv, fixed_iv_len);
- aead_ctx->fixed_nonce_len = fixed_iv_len;
+ assert(fixed_iv_len <= sizeof(aead_ctx->fixed_nonce_));
+ OPENSSL_memcpy(aead_ctx->fixed_nonce_, fixed_iv, fixed_iv_len);
+ aead_ctx->fixed_nonce_len_ = fixed_iv_len;
if (cipher->algorithm_enc & SSL_CHACHA20POLY1305) {
/* The fixed nonce into the actual nonce (the sequence number). */
- aead_ctx->xor_fixed_nonce = 1;
- aead_ctx->variable_nonce_len = 8;
+ aead_ctx->xor_fixed_nonce_ = true;
+ aead_ctx->variable_nonce_len_ = 8;
} else {
/* The fixed IV is prepended to the nonce. */
- assert(fixed_iv_len <= aead_ctx->variable_nonce_len);
- aead_ctx->variable_nonce_len -= fixed_iv_len;
+ assert(fixed_iv_len <= aead_ctx->variable_nonce_len_);
+ aead_ctx->variable_nonce_len_ -= fixed_iv_len;
}
/* AES-GCM uses an explicit nonce. */
if (cipher->algorithm_enc & (SSL_AES128GCM | SSL_AES256GCM)) {
- aead_ctx->variable_nonce_included_in_record = 1;
+ aead_ctx->variable_nonce_included_in_record_ = true;
}
/* The TLS 1.3 construction XORs the fixed nonce into the sequence number
* and omits the additional data. */
if (version >= TLS1_3_VERSION) {
- aead_ctx->xor_fixed_nonce = 1;
- aead_ctx->variable_nonce_len = 8;
- aead_ctx->variable_nonce_included_in_record = 0;
- aead_ctx->omit_ad = 1;
- assert(fixed_iv_len >= aead_ctx->variable_nonce_len);
+ aead_ctx->xor_fixed_nonce_ = true;
+ aead_ctx->variable_nonce_len_ = 8;
+ aead_ctx->variable_nonce_included_in_record_ = false;
+ aead_ctx->omit_ad_ = true;
+ assert(fixed_iv_len >= aead_ctx->variable_nonce_len_);
}
} else {
assert(version < TLS1_3_VERSION);
- aead_ctx->variable_nonce_included_in_record = 1;
- aead_ctx->random_variable_nonce = 1;
- aead_ctx->omit_length_in_ad = 1;
- aead_ctx->omit_version_in_ad = (version == SSL3_VERSION);
+ aead_ctx->variable_nonce_included_in_record_ = true;
+ aead_ctx->random_variable_nonce_ = true;
+ aead_ctx->omit_length_in_ad_ = true;
+ aead_ctx->omit_version_in_ad_ = (version == SSL3_VERSION);
}
return aead_ctx;
}
-void SSL_AEAD_CTX_free(SSL_AEAD_CTX *aead) {
- if (aead == NULL) {
- return;
- }
- EVP_AEAD_CTX_cleanup(&aead->ctx);
- OPENSSL_free(aead);
-}
-
-size_t SSL_AEAD_CTX_explicit_nonce_len(const SSL_AEAD_CTX *aead) {
-#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
- aead = NULL;
-#endif
-
- if (aead != NULL && aead->variable_nonce_included_in_record) {
- return aead->variable_nonce_len;
+size_t SSLAEADContext::ExplicitNonceLen() const {
+ if (!FUZZER_MODE && variable_nonce_included_in_record_) {
+ return variable_nonce_len_;
}
return 0;
}
-size_t SSL_AEAD_CTX_max_suffix_len(const SSL_AEAD_CTX *aead,
- size_t extra_in_len) {
-#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
- aead = NULL;
-#endif
-
+size_t SSLAEADContext::MaxSuffixLen(size_t extra_in_len) const {
return extra_in_len +
- (aead == NULL ? 0 : EVP_AEAD_max_overhead(aead->ctx.aead));
+ (is_null_cipher() || FUZZER_MODE
+ ? 0
+ : EVP_AEAD_max_overhead(EVP_AEAD_CTX_aead(ctx_.get())));
}
-size_t SSL_AEAD_CTX_max_overhead(const SSL_AEAD_CTX *aead) {
- return SSL_AEAD_CTX_explicit_nonce_len(aead) +
- SSL_AEAD_CTX_max_suffix_len(aead, 0);
+size_t SSLAEADContext::MaxOverhead() const {
+ return ExplicitNonceLen() + MaxSuffixLen(0);
}
-/* ssl_aead_ctx_get_ad writes the additional data for |aead| into |out| and
- * returns the number of bytes written. */
-static size_t ssl_aead_ctx_get_ad(SSL_AEAD_CTX *aead, uint8_t out[13],
- uint8_t type, uint16_t wire_version,
- const uint8_t seqnum[8],
- size_t plaintext_len) {
- if (aead->omit_ad) {
+size_t SSLAEADContext::GetAdditionalData(uint8_t out[13], uint8_t type,
+ uint16_t wire_version,
+ const uint8_t seqnum[8],
+ size_t plaintext_len) {
+ if (omit_ad_) {
return 0;
}
OPENSSL_memcpy(out, seqnum, 8);
size_t len = 8;
out[len++] = type;
- if (!aead->omit_version_in_ad) {
- out[len++] = (uint8_t)(wire_version >> 8);
- out[len++] = (uint8_t)wire_version;
+ if (!omit_version_in_ad_) {
+ out[len++] = static_cast<uint8_t>((wire_version >> 8));
+ out[len++] = static_cast<uint8_t>(wire_version);
}
- if (!aead->omit_length_in_ad) {
- out[len++] = (uint8_t)(plaintext_len >> 8);
- out[len++] = (uint8_t)plaintext_len;
+ if (!omit_length_in_ad_) {
+ out[len++] = static_cast<uint8_t>((plaintext_len >> 8));
+ out[len++] = static_cast<uint8_t>(plaintext_len);
}
return len;
}
-int SSL_AEAD_CTX_open(SSL_AEAD_CTX *aead, CBS *out, uint8_t type,
- uint16_t wire_version, const uint8_t seqnum[8],
- uint8_t *in, size_t in_len) {
-#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
- aead = NULL;
-#endif
-
- if (aead == NULL) {
+bool SSLAEADContext::Open(CBS *out, uint8_t type, uint16_t wire_version,
+ const uint8_t seqnum[8], uint8_t *in, size_t in_len) {
+ if (is_null_cipher() || FUZZER_MODE) {
/* Handle the initial NULL cipher. */
CBS_init(out, in, in_len);
- return 1;
+ return true;
}
/* TLS 1.2 AEADs include the length in the AD and are assumed to have fixed
* overhead. Otherwise the parameter is unused. */
size_t plaintext_len = 0;
- if (!aead->omit_length_in_ad) {
- size_t overhead = SSL_AEAD_CTX_max_overhead(aead);
+ if (!omit_length_in_ad_) {
+ size_t overhead = MaxOverhead();
if (in_len < overhead) {
/* Publicly invalid. */
OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_PACKET_LENGTH);
- return 0;
+ return false;
}
plaintext_len = in_len - overhead;
}
uint8_t ad[13];
- size_t ad_len = ssl_aead_ctx_get_ad(aead, ad, type, wire_version, seqnum,
- plaintext_len);
+ size_t ad_len =
+ GetAdditionalData(ad, type, wire_version, seqnum, plaintext_len);
/* Assemble the nonce. */
uint8_t nonce[EVP_AEAD_MAX_NONCE_LENGTH];
size_t nonce_len = 0;
/* Prepend the fixed nonce, or left-pad with zeros if XORing. */
- if (aead->xor_fixed_nonce) {
- nonce_len = aead->fixed_nonce_len - aead->variable_nonce_len;
+ if (xor_fixed_nonce_) {
+ nonce_len = fixed_nonce_len_ - variable_nonce_len_;
OPENSSL_memset(nonce, 0, nonce_len);
} else {
- OPENSSL_memcpy(nonce, aead->fixed_nonce, aead->fixed_nonce_len);
- nonce_len += aead->fixed_nonce_len;
+ OPENSSL_memcpy(nonce, fixed_nonce_, fixed_nonce_len_);
+ nonce_len += fixed_nonce_len_;
}
/* Add the variable nonce. */
- if (aead->variable_nonce_included_in_record) {
- if (in_len < aead->variable_nonce_len) {
+ if (variable_nonce_included_in_record_) {
+ if (in_len < variable_nonce_len_) {
/* Publicly invalid. */
OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_PACKET_LENGTH);
- return 0;
+ return false;
}
- OPENSSL_memcpy(nonce + nonce_len, in, aead->variable_nonce_len);
- in += aead->variable_nonce_len;
- in_len -= aead->variable_nonce_len;
+ OPENSSL_memcpy(nonce + nonce_len, in, variable_nonce_len_);
+ in += variable_nonce_len_;
+ in_len -= variable_nonce_len_;
} else {
- assert(aead->variable_nonce_len == 8);
- OPENSSL_memcpy(nonce + nonce_len, seqnum, aead->variable_nonce_len);
+ assert(variable_nonce_len_ == 8);
+ OPENSSL_memcpy(nonce + nonce_len, seqnum, variable_nonce_len_);
}
- nonce_len += aead->variable_nonce_len;
+ nonce_len += variable_nonce_len_;
/* XOR the fixed nonce, if necessary. */
- if (aead->xor_fixed_nonce) {
- assert(nonce_len == aead->fixed_nonce_len);
- for (size_t i = 0; i < aead->fixed_nonce_len; i++) {
- nonce[i] ^= aead->fixed_nonce[i];
+ if (xor_fixed_nonce_) {
+ assert(nonce_len == fixed_nonce_len_);
+ for (size_t i = 0; i < fixed_nonce_len_; i++) {
+ nonce[i] ^= fixed_nonce_[i];
}
}
/* Decrypt in-place. */
size_t len;
- if (!EVP_AEAD_CTX_open(&aead->ctx, in, &len, in_len, nonce, nonce_len,
- in, in_len, ad, ad_len)) {
- return 0;
+ if (!EVP_AEAD_CTX_open(ctx_.get(), in, &len, in_len, nonce, nonce_len, in,
+ in_len, ad, ad_len)) {
+ return false;
}
CBS_init(out, in, len);
- return 1;
+ return true;
}
-int SSL_AEAD_CTX_seal_scatter(SSL_AEAD_CTX *aead, uint8_t *out_prefix,
- uint8_t *out, uint8_t *out_suffix,
- size_t *out_suffix_len, size_t max_out_suffix_len,
- uint8_t type, uint16_t wire_version,
- const uint8_t seqnum[8], const uint8_t *in,
- size_t in_len, const uint8_t *extra_in,
- size_t extra_in_len) {
-#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
- aead = NULL;
-#endif
-
+bool SSLAEADContext::SealScatter(uint8_t *out_prefix, uint8_t *out,
+ uint8_t *out_suffix, size_t *out_suffix_len,
+ size_t max_out_suffix_len, uint8_t type,
+ uint16_t wire_version, const uint8_t seqnum[8],
+ const uint8_t *in, size_t in_len,
+ const uint8_t *extra_in, size_t extra_in_len) {
if ((in != out && buffers_alias(in, in_len, out, in_len)) ||
buffers_alias(in, in_len, out_suffix, max_out_suffix_len)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_OUTPUT_ALIASES_INPUT);
- return 0;
+ return false;
}
if (extra_in_len > max_out_suffix_len) {
OPENSSL_PUT_ERROR(SSL, SSL_R_BUFFER_TOO_SMALL);
- return 0;
+ return false;
}
- if (aead == NULL) {
+ if (is_null_cipher() || FUZZER_MODE) {
/* Handle the initial NULL cipher. */
OPENSSL_memmove(out, in, in_len);
OPENSSL_memmove(out_suffix, extra_in, extra_in_len);
*out_suffix_len = extra_in_len;
- return 1;
+ return true;
}
uint8_t ad[13];
- size_t ad_len = ssl_aead_ctx_get_ad(aead, ad, type, wire_version, seqnum,
- in_len);
+ size_t ad_len = GetAdditionalData(ad, type, wire_version, seqnum, in_len);
/* Assemble the nonce. */
uint8_t nonce[EVP_AEAD_MAX_NONCE_LENGTH];
size_t nonce_len = 0;
/* Prepend the fixed nonce, or left-pad with zeros if XORing. */
- if (aead->xor_fixed_nonce) {
- nonce_len = aead->fixed_nonce_len - aead->variable_nonce_len;
+ if (xor_fixed_nonce_) {
+ nonce_len = fixed_nonce_len_ - variable_nonce_len_;
OPENSSL_memset(nonce, 0, nonce_len);
} else {
- OPENSSL_memcpy(nonce, aead->fixed_nonce, aead->fixed_nonce_len);
- nonce_len += aead->fixed_nonce_len;
+ OPENSSL_memcpy(nonce, fixed_nonce_, fixed_nonce_len_);
+ nonce_len += fixed_nonce_len_;
}
/* Select the variable nonce. */
- if (aead->random_variable_nonce) {
- assert(aead->variable_nonce_included_in_record);
- if (!RAND_bytes(nonce + nonce_len, aead->variable_nonce_len)) {
- return 0;
+ if (random_variable_nonce_) {
+ assert(variable_nonce_included_in_record_);
+ if (!RAND_bytes(nonce + nonce_len, variable_nonce_len_)) {
+ return false;
}
} else {
/* When sending we use the sequence number as the variable part of the
* nonce. */
- assert(aead->variable_nonce_len == 8);
- OPENSSL_memcpy(nonce + nonce_len, seqnum, aead->variable_nonce_len);
+ assert(variable_nonce_len_ == 8);
+ OPENSSL_memcpy(nonce + nonce_len, seqnum, variable_nonce_len_);
}
- nonce_len += aead->variable_nonce_len;
+ nonce_len += variable_nonce_len_;
/* Emit the variable nonce if included in the record. */
- if (aead->variable_nonce_included_in_record) {
- assert(!aead->xor_fixed_nonce);
- if (buffers_alias(in, in_len, out_prefix, aead->variable_nonce_len)) {
+ if (variable_nonce_included_in_record_) {
+ assert(!xor_fixed_nonce_);
+ if (buffers_alias(in, in_len, out_prefix, variable_nonce_len_)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_OUTPUT_ALIASES_INPUT);
- return 0;
+ return false;
}
- OPENSSL_memcpy(out_prefix, nonce + aead->fixed_nonce_len,
- aead->variable_nonce_len);
+ OPENSSL_memcpy(out_prefix, nonce + fixed_nonce_len_,
+ variable_nonce_len_);
}
/* XOR the fixed nonce, if necessary. */
- if (aead->xor_fixed_nonce) {
- assert(nonce_len == aead->fixed_nonce_len);
- for (size_t i = 0; i < aead->fixed_nonce_len; i++) {
- nonce[i] ^= aead->fixed_nonce[i];
+ if (xor_fixed_nonce_) {
+ assert(nonce_len == fixed_nonce_len_);
+ for (size_t i = 0; i < fixed_nonce_len_; i++) {
+ nonce[i] ^= fixed_nonce_[i];
}
}
- return EVP_AEAD_CTX_seal_scatter(&aead->ctx, out, out_suffix, out_suffix_len,
- max_out_suffix_len, nonce, nonce_len, in,
- in_len, extra_in, extra_in_len, ad, ad_len);
+ return !!EVP_AEAD_CTX_seal_scatter(
+ ctx_.get(), out, out_suffix, out_suffix_len, max_out_suffix_len, nonce,
+ nonce_len, in, in_len, extra_in, extra_in_len, ad, ad_len);
}
-int SSL_AEAD_CTX_seal(SSL_AEAD_CTX *aead, uint8_t *out, size_t *out_len,
- size_t max_out_len, uint8_t type, uint16_t wire_version,
- const uint8_t seqnum[8], const uint8_t *in,
- size_t in_len) {
- size_t prefix_len = SSL_AEAD_CTX_explicit_nonce_len(aead);
+bool SSLAEADContext::Seal(uint8_t *out, size_t *out_len, size_t max_out_len,
+ uint8_t type, uint16_t wire_version,
+ const uint8_t seqnum[8], const uint8_t *in,
+ size_t in_len) {
+ size_t prefix_len = ExplicitNonceLen();
if (in_len + prefix_len < in_len) {
OPENSSL_PUT_ERROR(CIPHER, SSL_R_RECORD_TOO_LARGE);
- return 0;
+ return false;
}
if (in_len + prefix_len > max_out_len) {
OPENSSL_PUT_ERROR(SSL, SSL_R_BUFFER_TOO_SMALL);
- return 0;
+ return false;
}
size_t suffix_len;
- if (!SSL_AEAD_CTX_seal_scatter(aead, out, out + prefix_len,
- out + prefix_len + in_len, &suffix_len,
- max_out_len - prefix_len - in_len, type,
- wire_version, seqnum, in, in_len, 0, 0)) {
- return 0;
+ if (!SealScatter(out, out + prefix_len, out + prefix_len + in_len,
+ &suffix_len, max_out_len - prefix_len - in_len, type,
+ wire_version, seqnum, in, in_len, 0, 0)) {
+ return false;
}
- assert(suffix_len <= SSL_AEAD_CTX_max_suffix_len(aead, 0));
+ assert(suffix_len <= MaxSuffixLen(0));
*out_len = prefix_len + in_len + suffix_len;
- return 1;
+ return true;
+}
+
+bool SSLAEADContext::GetIV(const uint8_t **out_iv, size_t *out_iv_len) const {
+ return !is_null_cipher() &&
+ EVP_AEAD_CTX_get_iv(ctx_.get(), out_iv, out_iv_len);
}
+
+} // namespace bssl
diff --git a/src/ssl/ssl_asn1.cc b/src/ssl/ssl_asn1.cc
index 1d6140e9..d360a7aa 100644
--- a/src/ssl/ssl_asn1.cc
+++ b/src/ssl/ssl_asn1.cc
@@ -102,6 +102,8 @@
#include "internal.h"
+namespace bssl {
+
/* An SSL_SESSION is serialized as the following ASN.1 structure:
*
* SSLSession ::= SEQUENCE {
@@ -196,15 +198,14 @@ static const int kEarlyALPNTag =
static int SSL_SESSION_to_bytes_full(const SSL_SESSION *in, uint8_t **out_data,
size_t *out_len, int for_ticket) {
- CBB cbb, session, child, child2;
-
if (in == NULL || in->cipher == NULL) {
return 0;
}
- CBB_zero(&cbb);
- if (!CBB_init(&cbb, 0) ||
- !CBB_add_asn1(&cbb, &session, CBS_ASN1_SEQUENCE) ||
+ ScopedCBB cbb;
+ CBB session, child, child2;
+ if (!CBB_init(cbb.get(), 0) ||
+ !CBB_add_asn1(cbb.get(), &session, CBS_ASN1_SEQUENCE) ||
!CBB_add_asn1_uint64(&session, kVersion) ||
!CBB_add_asn1_uint64(&session, in->ssl_version) ||
!CBB_add_asn1(&session, &child, CBS_ASN1_OCTETSTRING) ||
@@ -220,7 +221,7 @@ static int SSL_SESSION_to_bytes_full(const SSL_SESSION *in, uint8_t **out_data,
!CBB_add_asn1(&session, &child, kTimeoutTag) ||
!CBB_add_asn1_uint64(&child, in->timeout)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- goto err;
+ return 0;
}
/* The peer certificate is only serialized if the SHA-256 isn't
@@ -231,7 +232,7 @@ static int SSL_SESSION_to_bytes_full(const SSL_SESSION *in, uint8_t **out_data,
!CBB_add_bytes(&child, CRYPTO_BUFFER_data(buffer),
CRYPTO_BUFFER_len(buffer))) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- goto err;
+ return 0;
}
}
@@ -241,14 +242,14 @@ static int SSL_SESSION_to_bytes_full(const SSL_SESSION *in, uint8_t **out_data,
!CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) ||
!CBB_add_bytes(&child2, in->sid_ctx, in->sid_ctx_length)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- goto err;
+ return 0;
}
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, ERR_R_MALLOC_FAILURE);
- goto err;
+ return 0;
}
}
@@ -258,7 +259,7 @@ static int SSL_SESSION_to_bytes_full(const SSL_SESSION *in, uint8_t **out_data,
!CBB_add_bytes(&child2, (const uint8_t *)in->tlsext_hostname,
strlen(in->tlsext_hostname))) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- goto err;
+ return 0;
}
}
@@ -268,7 +269,7 @@ static int SSL_SESSION_to_bytes_full(const SSL_SESSION *in, uint8_t **out_data,
!CBB_add_bytes(&child2, (const uint8_t *)in->psk_identity,
strlen(in->psk_identity))) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- goto err;
+ return 0;
}
}
@@ -276,7 +277,7 @@ static int SSL_SESSION_to_bytes_full(const SSL_SESSION *in, uint8_t **out_data,
if (!CBB_add_asn1(&session, &child, kTicketLifetimeHintTag) ||
!CBB_add_asn1_uint64(&child, in->tlsext_tick_lifetime_hint)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- goto err;
+ return 0;
}
}
@@ -285,7 +286,7 @@ static int SSL_SESSION_to_bytes_full(const SSL_SESSION *in, uint8_t **out_data,
!CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) ||
!CBB_add_bytes(&child2, in->tlsext_tick, in->tlsext_ticklen)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- goto err;
+ return 0;
}
}
@@ -294,7 +295,7 @@ static int SSL_SESSION_to_bytes_full(const SSL_SESSION *in, uint8_t **out_data,
!CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) ||
!CBB_add_bytes(&child2, in->peer_sha256, sizeof(in->peer_sha256))) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- goto err;
+ return 0;
}
}
@@ -304,7 +305,7 @@ static int SSL_SESSION_to_bytes_full(const SSL_SESSION *in, uint8_t **out_data,
!CBB_add_bytes(&child2, in->original_handshake_hash,
in->original_handshake_hash_len)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- goto err;
+ return 0;
}
}
@@ -314,7 +315,7 @@ static int SSL_SESSION_to_bytes_full(const SSL_SESSION *in, uint8_t **out_data,
!CBB_add_bytes(&child2, in->tlsext_signed_cert_timestamp_list,
in->tlsext_signed_cert_timestamp_list_length)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- goto err;
+ return 0;
}
}
@@ -323,7 +324,7 @@ static int SSL_SESSION_to_bytes_full(const SSL_SESSION *in, uint8_t **out_data,
!CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) ||
!CBB_add_bytes(&child2, in->ocsp_response, in->ocsp_response_length)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- goto err;
+ return 0;
}
}
@@ -332,7 +333,7 @@ static int SSL_SESSION_to_bytes_full(const SSL_SESSION *in, uint8_t **out_data,
!CBB_add_asn1(&child, &child2, CBS_ASN1_BOOLEAN) ||
!CBB_add_u8(&child2, 0xff)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- goto err;
+ return 0;
}
}
@@ -340,7 +341,7 @@ static int SSL_SESSION_to_bytes_full(const SSL_SESSION *in, uint8_t **out_data,
(!CBB_add_asn1(&session, &child, kGroupIDTag) ||
!CBB_add_asn1_uint64(&child, in->group_id))) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- goto err;
+ return 0;
}
/* The certificate chain is only serialized if the leaf's SHA-256 isn't
@@ -350,14 +351,14 @@ static int SSL_SESSION_to_bytes_full(const SSL_SESSION *in, uint8_t **out_data,
sk_CRYPTO_BUFFER_num(in->certs) >= 2) {
if (!CBB_add_asn1(&session, &child, kCertChainTag)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- goto err;
+ return 0;
}
for (size_t i = 1; i < sk_CRYPTO_BUFFER_num(in->certs); i++) {
const CRYPTO_BUFFER *buffer = sk_CRYPTO_BUFFER_value(in->certs, i);
if (!CBB_add_bytes(&child, CRYPTO_BUFFER_data(buffer),
CRYPTO_BUFFER_len(buffer))) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- goto err;
+ return 0;
}
}
}
@@ -367,7 +368,7 @@ static int SSL_SESSION_to_bytes_full(const SSL_SESSION *in, uint8_t **out_data,
!CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) ||
!CBB_add_u32(&child2, in->ticket_age_add)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- goto err;
+ return 0;
}
}
@@ -376,7 +377,7 @@ static int SSL_SESSION_to_bytes_full(const SSL_SESSION *in, uint8_t **out_data,
!CBB_add_asn1(&child, &child2, CBS_ASN1_BOOLEAN) ||
!CBB_add_u8(&child2, 0x00)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- goto err;
+ return 0;
}
}
@@ -384,21 +385,21 @@ static int SSL_SESSION_to_bytes_full(const SSL_SESSION *in, uint8_t **out_data,
(!CBB_add_asn1(&session, &child, kPeerSignatureAlgorithmTag) ||
!CBB_add_asn1_uint64(&child, in->peer_signature_algorithm))) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- goto err;
+ return 0;
}
if (in->ticket_max_early_data != 0 &&
(!CBB_add_asn1(&session, &child, kTicketMaxEarlyDataTag) ||
!CBB_add_asn1_uint64(&child, in->ticket_max_early_data))) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- goto err;
+ return 0;
}
if (in->timeout != in->auth_timeout &&
(!CBB_add_asn1(&session, &child, kAuthTimeoutTag) ||
!CBB_add_asn1_uint64(&child, in->auth_timeout))) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- goto err;
+ return 0;
}
if (in->early_alpn) {
@@ -407,68 +408,15 @@ static int SSL_SESSION_to_bytes_full(const SSL_SESSION *in, uint8_t **out_data,
!CBB_add_bytes(&child2, (const uint8_t *)in->early_alpn,
in->early_alpn_len)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- goto err;
+ return 0;
}
}
- if (!CBB_finish(&cbb, out_data, out_len)) {
+ if (!CBB_finish(cbb.get(), out_data, out_len)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- goto err;
+ return 0;
}
return 1;
-
- err:
- CBB_cleanup(&cbb);
- return 0;
-}
-
-int SSL_SESSION_to_bytes(const SSL_SESSION *in, uint8_t **out_data,
- size_t *out_len) {
- if (in->not_resumable) {
- /* If the caller has an unresumable session, e.g. if |SSL_get_session| were
- * called on a TLS 1.3 or False Started connection, serialize with a
- * placeholder value so it is not accidentally deserialized into a resumable
- * one. */
- static const char kNotResumableSession[] = "NOT RESUMABLE";
-
- *out_len = strlen(kNotResumableSession);
- *out_data = (uint8_t *)BUF_memdup(kNotResumableSession, *out_len);
- if (*out_data == NULL) {
- return 0;
- }
-
- return 1;
- }
-
- return SSL_SESSION_to_bytes_full(in, out_data, out_len, 0);
-}
-
-int SSL_SESSION_to_bytes_for_ticket(const 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, ERR_R_OVERFLOW);
- return -1;
- }
-
- if (pp) {
- OPENSSL_memcpy(*pp, out, len);
- *pp += len;
- }
- OPENSSL_free(out);
-
- return len;
}
/* SSL_SESSION_parse_string gets an optional ASN.1 OCTET STRING
@@ -574,11 +522,12 @@ static int SSL_SESSION_parse_u16(CBS *cbs, uint16_t *out, unsigned tag,
return 1;
}
-SSL_SESSION *SSL_SESSION_parse(CBS *cbs, const SSL_X509_METHOD *x509_method,
- CRYPTO_BUFFER_POOL *pool) {
- SSL_SESSION *ret = ssl_session_new(x509_method);
- if (ret == NULL) {
- goto err;
+UniquePtr<SSL_SESSION> SSL_SESSION_parse(CBS *cbs,
+ const SSL_X509_METHOD *x509_method,
+ CRYPTO_BUFFER_POOL *pool) {
+ UniquePtr<SSL_SESSION> ret = ssl_session_new(x509_method);
+ if (!ret) {
+ return nullptr;
}
CBS session;
@@ -595,7 +544,7 @@ SSL_SESSION *SSL_SESSION_parse(CBS *cbs, const SSL_X509_METHOD *x509_method,
ssl_version > UINT16_MAX ||
!ssl_protocol_version_from_wire(&unused, ssl_version)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
- goto err;
+ return nullptr;
}
ret->ssl_version = ssl_version;
@@ -605,12 +554,12 @@ SSL_SESSION *SSL_SESSION_parse(CBS *cbs, const SSL_X509_METHOD *x509_method,
!CBS_get_u16(&cipher, &cipher_value) ||
CBS_len(&cipher) != 0) {
OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
- goto err;
+ return nullptr;
}
ret->cipher = SSL_get_cipher_by_value(cipher_value);
if (ret->cipher == NULL) {
OPENSSL_PUT_ERROR(SSL, SSL_R_UNSUPPORTED_CIPHER);
- goto err;
+ return nullptr;
}
CBS session_id, master_key;
@@ -619,7 +568,7 @@ SSL_SESSION *SSL_SESSION_parse(CBS *cbs, const SSL_X509_METHOD *x509_method,
!CBS_get_asn1(&session, &master_key, CBS_ASN1_OCTETSTRING) ||
CBS_len(&master_key) > SSL_MAX_MASTER_KEY_LENGTH) {
OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
- goto err;
+ return nullptr;
}
OPENSSL_memcpy(ret->session_id, CBS_data(&session_id), CBS_len(&session_id));
ret->session_id_length = CBS_len(&session_id);
@@ -634,7 +583,7 @@ SSL_SESSION *SSL_SESSION_parse(CBS *cbs, const SSL_X509_METHOD *x509_method,
!CBS_get_asn1_uint64(&child, &timeout) ||
timeout > UINT32_MAX) {
OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
- goto err;
+ return nullptr;
}
ret->timeout = (uint32_t)timeout;
@@ -644,7 +593,7 @@ SSL_SESSION *SSL_SESSION_parse(CBS *cbs, const SSL_X509_METHOD *x509_method,
if (!CBS_get_optional_asn1(&session, &peer, &has_peer, kPeerTag) ||
(has_peer && CBS_len(&peer) == 0)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
- goto err;
+ return nullptr;
}
/* |peer| is processed with the certificate chain. */
@@ -661,7 +610,7 @@ SSL_SESSION *SSL_SESSION_parse(CBS *cbs, const SSL_X509_METHOD *x509_method,
kTicketLifetimeHintTag, 0) ||
!SSL_SESSION_parse_octet_string(&session, &ret->tlsext_tick,
&ret->tlsext_ticklen, kTicketTag)) {
- goto err;
+ return nullptr;
}
if (CBS_peek_asn1_tag(&session, kPeerSHA256Tag)) {
@@ -671,7 +620,7 @@ SSL_SESSION *SSL_SESSION_parse(CBS *cbs, const SSL_X509_METHOD *x509_method,
CBS_len(&peer_sha256) != sizeof(ret->peer_sha256) ||
CBS_len(&child) != 0) {
OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
- goto err;
+ return nullptr;
}
OPENSSL_memcpy(ret->peer_sha256, CBS_data(&peer_sha256),
sizeof(ret->peer_sha256));
@@ -691,7 +640,7 @@ SSL_SESSION *SSL_SESSION_parse(CBS *cbs, const SSL_X509_METHOD *x509_method,
!SSL_SESSION_parse_octet_string(
&session, &ret->ocsp_response, &ret->ocsp_response_length,
kOCSPResponseTag)) {
- goto err;
+ return nullptr;
}
int extended_master_secret;
@@ -699,13 +648,13 @@ SSL_SESSION *SSL_SESSION_parse(CBS *cbs, const SSL_X509_METHOD *x509_method,
kExtendedMasterSecretTag,
0 /* default to false */)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
- goto err;
+ return nullptr;
}
ret->extended_master_secret = !!extended_master_secret;
if (!SSL_SESSION_parse_u16(&session, &ret->group_id, kGroupIDTag, 0)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
- goto err;
+ return nullptr;
}
CBS cert_chain;
@@ -715,17 +664,17 @@ SSL_SESSION *SSL_SESSION_parse(CBS *cbs, const SSL_X509_METHOD *x509_method,
kCertChainTag) ||
(has_cert_chain && CBS_len(&cert_chain) == 0)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
- goto err;
+ return nullptr;
}
if (has_cert_chain && !has_peer) {
OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
- goto err;
+ return nullptr;
}
if (has_peer || has_cert_chain) {
ret->certs = sk_CRYPTO_BUFFER_new_null();
if (ret->certs == NULL) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- goto err;
+ return nullptr;
}
if (has_peer) {
@@ -735,7 +684,7 @@ SSL_SESSION *SSL_SESSION_parse(CBS *cbs, const SSL_X509_METHOD *x509_method,
!sk_CRYPTO_BUFFER_push(ret->certs, buffer)) {
CRYPTO_BUFFER_free(buffer);
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- goto err;
+ return nullptr;
}
}
@@ -744,7 +693,7 @@ SSL_SESSION *SSL_SESSION_parse(CBS *cbs, const SSL_X509_METHOD *x509_method,
if (!CBS_get_any_asn1_element(&cert_chain, &cert, NULL, NULL) ||
CBS_len(&cert) == 0) {
OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
- goto err;
+ return nullptr;
}
/* TODO(agl): this should use the |SSL_CTX|'s pool. */
@@ -753,14 +702,14 @@ SSL_SESSION *SSL_SESSION_parse(CBS *cbs, const SSL_X509_METHOD *x509_method,
!sk_CRYPTO_BUFFER_push(ret->certs, buffer)) {
CRYPTO_BUFFER_free(buffer);
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- goto err;
+ return nullptr;
}
}
}
- if (!x509_method->session_cache_objects(ret)) {
+ if (!x509_method->session_cache_objects(ret.get())) {
OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
- goto err;
+ return nullptr;
}
CBS age_add;
@@ -770,7 +719,7 @@ SSL_SESSION *SSL_SESSION_parse(CBS *cbs, const SSL_X509_METHOD *x509_method,
(age_add_present &&
!CBS_get_u32(&age_add, &ret->ticket_age_add)) ||
CBS_len(&age_add) != 0) {
- goto err;
+ return nullptr;
}
ret->ticket_age_add_valid = age_add_present;
@@ -778,7 +727,7 @@ SSL_SESSION *SSL_SESSION_parse(CBS *cbs, const SSL_X509_METHOD *x509_method,
if (!CBS_get_optional_asn1_bool(&session, &is_server, kIsServerTag,
1 /* default to true */)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
- goto err;
+ return nullptr;
}
/* TODO: in time we can include |is_server| for servers too, then we can
enforce that client and server sessions are never mixed up. */
@@ -795,28 +744,77 @@ SSL_SESSION *SSL_SESSION_parse(CBS *cbs, const SSL_X509_METHOD *x509_method,
&ret->early_alpn_len, kEarlyALPNTag) ||
CBS_len(&session) != 0) {
OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
- goto err;
+ return nullptr;
}
return ret;
+}
+
+} // namespace bssl
+
+using namespace bssl;
+
+int SSL_SESSION_to_bytes(const SSL_SESSION *in, uint8_t **out_data,
+ size_t *out_len) {
+ if (in->not_resumable) {
+ /* If the caller has an unresumable session, e.g. if |SSL_get_session| were
+ * called on a TLS 1.3 or False Started connection, serialize with a
+ * placeholder value so it is not accidentally deserialized into a resumable
+ * one. */
+ static const char kNotResumableSession[] = "NOT RESUMABLE";
+
+ *out_len = strlen(kNotResumableSession);
+ *out_data = (uint8_t *)BUF_memdup(kNotResumableSession, *out_len);
+ if (*out_data == NULL) {
+ return 0;
+ }
+
+ return 1;
+ }
+
+ return SSL_SESSION_to_bytes_full(in, out_data, out_len, 0);
+}
-err:
- SSL_SESSION_free(ret);
- return NULL;
+int SSL_SESSION_to_bytes_for_ticket(const 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, ERR_R_OVERFLOW);
+ return -1;
+ }
+
+ if (pp) {
+ OPENSSL_memcpy(*pp, out, len);
+ *pp += len;
+ }
+ OPENSSL_free(out);
+
+ return len;
}
SSL_SESSION *SSL_SESSION_from_bytes(const uint8_t *in, size_t in_len,
const SSL_CTX *ctx) {
CBS cbs;
CBS_init(&cbs, in, in_len);
- SSL_SESSION *ret = SSL_SESSION_parse(&cbs, ctx->x509_method, ctx->pool);
- if (ret == NULL) {
+ UniquePtr<SSL_SESSION> ret =
+ SSL_SESSION_parse(&cbs, ctx->x509_method, ctx->pool);
+ if (!ret) {
return NULL;
}
if (CBS_len(&cbs) != 0) {
OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
- SSL_SESSION_free(ret);
return NULL;
}
- return ret;
+ return ret.release();
}
diff --git a/src/ssl/ssl_buffer.cc b/src/ssl/ssl_buffer.cc
index 579899b2..7f11b6f1 100644
--- a/src/ssl/ssl_buffer.cc
+++ b/src/ssl/ssl_buffer.cc
@@ -27,6 +27,8 @@
#include "internal.h"
+namespace bssl {
+
/* BIO uses int instead of size_t. No lengths will exceed uint16_t, so this will
* not overflow. */
static_assert(0xffff <= INT_MAX, "uint16_t does not fit in int");
@@ -289,3 +291,5 @@ int ssl_write_buffer_flush(SSL *ssl) {
void ssl_write_buffer_clear(SSL *ssl) {
clear_buffer(&ssl->s3->write_buffer);
}
+
+} // namespace bssl
diff --git a/src/ssl/ssl_cert.cc b/src/ssl/ssl_cert.cc
index df4b9c8c..4f457f61 100644
--- a/src/ssl/ssl_cert.cc
+++ b/src/ssl/ssl_cert.cc
@@ -118,6 +118,8 @@
#include <limits.h>
#include <string.h>
+#include <utility>
+
#include <openssl/bn.h>
#include <openssl/buf.h>
#include <openssl/bytestring.h>
@@ -131,6 +133,8 @@
#include "internal.h"
+namespace bssl {
+
CERT *ssl_cert_new(const SSL_X509_METHOD *x509_method) {
CERT *ret = (CERT *)OPENSSL_malloc(sizeof(CERT));
if (ret == NULL) {
@@ -252,19 +256,17 @@ enum leaf_cert_and_privkey_result_t {
* |leaf_cert_and_privkey_ok|. */
static enum leaf_cert_and_privkey_result_t check_leaf_cert_and_privkey(
CRYPTO_BUFFER *leaf_buffer, EVP_PKEY *privkey) {
- enum leaf_cert_and_privkey_result_t ret = leaf_cert_and_privkey_error;
-
CBS cert_cbs;
CRYPTO_BUFFER_init_CBS(leaf_buffer, &cert_cbs);
- EVP_PKEY *pubkey = ssl_cert_parse_pubkey(&cert_cbs);
- if (pubkey == NULL) {
+ UniquePtr<EVP_PKEY> pubkey = ssl_cert_parse_pubkey(&cert_cbs);
+ if (!pubkey) {
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
- goto out;
+ return leaf_cert_and_privkey_error;
}
if (!ssl_is_key_type_supported(pubkey->type)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_CERTIFICATE_TYPE);
- goto out;
+ return leaf_cert_and_privkey_error;
}
/* An ECC certificate may be usable for ECDH or ECDSA. We only support ECDSA
@@ -272,22 +274,17 @@ static enum leaf_cert_and_privkey_result_t check_leaf_cert_and_privkey(
if (pubkey->type == EVP_PKEY_EC &&
!ssl_cert_check_digital_signature_key_usage(&cert_cbs)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_CERTIFICATE_TYPE);
- goto out;
+ return leaf_cert_and_privkey_error;
}
if (privkey != NULL &&
/* Sanity-check that the private key and the certificate match. */
- !ssl_compare_public_and_private_key(pubkey, privkey)) {
+ !ssl_compare_public_and_private_key(pubkey.get(), privkey)) {
ERR_clear_error();
- ret = leaf_cert_and_privkey_mismatch;
- goto out;
+ return leaf_cert_and_privkey_mismatch;
}
- ret = leaf_cert_and_privkey_ok;
-
-out:
- EVP_PKEY_free(pubkey);
- return ret;
+ return leaf_cert_and_privkey_ok;
}
static int cert_set_chain_and_key(
@@ -340,20 +337,6 @@ static int cert_set_chain_and_key(
return 1;
}
-int SSL_set_chain_and_key(SSL *ssl, CRYPTO_BUFFER *const *certs,
- size_t num_certs, EVP_PKEY *privkey,
- const SSL_PRIVATE_KEY_METHOD *privkey_method) {
- return cert_set_chain_and_key(ssl->cert, certs, num_certs, privkey,
- privkey_method);
-}
-
-int SSL_CTX_set_chain_and_key(SSL_CTX *ctx, CRYPTO_BUFFER *const *certs,
- size_t num_certs, EVP_PKEY *privkey,
- const SSL_PRIVATE_KEY_METHOD *privkey_method) {
- return cert_set_chain_and_key(ctx->cert, certs, num_certs, privkey,
- privkey_method);
-}
-
int ssl_set_cert(CERT *cert, CRYPTO_BUFFER *buffer) {
switch (check_leaf_cert_and_privkey(buffer, cert->privatekey)) {
case leaf_cert_and_privkey_error:
@@ -393,54 +376,29 @@ int ssl_set_cert(CERT *cert, CRYPTO_BUFFER *buffer) {
return 1;
}
-int SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, size_t der_len,
- const uint8_t *der) {
- CRYPTO_BUFFER *buffer = CRYPTO_BUFFER_new(der, der_len, NULL);
- if (buffer == NULL) {
- return 0;
- }
-
- const int ok = ssl_set_cert(ctx->cert, buffer);
- CRYPTO_BUFFER_free(buffer);
- return ok;
-}
-
-int SSL_use_certificate_ASN1(SSL *ssl, const uint8_t *der, size_t der_len) {
- CRYPTO_BUFFER *buffer = CRYPTO_BUFFER_new(der, der_len, NULL);
- if (buffer == NULL) {
- return 0;
- }
-
- const int ok = ssl_set_cert(ssl->cert, buffer);
- CRYPTO_BUFFER_free(buffer);
- return ok;
-}
-
int ssl_has_certificate(const SSL *ssl) {
return ssl->cert->chain != NULL &&
sk_CRYPTO_BUFFER_value(ssl->cert->chain, 0) != NULL &&
ssl_has_private_key(ssl);
}
-STACK_OF(CRYPTO_BUFFER) *ssl_parse_cert_chain(uint8_t *out_alert,
- EVP_PKEY **out_pubkey,
- uint8_t *out_leaf_sha256,
- CBS *cbs,
- CRYPTO_BUFFER_POOL *pool) {
- *out_pubkey = NULL;
-
- STACK_OF(CRYPTO_BUFFER) *ret = sk_CRYPTO_BUFFER_new_null();
- if (ret == NULL) {
+UniquePtr<STACK_OF(CRYPTO_BUFFER)>
+ ssl_parse_cert_chain(uint8_t *out_alert, UniquePtr<EVP_PKEY> *out_pubkey,
+ uint8_t *out_leaf_sha256, CBS *cbs,
+ CRYPTO_BUFFER_POOL *pool) {
+ UniquePtr<EVP_PKEY> pubkey;
+ UniquePtr<STACK_OF(CRYPTO_BUFFER)> ret(sk_CRYPTO_BUFFER_new_null());
+ if (!ret) {
*out_alert = SSL_AD_INTERNAL_ERROR;
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- return NULL;
+ return nullptr;
}
CBS certificate_list;
if (!CBS_get_u24_length_prefixed(cbs, &certificate_list)) {
*out_alert = SSL_AD_DECODE_ERROR;
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
- goto err;
+ return nullptr;
}
while (CBS_len(&certificate_list) > 0) {
@@ -449,14 +407,14 @@ STACK_OF(CRYPTO_BUFFER) *ssl_parse_cert_chain(uint8_t *out_alert,
CBS_len(&certificate) == 0) {
*out_alert = SSL_AD_DECODE_ERROR;
OPENSSL_PUT_ERROR(SSL, SSL_R_CERT_LENGTH_MISMATCH);
- goto err;
+ return nullptr;
}
- if (sk_CRYPTO_BUFFER_num(ret) == 0) {
- *out_pubkey = ssl_cert_parse_pubkey(&certificate);
- if (*out_pubkey == NULL) {
+ if (sk_CRYPTO_BUFFER_num(ret.get()) == 0) {
+ pubkey = ssl_cert_parse_pubkey(&certificate);
+ if (!pubkey) {
*out_alert = SSL_AD_DECODE_ERROR;
- goto err;
+ return nullptr;
}
/* Retain the hash of the leaf certificate if requested. */
@@ -467,26 +425,17 @@ STACK_OF(CRYPTO_BUFFER) *ssl_parse_cert_chain(uint8_t *out_alert,
CRYPTO_BUFFER *buf =
CRYPTO_BUFFER_new_from_CBS(&certificate, pool);
- if (buf == NULL) {
- *out_alert = SSL_AD_DECODE_ERROR;
- goto err;
- }
-
- if (!sk_CRYPTO_BUFFER_push(ret, buf)) {
+ if (buf == NULL ||
+ !sk_CRYPTO_BUFFER_push(ret.get(), buf)) {
*out_alert = SSL_AD_INTERNAL_ERROR;
CRYPTO_BUFFER_free(buf);
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- goto err;
+ return nullptr;
}
}
+ *out_pubkey = std::move(pubkey);
return ret;
-
-err:
- EVP_PKEY_free(*out_pubkey);
- *out_pubkey = NULL;
- sk_CRYPTO_BUFFER_pop_free(ret, CRYPTO_BUFFER_free);
- return NULL;
}
int ssl_add_cert_chain(SSL *ssl, CBB *cbb) {
@@ -561,14 +510,14 @@ static int ssl_cert_skip_to_spki(const CBS *in, CBS *out_tbs_cert) {
return 1;
}
-EVP_PKEY *ssl_cert_parse_pubkey(const CBS *in) {
+UniquePtr<EVP_PKEY> ssl_cert_parse_pubkey(const CBS *in) {
CBS buf = *in, tbs_cert;
if (!ssl_cert_skip_to_spki(&buf, &tbs_cert)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_CANNOT_PARSE_LEAF_CERT);
- return NULL;
+ return nullptr;
}
- return EVP_parse_public_key(&tbs_cert);
+ return UniquePtr<EVP_PKEY>(EVP_parse_public_key(&tbs_cert));
}
int ssl_compare_public_and_private_key(const EVP_PKEY *pubkey,
@@ -593,6 +542,7 @@ int ssl_compare_public_and_private_key(const EVP_PKEY *pubkey,
break;
case -2:
OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_KEY_TYPE);
+ break;
default:
assert(0);
break;
@@ -615,15 +565,13 @@ int ssl_cert_check_private_key(const CERT *cert, const EVP_PKEY *privkey) {
CBS cert_cbs;
CRYPTO_BUFFER_init_CBS(sk_CRYPTO_BUFFER_value(cert->chain, 0), &cert_cbs);
- EVP_PKEY *pubkey = ssl_cert_parse_pubkey(&cert_cbs);
+ UniquePtr<EVP_PKEY> pubkey = ssl_cert_parse_pubkey(&cert_cbs);
if (!pubkey) {
OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_KEY_TYPE);
return 0;
}
- const int ok = ssl_compare_public_and_private_key(pubkey, privkey);
- EVP_PKEY_free(pubkey);
- return ok;
+ return ssl_compare_public_and_private_key(pubkey.get(), privkey);
}
int ssl_cert_check_digital_signature_key_usage(const CBS *in) {
@@ -703,22 +651,23 @@ parse_err:
return 0;
}
-STACK_OF(CRYPTO_BUFFER) *
- ssl_parse_client_CA_list(SSL *ssl, uint8_t *out_alert, CBS *cbs) {
+UniquePtr<STACK_OF(CRYPTO_BUFFER)> ssl_parse_client_CA_list(SSL *ssl,
+ uint8_t *out_alert,
+ CBS *cbs) {
CRYPTO_BUFFER_POOL *const pool = ssl->ctx->pool;
- STACK_OF(CRYPTO_BUFFER) *ret = sk_CRYPTO_BUFFER_new_null();
- if (ret == NULL) {
+ UniquePtr<STACK_OF(CRYPTO_BUFFER)> ret(sk_CRYPTO_BUFFER_new_null());
+ if (!ret) {
*out_alert = SSL_AD_INTERNAL_ERROR;
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- return NULL;
+ return nullptr;
}
CBS child;
if (!CBS_get_u16_length_prefixed(cbs, &child)) {
*out_alert = SSL_AD_DECODE_ERROR;
OPENSSL_PUT_ERROR(SSL, SSL_R_LENGTH_MISMATCH);
- goto err;
+ return nullptr;
}
while (CBS_len(&child) > 0) {
@@ -726,31 +675,27 @@ STACK_OF(CRYPTO_BUFFER) *
if (!CBS_get_u16_length_prefixed(&child, &distinguished_name)) {
*out_alert = SSL_AD_DECODE_ERROR;
OPENSSL_PUT_ERROR(SSL, SSL_R_CA_DN_TOO_LONG);
- goto err;
+ return nullptr;
}
CRYPTO_BUFFER *buffer =
CRYPTO_BUFFER_new_from_CBS(&distinguished_name, pool);
if (buffer == NULL ||
- !sk_CRYPTO_BUFFER_push(ret, buffer)) {
+ !sk_CRYPTO_BUFFER_push(ret.get(), buffer)) {
CRYPTO_BUFFER_free(buffer);
*out_alert = SSL_AD_INTERNAL_ERROR;
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- goto err;
+ return nullptr;
}
}
- if (!ssl->ctx->x509_method->check_client_CA_list(ret)) {
+ if (!ssl->ctx->x509_method->check_client_CA_list(ret.get())) {
*out_alert = SSL_AD_INTERNAL_ERROR;
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
- goto err;
+ return nullptr;
}
return ret;
-
-err:
- sk_CRYPTO_BUFFER_pop_free(ret, CRYPTO_BUFFER_free);
- return NULL;
}
int ssl_add_client_CA_list(SSL *ssl, CBB *cbb) {
@@ -780,31 +725,6 @@ int ssl_add_client_CA_list(SSL *ssl, CBB *cbb) {
return CBB_flush(cbb);
}
-void SSL_CTX_set_cert_cb(SSL_CTX *ctx, int (*cb)(SSL *ssl, void *arg),
- void *arg) {
- ssl_cert_set_cert_cb(ctx->cert, cb, arg);
-}
-
-void SSL_set_cert_cb(SSL *ssl, int (*cb)(SSL *ssl, void *arg), void *arg) {
- ssl_cert_set_cert_cb(ssl->cert, cb, arg);
-}
-
-STACK_OF(CRYPTO_BUFFER) *SSL_get0_peer_certificates(const SSL *ssl) {
- SSL_SESSION *session = SSL_get_session(ssl);
- if (session == NULL) {
- return NULL;
- }
-
- return session->certs;
-}
-
-STACK_OF(CRYPTO_BUFFER) *SSL_get0_server_requested_CAs(const SSL *ssl) {
- if (ssl->s3->hs == NULL) {
- return NULL;
- }
- return ssl->s3->hs->ca_names;
-}
-
int ssl_check_leaf_certificate(SSL_HANDSHAKE *hs, EVP_PKEY *pkey,
const CRYPTO_BUFFER *leaf) {
SSL *const ssl = hs->ssl;
@@ -860,11 +780,76 @@ int ssl_on_certificate_selected(SSL_HANDSHAKE *hs) {
CBS leaf;
CRYPTO_BUFFER_init_CBS(sk_CRYPTO_BUFFER_value(ssl->cert->chain, 0), &leaf);
- EVP_PKEY_free(hs->local_pubkey);
hs->local_pubkey = ssl_cert_parse_pubkey(&leaf);
return hs->local_pubkey != NULL;
}
+} // namespace bssl
+
+using namespace bssl;
+
+int SSL_set_chain_and_key(SSL *ssl, CRYPTO_BUFFER *const *certs,
+ size_t num_certs, EVP_PKEY *privkey,
+ const SSL_PRIVATE_KEY_METHOD *privkey_method) {
+ return cert_set_chain_and_key(ssl->cert, certs, num_certs, privkey,
+ privkey_method);
+}
+
+int SSL_CTX_set_chain_and_key(SSL_CTX *ctx, CRYPTO_BUFFER *const *certs,
+ size_t num_certs, EVP_PKEY *privkey,
+ const SSL_PRIVATE_KEY_METHOD *privkey_method) {
+ return cert_set_chain_and_key(ctx->cert, certs, num_certs, privkey,
+ privkey_method);
+}
+
+int SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, size_t der_len,
+ const uint8_t *der) {
+ CRYPTO_BUFFER *buffer = CRYPTO_BUFFER_new(der, der_len, NULL);
+ if (buffer == NULL) {
+ return 0;
+ }
+
+ const int ok = ssl_set_cert(ctx->cert, buffer);
+ CRYPTO_BUFFER_free(buffer);
+ return ok;
+}
+
+int SSL_use_certificate_ASN1(SSL *ssl, const uint8_t *der, size_t der_len) {
+ CRYPTO_BUFFER *buffer = CRYPTO_BUFFER_new(der, der_len, NULL);
+ if (buffer == NULL) {
+ return 0;
+ }
+
+ const int ok = ssl_set_cert(ssl->cert, buffer);
+ CRYPTO_BUFFER_free(buffer);
+ return ok;
+}
+
+void SSL_CTX_set_cert_cb(SSL_CTX *ctx, int (*cb)(SSL *ssl, void *arg),
+ void *arg) {
+ ssl_cert_set_cert_cb(ctx->cert, cb, arg);
+}
+
+void SSL_set_cert_cb(SSL *ssl, int (*cb)(SSL *ssl, void *arg), void *arg) {
+ ssl_cert_set_cert_cb(ssl->cert, cb, arg);
+}
+
+STACK_OF(CRYPTO_BUFFER) *SSL_get0_peer_certificates(const SSL *ssl) {
+ SSL_SESSION *session = SSL_get_session(ssl);
+ if (session == NULL) {
+ return NULL;
+ }
+
+ return session->certs;
+}
+
+STACK_OF(CRYPTO_BUFFER) *SSL_get0_server_requested_CAs(const SSL *ssl) {
+ if (ssl->s3->hs == NULL) {
+ return NULL;
+ }
+ return ssl->s3->hs->ca_names.get();
+}
+
static int set_signed_cert_timestamp_list(CERT *cert, const uint8_t *list,
size_t list_len) {
CBS sct_list;
@@ -903,3 +888,15 @@ int SSL_set_ocsp_response(SSL *ssl, const uint8_t *response,
ssl->cert->ocsp_response = CRYPTO_BUFFER_new(response, response_len, NULL);
return ssl->cert->ocsp_response != NULL;
}
+
+void SSL_CTX_set0_client_CAs(SSL_CTX *ctx, STACK_OF(CRYPTO_BUFFER) *name_list) {
+ ctx->x509_method->ssl_ctx_flush_cached_client_CA(ctx);
+ sk_CRYPTO_BUFFER_pop_free(ctx->client_CA, CRYPTO_BUFFER_free);
+ ctx->client_CA = name_list;
+}
+
+void SSL_set0_client_CAs(SSL *ssl, STACK_OF(CRYPTO_BUFFER) *name_list) {
+ ssl->ctx->x509_method->ssl_flush_cached_client_CA(ssl);
+ sk_CRYPTO_BUFFER_pop_free(ssl->client_CA, CRYPTO_BUFFER_free);
+ ssl->client_CA = name_list;
+}
diff --git a/src/ssl/ssl_cipher.cc b/src/ssl/ssl_cipher.cc
index c0f4122a..dbb4c752 100644
--- a/src/ssl/ssl_cipher.cc
+++ b/src/ssl/ssl_cipher.cc
@@ -154,6 +154,8 @@
#include "../crypto/internal.h"
+namespace bssl {
+
/* kCiphers is an array of all supported ciphers, sorted by id. */
static const SSL_CIPHER kCiphers[] = {
/* The RSA ciphers */
@@ -643,14 +645,6 @@ static int ssl_cipher_id_cmp(const void *in_a, const void *in_b) {
}
}
-const SSL_CIPHER *SSL_get_cipher_by_value(uint16_t value) {
- SSL_CIPHER c;
-
- c.id = 0x03000000L | value;
- return reinterpret_cast<const SSL_CIPHER *>(bsearch(
- &c, kCiphers, kCiphersLen, sizeof(SSL_CIPHER), ssl_cipher_id_cmp));
-}
-
int ssl_cipher_get_evp_aead(const EVP_AEAD **out_aead,
size_t *out_mac_secret_len,
size_t *out_fixed_iv_len,
@@ -1371,8 +1365,6 @@ err:
return 0;
}
-uint32_t SSL_CIPHER_get_id(const SSL_CIPHER *cipher) { return cipher->id; }
-
uint16_t ssl_cipher_get_value(const SSL_CIPHER *cipher) {
uint32_t id = cipher->id;
/* All ciphers are SSLv3. */
@@ -1380,6 +1372,68 @@ uint16_t ssl_cipher_get_value(const SSL_CIPHER *cipher) {
return id & 0xffff;
}
+uint32_t ssl_cipher_auth_mask_for_key(const EVP_PKEY *key) {
+ switch (EVP_PKEY_id(key)) {
+ case EVP_PKEY_RSA:
+ return SSL_aRSA;
+ case EVP_PKEY_EC:
+ case EVP_PKEY_ED25519:
+ /* Ed25519 keys in TLS 1.2 repurpose the ECDSA ciphers. */
+ return SSL_aECDSA;
+ default:
+ return 0;
+ }
+}
+
+int ssl_cipher_uses_certificate_auth(const SSL_CIPHER *cipher) {
+ return (cipher->algorithm_auth & SSL_aCERT) != 0;
+}
+
+int ssl_cipher_requires_server_key_exchange(const SSL_CIPHER *cipher) {
+ /* Ephemeral Diffie-Hellman key exchanges require a ServerKeyExchange. */
+ if (cipher->algorithm_mkey & SSL_kECDHE) {
+ return 1;
+ }
+
+ /* It is optional in all others. */
+ return 0;
+}
+
+size_t ssl_cipher_get_record_split_len(const SSL_CIPHER *cipher) {
+ size_t block_size;
+ switch (cipher->algorithm_enc) {
+ case SSL_3DES:
+ block_size = 8;
+ break;
+ case SSL_AES128:
+ case SSL_AES256:
+ block_size = 16;
+ break;
+ default:
+ return 0;
+ }
+
+ /* All supported TLS 1.0 ciphers use SHA-1. */
+ assert(cipher->algorithm_mac == SSL_SHA1);
+ size_t ret = 1 + SHA_DIGEST_LENGTH;
+ ret += block_size - (ret % block_size);
+ return ret;
+}
+
+} // namespace bssl
+
+using namespace bssl;
+
+const SSL_CIPHER *SSL_get_cipher_by_value(uint16_t value) {
+ SSL_CIPHER c;
+
+ c.id = 0x03000000L | value;
+ return reinterpret_cast<const SSL_CIPHER *>(bsearch(
+ &c, kCiphers, kCiphersLen, sizeof(SSL_CIPHER), ssl_cipher_id_cmp));
+}
+
+uint32_t SSL_CIPHER_get_id(const SSL_CIPHER *cipher) { return cipher->id; }
+
int SSL_CIPHER_is_AES(const SSL_CIPHER *cipher) {
return (cipher->algorithm_enc & SSL_AES) != 0;
}
@@ -1697,51 +1751,3 @@ int SSL_COMP_add_compression_method(int id, COMP_METHOD *cm) { return 1; }
const char *SSL_COMP_get_name(const COMP_METHOD *comp) { return NULL; }
void SSL_COMP_free_compression_methods(void) {}
-
-uint32_t ssl_cipher_auth_mask_for_key(const EVP_PKEY *key) {
- switch (EVP_PKEY_id(key)) {
- case EVP_PKEY_RSA:
- return SSL_aRSA;
- case EVP_PKEY_EC:
- case EVP_PKEY_ED25519:
- /* Ed25519 keys in TLS 1.2 repurpose the ECDSA ciphers. */
- return SSL_aECDSA;
- default:
- return 0;
- }
-}
-
-int ssl_cipher_uses_certificate_auth(const SSL_CIPHER *cipher) {
- return (cipher->algorithm_auth & SSL_aCERT) != 0;
-}
-
-int ssl_cipher_requires_server_key_exchange(const SSL_CIPHER *cipher) {
- /* Ephemeral Diffie-Hellman key exchanges require a ServerKeyExchange. */
- if (cipher->algorithm_mkey & SSL_kECDHE) {
- return 1;
- }
-
- /* It is optional in all others. */
- return 0;
-}
-
-size_t ssl_cipher_get_record_split_len(const SSL_CIPHER *cipher) {
- size_t block_size;
- switch (cipher->algorithm_enc) {
- case SSL_3DES:
- block_size = 8;
- break;
- case SSL_AES128:
- case SSL_AES256:
- block_size = 16;
- break;
- default:
- return 0;
- }
-
- /* All supported TLS 1.0 ciphers use SHA-1. */
- assert(cipher->algorithm_mac == SSL_SHA1);
- size_t ret = 1 + SHA_DIGEST_LENGTH;
- ret += block_size - (ret % block_size);
- return ret;
-}
diff --git a/src/ssl/ssl_ecdh.cc b/src/ssl/ssl_ecdh.cc
deleted file mode 100644
index fa1cbe97..00000000
--- a/src/ssl/ssl_ecdh.cc
+++ /dev/null
@@ -1,342 +0,0 @@
-/* Copyright (c) 2015, Google Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
-
-#include <openssl/ssl.h>
-
-#include <assert.h>
-#include <string.h>
-
-#include <openssl/bn.h>
-#include <openssl/bytestring.h>
-#include <openssl/curve25519.h>
-#include <openssl/ec.h>
-#include <openssl/err.h>
-#include <openssl/mem.h>
-#include <openssl/nid.h>
-
-#include "internal.h"
-#include "../crypto/internal.h"
-
-
-/* |EC_POINT| implementation. */
-
-static void ssl_ec_point_cleanup(SSL_ECDH_CTX *ctx) {
- BIGNUM *private_key = (BIGNUM *)ctx->data;
- BN_clear_free(private_key);
-}
-
-static int ssl_ec_point_offer(SSL_ECDH_CTX *ctx, CBB *out) {
- /* Set up a shared |BN_CTX| for all operations. */
- bssl::UniquePtr<BN_CTX> bn_ctx(BN_CTX_new());
- if (!bn_ctx) {
- return 0;
- }
- bssl::BN_CTXScope scope(bn_ctx.get());
-
- /* Generate a private key. */
- bssl::UniquePtr<EC_GROUP> group(EC_GROUP_new_by_curve_name(ctx->method->nid));
- bssl::UniquePtr<BIGNUM> private_key(BN_new());
- if (!group || !private_key ||
- !BN_rand_range_ex(private_key.get(), 1,
- EC_GROUP_get0_order(group.get()))) {
- return 0;
- }
-
- /* Compute the corresponding public key and serialize it. */
- bssl::UniquePtr<EC_POINT> public_key(EC_POINT_new(group.get()));
- if (!public_key ||
- !EC_POINT_mul(group.get(), public_key.get(), private_key.get(), NULL,
- NULL, bn_ctx.get()) ||
- !EC_POINT_point2cbb(out, group.get(), public_key.get(),
- POINT_CONVERSION_UNCOMPRESSED, bn_ctx.get())) {
- return 0;
- }
-
- assert(ctx->data == NULL);
- ctx->data = private_key.release();
- return 1;
-}
-
-static int ssl_ec_point_finish(SSL_ECDH_CTX *ctx, uint8_t **out_secret,
- size_t *out_secret_len, uint8_t *out_alert,
- const uint8_t *peer_key, size_t peer_key_len) {
- BIGNUM *private_key = (BIGNUM *)ctx->data;
- assert(private_key != NULL);
- *out_alert = SSL_AD_INTERNAL_ERROR;
-
- /* Set up a shared |BN_CTX| for all operations. */
- bssl::UniquePtr<BN_CTX> bn_ctx(BN_CTX_new());
- if (!bn_ctx) {
- return 0;
- }
- bssl::BN_CTXScope scope(bn_ctx.get());
-
- bssl::UniquePtr<EC_GROUP> group(EC_GROUP_new_by_curve_name(ctx->method->nid));
- if (!group) {
- return 0;
- }
-
- bssl::UniquePtr<EC_POINT> peer_point(EC_POINT_new(group.get()));
- bssl::UniquePtr<EC_POINT> result(EC_POINT_new(group.get()));
- BIGNUM *x = BN_CTX_get(bn_ctx.get());
- if (!peer_point || !result || !x) {
- return 0;
- }
-
- if (!EC_POINT_oct2point(group.get(), peer_point.get(), peer_key, peer_key_len,
- bn_ctx.get())) {
- *out_alert = SSL_AD_DECODE_ERROR;
- return 0;
- }
-
- /* Compute the x-coordinate of |peer_key| * |private_key|. */
- if (!EC_POINT_mul(group.get(), result.get(), NULL, peer_point.get(),
- private_key, bn_ctx.get()) ||
- !EC_POINT_get_affine_coordinates_GFp(group.get(), result.get(), x, NULL,
- bn_ctx.get())) {
- return 0;
- }
-
- /* Encode the x-coordinate left-padded with zeros. */
- size_t secret_len = (EC_GROUP_get_degree(group.get()) + 7) / 8;
- bssl::UniquePtr<uint8_t> secret((uint8_t *)OPENSSL_malloc(secret_len));
- if (!secret || !BN_bn2bin_padded(secret.get(), secret_len, x)) {
- return 0;
- }
-
- *out_secret = secret.release();
- *out_secret_len = secret_len;
- return 1;
-}
-
-static int ssl_ec_point_accept(SSL_ECDH_CTX *ctx, CBB *out_public_key,
- uint8_t **out_secret, size_t *out_secret_len,
- uint8_t *out_alert, const uint8_t *peer_key,
- size_t peer_key_len) {
- *out_alert = SSL_AD_INTERNAL_ERROR;
- if (!ssl_ec_point_offer(ctx, out_public_key) ||
- !ssl_ec_point_finish(ctx, out_secret, out_secret_len, out_alert, peer_key,
- peer_key_len)) {
- return 0;
- }
- return 1;
-}
-
-/* X25119 implementation. */
-
-static void ssl_x25519_cleanup(SSL_ECDH_CTX *ctx) {
- if (ctx->data == NULL) {
- return;
- }
- OPENSSL_cleanse(ctx->data, 32);
- OPENSSL_free(ctx->data);
-}
-
-static int ssl_x25519_offer(SSL_ECDH_CTX *ctx, CBB *out) {
- assert(ctx->data == NULL);
-
- ctx->data = OPENSSL_malloc(32);
- if (ctx->data == NULL) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- return 0;
- }
- uint8_t public_key[32];
- X25519_keypair(public_key, (uint8_t *)ctx->data);
- return CBB_add_bytes(out, public_key, sizeof(public_key));
-}
-
-static int ssl_x25519_finish(SSL_ECDH_CTX *ctx, uint8_t **out_secret,
- size_t *out_secret_len, uint8_t *out_alert,
- const uint8_t *peer_key, size_t peer_key_len) {
- assert(ctx->data != NULL);
- *out_alert = SSL_AD_INTERNAL_ERROR;
-
- uint8_t *secret = (uint8_t *)OPENSSL_malloc(32);
- if (secret == NULL) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- return 0;
- }
-
- if (peer_key_len != 32 ||
- !X25519(secret, (uint8_t *)ctx->data, peer_key)) {
- OPENSSL_free(secret);
- *out_alert = SSL_AD_DECODE_ERROR;
- OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_ECPOINT);
- return 0;
- }
-
- *out_secret = secret;
- *out_secret_len = 32;
- return 1;
-}
-
-static int ssl_x25519_accept(SSL_ECDH_CTX *ctx, CBB *out_public_key,
- uint8_t **out_secret, size_t *out_secret_len,
- uint8_t *out_alert, const uint8_t *peer_key,
- size_t peer_key_len) {
- *out_alert = SSL_AD_INTERNAL_ERROR;
- if (!ssl_x25519_offer(ctx, out_public_key) ||
- !ssl_x25519_finish(ctx, out_secret, out_secret_len, out_alert, peer_key,
- peer_key_len)) {
- return 0;
- }
- return 1;
-}
-
-
-static const SSL_ECDH_METHOD kMethods[] = {
- {
- NID_secp224r1,
- SSL_CURVE_SECP224R1,
- "P-224",
- ssl_ec_point_cleanup,
- ssl_ec_point_offer,
- ssl_ec_point_accept,
- ssl_ec_point_finish,
- },
- {
- NID_X9_62_prime256v1,
- SSL_CURVE_SECP256R1,
- "P-256",
- ssl_ec_point_cleanup,
- ssl_ec_point_offer,
- ssl_ec_point_accept,
- ssl_ec_point_finish,
- },
- {
- NID_secp384r1,
- SSL_CURVE_SECP384R1,
- "P-384",
- ssl_ec_point_cleanup,
- ssl_ec_point_offer,
- ssl_ec_point_accept,
- ssl_ec_point_finish,
- },
- {
- NID_secp521r1,
- SSL_CURVE_SECP521R1,
- "P-521",
- ssl_ec_point_cleanup,
- ssl_ec_point_offer,
- ssl_ec_point_accept,
- ssl_ec_point_finish,
- },
- {
- NID_X25519,
- SSL_CURVE_X25519,
- "X25519",
- ssl_x25519_cleanup,
- ssl_x25519_offer,
- ssl_x25519_accept,
- ssl_x25519_finish,
- },
-};
-
-static const SSL_ECDH_METHOD *method_from_group_id(uint16_t group_id) {
- for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kMethods); i++) {
- if (kMethods[i].group_id == group_id) {
- return &kMethods[i];
- }
- }
- return NULL;
-}
-
-static const SSL_ECDH_METHOD *method_from_nid(int nid) {
- for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kMethods); i++) {
- if (kMethods[i].nid == nid) {
- return &kMethods[i];
- }
- }
- return NULL;
-}
-
-static const SSL_ECDH_METHOD *method_from_name(const char *name, size_t len) {
- for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kMethods); i++) {
- if (len == strlen(kMethods[i].name) &&
- !strncmp(kMethods[i].name, name, len)) {
- return &kMethods[i];
- }
- }
- return NULL;
-}
-
-const char* SSL_get_curve_name(uint16_t group_id) {
- const SSL_ECDH_METHOD *method = method_from_group_id(group_id);
- if (method == NULL) {
- return NULL;
- }
- return method->name;
-}
-
-int ssl_nid_to_group_id(uint16_t *out_group_id, int nid) {
- const SSL_ECDH_METHOD *method = method_from_nid(nid);
- if (method == NULL) {
- return 0;
- }
- *out_group_id = method->group_id;
- return 1;
-}
-
-int ssl_name_to_group_id(uint16_t *out_group_id, const char *name, size_t len) {
- const SSL_ECDH_METHOD *method = method_from_name(name, len);
- if (method == NULL) {
- return 0;
- }
- *out_group_id = method->group_id;
- return 1;
-}
-
-int SSL_ECDH_CTX_init(SSL_ECDH_CTX *ctx, uint16_t group_id) {
- SSL_ECDH_CTX_cleanup(ctx);
-
- const SSL_ECDH_METHOD *method = method_from_group_id(group_id);
- if (method == NULL) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_UNSUPPORTED_ELLIPTIC_CURVE);
- return 0;
- }
- ctx->method = method;
- return 1;
-}
-
-void SSL_ECDH_CTX_cleanup(SSL_ECDH_CTX *ctx) {
- if (ctx->method == NULL) {
- return;
- }
- ctx->method->cleanup(ctx);
- ctx->method = NULL;
- ctx->data = NULL;
-}
-
-uint16_t SSL_ECDH_CTX_get_id(const SSL_ECDH_CTX *ctx) {
- return ctx->method->group_id;
-}
-
-int SSL_ECDH_CTX_offer(SSL_ECDH_CTX *ctx, CBB *out_public_key) {
- return ctx->method->offer(ctx, out_public_key);
-}
-
-int SSL_ECDH_CTX_accept(SSL_ECDH_CTX *ctx, CBB *out_public_key,
- uint8_t **out_secret, size_t *out_secret_len,
- uint8_t *out_alert, const uint8_t *peer_key,
- size_t peer_key_len) {
- return ctx->method->accept(ctx, out_public_key, out_secret, out_secret_len,
- out_alert, peer_key, peer_key_len);
-}
-
-int SSL_ECDH_CTX_finish(SSL_ECDH_CTX *ctx, uint8_t **out_secret,
- size_t *out_secret_len, uint8_t *out_alert,
- const uint8_t *peer_key, size_t peer_key_len) {
- return ctx->method->finish(ctx, out_secret, out_secret_len, out_alert,
- peer_key, peer_key_len);
-}
diff --git a/src/ssl/ssl_key_share.cc b/src/ssl/ssl_key_share.cc
new file mode 100644
index 00000000..eb615352
--- /dev/null
+++ b/src/ssl/ssl_key_share.cc
@@ -0,0 +1,245 @@
+/* Copyright (c) 2015, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <openssl/ssl.h>
+
+#include <assert.h>
+#include <string.h>
+
+#include <openssl/bn.h>
+#include <openssl/bytestring.h>
+#include <openssl/curve25519.h>
+#include <openssl/ec.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+#include <openssl/nid.h>
+
+#include "internal.h"
+#include "../crypto/internal.h"
+
+
+namespace bssl {
+
+namespace {
+
+class ECKeyShare : public SSLKeyShare {
+ public:
+ ECKeyShare(int nid, uint16_t group_id) : nid_(nid), group_id_(group_id) {}
+ ~ECKeyShare() override {}
+
+ uint16_t GroupID() const override { return group_id_; }
+
+ bool Offer(CBB *out) override {
+ assert(!private_key_);
+ /* Set up a shared |BN_CTX| for all operations. */
+ UniquePtr<BN_CTX> bn_ctx(BN_CTX_new());
+ if (!bn_ctx) {
+ return false;
+ }
+ BN_CTXScope scope(bn_ctx.get());
+
+ /* Generate a private key. */
+ UniquePtr<EC_GROUP> group(EC_GROUP_new_by_curve_name(nid_));
+ private_key_.reset(BN_new());
+ if (!group || !private_key_ ||
+ !BN_rand_range_ex(private_key_.get(), 1,
+ EC_GROUP_get0_order(group.get()))) {
+ return false;
+ }
+
+ /* Compute the corresponding public key and serialize it. */
+ UniquePtr<EC_POINT> public_key(EC_POINT_new(group.get()));
+ if (!public_key ||
+ !EC_POINT_mul(group.get(), public_key.get(), private_key_.get(), NULL,
+ NULL, bn_ctx.get()) ||
+ !EC_POINT_point2cbb(out, group.get(), public_key.get(),
+ POINT_CONVERSION_UNCOMPRESSED, bn_ctx.get())) {
+ return false;
+ }
+
+ return true;
+ }
+
+ bool Finish(uint8_t **out_secret, size_t *out_secret_len, uint8_t *out_alert,
+ const uint8_t *peer_key, size_t peer_key_len) override {
+ assert(private_key_);
+ *out_alert = SSL_AD_INTERNAL_ERROR;
+
+ /* Set up a shared |BN_CTX| for all operations. */
+ UniquePtr<BN_CTX> bn_ctx(BN_CTX_new());
+ if (!bn_ctx) {
+ return false;
+ }
+ BN_CTXScope scope(bn_ctx.get());
+
+ UniquePtr<EC_GROUP> group(EC_GROUP_new_by_curve_name(nid_));
+ if (!group) {
+ return false;
+ }
+
+ UniquePtr<EC_POINT> peer_point(EC_POINT_new(group.get()));
+ UniquePtr<EC_POINT> result(EC_POINT_new(group.get()));
+ BIGNUM *x = BN_CTX_get(bn_ctx.get());
+ if (!peer_point || !result || !x) {
+ return false;
+ }
+
+ if (!EC_POINT_oct2point(group.get(), peer_point.get(), peer_key,
+ peer_key_len, bn_ctx.get())) {
+ *out_alert = SSL_AD_DECODE_ERROR;
+ return false;
+ }
+
+ /* Compute the x-coordinate of |peer_key| * |private_key_|. */
+ if (!EC_POINT_mul(group.get(), result.get(), NULL, peer_point.get(),
+ private_key_.get(), bn_ctx.get()) ||
+ !EC_POINT_get_affine_coordinates_GFp(group.get(), result.get(), x, NULL,
+ bn_ctx.get())) {
+ return false;
+ }
+
+ /* Encode the x-coordinate left-padded with zeros. */
+ size_t secret_len = (EC_GROUP_get_degree(group.get()) + 7) / 8;
+ UniquePtr<uint8_t> secret((uint8_t *)OPENSSL_malloc(secret_len));
+ if (!secret || !BN_bn2bin_padded(secret.get(), secret_len, x)) {
+ return false;
+ }
+
+ *out_secret = secret.release();
+ *out_secret_len = secret_len;
+ return true;
+ }
+
+ private:
+ UniquePtr<BIGNUM> private_key_;
+ int nid_;
+ uint16_t group_id_;
+};
+
+class X25519KeyShare : public SSLKeyShare {
+ public:
+ X25519KeyShare() {}
+ ~X25519KeyShare() override {
+ OPENSSL_cleanse(private_key_, sizeof(private_key_));
+ }
+
+ uint16_t GroupID() const override { return SSL_CURVE_X25519; }
+
+ bool Offer(CBB *out) override {
+ uint8_t public_key[32];
+ X25519_keypair(public_key, private_key_);
+ return !!CBB_add_bytes(out, public_key, sizeof(public_key));
+ }
+
+ bool Finish(uint8_t **out_secret, size_t *out_secret_len, uint8_t *out_alert,
+ const uint8_t *peer_key, size_t peer_key_len) override {
+ *out_alert = SSL_AD_INTERNAL_ERROR;
+
+ UniquePtr<uint8_t> secret((uint8_t *)OPENSSL_malloc(32));
+ if (!secret) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+ return false;
+ }
+
+ if (peer_key_len != 32 || !X25519(secret.get(), private_key_, peer_key)) {
+ *out_alert = SSL_AD_DECODE_ERROR;
+ OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_ECPOINT);
+ return false;
+ }
+
+ *out_secret = secret.release();
+ *out_secret_len = 32;
+ return true;
+ }
+
+ private:
+ uint8_t private_key_[32];
+};
+
+const struct {
+ int nid;
+ uint16_t group_id;
+ const char name[8];
+} kNamedGroups[] = {
+ {NID_secp224r1, SSL_CURVE_SECP224R1, "P-224"},
+ {NID_X9_62_prime256v1, SSL_CURVE_SECP256R1, "P-256"},
+ {NID_secp384r1, SSL_CURVE_SECP384R1, "P-384"},
+ {NID_secp521r1, SSL_CURVE_SECP521R1, "P-521"},
+ {NID_X25519, SSL_CURVE_X25519, "X25519"},
+};
+
+} // namespace
+
+UniquePtr<SSLKeyShare> SSLKeyShare::Create(uint16_t group_id) {
+ switch (group_id) {
+ case SSL_CURVE_SECP224R1:
+ return UniquePtr<SSLKeyShare>(
+ New<ECKeyShare>(NID_secp224r1, SSL_CURVE_SECP224R1));
+ case SSL_CURVE_SECP256R1:
+ return UniquePtr<SSLKeyShare>(
+ New<ECKeyShare>(NID_X9_62_prime256v1, SSL_CURVE_SECP256R1));
+ case SSL_CURVE_SECP384R1:
+ return UniquePtr<SSLKeyShare>(
+ New<ECKeyShare>(NID_secp384r1, SSL_CURVE_SECP384R1));
+ case SSL_CURVE_SECP521R1:
+ return UniquePtr<SSLKeyShare>(
+ New<ECKeyShare>(NID_secp521r1, SSL_CURVE_SECP521R1));
+ case SSL_CURVE_X25519:
+ return UniquePtr<SSLKeyShare>(New<X25519KeyShare>());
+ default:
+ return nullptr;
+ }
+}
+
+bool SSLKeyShare::Accept(CBB *out_public_key, uint8_t **out_secret,
+ size_t *out_secret_len, uint8_t *out_alert,
+ const uint8_t *peer_key, size_t peer_key_len) {
+ *out_alert = SSL_AD_INTERNAL_ERROR;
+ return Offer(out_public_key) &&
+ Finish(out_secret, out_secret_len, out_alert, peer_key, peer_key_len);
+}
+
+int ssl_nid_to_group_id(uint16_t *out_group_id, int nid) {
+ for (const auto &group : kNamedGroups) {
+ if (group.nid == nid) {
+ *out_group_id = group.group_id;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+int ssl_name_to_group_id(uint16_t *out_group_id, const char *name, size_t len) {
+ for (const auto &group : kNamedGroups) {
+ if (len == strlen(group.name) &&
+ !strncmp(group.name, name, len)) {
+ *out_group_id = group.group_id;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+} // namespace bssl
+
+using namespace bssl;
+
+const char* SSL_get_curve_name(uint16_t group_id) {
+ for (const auto &group : kNamedGroups) {
+ if (group.group_id == group_id) {
+ return group.name;
+ }
+ }
+ return nullptr;
+}
diff --git a/src/ssl/ssl_lib.cc b/src/ssl/ssl_lib.cc
index 74419252..8e7bd885 100644
--- a/src/ssl/ssl_lib.cc
+++ b/src/ssl/ssl_lib.cc
@@ -162,6 +162,8 @@
#endif
+namespace bssl {
+
/* |SSL_R_UNKNOWN_PROTOCOL| is no longer emitted, but continue to define it
* to avoid downstream churn. */
OPENSSL_DECLARE_ERROR_REASON(SSL, UNKNOWN_PROTOCOL)
@@ -185,6 +187,224 @@ static CRYPTO_EX_DATA_CLASS g_ex_data_class_ssl =
static CRYPTO_EX_DATA_CLASS g_ex_data_class_ssl_ctx =
CRYPTO_EX_DATA_CLASS_INIT_WITH_APP_DATA;
+void ssl_reset_error_state(SSL *ssl) {
+ /* Functions which use |SSL_get_error| must reset I/O and error state on
+ * entry. */
+ ssl->rwstate = SSL_NOTHING;
+ ERR_clear_error();
+ ERR_clear_system_error();
+}
+
+int ssl_can_write(const SSL *ssl) {
+ return !SSL_in_init(ssl) || ssl->s3->hs->can_early_write;
+}
+
+int ssl_can_read(const SSL *ssl) {
+ return !SSL_in_init(ssl) || ssl->s3->hs->can_early_read;
+}
+
+void ssl_cipher_preference_list_free(
+ struct ssl_cipher_preference_list_st *cipher_list) {
+ if (cipher_list == NULL) {
+ return;
+ }
+ sk_SSL_CIPHER_free(cipher_list->ciphers);
+ OPENSSL_free(cipher_list->in_group_flags);
+ OPENSSL_free(cipher_list);
+}
+
+void ssl_update_cache(SSL_HANDSHAKE *hs, int mode) {
+ SSL *const ssl = hs->ssl;
+ SSL_CTX *ctx = ssl->session_ctx;
+ /* Never cache sessions with empty session IDs. */
+ if (ssl->s3->established_session->session_id_length == 0 ||
+ (ctx->session_cache_mode & mode) != mode) {
+ return;
+ }
+
+ /* Clients never use the internal session cache. */
+ int use_internal_cache = ssl->server && !(ctx->session_cache_mode &
+ SSL_SESS_CACHE_NO_INTERNAL_STORE);
+
+ /* A client may see new sessions on abbreviated handshakes if the server
+ * decides to renew the ticket. Once the handshake is completed, it should be
+ * inserted into the cache. */
+ if (ssl->s3->established_session != ssl->session ||
+ (!ssl->server && hs->ticket_expected)) {
+ if (use_internal_cache) {
+ SSL_CTX_add_session(ctx, ssl->s3->established_session);
+ }
+ if (ctx->new_session_cb != NULL) {
+ SSL_SESSION_up_ref(ssl->s3->established_session);
+ if (!ctx->new_session_cb(ssl, ssl->s3->established_session)) {
+ /* |new_session_cb|'s return value signals whether it took ownership. */
+ SSL_SESSION_free(ssl->s3->established_session);
+ }
+ }
+ }
+
+ if (use_internal_cache &&
+ !(ctx->session_cache_mode & SSL_SESS_CACHE_NO_AUTO_CLEAR)) {
+ /* Automatically flush the internal session cache every 255 connections. */
+ int flush_cache = 0;
+ CRYPTO_MUTEX_lock_write(&ctx->lock);
+ ctx->handshakes_since_cache_flush++;
+ if (ctx->handshakes_since_cache_flush >= 255) {
+ flush_cache = 1;
+ ctx->handshakes_since_cache_flush = 0;
+ }
+ CRYPTO_MUTEX_unlock_write(&ctx->lock);
+
+ if (flush_cache) {
+ struct OPENSSL_timeval now;
+ ssl_get_current_time(ssl, &now);
+ SSL_CTX_flush_sessions(ctx, now.tv_sec);
+ }
+ }
+}
+
+static int cbb_add_hex(CBB *cbb, const uint8_t *in, size_t in_len) {
+ static const char hextable[] = "0123456789abcdef";
+ uint8_t *out;
+
+ if (!CBB_add_space(cbb, &out, in_len * 2)) {
+ return 0;
+ }
+
+ for (size_t i = 0; i < in_len; i++) {
+ *(out++) = (uint8_t)hextable[in[i] >> 4];
+ *(out++) = (uint8_t)hextable[in[i] & 0xf];
+ }
+
+ return 1;
+}
+
+int ssl_log_secret(const SSL *ssl, const char *label, const uint8_t *secret,
+ size_t secret_len) {
+ if (ssl->ctx->keylog_callback == NULL) {
+ return 1;
+ }
+
+ ScopedCBB cbb;
+ uint8_t *out;
+ size_t out_len;
+ if (!CBB_init(cbb.get(), strlen(label) + 1 + SSL3_RANDOM_SIZE * 2 + 1 +
+ secret_len * 2 + 1) ||
+ !CBB_add_bytes(cbb.get(), (const uint8_t *)label, strlen(label)) ||
+ !CBB_add_bytes(cbb.get(), (const uint8_t *)" ", 1) ||
+ !cbb_add_hex(cbb.get(), ssl->s3->client_random, SSL3_RANDOM_SIZE) ||
+ !CBB_add_bytes(cbb.get(), (const uint8_t *)" ", 1) ||
+ !cbb_add_hex(cbb.get(), secret, secret_len) ||
+ !CBB_add_u8(cbb.get(), 0 /* NUL */) ||
+ !CBB_finish(cbb.get(), &out, &out_len)) {
+ return 0;
+ }
+
+ ssl->ctx->keylog_callback(ssl, (const char *)out);
+ OPENSSL_free(out);
+ return 1;
+}
+
+int ssl3_can_false_start(const SSL *ssl) {
+ const SSL_CIPHER *const cipher = SSL_get_current_cipher(ssl);
+
+ /* False Start only for TLS 1.2 with an ECDHE+AEAD cipher and ALPN or NPN. */
+ return !SSL_is_dtls(ssl) &&
+ SSL_version(ssl) == TLS1_2_VERSION &&
+ (ssl->s3->alpn_selected != NULL ||
+ ssl->s3->next_proto_negotiated != NULL) &&
+ cipher != NULL &&
+ cipher->algorithm_mkey == SSL_kECDHE &&
+ cipher->algorithm_mac == SSL_AEAD;
+}
+
+void ssl_do_info_callback(const SSL *ssl, int type, int value) {
+ void (*cb)(const SSL *ssl, int type, int value) = NULL;
+ if (ssl->info_callback != NULL) {
+ cb = ssl->info_callback;
+ } else if (ssl->ctx->info_callback != NULL) {
+ cb = ssl->ctx->info_callback;
+ }
+
+ if (cb != NULL) {
+ cb(ssl, type, value);
+ }
+}
+
+void ssl_do_msg_callback(SSL *ssl, int is_write, int content_type,
+ const void *buf, size_t len) {
+ if (ssl->msg_callback == NULL) {
+ return;
+ }
+
+ /* |version| is zero when calling for |SSL3_RT_HEADER| and |SSL2_VERSION| for
+ * a V2ClientHello. */
+ int version;
+ switch (content_type) {
+ case 0:
+ /* V2ClientHello */
+ version = SSL2_VERSION;
+ break;
+ case SSL3_RT_HEADER:
+ version = 0;
+ break;
+ default:
+ version = SSL_version(ssl);
+ }
+
+ ssl->msg_callback(is_write, version, content_type, buf, len, ssl,
+ ssl->msg_callback_arg);
+}
+
+void ssl_get_current_time(const SSL *ssl, struct OPENSSL_timeval *out_clock) {
+ if (ssl->ctx->current_time_cb != NULL) {
+ /* TODO(davidben): Update current_time_cb to use OPENSSL_timeval. See
+ * https://crbug.com/boringssl/155. */
+ struct timeval clock;
+ ssl->ctx->current_time_cb(ssl, &clock);
+ if (clock.tv_sec < 0) {
+ assert(0);
+ out_clock->tv_sec = 0;
+ out_clock->tv_usec = 0;
+ } else {
+ out_clock->tv_sec = (uint64_t)clock.tv_sec;
+ out_clock->tv_usec = (uint32_t)clock.tv_usec;
+ }
+ return;
+ }
+
+#if defined(BORINGSSL_UNSAFE_DETERMINISTIC_MODE)
+ out_clock->tv_sec = 1234;
+ out_clock->tv_usec = 1234;
+#elif defined(OPENSSL_WINDOWS)
+ struct _timeb time;
+ _ftime(&time);
+ if (time.time < 0) {
+ assert(0);
+ out_clock->tv_sec = 0;
+ out_clock->tv_usec = 0;
+ } else {
+ out_clock->tv_sec = time.time;
+ out_clock->tv_usec = time.millitm * 1000;
+ }
+#else
+ struct timeval clock;
+ gettimeofday(&clock, NULL);
+ if (clock.tv_sec < 0) {
+ assert(0);
+ out_clock->tv_sec = 0;
+ out_clock->tv_usec = 0;
+ } else {
+ out_clock->tv_sec = (uint64_t)clock.tv_sec;
+ out_clock->tv_usec = (uint32_t)clock.tv_usec;
+ }
+#endif
+}
+
+} // namespace bssl
+
+using namespace bssl;
+
int SSL_library_init(void) {
CRYPTO_library_init();
return 1;
@@ -392,6 +612,7 @@ SSL *SSL_new(SSL_CTX *ctx) {
ssl->msg_callback_arg = ctx->msg_callback_arg;
ssl->verify_mode = ctx->verify_mode;
ssl->verify_callback = ctx->default_verify_callback;
+ ssl->custom_verify_callback = ctx->custom_verify_callback;
ssl->retain_only_sha256_of_client_certs =
ctx->retain_only_sha256_of_client_certs;
@@ -561,14 +782,6 @@ BIO *SSL_get_rbio(const SSL *ssl) { return ssl->rbio; }
BIO *SSL_get_wbio(const SSL *ssl) { return ssl->wbio; }
-void ssl_reset_error_state(SSL *ssl) {
- /* Functions which use |SSL_get_error| must reset I/O and error state on
- * entry. */
- ssl->rwstate = SSL_NOTHING;
- ERR_clear_error();
- ERR_clear_system_error();
-}
-
int SSL_do_handshake(SSL *ssl) {
ssl_reset_error_state(ssl);
@@ -620,14 +833,6 @@ int SSL_accept(SSL *ssl) {
return SSL_do_handshake(ssl);
}
-int ssl_can_write(const SSL *ssl) {
- return !SSL_in_init(ssl) || ssl->s3->hs->can_early_write;
-}
-
-int ssl_can_read(const SSL *ssl) {
- return !SSL_in_init(ssl) || ssl->s3->hs->can_early_read;
-}
-
static int ssl_do_renegotiate(SSL *ssl) {
/* We do not accept renegotiations as a server or SSL 3.0. SSL 3.0 will be
* removed entirely in the future and requires retaining more data for
@@ -880,8 +1085,7 @@ void SSL_reset_early_data_reject(SSL *ssl) {
hs->wait = ssl_hs_ok;
hs->in_early_data = 0;
- SSL_SESSION_free(hs->early_session);
- hs->early_session = NULL;
+ hs->early_session.reset();
/* Discard any unfinished writes from the perspective of |SSL_write|'s
* retry. The handshake will transparently flush out the pending record
@@ -984,6 +1188,9 @@ int SSL_get_error(const SSL *ssl, int ret_code) {
case SSL_EARLY_DATA_REJECTED:
return SSL_ERROR_EARLY_DATA_REJECTED;
+
+ case SSL_CERTIFICATE_VERIFY:
+ return SSL_ERROR_WANT_CERTIFICATE_VERIFY;
}
return SSL_ERROR_SYSCALL;
@@ -1104,16 +1311,6 @@ const uint8_t *SSL_get0_session_id_context(const SSL *ssl, size_t *out_len) {
return ssl->cert->sid_ctx;
}
-void ssl_cipher_preference_list_free(
- struct ssl_cipher_preference_list_st *cipher_list) {
- if (cipher_list == NULL) {
- return;
- }
- sk_SSL_CIPHER_free(cipher_list->ciphers);
- OPENSSL_free(cipher_list->in_group_flags);
- OPENSSL_free(cipher_list);
-}
-
void SSL_certs_clear(SSL *ssl) { ssl_cert_clear_certs(ssl->cert); }
int SSL_get_fd(const SSL *ssl) { return SSL_get_rfd(ssl); }
@@ -1532,7 +1729,7 @@ const char *SSL_get_servername(const SSL *ssl, const int type) {
/* During the handshake, report the handshake value. */
if (ssl->s3->hs != NULL) {
- return ssl->s3->hs->hostname;
+ return ssl->s3->hs->hostname.get();
}
/* SSL_get_servername may also be called after the handshake to look up the
@@ -1554,12 +1751,22 @@ int SSL_get_servername_type(const SSL *ssl) {
return TLSEXT_NAMETYPE_host_name;
}
-void SSL_CTX_enable_signed_cert_timestamps(SSL_CTX *ctx) {
- ctx->signed_cert_timestamps_enabled = 1;
+void SSL_CTX_set_custom_verify(
+ SSL_CTX *ctx, int mode,
+ enum ssl_verify_result_t (*callback)(SSL *ssl, uint8_t *out_alert)) {
+ ctx->verify_mode = mode;
+ ctx->custom_verify_callback = callback;
}
-void SSL_CTX_i_promise_to_verify_certs_after_the_handshake(SSL_CTX *ctx) {
- ctx->i_promise_to_verify_certs_after_the_handshake = 1;
+void SSL_set_custom_verify(
+ SSL *ssl, int mode,
+ enum ssl_verify_result_t (*callback)(SSL *ssl, uint8_t *out_alert)) {
+ ssl->verify_mode = mode;
+ ssl->custom_verify_callback = callback;
+}
+
+void SSL_CTX_enable_signed_cert_timestamps(SSL_CTX *ctx) {
+ ctx->signed_cert_timestamps_enabled = 1;
}
void SSL_enable_signed_cert_timestamps(SSL *ssl) {
@@ -1806,56 +2013,6 @@ size_t SSL_get0_certificate_types(SSL *ssl, const uint8_t **out_types) {
return ssl->s3->hs->num_certificate_types;
}
-void ssl_update_cache(SSL_HANDSHAKE *hs, int mode) {
- SSL *const ssl = hs->ssl;
- SSL_CTX *ctx = ssl->session_ctx;
- /* Never cache sessions with empty session IDs. */
- if (ssl->s3->established_session->session_id_length == 0 ||
- (ctx->session_cache_mode & mode) != mode) {
- return;
- }
-
- /* Clients never use the internal session cache. */
- int use_internal_cache = ssl->server && !(ctx->session_cache_mode &
- SSL_SESS_CACHE_NO_INTERNAL_STORE);
-
- /* A client may see new sessions on abbreviated handshakes if the server
- * decides to renew the ticket. Once the handshake is completed, it should be
- * inserted into the cache. */
- if (ssl->s3->established_session != ssl->session ||
- (!ssl->server && hs->ticket_expected)) {
- if (use_internal_cache) {
- SSL_CTX_add_session(ctx, ssl->s3->established_session);
- }
- if (ctx->new_session_cb != NULL) {
- SSL_SESSION_up_ref(ssl->s3->established_session);
- if (!ctx->new_session_cb(ssl, ssl->s3->established_session)) {
- /* |new_session_cb|'s return value signals whether it took ownership. */
- SSL_SESSION_free(ssl->s3->established_session);
- }
- }
- }
-
- if (use_internal_cache &&
- !(ctx->session_cache_mode & SSL_SESS_CACHE_NO_AUTO_CLEAR)) {
- /* Automatically flush the internal session cache every 255 connections. */
- int flush_cache = 0;
- CRYPTO_MUTEX_lock_write(&ctx->lock);
- ctx->handshakes_since_cache_flush++;
- if (ctx->handshakes_since_cache_flush >= 255) {
- flush_cache = 1;
- ctx->handshakes_since_cache_flush = 0;
- }
- CRYPTO_MUTEX_unlock_write(&ctx->lock);
-
- if (flush_cache) {
- struct OPENSSL_timeval now;
- ssl_get_current_time(ssl, &now);
- SSL_CTX_flush_sessions(ctx, now.tv_sec);
- }
- }
-}
-
EVP_PKEY *SSL_get_privatekey(const SSL *ssl) {
if (ssl->cert != NULL) {
return ssl->cert->privatekey;
@@ -1873,10 +2030,7 @@ EVP_PKEY *SSL_CTX_get0_privatekey(const SSL_CTX *ctx) {
}
const SSL_CIPHER *SSL_get_current_cipher(const SSL *ssl) {
- if (ssl->s3->aead_write_ctx == NULL) {
- return NULL;
- }
- return ssl->s3->aead_write_ctx->cipher;
+ return ssl->s3->aead_write_ctx->cipher();
}
int SSL_session_reused(const SSL *ssl) {
@@ -2155,49 +2309,6 @@ void SSL_CTX_set_current_time_cb(SSL_CTX *ctx,
ctx->current_time_cb = cb;
}
-static int cbb_add_hex(CBB *cbb, const uint8_t *in, size_t in_len) {
- static const char hextable[] = "0123456789abcdef";
- uint8_t *out;
-
- if (!CBB_add_space(cbb, &out, in_len * 2)) {
- return 0;
- }
-
- for (size_t i = 0; i < in_len; i++) {
- *(out++) = (uint8_t)hextable[in[i] >> 4];
- *(out++) = (uint8_t)hextable[in[i] & 0xf];
- }
-
- return 1;
-}
-
-int ssl_log_secret(const SSL *ssl, const char *label, const uint8_t *secret,
- size_t secret_len) {
- if (ssl->ctx->keylog_callback == NULL) {
- return 1;
- }
-
- CBB cbb;
- uint8_t *out;
- size_t out_len;
- if (!CBB_init(&cbb, strlen(label) + 1 + SSL3_RANDOM_SIZE * 2 + 1 +
- secret_len * 2 + 1) ||
- !CBB_add_bytes(&cbb, (const uint8_t *)label, strlen(label)) ||
- !CBB_add_bytes(&cbb, (const uint8_t *)" ", 1) ||
- !cbb_add_hex(&cbb, ssl->s3->client_random, SSL3_RANDOM_SIZE) ||
- !CBB_add_bytes(&cbb, (const uint8_t *)" ", 1) ||
- !cbb_add_hex(&cbb, secret, secret_len) ||
- !CBB_add_u8(&cbb, 0 /* NUL */) ||
- !CBB_finish(&cbb, &out, &out_len)) {
- CBB_cleanup(&cbb);
- return 0;
- }
-
- ssl->ctx->keylog_callback(ssl, (const char *)out);
- OPENSSL_free(out);
- return 1;
-}
-
int SSL_is_init_finished(const SSL *ssl) {
return !SSL_in_init(ssl);
}
@@ -2225,19 +2336,6 @@ void SSL_get_structure_sizes(size_t *ssl_size, size_t *ssl_ctx_size,
*ssl_session_size = sizeof(SSL_SESSION);
}
-int ssl3_can_false_start(const SSL *ssl) {
- const SSL_CIPHER *const cipher = SSL_get_current_cipher(ssl);
-
- /* False Start only for TLS 1.2 with an ECDHE+AEAD cipher and ALPN or NPN. */
- return !SSL_is_dtls(ssl) &&
- SSL_version(ssl) == TLS1_2_VERSION &&
- (ssl->s3->alpn_selected != NULL ||
- ssl->s3->next_proto_negotiated != NULL) &&
- cipher != NULL &&
- cipher->algorithm_mkey == SSL_kECDHE &&
- cipher->algorithm_mac == SSL_AEAD;
-}
-
int SSL_is_server(const SSL *ssl) { return ssl->server; }
int SSL_is_dtls(const SSL *ssl) { return ssl->method->is_dtls; }
@@ -2259,15 +2357,9 @@ void SSL_set_renegotiate_mode(SSL *ssl, enum ssl_renegotiate_mode_t mode) {
int SSL_get_ivs(const SSL *ssl, const uint8_t **out_read_iv,
const uint8_t **out_write_iv, size_t *out_iv_len) {
- if (ssl->s3->aead_read_ctx == NULL || ssl->s3->aead_write_ctx == NULL) {
- return 0;
- }
-
size_t write_iv_len;
- if (!EVP_AEAD_CTX_get_iv(&ssl->s3->aead_read_ctx->ctx, out_read_iv,
- out_iv_len) ||
- !EVP_AEAD_CTX_get_iv(&ssl->s3->aead_write_ctx->ctx, out_write_iv,
- &write_iv_len) ||
+ if (!ssl->s3->aead_read_ctx->GetIV(out_read_iv, out_iv_len) ||
+ !ssl->s3->aead_write_ctx->GetIV(out_write_iv, &write_iv_len) ||
*out_iv_len != write_iv_len) {
return 0;
}
@@ -2408,44 +2500,6 @@ int SSL_clear(SSL *ssl) {
return 1;
}
-void ssl_do_info_callback(const SSL *ssl, int type, int value) {
- void (*cb)(const SSL *ssl, int type, int value) = NULL;
- if (ssl->info_callback != NULL) {
- cb = ssl->info_callback;
- } else if (ssl->ctx->info_callback != NULL) {
- cb = ssl->ctx->info_callback;
- }
-
- if (cb != NULL) {
- cb(ssl, type, value);
- }
-}
-
-void ssl_do_msg_callback(SSL *ssl, int is_write, int content_type,
- const void *buf, size_t len) {
- if (ssl->msg_callback == NULL) {
- return;
- }
-
- /* |version| is zero when calling for |SSL3_RT_HEADER| and |SSL2_VERSION| for
- * a V2ClientHello. */
- int version;
- switch (content_type) {
- case 0:
- /* V2ClientHello */
- version = SSL2_VERSION;
- break;
- case SSL3_RT_HEADER:
- version = 0;
- break;
- default:
- version = SSL_version(ssl);
- }
-
- ssl->msg_callback(is_write, version, content_type, buf, len, ssl,
- ssl->msg_callback_arg);
-}
-
int SSL_CTX_sess_connect(const SSL_CTX *ctx) { return 0; }
int SSL_CTX_sess_connect_good(const SSL_CTX *ctx) { return 0; }
int SSL_CTX_sess_connect_renegotiate(const SSL_CTX *ctx) { return 0; }
@@ -2488,51 +2542,6 @@ int SSL_set_tmp_ecdh(SSL *ssl, const EC_KEY *ec_key) {
return SSL_set1_curves(ssl, &nid, 1);
}
-void ssl_get_current_time(const SSL *ssl, struct OPENSSL_timeval *out_clock) {
- if (ssl->ctx->current_time_cb != NULL) {
- /* TODO(davidben): Update current_time_cb to use OPENSSL_timeval. See
- * https://crbug.com/boringssl/155. */
- struct timeval clock;
- ssl->ctx->current_time_cb(ssl, &clock);
- if (clock.tv_sec < 0) {
- assert(0);
- out_clock->tv_sec = 0;
- out_clock->tv_usec = 0;
- } else {
- out_clock->tv_sec = (uint64_t)clock.tv_sec;
- out_clock->tv_usec = (uint32_t)clock.tv_usec;
- }
- return;
- }
-
-#if defined(BORINGSSL_UNSAFE_DETERMINISTIC_MODE)
- out_clock->tv_sec = 1234;
- out_clock->tv_usec = 1234;
-#elif defined(OPENSSL_WINDOWS)
- struct _timeb time;
- _ftime(&time);
- if (time.time < 0) {
- assert(0);
- out_clock->tv_sec = 0;
- out_clock->tv_usec = 0;
- } else {
- out_clock->tv_sec = time.time;
- out_clock->tv_usec = time.millitm * 1000;
- }
-#else
- struct timeval clock;
- gettimeofday(&clock, NULL);
- if (clock.tv_sec < 0) {
- assert(0);
- out_clock->tv_sec = 0;
- out_clock->tv_usec = 0;
- } else {
- out_clock->tv_sec = (uint64_t)clock.tv_sec;
- out_clock->tv_usec = (uint32_t)clock.tv_usec;
- }
-#endif
-}
-
void SSL_CTX_set_ticket_aead_method(SSL_CTX *ctx,
const SSL_TICKET_AEAD_METHOD *aead_method) {
ctx->ticket_aead_method = aead_method;
diff --git a/src/ssl/ssl_privkey.cc b/src/ssl/ssl_privkey.cc
index 5b620f88..3e3fa94b 100644
--- a/src/ssl/ssl_privkey.cc
+++ b/src/ssl/ssl_privkey.cc
@@ -69,6 +69,8 @@
#include "../crypto/internal.h"
+namespace bssl {
+
int ssl_is_key_type_supported(int key_type) {
return key_type == EVP_PKEY_RSA || key_type == EVP_PKEY_EC ||
key_type == EVP_PKEY_ED25519;
@@ -94,6 +96,229 @@ static int ssl_set_pkey(CERT *cert, EVP_PKEY *pkey) {
return 1;
}
+typedef struct {
+ uint16_t sigalg;
+ int pkey_type;
+ int curve;
+ const EVP_MD *(*digest_func)(void);
+ char is_rsa_pss;
+} SSL_SIGNATURE_ALGORITHM;
+
+static const SSL_SIGNATURE_ALGORITHM kSignatureAlgorithms[] = {
+ {SSL_SIGN_RSA_PKCS1_MD5_SHA1, EVP_PKEY_RSA, NID_undef, &EVP_md5_sha1, 0},
+ {SSL_SIGN_RSA_PKCS1_SHA1, EVP_PKEY_RSA, NID_undef, &EVP_sha1, 0},
+ {SSL_SIGN_RSA_PKCS1_SHA256, EVP_PKEY_RSA, NID_undef, &EVP_sha256, 0},
+ {SSL_SIGN_RSA_PKCS1_SHA384, EVP_PKEY_RSA, NID_undef, &EVP_sha384, 0},
+ {SSL_SIGN_RSA_PKCS1_SHA512, EVP_PKEY_RSA, NID_undef, &EVP_sha512, 0},
+
+ {SSL_SIGN_RSA_PSS_SHA256, EVP_PKEY_RSA, NID_undef, &EVP_sha256, 1},
+ {SSL_SIGN_RSA_PSS_SHA384, EVP_PKEY_RSA, NID_undef, &EVP_sha384, 1},
+ {SSL_SIGN_RSA_PSS_SHA512, EVP_PKEY_RSA, NID_undef, &EVP_sha512, 1},
+
+ {SSL_SIGN_ECDSA_SHA1, EVP_PKEY_EC, NID_undef, &EVP_sha1, 0},
+ {SSL_SIGN_ECDSA_SECP256R1_SHA256, EVP_PKEY_EC, NID_X9_62_prime256v1,
+ &EVP_sha256, 0},
+ {SSL_SIGN_ECDSA_SECP384R1_SHA384, EVP_PKEY_EC, NID_secp384r1, &EVP_sha384,
+ 0},
+ {SSL_SIGN_ECDSA_SECP521R1_SHA512, EVP_PKEY_EC, NID_secp521r1, &EVP_sha512,
+ 0},
+
+ {SSL_SIGN_ED25519, EVP_PKEY_ED25519, NID_undef, NULL, 0},
+};
+
+static const SSL_SIGNATURE_ALGORITHM *get_signature_algorithm(uint16_t sigalg) {
+ for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kSignatureAlgorithms); i++) {
+ if (kSignatureAlgorithms[i].sigalg == sigalg) {
+ return &kSignatureAlgorithms[i];
+ }
+ }
+ return NULL;
+}
+
+int ssl_has_private_key(const SSL *ssl) {
+ return ssl->cert->privatekey != NULL || ssl->cert->key_method != NULL;
+}
+
+static int pkey_supports_algorithm(const SSL *ssl, EVP_PKEY *pkey,
+ uint16_t sigalg) {
+ const SSL_SIGNATURE_ALGORITHM *alg = get_signature_algorithm(sigalg);
+ if (alg == NULL ||
+ EVP_PKEY_id(pkey) != alg->pkey_type) {
+ return 0;
+ }
+
+ if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION) {
+ /* RSA keys may only be used with RSA-PSS. */
+ if (alg->pkey_type == EVP_PKEY_RSA && !alg->is_rsa_pss) {
+ return 0;
+ }
+
+ /* EC keys have a curve requirement. */
+ if (alg->pkey_type == EVP_PKEY_EC &&
+ (alg->curve == NID_undef ||
+ EC_GROUP_get_curve_name(
+ EC_KEY_get0_group(EVP_PKEY_get0_EC_KEY(pkey))) != alg->curve)) {
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+static int setup_ctx(SSL *ssl, EVP_MD_CTX *ctx, EVP_PKEY *pkey, uint16_t sigalg,
+ int is_verify) {
+ if (!pkey_supports_algorithm(ssl, pkey, sigalg)) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SIGNATURE_TYPE);
+ return 0;
+ }
+
+ const SSL_SIGNATURE_ALGORITHM *alg = get_signature_algorithm(sigalg);
+ const EVP_MD *digest = alg->digest_func != NULL ? alg->digest_func() : NULL;
+ EVP_PKEY_CTX *pctx;
+ if (is_verify) {
+ if (!EVP_DigestVerifyInit(ctx, &pctx, digest, NULL, pkey)) {
+ return 0;
+ }
+ } else if (!EVP_DigestSignInit(ctx, &pctx, digest, NULL, pkey)) {
+ return 0;
+ }
+
+ if (alg->is_rsa_pss) {
+ if (!EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) ||
+ !EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, -1 /* salt len = hash len */)) {
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+static int legacy_sign_digest_supported(const SSL_SIGNATURE_ALGORITHM *alg) {
+ return (alg->pkey_type == EVP_PKEY_EC || alg->pkey_type == EVP_PKEY_RSA) &&
+ !alg->is_rsa_pss;
+}
+
+static enum ssl_private_key_result_t legacy_sign(
+ SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out, uint16_t sigalg,
+ const uint8_t *in, size_t in_len) {
+ /* TODO(davidben): Remove support for |sign_digest|-only
+ * |SSL_PRIVATE_KEY_METHOD|s. */
+ const SSL_SIGNATURE_ALGORITHM *alg = get_signature_algorithm(sigalg);
+ if (alg == NULL || !legacy_sign_digest_supported(alg)) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_UNSUPPORTED_PROTOCOL_FOR_CUSTOM_KEY);
+ return ssl_private_key_failure;
+ }
+
+ const EVP_MD *md = alg->digest_func();
+ uint8_t hash[EVP_MAX_MD_SIZE];
+ unsigned hash_len;
+ if (!EVP_Digest(in, in_len, hash, &hash_len, md, NULL)) {
+ return ssl_private_key_failure;
+ }
+
+ return ssl->cert->key_method->sign_digest(ssl, out, out_len, max_out, md,
+ hash, hash_len);
+}
+
+enum ssl_private_key_result_t ssl_private_key_sign(
+ SSL_HANDSHAKE *hs, uint8_t *out, size_t *out_len, size_t max_out,
+ uint16_t sigalg, const uint8_t *in, size_t in_len) {
+ SSL *const ssl = hs->ssl;
+ if (ssl->cert->key_method != NULL) {
+ enum ssl_private_key_result_t ret;
+ if (hs->pending_private_key_op) {
+ ret = ssl->cert->key_method->complete(ssl, out, out_len, max_out);
+ } else {
+ ret = (ssl->cert->key_method->sign != NULL
+ ? ssl->cert->key_method->sign
+ : legacy_sign)(ssl, out, out_len, max_out, sigalg, in, in_len);
+ }
+ hs->pending_private_key_op = ret == ssl_private_key_retry;
+ return ret;
+ }
+
+ *out_len = max_out;
+ ScopedEVP_MD_CTX ctx;
+ if (!setup_ctx(ssl, ctx.get(), ssl->cert->privatekey, sigalg, 0 /* sign */) ||
+ !EVP_DigestSign(ctx.get(), out, out_len, in, in_len)) {
+ return ssl_private_key_failure;
+ }
+ return ssl_private_key_success;
+}
+
+int ssl_public_key_verify(SSL *ssl, const uint8_t *signature,
+ size_t signature_len, uint16_t sigalg, EVP_PKEY *pkey,
+ const uint8_t *in, size_t in_len) {
+ ScopedEVP_MD_CTX ctx;
+ return setup_ctx(ssl, ctx.get(), pkey, sigalg, 1 /* verify */) &&
+ EVP_DigestVerify(ctx.get(), signature, signature_len, in, in_len);
+}
+
+enum ssl_private_key_result_t ssl_private_key_decrypt(
+ SSL_HANDSHAKE *hs, uint8_t *out, size_t *out_len, size_t max_out,
+ const uint8_t *in, size_t in_len) {
+ SSL *const ssl = hs->ssl;
+ if (ssl->cert->key_method != NULL) {
+ enum ssl_private_key_result_t ret;
+ if (hs->pending_private_key_op) {
+ ret = ssl->cert->key_method->complete(ssl, out, out_len, max_out);
+ } else {
+ ret = ssl->cert->key_method->decrypt(ssl, out, out_len, max_out, in,
+ in_len);
+ }
+ hs->pending_private_key_op = ret == ssl_private_key_retry;
+ return ret;
+ }
+
+ RSA *rsa = EVP_PKEY_get0_RSA(ssl->cert->privatekey);
+ if (rsa == NULL) {
+ /* Decrypt operations are only supported for RSA keys. */
+ OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+ return ssl_private_key_failure;
+ }
+
+ /* Decrypt with no padding. PKCS#1 padding will be removed as part
+ * of the timing-sensitive code by the caller. */
+ if (!RSA_decrypt(rsa, out_len, out, max_out, in, in_len, RSA_NO_PADDING)) {
+ return ssl_private_key_failure;
+ }
+ return ssl_private_key_success;
+}
+
+int ssl_private_key_supports_signature_algorithm(SSL_HANDSHAKE *hs,
+ uint16_t sigalg) {
+ SSL *const ssl = hs->ssl;
+ if (!pkey_supports_algorithm(ssl, hs->local_pubkey.get(), sigalg)) {
+ return 0;
+ }
+
+ /* Ensure the RSA key is large enough for the hash. RSASSA-PSS requires that
+ * emLen be at least hLen + sLen + 2. Both hLen and sLen are the size of the
+ * hash in TLS. Reasonable RSA key sizes are large enough for the largest
+ * defined RSASSA-PSS algorithm, but 1024-bit RSA is slightly too small for
+ * SHA-512. 1024-bit RSA is sometimes used for test credentials, so check the
+ * size so that we can fall back to another algorithm in that case. */
+ const SSL_SIGNATURE_ALGORITHM *alg = get_signature_algorithm(sigalg);
+ if (alg->is_rsa_pss && (size_t)EVP_PKEY_size(hs->local_pubkey.get()) <
+ 2 * EVP_MD_size(alg->digest_func()) + 2) {
+ return 0;
+ }
+
+ /* Newer algorithms require message-based private keys.
+ * TODO(davidben): Remove this check when sign_digest is gone. */
+ if (ssl->cert->key_method != NULL &&
+ ssl->cert->key_method->sign == NULL &&
+ !legacy_sign_digest_supported(alg)) {
+ return 0;
+ }
+
+ return 1;
+}
+
+} // namespace bssl
+
+using namespace bssl;
+
int SSL_use_RSAPrivateKey(SSL *ssl, RSA *rsa) {
EVP_PKEY *pkey;
int ret;
@@ -119,7 +344,7 @@ int SSL_use_RSAPrivateKey(SSL *ssl, RSA *rsa) {
}
int SSL_use_RSAPrivateKey_ASN1(SSL *ssl, const uint8_t *der, size_t der_len) {
- bssl::UniquePtr<RSA> rsa(RSA_private_key_from_bytes(der, der_len));
+ UniquePtr<RSA> rsa(RSA_private_key_from_bytes(der, der_len));
if (!rsa) {
OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB);
return 0;
@@ -314,226 +539,3 @@ int SSL_set_private_key_digest_prefs(SSL *ssl, const int *digest_nids,
return 1;
}
-
-typedef struct {
- uint16_t sigalg;
- int pkey_type;
- int curve;
- const EVP_MD *(*digest_func)(void);
- char is_rsa_pss;
-} SSL_SIGNATURE_ALGORITHM;
-
-static const SSL_SIGNATURE_ALGORITHM kSignatureAlgorithms[] = {
- {SSL_SIGN_RSA_PKCS1_MD5_SHA1, EVP_PKEY_RSA, NID_undef, &EVP_md5_sha1, 0},
- {SSL_SIGN_RSA_PKCS1_SHA1, EVP_PKEY_RSA, NID_undef, &EVP_sha1, 0},
- {SSL_SIGN_RSA_PKCS1_SHA256, EVP_PKEY_RSA, NID_undef, &EVP_sha256, 0},
- {SSL_SIGN_RSA_PKCS1_SHA384, EVP_PKEY_RSA, NID_undef, &EVP_sha384, 0},
- {SSL_SIGN_RSA_PKCS1_SHA512, EVP_PKEY_RSA, NID_undef, &EVP_sha512, 0},
-
- {SSL_SIGN_RSA_PSS_SHA256, EVP_PKEY_RSA, NID_undef, &EVP_sha256, 1},
- {SSL_SIGN_RSA_PSS_SHA384, EVP_PKEY_RSA, NID_undef, &EVP_sha384, 1},
- {SSL_SIGN_RSA_PSS_SHA512, EVP_PKEY_RSA, NID_undef, &EVP_sha512, 1},
-
- {SSL_SIGN_ECDSA_SHA1, EVP_PKEY_EC, NID_undef, &EVP_sha1, 0},
- {SSL_SIGN_ECDSA_SECP256R1_SHA256, EVP_PKEY_EC, NID_X9_62_prime256v1,
- &EVP_sha256, 0},
- {SSL_SIGN_ECDSA_SECP384R1_SHA384, EVP_PKEY_EC, NID_secp384r1, &EVP_sha384,
- 0},
- {SSL_SIGN_ECDSA_SECP521R1_SHA512, EVP_PKEY_EC, NID_secp521r1, &EVP_sha512,
- 0},
-
- {SSL_SIGN_ED25519, EVP_PKEY_ED25519, NID_undef, NULL, 0},
-};
-
-static const SSL_SIGNATURE_ALGORITHM *get_signature_algorithm(uint16_t sigalg) {
- for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kSignatureAlgorithms); i++) {
- if (kSignatureAlgorithms[i].sigalg == sigalg) {
- return &kSignatureAlgorithms[i];
- }
- }
- return NULL;
-}
-
-int ssl_has_private_key(const SSL *ssl) {
- return ssl->cert->privatekey != NULL || ssl->cert->key_method != NULL;
-}
-
-static int pkey_supports_algorithm(const SSL *ssl, EVP_PKEY *pkey,
- uint16_t sigalg) {
- const SSL_SIGNATURE_ALGORITHM *alg = get_signature_algorithm(sigalg);
- if (alg == NULL ||
- EVP_PKEY_id(pkey) != alg->pkey_type) {
- return 0;
- }
-
- if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION) {
- /* RSA keys may only be used with RSA-PSS. */
- if (alg->pkey_type == EVP_PKEY_RSA && !alg->is_rsa_pss) {
- return 0;
- }
-
- /* EC keys have a curve requirement. */
- if (alg->pkey_type == EVP_PKEY_EC &&
- (alg->curve == NID_undef ||
- EC_GROUP_get_curve_name(
- EC_KEY_get0_group(EVP_PKEY_get0_EC_KEY(pkey))) != alg->curve)) {
- return 0;
- }
- }
-
- return 1;
-}
-
-static int setup_ctx(SSL *ssl, EVP_MD_CTX *ctx, EVP_PKEY *pkey, uint16_t sigalg,
- int is_verify) {
- if (!pkey_supports_algorithm(ssl, pkey, sigalg)) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SIGNATURE_TYPE);
- return 0;
- }
-
- const SSL_SIGNATURE_ALGORITHM *alg = get_signature_algorithm(sigalg);
- const EVP_MD *digest = alg->digest_func != NULL ? alg->digest_func() : NULL;
- EVP_PKEY_CTX *pctx;
- if (is_verify) {
- if (!EVP_DigestVerifyInit(ctx, &pctx, digest, NULL, pkey)) {
- return 0;
- }
- } else if (!EVP_DigestSignInit(ctx, &pctx, digest, NULL, pkey)) {
- return 0;
- }
-
- if (alg->is_rsa_pss) {
- if (!EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) ||
- !EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, -1 /* salt len = hash len */)) {
- return 0;
- }
- }
-
- return 1;
-}
-
-static int legacy_sign_digest_supported(const SSL_SIGNATURE_ALGORITHM *alg) {
- return (alg->pkey_type == EVP_PKEY_EC || alg->pkey_type == EVP_PKEY_RSA) &&
- !alg->is_rsa_pss;
-}
-
-static enum ssl_private_key_result_t legacy_sign(
- SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out, uint16_t sigalg,
- const uint8_t *in, size_t in_len) {
- /* TODO(davidben): Remove support for |sign_digest|-only
- * |SSL_PRIVATE_KEY_METHOD|s. */
- const SSL_SIGNATURE_ALGORITHM *alg = get_signature_algorithm(sigalg);
- if (alg == NULL || !legacy_sign_digest_supported(alg)) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_UNSUPPORTED_PROTOCOL_FOR_CUSTOM_KEY);
- return ssl_private_key_failure;
- }
-
- const EVP_MD *md = alg->digest_func();
- uint8_t hash[EVP_MAX_MD_SIZE];
- unsigned hash_len;
- if (!EVP_Digest(in, in_len, hash, &hash_len, md, NULL)) {
- return ssl_private_key_failure;
- }
-
- return ssl->cert->key_method->sign_digest(ssl, out, out_len, max_out, md,
- hash, hash_len);
-}
-
-enum ssl_private_key_result_t ssl_private_key_sign(
- SSL_HANDSHAKE *hs, uint8_t *out, size_t *out_len, size_t max_out,
- uint16_t sigalg, const uint8_t *in, size_t in_len) {
- SSL *const ssl = hs->ssl;
- if (ssl->cert->key_method != NULL) {
- enum ssl_private_key_result_t ret;
- if (hs->pending_private_key_op) {
- ret = ssl->cert->key_method->complete(ssl, out, out_len, max_out);
- } else {
- ret = (ssl->cert->key_method->sign != NULL
- ? ssl->cert->key_method->sign
- : legacy_sign)(ssl, out, out_len, max_out, sigalg, in, in_len);
- }
- hs->pending_private_key_op = ret == ssl_private_key_retry;
- return ret;
- }
-
- *out_len = max_out;
- EVP_MD_CTX ctx;
- EVP_MD_CTX_init(&ctx);
- int ret = setup_ctx(ssl, &ctx, ssl->cert->privatekey, sigalg, 0 /* sign */) &&
- EVP_DigestSign(&ctx, out, out_len, in, in_len);
- EVP_MD_CTX_cleanup(&ctx);
- return ret ? ssl_private_key_success : ssl_private_key_failure;
-}
-
-int ssl_public_key_verify(SSL *ssl, const uint8_t *signature,
- size_t signature_len, uint16_t sigalg, EVP_PKEY *pkey,
- const uint8_t *in, size_t in_len) {
- EVP_MD_CTX ctx;
- EVP_MD_CTX_init(&ctx);
- int ret = setup_ctx(ssl, &ctx, pkey, sigalg, 1 /* verify */) &&
- EVP_DigestVerify(&ctx, signature, signature_len, in, in_len);
- EVP_MD_CTX_cleanup(&ctx);
- return ret;
-}
-
-enum ssl_private_key_result_t ssl_private_key_decrypt(
- SSL_HANDSHAKE *hs, uint8_t *out, size_t *out_len, size_t max_out,
- const uint8_t *in, size_t in_len) {
- SSL *const ssl = hs->ssl;
- if (ssl->cert->key_method != NULL) {
- enum ssl_private_key_result_t ret;
- if (hs->pending_private_key_op) {
- ret = ssl->cert->key_method->complete(ssl, out, out_len, max_out);
- } else {
- ret = ssl->cert->key_method->decrypt(ssl, out, out_len, max_out, in,
- in_len);
- }
- hs->pending_private_key_op = ret == ssl_private_key_retry;
- return ret;
- }
-
- RSA *rsa = EVP_PKEY_get0_RSA(ssl->cert->privatekey);
- if (rsa == NULL) {
- /* Decrypt operations are only supported for RSA keys. */
- OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
- return ssl_private_key_failure;
- }
-
- /* Decrypt with no padding. PKCS#1 padding will be removed as part
- * of the timing-sensitive code by the caller. */
- if (!RSA_decrypt(rsa, out_len, out, max_out, in, in_len, RSA_NO_PADDING)) {
- return ssl_private_key_failure;
- }
- return ssl_private_key_success;
-}
-
-int ssl_private_key_supports_signature_algorithm(SSL_HANDSHAKE *hs,
- uint16_t sigalg) {
- SSL *const ssl = hs->ssl;
- if (!pkey_supports_algorithm(ssl, hs->local_pubkey, sigalg)) {
- return 0;
- }
-
- /* Ensure the RSA key is large enough for the hash. RSASSA-PSS requires that
- * emLen be at least hLen + sLen + 2. Both hLen and sLen are the size of the
- * hash in TLS. Reasonable RSA key sizes are large enough for the largest
- * defined RSASSA-PSS algorithm, but 1024-bit RSA is slightly too small for
- * SHA-512. 1024-bit RSA is sometimes used for test credentials, so check the
- * size so that we can fall back to another algorithm in that case. */
- const SSL_SIGNATURE_ALGORITHM *alg = get_signature_algorithm(sigalg);
- if (alg->is_rsa_pss &&
- (size_t)EVP_PKEY_size(hs->local_pubkey) <
- 2 * EVP_MD_size(alg->digest_func()) + 2) {
- return 0;
- }
-
- /* Newer algorithms require message-based private keys.
- * TODO(davidben): Remove this check when sign_digest is gone. */
- if (ssl->cert->key_method != NULL &&
- ssl->cert->key_method->sign == NULL &&
- !legacy_sign_digest_supported(alg)) {
- return 0;
- }
-
- return 1;
-}
diff --git a/src/ssl/ssl_session.cc b/src/ssl/ssl_session.cc
index 9cb78cc2..02d64221 100644
--- a/src/ssl/ssl_session.cc
+++ b/src/ssl/ssl_session.cc
@@ -139,6 +139,8 @@
#include <stdlib.h>
#include <string.h>
+#include <utility>
+
#include <openssl/err.h>
#include <openssl/lhash.h>
#include <openssl/mem.h>
@@ -148,6 +150,8 @@
#include "../crypto/internal.h"
+namespace bssl {
+
/* The address of this is a magic value, a pointer to which is returned by
* SSL_magic_pending_session_ptr(). It allows a session callback to indicate
* that it needs to asynchronously fetch session information. */
@@ -160,13 +164,14 @@ static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *session);
static void SSL_SESSION_list_add(SSL_CTX *ctx, SSL_SESSION *session);
static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *session, int lock);
-SSL_SESSION *ssl_session_new(const SSL_X509_METHOD *x509_method) {
- SSL_SESSION *session = (SSL_SESSION *)OPENSSL_malloc(sizeof(SSL_SESSION));
- if (session == NULL) {
+UniquePtr<SSL_SESSION> ssl_session_new(const SSL_X509_METHOD *x509_method) {
+ UniquePtr<SSL_SESSION> session(
+ (SSL_SESSION *)OPENSSL_malloc(sizeof(SSL_SESSION)));
+ if (!session) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
return 0;
}
- OPENSSL_memset(session, 0, sizeof(SSL_SESSION));
+ OPENSSL_memset(session.get(), 0, sizeof(SSL_SESSION));
session->x509_method = x509_method;
session->verify_result = X509_V_ERR_INVALID_CALL;
@@ -178,14 +183,10 @@ SSL_SESSION *ssl_session_new(const SSL_X509_METHOD *x509_method) {
return session;
}
-SSL_SESSION *SSL_SESSION_new(const SSL_CTX *ctx) {
- return ssl_session_new(ctx->x509_method);
-}
-
-SSL_SESSION *SSL_SESSION_dup(SSL_SESSION *session, int dup_flags) {
- SSL_SESSION *new_session = ssl_session_new(session->x509_method);
- if (new_session == NULL) {
- goto err;
+UniquePtr<SSL_SESSION> SSL_SESSION_dup(SSL_SESSION *session, int dup_flags) {
+ UniquePtr<SSL_SESSION> new_session = ssl_session_new(session->x509_method);
+ if (!new_session) {
+ return nullptr;
}
new_session->is_server = session->is_server;
@@ -203,25 +204,25 @@ SSL_SESSION *SSL_SESSION_dup(SSL_SESSION *session, int dup_flags) {
if (session->psk_identity != NULL) {
new_session->psk_identity = BUF_strdup(session->psk_identity);
if (new_session->psk_identity == NULL) {
- goto err;
+ return nullptr;
}
}
if (session->certs != NULL) {
new_session->certs = sk_CRYPTO_BUFFER_new_null();
if (new_session->certs == NULL) {
- goto err;
+ return nullptr;
}
for (size_t i = 0; i < sk_CRYPTO_BUFFER_num(session->certs); i++) {
CRYPTO_BUFFER *buffer = sk_CRYPTO_BUFFER_value(session->certs, i);
if (!sk_CRYPTO_BUFFER_push(new_session->certs, buffer)) {
- goto err;
+ return nullptr;
}
CRYPTO_BUFFER_up_ref(buffer);
}
}
- if (!session->x509_method->session_dup(new_session, session)) {
- goto err;
+ if (!session->x509_method->session_dup(new_session.get(), session)) {
+ return nullptr;
}
new_session->verify_result = session->verify_result;
@@ -231,7 +232,7 @@ SSL_SESSION *SSL_SESSION_dup(SSL_SESSION *session, int dup_flags) {
new_session->ocsp_response = (uint8_t *)BUF_memdup(
session->ocsp_response, session->ocsp_response_length);
if (new_session->ocsp_response == NULL) {
- goto err;
+ return nullptr;
}
}
@@ -242,7 +243,7 @@ SSL_SESSION *SSL_SESSION_dup(SSL_SESSION *session, int dup_flags) {
session->tlsext_signed_cert_timestamp_list,
session->tlsext_signed_cert_timestamp_list_length);
if (new_session->tlsext_signed_cert_timestamp_list == NULL) {
- goto err;
+ return nullptr;
}
}
@@ -253,7 +254,7 @@ SSL_SESSION *SSL_SESSION_dup(SSL_SESSION *session, int dup_flags) {
if (session->tlsext_hostname != NULL) {
new_session->tlsext_hostname = BUF_strdup(session->tlsext_hostname);
if (new_session->tlsext_hostname == NULL) {
- goto err;
+ return nullptr;
}
}
@@ -285,7 +286,7 @@ SSL_SESSION *SSL_SESSION_dup(SSL_SESSION *session, int dup_flags) {
new_session->early_alpn =
(uint8_t *)BUF_memdup(session->early_alpn, session->early_alpn_len);
if (new_session->early_alpn == NULL) {
- goto err;
+ return nullptr;
}
}
new_session->early_alpn_len = session->early_alpn_len;
@@ -297,7 +298,7 @@ SSL_SESSION *SSL_SESSION_dup(SSL_SESSION *session, int dup_flags) {
new_session->tlsext_tick =
(uint8_t *)BUF_memdup(session->tlsext_tick, session->tlsext_ticklen);
if (new_session->tlsext_tick == NULL) {
- goto err;
+ return nullptr;
}
}
new_session->tlsext_ticklen = session->tlsext_ticklen;
@@ -307,11 +308,6 @@ SSL_SESSION *SSL_SESSION_dup(SSL_SESSION *session, int dup_flags) {
new_session->not_resumable = 1;
return new_session;
-
-err:
- SSL_SESSION_free(new_session);
- OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- return 0;
}
void ssl_session_rebase_time(SSL *ssl, SSL_SESSION *session) {
@@ -359,152 +355,6 @@ void ssl_session_renew_timeout(SSL *ssl, SSL_SESSION *session,
}
}
-int SSL_SESSION_up_ref(SSL_SESSION *session) {
- CRYPTO_refcount_inc(&session->references);
- return 1;
-}
-
-void SSL_SESSION_free(SSL_SESSION *session) {
- if (session == NULL ||
- !CRYPTO_refcount_dec_and_test_zero(&session->references)) {
- return;
- }
-
- CRYPTO_free_ex_data(&g_ex_data_class, session, &session->ex_data);
-
- OPENSSL_cleanse(session->master_key, sizeof(session->master_key));
- OPENSSL_cleanse(session->session_id, sizeof(session->session_id));
- sk_CRYPTO_BUFFER_pop_free(session->certs, CRYPTO_BUFFER_free);
- session->x509_method->session_clear(session);
- OPENSSL_free(session->tlsext_hostname);
- OPENSSL_free(session->tlsext_tick);
- OPENSSL_free(session->tlsext_signed_cert_timestamp_list);
- OPENSSL_free(session->ocsp_response);
- OPENSSL_free(session->psk_identity);
- OPENSSL_free(session->early_alpn);
- OPENSSL_cleanse(session, sizeof(*session));
- OPENSSL_free(session);
-}
-
-const uint8_t *SSL_SESSION_get_id(const SSL_SESSION *session,
- unsigned *out_len) {
- if (out_len != NULL) {
- *out_len = session->session_id_length;
- }
- return session->session_id;
-}
-
-uint32_t SSL_SESSION_get_timeout(const SSL_SESSION *session) {
- return session->timeout;
-}
-
-uint64_t SSL_SESSION_get_time(const SSL_SESSION *session) {
- if (session == NULL) {
- /* NULL should crash, but silently accept it here for compatibility. */
- return 0;
- }
- return session->time;
-}
-
-X509 *SSL_SESSION_get0_peer(const SSL_SESSION *session) {
- return session->x509_peer;
-}
-
-size_t SSL_SESSION_get_master_key(const SSL_SESSION *session, uint8_t *out,
- size_t max_out) {
- /* TODO(davidben): Fix master_key_length's type and remove these casts. */
- if (max_out == 0) {
- return (size_t)session->master_key_length;
- }
- if (max_out > (size_t)session->master_key_length) {
- max_out = (size_t)session->master_key_length;
- }
- OPENSSL_memcpy(out, session->master_key, max_out);
- return max_out;
-}
-
-uint64_t SSL_SESSION_set_time(SSL_SESSION *session, uint64_t time) {
- if (session == NULL) {
- return 0;
- }
-
- session->time = time;
- return time;
-}
-
-uint32_t SSL_SESSION_set_timeout(SSL_SESSION *session, uint32_t timeout) {
- if (session == NULL) {
- return 0;
- }
-
- session->timeout = timeout;
- session->auth_timeout = timeout;
- return 1;
-}
-
-int SSL_SESSION_set1_id_context(SSL_SESSION *session, const uint8_t *sid_ctx,
- size_t sid_ctx_len) {
- if (sid_ctx_len > sizeof(session->sid_ctx)) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG);
- return 0;
- }
-
- assert(sizeof(session->sid_ctx) < 256);
- session->sid_ctx_length = (uint8_t)sid_ctx_len;
- OPENSSL_memcpy(session->sid_ctx, sid_ctx, sid_ctx_len);
-
- return 1;
-}
-
-SSL_SESSION *SSL_magic_pending_session_ptr(void) {
- return (SSL_SESSION *)&g_pending_session_magic;
-}
-
-SSL_SESSION *SSL_get_session(const SSL *ssl) {
- /* Once the handshake completes we return the established session. Otherwise
- * we return the intermediate session, either |session| (for resumption) or
- * |new_session| if doing a full handshake. */
- if (!SSL_in_init(ssl)) {
- return ssl->s3->established_session;
- }
- SSL_HANDSHAKE *hs = ssl->s3->hs;
- if (hs->early_session != NULL) {
- return hs->early_session;
- }
- if (hs->new_session != NULL) {
- return hs->new_session;
- }
- return ssl->session;
-}
-
-SSL_SESSION *SSL_get1_session(SSL *ssl) {
- SSL_SESSION *ret = SSL_get_session(ssl);
- if (ret != NULL) {
- SSL_SESSION_up_ref(ret);
- }
- return ret;
-}
-
-int SSL_SESSION_get_ex_new_index(long argl, void *argp,
- CRYPTO_EX_unused *unused,
- CRYPTO_EX_dup *dup_unused,
- CRYPTO_EX_free *free_func) {
- int index;
- if (!CRYPTO_get_ex_new_index(&g_ex_data_class, &index, argl, argp,
- free_func)) {
- return -1;
- }
- return index;
-}
-
-int SSL_SESSION_set_ex_data(SSL_SESSION *session, int idx, void *arg) {
- return CRYPTO_set_ex_data(&session->ex_data, idx, arg);
-}
-
-void *SSL_SESSION_get_ex_data(const SSL_SESSION *session, int idx) {
- return CRYPTO_get_ex_data(&session->ex_data, idx);
-}
-
uint16_t SSL_SESSION_protocol_version(const SSL_SESSION *session) {
uint16_t ret;
if (!ssl_protocol_version_from_wire(&ret, session->ssl_version)) {
@@ -529,7 +379,7 @@ int ssl_get_new_session(SSL_HANDSHAKE *hs, int is_server) {
return 0;
}
- SSL_SESSION *session = ssl_session_new(ssl->ctx->x509_method);
+ UniquePtr<SSL_SESSION> session = ssl_session_new(ssl->ctx->x509_method);
if (session == NULL) {
return 0;
}
@@ -563,7 +413,7 @@ int ssl_get_new_session(SSL_HANDSHAKE *hs, int is_server) {
} else {
session->session_id_length = SSL3_SSL_SESSION_ID_LENGTH;
if (!RAND_bytes(session->session_id, session->session_id_length)) {
- goto err;
+ return 0;
}
}
} else {
@@ -572,7 +422,7 @@ int ssl_get_new_session(SSL_HANDSHAKE *hs, int is_server) {
if (ssl->cert->sid_ctx_length > sizeof(session->sid_ctx)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
- goto err;
+ return 0;
}
OPENSSL_memcpy(session->sid_ctx, ssl->cert->sid_ctx,
ssl->cert->sid_ctx_length);
@@ -582,21 +432,16 @@ int ssl_get_new_session(SSL_HANDSHAKE *hs, int is_server) {
session->not_resumable = 1;
session->verify_result = X509_V_ERR_INVALID_CALL;
- SSL_SESSION_free(hs->new_session);
- hs->new_session = session;
+ hs->new_session = std::move(session);
ssl_set_session(ssl, NULL);
return 1;
-
-err:
- SSL_SESSION_free(session);
- return 0;
}
static int ssl_encrypt_ticket_with_cipher_ctx(SSL *ssl, CBB *out,
const uint8_t *session_buf,
size_t session_len) {
- bssl::ScopedEVP_CIPHER_CTX ctx;
- bssl::ScopedHMAC_CTX hctx;
+ ScopedEVP_CIPHER_CTX ctx;
+ ScopedHMAC_CTX hctx;
/* If the session is too long, emit a dummy value rather than abort the
* connection. */
@@ -881,6 +726,249 @@ enum ssl_session_result_t ssl_get_prev_session(
return ssl_session_success;
}
+static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *session, int lock) {
+ int ret = 0;
+
+ if (session != NULL && session->session_id_length != 0) {
+ if (lock) {
+ CRYPTO_MUTEX_lock_write(&ctx->lock);
+ }
+ SSL_SESSION *found_session = lh_SSL_SESSION_retrieve(ctx->sessions,
+ session);
+ if (found_session == session) {
+ ret = 1;
+ found_session = lh_SSL_SESSION_delete(ctx->sessions, session);
+ SSL_SESSION_list_remove(ctx, session);
+ }
+
+ if (lock) {
+ CRYPTO_MUTEX_unlock_write(&ctx->lock);
+ }
+
+ if (ret) {
+ if (ctx->remove_session_cb != NULL) {
+ ctx->remove_session_cb(ctx, found_session);
+ }
+ SSL_SESSION_free(found_session);
+ }
+ }
+
+ return ret;
+}
+
+void ssl_set_session(SSL *ssl, SSL_SESSION *session) {
+ if (ssl->session == session) {
+ return;
+ }
+
+ SSL_SESSION_free(ssl->session);
+ ssl->session = session;
+ if (session != NULL) {
+ SSL_SESSION_up_ref(session);
+ }
+}
+
+/* locked by SSL_CTX in the calling function */
+static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *session) {
+ if (session->next == NULL || session->prev == NULL) {
+ return;
+ }
+
+ if (session->next == (SSL_SESSION *)&ctx->session_cache_tail) {
+ /* last element in list */
+ if (session->prev == (SSL_SESSION *)&ctx->session_cache_head) {
+ /* only one element in list */
+ ctx->session_cache_head = NULL;
+ ctx->session_cache_tail = NULL;
+ } else {
+ ctx->session_cache_tail = session->prev;
+ session->prev->next = (SSL_SESSION *)&(ctx->session_cache_tail);
+ }
+ } else {
+ if (session->prev == (SSL_SESSION *)&ctx->session_cache_head) {
+ /* first element in list */
+ ctx->session_cache_head = session->next;
+ session->next->prev = (SSL_SESSION *)&(ctx->session_cache_head);
+ } else { /* middle of list */
+ session->next->prev = session->prev;
+ session->prev->next = session->next;
+ }
+ }
+ session->prev = session->next = NULL;
+}
+
+static void SSL_SESSION_list_add(SSL_CTX *ctx, SSL_SESSION *session) {
+ if (session->next != NULL && session->prev != NULL) {
+ SSL_SESSION_list_remove(ctx, session);
+ }
+
+ if (ctx->session_cache_head == NULL) {
+ ctx->session_cache_head = session;
+ ctx->session_cache_tail = session;
+ session->prev = (SSL_SESSION *)&(ctx->session_cache_head);
+ session->next = (SSL_SESSION *)&(ctx->session_cache_tail);
+ } else {
+ session->next = ctx->session_cache_head;
+ session->next->prev = session;
+ session->prev = (SSL_SESSION *)&(ctx->session_cache_head);
+ ctx->session_cache_head = session;
+ }
+}
+
+} // namespace bssl
+
+using namespace bssl;
+
+SSL_SESSION *SSL_SESSION_new(const SSL_CTX *ctx) {
+ return ssl_session_new(ctx->x509_method).release();
+}
+
+int SSL_SESSION_up_ref(SSL_SESSION *session) {
+ CRYPTO_refcount_inc(&session->references);
+ return 1;
+}
+
+void SSL_SESSION_free(SSL_SESSION *session) {
+ if (session == NULL ||
+ !CRYPTO_refcount_dec_and_test_zero(&session->references)) {
+ return;
+ }
+
+ CRYPTO_free_ex_data(&g_ex_data_class, session, &session->ex_data);
+
+ OPENSSL_cleanse(session->master_key, sizeof(session->master_key));
+ OPENSSL_cleanse(session->session_id, sizeof(session->session_id));
+ sk_CRYPTO_BUFFER_pop_free(session->certs, CRYPTO_BUFFER_free);
+ session->x509_method->session_clear(session);
+ OPENSSL_free(session->tlsext_hostname);
+ OPENSSL_free(session->tlsext_tick);
+ OPENSSL_free(session->tlsext_signed_cert_timestamp_list);
+ OPENSSL_free(session->ocsp_response);
+ OPENSSL_free(session->psk_identity);
+ OPENSSL_free(session->early_alpn);
+ OPENSSL_cleanse(session, sizeof(*session));
+ OPENSSL_free(session);
+}
+
+const uint8_t *SSL_SESSION_get_id(const SSL_SESSION *session,
+ unsigned *out_len) {
+ if (out_len != NULL) {
+ *out_len = session->session_id_length;
+ }
+ return session->session_id;
+}
+
+uint32_t SSL_SESSION_get_timeout(const SSL_SESSION *session) {
+ return session->timeout;
+}
+
+uint64_t SSL_SESSION_get_time(const SSL_SESSION *session) {
+ if (session == NULL) {
+ /* NULL should crash, but silently accept it here for compatibility. */
+ return 0;
+ }
+ return session->time;
+}
+
+X509 *SSL_SESSION_get0_peer(const SSL_SESSION *session) {
+ return session->x509_peer;
+}
+
+size_t SSL_SESSION_get_master_key(const SSL_SESSION *session, uint8_t *out,
+ size_t max_out) {
+ /* TODO(davidben): Fix master_key_length's type and remove these casts. */
+ if (max_out == 0) {
+ return (size_t)session->master_key_length;
+ }
+ if (max_out > (size_t)session->master_key_length) {
+ max_out = (size_t)session->master_key_length;
+ }
+ OPENSSL_memcpy(out, session->master_key, max_out);
+ return max_out;
+}
+
+uint64_t SSL_SESSION_set_time(SSL_SESSION *session, uint64_t time) {
+ if (session == NULL) {
+ return 0;
+ }
+
+ session->time = time;
+ return time;
+}
+
+uint32_t SSL_SESSION_set_timeout(SSL_SESSION *session, uint32_t timeout) {
+ if (session == NULL) {
+ return 0;
+ }
+
+ session->timeout = timeout;
+ session->auth_timeout = timeout;
+ return 1;
+}
+
+int SSL_SESSION_set1_id_context(SSL_SESSION *session, const uint8_t *sid_ctx,
+ size_t sid_ctx_len) {
+ if (sid_ctx_len > sizeof(session->sid_ctx)) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG);
+ return 0;
+ }
+
+ assert(sizeof(session->sid_ctx) < 256);
+ session->sid_ctx_length = (uint8_t)sid_ctx_len;
+ OPENSSL_memcpy(session->sid_ctx, sid_ctx, sid_ctx_len);
+
+ return 1;
+}
+
+SSL_SESSION *SSL_magic_pending_session_ptr(void) {
+ return (SSL_SESSION *)&g_pending_session_magic;
+}
+
+SSL_SESSION *SSL_get_session(const SSL *ssl) {
+ /* Once the handshake completes we return the established session. Otherwise
+ * we return the intermediate session, either |session| (for resumption) or
+ * |new_session| if doing a full handshake. */
+ if (!SSL_in_init(ssl)) {
+ return ssl->s3->established_session;
+ }
+ SSL_HANDSHAKE *hs = ssl->s3->hs;
+ if (hs->early_session) {
+ return hs->early_session.get();
+ }
+ if (hs->new_session) {
+ return hs->new_session.get();
+ }
+ return ssl->session;
+}
+
+SSL_SESSION *SSL_get1_session(SSL *ssl) {
+ SSL_SESSION *ret = SSL_get_session(ssl);
+ if (ret != NULL) {
+ SSL_SESSION_up_ref(ret);
+ }
+ return ret;
+}
+
+int SSL_SESSION_get_ex_new_index(long argl, void *argp,
+ CRYPTO_EX_unused *unused,
+ CRYPTO_EX_dup *dup_unused,
+ CRYPTO_EX_free *free_func) {
+ int index;
+ if (!CRYPTO_get_ex_new_index(&g_ex_data_class, &index, argl, argp,
+ free_func)) {
+ return -1;
+ }
+ return index;
+}
+
+int SSL_SESSION_set_ex_data(SSL_SESSION *session, int idx, void *arg) {
+ return CRYPTO_set_ex_data(&session->ex_data, idx, arg);
+}
+
+void *SSL_SESSION_get_ex_data(const SSL_SESSION *session, int idx) {
+ return CRYPTO_get_ex_data(&session->ex_data, idx);
+}
+
int SSL_CTX_add_session(SSL_CTX *ctx, SSL_SESSION *session) {
/* Although |session| is inserted into two structures (a doubly-linked list
* and the hash table), |ctx| only takes one reference. */
@@ -927,36 +1015,6 @@ int SSL_CTX_remove_session(SSL_CTX *ctx, SSL_SESSION *session) {
return remove_session_lock(ctx, session, 1);
}
-static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *session, int lock) {
- int ret = 0;
-
- if (session != NULL && session->session_id_length != 0) {
- if (lock) {
- CRYPTO_MUTEX_lock_write(&ctx->lock);
- }
- SSL_SESSION *found_session = lh_SSL_SESSION_retrieve(ctx->sessions,
- session);
- if (found_session == session) {
- ret = 1;
- found_session = lh_SSL_SESSION_delete(ctx->sessions, session);
- SSL_SESSION_list_remove(ctx, session);
- }
-
- if (lock) {
- CRYPTO_MUTEX_unlock_write(&ctx->lock);
- }
-
- if (ret) {
- if (ctx->remove_session_cb != NULL) {
- ctx->remove_session_cb(ctx, found_session);
- }
- SSL_SESSION_free(found_session);
- }
- }
-
- return ret;
-}
-
int SSL_set_session(SSL *ssl, SSL_SESSION *session) {
/* SSL_set_session may only be called before the handshake has started. */
if (ssl->s3->initial_handshake_complete ||
@@ -969,18 +1027,6 @@ int SSL_set_session(SSL *ssl, SSL_SESSION *session) {
return 1;
}
-void ssl_set_session(SSL *ssl, SSL_SESSION *session) {
- if (ssl->session == session) {
- return;
- }
-
- SSL_SESSION_free(ssl->session);
- ssl->session = session;
- if (session != NULL) {
- SSL_SESSION_up_ref(session);
- }
-}
-
uint32_t SSL_CTX_set_timeout(SSL_CTX *ctx, uint32_t timeout) {
if (ctx == NULL) {
return 0;
@@ -1046,53 +1092,6 @@ void SSL_CTX_flush_sessions(SSL_CTX *ctx, uint64_t time) {
CRYPTO_MUTEX_unlock_write(&ctx->lock);
}
-/* locked by SSL_CTX in the calling function */
-static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *session) {
- if (session->next == NULL || session->prev == NULL) {
- return;
- }
-
- if (session->next == (SSL_SESSION *)&ctx->session_cache_tail) {
- /* last element in list */
- if (session->prev == (SSL_SESSION *)&ctx->session_cache_head) {
- /* only one element in list */
- ctx->session_cache_head = NULL;
- ctx->session_cache_tail = NULL;
- } else {
- ctx->session_cache_tail = session->prev;
- session->prev->next = (SSL_SESSION *)&(ctx->session_cache_tail);
- }
- } else {
- if (session->prev == (SSL_SESSION *)&ctx->session_cache_head) {
- /* first element in list */
- ctx->session_cache_head = session->next;
- session->next->prev = (SSL_SESSION *)&(ctx->session_cache_head);
- } else { /* middle of list */
- session->next->prev = session->prev;
- session->prev->next = session->next;
- }
- }
- session->prev = session->next = NULL;
-}
-
-static void SSL_SESSION_list_add(SSL_CTX *ctx, SSL_SESSION *session) {
- if (session->next != NULL && session->prev != NULL) {
- SSL_SESSION_list_remove(ctx, session);
- }
-
- if (ctx->session_cache_head == NULL) {
- ctx->session_cache_head = session;
- ctx->session_cache_tail = session;
- session->prev = (SSL_SESSION *)&(ctx->session_cache_head);
- session->next = (SSL_SESSION *)&(ctx->session_cache_tail);
- } else {
- session->next = ctx->session_cache_head;
- session->next->prev = session;
- session->prev = (SSL_SESSION *)&(ctx->session_cache_head);
- ctx->session_cache_head = session;
- }
-}
-
void SSL_CTX_sess_set_new_cb(SSL_CTX *ctx,
int (*cb)(SSL *ssl, SSL_SESSION *session)) {
ctx->new_session_cb = cb;
diff --git a/src/ssl/ssl_test.cc b/src/ssl/ssl_test.cc
index 2c648acb..a57298f8 100644
--- a/src/ssl/ssl_test.cc
+++ b/src/ssl/ssl_test.cc
@@ -1293,6 +1293,15 @@ static bssl::UniquePtr<EVP_PKEY> GetChainTestKey() {
PEM_read_bio_PrivateKey(bio.get(), nullptr, nullptr, nullptr));
}
+static const uint8_t kTestName[] = {
+ 0x30, 0x45, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
+ 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08,
+ 0x0c, 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65,
+ 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x18, 0x49,
+ 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67,
+ 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, 0x74, 0x64,
+};
+
static bool CompleteHandshakes(SSL *client, SSL *server) {
// Drive both their handshakes to completion.
for (;;) {
@@ -1517,8 +1526,8 @@ TEST(SSLTest, SessionDuplication) {
nullptr /* no session */));
SSL_SESSION *session0 = SSL_get_session(client.get());
- bssl::UniquePtr<SSL_SESSION> session1(
- SSL_SESSION_dup(session0, SSL_SESSION_DUP_ALL));
+ bssl::UniquePtr<SSL_SESSION> session1 =
+ bssl::SSL_SESSION_dup(session0, SSL_SESSION_DUP_ALL);
ASSERT_TRUE(session1);
session1->not_resumable = 0;
@@ -3276,12 +3285,80 @@ TEST(SSLTest, SetChainAndKey) {
ASSERT_TRUE(SSL_CTX_set_chain_and_key(server_ctx.get(), &chain[0],
chain.size(), key.get(), nullptr));
- SSL_CTX_i_promise_to_verify_certs_after_the_handshake(client_ctx.get());
+ SSL_CTX_set_custom_verify(
+ client_ctx.get(), SSL_VERIFY_PEER,
+ [](SSL *ssl, uint8_t *out_alert) -> ssl_verify_result_t {
+ return ssl_verify_ok;
+ });
+
+ bssl::UniquePtr<SSL> client, server;
+ ASSERT_TRUE(ConnectClientAndServer(&client, &server, client_ctx.get(),
+ server_ctx.get(),
+ nullptr /* no session */));
+}
+
+TEST(SSLTest, ClientCABuffers) {
+ bssl::UniquePtr<SSL_CTX> client_ctx(SSL_CTX_new(TLS_with_buffers_method()));
+ ASSERT_TRUE(client_ctx);
+ bssl::UniquePtr<SSL_CTX> server_ctx(SSL_CTX_new(TLS_with_buffers_method()));
+ ASSERT_TRUE(server_ctx);
+
+ bssl::UniquePtr<EVP_PKEY> key = GetChainTestKey();
+ ASSERT_TRUE(key);
+ bssl::UniquePtr<CRYPTO_BUFFER> leaf = GetChainTestCertificateBuffer();
+ ASSERT_TRUE(leaf);
+ bssl::UniquePtr<CRYPTO_BUFFER> intermediate =
+ GetChainTestIntermediateBuffer();
+ ASSERT_TRUE(intermediate);
+ std::vector<CRYPTO_BUFFER *> chain = {
+ leaf.get(),
+ intermediate.get(),
+ };
+ ASSERT_TRUE(SSL_CTX_set_chain_and_key(server_ctx.get(), &chain[0],
+ chain.size(), key.get(), nullptr));
+
+ bssl::UniquePtr<CRYPTO_BUFFER> ca_name(
+ CRYPTO_BUFFER_new(kTestName, sizeof(kTestName), nullptr));
+ ASSERT_TRUE(ca_name);
+ bssl::UniquePtr<STACK_OF(CRYPTO_BUFFER)> ca_names(
+ sk_CRYPTO_BUFFER_new_null());
+ ASSERT_TRUE(ca_names);
+ ASSERT_TRUE(sk_CRYPTO_BUFFER_push(ca_names.get(), ca_name.get()));
+ ca_name.release();
+ SSL_CTX_set0_client_CAs(server_ctx.get(), ca_names.release());
+
+ // Configure client and server to accept all certificates.
+ SSL_CTX_set_custom_verify(
+ client_ctx.get(), SSL_VERIFY_PEER,
+ [](SSL *ssl, uint8_t *out_alert) -> ssl_verify_result_t {
+ return ssl_verify_ok;
+ });
+ SSL_CTX_set_custom_verify(
+ server_ctx.get(), SSL_VERIFY_PEER,
+ [](SSL *ssl, uint8_t *out_alert) -> ssl_verify_result_t {
+ return ssl_verify_ok;
+ });
+
+ bool cert_cb_called = false;
+ SSL_CTX_set_cert_cb(
+ client_ctx.get(),
+ [](SSL *ssl, void *arg) -> int {
+ STACK_OF(CRYPTO_BUFFER) *peer_names =
+ SSL_get0_server_requested_CAs(ssl);
+ EXPECT_EQ(1u, sk_CRYPTO_BUFFER_num(peer_names));
+ CRYPTO_BUFFER *peer_name = sk_CRYPTO_BUFFER_value(peer_names, 0);
+ EXPECT_EQ(Bytes(kTestName), Bytes(CRYPTO_BUFFER_data(peer_name),
+ CRYPTO_BUFFER_len(peer_name)));
+ *reinterpret_cast<bool *>(arg) = true;
+ return 1;
+ },
+ &cert_cb_called);
bssl::UniquePtr<SSL> client, server;
ASSERT_TRUE(ConnectClientAndServer(&client, &server, client_ctx.get(),
server_ctx.get(),
nullptr /* no session */));
+ EXPECT_TRUE(cert_cb_called);
}
// Configuring the empty cipher list, though an error, should still modify the
diff --git a/src/ssl/ssl_transcript.cc b/src/ssl/ssl_transcript.cc
index 9cc37778..4a00d0f2 100644
--- a/src/ssl/ssl_transcript.cc
+++ b/src/ssl/ssl_transcript.cc
@@ -150,136 +150,117 @@
#include "internal.h"
-int SSL_TRANSCRIPT_init(SSL_TRANSCRIPT *transcript) {
- SSL_TRANSCRIPT_cleanup(transcript);
- transcript->buffer = BUF_MEM_new();
- return transcript->buffer != NULL;
+namespace bssl {
+
+SSLTranscript::SSLTranscript() {}
+
+SSLTranscript::~SSLTranscript() {}
+
+bool SSLTranscript::Init() {
+ buffer_.reset(BUF_MEM_new());
+ if (!buffer_) {
+ return false;
+ }
+
+ hash_.Reset();
+ md5_.Reset();
+ return true;
}
-/* init_digest_with_data calls |EVP_DigestInit_ex| on |ctx| with |md| and then
+/* InitDigestWithData calls |EVP_DigestInit_ex| on |ctx| with |md| and then
* writes the data in |buf| to it. */
-static int init_digest_with_data(EVP_MD_CTX *ctx, const EVP_MD *md,
- const BUF_MEM *buf) {
+static bool InitDigestWithData(EVP_MD_CTX *ctx, const EVP_MD *md,
+ const BUF_MEM *buf) {
if (!EVP_DigestInit_ex(ctx, md, NULL)) {
- return 0;
+ return false;
}
EVP_DigestUpdate(ctx, buf->data, buf->length);
- return 1;
+ return true;
}
-int SSL_TRANSCRIPT_init_hash(SSL_TRANSCRIPT *transcript, uint16_t version,
- int algorithm_prf) {
+bool SSLTranscript::InitHash(uint16_t version, int algorithm_prf) {
const EVP_MD *md = ssl_get_handshake_digest(algorithm_prf, version);
/* To support SSL 3.0's Finished and CertificateVerify constructions,
* EVP_md5_sha1() is split into MD5 and SHA-1 halves. When SSL 3.0 is removed,
* we can simplify this. */
if (md == EVP_md5_sha1()) {
- if (!init_digest_with_data(&transcript->md5, EVP_md5(),
- transcript->buffer)) {
- return 0;
+ if (!InitDigestWithData(md5_.get(), EVP_md5(), buffer_.get())) {
+ return false;
}
md = EVP_sha1();
}
- if (!init_digest_with_data(&transcript->hash, md, transcript->buffer)) {
- return 0;
- }
-
- return 1;
-}
-
-void SSL_TRANSCRIPT_cleanup(SSL_TRANSCRIPT *transcript) {
- SSL_TRANSCRIPT_free_buffer(transcript);
- EVP_MD_CTX_cleanup(&transcript->hash);
- EVP_MD_CTX_cleanup(&transcript->md5);
+ return InitDigestWithData(hash_.get(), md, buffer_.get());
}
-void SSL_TRANSCRIPT_free_buffer(SSL_TRANSCRIPT *transcript) {
- BUF_MEM_free(transcript->buffer);
- transcript->buffer = NULL;
+void SSLTranscript::FreeBuffer() {
+ buffer_.reset();
}
-size_t SSL_TRANSCRIPT_digest_len(const SSL_TRANSCRIPT *transcript) {
- return EVP_MD_size(SSL_TRANSCRIPT_md(transcript));
+size_t SSLTranscript::DigestLen() const {
+ return EVP_MD_size(Digest());
}
-const EVP_MD *SSL_TRANSCRIPT_md(const SSL_TRANSCRIPT *transcript) {
- if (EVP_MD_CTX_md(&transcript->md5) != NULL) {
+const EVP_MD *SSLTranscript::Digest() const {
+ if (EVP_MD_CTX_md(md5_.get()) != nullptr) {
return EVP_md5_sha1();
}
- return EVP_MD_CTX_md(&transcript->hash);
+ return EVP_MD_CTX_md(hash_.get());
}
-int SSL_TRANSCRIPT_update(SSL_TRANSCRIPT *transcript, const uint8_t *in,
- size_t in_len) {
+bool SSLTranscript::Update(const uint8_t *in, size_t in_len) {
/* Depending on the state of the handshake, either the handshake buffer may be
* active, the rolling hash, or both. */
- if (transcript->buffer != NULL) {
- size_t new_len = transcript->buffer->length + in_len;
+ if (buffer_) {
+ size_t new_len = buffer_->length + in_len;
if (new_len < in_len) {
OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
- return 0;
+ return false;
}
- if (!BUF_MEM_grow(transcript->buffer, new_len)) {
- return 0;
+ if (!BUF_MEM_grow(buffer_.get(), new_len)) {
+ return false;
}
- OPENSSL_memcpy(transcript->buffer->data + new_len - in_len, in, in_len);
+ OPENSSL_memcpy(buffer_->data + new_len - in_len, in, in_len);
}
- if (EVP_MD_CTX_md(&transcript->hash) != NULL) {
- EVP_DigestUpdate(&transcript->hash, in, in_len);
+ if (EVP_MD_CTX_md(hash_.get()) != NULL) {
+ EVP_DigestUpdate(hash_.get(), in, in_len);
}
- if (EVP_MD_CTX_md(&transcript->md5) != NULL) {
- EVP_DigestUpdate(&transcript->md5, in, in_len);
+ if (EVP_MD_CTX_md(md5_.get()) != NULL) {
+ EVP_DigestUpdate(md5_.get(), in, in_len);
}
- return 1;
+ return true;
}
-int SSL_TRANSCRIPT_get_hash(const SSL_TRANSCRIPT *transcript, uint8_t *out,
- size_t *out_len) {
- int ret = 0;
- EVP_MD_CTX ctx;
- EVP_MD_CTX_init(&ctx);
+bool SSLTranscript::GetHash(uint8_t *out, size_t *out_len) {
+ ScopedEVP_MD_CTX ctx;
unsigned md5_len = 0;
- if (EVP_MD_CTX_md(&transcript->md5) != NULL) {
- if (!EVP_MD_CTX_copy_ex(&ctx, &transcript->md5) ||
- !EVP_DigestFinal_ex(&ctx, out, &md5_len)) {
- goto err;
+ if (EVP_MD_CTX_md(md5_.get()) != NULL) {
+ if (!EVP_MD_CTX_copy_ex(ctx.get(), md5_.get()) ||
+ !EVP_DigestFinal_ex(ctx.get(), out, &md5_len)) {
+ return false;
}
}
unsigned len;
- if (!EVP_MD_CTX_copy_ex(&ctx, &transcript->hash) ||
- !EVP_DigestFinal_ex(&ctx, out + md5_len, &len)) {
- goto err;
+ if (!EVP_MD_CTX_copy_ex(ctx.get(), hash_.get()) ||
+ !EVP_DigestFinal_ex(ctx.get(), out + md5_len, &len)) {
+ return false;
}
*out_len = md5_len + len;
- ret = 1;
-
-err:
- EVP_MD_CTX_cleanup(&ctx);
- return ret;
+ return true;
}
-static int ssl3_handshake_mac(SSL_TRANSCRIPT *transcript,
- const SSL_SESSION *session,
- const EVP_MD_CTX *ctx_template,
- const char *sender, size_t sender_len,
- uint8_t *p, size_t *out_len) {
- unsigned int len;
- size_t npad, n;
- unsigned int i;
- uint8_t md_buf[EVP_MAX_MD_SIZE];
- EVP_MD_CTX ctx;
-
- EVP_MD_CTX_init(&ctx);
- if (!EVP_MD_CTX_copy_ex(&ctx, ctx_template)) {
- EVP_MD_CTX_cleanup(&ctx);
+static bool SSL3HandshakeMAC(const SSL_SESSION *session,
+ const EVP_MD_CTX *ctx_template, const char *sender,
+ size_t sender_len, uint8_t *p, size_t *out_len) {
+ ScopedEVP_MD_CTX ctx;
+ if (!EVP_MD_CTX_copy_ex(ctx.get(), ctx_template)) {
OPENSSL_PUT_ERROR(SSL, ERR_LIB_EVP);
- return 0;
+ return false;
}
static const uint8_t kPad1[48] = {
@@ -296,89 +277,83 @@ static int ssl3_handshake_mac(SSL_TRANSCRIPT *transcript,
0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
};
- n = EVP_MD_CTX_size(&ctx);
+ size_t n = EVP_MD_CTX_size(ctx.get());
- npad = (48 / n) * n;
- if (sender != NULL) {
- EVP_DigestUpdate(&ctx, sender, sender_len);
- }
- EVP_DigestUpdate(&ctx, session->master_key, session->master_key_length);
- EVP_DigestUpdate(&ctx, kPad1, npad);
- EVP_DigestFinal_ex(&ctx, md_buf, &i);
+ size_t npad = (48 / n) * n;
+ EVP_DigestUpdate(ctx.get(), sender, sender_len);
+ EVP_DigestUpdate(ctx.get(), session->master_key, session->master_key_length);
+ EVP_DigestUpdate(ctx.get(), kPad1, npad);
+ unsigned md_buf_len;
+ uint8_t md_buf[EVP_MAX_MD_SIZE];
+ EVP_DigestFinal_ex(ctx.get(), md_buf, &md_buf_len);
- if (!EVP_DigestInit_ex(&ctx, EVP_MD_CTX_md(&ctx), NULL)) {
- EVP_MD_CTX_cleanup(&ctx);
+ if (!EVP_DigestInit_ex(ctx.get(), EVP_MD_CTX_md(ctx.get()), NULL)) {
OPENSSL_PUT_ERROR(SSL, ERR_LIB_EVP);
- return 0;
+ return false;
}
- EVP_DigestUpdate(&ctx, session->master_key, session->master_key_length);
- EVP_DigestUpdate(&ctx, kPad2, npad);
- EVP_DigestUpdate(&ctx, md_buf, i);
- EVP_DigestFinal_ex(&ctx, p, &len);
-
- EVP_MD_CTX_cleanup(&ctx);
+ EVP_DigestUpdate(ctx.get(), session->master_key, session->master_key_length);
+ EVP_DigestUpdate(ctx.get(), kPad2, npad);
+ EVP_DigestUpdate(ctx.get(), md_buf, md_buf_len);
+ unsigned len;
+ EVP_DigestFinal_ex(ctx.get(), p, &len);
*out_len = len;
- return 1;
+ return true;
}
-int SSL_TRANSCRIPT_ssl3_cert_verify_hash(SSL_TRANSCRIPT *transcript,
- uint8_t *out, size_t *out_len,
- const SSL_SESSION *session,
- int signature_algorithm) {
- if (SSL_TRANSCRIPT_md(transcript) != EVP_md5_sha1()) {
+bool SSLTranscript::GetSSL3CertVerifyHash(uint8_t *out, size_t *out_len,
+ const SSL_SESSION *session,
+ uint16_t signature_algorithm) {
+ if (Digest() != EVP_md5_sha1()) {
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
- return 0;
+ return false;
}
if (signature_algorithm == SSL_SIGN_RSA_PKCS1_MD5_SHA1) {
size_t md5_len, len;
- if (!ssl3_handshake_mac(transcript, session, &transcript->md5, NULL, 0, out,
- &md5_len) ||
- !ssl3_handshake_mac(transcript, session, &transcript->hash, NULL, 0,
- out + md5_len, &len)) {
- return 0;
+ if (!SSL3HandshakeMAC(session, md5_.get(), NULL, 0, out, &md5_len) ||
+ !SSL3HandshakeMAC(session, hash_.get(), NULL, 0, out + md5_len, &len)) {
+ return false;
}
*out_len = md5_len + len;
- return 1;
+ return true;
}
if (signature_algorithm == SSL_SIGN_ECDSA_SHA1) {
- return ssl3_handshake_mac(transcript, session, &transcript->hash, NULL, 0,
- out, out_len);
+ return SSL3HandshakeMAC(session, hash_.get(), NULL, 0, out, out_len);
}
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
- return 0;
+ return false;
}
-int SSL_TRANSCRIPT_finish_mac(SSL_TRANSCRIPT *transcript, uint8_t *out,
- size_t *out_len, const SSL_SESSION *session,
- int from_server, uint16_t version) {
+bool SSLTranscript::GetFinishedMAC(uint8_t *out, size_t *out_len,
+ const SSL_SESSION *session, bool from_server,
+ uint16_t version) {
if (version == SSL3_VERSION) {
- if (SSL_TRANSCRIPT_md(transcript) != EVP_md5_sha1()) {
+ if (Digest() != EVP_md5_sha1()) {
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
- return 0;
+ return false;
}
const char *sender = from_server ? SSL3_MD_SERVER_FINISHED_CONST
: SSL3_MD_CLIENT_FINISHED_CONST;
const size_t sender_len = 4;
size_t md5_len, len;
- if (!ssl3_handshake_mac(transcript, session, &transcript->md5, sender,
- sender_len, out, &md5_len) ||
- !ssl3_handshake_mac(transcript, session, &transcript->hash, sender,
- sender_len, out + md5_len, &len)) {
- return 0;
+ if (!SSL3HandshakeMAC(session, md5_.get(), sender, sender_len, out,
+ &md5_len) ||
+ !SSL3HandshakeMAC(session, hash_.get(), sender, sender_len,
+ out + md5_len, &len)) {
+ return false;
}
*out_len = md5_len + len;
- return 1;
+ return true;
}
/* At this point, the handshake should have released the handshake buffer on
* its own. */
- assert(transcript->buffer == NULL);
+ assert(!buffer_);
const char *label = TLS_MD_CLIENT_FINISH_CONST;
size_t label_len = TLS_MD_SERVER_FINISH_CONST_SIZE;
@@ -389,17 +364,19 @@ int SSL_TRANSCRIPT_finish_mac(SSL_TRANSCRIPT *transcript, uint8_t *out,
uint8_t digests[EVP_MAX_MD_SIZE];
size_t digests_len;
- if (!SSL_TRANSCRIPT_get_hash(transcript, digests, &digests_len)) {
- return 0;
+ if (!GetHash(digests, &digests_len)) {
+ return false;
}
static const size_t kFinishedLen = 12;
- if (!tls1_prf(SSL_TRANSCRIPT_md(transcript), out, kFinishedLen,
- session->master_key, session->master_key_length, label,
- label_len, digests, digests_len, NULL, 0)) {
- return 0;
+ if (!tls1_prf(Digest(), out, kFinishedLen, session->master_key,
+ session->master_key_length, label, label_len, digests,
+ digests_len, NULL, 0)) {
+ return false;
}
*out_len = kFinishedLen;
- return 1;
+ return true;
}
+
+} // namespace bssl
diff --git a/src/ssl/ssl_versions.cc b/src/ssl/ssl_versions.cc
index 8b54bd2f..0b13781d 100644
--- a/src/ssl/ssl_versions.cc
+++ b/src/ssl/ssl_versions.cc
@@ -23,6 +23,8 @@
#include "../crypto/internal.h"
+namespace bssl {
+
int ssl_protocol_version_from_wire(uint16_t *out, uint16_t version) {
switch (version) {
case SSL3_VERSION:
@@ -141,22 +143,6 @@ static int set_max_version(const SSL_PROTOCOL_METHOD *method, uint16_t *out,
return set_version_bound(method, out, version);
}
-int SSL_CTX_set_min_proto_version(SSL_CTX *ctx, uint16_t version) {
- return set_min_version(ctx->method, &ctx->conf_min_version, version);
-}
-
-int SSL_CTX_set_max_proto_version(SSL_CTX *ctx, uint16_t version) {
- return set_max_version(ctx->method, &ctx->conf_max_version, version);
-}
-
-int SSL_set_min_proto_version(SSL *ssl, uint16_t version) {
- return set_min_version(ssl->method, &ssl->conf_min_version, version);
-}
-
-int SSL_set_max_proto_version(SSL *ssl, uint16_t version) {
- return set_max_version(ssl->method, &ssl->conf_max_version, version);
-}
-
const struct {
uint16_t version;
uint32_t flag;
@@ -238,17 +224,7 @@ static uint16_t ssl_version(const SSL *ssl) {
return ssl->version;
}
-int SSL_version(const SSL *ssl) {
- uint16_t ret = ssl_version(ssl);
- /* Report TLS 1.3 draft version as TLS 1.3 in the public API. */
- if (ret == TLS1_3_DRAFT_VERSION || ret == TLS1_3_EXPERIMENT_VERSION ||
- ret == TLS1_3_RECORD_TYPE_EXPERIMENT_VERSION) {
- return TLS1_3_VERSION;
- }
- return ret;
-}
-
-static const char *ssl_get_version(int version) {
+static const char *ssl_version_to_string(uint16_t version) {
switch (version) {
/* Report TLS 1.3 draft version as TLS 1.3 in the public API. */
case TLS1_3_DRAFT_VERSION:
@@ -279,14 +255,6 @@ static const char *ssl_get_version(int version) {
}
}
-const char *SSL_get_version(const SSL *ssl) {
- return ssl_get_version(ssl_version(ssl));
-}
-
-const char *SSL_SESSION_get_version(const SSL_SESSION *session) {
- return ssl_get_version(session->ssl_version);
-}
-
uint16_t ssl3_protocol_version(const SSL *ssl) {
assert(ssl->s3->have_version);
uint16_t version;
@@ -312,6 +280,7 @@ int ssl_supports_version(SSL_HANDSHAKE *hs, uint16_t version) {
}
} else {
if ((ssl->tls13_variant != tls13_experiment &&
+ ssl->tls13_variant != tls13_no_session_id_experiment &&
version == TLS1_3_EXPERIMENT_VERSION) ||
(ssl->tls13_variant != tls13_record_type_experiment &&
version == TLS1_3_RECORD_TYPE_EXPERIMENT_VERSION) ||
@@ -371,3 +340,41 @@ int ssl_negotiate_version(SSL_HANDSHAKE *hs, uint8_t *out_alert,
*out_alert = SSL_AD_PROTOCOL_VERSION;
return 0;
}
+
+} // namespace bssl
+
+using namespace bssl;
+
+int SSL_CTX_set_min_proto_version(SSL_CTX *ctx, uint16_t version) {
+ return set_min_version(ctx->method, &ctx->conf_min_version, version);
+}
+
+int SSL_CTX_set_max_proto_version(SSL_CTX *ctx, uint16_t version) {
+ return set_max_version(ctx->method, &ctx->conf_max_version, version);
+}
+
+int SSL_set_min_proto_version(SSL *ssl, uint16_t version) {
+ return set_min_version(ssl->method, &ssl->conf_min_version, version);
+}
+
+int SSL_set_max_proto_version(SSL *ssl, uint16_t version) {
+ return set_max_version(ssl->method, &ssl->conf_max_version, version);
+}
+
+int SSL_version(const SSL *ssl) {
+ uint16_t ret = ssl_version(ssl);
+ /* Report TLS 1.3 draft version as TLS 1.3 in the public API. */
+ if (ret == TLS1_3_DRAFT_VERSION || ret == TLS1_3_EXPERIMENT_VERSION ||
+ ret == TLS1_3_RECORD_TYPE_EXPERIMENT_VERSION) {
+ return TLS1_3_VERSION;
+ }
+ return ret;
+}
+
+const char *SSL_get_version(const SSL *ssl) {
+ return ssl_version_to_string(ssl_version(ssl));
+}
+
+const char *SSL_SESSION_get_version(const SSL_SESSION *session) {
+ return ssl_version_to_string(session->ssl_version);
+}
diff --git a/src/ssl/ssl_x509.cc b/src/ssl/ssl_x509.cc
index 77fc0e2a..fd643086 100644
--- a/src/ssl/ssl_x509.cc
+++ b/src/ssl/ssl_x509.cc
@@ -155,6 +155,8 @@
#include "../crypto/internal.h"
+namespace bssl {
+
/* check_ssl_x509_method asserts that |ssl| has the X509-based method
* installed. Calling an X509-based method on an |ssl| with a different method
* will likely misbehave and possibly crash or leak memory. */
@@ -168,205 +170,6 @@ static void check_ssl_ctx_x509_method(const SSL_CTX *ctx) {
assert(ctx == NULL || ctx->x509_method == &ssl_crypto_x509_method);
}
-X509 *SSL_get_peer_certificate(const SSL *ssl) {
- check_ssl_x509_method(ssl);
- if (ssl == NULL) {
- return NULL;
- }
- SSL_SESSION *session = SSL_get_session(ssl);
- if (session == NULL || session->x509_peer == NULL) {
- return NULL;
- }
- X509_up_ref(session->x509_peer);
- return session->x509_peer;
-}
-
-STACK_OF(X509) *SSL_get_peer_cert_chain(const SSL *ssl) {
- check_ssl_x509_method(ssl);
- if (ssl == NULL) {
- return NULL;
- }
- SSL_SESSION *session = SSL_get_session(ssl);
- if (session == NULL ||
- session->x509_chain == NULL) {
- return NULL;
- }
-
- if (!ssl->server) {
- return session->x509_chain;
- }
-
- /* OpenSSL historically didn't include the leaf certificate in the returned
- * certificate chain, but only for servers. */
- if (session->x509_chain_without_leaf == NULL) {
- session->x509_chain_without_leaf = sk_X509_new_null();
- if (session->x509_chain_without_leaf == NULL) {
- return NULL;
- }
-
- for (size_t i = 1; i < sk_X509_num(session->x509_chain); i++) {
- X509 *cert = sk_X509_value(session->x509_chain, i);
- if (!sk_X509_push(session->x509_chain_without_leaf, cert)) {
- sk_X509_pop_free(session->x509_chain_without_leaf, X509_free);
- session->x509_chain_without_leaf = NULL;
- return NULL;
- }
- X509_up_ref(cert);
- }
- }
-
- return session->x509_chain_without_leaf;
-}
-
-STACK_OF(X509) *SSL_get_peer_full_cert_chain(const SSL *ssl) {
- check_ssl_x509_method(ssl);
- SSL_SESSION *session = SSL_get_session(ssl);
- if (session == NULL) {
- return NULL;
- }
-
- return session->x509_chain;
-}
-
-int SSL_CTX_set_purpose(SSL_CTX *ctx, int purpose) {
- check_ssl_ctx_x509_method(ctx);
- return X509_VERIFY_PARAM_set_purpose(ctx->param, purpose);
-}
-
-int SSL_set_purpose(SSL *ssl, int purpose) {
- check_ssl_x509_method(ssl);
- return X509_VERIFY_PARAM_set_purpose(ssl->param, purpose);
-}
-
-int SSL_CTX_set_trust(SSL_CTX *ctx, int trust) {
- check_ssl_ctx_x509_method(ctx);
- return X509_VERIFY_PARAM_set_trust(ctx->param, trust);
-}
-
-int SSL_set_trust(SSL *ssl, int trust) {
- check_ssl_x509_method(ssl);
- return X509_VERIFY_PARAM_set_trust(ssl->param, trust);
-}
-
-int SSL_CTX_set1_param(SSL_CTX *ctx, const X509_VERIFY_PARAM *param) {
- check_ssl_ctx_x509_method(ctx);
- return X509_VERIFY_PARAM_set1(ctx->param, param);
-}
-
-int SSL_set1_param(SSL *ssl, const X509_VERIFY_PARAM *param) {
- check_ssl_x509_method(ssl);
- return X509_VERIFY_PARAM_set1(ssl->param, param);
-}
-
-X509_VERIFY_PARAM *SSL_CTX_get0_param(SSL_CTX *ctx) {
- check_ssl_ctx_x509_method(ctx);
- return ctx->param;
-}
-
-X509_VERIFY_PARAM *SSL_get0_param(SSL *ssl) {
- check_ssl_x509_method(ssl);
- return ssl->param;
-}
-
-int SSL_get_verify_depth(const SSL *ssl) {
- check_ssl_x509_method(ssl);
- return X509_VERIFY_PARAM_get_depth(ssl->param);
-}
-
-int (*SSL_get_verify_callback(const SSL *ssl))(int, X509_STORE_CTX *) {
- check_ssl_x509_method(ssl);
- return ssl->verify_callback;
-}
-
-int SSL_CTX_get_verify_mode(const SSL_CTX *ctx) {
- check_ssl_ctx_x509_method(ctx);
- return ctx->verify_mode;
-}
-
-int SSL_CTX_get_verify_depth(const SSL_CTX *ctx) {
- check_ssl_ctx_x509_method(ctx);
- return X509_VERIFY_PARAM_get_depth(ctx->param);
-}
-
-int (*SSL_CTX_get_verify_callback(const SSL_CTX *ctx))(
- int ok, X509_STORE_CTX *store_ctx) {
- check_ssl_ctx_x509_method(ctx);
- return ctx->default_verify_callback;
-}
-
-void SSL_set_verify(SSL *ssl, int mode,
- int (*callback)(int ok, X509_STORE_CTX *store_ctx)) {
- check_ssl_x509_method(ssl);
- ssl->verify_mode = mode;
- if (callback != NULL) {
- ssl->verify_callback = callback;
- }
-}
-
-void SSL_set_verify_depth(SSL *ssl, int depth) {
- check_ssl_x509_method(ssl);
- X509_VERIFY_PARAM_set_depth(ssl->param, depth);
-}
-
-void SSL_CTX_set_cert_verify_callback(SSL_CTX *ctx,
- int (*cb)(X509_STORE_CTX *store_ctx,
- void *arg),
- void *arg) {
- check_ssl_ctx_x509_method(ctx);
- ctx->app_verify_callback = cb;
- ctx->app_verify_arg = arg;
-}
-
-void SSL_CTX_set_verify(SSL_CTX *ctx, int mode,
- int (*cb)(int, X509_STORE_CTX *)) {
- check_ssl_ctx_x509_method(ctx);
- ctx->verify_mode = mode;
- ctx->default_verify_callback = cb;
-}
-
-void SSL_CTX_set_verify_depth(SSL_CTX *ctx, int depth) {
- check_ssl_ctx_x509_method(ctx);
- X509_VERIFY_PARAM_set_depth(ctx->param, depth);
-}
-
-int SSL_CTX_set_default_verify_paths(SSL_CTX *ctx) {
- check_ssl_ctx_x509_method(ctx);
- return X509_STORE_set_default_paths(ctx->cert_store);
-}
-
-int SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *ca_file,
- const char *ca_dir) {
- check_ssl_ctx_x509_method(ctx);
- return X509_STORE_load_locations(ctx->cert_store, ca_file, ca_dir);
-}
-
-void SSL_set_verify_result(SSL *ssl, long result) {
- check_ssl_x509_method(ssl);
- if (result != X509_V_OK) {
- abort();
- }
-}
-
-long SSL_get_verify_result(const SSL *ssl) {
- check_ssl_x509_method(ssl);
- SSL_SESSION *session = SSL_get_session(ssl);
- if (session == NULL) {
- return X509_V_ERR_INVALID_CALL;
- }
- return session->verify_result;
-}
-
-X509_STORE *SSL_CTX_get_cert_store(const SSL_CTX *ctx) {
- check_ssl_ctx_x509_method(ctx);
- return ctx->cert_store;
-}
-
-void SSL_CTX_set_cert_store(SSL_CTX *ctx, X509_STORE *store) {
- check_ssl_ctx_x509_method(ctx);
- X509_STORE_free(ctx->cert_store);
- ctx->cert_store = store;
-}
-
/* x509_to_buffer returns a |CRYPTO_BUFFER| that contains the serialised
* contents of |x509|. */
static CRYPTO_BUFFER *x509_to_buffer(X509 *x509) {
@@ -620,7 +423,9 @@ static int ssl_verify_alarm_type(long type) {
}
static int ssl_crypto_x509_session_verify_cert_chain(SSL_SESSION *session,
- SSL *ssl) {
+ SSL *ssl,
+ uint8_t *out_alert) {
+ *out_alert = SSL_AD_INTERNAL_ERROR;
STACK_OF(X509) *const cert_chain = session->x509_chain;
if (cert_chain == NULL || sk_X509_num(cert_chain) == 0) {
return 0;
@@ -666,8 +471,7 @@ static int ssl_crypto_x509_session_verify_cert_chain(SSL_SESSION *session,
/* If |SSL_VERIFY_NONE|, the error is non-fatal, but we keep the result. */
if (verify_ret <= 0 && ssl->verify_mode != SSL_VERIFY_NONE) {
- ssl3_send_alert(ssl, SSL3_AL_FATAL, ssl_verify_alarm_type(ctx.error));
- OPENSSL_PUT_ERROR(SSL, SSL_R_CERTIFICATE_VERIFY_FAILED);
+ *out_alert = ssl_verify_alarm_type(ctx.error);
goto err;
}
@@ -784,6 +588,209 @@ const SSL_X509_METHOD ssl_crypto_x509_method = {
ssl_crypto_x509_ssl_ctx_flush_cached_client_CA,
};
+} // namespace bssl
+
+using namespace bssl;
+
+X509 *SSL_get_peer_certificate(const SSL *ssl) {
+ check_ssl_x509_method(ssl);
+ if (ssl == NULL) {
+ return NULL;
+ }
+ SSL_SESSION *session = SSL_get_session(ssl);
+ if (session == NULL || session->x509_peer == NULL) {
+ return NULL;
+ }
+ X509_up_ref(session->x509_peer);
+ return session->x509_peer;
+}
+
+STACK_OF(X509) *SSL_get_peer_cert_chain(const SSL *ssl) {
+ check_ssl_x509_method(ssl);
+ if (ssl == NULL) {
+ return NULL;
+ }
+ SSL_SESSION *session = SSL_get_session(ssl);
+ if (session == NULL ||
+ session->x509_chain == NULL) {
+ return NULL;
+ }
+
+ if (!ssl->server) {
+ return session->x509_chain;
+ }
+
+ /* OpenSSL historically didn't include the leaf certificate in the returned
+ * certificate chain, but only for servers. */
+ if (session->x509_chain_without_leaf == NULL) {
+ session->x509_chain_without_leaf = sk_X509_new_null();
+ if (session->x509_chain_without_leaf == NULL) {
+ return NULL;
+ }
+
+ for (size_t i = 1; i < sk_X509_num(session->x509_chain); i++) {
+ X509 *cert = sk_X509_value(session->x509_chain, i);
+ if (!sk_X509_push(session->x509_chain_without_leaf, cert)) {
+ sk_X509_pop_free(session->x509_chain_without_leaf, X509_free);
+ session->x509_chain_without_leaf = NULL;
+ return NULL;
+ }
+ X509_up_ref(cert);
+ }
+ }
+
+ return session->x509_chain_without_leaf;
+}
+
+STACK_OF(X509) *SSL_get_peer_full_cert_chain(const SSL *ssl) {
+ check_ssl_x509_method(ssl);
+ SSL_SESSION *session = SSL_get_session(ssl);
+ if (session == NULL) {
+ return NULL;
+ }
+
+ return session->x509_chain;
+}
+
+int SSL_CTX_set_purpose(SSL_CTX *ctx, int purpose) {
+ check_ssl_ctx_x509_method(ctx);
+ return X509_VERIFY_PARAM_set_purpose(ctx->param, purpose);
+}
+
+int SSL_set_purpose(SSL *ssl, int purpose) {
+ check_ssl_x509_method(ssl);
+ return X509_VERIFY_PARAM_set_purpose(ssl->param, purpose);
+}
+
+int SSL_CTX_set_trust(SSL_CTX *ctx, int trust) {
+ check_ssl_ctx_x509_method(ctx);
+ return X509_VERIFY_PARAM_set_trust(ctx->param, trust);
+}
+
+int SSL_set_trust(SSL *ssl, int trust) {
+ check_ssl_x509_method(ssl);
+ return X509_VERIFY_PARAM_set_trust(ssl->param, trust);
+}
+
+int SSL_CTX_set1_param(SSL_CTX *ctx, const X509_VERIFY_PARAM *param) {
+ check_ssl_ctx_x509_method(ctx);
+ return X509_VERIFY_PARAM_set1(ctx->param, param);
+}
+
+int SSL_set1_param(SSL *ssl, const X509_VERIFY_PARAM *param) {
+ check_ssl_x509_method(ssl);
+ return X509_VERIFY_PARAM_set1(ssl->param, param);
+}
+
+X509_VERIFY_PARAM *SSL_CTX_get0_param(SSL_CTX *ctx) {
+ check_ssl_ctx_x509_method(ctx);
+ return ctx->param;
+}
+
+X509_VERIFY_PARAM *SSL_get0_param(SSL *ssl) {
+ check_ssl_x509_method(ssl);
+ return ssl->param;
+}
+
+int SSL_get_verify_depth(const SSL *ssl) {
+ check_ssl_x509_method(ssl);
+ return X509_VERIFY_PARAM_get_depth(ssl->param);
+}
+
+int (*SSL_get_verify_callback(const SSL *ssl))(int, X509_STORE_CTX *) {
+ check_ssl_x509_method(ssl);
+ return ssl->verify_callback;
+}
+
+int SSL_CTX_get_verify_mode(const SSL_CTX *ctx) {
+ check_ssl_ctx_x509_method(ctx);
+ return ctx->verify_mode;
+}
+
+int SSL_CTX_get_verify_depth(const SSL_CTX *ctx) {
+ check_ssl_ctx_x509_method(ctx);
+ return X509_VERIFY_PARAM_get_depth(ctx->param);
+}
+
+int (*SSL_CTX_get_verify_callback(const SSL_CTX *ctx))(
+ int ok, X509_STORE_CTX *store_ctx) {
+ check_ssl_ctx_x509_method(ctx);
+ return ctx->default_verify_callback;
+}
+
+void SSL_set_verify(SSL *ssl, int mode,
+ int (*callback)(int ok, X509_STORE_CTX *store_ctx)) {
+ check_ssl_x509_method(ssl);
+ ssl->verify_mode = mode;
+ if (callback != NULL) {
+ ssl->verify_callback = callback;
+ }
+}
+
+void SSL_set_verify_depth(SSL *ssl, int depth) {
+ check_ssl_x509_method(ssl);
+ X509_VERIFY_PARAM_set_depth(ssl->param, depth);
+}
+
+void SSL_CTX_set_cert_verify_callback(SSL_CTX *ctx,
+ int (*cb)(X509_STORE_CTX *store_ctx,
+ void *arg),
+ void *arg) {
+ check_ssl_ctx_x509_method(ctx);
+ ctx->app_verify_callback = cb;
+ ctx->app_verify_arg = arg;
+}
+
+void SSL_CTX_set_verify(SSL_CTX *ctx, int mode,
+ int (*cb)(int, X509_STORE_CTX *)) {
+ check_ssl_ctx_x509_method(ctx);
+ ctx->verify_mode = mode;
+ ctx->default_verify_callback = cb;
+}
+
+void SSL_CTX_set_verify_depth(SSL_CTX *ctx, int depth) {
+ check_ssl_ctx_x509_method(ctx);
+ X509_VERIFY_PARAM_set_depth(ctx->param, depth);
+}
+
+int SSL_CTX_set_default_verify_paths(SSL_CTX *ctx) {
+ check_ssl_ctx_x509_method(ctx);
+ return X509_STORE_set_default_paths(ctx->cert_store);
+}
+
+int SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *ca_file,
+ const char *ca_dir) {
+ check_ssl_ctx_x509_method(ctx);
+ return X509_STORE_load_locations(ctx->cert_store, ca_file, ca_dir);
+}
+
+void SSL_set_verify_result(SSL *ssl, long result) {
+ check_ssl_x509_method(ssl);
+ if (result != X509_V_OK) {
+ abort();
+ }
+}
+
+long SSL_get_verify_result(const SSL *ssl) {
+ check_ssl_x509_method(ssl);
+ SSL_SESSION *session = SSL_get_session(ssl);
+ if (session == NULL) {
+ return X509_V_ERR_INVALID_CALL;
+ }
+ return session->verify_result;
+}
+
+X509_STORE *SSL_CTX_get_cert_store(const SSL_CTX *ctx) {
+ check_ssl_ctx_x509_method(ctx);
+ return ctx->cert_store;
+}
+
+void SSL_CTX_set_cert_store(SSL_CTX *ctx, X509_STORE *store) {
+ check_ssl_ctx_x509_method(ctx);
+ X509_STORE_free(ctx->cert_store);
+ ctx->cert_store = store;
+}
+
static int ssl_use_certificate(CERT *cert, X509 *x) {
if (x == NULL) {
OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER);
@@ -1045,7 +1052,7 @@ int SSL_get0_chain_certs(const SSL *ssl, STACK_OF(X509) **out_chain) {
}
static SSL_SESSION *ssl_session_new_with_crypto_x509(void) {
- return ssl_session_new(&ssl_crypto_x509_method);
+ return ssl_session_new(&ssl_crypto_x509_method).release();
}
SSL_SESSION *d2i_SSL_SESSION_bio(BIO *bio, SSL_SESSION **out) {
@@ -1068,18 +1075,18 @@ SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a, const uint8_t **pp, long length) {
CBS cbs;
CBS_init(&cbs, *pp, length);
- SSL_SESSION *ret = SSL_SESSION_parse(&cbs, &ssl_crypto_x509_method,
- NULL /* no buffer pool */);
- if (ret == NULL) {
+ UniquePtr<SSL_SESSION> ret = SSL_SESSION_parse(&cbs, &ssl_crypto_x509_method,
+ NULL /* no buffer pool */);
+ if (!ret) {
return NULL;
}
if (a) {
SSL_SESSION_free(*a);
- *a = ret;
+ *a = ret.get();
}
*pp = CBS_data(&cbs);
- return ret;
+ return ret.release();
}
STACK_OF(X509_NAME) *SSL_dup_CA_list(STACK_OF(X509_NAME) *list) {
@@ -1179,7 +1186,7 @@ STACK_OF(X509_NAME) *SSL_get_client_CA_list(const SSL *ssl) {
* indeterminate mode and |ssl->server| is unset. */
if (ssl->handshake_func != NULL && !ssl->server) {
if (ssl->s3->hs != NULL) {
- return buffer_names_to_x509(ssl->s3->hs->ca_names,
+ return buffer_names_to_x509(ssl->s3->hs->ca_names.get(),
&ssl->s3->hs->cached_x509_ca_names);
}
diff --git a/src/ssl/t1_enc.cc b/src/ssl/t1_enc.cc
index c2242405..2349df03 100644
--- a/src/ssl/t1_enc.cc
+++ b/src/ssl/t1_enc.cc
@@ -138,6 +138,8 @@
#include <assert.h>
#include <string.h>
+#include <utility>
+
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/hmac.h>
@@ -150,6 +152,8 @@
#include "internal.h"
+namespace bssl {
+
/* tls1_P_hash computes the TLS P_<hash> function as described in RFC 5246,
* section 5. It XORs |out_len| bytes to |out|, using |md| as the hash and
* |secret| as the secret. |seed1| through |seed3| are concatenated to form the
@@ -159,36 +163,33 @@ static int tls1_P_hash(uint8_t *out, size_t out_len, const EVP_MD *md,
const uint8_t *seed1, size_t seed1_len,
const uint8_t *seed2, size_t seed2_len,
const uint8_t *seed3, size_t seed3_len) {
- HMAC_CTX ctx, ctx_tmp, ctx_init;
+ ScopedHMAC_CTX ctx, ctx_tmp, ctx_init;
uint8_t A1[EVP_MAX_MD_SIZE];
unsigned A1_len;
int ret = 0;
size_t chunk = EVP_MD_size(md);
- HMAC_CTX_init(&ctx);
- HMAC_CTX_init(&ctx_tmp);
- HMAC_CTX_init(&ctx_init);
- if (!HMAC_Init_ex(&ctx_init, secret, secret_len, md, NULL) ||
- !HMAC_CTX_copy_ex(&ctx, &ctx_init) ||
- !HMAC_Update(&ctx, seed1, seed1_len) ||
- !HMAC_Update(&ctx, seed2, seed2_len) ||
- !HMAC_Update(&ctx, seed3, seed3_len) ||
- !HMAC_Final(&ctx, A1, &A1_len)) {
+ if (!HMAC_Init_ex(ctx_init.get(), secret, secret_len, md, NULL) ||
+ !HMAC_CTX_copy_ex(ctx.get(), ctx_init.get()) ||
+ !HMAC_Update(ctx.get(), seed1, seed1_len) ||
+ !HMAC_Update(ctx.get(), seed2, seed2_len) ||
+ !HMAC_Update(ctx.get(), seed3, seed3_len) ||
+ !HMAC_Final(ctx.get(), A1, &A1_len)) {
goto err;
}
for (;;) {
unsigned len;
uint8_t hmac[EVP_MAX_MD_SIZE];
- if (!HMAC_CTX_copy_ex(&ctx, &ctx_init) ||
- !HMAC_Update(&ctx, A1, A1_len) ||
+ if (!HMAC_CTX_copy_ex(ctx.get(), ctx_init.get()) ||
+ !HMAC_Update(ctx.get(), A1, A1_len) ||
/* Save a copy of |ctx| to compute the next A1 value below. */
- (out_len > chunk && !HMAC_CTX_copy_ex(&ctx_tmp, &ctx)) ||
- !HMAC_Update(&ctx, seed1, seed1_len) ||
- !HMAC_Update(&ctx, seed2, seed2_len) ||
- !HMAC_Update(&ctx, seed3, seed3_len) ||
- !HMAC_Final(&ctx, hmac, &len)) {
+ (out_len > chunk && !HMAC_CTX_copy_ex(ctx_tmp.get(), ctx.get())) ||
+ !HMAC_Update(ctx.get(), seed1, seed1_len) ||
+ !HMAC_Update(ctx.get(), seed2, seed2_len) ||
+ !HMAC_Update(ctx.get(), seed3, seed3_len) ||
+ !HMAC_Final(ctx.get(), hmac, &len)) {
goto err;
}
assert(len == chunk);
@@ -209,7 +210,7 @@ static int tls1_P_hash(uint8_t *out, size_t out_len, const EVP_MD *md,
}
/* Calculate the next A1 value. */
- if (!HMAC_Final(&ctx_tmp, A1, &A1_len)) {
+ if (!HMAC_Final(ctx_tmp.get(), A1, &A1_len)) {
goto err;
}
}
@@ -217,9 +218,6 @@ static int tls1_P_hash(uint8_t *out, size_t out_len, const EVP_MD *md,
ret = 1;
err:
- HMAC_CTX_cleanup(&ctx);
- HMAC_CTX_cleanup(&ctx_tmp);
- HMAC_CTX_cleanup(&ctx_init);
OPENSSL_cleanse(A1, sizeof(A1));
return ret;
}
@@ -264,15 +262,13 @@ static int ssl3_prf(uint8_t *out, size_t out_len, const uint8_t *secret,
size_t secret_len, const char *label, size_t label_len,
const uint8_t *seed1, size_t seed1_len,
const uint8_t *seed2, size_t seed2_len) {
- EVP_MD_CTX md5;
- EVP_MD_CTX sha1;
+ ScopedEVP_MD_CTX md5;
+ ScopedEVP_MD_CTX sha1;
uint8_t buf[16], smd[SHA_DIGEST_LENGTH];
uint8_t c = 'A';
size_t i, j, k;
k = 0;
- EVP_MD_CTX_init(&md5);
- EVP_MD_CTX_init(&sha1);
for (i = 0; i < out_len; i += MD5_DIGEST_LENGTH) {
k++;
if (k > sizeof(buf)) {
@@ -285,41 +281,38 @@ static int ssl3_prf(uint8_t *out, size_t out_len, const uint8_t *secret,
buf[j] = c;
}
c++;
- if (!EVP_DigestInit_ex(&sha1, EVP_sha1(), NULL)) {
+ if (!EVP_DigestInit_ex(sha1.get(), EVP_sha1(), NULL)) {
OPENSSL_PUT_ERROR(SSL, ERR_LIB_EVP);
return 0;
}
- EVP_DigestUpdate(&sha1, buf, k);
- EVP_DigestUpdate(&sha1, secret, secret_len);
+ EVP_DigestUpdate(sha1.get(), buf, k);
+ EVP_DigestUpdate(sha1.get(), secret, secret_len);
/* |label| is ignored for SSLv3. */
if (seed1_len) {
- EVP_DigestUpdate(&sha1, seed1, seed1_len);
+ EVP_DigestUpdate(sha1.get(), seed1, seed1_len);
}
if (seed2_len) {
- EVP_DigestUpdate(&sha1, seed2, seed2_len);
+ EVP_DigestUpdate(sha1.get(), seed2, seed2_len);
}
- EVP_DigestFinal_ex(&sha1, smd, NULL);
+ EVP_DigestFinal_ex(sha1.get(), smd, NULL);
- if (!EVP_DigestInit_ex(&md5, EVP_md5(), NULL)) {
+ if (!EVP_DigestInit_ex(md5.get(), EVP_md5(), NULL)) {
OPENSSL_PUT_ERROR(SSL, ERR_LIB_EVP);
return 0;
}
- EVP_DigestUpdate(&md5, secret, secret_len);
- EVP_DigestUpdate(&md5, smd, SHA_DIGEST_LENGTH);
+ EVP_DigestUpdate(md5.get(), secret, secret_len);
+ EVP_DigestUpdate(md5.get(), smd, SHA_DIGEST_LENGTH);
if (i + MD5_DIGEST_LENGTH > out_len) {
- EVP_DigestFinal_ex(&md5, smd, NULL);
+ EVP_DigestFinal_ex(md5.get(), smd, NULL);
OPENSSL_memcpy(out, smd, out_len - i);
} else {
- EVP_DigestFinal_ex(&md5, out, NULL);
+ EVP_DigestFinal_ex(md5.get(), out, NULL);
}
out += MD5_DIGEST_LENGTH;
}
OPENSSL_cleanse(smd, SHA_DIGEST_LENGTH);
- EVP_MD_CTX_cleanup(&md5);
- EVP_MD_CTX_cleanup(&sha1);
-
return 1;
}
@@ -330,8 +323,8 @@ static int tls1_setup_key_block(SSL_HANDSHAKE *hs) {
}
SSL_SESSION *session = ssl->session;
- if (hs->new_session != NULL) {
- session = hs->new_session;
+ if (hs->new_session) {
+ session = hs->new_session.get();
}
const EVP_AEAD *aead = NULL;
@@ -428,46 +421,19 @@ int tls1_change_cipher_state(SSL_HANDSHAKE *hs, int which) {
iv = server_write_iv;
}
- SSL_AEAD_CTX *aead_ctx = SSL_AEAD_CTX_new(
- is_read ? evp_aead_open : evp_aead_seal, ssl3_protocol_version(ssl), SSL_is_dtls(ssl),
- hs->new_cipher, key, key_len, mac_secret, mac_secret_len, iv, iv_len);
- if (aead_ctx == NULL) {
+ UniquePtr<SSLAEADContext> aead_ctx = SSLAEADContext::Create(
+ is_read ? evp_aead_open : evp_aead_seal, ssl3_protocol_version(ssl),
+ SSL_is_dtls(ssl), hs->new_cipher, key, key_len, mac_secret,
+ mac_secret_len, iv, iv_len);
+ if (!aead_ctx) {
return 0;
}
if (is_read) {
- return ssl->method->set_read_state(ssl, aead_ctx);
- }
-
- return ssl->method->set_write_state(ssl, aead_ctx);
-}
-
-size_t SSL_get_key_block_len(const SSL *ssl) {
- return 2 * ((size_t)ssl->s3->tmp.new_mac_secret_len +
- (size_t)ssl->s3->tmp.new_key_len +
- (size_t)ssl->s3->tmp.new_fixed_iv_len);
-}
-
-int SSL_generate_key_block(const SSL *ssl, uint8_t *out, size_t out_len) {
- if (ssl3_protocol_version(ssl) == SSL3_VERSION) {
- return ssl3_prf(out, out_len, SSL_get_session(ssl)->master_key,
- SSL_get_session(ssl)->master_key_length,
- TLS_MD_KEY_EXPANSION_CONST, TLS_MD_KEY_EXPANSION_CONST_SIZE,
- ssl->s3->server_random, SSL3_RANDOM_SIZE,
- ssl->s3->client_random, SSL3_RANDOM_SIZE);
+ return ssl->method->set_read_state(ssl, std::move(aead_ctx));
}
- const EVP_MD *digest = ssl_get_handshake_digest(
- SSL_get_session(ssl)->cipher->algorithm_prf, ssl3_protocol_version(ssl));
- if (digest == NULL) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
- return 0;
- }
- return tls1_prf(digest, out, out_len, SSL_get_session(ssl)->master_key,
- SSL_get_session(ssl)->master_key_length,
- TLS_MD_KEY_EXPANSION_CONST, TLS_MD_KEY_EXPANSION_CONST_SIZE,
- ssl->s3->server_random, SSL3_RANDOM_SIZE,
- ssl->s3->client_random, SSL3_RANDOM_SIZE);
+ return ssl->method->set_write_state(ssl, std::move(aead_ctx));
}
int tls1_generate_master_secret(SSL_HANDSHAKE *hs, uint8_t *out,
@@ -477,10 +443,9 @@ int tls1_generate_master_secret(SSL_HANDSHAKE *hs, uint8_t *out,
if (hs->extended_master_secret) {
uint8_t digests[EVP_MAX_MD_SIZE];
size_t digests_len;
- if (!SSL_TRANSCRIPT_get_hash(&hs->transcript, digests, &digests_len) ||
- !tls1_prf(SSL_TRANSCRIPT_md(&hs->transcript), out,
- SSL3_MASTER_SECRET_SIZE, premaster, premaster_len,
- TLS_MD_EXTENDED_MASTER_SECRET_CONST,
+ if (!hs->transcript.GetHash(digests, &digests_len) ||
+ !tls1_prf(hs->transcript.Digest(), out, SSL3_MASTER_SECRET_SIZE,
+ premaster, premaster_len, TLS_MD_EXTENDED_MASTER_SECRET_CONST,
TLS_MD_EXTENDED_MASTER_SECRET_CONST_SIZE, digests,
digests_len, NULL, 0)) {
return 0;
@@ -494,11 +459,11 @@ int tls1_generate_master_secret(SSL_HANDSHAKE *hs, uint8_t *out,
return 0;
}
} else {
- if (!tls1_prf(SSL_TRANSCRIPT_md(&hs->transcript), out,
- SSL3_MASTER_SECRET_SIZE, premaster, premaster_len,
- TLS_MD_MASTER_SECRET_CONST, TLS_MD_MASTER_SECRET_CONST_SIZE,
- ssl->s3->client_random, SSL3_RANDOM_SIZE,
- ssl->s3->server_random, SSL3_RANDOM_SIZE)) {
+ if (!tls1_prf(hs->transcript.Digest(), out, SSL3_MASTER_SECRET_SIZE,
+ premaster, premaster_len, TLS_MD_MASTER_SECRET_CONST,
+ TLS_MD_MASTER_SECRET_CONST_SIZE, ssl->s3->client_random,
+ SSL3_RANDOM_SIZE, ssl->s3->server_random,
+ SSL3_RANDOM_SIZE)) {
return 0;
}
}
@@ -507,6 +472,38 @@ int tls1_generate_master_secret(SSL_HANDSHAKE *hs, uint8_t *out,
return SSL3_MASTER_SECRET_SIZE;
}
+} // namespace bssl
+
+using namespace bssl;
+
+size_t SSL_get_key_block_len(const SSL *ssl) {
+ return 2 * ((size_t)ssl->s3->tmp.new_mac_secret_len +
+ (size_t)ssl->s3->tmp.new_key_len +
+ (size_t)ssl->s3->tmp.new_fixed_iv_len);
+}
+
+int SSL_generate_key_block(const SSL *ssl, uint8_t *out, size_t out_len) {
+ if (ssl3_protocol_version(ssl) == SSL3_VERSION) {
+ return ssl3_prf(out, out_len, SSL_get_session(ssl)->master_key,
+ SSL_get_session(ssl)->master_key_length,
+ TLS_MD_KEY_EXPANSION_CONST, TLS_MD_KEY_EXPANSION_CONST_SIZE,
+ ssl->s3->server_random, SSL3_RANDOM_SIZE,
+ ssl->s3->client_random, SSL3_RANDOM_SIZE);
+ }
+
+ const EVP_MD *digest = ssl_get_handshake_digest(
+ SSL_get_session(ssl)->cipher->algorithm_prf, ssl3_protocol_version(ssl));
+ if (digest == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ return tls1_prf(digest, out, out_len, SSL_get_session(ssl)->master_key,
+ SSL_get_session(ssl)->master_key_length,
+ TLS_MD_KEY_EXPANSION_CONST, TLS_MD_KEY_EXPANSION_CONST_SIZE,
+ ssl->s3->server_random, SSL3_RANDOM_SIZE,
+ ssl->s3->client_random, SSL3_RANDOM_SIZE);
+}
+
int SSL_export_keying_material(SSL *ssl, uint8_t *out, size_t out_len,
const char *label, size_t label_len,
const uint8_t *context, size_t context_len,
diff --git a/src/ssl/t1_lib.cc b/src/ssl/t1_lib.cc
index 76469ebb..19f256dc 100644
--- a/src/ssl/t1_lib.cc
+++ b/src/ssl/t1_lib.cc
@@ -126,6 +126,8 @@
#include "../crypto/internal.h"
+namespace bssl {
+
static int ssl_check_clienthello_tlsext(SSL_HANDSHAKE *hs);
static int compare_uint16_t(const void *p1, const void *p2) {
@@ -289,20 +291,6 @@ int ssl_client_hello_get_extension(const SSL_CLIENT_HELLO *client_hello,
return 0;
}
-int SSL_early_callback_ctx_extension_get(const SSL_CLIENT_HELLO *client_hello,
- uint16_t extension_type,
- const uint8_t **out_data,
- size_t *out_len) {
- CBS cbs;
- if (!ssl_client_hello_get_extension(client_hello, &cbs, extension_type)) {
- return 0;
- }
-
- *out_data = CBS_data(&cbs);
- *out_len = CBS_len(&cbs);
- return 1;
-}
-
static const uint16_t kDefaultGroups[] = {
SSL_CURVE_X25519,
SSL_CURVE_SECP256R1,
@@ -508,10 +496,6 @@ static const uint16_t kSignSignatureAlgorithms[] = {
SSL_SIGN_RSA_PKCS1_SHA1,
};
-void SSL_CTX_set_ed25519_enabled(SSL_CTX *ctx, int enabled) {
- ctx->ed25519_enabled = !!enabled;
-}
-
int tls12_add_verify_sigalgs(const SSL *ssl, CBB *out) {
const uint16_t *sigalgs = kVerifySignatureAlgorithms;
size_t num_sigalgs = OPENSSL_ARRAY_SIZE(kVerifySignatureAlgorithms);
@@ -690,10 +674,12 @@ static int ext_sni_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
}
/* Copy the hostname as a string. */
- if (!CBS_strdup(&host_name, &hs->hostname)) {
+ char *hostname_raw = nullptr;
+ if (!CBS_strdup(&host_name, &hostname_raw)) {
*out_alert = SSL_AD_INTERNAL_ERROR;
return 0;
}
+ hs->hostname.reset(hostname_raw);
hs->should_ack_sni = 1;
return 1;
@@ -2149,7 +2135,7 @@ static int ext_key_share_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) {
uint16_t group_id = hs->retry_group;
if (hs->received_hello_retry_request) {
/* We received a HelloRetryRequest without a new curve, so there is no new
- * share to append. Leave |ecdh_ctx| as-is. */
+ * share to append. Leave |hs->key_share| as-is. */
if (group_id == 0 &&
!CBB_add_bytes(&kse_bytes, hs->key_share_bytes,
hs->key_share_bytes_len)) {
@@ -2183,11 +2169,12 @@ static int ext_key_share_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) {
group_id = groups[0];
}
+ hs->key_share = SSLKeyShare::Create(group_id);
CBB key_exchange;
- if (!CBB_add_u16(&kse_bytes, group_id) ||
+ if (!hs->key_share ||
+ !CBB_add_u16(&kse_bytes, group_id) ||
!CBB_add_u16_length_prefixed(&kse_bytes, &key_exchange) ||
- !SSL_ECDH_CTX_init(&hs->ecdh_ctx, group_id) ||
- !SSL_ECDH_CTX_offer(&hs->ecdh_ctx, &key_exchange) ||
+ !hs->key_share->Offer(&key_exchange) ||
!CBB_flush(&kse_bytes)) {
return 0;
}
@@ -2218,20 +2205,20 @@ int ssl_ext_key_share_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t **out_secret,
return 0;
}
- if (SSL_ECDH_CTX_get_id(&hs->ecdh_ctx) != group_id) {
+ if (hs->key_share->GroupID() != group_id) {
*out_alert = SSL_AD_ILLEGAL_PARAMETER;
OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CURVE);
return 0;
}
- if (!SSL_ECDH_CTX_finish(&hs->ecdh_ctx, out_secret, out_secret_len, out_alert,
- CBS_data(&peer_key), CBS_len(&peer_key))) {
+ if (!hs->key_share->Finish(out_secret, out_secret_len, out_alert,
+ CBS_data(&peer_key), CBS_len(&peer_key))) {
*out_alert = SSL_AD_INTERNAL_ERROR;
return 0;
}
hs->new_session->group_id = group_id;
- SSL_ECDH_CTX_cleanup(&hs->ecdh_ctx);
+ hs->key_share.reset();
return 1;
}
@@ -2288,24 +2275,19 @@ int ssl_ext_key_share_parse_clienthello(SSL_HANDSHAKE *hs, int *out_found,
/* Compute the DH secret. */
uint8_t *secret = NULL;
size_t secret_len;
- SSL_ECDH_CTX group;
- OPENSSL_memset(&group, 0, sizeof(SSL_ECDH_CTX));
- CBB public_key;
- if (!CBB_init(&public_key, 32) ||
- !SSL_ECDH_CTX_init(&group, group_id) ||
- !SSL_ECDH_CTX_accept(&group, &public_key, &secret, &secret_len, out_alert,
- CBS_data(&peer_key), CBS_len(&peer_key)) ||
- !CBB_finish(&public_key, &hs->ecdh_public_key,
+ ScopedCBB public_key;
+ UniquePtr<SSLKeyShare> key_share = SSLKeyShare::Create(group_id);
+ if (!key_share ||
+ !CBB_init(public_key.get(), 32) ||
+ !key_share->Accept(public_key.get(), &secret, &secret_len, out_alert,
+ CBS_data(&peer_key), CBS_len(&peer_key)) ||
+ !CBB_finish(public_key.get(), &hs->ecdh_public_key,
&hs->ecdh_public_key_len)) {
OPENSSL_free(secret);
- SSL_ECDH_CTX_cleanup(&group);
- CBB_cleanup(&public_key);
*out_alert = SSL_AD_ILLEGAL_PARAMETER;
return 0;
}
- SSL_ECDH_CTX_cleanup(&group);
-
*out_secret = secret;
*out_secret_len = secret_len;
*out_found = 1;
@@ -2658,12 +2640,6 @@ static const struct tls_extension *tls_extension_find(uint32_t *out_index,
return NULL;
}
-int SSL_extension_supported(unsigned extension_value) {
- uint32_t index;
- return extension_value == TLSEXT_TYPE_padding ||
- tls_extension_find(&index, extension_value) != NULL;
-}
-
int ssl_add_clienthello_tlsext(SSL_HANDSHAKE *hs, CBB *out, size_t header_len) {
SSL *const ssl = hs->ssl;
/* Don't add extensions for SSLv3 unless doing secure renegotiation. */
@@ -3044,8 +3020,8 @@ ssl_decrypt_ticket_with_cipher_ctx(SSL *ssl, uint8_t **out, size_t *out_len,
size_t ticket_len) {
const SSL_CTX *const ssl_ctx = ssl->session_ctx;
- bssl::ScopedHMAC_CTX hmac_ctx;
- bssl::ScopedEVP_CIPHER_CTX cipher_ctx;
+ ScopedHMAC_CTX hmac_ctx;
+ ScopedEVP_CIPHER_CTX cipher_ctx;
/* Ensure there is room for the key name and the largest IV
* |tlsext_ticket_key_cb| may try to consume. The real limit may be lower, but
@@ -3105,7 +3081,7 @@ ssl_decrypt_ticket_with_cipher_ctx(SSL *ssl, uint8_t **out, size_t *out_len,
const uint8_t *ciphertext = ticket + SSL_TICKET_KEY_NAME_LEN + iv_len;
size_t ciphertext_len = ticket_len - SSL_TICKET_KEY_NAME_LEN - iv_len -
mac_len;
- bssl::UniquePtr<uint8_t> plaintext((uint8_t *)OPENSSL_malloc(ciphertext_len));
+ UniquePtr<uint8_t> plaintext((uint8_t *)OPENSSL_malloc(ciphertext_len));
if (!plaintext) {
return ssl_ticket_aead_error;
}
@@ -3263,7 +3239,7 @@ int tls1_choose_signature_algorithm(SSL_HANDSHAKE *hs, uint16_t *out) {
/* Before TLS 1.2, the signature algorithm isn't negotiated as part of the
* handshake. */
if (ssl3_protocol_version(ssl) < TLS1_2_VERSION) {
- if (!tls1_get_legacy_signature_algorithm(out, hs->local_pubkey)) {
+ if (!tls1_get_legacy_signature_algorithm(out, hs->local_pubkey.get())) {
OPENSSL_PUT_ERROR(SSL, SSL_R_NO_COMMON_SIGNATURE_ALGORITHMS);
return 0;
}
@@ -3328,15 +3304,14 @@ int tls1_verify_channel_id(SSL_HANDSHAKE *hs) {
return 0;
}
- bssl::UniquePtr<EC_GROUP> p256(
- EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
+ UniquePtr<EC_GROUP> p256(EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
if (!p256) {
OPENSSL_PUT_ERROR(SSL, SSL_R_NO_P256_SUPPORT);
return 0;
}
- bssl::UniquePtr<ECDSA_SIG> sig(ECDSA_SIG_new());
- bssl::UniquePtr<BIGNUM> x(BN_new()), y(BN_new());
+ UniquePtr<ECDSA_SIG> sig(ECDSA_SIG_new());
+ UniquePtr<BIGNUM> x(BN_new()), y(BN_new());
if (!sig || !x || !y) {
return 0;
}
@@ -3349,8 +3324,8 @@ int tls1_verify_channel_id(SSL_HANDSHAKE *hs) {
return 0;
}
- bssl::UniquePtr<EC_KEY> key(EC_KEY_new());
- bssl::UniquePtr<EC_POINT> point(EC_POINT_new(p256.get()));
+ UniquePtr<EC_KEY> key(EC_KEY_new());
+ UniquePtr<EC_POINT> point(EC_POINT_new(p256.get()));
if (!key || !point ||
!EC_POINT_set_affine_coordinates_GFp(p256.get(), point.get(), x.get(),
y.get(), nullptr) ||
@@ -3464,7 +3439,7 @@ int tls1_channel_id_hash(SSL_HANDSHAKE *hs, uint8_t *out, size_t *out_len) {
uint8_t hs_hash[EVP_MAX_MD_SIZE];
size_t hs_hash_len;
- if (!SSL_TRANSCRIPT_get_hash(&hs->transcript, hs_hash, &hs_hash_len)) {
+ if (!hs->transcript.GetHash(hs_hash, &hs_hash_len)) {
return 0;
}
SHA256_Update(&ctx, hs_hash, (size_t)hs_hash_len);
@@ -3490,9 +3465,8 @@ int tls1_record_handshake_hashes_for_channel_id(SSL_HANDSHAKE *hs) {
"original_handshake_hash is too small");
size_t digest_len;
- if (!SSL_TRANSCRIPT_get_hash(&hs->transcript,
- hs->new_session->original_handshake_hash,
- &digest_len)) {
+ if (!hs->transcript.GetHash(hs->new_session->original_handshake_hash,
+ &digest_len)) {
return -1;
}
@@ -3543,3 +3517,31 @@ int ssl_is_sct_list_valid(const CBS *contents) {
return 1;
}
+
+} // namespace bssl
+
+using namespace bssl;
+
+int SSL_early_callback_ctx_extension_get(const SSL_CLIENT_HELLO *client_hello,
+ uint16_t extension_type,
+ const uint8_t **out_data,
+ size_t *out_len) {
+ CBS cbs;
+ if (!ssl_client_hello_get_extension(client_hello, &cbs, extension_type)) {
+ return 0;
+ }
+
+ *out_data = CBS_data(&cbs);
+ *out_len = CBS_len(&cbs);
+ return 1;
+}
+
+void SSL_CTX_set_ed25519_enabled(SSL_CTX *ctx, int enabled) {
+ ctx->ed25519_enabled = !!enabled;
+}
+
+int SSL_extension_supported(unsigned extension_value) {
+ uint32_t index;
+ return extension_value == TLSEXT_TYPE_padding ||
+ tls_extension_find(&index, extension_value) != NULL;
+}
diff --git a/src/ssl/test/bssl_shim.cc b/src/ssl/test/bssl_shim.cc
index cd846be4..a056be09 100644
--- a/src/ssl/test/bssl_shim.cc
+++ b/src/ssl/test/bssl_shim.cc
@@ -112,6 +112,7 @@ struct TestState {
bool alpn_select_done = false;
bool is_resume = false;
bool early_callback_ready = false;
+ bool custom_verify_ready = false;
};
static void TestStateExFree(void *parent, void *ptr, CRYPTO_EX_DATA *ad,
@@ -684,27 +685,52 @@ static int CertCallback(SSL *ssl, void *arg) {
return 1;
}
-static int VerifySucceed(X509_STORE_CTX *store_ctx, void *arg) {
- SSL* ssl = (SSL*)X509_STORE_CTX_get_ex_data(store_ctx,
- SSL_get_ex_data_X509_STORE_CTX_idx());
+static bool CheckVerifyCallback(SSL *ssl) {
const TestConfig *config = GetTestConfig(ssl);
-
if (!config->expected_ocsp_response.empty()) {
const uint8_t *data;
size_t len;
SSL_get0_ocsp_response(ssl, &data, &len);
if (len == 0) {
fprintf(stderr, "OCSP response not available in verify callback\n");
- return 0;
+ return false;
}
}
+ return true;
+}
+
+static int CertVerifyCallback(X509_STORE_CTX *store_ctx, void *arg) {
+ SSL* ssl = (SSL*)X509_STORE_CTX_get_ex_data(store_ctx,
+ SSL_get_ex_data_X509_STORE_CTX_idx());
+ const TestConfig *config = GetTestConfig(ssl);
+ if (!CheckVerifyCallback(ssl)) {
+ return 0;
+ }
+
+ if (config->verify_fail) {
+ store_ctx->error = X509_V_ERR_APPLICATION_VERIFICATION;
+ return 0;
+ }
+
return 1;
}
-static int VerifyFail(X509_STORE_CTX *store_ctx, void *arg) {
- store_ctx->error = X509_V_ERR_APPLICATION_VERIFICATION;
- return 0;
+static ssl_verify_result_t CustomVerifyCallback(SSL *ssl, uint8_t *out_alert) {
+ const TestConfig *config = GetTestConfig(ssl);
+ if (!CheckVerifyCallback(ssl)) {
+ return ssl_verify_invalid;
+ }
+
+ if (config->async && !GetTestState(ssl)->custom_verify_ready) {
+ return ssl_verify_retry;
+ }
+
+ if (config->verify_fail) {
+ return ssl_verify_invalid;
+ }
+
+ return ssl_verify_ok;
}
static int NextProtosAdvertisedCallback(SSL *ssl, const uint8_t **out,
@@ -1051,12 +1077,12 @@ class SocketCloser {
};
static void ssl_ctx_add_session(SSL_SESSION *session, void *void_param) {
- SSL_SESSION *new_session = SSL_SESSION_dup(
+ SSL_CTX *ctx = reinterpret_cast<SSL_CTX *>(void_param);
+ bssl::UniquePtr<SSL_SESSION> new_session = bssl::SSL_SESSION_dup(
session, SSL_SESSION_INCLUDE_NONAUTH | SSL_SESSION_INCLUDE_TICKET);
if (new_session != nullptr) {
- SSL_CTX_add_session((SSL_CTX *)void_param, new_session);
+ SSL_CTX_add_session(ctx, new_session.get());
}
- SSL_SESSION_free(new_session);
}
static bssl::UniquePtr<SSL_CTX> SetupCtx(SSL_CTX *old_ctx,
@@ -1139,10 +1165,8 @@ static bssl::UniquePtr<SSL_CTX> SetupCtx(SSL_CTX *old_ctx,
return nullptr;
}
- if (config->verify_fail) {
- SSL_CTX_set_cert_verify_callback(ssl_ctx.get(), VerifyFail, NULL);
- } else {
- SSL_CTX_set_cert_verify_callback(ssl_ctx.get(), VerifySucceed, NULL);
+ if (!config->use_custom_verify_callback) {
+ SSL_CTX_set_cert_verify_callback(ssl_ctx.get(), CertVerifyCallback, NULL);
}
if (!config->signed_cert_timestamps.empty() &&
@@ -1270,6 +1294,9 @@ static bool RetryAsync(SSL *ssl, int ret) {
case SSL_ERROR_WANT_PRIVATE_KEY_OPERATION:
test_state->private_key_retries++;
return true;
+ case SSL_ERROR_WANT_CERTIFICATE_VERIFY:
+ test_state->custom_verify_ready = true;
+ return true;
default:
return false;
}
@@ -1763,20 +1790,23 @@ static bool DoConnection(bssl::UniquePtr<SSL_SESSION> *out_session,
if (!config->use_old_client_cert_callback) {
SSL_set_cert_cb(ssl.get(), CertCallback, nullptr);
}
+ int mode = SSL_VERIFY_NONE;
if (config->require_any_client_certificate) {
- SSL_set_verify(ssl.get(), SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
- NULL);
+ mode = SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
}
if (config->verify_peer) {
- SSL_set_verify(ssl.get(), SSL_VERIFY_PEER, NULL);
+ mode = SSL_VERIFY_PEER;
}
if (config->verify_peer_if_no_obc) {
// Set SSL_VERIFY_FAIL_IF_NO_PEER_CERT so testing whether client
// certificates were requested is easy.
- SSL_set_verify(ssl.get(),
- SSL_VERIFY_PEER | SSL_VERIFY_PEER_IF_NO_OBC |
- SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
- NULL);
+ mode = SSL_VERIFY_PEER | SSL_VERIFY_PEER_IF_NO_OBC |
+ SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
+ }
+ if (config->use_custom_verify_callback) {
+ SSL_set_custom_verify(ssl.get(), mode, CustomVerifyCallback);
+ } else if (mode != SSL_VERIFY_NONE) {
+ SSL_set_verify(ssl.get(), mode, NULL);
}
if (config->false_start) {
SSL_set_mode(ssl.get(), SSL_MODE_ENABLE_FALSE_START);
diff --git a/src/ssl/test/runner/common.go b/src/ssl/test/runner/common.go
index fd9fb3d5..a6a521b9 100644
--- a/src/ssl/test/runner/common.go
+++ b/src/ssl/test/runner/common.go
@@ -39,9 +39,10 @@ const (
)
const (
- TLS13Default = 0
- TLS13Experiment = 1
- TLS13RecordTypeExperiment = 2
+ TLS13Default = 0
+ TLS13Experiment = 1
+ TLS13RecordTypeExperiment = 2
+ TLS13NoSessionIDExperiment = 3
)
var allTLSWireVersions = []uint16{
@@ -717,6 +718,18 @@ type ProtocolBugs struct {
// normally expected to look ahead for ChangeCipherSpec.)
EmptyTicketSessionID bool
+ // SendClientHelloSessionID, if not nil, is the session ID sent in the
+ // ClientHello.
+ SendClientHelloSessionID []byte
+
+ // ExpectClientHelloSessionID, if true, causes the server to fail the
+ // connection if there is not a SessionID in the ClientHello.
+ ExpectClientHelloSessionID bool
+
+ // ExpectEmptyClientHelloSessionID, if true, causes the server to fail the
+ // connection if there is a SessionID in the ClientHello.
+ ExpectEmptyClientHelloSessionID bool
+
// ExpectNoTLS12Session, if true, causes the server to fail the
// connection if either a session ID or TLS 1.2 ticket is offered.
ExpectNoTLS12Session bool
@@ -1389,9 +1402,13 @@ type ProtocolBugs struct {
// and ServerHello messages to be omitted.
OmitExtensions bool
- // EmptyExtensions, if true, causese the extensions field in ClientHello
+ // EmptyExtensions, if true, causes the extensions field in ClientHello
// and ServerHello messages to be present, but empty.
EmptyExtensions bool
+
+ // ExpectRecordSplitting, if true, causes application records to only be
+ // accepted if they follow a 1/n-1 record split.
+ ExpectRecordSplitting bool
}
func (c *Config) serverInit() {
@@ -1496,7 +1513,7 @@ func (c *Config) defaultCurves() map[CurveID]bool {
// it returns true and the corresponding protocol version. Otherwise, it returns
// false.
func (c *Config) isSupportedVersion(wireVers uint16, isDTLS bool) (uint16, bool) {
- if (c.TLS13Variant != TLS13Experiment && wireVers == tls13ExperimentVersion) ||
+ if (c.TLS13Variant != TLS13Experiment && c.TLS13Variant != TLS13NoSessionIDExperiment && wireVers == tls13ExperimentVersion) ||
(c.TLS13Variant != TLS13RecordTypeExperiment && wireVers == tls13RecordTypeExperimentVersion) ||
(c.TLS13Variant != TLS13Default && wireVers == tls13DraftVersion) {
return 0, false
diff --git a/src/ssl/test/runner/conn.go b/src/ssl/test/runner/conn.go
index c974bd43..047c3c5b 100644
--- a/src/ssl/test/runner/conn.go
+++ b/src/ssl/test/runner/conn.go
@@ -98,6 +98,7 @@ type Conn struct {
pendingFragments [][]byte // pending outgoing handshake fragments.
keyUpdateRequested bool
+ seenOneByteRecord bool
tmp [16]byte
}
@@ -844,6 +845,13 @@ RestartReadRecord:
}
typ = encTyp
}
+
+ length := len(b.data[b.off:])
+ if c.config.Bugs.ExpectRecordSplitting && typ == recordTypeApplicationData && length != 1 && !c.seenOneByteRecord {
+ return 0, nil, c.in.setErrorLocked(fmt.Errorf("tls: application data records were not split"))
+ }
+
+ c.seenOneByteRecord = typ == recordTypeApplicationData && length == 1
return typ, b, nil
}
diff --git a/src/ssl/test/runner/fuzzer_mode.json b/src/ssl/test/runner/fuzzer_mode.json
index 3957bea1..834be404 100644
--- a/src/ssl/test/runner/fuzzer_mode.json
+++ b/src/ssl/test/runner/fuzzer_mode.json
@@ -48,6 +48,8 @@
"*-EarlyData-Reject-Client": "Trial decryption does not work with the NULL cipher.",
"*-EarlyData-RejectTicket-Client": "Trial decryption does not work with the NULL cipher.",
- "Renegotiate-Client-BadExt*": "Fuzzer mode does not check renegotiation_info."
+ "Renegotiate-Client-BadExt*": "Fuzzer mode does not check renegotiation_info.",
+
+ "CBCRecordSplitting*": "Fuzzer mode does not implement record-splitting."
}
}
diff --git a/src/ssl/test/runner/handshake_client.go b/src/ssl/test/runner/handshake_client.go
index 05e7311c..10e841a5 100644
--- a/src/ssl/test/runner/handshake_client.go
+++ b/src/ssl/test/runner/handshake_client.go
@@ -358,6 +358,9 @@ NextCipherSuite:
if c.config.Bugs.OmitEarlyDataExtension {
hello.hasEarlyData = false
}
+ if c.config.Bugs.SendClientHelloSessionID != nil {
+ hello.sessionId = c.config.Bugs.SendClientHelloSessionID
+ }
var helloBytes []byte
if c.config.Bugs.SendV2ClientHello {
@@ -684,6 +687,10 @@ NextCipherSuite:
func (hs *clientHandshakeState) doTLS13Handshake() error {
c := hs.c
+ if c.wireVersion == tls13ExperimentVersion && !bytes.Equal(hs.hello.sessionId, hs.serverHello.sessionId) {
+ return errors.New("tls: session IDs did not match.")
+ }
+
// Once the PRF hash is known, TLS 1.3 does not require a handshake
// buffer.
hs.finishedHash.discardHandshakeBuffer()
diff --git a/src/ssl/test/runner/handshake_server.go b/src/ssl/test/runner/handshake_server.go
index b31a562e..3e70185c 100644
--- a/src/ssl/test/runner/handshake_server.go
+++ b/src/ssl/test/runner/handshake_server.go
@@ -1087,6 +1087,13 @@ func (hs *serverHandshakeState) processClientHello() (isResume bool, err error)
copy(hs.hello.random[len(hs.hello.random)-8:], downgradeTLS12)
}
+ if len(hs.clientHello.sessionId) > 0 && c.config.Bugs.ExpectEmptyClientHelloSessionID {
+ return false, errors.New("tls: expected empty session ID from client")
+ }
+ if len(hs.clientHello.sessionId) == 0 && c.config.Bugs.ExpectClientHelloSessionID {
+ return false, errors.New("tls: expected non-empty session ID from client")
+ }
+
foundCompression := false
// We only support null compression, so check that the client offered it.
for _, compression := range hs.clientHello.compressionMethods {
diff --git a/src/ssl/test/runner/runner.go b/src/ssl/test/runner/runner.go
index 29747db6..c5f99715 100644
--- a/src/ssl/test/runner/runner.go
+++ b/src/ssl/test/runner/runner.go
@@ -527,6 +527,9 @@ func doExchange(test *testCase, config *Config, conn net.Conn, isResume bool, tr
if *deterministic {
config.Time = func() time.Time { return time.Unix(1234, 1234) }
}
+ if test.tls13Variant != 0 {
+ config.TLS13Variant = test.tls13Variant
+ }
conn = &timeoutConn{conn, *idleTimeout}
@@ -1038,7 +1041,6 @@ func runTest(test *testCase, shimPath string, mallocNumToFail int64) error {
}
if test.tls13Variant != 0 {
- test.config.TLS13Variant = test.tls13Variant
flags = append(flags, "-tls13-variant", strconv.Itoa(test.tls13Variant))
}
@@ -3324,6 +3326,9 @@ func addCBCSplittingTests() {
MaxVersion: VersionTLS10,
MinVersion: VersionTLS10,
CipherSuites: []uint16{t.cipher},
+ Bugs: ProtocolBugs{
+ ExpectRecordSplitting: true,
+ },
},
messageLen: -1, // read until EOF
resumeSession: true,
@@ -3339,6 +3344,9 @@ func addCBCSplittingTests() {
MaxVersion: VersionTLS10,
MinVersion: VersionTLS10,
CipherSuites: []uint16{t.cipher},
+ Bugs: ProtocolBugs{
+ ExpectRecordSplitting: true,
+ },
},
messageLen: -1, // read until EOF
flags: []string{
@@ -4009,25 +4017,23 @@ func addStateMachineCoverageTests(config stateMachineTestConfig) {
config: Config{
MaxVersion: VersionTLS13,
MinVersion: VersionTLS13,
- TLS13Variant: TLS13Experiment,
MaxEarlyDataSize: 16384,
},
resumeConfig: &Config{
MaxVersion: VersionTLS13,
MinVersion: VersionTLS13,
- TLS13Variant: TLS13Experiment,
MaxEarlyDataSize: 16384,
Bugs: ProtocolBugs{
ExpectEarlyData: [][]byte{{'h', 'e', 'l', 'l', 'o'}},
},
},
+ tls13Variant: TLS13Experiment,
resumeSession: true,
flags: []string{
"-enable-early-data",
"-expect-early-data-info",
"-expect-accept-early-data",
"-on-resume-shim-writes-first",
- "-tls13-variant", "1",
},
})
@@ -4049,13 +4055,13 @@ func addStateMachineCoverageTests(config stateMachineTestConfig) {
ExpectEarlyData: [][]byte{{'h', 'e', 'l', 'l', 'o'}},
},
},
+ tls13Variant: TLS13RecordTypeExperiment,
resumeSession: true,
flags: []string{
"-enable-early-data",
"-expect-early-data-info",
"-expect-accept-early-data",
"-on-resume-shim-writes-first",
- "-tls13-variant", "2",
},
})
@@ -4547,47 +4553,49 @@ func addStateMachineCoverageTests(config stateMachineTestConfig) {
if config.protocol == dtls && !vers.hasDTLS {
continue
}
- for _, testType := range []testType{clientTest, serverTest} {
- suffix := "-Client"
- if testType == serverTest {
- suffix = "-Server"
- }
- suffix += "-" + vers.name
+ for _, useCustomCallback := range []bool{false, true} {
+ for _, testType := range []testType{clientTest, serverTest} {
+ suffix := "-Client"
+ if testType == serverTest {
+ suffix = "-Server"
+ }
+ suffix += "-" + vers.name
+ if useCustomCallback {
+ suffix += "-CustomCallback"
+ }
- flag := "-verify-peer"
- if testType == serverTest {
- flag = "-require-any-client-certificate"
- }
+ flags := []string{"-verify-peer"}
+ if testType == serverTest {
+ flags = append(flags, "-require-any-client-certificate")
+ }
+ if useCustomCallback {
+ flags = append(flags, "-use-custom-verify-callback")
+ }
- tests = append(tests, testCase{
- testType: testType,
- name: "CertificateVerificationSucceed" + suffix,
- config: Config{
- MaxVersion: vers.version,
- Certificates: []Certificate{rsaCertificate},
- },
- tls13Variant: vers.tls13Variant,
- flags: []string{
- flag,
- "-expect-verify-result",
- },
- resumeSession: true,
- })
- tests = append(tests, testCase{
- testType: testType,
- name: "CertificateVerificationFail" + suffix,
- config: Config{
- MaxVersion: vers.version,
- Certificates: []Certificate{rsaCertificate},
- },
- tls13Variant: vers.tls13Variant,
- flags: []string{
- flag,
- "-verify-fail",
- },
- shouldFail: true,
- expectedError: ":CERTIFICATE_VERIFY_FAILED:",
- })
+ tests = append(tests, testCase{
+ testType: testType,
+ name: "CertificateVerificationSucceed" + suffix,
+ config: Config{
+ MaxVersion: vers.version,
+ Certificates: []Certificate{rsaCertificate},
+ },
+ tls13Variant: vers.tls13Variant,
+ flags: append([]string{"-expect-verify-result"}, flags...),
+ resumeSession: true,
+ })
+ tests = append(tests, testCase{
+ testType: testType,
+ name: "CertificateVerificationFail" + suffix,
+ config: Config{
+ MaxVersion: vers.version,
+ Certificates: []Certificate{rsaCertificate},
+ },
+ tls13Variant: vers.tls13Variant,
+ flags: append([]string{"-verify-fail"}, flags...),
+ shouldFail: true,
+ expectedError: ":CERTIFICATE_VERIFY_FAILED:",
+ })
+ }
}
// By default, the client is in a soft fail mode where the peer
@@ -11030,6 +11038,93 @@ func addTLS13HandshakeTests() {
},
})
+ for _, noSessionID := range []bool{false, true} {
+ prefix := "TLS13Experiment"
+ variant := TLS13Experiment
+ if noSessionID {
+ prefix = "TLS13NoSessionIDExperiment"
+ variant = TLS13NoSessionIDExperiment
+ }
+
+ // Test that enabling a TLS 1.3 variant does not interfere with
+ // TLS 1.2 session ID resumption.
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: prefix + "-ResumeTLS12SessionID",
+ config: Config{
+ MaxVersion: VersionTLS12,
+ SessionTicketsDisabled: true,
+ },
+ resumeSession: true,
+ flags: []string{"-tls13-variant", strconv.Itoa(variant)},
+ })
+
+ // Test that the server correctly echoes back session IDs of
+ // various lengths.
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: prefix + "-EmptySessionID",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ SendClientHelloSessionID: []byte{},
+ },
+ },
+ tls13Variant: variant,
+ })
+
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: prefix + "-ShortSessionID",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ SendClientHelloSessionID: make([]byte, 16),
+ },
+ },
+ tls13Variant: variant,
+ })
+
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: prefix + "-FullSessionID",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ SendClientHelloSessionID: make([]byte, 32),
+ },
+ },
+ tls13Variant: variant,
+ })
+ }
+
+ // Test that the client sends a fake session ID in TLS13Experiment.
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: "TLS13Experiment-RequireSessionID",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ ExpectClientHelloSessionID: true,
+ },
+ },
+ tls13Variant: TLS13Experiment,
+ })
+
+ // Test that the client does not send a fake session ID in
+ // TLS13NoSessionIDExperiment.
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: "TLS13NoSessionIDExperiment-RequireEmptySessionID",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ ExpectEmptyClientHelloSessionID: true,
+ },
+ },
+ tls13Variant: TLS13NoSessionIDExperiment,
+ })
+
testCases = append(testCases, testCase{
testType: clientTest,
name: "TLS13-EarlyData-Reject-Client",
@@ -11059,23 +11154,21 @@ func addTLS13HandshakeTests() {
config: Config{
MaxVersion: VersionTLS13,
MaxEarlyDataSize: 16384,
- TLS13Variant: TLS13Experiment,
},
resumeConfig: &Config{
MaxVersion: VersionTLS13,
- TLS13Variant: TLS13Experiment,
MaxEarlyDataSize: 16384,
Bugs: ProtocolBugs{
AlwaysRejectEarlyData: true,
},
},
+ tls13Variant: TLS13Experiment,
resumeSession: true,
flags: []string{
"-enable-early-data",
"-expect-early-data-info",
"-expect-reject-early-data",
"-on-resume-shim-writes-first",
- "-tls13-variant", "1",
},
})
@@ -11085,23 +11178,21 @@ func addTLS13HandshakeTests() {
config: Config{
MaxVersion: VersionTLS13,
MaxEarlyDataSize: 16384,
- TLS13Variant: TLS13RecordTypeExperiment,
},
resumeConfig: &Config{
MaxVersion: VersionTLS13,
- TLS13Variant: TLS13RecordTypeExperiment,
MaxEarlyDataSize: 16384,
Bugs: ProtocolBugs{
AlwaysRejectEarlyData: true,
},
},
+ tls13Variant: TLS13RecordTypeExperiment,
resumeSession: true,
flags: []string{
"-enable-early-data",
"-expect-early-data-info",
"-expect-reject-early-data",
"-on-resume-shim-writes-first",
- "-tls13-variant", "2",
},
})
diff --git a/src/ssl/test/test_config.cc b/src/ssl/test/test_config.cc
index f925504d..fa7dfe18 100644
--- a/src/ssl/test/test_config.cc
+++ b/src/ssl/test/test_config.cc
@@ -129,6 +129,7 @@ const Flag<bool> kBoolFlags[] = {
{ "-handshake-twice", &TestConfig::handshake_twice },
{ "-allow-unknown-alpn-protos", &TestConfig::allow_unknown_alpn_protos },
{ "-enable-ed25519", &TestConfig::enable_ed25519 },
+ { "-use-custom-verify-callback", &TestConfig::use_custom_verify_callback },
};
const Flag<std::string> kStringFlags[] = {
diff --git a/src/ssl/test/test_config.h b/src/ssl/test/test_config.h
index e157936d..1e5912e3 100644
--- a/src/ssl/test/test_config.h
+++ b/src/ssl/test/test_config.h
@@ -144,6 +144,7 @@ struct TestConfig {
bool handshake_twice = false;
bool allow_unknown_alpn_protos = false;
bool enable_ed25519 = false;
+ bool use_custom_verify_callback = false;
};
bool ParseConfig(int argc, char **argv, TestConfig *out_initial,
diff --git a/src/ssl/tls13_both.cc b/src/ssl/tls13_both.cc
index 763dc0e5..338975b1 100644
--- a/src/ssl/tls13_both.cc
+++ b/src/ssl/tls13_both.cc
@@ -17,6 +17,8 @@
#include <assert.h>
#include <string.h>
+#include <utility>
+
#include <openssl/bytestring.h>
#include <openssl/err.h>
#include <openssl/hkdf.h>
@@ -28,6 +30,8 @@
#include "internal.h"
+namespace bssl {
+
/* kMaxKeyUpdates is the number of consecutive KeyUpdates that will be
* processed. Without this limit an attacker could force unbounded processing
* without being able to return application data. */
@@ -53,7 +57,7 @@ int tls13_handshake(SSL_HANDSHAKE *hs, int *out_early_return) {
}
ssl->method->expect_flight(ssl);
hs->wait = ssl_hs_read_message;
- /* Fall-through. */
+ SSL_FALLTHROUGH;
}
case ssl_hs_read_message: {
@@ -102,6 +106,11 @@ int tls13_handshake(SSL_HANDSHAKE *hs, int *out_early_return) {
hs->wait = ssl_hs_ok;
return -1;
+ case ssl_hs_certificate_verify:
+ ssl->rwstate = SSL_CERTIFICATE_VERIFY;
+ hs->wait = ssl_hs_ok;
+ return -1;
+
case ssl_hs_early_data_rejected:
ssl->rwstate = SSL_EARLY_DATA_REJECTED;
/* Cause |SSL_write| to start failing immediately. */
@@ -132,14 +141,16 @@ int tls13_handshake(SSL_HANDSHAKE *hs, int *out_early_return) {
int tls13_get_cert_verify_signature_input(
SSL_HANDSHAKE *hs, uint8_t **out, size_t *out_len,
enum ssl_cert_verify_context_t cert_verify_context) {
- CBB cbb;
- if (!CBB_init(&cbb, 64 + 33 + 1 + 2 * EVP_MAX_MD_SIZE)) {
- goto err;
+ ScopedCBB cbb;
+ if (!CBB_init(cbb.get(), 64 + 33 + 1 + 2 * EVP_MAX_MD_SIZE)) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+ return 0;
}
for (size_t i = 0; i < 64; i++) {
- if (!CBB_add_u8(&cbb, 0x20)) {
- goto err;
+ if (!CBB_add_u8(cbb.get(), 0x20)) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+ return 0;
}
}
@@ -159,28 +170,25 @@ int tls13_get_cert_verify_signature_input(
context = (const uint8_t *)kContext;
context_len = sizeof(kContext);
} else {
- goto err;
+ OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+ return 0;
}
- if (!CBB_add_bytes(&cbb, context, context_len)) {
- goto err;
+ if (!CBB_add_bytes(cbb.get(), context, context_len)) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+ return 0;
}
uint8_t context_hash[EVP_MAX_MD_SIZE];
size_t context_hash_len;
- if (!SSL_TRANSCRIPT_get_hash(&hs->transcript, context_hash,
- &context_hash_len) ||
- !CBB_add_bytes(&cbb, context_hash, context_hash_len) ||
- !CBB_finish(&cbb, out, out_len)) {
- goto err;
+ if (!hs->transcript.GetHash(context_hash, &context_hash_len) ||
+ !CBB_add_bytes(cbb.get(), context_hash, context_hash_len) ||
+ !CBB_finish(cbb.get(), out, out_len)) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+ return 0;
}
return 1;
-
-err:
- OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- CBB_cleanup(&cbb);
- return 0;
}
int tls13_process_certificate(SSL_HANDSHAKE *hs, int allow_anonymous) {
@@ -194,24 +202,22 @@ int tls13_process_certificate(SSL_HANDSHAKE *hs, int allow_anonymous) {
return 0;
}
- const int retain_sha256 =
- ssl->server && ssl->retain_only_sha256_of_client_certs;
- int ret = 0;
-
- EVP_PKEY *pkey = NULL;
- STACK_OF(CRYPTO_BUFFER) *certs = sk_CRYPTO_BUFFER_new_null();
- if (certs == NULL) {
+ UniquePtr<STACK_OF(CRYPTO_BUFFER)> certs(sk_CRYPTO_BUFFER_new_null());
+ if (!certs) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- goto err;
+ return 0;
}
if (!CBS_get_u24_length_prefixed(&cbs, &certificate_list)) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
- goto err;
+ return 0;
}
+ const bool retain_sha256 =
+ ssl->server && ssl->retain_only_sha256_of_client_certs;
+ UniquePtr<EVP_PKEY> pkey;
while (CBS_len(&certificate_list) > 0) {
CBS certificate, extensions;
if (!CBS_get_u24_length_prefixed(&certificate_list, &certificate) ||
@@ -219,21 +225,21 @@ int tls13_process_certificate(SSL_HANDSHAKE *hs, int allow_anonymous) {
CBS_len(&certificate) == 0) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
OPENSSL_PUT_ERROR(SSL, SSL_R_CERT_LENGTH_MISMATCH);
- goto err;
+ return 0;
}
- if (sk_CRYPTO_BUFFER_num(certs) == 0) {
+ if (sk_CRYPTO_BUFFER_num(certs.get()) == 0) {
pkey = ssl_cert_parse_pubkey(&certificate);
- if (pkey == NULL) {
+ if (!pkey) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
- goto err;
+ return 0;
}
/* TLS 1.3 always uses certificate keys for signing thus the correct
* keyUsage is enforced. */
if (!ssl_cert_check_digital_signature_key_usage(&certificate)) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
- goto err;
+ return 0;
}
if (retain_sha256) {
@@ -246,11 +252,11 @@ int tls13_process_certificate(SSL_HANDSHAKE *hs, int allow_anonymous) {
CRYPTO_BUFFER *buf =
CRYPTO_BUFFER_new_from_CBS(&certificate, ssl->ctx->pool);
if (buf == NULL ||
- !sk_CRYPTO_BUFFER_push(certs, buf)) {
+ !sk_CRYPTO_BUFFER_push(certs.get(), buf)) {
CRYPTO_BUFFER_free(buf);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- goto err;
+ return 0;
}
/* Parse out the extensions. */
@@ -266,7 +272,7 @@ int tls13_process_certificate(SSL_HANDSHAKE *hs, int allow_anonymous) {
OPENSSL_ARRAY_SIZE(ext_types),
0 /* reject unknown */)) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
- goto err;
+ return 0;
}
/* All Certificate extensions are parsed, but only the leaf extensions are
@@ -275,7 +281,7 @@ int tls13_process_certificate(SSL_HANDSHAKE *hs, int allow_anonymous) {
if (ssl->server || !ssl->ocsp_stapling_enabled) {
OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNSUPPORTED_EXTENSION);
- goto err;
+ return 0;
}
uint8_t status_type;
@@ -286,14 +292,14 @@ int tls13_process_certificate(SSL_HANDSHAKE *hs, int allow_anonymous) {
CBS_len(&ocsp_response) == 0 ||
CBS_len(&status_request) != 0) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
- goto err;
+ return 0;
}
- if (sk_CRYPTO_BUFFER_num(certs) == 1 &&
+ if (sk_CRYPTO_BUFFER_num(certs.get()) == 1 &&
!CBS_stow(&ocsp_response, &hs->new_session->ocsp_response,
&hs->new_session->ocsp_response_length)) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
- goto err;
+ return 0;
}
}
@@ -301,21 +307,21 @@ int tls13_process_certificate(SSL_HANDSHAKE *hs, int allow_anonymous) {
if (ssl->server || !ssl->signed_cert_timestamps_enabled) {
OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNSUPPORTED_EXTENSION);
- goto err;
+ return 0;
}
if (!ssl_is_sct_list_valid(&sct)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_ERROR_PARSING_EXTENSION);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
- goto err;
+ return 0;
}
- if (sk_CRYPTO_BUFFER_num(certs) == 1 &&
+ if (sk_CRYPTO_BUFFER_num(certs.get()) == 1 &&
!CBS_stow(
&sct, &hs->new_session->tlsext_signed_cert_timestamp_list,
&hs->new_session->tlsext_signed_cert_timestamp_list_length)) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
- goto err;
+ return 0;
}
}
}
@@ -323,28 +329,25 @@ int tls13_process_certificate(SSL_HANDSHAKE *hs, int allow_anonymous) {
if (CBS_len(&cbs) != 0) {
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
- goto err;
+ return 0;
}
- EVP_PKEY_free(hs->peer_pubkey);
- hs->peer_pubkey = pkey;
- pkey = NULL;
+ hs->peer_pubkey = std::move(pkey);
sk_CRYPTO_BUFFER_pop_free(hs->new_session->certs, CRYPTO_BUFFER_free);
- hs->new_session->certs = certs;
- certs = NULL;
+ hs->new_session->certs = certs.release();
- if (!ssl->ctx->x509_method->session_cache_objects(hs->new_session)) {
+ if (!ssl->ctx->x509_method->session_cache_objects(hs->new_session.get())) {
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
- goto err;
+ return 0;
}
if (sk_CRYPTO_BUFFER_num(hs->new_session->certs) == 0) {
if (!allow_anonymous) {
OPENSSL_PUT_ERROR(SSL, SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_CERTIFICATE_REQUIRED);
- goto err;
+ return 0;
}
/* OpenSSL returns X509_V_OK when no certificates are requested. This is
@@ -352,23 +355,11 @@ int tls13_process_certificate(SSL_HANDSHAKE *hs, int allow_anonymous) {
hs->new_session->verify_result = X509_V_OK;
/* No certificate, so nothing more to do. */
- ret = 1;
- goto err;
+ return 1;
}
hs->new_session->peer_sha256_valid = retain_sha256;
-
- if (!ssl->ctx->x509_method->session_verify_cert_chain(hs->new_session,
- ssl)) {
- goto err;
- }
-
- ret = 1;
-
-err:
- sk_CRYPTO_BUFFER_pop_free(certs, CRYPTO_BUFFER_free);
- EVP_PKEY_free(pkey);
- return ret;
+ return 1;
}
int tls13_process_certificate_verify(SSL_HANDSHAKE *hs) {
@@ -404,11 +395,11 @@ int tls13_process_certificate_verify(SSL_HANDSHAKE *hs) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
return 0;
}
- bssl::UniquePtr<uint8_t> free_msg(msg);
+ UniquePtr<uint8_t> free_msg(msg);
- int sig_ok =
- ssl_public_key_verify(ssl, CBS_data(&signature), CBS_len(&signature),
- signature_algorithm, hs->peer_pubkey, msg, msg_len);
+ int sig_ok = ssl_public_key_verify(ssl, CBS_data(&signature),
+ CBS_len(&signature), signature_algorithm,
+ hs->peer_pubkey.get(), msg, msg_len);
#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
sig_ok = 1;
ERR_clear_error();
@@ -456,7 +447,7 @@ int tls13_process_finished(SSL_HANDSHAKE *hs, int use_saved_value) {
int tls13_add_certificate(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
- bssl::ScopedCBB cbb;
+ ScopedCBB cbb;
CBB body, certificate_list;
if (!ssl->method->init_message(ssl, cbb.get(), &body, SSL3_MT_CERTIFICATE) ||
/* The request context is always empty in the handshake. */
@@ -533,7 +524,7 @@ enum ssl_private_key_result_t tls13_add_certificate_verify(SSL_HANDSHAKE *hs) {
return ssl_private_key_failure;
}
- bssl::ScopedCBB cbb;
+ ScopedCBB cbb;
CBB body;
if (!ssl->method->init_message(ssl, cbb.get(), &body,
SSL3_MT_CERTIFICATE_VERIFY) ||
@@ -544,7 +535,7 @@ enum ssl_private_key_result_t tls13_add_certificate_verify(SSL_HANDSHAKE *hs) {
/* Sign the digest. */
CBB child;
- const size_t max_sig_len = EVP_PKEY_size(hs->local_pubkey);
+ const size_t max_sig_len = EVP_PKEY_size(hs->local_pubkey.get());
uint8_t *sig;
size_t sig_len;
if (!CBB_add_u16_length_prefixed(&body, &child) ||
@@ -561,7 +552,7 @@ enum ssl_private_key_result_t tls13_add_certificate_verify(SSL_HANDSHAKE *hs) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
return ssl_private_key_failure;
}
- bssl::UniquePtr<uint8_t> free_msg(msg);
+ UniquePtr<uint8_t> free_msg(msg);
enum ssl_private_key_result_t sign_result = ssl_private_key_sign(
hs, sig, &sig_len, max_sig_len, signature_algorithm, msg, msg_len);
@@ -588,11 +579,11 @@ int tls13_add_finished(SSL_HANDSHAKE *hs) {
return 0;
}
- CBB cbb, body;
- if (!ssl->method->init_message(ssl, &cbb, &body, SSL3_MT_FINISHED) ||
+ ScopedCBB cbb;
+ CBB body;
+ if (!ssl->method->init_message(ssl, cbb.get(), &body, SSL3_MT_FINISHED) ||
!CBB_add_bytes(&body, verify_data, verify_data_len) ||
- !ssl_add_message_cbb(ssl, &cbb)) {
- CBB_cleanup(&cbb);
+ !ssl_add_message_cbb(ssl, cbb.get())) {
return 0;
}
@@ -619,12 +610,12 @@ static int tls13_receive_key_update(SSL *ssl) {
/* Acknowledge the KeyUpdate */
if (key_update_request == SSL_KEY_UPDATE_REQUESTED &&
!ssl->s3->key_update_pending) {
- CBB cbb, body;
- if (!ssl->method->init_message(ssl, &cbb, &body, SSL3_MT_KEY_UPDATE) ||
+ ScopedCBB cbb;
+ CBB body;
+ if (!ssl->method->init_message(ssl, cbb.get(), &body, SSL3_MT_KEY_UPDATE) ||
!CBB_add_u8(&body, SSL_KEY_UPDATE_NOT_REQUESTED) ||
- !ssl_add_message_cbb(ssl, &cbb) ||
+ !ssl_add_message_cbb(ssl, cbb.get()) ||
!tls13_rotate_traffic_key(ssl, evp_aead_seal)) {
- CBB_cleanup(&cbb);
return 0;
}
@@ -661,3 +652,5 @@ int tls13_post_handshake(SSL *ssl) {
OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_MESSAGE);
return 0;
}
+
+} // namespace bssl
diff --git a/src/ssl/tls13_client.cc b/src/ssl/tls13_client.cc
index 7f961bff..4cc7e604 100644
--- a/src/ssl/tls13_client.cc
+++ b/src/ssl/tls13_client.cc
@@ -18,6 +18,8 @@
#include <limits.h>
#include <string.h>
+#include <utility>
+
#include <openssl/bytestring.h>
#include <openssl/digest.h>
#include <openssl/err.h>
@@ -28,6 +30,8 @@
#include "internal.h"
+namespace bssl {
+
enum client_hs_state_t {
state_process_hello_retry_request = 0,
state_send_second_client_hello,
@@ -126,13 +130,13 @@ static enum ssl_hs_wait_t do_process_hello_retry_request(SSL_HANDSHAKE *hs) {
/* Check that the HelloRetryRequest does not request the key share that
* was provided in the initial ClientHello. */
- if (SSL_ECDH_CTX_get_id(&hs->ecdh_ctx) == group_id) {
+ if (hs->key_share->GroupID() == group_id) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CURVE);
return ssl_hs_error;
}
- SSL_ECDH_CTX_cleanup(&hs->ecdh_ctx);
+ hs->key_share.reset();
hs->retry_group = group_id;
}
@@ -151,7 +155,10 @@ static enum ssl_hs_wait_t do_process_hello_retry_request(SSL_HANDSHAKE *hs) {
static enum ssl_hs_wait_t do_send_second_client_hello(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
- if (!ssl->method->set_write_state(ssl, NULL) ||
+ /* Restore the null cipher. We may have switched due to 0-RTT. */
+ bssl::UniquePtr<SSLAEADContext> null_ctx = SSLAEADContext::CreateNullCipher();
+ if (!null_ctx ||
+ !ssl->method->set_write_state(ssl, std::move(null_ctx)) ||
!ssl_write_client_hello(hs)) {
return ssl_hs_error;
}
@@ -275,14 +282,14 @@ static enum ssl_hs_wait_t do_process_server_hello(SSL_HANDSHAKE *hs) {
ssl->s3->session_reused = 1;
/* Only authentication information carries over in TLS 1.3. */
hs->new_session = SSL_SESSION_dup(ssl->session, SSL_SESSION_DUP_AUTH_ONLY);
- if (hs->new_session == NULL) {
+ if (!hs->new_session) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
return ssl_hs_error;
}
ssl_set_session(ssl, NULL);
/* Resumption incorporates fresh key material, so refresh the timeout. */
- ssl_session_renew_timeout(ssl, hs->new_session,
+ ssl_session_renew_timeout(ssl, hs->new_session.get(),
ssl->session_ctx->session_psk_dhe_timeout);
} else if (!ssl_get_new_session(hs, 0)) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
@@ -449,9 +456,9 @@ static enum ssl_hs_wait_t do_process_certificate_request(SSL_HANDSHAKE *hs) {
}
uint8_t alert = SSL_AD_DECODE_ERROR;
- STACK_OF(CRYPTO_BUFFER) *ca_names =
+ UniquePtr<STACK_OF(CRYPTO_BUFFER)> ca_names =
ssl_parse_client_CA_list(ssl, &alert, &cbs);
- if (ca_names == NULL) {
+ if (!ca_names) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
return ssl_hs_error;
}
@@ -461,14 +468,12 @@ static enum ssl_hs_wait_t do_process_certificate_request(SSL_HANDSHAKE *hs) {
if (!CBS_get_u16_length_prefixed(&cbs, &extensions) ||
CBS_len(&cbs) != 0) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
- sk_CRYPTO_BUFFER_pop_free(ca_names, CRYPTO_BUFFER_free);
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
return ssl_hs_error;
}
hs->cert_request = 1;
- sk_CRYPTO_BUFFER_pop_free(hs->ca_names, CRYPTO_BUFFER_free);
- hs->ca_names = ca_names;
+ hs->ca_names = std::move(ca_names);
ssl->ctx->x509_method->hs_flush_cached_ca_names(hs);
if (!ssl_hash_current_message(hs)) {
@@ -494,6 +499,16 @@ static enum ssl_hs_wait_t do_process_server_certificate(SSL_HANDSHAKE *hs) {
static enum ssl_hs_wait_t do_process_server_certificate_verify(
SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
+ switch (ssl_verify_peer_cert(hs)) {
+ case ssl_verify_ok:
+ break;
+ case ssl_verify_invalid:
+ return ssl_hs_error;
+ case ssl_verify_retry:
+ hs->tls13_state = state_process_server_certificate_verify;
+ return ssl_hs_certificate_verify;
+ }
+
if (!ssl_check_message_type(ssl, SSL3_MT_CERTIFICATE_VERIFY) ||
!tls13_process_certificate_verify(hs) ||
!ssl_hash_current_message(hs)) {
@@ -615,11 +630,11 @@ static enum ssl_hs_wait_t do_complete_second_flight(SSL_HANDSHAKE *hs) {
return ssl_hs_channel_id_lookup;
}
- CBB cbb, body;
- if (!ssl->method->init_message(ssl, &cbb, &body, SSL3_MT_CHANNEL_ID) ||
+ ScopedCBB cbb;
+ CBB body;
+ if (!ssl->method->init_message(ssl, cbb.get(), &body, SSL3_MT_CHANNEL_ID) ||
!tls1_write_channel_id(hs, &body) ||
- !ssl_add_message_cbb(ssl, &cbb)) {
- CBB_cleanup(&cbb);
+ !ssl_add_message_cbb(ssl, cbb.get())) {
return ssl_hs_error;
}
}
@@ -704,8 +719,8 @@ enum ssl_hs_wait_t tls13_client_handshake(SSL_HANDSHAKE *hs) {
}
int tls13_process_new_session_ticket(SSL *ssl) {
- bssl::UniquePtr<SSL_SESSION> session(SSL_SESSION_dup(
- ssl->s3->established_session, SSL_SESSION_INCLUDE_NONAUTH));
+ UniquePtr<SSL_SESSION> session(SSL_SESSION_dup(ssl->s3->established_session,
+ SSL_SESSION_INCLUDE_NONAUTH));
if (!session) {
return 0;
}
@@ -770,9 +785,11 @@ int tls13_process_new_session_ticket(SSL *ssl) {
}
void ssl_clear_tls13_state(SSL_HANDSHAKE *hs) {
- SSL_ECDH_CTX_cleanup(&hs->ecdh_ctx);
+ hs->key_share.reset();
OPENSSL_free(hs->key_share_bytes);
hs->key_share_bytes = NULL;
hs->key_share_bytes_len = 0;
}
+
+} // namespace bssl
diff --git a/src/ssl/tls13_enc.cc b/src/ssl/tls13_enc.cc
index 97f0ed93..1ae4849d 100644
--- a/src/ssl/tls13_enc.cc
+++ b/src/ssl/tls13_enc.cc
@@ -17,6 +17,8 @@
#include <assert.h>
#include <string.h>
+#include <utility>
+
#include <openssl/aead.h>
#include <openssl/bytestring.h>
#include <openssl/digest.h>
@@ -28,13 +30,15 @@
#include "internal.h"
+namespace bssl {
+
static int init_key_schedule(SSL_HANDSHAKE *hs, uint16_t version,
int algorithm_prf) {
- if (!SSL_TRANSCRIPT_init_hash(&hs->transcript, version, algorithm_prf)) {
+ if (!hs->transcript.InitHash(version, algorithm_prf)) {
return 0;
}
- hs->hash_len = SSL_TRANSCRIPT_digest_len(&hs->transcript);
+ hs->hash_len = hs->transcript.DigestLen();
/* Initialize the secret to the zero key. */
OPENSSL_memset(hs->secret, 0, hs->hash_len);
@@ -48,7 +52,7 @@ int tls13_init_key_schedule(SSL_HANDSHAKE *hs) {
return 0;
}
- SSL_TRANSCRIPT_free_buffer(&hs->transcript);
+ hs->transcript.FreeBuffer();
return 1;
}
@@ -60,9 +64,8 @@ int tls13_init_early_key_schedule(SSL_HANDSHAKE *hs) {
int tls13_advance_key_schedule(SSL_HANDSHAKE *hs, const uint8_t *in,
size_t len) {
- return HKDF_extract(hs->secret, &hs->hash_len,
- SSL_TRANSCRIPT_md(&hs->transcript), in, len, hs->secret,
- hs->hash_len);
+ return HKDF_extract(hs->secret, &hs->hash_len, hs->transcript.Digest(), in,
+ len, hs->secret, hs->hash_len);
}
static int hkdf_expand_label(uint8_t *out, const EVP_MD *digest,
@@ -71,20 +74,20 @@ static int hkdf_expand_label(uint8_t *out, const EVP_MD *digest,
const uint8_t *hash, size_t hash_len, size_t len) {
static const char kTLS13LabelVersion[] = "TLS 1.3, ";
- CBB cbb, child;
+ ScopedCBB cbb;
+ CBB child;
uint8_t *hkdf_label;
size_t hkdf_label_len;
- if (!CBB_init(&cbb, 2 + 1 + strlen(kTLS13LabelVersion) + label_len + 1 +
- hash_len) ||
- !CBB_add_u16(&cbb, len) ||
- !CBB_add_u8_length_prefixed(&cbb, &child) ||
+ if (!CBB_init(cbb.get(), 2 + 1 + strlen(kTLS13LabelVersion) + label_len + 1 +
+ hash_len) ||
+ !CBB_add_u16(cbb.get(), len) ||
+ !CBB_add_u8_length_prefixed(cbb.get(), &child) ||
!CBB_add_bytes(&child, (const uint8_t *)kTLS13LabelVersion,
strlen(kTLS13LabelVersion)) ||
!CBB_add_bytes(&child, label, label_len) ||
- !CBB_add_u8_length_prefixed(&cbb, &child) ||
+ !CBB_add_u8_length_prefixed(cbb.get(), &child) ||
!CBB_add_bytes(&child, hash, hash_len) ||
- !CBB_finish(&cbb, &hkdf_label, &hkdf_label_len)) {
- CBB_cleanup(&cbb);
+ !CBB_finish(cbb.get(), &hkdf_label, &hkdf_label_len)) {
return 0;
}
@@ -101,12 +104,11 @@ static int derive_secret(SSL_HANDSHAKE *hs, uint8_t *out, size_t len,
const uint8_t *label, size_t label_len) {
uint8_t context_hash[EVP_MAX_MD_SIZE];
size_t context_hash_len;
- if (!SSL_TRANSCRIPT_get_hash(&hs->transcript, context_hash,
- &context_hash_len)) {
+ if (!hs->transcript.GetHash(context_hash, &context_hash_len)) {
return 0;
}
- return hkdf_expand_label(out, SSL_TRANSCRIPT_md(&hs->transcript), hs->secret,
+ return hkdf_expand_label(out, hs->transcript.Digest(), hs->secret,
hs->hash_len, label, label_len, context_hash,
context_hash_len, len);
}
@@ -148,19 +150,19 @@ int tls13_set_traffic_key(SSL *ssl, enum evp_aead_direction_t direction,
return 0;
}
- SSL_AEAD_CTX *traffic_aead =
- SSL_AEAD_CTX_new(direction, version, SSL_is_dtls(ssl), session->cipher,
- key, key_len, NULL, 0, iv, iv_len);
- if (traffic_aead == NULL) {
+ UniquePtr<SSLAEADContext> traffic_aead = SSLAEADContext::Create(
+ direction, version, SSL_is_dtls(ssl), session->cipher, key, key_len, NULL,
+ 0, iv, iv_len);
+ if (!traffic_aead) {
return 0;
}
if (direction == evp_aead_open) {
- if (!ssl->method->set_read_state(ssl, traffic_aead)) {
+ if (!ssl->method->set_read_state(ssl, std::move(traffic_aead))) {
return 0;
}
} else {
- if (!ssl->method->set_write_state(ssl, traffic_aead)) {
+ if (!ssl->method->set_write_state(ssl, std::move(traffic_aead))) {
return 0;
}
}
@@ -309,11 +311,9 @@ int tls13_finished_mac(SSL_HANDSHAKE *hs, uint8_t *out, size_t *out_len,
uint8_t context_hash[EVP_MAX_MD_SIZE];
size_t context_hash_len;
- if (!SSL_TRANSCRIPT_get_hash(&hs->transcript, context_hash,
- &context_hash_len) ||
- !tls13_verify_data(SSL_TRANSCRIPT_md(&hs->transcript), out, out_len,
- traffic_secret, hs->hash_len, context_hash,
- context_hash_len)) {
+ if (!hs->transcript.GetHash(context_hash, &context_hash_len) ||
+ !tls13_verify_data(hs->transcript.Digest(), out, out_len, traffic_secret,
+ hs->hash_len, context_hash, context_hash_len)) {
return 0;
}
return 1;
@@ -379,21 +379,17 @@ int tls13_write_psk_binder(SSL_HANDSHAKE *hs, uint8_t *msg, size_t len) {
return 0;
}
- EVP_MD_CTX ctx;
- EVP_MD_CTX_init(&ctx);
+ ScopedEVP_MD_CTX ctx;
uint8_t context[EVP_MAX_MD_SIZE];
unsigned context_len;
- if (!EVP_DigestInit_ex(&ctx, digest, NULL) ||
- !EVP_DigestUpdate(&ctx, hs->transcript.buffer->data,
- hs->transcript.buffer->length) ||
- !EVP_DigestUpdate(&ctx, msg, len - hash_len - 3) ||
- !EVP_DigestFinal_ex(&ctx, context, &context_len)) {
- EVP_MD_CTX_cleanup(&ctx);
+ if (!EVP_DigestInit_ex(ctx.get(), digest, NULL) ||
+ !EVP_DigestUpdate(ctx.get(), hs->transcript.buffer_data(),
+ hs->transcript.buffer_len()) ||
+ !EVP_DigestUpdate(ctx.get(), msg, len - hash_len - 3) ||
+ !EVP_DigestFinal_ex(ctx.get(), context, &context_len)) {
return 0;
}
- EVP_MD_CTX_cleanup(&ctx);
-
uint8_t verify_data[EVP_MAX_MD_SIZE] = {0};
if (!tls13_psk_binder(verify_data, digest, ssl->session->master_key,
ssl->session->master_key_length, context, context_len,
@@ -407,7 +403,7 @@ int tls13_write_psk_binder(SSL_HANDSHAKE *hs, uint8_t *msg, size_t len) {
int tls13_verify_psk_binder(SSL_HANDSHAKE *hs, SSL_SESSION *session,
CBS *binders) {
- size_t hash_len = SSL_TRANSCRIPT_digest_len(&hs->transcript);
+ size_t hash_len = hs->transcript.DigestLen();
/* Get the full ClientHello, including message header. It must be large enough
* to exclude the binders. */
@@ -423,14 +419,13 @@ int tls13_verify_psk_binder(SSL_HANDSHAKE *hs, SSL_SESSION *session,
uint8_t context[EVP_MAX_MD_SIZE];
unsigned context_len;
if (!EVP_Digest(CBS_data(&message), CBS_len(&message) - CBS_len(binders) - 2,
- context, &context_len, SSL_TRANSCRIPT_md(&hs->transcript),
- NULL)) {
+ context, &context_len, hs->transcript.Digest(), NULL)) {
return 0;
}
uint8_t verify_data[EVP_MAX_MD_SIZE] = {0};
CBS binder;
- if (!tls13_psk_binder(verify_data, SSL_TRANSCRIPT_md(&hs->transcript),
+ if (!tls13_psk_binder(verify_data, hs->transcript.Digest(),
session->master_key, session->master_key_length,
context, context_len, hash_len) ||
/* We only consider the first PSK, so compare against the first binder. */
@@ -452,3 +447,5 @@ int tls13_verify_psk_binder(SSL_HANDSHAKE *hs, SSL_SESSION *session,
return 1;
}
+
+} // namespace bssl
diff --git a/src/ssl/tls13_server.cc b/src/ssl/tls13_server.cc
index 4e66016f..067c427c 100644
--- a/src/ssl/tls13_server.cc
+++ b/src/ssl/tls13_server.cc
@@ -36,6 +36,8 @@
#include "internal.h"
+namespace bssl {
+
enum server_hs_state_t {
state_select_parameters = 0,
state_select_session,
@@ -157,40 +159,38 @@ static int add_new_session_tickets(SSL_HANDSHAKE *hs) {
* the client makes several connections before getting a renewal. */
static const int kNumTickets = 2;
- SSL_SESSION *session = hs->new_session;
- CBB cbb;
- CBB_zero(&cbb);
-
/* Rebase the session timestamp so that it is measured from ticket
* issuance. */
- ssl_session_rebase_time(ssl, session);
+ ssl_session_rebase_time(ssl, hs->new_session.get());
for (int i = 0; i < kNumTickets; i++) {
- if (!RAND_bytes((uint8_t *)&session->ticket_age_add, 4)) {
- goto err;
+ if (!RAND_bytes((uint8_t *)&hs->new_session->ticket_age_add, 4)) {
+ return 0;
}
- session->ticket_age_add_valid = 1;
+ hs->new_session->ticket_age_add_valid = 1;
+ ScopedCBB cbb;
CBB body, ticket, extensions;
- if (!ssl->method->init_message(ssl, &cbb, &body,
+ if (!ssl->method->init_message(ssl, cbb.get(), &body,
SSL3_MT_NEW_SESSION_TICKET) ||
- !CBB_add_u32(&body, session->timeout) ||
- !CBB_add_u32(&body, session->ticket_age_add) ||
+ !CBB_add_u32(&body, hs->new_session->timeout) ||
+ !CBB_add_u32(&body, hs->new_session->ticket_age_add) ||
!CBB_add_u16_length_prefixed(&body, &ticket) ||
- !ssl_encrypt_ticket(ssl, &ticket, session) ||
+ !ssl_encrypt_ticket(ssl, &ticket, hs->new_session.get()) ||
!CBB_add_u16_length_prefixed(&body, &extensions)) {
- goto err;
+ return 0;
}
if (ssl->cert->enable_early_data) {
- session->ticket_max_early_data = kMaxEarlyDataAccepted;
+ hs->new_session->ticket_max_early_data = kMaxEarlyDataAccepted;
CBB early_data_info;
if (!CBB_add_u16(&extensions, TLSEXT_TYPE_ticket_early_data_info) ||
!CBB_add_u16_length_prefixed(&extensions, &early_data_info) ||
- !CBB_add_u32(&early_data_info, session->ticket_max_early_data) ||
+ !CBB_add_u32(&early_data_info,
+ hs->new_session->ticket_max_early_data) ||
!CBB_flush(&extensions)) {
- goto err;
+ return 0;
}
}
@@ -198,19 +198,15 @@ static int add_new_session_tickets(SSL_HANDSHAKE *hs) {
if (!CBB_add_u16(&extensions,
ssl_get_grease_value(ssl, ssl_grease_ticket_extension)) ||
!CBB_add_u16(&extensions, 0 /* empty */)) {
- goto err;
+ return 0;
}
- if (!ssl_add_message_cbb(ssl, &cbb)) {
- goto err;
+ if (!ssl_add_message_cbb(ssl, cbb.get())) {
+ return 0;
}
}
return 1;
-
-err:
- CBB_cleanup(&cbb);
- return 0;
}
static enum ssl_hs_wait_t do_select_parameters(SSL_HANDSHAKE *hs) {
@@ -397,7 +393,7 @@ static enum ssl_hs_wait_t do_select_session(SSL_HANDSHAKE *hs) {
ssl->s3->session_reused = 1;
/* Resumption incorporates fresh key material, so refresh the timeout. */
- ssl_session_renew_timeout(ssl, hs->new_session,
+ ssl_session_renew_timeout(ssl, hs->new_session.get(),
ssl->session_ctx->session_psk_dhe_timeout);
break;
@@ -415,7 +411,7 @@ static enum ssl_hs_wait_t do_select_session(SSL_HANDSHAKE *hs) {
if (hs->hostname != NULL) {
OPENSSL_free(hs->new_session->tlsext_hostname);
- hs->new_session->tlsext_hostname = BUF_strdup(hs->hostname);
+ hs->new_session->tlsext_hostname = BUF_strdup(hs->hostname.get());
if (hs->new_session->tlsext_hostname == NULL) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
return ssl_hs_error;
@@ -479,9 +475,10 @@ static enum ssl_hs_wait_t do_select_session(SSL_HANDSHAKE *hs) {
static enum ssl_hs_wait_t do_send_hello_retry_request(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
- CBB cbb, body, extensions;
+ ScopedCBB cbb;
+ CBB body, extensions;
uint16_t group_id;
- if (!ssl->method->init_message(ssl, &cbb, &body,
+ if (!ssl->method->init_message(ssl, cbb.get(), &body,
SSL3_MT_HELLO_RETRY_REQUEST) ||
!CBB_add_u16(&body, ssl->version) ||
!tls1_get_shared_group(hs, &group_id) ||
@@ -489,8 +486,7 @@ static enum ssl_hs_wait_t do_send_hello_retry_request(SSL_HANDSHAKE *hs) {
!CBB_add_u16(&extensions, TLSEXT_TYPE_key_share) ||
!CBB_add_u16(&extensions, 2 /* length */) ||
!CBB_add_u16(&extensions, group_id) ||
- !ssl_add_message_cbb(ssl, &cbb)) {
- CBB_cleanup(&cbb);
+ !ssl_add_message_cbb(ssl, cbb.get())) {
return ssl_hs_error;
}
@@ -540,8 +536,9 @@ static enum ssl_hs_wait_t do_send_server_hello(SSL_HANDSHAKE *hs) {
}
/* Send a ServerHello. */
- CBB cbb, body, extensions, session_id;
- if (!ssl->method->init_message(ssl, &cbb, &body, SSL3_MT_SERVER_HELLO) ||
+ ScopedCBB cbb;
+ CBB body, extensions, session_id;
+ if (!ssl->method->init_message(ssl, cbb.get(), &body, SSL3_MT_SERVER_HELLO) ||
!CBB_add_u16(&body, version) ||
!RAND_bytes(ssl->s3->server_random, sizeof(ssl->s3->server_random)) ||
!CBB_add_bytes(&body, ssl->s3->server_random, SSL3_RANDOM_SIZE) ||
@@ -555,28 +552,28 @@ static enum ssl_hs_wait_t do_send_server_hello(SSL_HANDSHAKE *hs) {
!ssl_ext_key_share_add_serverhello(hs, &extensions) ||
(ssl->version == TLS1_3_EXPERIMENT_VERSION &&
!ssl_ext_supported_versions_add_serverhello(hs, &extensions)) ||
- !ssl_add_message_cbb(ssl, &cbb)) {
- goto err;
+ !ssl_add_message_cbb(ssl, cbb.get())) {
+ return ssl_hs_error;
}
if (ssl->version == TLS1_3_EXPERIMENT_VERSION &&
!ssl3_add_change_cipher_spec(ssl)) {
- goto err;
+ return ssl_hs_error;
}
/* Derive and enable the handshake traffic secrets. */
if (!tls13_derive_handshake_secrets(hs) ||
!tls13_set_traffic_key(ssl, evp_aead_seal, hs->server_handshake_secret,
hs->hash_len)) {
- goto err;
+ return ssl_hs_error;
}
/* Send EncryptedExtensions. */
- if (!ssl->method->init_message(ssl, &cbb, &body,
+ if (!ssl->method->init_message(ssl, cbb.get(), &body,
SSL3_MT_ENCRYPTED_EXTENSIONS) ||
!ssl_add_serverhello_tlsext(hs, &body) ||
- !ssl_add_message_cbb(ssl, &cbb)) {
- goto err;
+ !ssl_add_message_cbb(ssl, cbb.get())) {
+ return ssl_hs_error;
}
if (!ssl->s3->session_reused) {
@@ -592,15 +589,15 @@ static enum ssl_hs_wait_t do_send_server_hello(SSL_HANDSHAKE *hs) {
/* Send a CertificateRequest, if necessary. */
if (hs->cert_request) {
CBB sigalgs_cbb;
- if (!ssl->method->init_message(ssl, &cbb, &body,
+ if (!ssl->method->init_message(ssl, cbb.get(), &body,
SSL3_MT_CERTIFICATE_REQUEST) ||
!CBB_add_u8(&body, 0 /* no certificate_request_context. */) ||
!CBB_add_u16_length_prefixed(&body, &sigalgs_cbb) ||
!tls12_add_verify_sigalgs(ssl, &sigalgs_cbb) ||
!ssl_add_client_CA_list(ssl, &body) ||
!CBB_add_u16(&body, 0 /* empty certificate_extensions. */) ||
- !ssl_add_message_cbb(ssl, &cbb)) {
- goto err;
+ !ssl_add_message_cbb(ssl, cbb.get())) {
+ return ssl_hs_error;
}
}
@@ -608,11 +605,11 @@ static enum ssl_hs_wait_t do_send_server_hello(SSL_HANDSHAKE *hs) {
if (!ssl->s3->session_reused) {
if (!ssl_has_certificate(ssl)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CERTIFICATE_SET);
- goto err;
+ return ssl_hs_error;
}
if (!tls13_add_certificate(hs)) {
- goto err;
+ return ssl_hs_error;
}
hs->tls13_state = state_send_server_certificate_verify;
@@ -621,10 +618,6 @@ static enum ssl_hs_wait_t do_send_server_hello(SSL_HANDSHAKE *hs) {
hs->tls13_state = state_send_server_finished;
return ssl_hs_ok;
-
-err:
- CBB_cleanup(&cbb);
- return ssl_hs_error;
}
static enum ssl_hs_wait_t do_send_server_certificate_verify(SSL_HANDSHAKE *hs) {
@@ -678,12 +671,11 @@ static enum ssl_hs_wait_t do_send_server_finished(SSL_HANDSHAKE *hs) {
* TODO(davidben): This will need to be updated for DTLS 1.3. */
assert(!SSL_is_dtls(hs->ssl));
assert(hs->hash_len <= 0xff);
- uint8_t header[4] = {SSL3_MT_FINISHED, 0, 0, static_cast<uint8_t>(hs->hash_len)};
- if (!SSL_TRANSCRIPT_update(&hs->transcript, header, sizeof(header)) ||
- !SSL_TRANSCRIPT_update(&hs->transcript, hs->expected_client_finished,
- hs->hash_len) ||
- !tls13_derive_resumption_secret(hs) ||
- !add_new_session_tickets(hs)) {
+ uint8_t header[4] = {SSL3_MT_FINISHED, 0, 0,
+ static_cast<uint8_t>(hs->hash_len)};
+ if (!hs->transcript.Update(header, sizeof(header)) ||
+ !hs->transcript.Update(hs->expected_client_finished, hs->hash_len) ||
+ !tls13_derive_resumption_secret(hs) || !add_new_session_tickets(hs)) {
return ssl_hs_error;
}
}
@@ -766,6 +758,16 @@ static enum ssl_hs_wait_t do_process_client_certificate_verify(
return ssl_hs_ok;
}
+ switch (ssl_verify_peer_cert(hs)) {
+ case ssl_verify_ok:
+ break;
+ case ssl_verify_invalid:
+ return ssl_hs_error;
+ case ssl_verify_retry:
+ hs->tls13_state = state_process_client_certificate_verify;
+ return ssl_hs_certificate_verify;
+ }
+
if (!ssl_check_message_type(ssl, SSL3_MT_CERTIFICATE_VERIFY) ||
!tls13_process_certificate_verify(hs) ||
!ssl_hash_current_message(hs)) {
@@ -900,3 +902,5 @@ enum ssl_hs_wait_t tls13_server_handshake(SSL_HANDSHAKE *hs) {
return ssl_hs_ok;
}
+
+} // namespace bssl
diff --git a/src/ssl/tls_method.cc b/src/ssl/tls_method.cc
index d039b7db..4751e2e9 100644
--- a/src/ssl/tls_method.cc
+++ b/src/ssl/tls_method.cc
@@ -65,33 +65,34 @@
#include "internal.h"
+namespace bssl {
+
static int ssl3_supports_cipher(const SSL_CIPHER *cipher) { return 1; }
static void ssl3_expect_flight(SSL *ssl) {}
static void ssl3_received_flight(SSL *ssl) {}
-static int ssl3_set_read_state(SSL *ssl, SSL_AEAD_CTX *aead_ctx) {
+static int ssl3_set_read_state(SSL *ssl, UniquePtr<SSLAEADContext> aead_ctx) {
if (ssl->s3->rrec.length != 0) {
/* There may not be unprocessed record data at a cipher change. */
OPENSSL_PUT_ERROR(SSL, SSL_R_BUFFERED_MESSAGES_ON_CIPHER_CHANGE);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
- SSL_AEAD_CTX_free(aead_ctx);
return 0;
}
OPENSSL_memset(ssl->s3->read_sequence, 0, sizeof(ssl->s3->read_sequence));
- SSL_AEAD_CTX_free(ssl->s3->aead_read_ctx);
- ssl->s3->aead_read_ctx = aead_ctx;
+ Delete(ssl->s3->aead_read_ctx);
+ ssl->s3->aead_read_ctx = aead_ctx.release();
return 1;
}
-static int ssl3_set_write_state(SSL *ssl, SSL_AEAD_CTX *aead_ctx) {
+static int ssl3_set_write_state(SSL *ssl, UniquePtr<SSLAEADContext> aead_ctx) {
OPENSSL_memset(ssl->s3->write_sequence, 0, sizeof(ssl->s3->write_sequence));
- SSL_AEAD_CTX_free(ssl->s3->aead_write_ctx);
- ssl->s3->aead_write_ctx = aead_ctx;
+ Delete(ssl->s3->aead_write_ctx);
+ ssl->s3->aead_write_ctx = aead_ctx.release();
return 1;
}
@@ -120,6 +121,64 @@ static const SSL_PROTOCOL_METHOD kTLSProtocolMethod = {
ssl3_set_write_state,
};
+static int ssl_noop_x509_check_client_CA_names(
+ STACK_OF(CRYPTO_BUFFER) *names) {
+ return 1;
+}
+
+static void ssl_noop_x509_clear(CERT *cert) {}
+static void ssl_noop_x509_free(CERT *cert) {}
+static void ssl_noop_x509_dup(CERT *new_cert, const CERT *cert) {}
+static void ssl_noop_x509_flush_cached_leaf(CERT *cert) {}
+static void ssl_noop_x509_flush_cached_chain(CERT *cert) {}
+static int ssl_noop_x509_session_cache_objects(SSL_SESSION *sess) {
+ return 1;
+}
+static int ssl_noop_x509_session_dup(SSL_SESSION *new_session,
+ const SSL_SESSION *session) {
+ return 1;
+}
+static void ssl_noop_x509_session_clear(SSL_SESSION *session) {}
+static int ssl_noop_x509_session_verify_cert_chain(SSL_SESSION *session,
+ SSL *ssl,
+ uint8_t *out_alert) {
+ return 0;
+}
+
+static void ssl_noop_x509_hs_flush_cached_ca_names(SSL_HANDSHAKE *hs) {}
+static int ssl_noop_x509_ssl_new(SSL *ctx) { return 1; }
+static void ssl_noop_x509_ssl_free(SSL *ctx) { }
+static void ssl_noop_x509_ssl_flush_cached_client_CA(SSL *ssl) {}
+static int ssl_noop_x509_ssl_auto_chain_if_needed(SSL *ssl) { return 1; }
+static int ssl_noop_x509_ssl_ctx_new(SSL_CTX *ctx) { return 1; }
+static void ssl_noop_x509_ssl_ctx_free(SSL_CTX *ctx) { }
+static void ssl_noop_x509_ssl_ctx_flush_cached_client_CA(SSL_CTX *ctx) {}
+
+static const SSL_X509_METHOD ssl_noop_x509_method = {
+ ssl_noop_x509_check_client_CA_names,
+ ssl_noop_x509_clear,
+ ssl_noop_x509_free,
+ ssl_noop_x509_dup,
+ ssl_noop_x509_flush_cached_chain,
+ ssl_noop_x509_flush_cached_leaf,
+ ssl_noop_x509_session_cache_objects,
+ ssl_noop_x509_session_dup,
+ ssl_noop_x509_session_clear,
+ ssl_noop_x509_session_verify_cert_chain,
+ ssl_noop_x509_hs_flush_cached_ca_names,
+ ssl_noop_x509_ssl_new,
+ ssl_noop_x509_ssl_free,
+ ssl_noop_x509_ssl_flush_cached_client_CA,
+ ssl_noop_x509_ssl_auto_chain_if_needed,
+ ssl_noop_x509_ssl_ctx_new,
+ ssl_noop_x509_ssl_ctx_free,
+ ssl_noop_x509_ssl_ctx_flush_cached_client_CA,
+};
+
+} // namespace bssl
+
+using namespace bssl;
+
const SSL_METHOD *TLS_method(void) {
static const SSL_METHOD kMethod = {
0,
@@ -133,6 +192,15 @@ const SSL_METHOD *SSLv23_method(void) {
return TLS_method();
}
+const SSL_METHOD *TLS_with_buffers_method(void) {
+ static const SSL_METHOD kMethod = {
+ 0,
+ &kTLSProtocolMethod,
+ &ssl_noop_x509_method,
+ };
+ return &kMethod;
+}
+
/* Legacy version-locked methods. */
const SSL_METHOD *TLSv1_2_method(void) {
@@ -220,72 +288,3 @@ const SSL_METHOD *TLS_server_method(void) {
const SSL_METHOD *TLS_client_method(void) {
return TLS_method();
}
-
-static int ssl_noop_x509_check_client_CA_names(
- STACK_OF(CRYPTO_BUFFER) *names) {
- return 1;
-}
-
-static void ssl_noop_x509_clear(CERT *cert) {}
-static void ssl_noop_x509_free(CERT *cert) {}
-static void ssl_noop_x509_dup(CERT *new_cert, const CERT *cert) {}
-static void ssl_noop_x509_flush_cached_leaf(CERT *cert) {}
-static void ssl_noop_x509_flush_cached_chain(CERT *cert) {}
-static int ssl_noop_x509_session_cache_objects(SSL_SESSION *sess) {
- return 1;
-}
-static int ssl_noop_x509_session_dup(SSL_SESSION *new_session,
- const SSL_SESSION *session) {
- return 1;
-}
-static void ssl_noop_x509_session_clear(SSL_SESSION *session) {}
-static int ssl_noop_x509_session_verify_cert_chain(SSL_SESSION *session,
- SSL *ssl) {
- if (!ssl->ctx->i_promise_to_verify_certs_after_the_handshake) {
- ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNKNOWN_CA);
- OPENSSL_PUT_ERROR(SSL, SSL_R_CERTIFICATE_VERIFY_FAILED);
- return 0;
- }
-
- session->verify_result = X509_V_OK;
- return 1;
-}
-
-static void ssl_noop_x509_hs_flush_cached_ca_names(SSL_HANDSHAKE *hs) {}
-static int ssl_noop_x509_ssl_new(SSL *ctx) { return 1; }
-static void ssl_noop_x509_ssl_free(SSL *ctx) { }
-static void ssl_noop_x509_ssl_flush_cached_client_CA(SSL *ssl) {}
-static int ssl_noop_x509_ssl_auto_chain_if_needed(SSL *ssl) { return 1; }
-static int ssl_noop_x509_ssl_ctx_new(SSL_CTX *ctx) { return 1; }
-static void ssl_noop_x509_ssl_ctx_free(SSL_CTX *ctx) { }
-static void ssl_noop_x509_ssl_ctx_flush_cached_client_CA(SSL_CTX *ctx) {}
-
-static const SSL_X509_METHOD ssl_noop_x509_method = {
- ssl_noop_x509_check_client_CA_names,
- ssl_noop_x509_clear,
- ssl_noop_x509_free,
- ssl_noop_x509_dup,
- ssl_noop_x509_flush_cached_chain,
- ssl_noop_x509_flush_cached_leaf,
- ssl_noop_x509_session_cache_objects,
- ssl_noop_x509_session_dup,
- ssl_noop_x509_session_clear,
- ssl_noop_x509_session_verify_cert_chain,
- ssl_noop_x509_hs_flush_cached_ca_names,
- ssl_noop_x509_ssl_new,
- ssl_noop_x509_ssl_free,
- ssl_noop_x509_ssl_flush_cached_client_CA,
- ssl_noop_x509_ssl_auto_chain_if_needed,
- ssl_noop_x509_ssl_ctx_new,
- ssl_noop_x509_ssl_ctx_free,
- ssl_noop_x509_ssl_ctx_flush_cached_client_CA,
-};
-
-const SSL_METHOD *TLS_with_buffers_method(void) {
- static const SSL_METHOD kMethod = {
- 0,
- &kTLSProtocolMethod,
- &ssl_noop_x509_method,
- };
- return &kMethod;
-}
diff --git a/src/ssl/tls_record.cc b/src/ssl/tls_record.cc
index 47082960..437d02f1 100644
--- a/src/ssl/tls_record.cc
+++ b/src/ssl/tls_record.cc
@@ -119,6 +119,8 @@
#include "../crypto/internal.h"
+namespace bssl {
+
/* kMaxEmptyRecords is the number of consecutive, empty records that will be
* processed. Without this limit an attacker could send empty records at a
* faster rate than we can process and cause record processing to loop
@@ -140,10 +142,10 @@ static const uint8_t kMaxWarningAlerts = 4;
* state needs record-splitting and zero otherwise. */
static int ssl_needs_record_splitting(const SSL *ssl) {
#if !defined(BORINGSSL_UNSAFE_FUZZER_MODE)
- return ssl->s3->aead_write_ctx != NULL &&
- ssl->s3->aead_write_ctx->version < TLS1_1_VERSION &&
+ return !ssl->s3->aead_write_ctx->is_null_cipher() &&
+ ssl->s3->aead_write_ctx->version() < TLS1_1_VERSION &&
(ssl->mode & SSL_MODE_CBC_RECORD_SPLITTING) != 0 &&
- SSL_CIPHER_is_block_cipher(ssl->s3->aead_write_ctx->cipher);
+ SSL_CIPHER_is_block_cipher(ssl->s3->aead_write_ctx->cipher());
#else
return 0;
#endif
@@ -168,38 +170,19 @@ size_t ssl_record_prefix_len(const SSL *ssl) {
header_len = SSL3_RT_HEADER_LENGTH;
}
- return header_len + SSL_AEAD_CTX_explicit_nonce_len(ssl->s3->aead_read_ctx);
+ return header_len + ssl->s3->aead_read_ctx->ExplicitNonceLen();
}
size_t ssl_seal_align_prefix_len(const SSL *ssl) {
if (SSL_is_dtls(ssl)) {
- return DTLS1_RT_HEADER_LENGTH +
- SSL_AEAD_CTX_explicit_nonce_len(ssl->s3->aead_write_ctx);
+ return DTLS1_RT_HEADER_LENGTH + ssl->s3->aead_write_ctx->ExplicitNonceLen();
}
- size_t ret = SSL3_RT_HEADER_LENGTH +
- SSL_AEAD_CTX_explicit_nonce_len(ssl->s3->aead_write_ctx);
+ size_t ret =
+ SSL3_RT_HEADER_LENGTH + ssl->s3->aead_write_ctx->ExplicitNonceLen();
if (ssl_needs_record_splitting(ssl)) {
ret += SSL3_RT_HEADER_LENGTH;
- ret += ssl_cipher_get_record_split_len(ssl->s3->aead_write_ctx->cipher);
- }
- return ret;
-}
-
-size_t SSL_max_seal_overhead(const SSL *ssl) {
- if (SSL_is_dtls(ssl)) {
- return dtls_max_seal_overhead(ssl, dtls1_use_current_epoch);
- }
-
- size_t ret = SSL3_RT_HEADER_LENGTH;
- ret += SSL_AEAD_CTX_max_overhead(ssl->s3->aead_write_ctx);
- /* TLS 1.3 needs an extra byte for the encrypted record type. */
- if (ssl->s3->aead_write_ctx != NULL &&
- ssl->s3->aead_write_ctx->version >= TLS1_3_VERSION) {
- ret += 1;
- }
- if (ssl_needs_record_splitting(ssl)) {
- ret *= 2;
+ ret += ssl_cipher_get_record_split_len(ssl->s3->aead_write_ctx->cipher());
}
return ret;
}
@@ -223,7 +206,7 @@ enum ssl_open_record_t tls_open_record(SSL *ssl, uint8_t *out_type, CBS *out,
}
int version_ok;
- if (ssl->s3->aead_read_ctx == NULL) {
+ if (ssl->s3->aead_read_ctx->is_null_cipher()) {
/* Only check the first byte. Enforcing beyond that can prevent decoding
* version negotiation failure alerts. */
version_ok = (version >> 8) == SSL3_VERSION_MAJOR;
@@ -263,17 +246,16 @@ enum ssl_open_record_t tls_open_record(SSL *ssl, uint8_t *out_type, CBS *out,
/* Skip early data received when expecting a second ClientHello if we rejected
* 0RTT. */
if (ssl->s3->skip_early_data &&
- ssl->s3->aead_read_ctx == NULL &&
+ ssl->s3->aead_read_ctx->is_null_cipher() &&
type == SSL3_RT_APPLICATION_DATA) {
goto skipped_data;
}
/* Decrypt the body in-place. */
- if (!SSL_AEAD_CTX_open(ssl->s3->aead_read_ctx, out, type, version,
- ssl->s3->read_sequence, (uint8_t *)CBS_data(&body),
- CBS_len(&body))) {
- if (ssl->s3->skip_early_data &&
- ssl->s3->aead_read_ctx != NULL) {
+ if (!ssl->s3->aead_read_ctx->Open(out, type, version, ssl->s3->read_sequence,
+ (uint8_t *)CBS_data(&body),
+ CBS_len(&body))) {
+ if (ssl->s3->skip_early_data && !ssl->s3->aead_read_ctx->is_null_cipher()) {
ERR_clear_error();
goto skipped_data;
}
@@ -291,8 +273,8 @@ enum ssl_open_record_t tls_open_record(SSL *ssl, uint8_t *out_type, CBS *out,
}
/* TLS 1.3 hides the record type inside the encrypted data. */
- if (ssl->s3->aead_read_ctx != NULL &&
- ssl->s3->aead_read_ctx->version >= TLS1_3_VERSION) {
+ if (!ssl->s3->aead_read_ctx->is_null_cipher() &&
+ ssl->s3->aead_read_ctx->version() >= TLS1_3_VERSION) {
/* The outer record type is always application_data. */
if (type != SSL3_RT_APPLICATION_DATA) {
OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_OUTER_RECORD_TYPE);
@@ -373,8 +355,8 @@ static int do_seal_record(SSL *ssl, uint8_t *out_prefix, uint8_t *out,
/* TLS 1.3 hides the actual record type inside the encrypted data. */
uint8_t *extra_in = NULL;
size_t extra_in_len = 0;
- if (ssl->s3->aead_write_ctx != NULL &&
- ssl->s3->aead_write_ctx->version >= TLS1_3_VERSION) {
+ if (!ssl->s3->aead_write_ctx->is_null_cipher() &&
+ ssl->s3->aead_write_ctx->version() >= TLS1_3_VERSION) {
extra_in = &type;
extra_in_len = 1;
out_prefix[0] = SSL3_RT_APPLICATION_DATA;
@@ -397,18 +379,17 @@ static int do_seal_record(SSL *ssl, uint8_t *out_prefix, uint8_t *out,
out_prefix[2] = wire_version & 0xff;
/* Write the ciphertext, leaving two bytes for the length. */
- if (!SSL_AEAD_CTX_seal_scatter(
- ssl->s3->aead_write_ctx, out_prefix + SSL3_RT_HEADER_LENGTH, out,
- out_suffix, out_suffix_len, max_out_suffix_len, type, wire_version,
- ssl->s3->write_sequence, in, in_len, extra_in, extra_in_len) ||
+ if (!ssl->s3->aead_write_ctx->SealScatter(
+ out_prefix + SSL3_RT_HEADER_LENGTH, out, out_suffix, out_suffix_len,
+ max_out_suffix_len, type, wire_version, ssl->s3->write_sequence, in,
+ in_len, extra_in, extra_in_len) ||
!ssl_record_sequence_update(ssl->s3->write_sequence, 8)) {
return 0;
}
/* Fill in the length. */
const size_t ciphertext_len =
- SSL_AEAD_CTX_explicit_nonce_len(ssl->s3->aead_write_ctx) + in_len +
- *out_suffix_len;
+ ssl->s3->aead_write_ctx->ExplicitNonceLen() + in_len + *out_suffix_len;
if (ciphertext_len >= 1 << 15) {
OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
return 0;
@@ -430,10 +411,10 @@ static size_t tls_seal_scatter_prefix_len(const SSL *ssl, uint8_t type,
* will be placed in the prefix, as will four of the five bytes of the
* record header for the main record. The final byte will replace the first
* byte of the plaintext that was used in the small record. */
- ret += ssl_cipher_get_record_split_len(ssl->s3->aead_write_ctx->cipher);
+ ret += ssl_cipher_get_record_split_len(ssl->s3->aead_write_ctx->cipher());
ret += SSL3_RT_HEADER_LENGTH - 1;
} else {
- ret += SSL_AEAD_CTX_explicit_nonce_len(ssl->s3->aead_write_ctx);
+ ret += ssl->s3->aead_write_ctx->ExplicitNonceLen();
}
return ret;
}
@@ -441,7 +422,7 @@ static size_t tls_seal_scatter_prefix_len(const SSL *ssl, uint8_t type,
/* tls_seal_scatter_record seals a new record of type |type| and body |in| and
* splits it between |out_prefix|, |out|, and |out_suffix|. Exactly
* |tls_seal_scatter_prefix_len| bytes are written to |out_prefix|, |in_len|
- * bytes to |out|, and up to 1 + |SSL_AEAD_CTX_max_overhead| bytes to
+ * bytes to |out|, and up to 1 + |SSLAEADContext::MaxOverhead| bytes to
* |out_suffix|. |*out_suffix_len| is set to the actual number of bytes written
* to |out_suffix|. It returns one on success and zero on error. If enabled,
* |tls_seal_scatter_record| implements TLS 1.0 CBC 1/n-1 record splitting and
@@ -452,7 +433,7 @@ static int tls_seal_scatter_record(SSL *ssl, uint8_t *out_prefix, uint8_t *out,
const uint8_t *in, size_t in_len) {
if (type == SSL3_RT_APPLICATION_DATA && in_len > 1 &&
ssl_needs_record_splitting(ssl)) {
- assert(SSL_AEAD_CTX_explicit_nonce_len(ssl->s3->aead_write_ctx) == 0);
+ assert(ssl->s3->aead_write_ctx->ExplicitNonceLen() == 0);
const size_t prefix_len = SSL3_RT_HEADER_LENGTH;
/* Write the 1-byte fragment into |out_prefix|. */
@@ -461,8 +442,7 @@ static int tls_seal_scatter_record(SSL *ssl, uint8_t *out_prefix, uint8_t *out,
/* TODO(martinkr): Make AEAD code not complain if max_suffix_len is lower
* than |EVP_AEAD_max_overhead| but still sufficiently large. */
- size_t split_max_suffix_len =
- SSL_AEAD_CTX_max_suffix_len(ssl->s3->aead_write_ctx, 0);
+ size_t split_max_suffix_len = ssl->s3->aead_write_ctx->MaxSuffixLen(0);
size_t split_suffix_len = 0;
if (!do_seal_record(ssl, out_prefix, split_body, split_suffix,
&split_suffix_len, split_max_suffix_len, type, in, 1)) {
@@ -472,7 +452,7 @@ static int tls_seal_scatter_record(SSL *ssl, uint8_t *out_prefix, uint8_t *out,
size_t split_record_len = prefix_len + 1 + split_suffix_len;
assert(SSL3_RT_HEADER_LENGTH + ssl_cipher_get_record_split_len(
- ssl->s3->aead_write_ctx->cipher) ==
+ ssl->s3->aead_write_ctx->cipher()) ==
split_record_len);
/* Write the n-1-byte fragment. The header gets split between |out_prefix|
@@ -586,3 +566,25 @@ enum ssl_open_record_t ssl_process_alert(SSL *ssl, uint8_t *out_alert,
OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_ALERT_TYPE);
return ssl_open_record_error;
}
+
+} // namespace bssl
+
+using namespace bssl;
+
+size_t SSL_max_seal_overhead(const SSL *ssl) {
+ if (SSL_is_dtls(ssl)) {
+ return dtls_max_seal_overhead(ssl, dtls1_use_current_epoch);
+ }
+
+ size_t ret = SSL3_RT_HEADER_LENGTH;
+ ret += ssl->s3->aead_write_ctx->MaxOverhead();
+ /* TLS 1.3 needs an extra byte for the encrypted record type. */
+ if (!ssl->s3->aead_write_ctx->is_null_cipher() &&
+ ssl->s3->aead_write_ctx->version() >= TLS1_3_VERSION) {
+ ret += 1;
+ }
+ if (ssl_needs_record_splitting(ssl)) {
+ ret *= 2;
+ }
+ return ret;
+}
diff --git a/src/util/all_tests.go b/src/util/all_tests.go
index 235db05d..d3f9203a 100644
--- a/src/util/all_tests.go
+++ b/src/util/all_tests.go
@@ -162,7 +162,16 @@ func gdbOf(path string, args ...string) *exec.Cmd {
}
func sdeOf(cpu, path string, args ...string) *exec.Cmd {
- sdeArgs := []string{"-" + cpu, "--", path}
+ sdeArgs := []string{"-" + cpu}
+ // The kernel's vdso code for gettimeofday sometimes uses the RDTSCP
+ // instruction. Although SDE has a -chip_check_vsyscall flag that
+ // excludes such code by default, it does not seem to work. Instead,
+ // pass the -chip_check_exe_only flag which retains test coverage when
+ // statically linked and excludes the vdso.
+ if cpu == "p4p" || cpu == "pnr" || cpu == "mrm" || cpu == "slt" {
+ sdeArgs = append(sdeArgs, "-chip_check_exe_only")
+ }
+ sdeArgs = append(sdeArgs, "--", path)
sdeArgs = append(sdeArgs, args...)
return exec.Command(*sdePath, sdeArgs...)
}