If we need an extension, we can implement it in-library. Change-Id: I0eac5affcd8e7252b998b6c86ed2068234134b08 Reviewed-on: https://boringssl-review.googlesource.com/1051 Reviewed-by: Adam Langley <agl@google.com>kris/onging/CECPQ3_patch15
@@ -347,8 +347,6 @@ static int ssl23_client_hello(SSL *s) | |||
#endif | |||
if (s->ctx->tlsext_authz_server_audit_proof_cb != NULL) | |||
ssl2_compat = 0; | |||
if (s->ctx->custom_cli_ext_records_count != 0) | |||
ssl2_compat = 0; | |||
} | |||
#endif | |||
@@ -370,58 +370,6 @@ DECLARE_STACK_OF(SRTP_PROTECTION_PROFILE) | |||
typedef int (*tls_session_ticket_ext_cb_fn)(SSL *s, const unsigned char *data, int len, void *arg); | |||
typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len, STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg); | |||
#ifndef OPENSSL_NO_TLSEXT | |||
/* Callbacks and structures for handling custom TLS Extensions: | |||
* cli_ext_first_cb - sends data for ClientHello TLS Extension | |||
* cli_ext_second_cb - receives data from ServerHello TLS Extension | |||
* srv_ext_first_cb - receives data from ClientHello TLS Extension | |||
* srv_ext_second_cb - sends data for ServerHello TLS Extension | |||
* | |||
* All these functions return nonzero on success. Zero will terminate | |||
* the handshake (and return a specific TLS Fatal alert, if the function | |||
* declaration has an "al" parameter). -1 for the "sending" functions | |||
* will cause the TLS Extension to be omitted. | |||
* | |||
* "ext_type" is a TLS "ExtensionType" from 0-65535. | |||
* "in" is a pointer to TLS "extension_data" being provided to the cb. | |||
* "out" is used by the callback to return a pointer to "extension data" | |||
* which OpenSSL will later copy into the TLS handshake. The contents | |||
* of this buffer should not be changed until the handshake is complete. | |||
* "inlen" and "outlen" are TLS Extension lengths from 0-65535. | |||
* "al" is a TLS "AlertDescription" from 0-255 which WILL be sent as a | |||
* fatal TLS alert, if the callback returns zero. | |||
*/ | |||
typedef int (*custom_cli_ext_first_cb_fn)(SSL *s, unsigned short ext_type, | |||
const unsigned char **out, | |||
unsigned short *outlen, void *arg); | |||
typedef int (*custom_cli_ext_second_cb_fn)(SSL *s, unsigned short ext_type, | |||
const unsigned char *in, | |||
unsigned short inlen, int *al, | |||
void *arg); | |||
typedef int (*custom_srv_ext_first_cb_fn)(SSL *s, unsigned short ext_type, | |||
const unsigned char *in, | |||
unsigned short inlen, int *al, | |||
void *arg); | |||
typedef int (*custom_srv_ext_second_cb_fn)(SSL *s, unsigned short ext_type, | |||
const unsigned char **out, | |||
unsigned short *outlen, void *arg); | |||
typedef struct { | |||
unsigned short ext_type; | |||
custom_cli_ext_first_cb_fn fn1; | |||
custom_cli_ext_second_cb_fn fn2; | |||
void *arg; | |||
} custom_cli_ext_record; | |||
typedef struct { | |||
unsigned short ext_type; | |||
custom_srv_ext_first_cb_fn fn1; | |||
custom_srv_ext_second_cb_fn fn2; | |||
void *arg; | |||
} custom_srv_ext_record; | |||
#endif | |||
#ifndef OPENSSL_NO_SSL_INTERN | |||
/* used to hold info on the particular ciphers used */ | |||
@@ -1196,12 +1144,6 @@ struct ssl_ctx_st | |||
void *tlsext_authz_server_audit_proof_cb_arg; | |||
#endif | |||
/* Arrays containing the callbacks for custom TLS Extensions. */ | |||
custom_cli_ext_record *custom_cli_ext_records; | |||
size_t custom_cli_ext_records_count; | |||
custom_srv_ext_record *custom_srv_ext_records; | |||
size_t custom_srv_ext_records_count; | |||
/* If true, a client will advertise the Channel ID extension and a | |||
* server will echo it. */ | |||
char tlsext_channel_id_enabled; | |||
@@ -1345,32 +1287,6 @@ const char *SSL_get_psk_identity_hint(const SSL *s); | |||
const char *SSL_get_psk_identity(const SSL *s); | |||
#endif | |||
#ifndef OPENSSL_NO_TLSEXT | |||
/* Register callbacks to handle custom TLS Extensions as client or server. | |||
* | |||
* Returns nonzero on success. You cannot register twice for the same | |||
* extension number, and registering for an extension number already | |||
* handled by OpenSSL will succeed, but the callbacks will not be invoked. | |||
* | |||
* NULL can be registered for any callback function. For the client | |||
* functions, a NULL custom_cli_ext_first_cb_fn sends an empty ClientHello | |||
* Extension, and a NULL custom_cli_ext_second_cb_fn ignores the ServerHello | |||
* response (if any). | |||
* | |||
* For the server functions, a NULL custom_srv_ext_first_cb_fn means the | |||
* ClientHello extension's data will be ignored, but the extension will still | |||
* be noted and custom_srv_ext_second_cb_fn will still be invoked. A NULL | |||
* custom_srv_ext_second_cb doesn't send a ServerHello extension. | |||
*/ | |||
int SSL_CTX_set_custom_cli_ext(SSL_CTX *ctx, unsigned short ext_type, | |||
custom_cli_ext_first_cb_fn fn1, | |||
custom_cli_ext_second_cb_fn fn2, void *arg); | |||
int SSL_CTX_set_custom_srv_ext(SSL_CTX *ctx, unsigned short ext_type, | |||
custom_srv_ext_first_cb_fn fn1, | |||
custom_srv_ext_second_cb_fn fn2, void *arg); | |||
#endif | |||
#define SSL_NOTHING 1 | |||
#define SSL_WRITING 2 | |||
#define SSL_READING 3 | |||
@@ -2192,13 +2108,6 @@ int SSL_CTX_use_authz_file(SSL_CTX *ctx, const char *file); | |||
int SSL_use_authz_file(SSL *ssl, const char *file); | |||
#endif | |||
/* Set serverinfo data for the current active cert. */ | |||
int SSL_CTX_use_serverinfo(SSL_CTX *ctx, const unsigned char *serverinfo, | |||
size_t serverinfo_length); | |||
#ifndef OPENSSL_NO_STDIO | |||
int SSL_CTX_use_serverinfo_file(SSL_CTX *ctx, const char *file); | |||
#endif /* NO_STDIO */ | |||
#endif | |||
#ifndef OPENSSL_NO_STDIO | |||
@@ -2570,7 +2479,6 @@ void ERR_load_SSL_strings(void); | |||
#define SSL_F_dtls1_heartbeat 106 | |||
#define SSL_F_ssl3_digest_cached_records 107 | |||
#define SSL_F_SSL_set_wfd 108 | |||
#define SSL_F_SSL_CTX_use_serverinfo 109 | |||
#define SSL_F_ssl_set_pkey 110 | |||
#define SSL_F_SSL_CTX_use_certificate 111 | |||
#define SSL_F_dtls1_read_bytes 112 | |||
@@ -2611,7 +2519,6 @@ void ERR_load_SSL_strings(void); | |||
#define SSL_F_ssl3_get_record 147 | |||
#define SSL_F_SSL_CTX_use_RSAPrivateKey 148 | |||
#define SSL_F_SSL_use_certificate_file 149 | |||
#define SSL_F_SSL_CTX_use_serverinfo_file 150 | |||
#define SSL_F_SSL_load_client_CA_file 151 | |||
#define SSL_F_dtls1_preprocess_fragment 152 | |||
#define SSL_F_SSL_CTX_check_private_key 153 | |||
@@ -341,23 +341,6 @@ CERT *ssl_cert_dup(CERT *cert) | |||
cert->pkeys[i].authz, | |||
cert->pkeys[i].authz_length); | |||
} | |||
if (cert->pkeys[i].serverinfo != NULL) | |||
{ | |||
/* Just copy everything. */ | |||
ret->pkeys[i].serverinfo = | |||
OPENSSL_malloc(cert->pkeys[i].serverinfo_length); | |||
if (ret->pkeys[i].serverinfo == NULL) | |||
{ | |||
OPENSSL_PUT_ERROR(SSL, ssl_cert_dup, ERR_R_MALLOC_FAILURE); | |||
return NULL; | |||
} | |||
ret->pkeys[i].serverinfo_length = | |||
cert->pkeys[i].serverinfo_length; | |||
memcpy(ret->pkeys[i].serverinfo, | |||
cert->pkeys[i].serverinfo, | |||
cert->pkeys[i].serverinfo_length); | |||
} | |||
#endif | |||
} | |||
@@ -479,12 +462,6 @@ void ssl_cert_clear_certs(CERT *c) | |||
OPENSSL_free(cpk->authz); | |||
cpk->authz = NULL; | |||
} | |||
if (cpk->serverinfo) | |||
{ | |||
OPENSSL_free(cpk->serverinfo); | |||
cpk->serverinfo = NULL; | |||
cpk->serverinfo_length = 0; | |||
} | |||
#endif | |||
/* Clear all flags apart from explicit sign */ | |||
cpk->valid_flags &= CERT_PKEY_EXPLICIT_SIGN; | |||
@@ -36,8 +36,6 @@ const ERR_STRING_DATA SSL_error_string_data[] = { | |||
{ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_use_certificate_chain_file, 0), "SSL_CTX_use_certificate_chain_file"}, | |||
{ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_use_certificate_file, 0), "SSL_CTX_use_certificate_file"}, | |||
{ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_use_psk_identity_hint, 0), "SSL_CTX_use_psk_identity_hint"}, | |||
{ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_use_serverinfo, 0), "SSL_CTX_use_serverinfo"}, | |||
{ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_CTX_use_serverinfo_file, 0), "SSL_CTX_use_serverinfo_file"}, | |||
{ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SESSION_new, 0), "SSL_SESSION_new"}, | |||
{ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SESSION_print_fp, 0), "SSL_SESSION_print_fp"}, | |||
{ERR_PACK(ERR_LIB_SSL, SSL_F_SSL_SESSION_set1_id_context, 0), "SSL_SESSION_set1_id_context"}, | |||
@@ -1839,62 +1839,6 @@ void SSL_CTX_set_next_proto_select_cb(SSL_CTX *ctx, int (*cb) (SSL *s, unsigned | |||
} | |||
# endif | |||
int SSL_CTX_set_custom_cli_ext(SSL_CTX *ctx, unsigned short ext_type, | |||
custom_cli_ext_first_cb_fn fn1, | |||
custom_cli_ext_second_cb_fn fn2, void* arg) | |||
{ | |||
size_t i; | |||
custom_cli_ext_record* record; | |||
/* Check for duplicates */ | |||
for (i=0; i < ctx->custom_cli_ext_records_count; i++) | |||
if (ext_type == ctx->custom_cli_ext_records[i].ext_type) | |||
return 0; | |||
ctx->custom_cli_ext_records = OPENSSL_realloc(ctx->custom_cli_ext_records, | |||
(ctx->custom_cli_ext_records_count + 1) * | |||
sizeof(custom_cli_ext_record)); | |||
if (!ctx->custom_cli_ext_records) { | |||
ctx->custom_cli_ext_records_count = 0; | |||
return 0; | |||
} | |||
ctx->custom_cli_ext_records_count++; | |||
record = &ctx->custom_cli_ext_records[ctx->custom_cli_ext_records_count - 1]; | |||
record->ext_type = ext_type; | |||
record->fn1 = fn1; | |||
record->fn2 = fn2; | |||
record->arg = arg; | |||
return 1; | |||
} | |||
int SSL_CTX_set_custom_srv_ext(SSL_CTX *ctx, unsigned short ext_type, | |||
custom_srv_ext_first_cb_fn fn1, | |||
custom_srv_ext_second_cb_fn fn2, void* arg) | |||
{ | |||
size_t i; | |||
custom_srv_ext_record* record; | |||
/* Check for duplicates */ | |||
for (i=0; i < ctx->custom_srv_ext_records_count; i++) | |||
if (ext_type == ctx->custom_srv_ext_records[i].ext_type) | |||
return 0; | |||
ctx->custom_srv_ext_records = OPENSSL_realloc(ctx->custom_srv_ext_records, | |||
(ctx->custom_srv_ext_records_count + 1) * | |||
sizeof(custom_srv_ext_record)); | |||
if (!ctx->custom_srv_ext_records) { | |||
ctx->custom_srv_ext_records_count = 0; | |||
return 0; | |||
} | |||
ctx->custom_srv_ext_records_count++; | |||
record = &ctx->custom_srv_ext_records[ctx->custom_srv_ext_records_count - 1]; | |||
record->ext_type = ext_type; | |||
record->fn1 = fn1; | |||
record->fn2 = fn2; | |||
record->arg = arg; | |||
return 1; | |||
} | |||
/* SSL_CTX_set_alpn_protos sets the ALPN protocol list on |ctx| to |protos|. | |||
* |protos| must be in wire-format (i.e. a series of non-empty, 8-bit | |||
* length-prefixed strings). | |||
@@ -2138,10 +2082,6 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth) | |||
ret->psk_client_callback=NULL; | |||
ret->psk_server_callback=NULL; | |||
#endif | |||
ret->custom_cli_ext_records = NULL; | |||
ret->custom_cli_ext_records_count = 0; | |||
ret->custom_srv_ext_records = NULL; | |||
ret->custom_srv_ext_records_count = 0; | |||
#ifndef OPENSSL_NO_BUF_FREELISTS | |||
ret->freelist_max_len = SSL_MAX_BUF_FREELIST_LEN_DEFAULT; | |||
ret->rbuf_freelist = OPENSSL_malloc(sizeof(SSL3_BUF_FREELIST)); | |||
@@ -2268,10 +2208,6 @@ void SSL_CTX_free(SSL_CTX *a) | |||
if (a->psk_identity_hint) | |||
OPENSSL_free(a->psk_identity_hint); | |||
#endif | |||
#ifndef OPENSSL_NO_TLSEXT | |||
OPENSSL_free(a->custom_cli_ext_records); | |||
OPENSSL_free(a->custom_srv_ext_records); | |||
#endif | |||
/* TODO(fork): remove. */ | |||
#if 0 | |||
@@ -2728,26 +2664,6 @@ unsigned char *ssl_get_authz_data(SSL *s, size_t *authz_length) | |||
return c->pkeys[i].authz; | |||
} | |||
int ssl_get_server_cert_serverinfo(SSL *s, const unsigned char **serverinfo, | |||
size_t *serverinfo_length) | |||
{ | |||
CERT *c = NULL; | |||
int i = 0; | |||
*serverinfo_length = 0; | |||
c = s->cert; | |||
i = ssl_get_server_cert_index(s); | |||
if (i == -1) | |||
return 0; | |||
if (c->pkeys[i].serverinfo == NULL) | |||
return 0; | |||
*serverinfo = c->pkeys[i].serverinfo; | |||
*serverinfo_length = c->pkeys[i].serverinfo_length; | |||
return 1; | |||
} | |||
#endif | |||
void ssl_update_cache(SSL *s,int mode) | |||
@@ -519,14 +519,6 @@ typedef struct cert_pkey_st | |||
* uint8_t data[length]; */ | |||
unsigned char *authz; | |||
size_t authz_length; | |||
/* serverinfo data for this certificate. The data is in TLS Extension | |||
* wire format, specifically it's a series of records like: | |||
* uint16_t extension_type; // (RFC 5246, 7.4.1.4, Extension) | |||
* uint16_t length; | |||
* uint8_t data[length]; */ | |||
unsigned char *serverinfo; | |||
size_t serverinfo_length; | |||
#endif | |||
/* Set if CERT_PKEY can be used with current SSL session: e.g. | |||
* appropriate curve, signature algorithms etc. If zero it can't be | |||
@@ -1030,8 +1022,6 @@ int ssl_undefined_const_function(const SSL *s); | |||
CERT_PKEY *ssl_get_server_send_pkey(const SSL *s); | |||
#ifndef OPENSSL_NO_TLSEXT | |||
unsigned char *ssl_get_authz_data(SSL *s, size_t *authz_length); | |||
int ssl_get_server_cert_serverinfo(SSL *s, const unsigned char **serverinfo, | |||
size_t *serverinfo_length); | |||
#endif | |||
EVP_PKEY *ssl_get_sign_pkey(SSL *s,const SSL_CIPHER *c, const EVP_MD **pmd); | |||
int ssl_cert_type(X509 *x,EVP_PKEY *pkey); | |||
@@ -850,138 +850,6 @@ static char authz_validate(const unsigned char *authz, size_t length) | |||
} | |||
} | |||
static int serverinfo_find_extension(const unsigned char *serverinfo, | |||
size_t serverinfo_length, | |||
unsigned short extension_type, | |||
const unsigned char **extension_data, | |||
unsigned short *extension_length) | |||
{ | |||
*extension_data = NULL; | |||
*extension_length = 0; | |||
if (serverinfo == NULL || serverinfo_length == 0) | |||
return 0; | |||
for (;;) | |||
{ | |||
unsigned short type = 0; /* uint16 */ | |||
unsigned short len = 0; /* uint16 */ | |||
/* end of serverinfo */ | |||
if (serverinfo_length == 0) | |||
return -1; /* Extension not found */ | |||
/* read 2-byte type field */ | |||
if (serverinfo_length < 2) | |||
return 0; /* Error */ | |||
type = (serverinfo[0] << 8) + serverinfo[1]; | |||
serverinfo += 2; | |||
serverinfo_length -= 2; | |||
/* read 2-byte len field */ | |||
if (serverinfo_length < 2) | |||
return 0; /* Error */ | |||
len = (serverinfo[0] << 8) + serverinfo[1]; | |||
serverinfo += 2; | |||
serverinfo_length -= 2; | |||
if (len > serverinfo_length) | |||
return 0; /* Error */ | |||
if (type == extension_type) | |||
{ | |||
*extension_data = serverinfo; | |||
*extension_length = len; | |||
return 1; /* Success */ | |||
} | |||
serverinfo += len; | |||
serverinfo_length -= len; | |||
} | |||
return 0; /* Error */ | |||
} | |||
static int serverinfo_srv_first_cb(SSL *s, unsigned short ext_type, | |||
const unsigned char *in, | |||
unsigned short inlen, int *al, | |||
void *arg) | |||
{ | |||
if (inlen != 0) | |||
{ | |||
*al = SSL_AD_DECODE_ERROR; | |||
return 0; | |||
} | |||
return 1; | |||
} | |||
static int serverinfo_srv_second_cb(SSL *s, unsigned short ext_type, | |||
const unsigned char **out, unsigned short *outlen, | |||
void *arg) | |||
{ | |||
const unsigned char *serverinfo = NULL; | |||
size_t serverinfo_length = 0; | |||
/* Is there serverinfo data for the chosen server cert? */ | |||
if ((ssl_get_server_cert_serverinfo(s, &serverinfo, | |||
&serverinfo_length)) != 0) | |||
{ | |||
/* Find the relevant extension from the serverinfo */ | |||
int retval = serverinfo_find_extension(serverinfo, serverinfo_length, | |||
ext_type, out, outlen); | |||
if (retval == 0) | |||
return 0; /* Error */ | |||
if (retval == -1) | |||
return -1; /* No extension found, don't send extension */ | |||
return 1; /* Send extension */ | |||
} | |||
return -1; /* No serverinfo data found, don't send extension */ | |||
} | |||
/* With a NULL context, this function just checks that the serverinfo data | |||
parses correctly. With a non-NULL context, it registers callbacks for | |||
the included extensions. */ | |||
static int serverinfo_process_buffer(const unsigned char *serverinfo, | |||
size_t serverinfo_length, SSL_CTX *ctx) | |||
{ | |||
if (serverinfo == NULL || serverinfo_length == 0) | |||
return 0; | |||
for (;;) | |||
{ | |||
unsigned short ext_type = 0; /* uint16 */ | |||
unsigned short len = 0; /* uint16 */ | |||
/* end of serverinfo */ | |||
if (serverinfo_length == 0) | |||
return 1; | |||
/* read 2-byte type field */ | |||
if (serverinfo_length < 2) | |||
return 0; | |||
/* FIXME: check for types we understand explicitly? */ | |||
/* Register callbacks for extensions */ | |||
ext_type = (serverinfo[0] << 8) + serverinfo[1]; | |||
if (ctx && !SSL_CTX_set_custom_srv_ext(ctx, ext_type, | |||
serverinfo_srv_first_cb, | |||
serverinfo_srv_second_cb, NULL)) | |||
return 0; | |||
serverinfo += 2; | |||
serverinfo_length -= 2; | |||
/* read 2-byte len field */ | |||
if (serverinfo_length < 2) | |||
return 0; | |||
len = (serverinfo[0] << 8) + serverinfo[1]; | |||
serverinfo += 2; | |||
serverinfo_length -= 2; | |||
if (len > serverinfo_length) | |||
return 0; | |||
serverinfo += len; | |||
serverinfo_length -= len; | |||
} | |||
} | |||
static const unsigned char *authz_find_data(const unsigned char *authz, | |||
size_t authz_length, | |||
unsigned char data_type, | |||
@@ -1059,49 +927,6 @@ int SSL_CTX_use_authz(SSL_CTX *ctx, unsigned char *authz, | |||
return ssl_set_authz(ctx->cert, authz, authz_length); | |||
} | |||
int SSL_CTX_use_serverinfo(SSL_CTX *ctx, const unsigned char *serverinfo, | |||
size_t serverinfo_length) | |||
{ | |||
if (ctx == NULL || serverinfo == NULL || serverinfo_length == 0) | |||
{ | |||
OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_serverinfo, ERR_R_PASSED_NULL_PARAMETER); | |||
return 0; | |||
} | |||
if (!serverinfo_process_buffer(serverinfo, serverinfo_length, NULL)) | |||
{ | |||
OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_serverinfo, SSL_R_INVALID_SERVERINFO_DATA); | |||
return 0; | |||
} | |||
if (!ssl_cert_inst(&ctx->cert)) | |||
{ | |||
OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_serverinfo, ERR_R_MALLOC_FAILURE); | |||
return 0; | |||
} | |||
if (ctx->cert->key == NULL) | |||
{ | |||
OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_serverinfo, ERR_R_INTERNAL_ERROR); | |||
return 0; | |||
} | |||
ctx->cert->key->serverinfo = OPENSSL_realloc(ctx->cert->key->serverinfo, | |||
serverinfo_length); | |||
if (ctx->cert->key->serverinfo == NULL) | |||
{ | |||
OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_serverinfo, ERR_R_MALLOC_FAILURE); | |||
return 0; | |||
} | |||
memcpy(ctx->cert->key->serverinfo, serverinfo, serverinfo_length); | |||
ctx->cert->key->serverinfo_length = serverinfo_length; | |||
/* Now that the serverinfo is validated and stored, go ahead and | |||
* register callbacks. */ | |||
if (!serverinfo_process_buffer(serverinfo, serverinfo_length, ctx)) | |||
{ | |||
OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_serverinfo, SSL_R_INVALID_SERVERINFO_DATA); | |||
return 0; | |||
} | |||
return 1; | |||
} | |||
int SSL_use_authz(SSL *ssl, unsigned char *authz, size_t authz_length) | |||
{ | |||
if (authz == NULL) | |||
@@ -1201,93 +1026,5 @@ int SSL_use_authz_file(SSL *ssl, const char *file) | |||
OPENSSL_free(authz); | |||
return ret; | |||
} | |||
int SSL_CTX_use_serverinfo_file(SSL_CTX *ctx, const char *file) | |||
{ | |||
unsigned char *serverinfo = NULL; | |||
size_t serverinfo_length = 0; | |||
unsigned char* extension = 0; | |||
long extension_length = 0; | |||
char* name = NULL; | |||
char* header = NULL; | |||
char namePrefix[] = "SERVERINFO FOR "; | |||
int ret = 0; | |||
BIO *bin = NULL; | |||
size_t num_extensions = 0; | |||
if (ctx == NULL || file == NULL) | |||
{ | |||
OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_serverinfo_file, ERR_R_PASSED_NULL_PARAMETER); | |||
goto end; | |||
} | |||
bin = BIO_new(BIO_s_file()); | |||
if (bin == NULL) | |||
{ | |||
OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_serverinfo_file, ERR_R_BUF_LIB); | |||
goto end; | |||
} | |||
if (BIO_read_filename(bin, file) <= 0) | |||
{ | |||
OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_serverinfo_file, ERR_R_SYS_LIB); | |||
goto end; | |||
} | |||
for (num_extensions=0;; num_extensions++) | |||
{ | |||
if (PEM_read_bio(bin, &name, &header, &extension, &extension_length) == 0) | |||
{ | |||
/* There must be at least one extension in this file */ | |||
if (num_extensions == 0) | |||
{ | |||
OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_serverinfo_file, SSL_R_NO_PEM_EXTENSIONS); | |||
goto end; | |||
} | |||
else /* End of file, we're done */ | |||
break; | |||
} | |||
/* Check that PEM name starts with "BEGIN SERVERINFO FOR " */ | |||
if (strlen(name) < strlen(namePrefix)) | |||
{ | |||
OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_serverinfo_file, SSL_R_PEM_NAME_TOO_SHORT); | |||
goto end; | |||
} | |||
if (strncmp(name, namePrefix, strlen(namePrefix)) != 0) | |||
{ | |||
OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_serverinfo_file, SSL_R_PEM_NAME_BAD_PREFIX); | |||
goto end; | |||
} | |||
/* Check that the decoded PEM data is plausible (valid length field) */ | |||
if (extension_length < 4 || (extension[2] << 8) + extension[3] != extension_length - 4) | |||
{ | |||
OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_serverinfo_file, SSL_R_BAD_DATA); | |||
goto end; | |||
} | |||
/* Append the decoded extension to the serverinfo buffer */ | |||
serverinfo = OPENSSL_realloc(serverinfo, serverinfo_length + extension_length); | |||
if (serverinfo == NULL) | |||
{ | |||
OPENSSL_PUT_ERROR(SSL, SSL_CTX_use_serverinfo_file, ERR_R_MALLOC_FAILURE); | |||
goto end; | |||
} | |||
memcpy(serverinfo + serverinfo_length, extension, extension_length); | |||
serverinfo_length += extension_length; | |||
OPENSSL_free(name); name = NULL; | |||
OPENSSL_free(header); header = NULL; | |||
OPENSSL_free(extension); extension = NULL; | |||
} | |||
ret = SSL_CTX_use_serverinfo(ctx, serverinfo, serverinfo_length); | |||
end: | |||
/* SSL_CTX_use_serverinfo makes a local copy of the serverinfo. */ | |||
OPENSSL_free(name); | |||
OPENSSL_free(header); | |||
OPENSSL_free(extension); | |||
OPENSSL_free(serverinfo); | |||
if (bin != NULL) | |||
BIO_free(bin); | |||
return ret; | |||
} | |||
#endif /* OPENSSL_NO_STDIO */ | |||
#endif /* OPENSSL_NO_TLSEXT */ |
@@ -1536,40 +1536,6 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *buf, unsigned c | |||
*(ret++) = TLSEXT_AUTHZDATAFORMAT_audit_proof; | |||
} | |||
/* Add custom TLS Extensions to ClientHello */ | |||
if (s->ctx->custom_cli_ext_records_count) | |||
{ | |||
size_t i; | |||
custom_cli_ext_record* record; | |||
for (i = 0; i < s->ctx->custom_cli_ext_records_count; i++) | |||
{ | |||
const unsigned char* out = NULL; | |||
unsigned short outlen = 0; | |||
record = &s->ctx->custom_cli_ext_records[i]; | |||
/* NULL callback sends empty extension */ | |||
/* -1 from callback omits extension */ | |||
if (record->fn1) | |||
{ | |||
int cb_retval = 0; | |||
cb_retval = record->fn1(s, record->ext_type, | |||
&out, &outlen, | |||
record->arg); | |||
if (cb_retval == 0) | |||
return NULL; /* error */ | |||
if (cb_retval == -1) | |||
continue; /* skip this extension */ | |||
} | |||
if (limit < ret + 4 + outlen) | |||
return NULL; | |||
s2n(record->ext_type, ret); | |||
s2n(outlen, ret); | |||
memcpy(ret, out, outlen); | |||
ret += outlen; | |||
} | |||
} | |||
#ifndef OPENSSL_NO_EC | |||
if (using_ecc) | |||
{ | |||
@@ -1886,47 +1852,6 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *buf, unsigned c | |||
} | |||
} | |||
/* If custom types were sent in ClientHello, add ServerHello responses */ | |||
if (s->s3->tlsext_custom_types_count) | |||
{ | |||
size_t i; | |||
for (i = 0; i < s->s3->tlsext_custom_types_count; i++) | |||
{ | |||
size_t j; | |||
custom_srv_ext_record *record; | |||
for (j = 0; j < s->ctx->custom_srv_ext_records_count; j++) | |||
{ | |||
record = &s->ctx->custom_srv_ext_records[j]; | |||
if (s->s3->tlsext_custom_types[i] == record->ext_type) | |||
{ | |||
const unsigned char *out = NULL; | |||
unsigned short outlen = 0; | |||
int cb_retval = 0; | |||
/* NULL callback or -1 omits extension */ | |||
if (!record->fn2) | |||
break; | |||
cb_retval = record->fn2(s, record->ext_type, | |||
&out, &outlen, | |||
record->arg); | |||
if (cb_retval == 0) | |||
return NULL; /* error */ | |||
if (cb_retval == -1) | |||
break; /* skip this extension */ | |||
if (limit < ret + 4 + outlen) | |||
return NULL; | |||
s2n(record->ext_type, ret); | |||
s2n(outlen, ret); | |||
memcpy(ret, out, outlen); | |||
ret += outlen; | |||
break; | |||
} | |||
} | |||
} | |||
} | |||
if (s->s3->alpn_selected) | |||
{ | |||
const uint8_t *selected = s->s3->alpn_selected; | |||
@@ -2130,14 +2055,6 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char | |||
s->s3->next_proto_neg_seen = 0; | |||
#endif | |||
/* Clear observed custom extensions */ | |||
s->s3->tlsext_custom_types_count = 0; | |||
if (s->s3->tlsext_custom_types != NULL) | |||
{ | |||
OPENSSL_free(s->s3->tlsext_custom_types); | |||
s->s3->tlsext_custom_types = NULL; | |||
} | |||
if (s->s3->alpn_selected) | |||
{ | |||
OPENSSL_free(s->s3->alpn_selected); | |||
@@ -2674,54 +2591,6 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char | |||
} | |||
} | |||
/* If this ClientHello extension was unhandled and this is | |||
* a nonresumed connection, check whether the extension is a | |||
* custom TLS Extension (has a custom_srv_ext_record), and if | |||
* so call the callback and record the extension number so that | |||
* an appropriate ServerHello may be later returned. | |||
*/ | |||
else if (!s->hit && s->ctx->custom_srv_ext_records_count) | |||
{ | |||
custom_srv_ext_record *record; | |||
for (i=0; i < s->ctx->custom_srv_ext_records_count; i++) | |||
{ | |||
record = &s->ctx->custom_srv_ext_records[i]; | |||
if (type == record->ext_type) | |||
{ | |||
size_t j; | |||
/* Error on duplicate TLS Extensions */ | |||
for (j = 0; j < s->s3->tlsext_custom_types_count; j++) | |||
{ | |||
if (type == s->s3->tlsext_custom_types[j]) | |||
{ | |||
*al = TLS1_AD_DECODE_ERROR; | |||
return 0; | |||
} | |||
} | |||
/* NULL callback still notes the extension */ | |||
if (record->fn1 && !record->fn1(s, type, data, size, al, record->arg)) | |||
return 0; | |||
/* Add the (non-duplicated) entry */ | |||
s->s3->tlsext_custom_types_count++; | |||
s->s3->tlsext_custom_types = OPENSSL_realloc( | |||
s->s3->tlsext_custom_types, | |||
s->s3->tlsext_custom_types_count * 2); | |||
if (s->s3->tlsext_custom_types == NULL) | |||
{ | |||
s->s3->tlsext_custom_types = 0; | |||
*al = TLS1_AD_INTERNAL_ERROR; | |||
return 0; | |||
} | |||
s->s3->tlsext_custom_types[ | |||
s->s3->tlsext_custom_types_count - 1] = type; | |||
} | |||
} | |||
} | |||
data+=size; | |||
} | |||
@@ -3057,31 +2926,6 @@ static int ssl_scan_serverhello_tlsext(SSL *s, CBS *cbs, int *out_alert) | |||
s->s3->tlsext_authz_server_promised = 1; | |||
} | |||
/* If this extension type was not otherwise handled, but | |||
* matches a custom_cli_ext_record, then send it to the c | |||
* callback */ | |||
/* TODO(fork): Can this be removed or transitioned to a | |||
* CBS-based API? It's only used in certificate_transparency to | |||
* parse the signed_certificate_timestamp extension which should | |||
* just be built-in. */ | |||
else if (s->ctx->custom_cli_ext_records_count) | |||
{ | |||
size_t i; | |||
custom_cli_ext_record* record; | |||
for (i = 0; i < s->ctx->custom_cli_ext_records_count; i++) | |||
{ | |||
record = &s->ctx->custom_cli_ext_records[i]; | |||
if (record->ext_type == type) | |||
{ | |||
if (record->fn2 && !record->fn2(s, type, CBS_data(&extension), CBS_len(&extension), out_alert, record->arg)) | |||
return 0; | |||
break; | |||
} | |||
} | |||
} | |||
} | |||
if (!s->hit && tlsext_servername == 1) | |||