This is horrible, but everything else I tried was worse. The goal with this CL is to take the extern "C" out of ssl/internal.h and move most symbols to namespace bssl, so we can start using C++ helpers and destructors without worry. Complications: - Public API functions must be extern "C" and match their declaration in ssl.h, which is unnamespaced. C++ really does not want you to interleave namespaced and unnamespaced things. One can actually write a namespaced extern "C" function, but this means, from C++'s perspective, the function is namespaced. Trying to namespace the public header would worked but ended up too deep a rabbithole. - Our STACK_OF macros do not work right in namespaces. - The typedefs for our exposed but opaque types are visible in the header files and copied into consuming projects as forward declarations. We ultimately want to give SSL a destructor, but clobbering an unnamespaced ssl_st::~ssl_st seems bad manners. - MSVC complains about ambiguous names if one typedefs SSL to bssl::SSL. This CL opts for: - ssl/*.cc must begin with #define BORINGSSL_INTERNAL_CXX_TYPES. This informs the public headers to create forward declarations which are compatible with our namespaces. - For now, C++-defined type FOO ends up at bssl::FOO with a typedef outside. Later I imagine we'll rename many of them. - Internal functions get namespace bssl, so we stop worrying about stomping the tls1_prf symbol. Exported C functions are stuck as they are. Rather than try anything weird, bite the bullet and reorder files which have a mix of public and private functions. I expect that over time, the public functions will become fairly small as we move logic to more idiomatic C++. Files without any public C functions can just be written normally. - To avoid MSVC troubles, some bssl types are renamed to CPlusPlusStyle in advance of them being made idiomatic C++. Bug: 132 Change-Id: Ic931895e117c38b14ff8d6e5a273e868796c7581 Reviewed-on: https://boringssl-review.googlesource.com/18124 Reviewed-by: David Benjamin <davidben@google.com>kris/onging/CECPQ3_patch15
@@ -317,11 +317,8 @@ 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; | |||
typedef struct ssl_st SSL; | |||
typedef struct ssl_ticket_aead_method_st SSL_TICKET_AEAD_METHOD; | |||
typedef struct st_ERR_FNS ERR_FNS; | |||
typedef struct v3_ext_ctx X509V3_CTX; | |||
@@ -338,6 +335,25 @@ typedef struct x509_trust_st X509_TRUST; | |||
typedef void *OPENSSL_BLOCK; | |||
/* The following opaque types are visible in public header files but are defined | |||
* internally in C++. For compatibility with projects which copy the historical | |||
* typedefs in forward declarations, the typedefs cannot change for external | |||
* consumers. The C++ implementation files define |BORINGSSL_INTERNAL_CXX_TYPES| | |||
* to namespace the underlying types. */ | |||
#if defined(BORINGSSL_INTERNAL_CXX_TYPES) | |||
extern "C++" { | |||
namespace bssl { | |||
struct SSLConnection; | |||
struct SSLMethod; | |||
} | |||
using SSL = bssl::SSLConnection; | |||
using SSL_METHOD = bssl::SSLMethod; | |||
} | |||
#else | |||
typedef struct ssl_st SSL; | |||
typedef struct ssl_method_st SSL_METHOD; | |||
#endif | |||
#if defined(__cplusplus) | |||
} /* extern C */ | |||
@@ -3983,8 +3983,26 @@ 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. */ | |||
#if defined(BORINGSSL_INTERNAL_CXX_TYPES) | |||
extern "C++" { | |||
namespace bssl { | |||
struct CERT; | |||
struct SSLProtocolMethod; | |||
struct SSLX509Method; | |||
} | |||
using SSL_CERT_CONFIG = bssl::CERT; | |||
using SSL_PROTOCOL_METHOD = bssl::SSLProtocolMethod; | |||
using SSL_X509_METHOD = bssl::SSLX509Method; | |||
} | |||
#else | |||
typedef struct ssl_cert_config_st SSL_CERT_CONFIG; | |||
typedef struct ssl_protocol_method_st SSL_PROTOCOL_METHOD; | |||
typedef struct ssl_x509_method_st SSL_X509_METHOD; | |||
#endif | |||
DECLARE_STACK_OF(SSL_CUSTOM_EXTENSION) | |||
struct ssl_cipher_st { | |||
/* name is the OpenSSL name for the cipher. */ | |||
@@ -4169,8 +4187,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 { | |||
@@ -4282,7 +4298,7 @@ struct ssl_ctx_st { | |||
uint32_t mode; | |||
uint32_t max_cert_list; | |||
struct cert_st /* CERT */ *cert; | |||
SSL_CERT_CONFIG *cert; | |||
/* callback that allows applications to peek at protocol messages */ | |||
void (*msg_callback)(int write_p, int version, int content_type, | |||
@@ -12,6 +12,8 @@ | |||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | |||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ | |||
#define BORINGSSL_INTERNAL_CXX_TYPES | |||
#include <openssl/ssl.h> | |||
#include <assert.h> | |||
@@ -25,6 +27,8 @@ | |||
#include "internal.h" | |||
namespace bssl { | |||
void SSL_CUSTOM_EXTENSION_free(SSL_CUSTOM_EXTENSION *custom_extension) { | |||
OPENSSL_free(custom_extension); | |||
} | |||
@@ -246,6 +250,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, | |||
@@ -111,6 +111,8 @@ | |||
* copied and put under another distribution licence | |||
* [including the GNU Public Licence.] */ | |||
#define BORINGSSL_INTERNAL_CXX_TYPES | |||
#include <openssl/ssl.h> | |||
#include <assert.h> | |||
@@ -127,6 +129,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 | |||
@@ -812,3 +816,5 @@ int dtls1_retransmit_outgoing_messages(SSL *ssl) { | |||
unsigned int dtls1_min_mtu(void) { | |||
return kMinMTU; | |||
} | |||
} // namespace bssl |
@@ -54,6 +54,8 @@ | |||
* (eay@cryptsoft.com). This product includes software written by Tim | |||
* Hudson (tjh@cryptsoft.com). */ | |||
#define BORINGSSL_INTERNAL_CXX_TYPES | |||
#include <openssl/ssl.h> | |||
#include <assert.h> | |||
@@ -68,6 +70,7 @@ | |||
#include "internal.h" | |||
namespace bssl { | |||
/* DTLS1_MTU_TIMEOUTS is the maximum number of timeouts to expire | |||
* before starting to decrease the MTU. */ | |||
@@ -113,10 +116,6 @@ void dtls1_free(SSL *ssl) { | |||
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 +134,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 +190,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); | |||
@@ -109,6 +109,8 @@ | |||
* copied and put under another distribution licence | |||
* [including the GNU Public Licence.] */ | |||
#define BORINGSSL_INTERNAL_CXX_TYPES | |||
#include <openssl/ssl.h> | |||
#include <assert.h> | |||
@@ -126,6 +128,8 @@ | |||
#include "internal.h" | |||
namespace bssl { | |||
int dtls1_get_record(SSL *ssl) { | |||
again: | |||
switch (ssl->s3->recv_shutdown) { | |||
@@ -415,3 +419,5 @@ int dtls1_dispatch_alert(SSL *ssl) { | |||
return 1; | |||
} | |||
} // namespace bssl |
@@ -114,6 +114,8 @@ | |||
Copyright (C) 2011, RTFM, Inc. | |||
*/ | |||
#define BORINGSSL_INTERNAL_CXX_TYPES | |||
#include <openssl/ssl.h> | |||
#include <string.h> | |||
@@ -124,6 +126,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 +147,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; | |||
@@ -54,6 +54,8 @@ | |||
* (eay@cryptsoft.com). This product includes software written by Tim | |||
* Hudson (tjh@cryptsoft.com). */ | |||
#define BORINGSSL_INTERNAL_CXX_TYPES | |||
#include <openssl/ssl.h> | |||
#include <assert.h> | |||
@@ -66,6 +68,8 @@ | |||
#include "internal.h" | |||
using namespace bssl; | |||
static int dtls1_supports_cipher(const SSL_CIPHER *cipher) { | |||
return cipher->algorithm_enc != SSL_eNULL; | |||
} | |||
@@ -109,6 +109,8 @@ | |||
* copied and put under another distribution licence | |||
* [including the GNU Public Licence.] */ | |||
#define BORINGSSL_INTERNAL_CXX_TYPES | |||
#include <openssl/ssl.h> | |||
#include <assert.h> | |||
@@ -121,6 +123,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]) { | |||
@@ -332,3 +336,5 @@ int dtls_seal_record(SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out, | |||
return 1; | |||
} | |||
} // namespace bssl |
@@ -147,6 +147,8 @@ | |||
* OTHERWISE. | |||
*/ | |||
#define BORINGSSL_INTERNAL_CXX_TYPES | |||
#include <openssl/ssl.h> | |||
#include <assert.h> | |||
@@ -168,6 +170,8 @@ | |||
#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); | |||
@@ -653,7 +657,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; | |||
@@ -1515,7 +1519,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)) { | |||
@@ -1696,7 +1700,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)) { | |||
@@ -1894,3 +1898,5 @@ err: | |||
} | |||
return -1; | |||
} | |||
} // namespace bssl |
@@ -146,6 +146,8 @@ | |||
* OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR | |||
* OTHERWISE. */ | |||
#define BORINGSSL_INTERNAL_CXX_TYPES | |||
#include <openssl/ssl.h> | |||
#include <assert.h> | |||
@@ -170,6 +172,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); | |||
@@ -825,12 +829,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; | |||
@@ -1001,7 +1005,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)) { | |||
@@ -1722,3 +1726,5 @@ static int ssl3_send_server_finished(SSL_HANDSHAKE *hs) { | |||
return ssl3_send_finished(hs); | |||
} | |||
} // namespace bssl |
@@ -142,6 +142,10 @@ | |||
#ifndef OPENSSL_HEADER_SSL_INTERNAL_H | |||
#define OPENSSL_HEADER_SSL_INTERNAL_H | |||
#if !defined(BORINGSSL_INTERNAL_CXX_TYPES) | |||
#error "Files including this header must define BORINGSSL_INTERNAL_CXX_TYPES before including any headers" | |||
#endif | |||
#include <openssl/base.h> | |||
#include <openssl/aead.h> | |||
@@ -158,12 +162,10 @@ OPENSSL_MSVC_PRAGMA(warning(pop)) | |||
#include <sys/time.h> | |||
#endif | |||
#if defined(__cplusplus) | |||
extern "C" { | |||
#endif | |||
namespace bssl { | |||
typedef struct ssl_handshake_st SSL_HANDSHAKE; | |||
struct SSL_HANDSHAKE; | |||
/* Protocol versions. | |||
* | |||
@@ -314,7 +316,7 @@ size_t ssl_cipher_get_record_split_len(const SSL_CIPHER *cipher); | |||
/* SSL_TRANSCRIPT maintains the handshake transcript as a combination of a | |||
* buffer and running hash. */ | |||
typedef struct ssl_transcript_st { | |||
struct SSL_TRANSCRIPT { | |||
/* buffer, if non-NULL, contains the handshake transcript. */ | |||
BUF_MEM *buffer; | |||
/* hash, if initialized with an |EVP_MD|, maintains the handshake hash. For | |||
@@ -323,7 +325,7 @@ typedef struct ssl_transcript_st { | |||
/* 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 | |||
@@ -395,7 +397,7 @@ int tls1_prf(const EVP_MD *digest, uint8_t *out, size_t out_len, | |||
/* SSL_AEAD_CTX contains information about an AEAD that is being used to encrypt | |||
* an SSL connection. */ | |||
typedef struct ssl_aead_ctx_st { | |||
struct SSL_AEAD_CTX { | |||
const SSL_CIPHER *cipher; | |||
EVP_AEAD_CTX ctx; | |||
/* fixed_nonce contains any bytes of the nonce that are fixed for all | |||
@@ -422,7 +424,7 @@ typedef struct ssl_aead_ctx_st { | |||
/* xor_fixed_nonce is non-zero 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 | |||
@@ -502,14 +504,14 @@ int SSL_AEAD_CTX_seal_scatter(SSL_AEAD_CTX *aead, uint8_t *out_prefix, | |||
/* 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 +660,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); | |||
@@ -683,11 +690,11 @@ int custom_ext_add_serverhello(SSL_HANDSHAKE *hs, CBB *extensions); | |||
/* ECDH groups. */ | |||
typedef struct ssl_ecdh_ctx_st SSL_ECDH_CTX; | |||
struct SSL_ECDH_CTX; | |||
/* An SSL_ECDH_METHOD is an implementation of ECDH-like key exchanges for | |||
* TLS. */ | |||
typedef struct ssl_ecdh_method_st { | |||
struct SSL_ECDH_METHOD { | |||
int nid; | |||
uint16_t group_id; | |||
const char name[8]; | |||
@@ -718,9 +725,9 @@ typedef struct ssl_ecdh_method_st { | |||
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 { | |||
struct SSL_ECDH_CTX { | |||
const SSL_ECDH_METHOD *method; | |||
void *data; | |||
}; | |||
@@ -785,12 +792,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); | |||
@@ -1010,7 +1017,7 @@ enum ssl_hs_wait_t { | |||
ssl_hs_certificate_verify, | |||
}; | |||
struct ssl_handshake_st { | |||
struct SSL_HANDSHAKE { | |||
/* ssl is a non-owning pointer to the parent |SSL| object. */ | |||
SSL *ssl; | |||
@@ -1237,7 +1244,7 @@ struct ssl_handshake_st { | |||
/* early_data_written is the amount of early data that has been written by the | |||
* record layer. */ | |||
uint16_t early_data_written; | |||
} /* SSL_HANDSHAKE */; | |||
}; | |||
SSL_HANDSHAKE *ssl_handshake_new(SSL *ssl); | |||
@@ -1327,11 +1334,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 | |||
@@ -1420,7 +1427,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 CERT { | |||
EVP_PKEY *privatekey; | |||
/* chain contains the certificate chain, with the leaf at the beginning. The | |||
@@ -1485,11 +1492,11 @@ 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 { | |||
/* SSLMethod backs the public |SSL_METHOD| type. It is a compatibility structure | |||
* to support the legacy version-locked methods. */ | |||
struct SSLMethod { | |||
/* version, if non-zero, is the only protocol version acceptable to an | |||
* SSL_CTX initialized from this method. */ | |||
uint16_t version; | |||
@@ -1501,8 +1508,9 @@ struct ssl_method_st { | |||
const SSL_X509_METHOD *x509_method; | |||
}; | |||
/* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */ | |||
struct ssl_protocol_method_st { | |||
/* SSLProtocolMethod is use to hold functions for SSLv2 or SSLv3/TLSv1 | |||
* functions */ | |||
struct SSLProtocolMethod { | |||
/* is_dtls is one if the protocol is DTLS and zero otherwise. */ | |||
char is_dtls; | |||
int (*ssl_new)(SSL *ssl); | |||
@@ -1570,7 +1578,7 @@ struct ssl_protocol_method_st { | |||
int (*set_write_state)(SSL *ssl, SSL_AEAD_CTX *aead_ctx); | |||
}; | |||
struct ssl_x509_method_st { | |||
struct SSLX509Method { | |||
/* 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. */ | |||
@@ -1626,20 +1634,20 @@ struct ssl_x509_method_st { | |||
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. */ | |||
@@ -1648,7 +1656,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. */ | |||
@@ -1658,7 +1666,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]; | |||
@@ -1825,7 +1833,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 | |||
@@ -1847,7 +1855,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. */ | |||
@@ -1860,14 +1868,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; | |||
@@ -1919,9 +1927,10 @@ 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. */ | |||
struct SSLConnection { | |||
/* method is the method table corresponding to the current protocol (DTLS or | |||
* TLS). */ | |||
const SSL_PROTOCOL_METHOD *method; | |||
@@ -1960,8 +1969,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, | |||
@@ -1977,7 +1986,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 | |||
@@ -2390,9 +2399,7 @@ void ssl_reset_error_state(SSL *ssl); | |||
#define SSL_FALLTHROUGH | |||
#endif | |||
} // namespace bssl | |||
#if defined(__cplusplus) | |||
} /* extern C */ | |||
#endif | |||
#endif /* OPENSSL_HEADER_SSL_INTERNAL_H */ |
@@ -110,6 +110,8 @@ | |||
* ECC cipher suite support in OpenSSL originally developed by | |||
* SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project. */ | |||
#define BORINGSSL_INTERNAL_CXX_TYPES | |||
#include <openssl/ssl.h> | |||
#include <assert.h> | |||
@@ -130,6 +132,8 @@ | |||
#include "internal.h" | |||
namespace bssl { | |||
SSL_HANDSHAKE *ssl_handshake_new(SSL *ssl) { | |||
SSL_HANDSHAKE *hs = (SSL_HANDSHAKE *)OPENSSL_malloc(sizeof(SSL_HANDSHAKE)); | |||
if (hs == NULL) { | |||
@@ -861,3 +865,5 @@ enum ssl_verify_result_t ssl_verify_peer_cert(SSL_HANDSHAKE *hs) { | |||
return ret; | |||
} | |||
} // namespace bssl |
@@ -146,6 +146,8 @@ | |||
* OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR | |||
* OTHERWISE. */ | |||
#define BORINGSSL_INTERNAL_CXX_TYPES | |||
#include <openssl/ssl.h> | |||
#include <assert.h> | |||
@@ -162,6 +164,8 @@ | |||
#include "internal.h" | |||
namespace bssl { | |||
int ssl3_new(SSL *ssl) { | |||
SSL3_STATE *s3 = (SSL3_STATE *)OPENSSL_malloc(sizeof *s3); | |||
if (s3 == NULL) { | |||
@@ -215,3 +219,5 @@ const struct ssl_cipher_preference_list_st *ssl_get_cipher_preferences( | |||
return ssl->ctx->cipher_list; | |||
} | |||
} // namespace bssl |
@@ -106,6 +106,8 @@ | |||
* (eay@cryptsoft.com). This product includes software written by Tim | |||
* Hudson (tjh@cryptsoft.com). */ | |||
#define BORINGSSL_INTERNAL_CXX_TYPES | |||
#include <openssl/ssl.h> | |||
#include <assert.h> | |||
@@ -122,6 +124,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 | |||
@@ -590,3 +594,5 @@ int ssl3_dispatch_alert(SSL *ssl) { | |||
return 1; | |||
} | |||
} // namespace bssl |
@@ -12,6 +12,8 @@ | |||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | |||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ | |||
#define BORINGSSL_INTERNAL_CXX_TYPES | |||
#include <openssl/ssl.h> | |||
#include <assert.h> | |||
@@ -25,6 +27,8 @@ | |||
#include "internal.h" | |||
namespace bssl { | |||
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, | |||
@@ -363,3 +367,5 @@ int SSL_AEAD_CTX_seal(SSL_AEAD_CTX *aead, uint8_t *out, size_t *out_len, | |||
*out_len = prefix_len + in_len + suffix_len; | |||
return 1; | |||
} | |||
} // namespace bssl |
@@ -87,6 +87,8 @@ | |||
#define __STDC_LIMIT_MACROS | |||
#endif | |||
#define BORINGSSL_INTERNAL_CXX_TYPES | |||
#include <openssl/ssl.h> | |||
#include <limits.h> | |||
@@ -102,6 +104,8 @@ | |||
#include "internal.h" | |||
namespace bssl { | |||
/* An SSL_SESSION is serialized as the following ASN.1 structure: | |||
* | |||
* SSLSession ::= SEQUENCE { | |||
@@ -422,55 +426,6 @@ static int SSL_SESSION_to_bytes_full(const SSL_SESSION *in, uint8_t **out_data, | |||
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 | |||
* explicitly tagged with |tag| from |cbs| and saves it in |*out|. On | |||
* entry, if |*out| is not NULL, it frees the existing contents. If | |||
@@ -805,6 +760,59 @@ err: | |||
return NULL; | |||
} | |||
} // 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); | |||
} | |||
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; | |||
@@ -12,6 +12,8 @@ | |||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | |||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ | |||
#define BORINGSSL_INTERNAL_CXX_TYPES | |||
#include <openssl/ssl.h> | |||
#include <assert.h> | |||
@@ -27,6 +29,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 +293,5 @@ int ssl_write_buffer_flush(SSL *ssl) { | |||
void ssl_write_buffer_clear(SSL *ssl) { | |||
clear_buffer(&ssl->s3->write_buffer); | |||
} | |||
} // namespace bssl |
@@ -112,6 +112,8 @@ | |||
* ECC cipher suite support in OpenSSL originally developed by | |||
* SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project. */ | |||
#define BORINGSSL_INTERNAL_CXX_TYPES | |||
#include <openssl/ssl.h> | |||
#include <assert.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) { | |||
@@ -340,20 +344,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,29 +383,6 @@ 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 && | |||
@@ -781,31 +748,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; | |||
@@ -866,6 +808,72 @@ int ssl_on_certificate_selected(SSL_HANDSHAKE *hs) { | |||
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; | |||
} | |||
static int set_signed_cert_timestamp_list(CERT *cert, const uint8_t *list, | |||
size_t list_len) { | |||
CBS sct_list; | |||
@@ -138,6 +138,8 @@ | |||
* OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR | |||
* OTHERWISE. */ | |||
#define BORINGSSL_INTERNAL_CXX_TYPES | |||
#include <openssl/ssl.h> | |||
#include <assert.h> | |||
@@ -154,6 +156,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 +647,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 +1367,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 +1374,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 +1753,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; | |||
} |
@@ -12,6 +12,8 @@ | |||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | |||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ | |||
#define BORINGSSL_INTERNAL_CXX_TYPES | |||
#include <openssl/ssl.h> | |||
#include <assert.h> | |||
@@ -29,6 +31,8 @@ | |||
#include "../crypto/internal.h" | |||
namespace bssl { | |||
/* |EC_POINT| implementation. */ | |||
static void ssl_ec_point_cleanup(SSL_ECDH_CTX *ctx) { | |||
@@ -38,15 +42,15 @@ static void ssl_ec_point_cleanup(SSL_ECDH_CTX *ctx) { | |||
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()); | |||
UniquePtr<BN_CTX> bn_ctx(BN_CTX_new()); | |||
if (!bn_ctx) { | |||
return 0; | |||
} | |||
bssl::BN_CTXScope scope(bn_ctx.get()); | |||
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()); | |||
UniquePtr<EC_GROUP> group(EC_GROUP_new_by_curve_name(ctx->method->nid)); | |||
UniquePtr<BIGNUM> private_key(BN_new()); | |||
if (!group || !private_key || | |||
!BN_rand_range_ex(private_key.get(), 1, | |||
EC_GROUP_get0_order(group.get()))) { | |||
@@ -54,7 +58,7 @@ static int ssl_ec_point_offer(SSL_ECDH_CTX *ctx, CBB *out) { | |||
} | |||
/* Compute the corresponding public key and serialize it. */ | |||
bssl::UniquePtr<EC_POINT> public_key(EC_POINT_new(group.get())); | |||
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()) || | |||
@@ -76,19 +80,19 @@ static int ssl_ec_point_finish(SSL_ECDH_CTX *ctx, uint8_t **out_secret, | |||
*out_alert = SSL_AD_INTERNAL_ERROR; | |||
/* Set up a shared |BN_CTX| for all operations. */ | |||
bssl::UniquePtr<BN_CTX> bn_ctx(BN_CTX_new()); | |||
UniquePtr<BN_CTX> bn_ctx(BN_CTX_new()); | |||
if (!bn_ctx) { | |||
return 0; | |||
} | |||
bssl::BN_CTXScope scope(bn_ctx.get()); | |||
BN_CTXScope scope(bn_ctx.get()); | |||
bssl::UniquePtr<EC_GROUP> group(EC_GROUP_new_by_curve_name(ctx->method->nid)); | |||
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())); | |||
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 0; | |||
@@ -110,7 +114,7 @@ static int ssl_ec_point_finish(SSL_ECDH_CTX *ctx, uint8_t **out_secret, | |||
/* 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)); | |||
UniquePtr<uint8_t> secret((uint8_t *)OPENSSL_malloc(secret_len)); | |||
if (!secret || !BN_bn2bin_padded(secret.get(), secret_len, x)) { | |||
return 0; | |||
} | |||
@@ -271,14 +275,6 @@ static const SSL_ECDH_METHOD *method_from_name(const char *name, size_t len) { | |||
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) { | |||
@@ -340,3 +336,15 @@ int SSL_ECDH_CTX_finish(SSL_ECDH_CTX *ctx, uint8_t **out_secret, | |||
return ctx->method->finish(ctx, out_secret, out_secret_len, out_alert, | |||
peer_key, peer_key_len); | |||
} | |||
} // namespace bssl | |||
using namespace bssl; | |||
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; | |||
} |
@@ -108,6 +108,8 @@ | |||
* | |||
*/ | |||
#define BORINGSSL_INTERNAL_CXX_TYPES | |||
#include <openssl/ssl.h> | |||
#include <errno.h> | |||
@@ -138,6 +138,8 @@ | |||
* OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR | |||
* OTHERWISE. */ | |||
#define BORINGSSL_INTERNAL_CXX_TYPES | |||
#include <openssl/ssl.h> | |||
#include <assert.h> | |||
@@ -162,6 +164,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 +189,225 @@ 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; | |||
} | |||
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 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; | |||
@@ -562,14 +785,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); | |||
@@ -621,14 +836,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 | |||
@@ -1108,16 +1315,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); } | |||
@@ -1820,56 +2017,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; | |||
@@ -2169,49 +2316,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); | |||
} | |||
@@ -2239,19 +2343,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; } | |||
@@ -2422,44 +2513,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; } | |||
@@ -2502,51 +2555,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; | |||
@@ -54,6 +54,8 @@ | |||
* copied and put under another distribution licence | |||
* [including the GNU Public Licence.] */ | |||
#define BORINGSSL_INTERNAL_CXX_TYPES | |||
#include <openssl/ssl.h> | |||
#include <assert.h> | |||
@@ -69,6 +71,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,227 +98,6 @@ static int ssl_set_pkey(CERT *cert, EVP_PKEY *pkey) { | |||
return 1; | |||
} | |||
int SSL_use_RSAPrivateKey(SSL *ssl, RSA *rsa) { | |||
EVP_PKEY *pkey; | |||
int ret; | |||
if (rsa == NULL) { | |||
OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER); | |||
return 0; | |||
} | |||
pkey = EVP_PKEY_new(); | |||
if (pkey == NULL) { | |||
OPENSSL_PUT_ERROR(SSL, ERR_R_EVP_LIB); | |||
return 0; | |||
} | |||
RSA_up_ref(rsa); | |||
EVP_PKEY_assign_RSA(pkey, rsa); | |||
ret = ssl_set_pkey(ssl->cert, pkey); | |||
EVP_PKEY_free(pkey); | |||
return ret; | |||
} | |||
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)); | |||
if (!rsa) { | |||
OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB); | |||
return 0; | |||
} | |||
return SSL_use_RSAPrivateKey(ssl, rsa.get()); | |||
} | |||
int SSL_use_PrivateKey(SSL *ssl, EVP_PKEY *pkey) { | |||
if (pkey == NULL) { | |||
OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER); | |||
return 0; | |||
} | |||
return ssl_set_pkey(ssl->cert, pkey); | |||
} | |||
int SSL_use_PrivateKey_ASN1(int type, SSL *ssl, const uint8_t *der, | |||
size_t der_len) { | |||
if (der_len > LONG_MAX) { | |||
OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW); | |||
return 0; | |||
} | |||
const uint8_t *p = der; | |||
EVP_PKEY *pkey = d2i_PrivateKey(type, NULL, &p, (long)der_len); | |||
if (pkey == NULL || p != der + der_len) { | |||
OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB); | |||
EVP_PKEY_free(pkey); | |||
return 0; | |||
} | |||
int ret = SSL_use_PrivateKey(ssl, pkey); | |||
EVP_PKEY_free(pkey); | |||
return ret; | |||
} | |||
int SSL_CTX_use_RSAPrivateKey(SSL_CTX *ctx, RSA *rsa) { | |||
int ret; | |||
EVP_PKEY *pkey; | |||
if (rsa == NULL) { | |||
OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER); | |||
return 0; | |||
} | |||
pkey = EVP_PKEY_new(); | |||
if (pkey == NULL) { | |||
OPENSSL_PUT_ERROR(SSL, ERR_R_EVP_LIB); | |||
return 0; | |||
} | |||
RSA_up_ref(rsa); | |||
EVP_PKEY_assign_RSA(pkey, rsa); | |||
ret = ssl_set_pkey(ctx->cert, pkey); | |||
EVP_PKEY_free(pkey); | |||
return ret; | |||
} | |||
int SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX *ctx, const uint8_t *der, | |||
size_t der_len) { | |||
RSA *rsa = RSA_private_key_from_bytes(der, der_len); | |||
if (rsa == NULL) { | |||
OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB); | |||
return 0; | |||
} | |||
int ret = SSL_CTX_use_RSAPrivateKey(ctx, rsa); | |||
RSA_free(rsa); | |||
return ret; | |||
} | |||
int SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey) { | |||
if (pkey == NULL) { | |||
OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER); | |||
return 0; | |||
} | |||
return ssl_set_pkey(ctx->cert, pkey); | |||
} | |||
int SSL_CTX_use_PrivateKey_ASN1(int type, SSL_CTX *ctx, const uint8_t *der, | |||
size_t der_len) { | |||
if (der_len > LONG_MAX) { | |||
OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW); | |||
return 0; | |||
} | |||
const uint8_t *p = der; | |||
EVP_PKEY *pkey = d2i_PrivateKey(type, NULL, &p, (long)der_len); | |||
if (pkey == NULL || p != der + der_len) { | |||
OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB); | |||
EVP_PKEY_free(pkey); | |||
return 0; | |||
} | |||
int ret = SSL_CTX_use_PrivateKey(ctx, pkey); | |||
EVP_PKEY_free(pkey); | |||
return ret; | |||
} | |||
void SSL_set_private_key_method(SSL *ssl, | |||
const SSL_PRIVATE_KEY_METHOD *key_method) { | |||
ssl->cert->key_method = key_method; | |||
} | |||
void SSL_CTX_set_private_key_method(SSL_CTX *ctx, | |||
const SSL_PRIVATE_KEY_METHOD *key_method) { | |||
ctx->cert->key_method = key_method; | |||
} | |||
static int set_algorithm_prefs(uint16_t **out_prefs, size_t *out_num_prefs, | |||
const uint16_t *prefs, size_t num_prefs) { | |||
OPENSSL_free(*out_prefs); | |||
*out_num_prefs = 0; | |||
*out_prefs = (uint16_t *)BUF_memdup(prefs, num_prefs * sizeof(prefs[0])); | |||
if (*out_prefs == NULL) { | |||
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); | |||
return 0; | |||
} | |||
*out_num_prefs = num_prefs; | |||
return 1; | |||
} | |||
int SSL_CTX_set_signing_algorithm_prefs(SSL_CTX *ctx, const uint16_t *prefs, | |||
size_t num_prefs) { | |||
return set_algorithm_prefs(&ctx->cert->sigalgs, &ctx->cert->num_sigalgs, | |||
prefs, num_prefs); | |||
} | |||
int SSL_set_signing_algorithm_prefs(SSL *ssl, const uint16_t *prefs, | |||
size_t num_prefs) { | |||
return set_algorithm_prefs(&ssl->cert->sigalgs, &ssl->cert->num_sigalgs, | |||
prefs, num_prefs); | |||
} | |||
int SSL_CTX_set_verify_algorithm_prefs(SSL_CTX *ctx, const uint16_t *prefs, | |||
size_t num_prefs) { | |||
return set_algorithm_prefs(&ctx->verify_sigalgs, &ctx->num_verify_sigalgs, | |||
prefs, num_prefs); | |||
} | |||
int SSL_set_private_key_digest_prefs(SSL *ssl, const int *digest_nids, | |||
size_t num_digests) { | |||
OPENSSL_free(ssl->cert->sigalgs); | |||
static_assert(sizeof(int) >= 2 * sizeof(uint16_t), | |||
"sigalgs allocation may overflow"); | |||
ssl->cert->num_sigalgs = 0; | |||
ssl->cert->sigalgs = | |||
(uint16_t *)OPENSSL_malloc(sizeof(uint16_t) * 2 * num_digests); | |||
if (ssl->cert->sigalgs == NULL) { | |||
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); | |||
return 0; | |||
} | |||
/* Convert the digest list to a signature algorithms list. | |||
* | |||
* TODO(davidben): Replace this API with one that can express RSA-PSS, etc. */ | |||
for (size_t i = 0; i < num_digests; i++) { | |||
switch (digest_nids[i]) { | |||
case NID_sha1: | |||
ssl->cert->sigalgs[ssl->cert->num_sigalgs] = SSL_SIGN_RSA_PKCS1_SHA1; | |||
ssl->cert->sigalgs[ssl->cert->num_sigalgs + 1] = SSL_SIGN_ECDSA_SHA1; | |||
ssl->cert->num_sigalgs += 2; | |||
break; | |||
case NID_sha256: | |||
ssl->cert->sigalgs[ssl->cert->num_sigalgs] = SSL_SIGN_RSA_PKCS1_SHA256; | |||
ssl->cert->sigalgs[ssl->cert->num_sigalgs + 1] = | |||
SSL_SIGN_ECDSA_SECP256R1_SHA256; | |||
ssl->cert->num_sigalgs += 2; | |||
break; | |||
case NID_sha384: | |||
ssl->cert->sigalgs[ssl->cert->num_sigalgs] = SSL_SIGN_RSA_PKCS1_SHA384; | |||
ssl->cert->sigalgs[ssl->cert->num_sigalgs + 1] = | |||
SSL_SIGN_ECDSA_SECP384R1_SHA384; | |||
ssl->cert->num_sigalgs += 2; | |||
break; | |||
case NID_sha512: | |||
ssl->cert->sigalgs[ssl->cert->num_sigalgs] = SSL_SIGN_RSA_PKCS1_SHA512; | |||
ssl->cert->sigalgs[ssl->cert->num_sigalgs + 1] = | |||
SSL_SIGN_ECDSA_SECP521R1_SHA512; | |||
ssl->cert->num_sigalgs += 2; | |||
break; | |||
} | |||
} | |||
return 1; | |||
} | |||
typedef struct { | |||
uint16_t sigalg; | |||
int pkey_type; | |||
@@ -537,3 +320,228 @@ int ssl_private_key_supports_signature_algorithm(SSL_HANDSHAKE *hs, | |||
return 1; | |||
} | |||
} // namespace bssl | |||
using namespace bssl; | |||
int SSL_use_RSAPrivateKey(SSL *ssl, RSA *rsa) { | |||
EVP_PKEY *pkey; | |||
int ret; | |||
if (rsa == NULL) { | |||
OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER); | |||
return 0; | |||
} | |||
pkey = EVP_PKEY_new(); | |||
if (pkey == NULL) { | |||
OPENSSL_PUT_ERROR(SSL, ERR_R_EVP_LIB); | |||
return 0; | |||
} | |||
RSA_up_ref(rsa); | |||
EVP_PKEY_assign_RSA(pkey, rsa); | |||
ret = ssl_set_pkey(ssl->cert, pkey); | |||
EVP_PKEY_free(pkey); | |||
return ret; | |||
} | |||
int SSL_use_RSAPrivateKey_ASN1(SSL *ssl, const uint8_t *der, size_t 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; | |||
} | |||
return SSL_use_RSAPrivateKey(ssl, rsa.get()); | |||
} | |||
int SSL_use_PrivateKey(SSL *ssl, EVP_PKEY *pkey) { | |||
if (pkey == NULL) { | |||
OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER); | |||
return 0; | |||
} | |||
return ssl_set_pkey(ssl->cert, pkey); | |||
} | |||
int SSL_use_PrivateKey_ASN1(int type, SSL *ssl, const uint8_t *der, | |||
size_t der_len) { | |||
if (der_len > LONG_MAX) { | |||
OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW); | |||
return 0; | |||
} | |||
const uint8_t *p = der; | |||
EVP_PKEY *pkey = d2i_PrivateKey(type, NULL, &p, (long)der_len); | |||
if (pkey == NULL || p != der + der_len) { | |||
OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB); | |||
EVP_PKEY_free(pkey); | |||
return 0; | |||
} | |||
int ret = SSL_use_PrivateKey(ssl, pkey); | |||
EVP_PKEY_free(pkey); | |||
return ret; | |||
} | |||
int SSL_CTX_use_RSAPrivateKey(SSL_CTX *ctx, RSA *rsa) { | |||
int ret; | |||
EVP_PKEY *pkey; | |||
if (rsa == NULL) { | |||
OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER); | |||
return 0; | |||
} | |||
pkey = EVP_PKEY_new(); | |||
if (pkey == NULL) { | |||
OPENSSL_PUT_ERROR(SSL, ERR_R_EVP_LIB); | |||
return 0; | |||
} | |||
RSA_up_ref(rsa); | |||
EVP_PKEY_assign_RSA(pkey, rsa); | |||
ret = ssl_set_pkey(ctx->cert, pkey); | |||
EVP_PKEY_free(pkey); | |||
return ret; | |||
} | |||
int SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX *ctx, const uint8_t *der, | |||
size_t der_len) { | |||
RSA *rsa = RSA_private_key_from_bytes(der, der_len); | |||
if (rsa == NULL) { | |||
OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB); | |||
return 0; | |||
} | |||
int ret = SSL_CTX_use_RSAPrivateKey(ctx, rsa); | |||
RSA_free(rsa); | |||
return ret; | |||
} | |||
int SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey) { | |||
if (pkey == NULL) { | |||
OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER); | |||
return 0; | |||
} | |||
return ssl_set_pkey(ctx->cert, pkey); | |||
} | |||
int SSL_CTX_use_PrivateKey_ASN1(int type, SSL_CTX *ctx, const uint8_t *der, | |||
size_t der_len) { | |||
if (der_len > LONG_MAX) { | |||
OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW); | |||
return 0; | |||
} | |||
const uint8_t *p = der; | |||
EVP_PKEY *pkey = d2i_PrivateKey(type, NULL, &p, (long)der_len); | |||
if (pkey == NULL || p != der + der_len) { | |||
OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB); | |||
EVP_PKEY_free(pkey); | |||
return 0; | |||
} | |||
int ret = SSL_CTX_use_PrivateKey(ctx, pkey); | |||
EVP_PKEY_free(pkey); | |||
return ret; | |||
} | |||
void SSL_set_private_key_method(SSL *ssl, | |||
const SSL_PRIVATE_KEY_METHOD *key_method) { | |||
ssl->cert->key_method = key_method; | |||
} | |||
void SSL_CTX_set_private_key_method(SSL_CTX *ctx, | |||
const SSL_PRIVATE_KEY_METHOD *key_method) { | |||
ctx->cert->key_method = key_method; | |||
} | |||
static int set_algorithm_prefs(uint16_t **out_prefs, size_t *out_num_prefs, | |||
const uint16_t *prefs, size_t num_prefs) { | |||
OPENSSL_free(*out_prefs); | |||
*out_num_prefs = 0; | |||
*out_prefs = (uint16_t *)BUF_memdup(prefs, num_prefs * sizeof(prefs[0])); | |||
if (*out_prefs == NULL) { | |||
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); | |||
return 0; | |||
} | |||
*out_num_prefs = num_prefs; | |||
return 1; | |||
} | |||
int SSL_CTX_set_signing_algorithm_prefs(SSL_CTX *ctx, const uint16_t *prefs, | |||
size_t num_prefs) { | |||
return set_algorithm_prefs(&ctx->cert->sigalgs, &ctx->cert->num_sigalgs, | |||
prefs, num_prefs); | |||
} | |||
int SSL_set_signing_algorithm_prefs(SSL *ssl, const uint16_t *prefs, | |||
size_t num_prefs) { | |||
return set_algorithm_prefs(&ssl->cert->sigalgs, &ssl->cert->num_sigalgs, | |||
prefs, num_prefs); | |||
} | |||
int SSL_CTX_set_verify_algorithm_prefs(SSL_CTX *ctx, const uint16_t *prefs, | |||
size_t num_prefs) { | |||
return set_algorithm_prefs(&ctx->verify_sigalgs, &ctx->num_verify_sigalgs, | |||
prefs, num_prefs); | |||
} | |||
int SSL_set_private_key_digest_prefs(SSL *ssl, const int *digest_nids, | |||
size_t num_digests) { | |||
OPENSSL_free(ssl->cert->sigalgs); | |||
static_assert(sizeof(int) >= 2 * sizeof(uint16_t), | |||
"sigalgs allocation may overflow"); | |||
ssl->cert->num_sigalgs = 0; | |||
ssl->cert->sigalgs = | |||
(uint16_t *)OPENSSL_malloc(sizeof(uint16_t) * 2 * num_digests); | |||
if (ssl->cert->sigalgs == NULL) { | |||
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); | |||
return 0; | |||
} | |||
/* Convert the digest list to a signature algorithms list. | |||
* | |||
* TODO(davidben): Replace this API with one that can express RSA-PSS, etc. */ | |||
for (size_t i = 0; i < num_digests; i++) { | |||
switch (digest_nids[i]) { | |||
case NID_sha1: | |||
ssl->cert->sigalgs[ssl->cert->num_sigalgs] = SSL_SIGN_RSA_PKCS1_SHA1; | |||
ssl->cert->sigalgs[ssl->cert->num_sigalgs + 1] = SSL_SIGN_ECDSA_SHA1; | |||
ssl->cert->num_sigalgs += 2; | |||
break; | |||
case NID_sha256: | |||
ssl->cert->sigalgs[ssl->cert->num_sigalgs] = SSL_SIGN_RSA_PKCS1_SHA256; | |||
ssl->cert->sigalgs[ssl->cert->num_sigalgs + 1] = | |||
SSL_SIGN_ECDSA_SECP256R1_SHA256; | |||
ssl->cert->num_sigalgs += 2; | |||
break; | |||
case NID_sha384: | |||
ssl->cert->sigalgs[ssl->cert->num_sigalgs] = SSL_SIGN_RSA_PKCS1_SHA384; | |||
ssl->cert->sigalgs[ssl->cert->num_sigalgs + 1] = | |||
SSL_SIGN_ECDSA_SECP384R1_SHA384; | |||
ssl->cert->num_sigalgs += 2; | |||
break; | |||
case NID_sha512: | |||
ssl->cert->sigalgs[ssl->cert->num_sigalgs] = SSL_SIGN_RSA_PKCS1_SHA512; | |||
ssl->cert->sigalgs[ssl->cert->num_sigalgs + 1] = | |||
SSL_SIGN_ECDSA_SECP521R1_SHA512; | |||
ssl->cert->num_sigalgs += 2; | |||
break; | |||
} | |||
} | |||
return 1; | |||
} |
@@ -133,6 +133,8 @@ | |||
* OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR | |||
* OTHERWISE. */ | |||
#define BORINGSSL_INTERNAL_CXX_TYPES | |||
#include <openssl/ssl.h> | |||
#include <assert.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. */ | |||
@@ -178,10 +182,6 @@ 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) { | |||
@@ -359,152 +359,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)) { | |||
@@ -595,8 +449,8 @@ err: | |||
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 +735,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); | |||
} | |||
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); | |||
} | |||
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 +1024,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 +1036,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 +1101,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; | |||
@@ -81,6 +81,8 @@ | |||
* OTHERWISE. | |||
*/ | |||
#define BORINGSSL_INTERNAL_CXX_TYPES | |||
#include <openssl/ssl.h> | |||
#include <assert.h> | |||
@@ -12,6 +12,8 @@ | |||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | |||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ | |||
#define BORINGSSL_INTERNAL_CXX_TYPES | |||
#include <stdio.h> | |||
#include <string.h> | |||
#include <time.h> | |||
@@ -1527,7 +1529,7 @@ TEST(SSLTest, SessionDuplication) { | |||
SSL_SESSION *session0 = SSL_get_session(client.get()); | |||
bssl::UniquePtr<SSL_SESSION> session1( | |||
SSL_SESSION_dup(session0, SSL_SESSION_DUP_ALL)); | |||
bssl::SSL_SESSION_dup(session0, SSL_SESSION_DUP_ALL)); | |||
ASSERT_TRUE(session1); | |||
session1->not_resumable = 0; | |||
@@ -133,6 +133,8 @@ | |||
* OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR | |||
* OTHERWISE. */ | |||
#define BORINGSSL_INTERNAL_CXX_TYPES | |||
#include <openssl/ssl.h> | |||
#include <assert.h> | |||
@@ -150,6 +152,8 @@ | |||
#include "internal.h" | |||
namespace bssl { | |||
int SSL_TRANSCRIPT_init(SSL_TRANSCRIPT *transcript) { | |||
SSL_TRANSCRIPT_cleanup(transcript); | |||
transcript->buffer = BUF_MEM_new(); | |||
@@ -403,3 +407,5 @@ int SSL_TRANSCRIPT_finish_mac(SSL_TRANSCRIPT *transcript, uint8_t *out, | |||
*out_len = kFinishedLen; | |||
return 1; | |||
} | |||
} // namespace bssl |
@@ -12,6 +12,8 @@ | |||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | |||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ | |||
#define BORINGSSL_INTERNAL_CXX_TYPES | |||
#include <openssl/ssl.h> | |||
#include <assert.h> | |||
@@ -23,6 +25,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 +145,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 +226,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 +257,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; | |||
@@ -372,3 +342,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); | |||
} |
@@ -138,6 +138,8 @@ | |||
* OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR | |||
* OTHERWISE. */ | |||
#define BORINGSSL_INTERNAL_CXX_TYPES | |||
#include <openssl/ssl.h> | |||
#include <assert.h> | |||
@@ -155,6 +157,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 +172,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) { | |||
@@ -785,6 +590,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); | |||
@@ -133,6 +133,8 @@ | |||
* OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR | |||
* OTHERWISE. */ | |||
#define BORINGSSL_INTERNAL_CXX_TYPES | |||
#include <openssl/ssl.h> | |||
#include <assert.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 | |||
@@ -442,34 +446,6 @@ int tls1_change_cipher_state(SSL_HANDSHAKE *hs, int which) { | |||
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); | |||
} | |||
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 tls1_generate_master_secret(SSL_HANDSHAKE *hs, uint8_t *out, | |||
const uint8_t *premaster, | |||
size_t premaster_len) { | |||
@@ -507,6 +483,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, | |||
@@ -106,6 +106,8 @@ | |||
* (eay@cryptsoft.com). This product includes software written by Tim | |||
* Hudson (tjh@cryptsoft.com). */ | |||
#define BORINGSSL_INTERNAL_CXX_TYPES | |||
#include <openssl/ssl.h> | |||
#include <assert.h> | |||
@@ -126,6 +128,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 +293,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 +498,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); | |||
@@ -2658,12 +2644,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 +3024,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 +3085,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; | |||
} | |||
@@ -3328,15 +3308,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 +3328,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) || | |||
@@ -3543,3 +3522,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; | |||
} |
@@ -16,6 +16,8 @@ | |||
#define __STDC_FORMAT_MACROS | |||
#endif | |||
#define BORINGSSL_INTERNAL_CXX_TYPES | |||
#include <openssl/base.h> | |||
#if !defined(OPENSSL_WINDOWS) | |||
@@ -1077,12 +1079,12 @@ class SocketCloser { | |||
}; | |||
static void ssl_ctx_add_session(SSL_SESSION *session, void *void_param) { | |||
SSL_SESSION *new_session = SSL_SESSION_dup( | |||
session, SSL_SESSION_INCLUDE_NONAUTH | SSL_SESSION_INCLUDE_TICKET); | |||
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, | |||
@@ -12,6 +12,8 @@ | |||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | |||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ | |||
#define BORINGSSL_INTERNAL_CXX_TYPES | |||
#include <openssl/ssl.h> | |||
#include <assert.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. */ | |||
@@ -403,7 +407,7 @@ 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), | |||
@@ -455,7 +459,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. */ | |||
@@ -532,7 +536,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) || | |||
@@ -560,7 +564,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); | |||
@@ -660,3 +664,5 @@ int tls13_post_handshake(SSL *ssl) { | |||
OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_MESSAGE); | |||
return 0; | |||
} | |||
} // namespace bssl |
@@ -12,6 +12,8 @@ | |||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | |||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ | |||
#define BORINGSSL_INTERNAL_CXX_TYPES | |||
#include <openssl/ssl.h> | |||
#include <assert.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, | |||
@@ -714,8 +718,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; | |||
} | |||
@@ -786,3 +790,5 @@ void ssl_clear_tls13_state(SSL_HANDSHAKE *hs) { | |||
hs->key_share_bytes = NULL; | |||
hs->key_share_bytes_len = 0; | |||
} | |||
} // namespace bssl |
@@ -12,6 +12,8 @@ | |||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | |||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ | |||
#define BORINGSSL_INTERNAL_CXX_TYPES | |||
#include <openssl/ssl.h> | |||
#include <assert.h> | |||
@@ -28,6 +30,8 @@ | |||
#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)) { | |||
@@ -452,3 +456,5 @@ int tls13_verify_psk_binder(SSL_HANDSHAKE *hs, SSL_SESSION *session, | |||
return 1; | |||
} | |||
} // namespace bssl |
@@ -19,6 +19,8 @@ | |||
#define __STDC_LIMIT_MACROS | |||
#endif | |||
#define BORINGSSL_INTERNAL_CXX_TYPES | |||
#include <openssl/ssl.h> | |||
#include <assert.h> | |||
@@ -36,6 +38,8 @@ | |||
#include "internal.h" | |||
namespace bssl { | |||
enum server_hs_state_t { | |||
state_select_parameters = 0, | |||
state_select_session, | |||
@@ -910,3 +914,5 @@ enum ssl_hs_wait_t tls13_server_handshake(SSL_HANDSHAKE *hs) { | |||
return ssl_hs_ok; | |||
} | |||
} // namespace bssl |
@@ -54,6 +54,8 @@ | |||
* copied and put under another distribution licence | |||
* [including the GNU Public Licence.] */ | |||
#define BORINGSSL_INTERNAL_CXX_TYPES | |||
#include <openssl/ssl.h> | |||
#include <assert.h> | |||
@@ -65,6 +67,8 @@ | |||
#include "internal.h" | |||
namespace bssl { | |||
static int ssl3_supports_cipher(const SSL_CIPHER *cipher) { return 1; } | |||
static void ssl3_expect_flight(SSL *ssl) {} | |||
@@ -120,6 +124,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 +195,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,66 +291,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, | |||
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, | |||
}; | |||
const SSL_METHOD *TLS_with_buffers_method(void) { | |||
static const SSL_METHOD kMethod = { | |||
0, | |||
&kTLSProtocolMethod, | |||
&ssl_noop_x509_method, | |||
}; | |||
return &kMethod; | |||
} |
@@ -106,6 +106,8 @@ | |||
* (eay@cryptsoft.com). This product includes software written by Tim | |||
* Hudson (tjh@cryptsoft.com). */ | |||
#define BORINGSSL_INTERNAL_CXX_TYPES | |||
#include <openssl/ssl.h> | |||
#include <assert.h> | |||
@@ -119,6 +121,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 | |||
@@ -186,24 +190,6 @@ size_t ssl_seal_align_prefix_len(const SSL *ssl) { | |||
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; | |||
} | |||
return ret; | |||
} | |||
enum ssl_open_record_t tls_open_record(SSL *ssl, uint8_t *out_type, CBS *out, | |||
size_t *out_consumed, uint8_t *out_alert, | |||
uint8_t *in, size_t in_len) { | |||
@@ -586,3 +572,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_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; | |||
} | |||
return ret; | |||
} |