summaryrefslogtreecommitdiffstats
path: root/src/ssl/ssl_asn1.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ssl/ssl_asn1.c')
-rw-r--r--src/ssl/ssl_asn1.c393
1 files changed, 152 insertions, 241 deletions
diff --git a/src/ssl/ssl_asn1.c b/src/ssl/ssl_asn1.c
index 0d4760d..76052df 100644
--- a/src/ssl/ssl_asn1.c
+++ b/src/ssl/ssl_asn1.c
@@ -80,8 +80,6 @@
* OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
* OTHERWISE. */
-#include <openssl/ssl.h>
-
#include <limits.h>
#include <string.h>
@@ -116,10 +114,8 @@
* signedCertTimestampList [15] OCTET STRING OPTIONAL,
* -- contents of SCT extension
* ocspResponse [16] OCTET STRING OPTIONAL,
- * -- stapled OCSP response from the server
+ * -- stapled OCSP response from the server
* extendedMasterSecret [17] BOOLEAN OPTIONAL,
- * keyExchangeInfo [18] INTEGER OPTIONAL,
- * certChain [19] SEQUENCE OF Certificate OPTIONAL,
* }
*
* Note: historically this serialization has included other optional
@@ -158,28 +154,8 @@ static const int kOCSPResponseTag =
CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 16;
static const int kExtendedMasterSecretTag =
CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 17;
-static const int kKeyExchangeInfoTag =
- CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 18;
-static const int kCertChainTag =
- CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 19;
-
-static int add_X509(CBB *cbb, X509 *x509) {
- int len = i2d_X509(x509, NULL);
- if (len < 0) {
- return 0;
- }
- uint8_t *buf;
- if (!CBB_add_space(cbb, &buf, len)) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- return 0;
- }
- if (buf != NULL && i2d_X509(x509, &buf) < 0) {
- return 0;
- }
- return 1;
-}
-static int SSL_SESSION_to_bytes_full(const SSL_SESSION *in, uint8_t **out_data,
+static int SSL_SESSION_to_bytes_full(SSL_SESSION *in, uint8_t **out_data,
size_t *out_len, int for_ticket) {
CBB cbb, session, child, child2;
@@ -187,9 +163,11 @@ static int SSL_SESSION_to_bytes_full(const SSL_SESSION *in, uint8_t **out_data,
return 0;
}
- CBB_zero(&cbb);
- if (!CBB_init(&cbb, 0) ||
- !CBB_add_asn1(&cbb, &session, CBS_ASN1_SEQUENCE) ||
+ if (!CBB_init(&cbb, 0)) {
+ return 0;
+ }
+
+ if (!CBB_add_asn1(&cbb, &session, CBS_ASN1_SEQUENCE) ||
!CBB_add_asn1_uint64(&session, SSL_SESSION_ASN1_VERSION) ||
!CBB_add_asn1_uint64(&session, in->ssl_version) ||
!CBB_add_asn1(&session, &child, CBS_ASN1_OCTETSTRING) ||
@@ -200,14 +178,14 @@ static int SSL_SESSION_to_bytes_full(const SSL_SESSION *in, uint8_t **out_data,
for_ticket ? 0 : in->session_id_length) ||
!CBB_add_asn1(&session, &child, CBS_ASN1_OCTETSTRING) ||
!CBB_add_bytes(&child, in->master_key, in->master_key_length)) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+ OPENSSL_PUT_ERROR(SSL, SSL_SESSION_to_bytes_full, ERR_R_MALLOC_FAILURE);
goto err;
}
if (in->time != 0) {
if (!CBB_add_asn1(&session, &child, kTimeTag) ||
!CBB_add_asn1_uint64(&child, in->time)) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+ OPENSSL_PUT_ERROR(SSL, SSL_SESSION_to_bytes_full, ERR_R_MALLOC_FAILURE);
goto err;
}
}
@@ -215,7 +193,7 @@ static int SSL_SESSION_to_bytes_full(const SSL_SESSION *in, uint8_t **out_data,
if (in->timeout != 0) {
if (!CBB_add_asn1(&session, &child, kTimeoutTag) ||
!CBB_add_asn1_uint64(&child, in->timeout)) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+ OPENSSL_PUT_ERROR(SSL, SSL_SESSION_to_bytes_full, ERR_R_MALLOC_FAILURE);
goto err;
}
}
@@ -223,11 +201,17 @@ static int SSL_SESSION_to_bytes_full(const SSL_SESSION *in, uint8_t **out_data,
/* The peer certificate is only serialized if the SHA-256 isn't
* serialized instead. */
if (in->peer && !in->peer_sha256_valid) {
- if (!CBB_add_asn1(&session, &child, kPeerTag)) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+ uint8_t *buf;
+ int len = i2d_X509(in->peer, NULL);
+ if (len < 0) {
+ goto err;
+ }
+ if (!CBB_add_asn1(&session, &child, kPeerTag) ||
+ !CBB_add_space(&child, &buf, len)) {
+ OPENSSL_PUT_ERROR(SSL, SSL_SESSION_to_bytes_full, ERR_R_MALLOC_FAILURE);
goto err;
}
- if (!add_X509(&child, in->peer)) {
+ if (buf != NULL && i2d_X509(in->peer, &buf) < 0) {
goto err;
}
}
@@ -237,14 +221,14 @@ static int SSL_SESSION_to_bytes_full(const SSL_SESSION *in, uint8_t **out_data,
if (!CBB_add_asn1(&session, &child, kSessionIDContextTag) ||
!CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) ||
!CBB_add_bytes(&child2, in->sid_ctx, in->sid_ctx_length)) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+ OPENSSL_PUT_ERROR(SSL, SSL_SESSION_to_bytes_full, ERR_R_MALLOC_FAILURE);
goto err;
}
if (in->verify_result != X509_V_OK) {
if (!CBB_add_asn1(&session, &child, kVerifyResultTag) ||
!CBB_add_asn1_uint64(&child, in->verify_result)) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+ OPENSSL_PUT_ERROR(SSL, SSL_SESSION_to_bytes_full, ERR_R_MALLOC_FAILURE);
goto err;
}
}
@@ -254,7 +238,7 @@ static int SSL_SESSION_to_bytes_full(const SSL_SESSION *in, uint8_t **out_data,
!CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) ||
!CBB_add_bytes(&child2, (const uint8_t *)in->tlsext_hostname,
strlen(in->tlsext_hostname))) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+ OPENSSL_PUT_ERROR(SSL, SSL_SESSION_to_bytes_full, ERR_R_MALLOC_FAILURE);
goto err;
}
}
@@ -264,7 +248,7 @@ static int SSL_SESSION_to_bytes_full(const SSL_SESSION *in, uint8_t **out_data,
!CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) ||
!CBB_add_bytes(&child2, (const uint8_t *)in->psk_identity,
strlen(in->psk_identity))) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+ OPENSSL_PUT_ERROR(SSL, SSL_SESSION_to_bytes_full, ERR_R_MALLOC_FAILURE);
goto err;
}
}
@@ -272,7 +256,7 @@ static int SSL_SESSION_to_bytes_full(const SSL_SESSION *in, uint8_t **out_data,
if (in->tlsext_tick_lifetime_hint > 0) {
if (!CBB_add_asn1(&session, &child, kTicketLifetimeHintTag) ||
!CBB_add_asn1_uint64(&child, in->tlsext_tick_lifetime_hint)) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+ OPENSSL_PUT_ERROR(SSL, SSL_SESSION_to_bytes_full, ERR_R_MALLOC_FAILURE);
goto err;
}
}
@@ -281,7 +265,7 @@ static int SSL_SESSION_to_bytes_full(const SSL_SESSION *in, uint8_t **out_data,
if (!CBB_add_asn1(&session, &child, kTicketTag) ||
!CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) ||
!CBB_add_bytes(&child2, in->tlsext_tick, in->tlsext_ticklen)) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+ OPENSSL_PUT_ERROR(SSL, SSL_SESSION_to_bytes_full, ERR_R_MALLOC_FAILURE);
goto err;
}
}
@@ -290,7 +274,7 @@ static int SSL_SESSION_to_bytes_full(const SSL_SESSION *in, uint8_t **out_data,
if (!CBB_add_asn1(&session, &child, kPeerSHA256Tag) ||
!CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) ||
!CBB_add_bytes(&child2, in->peer_sha256, sizeof(in->peer_sha256))) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+ OPENSSL_PUT_ERROR(SSL, SSL_SESSION_to_bytes_full, ERR_R_MALLOC_FAILURE);
goto err;
}
}
@@ -300,7 +284,7 @@ static int SSL_SESSION_to_bytes_full(const SSL_SESSION *in, uint8_t **out_data,
!CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) ||
!CBB_add_bytes(&child2, in->original_handshake_hash,
in->original_handshake_hash_len)) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+ OPENSSL_PUT_ERROR(SSL, SSL_SESSION_to_bytes_full, ERR_R_MALLOC_FAILURE);
goto err;
}
}
@@ -310,7 +294,7 @@ static int SSL_SESSION_to_bytes_full(const SSL_SESSION *in, uint8_t **out_data,
!CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) ||
!CBB_add_bytes(&child2, in->tlsext_signed_cert_timestamp_list,
in->tlsext_signed_cert_timestamp_list_length)) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+ OPENSSL_PUT_ERROR(SSL, SSL_SESSION_to_bytes_full, ERR_R_MALLOC_FAILURE);
goto err;
}
}
@@ -319,7 +303,7 @@ static int SSL_SESSION_to_bytes_full(const SSL_SESSION *in, uint8_t **out_data,
if (!CBB_add_asn1(&session, &child, kOCSPResponseTag) ||
!CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) ||
!CBB_add_bytes(&child2, in->ocsp_response, in->ocsp_response_length)) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+ OPENSSL_PUT_ERROR(SSL, SSL_SESSION_to_bytes_full, ERR_R_MALLOC_FAILURE);
goto err;
}
}
@@ -328,35 +312,13 @@ static int SSL_SESSION_to_bytes_full(const SSL_SESSION *in, uint8_t **out_data,
if (!CBB_add_asn1(&session, &child, kExtendedMasterSecretTag) ||
!CBB_add_asn1(&child, &child2, CBS_ASN1_BOOLEAN) ||
!CBB_add_u8(&child2, 0xff)) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+ OPENSSL_PUT_ERROR(SSL, SSL_SESSION_to_bytes_full, ERR_R_MALLOC_FAILURE);
goto err;
}
}
- if (in->key_exchange_info > 0 &&
- (!CBB_add_asn1(&session, &child, kKeyExchangeInfoTag) ||
- !CBB_add_asn1_uint64(&child, in->key_exchange_info))) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
- /* The certificate chain is only serialized if the leaf's SHA-256 isn't
- * serialized instead. */
- if (in->cert_chain != NULL && !in->peer_sha256_valid) {
- if (!CBB_add_asn1(&session, &child, kCertChainTag)) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- size_t i;
- for (i = 0; i < sk_X509_num(in->cert_chain); i++) {
- if (!add_X509(&child, sk_X509_value(in->cert_chain, i))) {
- goto err;
- }
- }
- }
-
if (!CBB_finish(&cbb, out_data, out_len)) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+ OPENSSL_PUT_ERROR(SSL, SSL_SESSION_to_bytes_full, ERR_R_MALLOC_FAILURE);
goto err;
}
return 1;
@@ -366,12 +328,11 @@ 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) {
+int SSL_SESSION_to_bytes(SSL_SESSION *in, uint8_t **out_data, size_t *out_len) {
return SSL_SESSION_to_bytes_full(in, out_data, out_len, 0);
}
-int SSL_SESSION_to_bytes_for_ticket(const SSL_SESSION *in, uint8_t **out_data,
+int SSL_SESSION_to_bytes_for_ticket(SSL_SESSION *in, uint8_t **out_data,
size_t *out_len) {
return SSL_SESSION_to_bytes_full(in, out_data, out_len, 1);
}
@@ -386,7 +347,7 @@ int i2d_SSL_SESSION(SSL_SESSION *in, uint8_t **pp) {
if (len > INT_MAX) {
OPENSSL_free(out);
- OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
+ OPENSSL_PUT_ERROR(SSL, i2d_SSL_SESSION, ERR_R_OVERFLOW);
return -1;
}
@@ -409,16 +370,17 @@ static int SSL_SESSION_parse_string(CBS *cbs, char **out, unsigned tag) {
CBS value;
int present;
if (!CBS_get_optional_asn1_octet_string(cbs, &value, &present, tag)) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
+ OPENSSL_PUT_ERROR(SSL, SSL_SESSION_parse_string, SSL_R_INVALID_SSL_SESSION);
return 0;
}
if (present) {
if (CBS_contains_zero_byte(&value)) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
+ OPENSSL_PUT_ERROR(SSL, SSL_SESSION_parse_string,
+ SSL_R_INVALID_SSL_SESSION);
return 0;
}
if (!CBS_strdup(&value, out)) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+ OPENSSL_PUT_ERROR(SSL, SSL_SESSION_parse_string, ERR_R_MALLOC_FAILURE);
return 0;
}
} else {
@@ -435,168 +397,170 @@ static int SSL_SESSION_parse_string(CBS *cbs, char **out, unsigned tag) {
* |*out_ptr| to NULL. It returns one on success, whether or not the
* element was found, and zero on decode error. */
static int SSL_SESSION_parse_octet_string(CBS *cbs, uint8_t **out_ptr,
- size_t *out_len, unsigned tag) {
+ size_t *out_len, unsigned tag) {
CBS value;
if (!CBS_get_optional_asn1_octet_string(cbs, &value, NULL, tag)) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
+ OPENSSL_PUT_ERROR(SSL, SSL_SESSION_parse_octet_string,
+ SSL_R_INVALID_SSL_SESSION);
return 0;
}
if (!CBS_stow(&value, out_ptr, out_len)) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+ OPENSSL_PUT_ERROR(SSL, SSL_SESSION_parse_octet_string,
+ ERR_R_MALLOC_FAILURE);
return 0;
}
return 1;
}
-/* SSL_SESSION_parse_bounded_octet_string parses an optional ASN.1 OCTET STRING
- * explicitly tagged with |tag| of size at most |max_out|. */
-static int SSL_SESSION_parse_bounded_octet_string(
- CBS *cbs, uint8_t *out, unsigned *out_len, unsigned max_out, unsigned tag) {
- CBS value;
- if (!CBS_get_optional_asn1_octet_string(cbs, &value, NULL, tag) ||
- CBS_len(&value) > max_out) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
- return 0;
- }
- memcpy(out, CBS_data(&value), CBS_len(&value));
- *out_len = (unsigned)CBS_len(&value);
- return 1;
-}
+static SSL_SESSION *SSL_SESSION_parse(CBS *cbs) {
+ SSL_SESSION *ret = NULL;
+ CBS session, cipher, session_id, master_key;
+ CBS peer, sid_ctx, peer_sha256, original_handshake_hash;
+ int has_peer, has_peer_sha256, extended_master_secret;
+ uint64_t version, ssl_version;
+ uint64_t session_time, timeout, verify_result, ticket_lifetime_hint;
-static int SSL_SESSION_parse_long(CBS *cbs, long *out, unsigned tag,
- long default_value) {
- uint64_t value;
- if (!CBS_get_optional_asn1_uint64(cbs, &value, tag,
- (uint64_t)default_value) ||
- value > LONG_MAX) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
- return 0;
+ ret = SSL_SESSION_new();
+ if (ret == NULL) {
+ goto err;
}
- *out = (long)value;
- return 1;
-}
-static int SSL_SESSION_parse_u32(CBS *cbs, uint32_t *out, unsigned tag,
- uint32_t default_value) {
- uint64_t value;
- if (!CBS_get_optional_asn1_uint64(cbs, &value, tag,
- (uint64_t)default_value) ||
- value > 0xffffffff) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
- return 0;
+ if (!CBS_get_asn1(cbs, &session, CBS_ASN1_SEQUENCE) ||
+ !CBS_get_asn1_uint64(&session, &version) ||
+ !CBS_get_asn1_uint64(&session, &ssl_version) ||
+ !CBS_get_asn1(&session, &cipher, CBS_ASN1_OCTETSTRING) ||
+ !CBS_get_asn1(&session, &session_id, CBS_ASN1_OCTETSTRING) ||
+ !CBS_get_asn1(&session, &master_key, CBS_ASN1_OCTETSTRING) ||
+ !CBS_get_optional_asn1_uint64(&session, &session_time, kTimeTag,
+ time(NULL)) ||
+ !CBS_get_optional_asn1_uint64(&session, &timeout, kTimeoutTag, 3) ||
+ !CBS_get_optional_asn1(&session, &peer, &has_peer, kPeerTag) ||
+ !CBS_get_optional_asn1_octet_string(&session, &sid_ctx, NULL,
+ kSessionIDContextTag) ||
+ !CBS_get_optional_asn1_uint64(&session, &verify_result, kVerifyResultTag,
+ X509_V_OK)) {
+ OPENSSL_PUT_ERROR(SSL, SSL_SESSION_parse, SSL_R_INVALID_SSL_SESSION);
+ goto err;
}
- *out = (uint32_t)value;
- return 1;
-}
-
-static X509 *parse_x509(CBS *cbs) {
- const uint8_t *ptr = CBS_data(cbs);
- X509 *ret = d2i_X509(NULL, &ptr, CBS_len(cbs));
- if (ret == NULL) {
- return NULL;
+ if (!SSL_SESSION_parse_string(&session, &ret->tlsext_hostname,
+ kHostNameTag) ||
+ !SSL_SESSION_parse_string(&session, &ret->psk_identity,
+ kPSKIdentityTag)) {
+ goto err;
}
- CBS_skip(cbs, ptr - CBS_data(cbs));
- return ret;
-}
-
-static SSL_SESSION *SSL_SESSION_parse(CBS *cbs) {
- SSL_SESSION *ret = SSL_SESSION_new();
- if (ret == NULL) {
+ if (!CBS_get_optional_asn1_uint64(&session, &ticket_lifetime_hint,
+ kTicketLifetimeHintTag, 0)) {
+ OPENSSL_PUT_ERROR(SSL, SSL_SESSION_parse, SSL_R_INVALID_SSL_SESSION);
+ goto err;
+ }
+ if (!SSL_SESSION_parse_octet_string(&session, &ret->tlsext_tick,
+ &ret->tlsext_ticklen, kTicketTag)) {
goto err;
}
+ if (!CBS_get_optional_asn1_octet_string(&session, &peer_sha256,
+ &has_peer_sha256, kPeerSHA256Tag) ||
+ !CBS_get_optional_asn1_octet_string(&session, &original_handshake_hash,
+ NULL, kOriginalHandshakeHashTag)) {
+ OPENSSL_PUT_ERROR(SSL, SSL_SESSION_parse, SSL_R_INVALID_SSL_SESSION);
+ goto err;
+ }
+ if (!SSL_SESSION_parse_octet_string(
+ &session, &ret->tlsext_signed_cert_timestamp_list,
+ &ret->tlsext_signed_cert_timestamp_list_length,
+ kSignedCertTimestampListTag) ||
+ !SSL_SESSION_parse_octet_string(
+ &session, &ret->ocsp_response, &ret->ocsp_response_length,
+ kOCSPResponseTag)) {
+ goto err;
+ }
+ if (!CBS_get_optional_asn1_bool(&session, &extended_master_secret,
+ kExtendedMasterSecretTag,
+ 0 /* default to false */) ||
+ CBS_len(&session) != 0) {
+ OPENSSL_PUT_ERROR(SSL, SSL_SESSION_parse, SSL_R_INVALID_SSL_SESSION);
+ goto err;
+ }
+ ret->extended_master_secret = extended_master_secret;
- CBS session;
- uint64_t version, ssl_version;
- if (!CBS_get_asn1(cbs, &session, CBS_ASN1_SEQUENCE) ||
- !CBS_get_asn1_uint64(&session, &version) ||
- version != SSL_SESSION_ASN1_VERSION ||
- !CBS_get_asn1_uint64(&session, &ssl_version)) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
+ if (version != SSL_SESSION_ASN1_VERSION) {
+ OPENSSL_PUT_ERROR(SSL, SSL_SESSION_parse, SSL_R_INVALID_SSL_SESSION);
goto err;
}
+
/* Only support SSLv3/TLS and DTLS. */
if ((ssl_version >> 8) != SSL3_VERSION_MAJOR &&
(ssl_version >> 8) != (DTLS1_VERSION >> 8)) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_SSL_VERSION);
+ OPENSSL_PUT_ERROR(SSL, SSL_SESSION_parse, SSL_R_UNKNOWN_SSL_VERSION);
goto err;
}
ret->ssl_version = ssl_version;
- CBS cipher;
uint16_t cipher_value;
- if (!CBS_get_asn1(&session, &cipher, CBS_ASN1_OCTETSTRING) ||
- !CBS_get_u16(&cipher, &cipher_value) ||
- CBS_len(&cipher) != 0) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
+ if (!CBS_get_u16(&cipher, &cipher_value) || CBS_len(&cipher) != 0) {
+ OPENSSL_PUT_ERROR(SSL, SSL_SESSION_parse, SSL_R_CIPHER_CODE_WRONG_LENGTH);
goto err;
}
ret->cipher = SSL_get_cipher_by_value(cipher_value);
if (ret->cipher == NULL) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_UNSUPPORTED_CIPHER);
+ OPENSSL_PUT_ERROR(SSL, SSL_SESSION_parse, SSL_R_UNSUPPORTED_CIPHER);
goto err;
}
- CBS session_id, master_key;
- if (!CBS_get_asn1(&session, &session_id, CBS_ASN1_OCTETSTRING) ||
- CBS_len(&session_id) > SSL3_MAX_SSL_SESSION_ID_LENGTH ||
- !CBS_get_asn1(&session, &master_key, CBS_ASN1_OCTETSTRING) ||
- CBS_len(&master_key) > SSL_MAX_MASTER_KEY_LENGTH) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
+ if (CBS_len(&session_id) > SSL3_MAX_SSL_SESSION_ID_LENGTH) {
+ OPENSSL_PUT_ERROR(SSL, SSL_SESSION_parse, SSL_R_INVALID_SSL_SESSION);
goto err;
}
memcpy(ret->session_id, CBS_data(&session_id), CBS_len(&session_id));
ret->session_id_length = CBS_len(&session_id);
- memcpy(ret->master_key, CBS_data(&master_key), CBS_len(&master_key));
- ret->master_key_length = CBS_len(&master_key);
- if (!SSL_SESSION_parse_long(&session, &ret->time, kTimeTag, time(NULL)) ||
- !SSL_SESSION_parse_long(&session, &ret->timeout, kTimeoutTag, 3)) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
+ if (CBS_len(&master_key) > SSL_MAX_MASTER_KEY_LENGTH) {
+ OPENSSL_PUT_ERROR(SSL, SSL_SESSION_parse, SSL_R_INVALID_SSL_SESSION);
goto err;
}
+ memcpy(ret->master_key, CBS_data(&master_key), CBS_len(&master_key));
+ ret->master_key_length = CBS_len(&master_key);
- CBS peer;
- int has_peer;
- if (!CBS_get_optional_asn1(&session, &peer, &has_peer, kPeerTag)) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
+ if (session_time > LONG_MAX ||
+ timeout > LONG_MAX) {
+ OPENSSL_PUT_ERROR(SSL, SSL_SESSION_parse, SSL_R_INVALID_SSL_SESSION);
goto err;
}
+ ret->time = session_time;
+ ret->timeout = timeout;
+
X509_free(ret->peer);
ret->peer = NULL;
if (has_peer) {
- ret->peer = parse_x509(&peer);
+ const uint8_t *ptr;
+ ptr = CBS_data(&peer);
+ ret->peer = d2i_X509(NULL, &ptr, CBS_len(&peer));
if (ret->peer == NULL) {
goto err;
}
- if (CBS_len(&peer) != 0) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
+ if (ptr != CBS_data(&peer) + CBS_len(&peer)) {
+ OPENSSL_PUT_ERROR(SSL, SSL_SESSION_parse, SSL_R_INVALID_SSL_SESSION);
goto err;
}
}
- if (!SSL_SESSION_parse_bounded_octet_string(
- &session, ret->sid_ctx, &ret->sid_ctx_length, sizeof(ret->sid_ctx),
- kSessionIDContextTag) ||
- !SSL_SESSION_parse_long(&session, &ret->verify_result, kVerifyResultTag,
- X509_V_OK) ||
- !SSL_SESSION_parse_string(&session, &ret->tlsext_hostname,
- kHostNameTag) ||
- !SSL_SESSION_parse_string(&session, &ret->psk_identity,
- kPSKIdentityTag) ||
- !SSL_SESSION_parse_u32(&session, &ret->tlsext_tick_lifetime_hint,
- kTicketLifetimeHintTag, 0) ||
- !SSL_SESSION_parse_octet_string(&session, &ret->tlsext_tick,
- &ret->tlsext_ticklen, kTicketTag)) {
+ if (CBS_len(&sid_ctx) > sizeof(ret->sid_ctx)) {
+ OPENSSL_PUT_ERROR(SSL, SSL_SESSION_parse, SSL_R_INVALID_SSL_SESSION);
+ goto err;
+ }
+ memcpy(ret->sid_ctx, CBS_data(&sid_ctx), CBS_len(&sid_ctx));
+ ret->sid_ctx_length = CBS_len(&sid_ctx);
+
+ if (verify_result > LONG_MAX ||
+ ticket_lifetime_hint > 0xffffffff) {
+ OPENSSL_PUT_ERROR(SSL, SSL_SESSION_parse, SSL_R_INVALID_SSL_SESSION);
goto err;
}
+ ret->verify_result = verify_result;
+ ret->tlsext_tick_lifetime_hint = ticket_lifetime_hint;
- if (CBS_peek_asn1_tag(&session, kPeerSHA256Tag)) {
- CBS child, peer_sha256;
- if (!CBS_get_asn1(&session, &child, kPeerSHA256Tag) ||
- !CBS_get_asn1(&child, &peer_sha256, CBS_ASN1_OCTETSTRING) ||
- CBS_len(&peer_sha256) != sizeof(ret->peer_sha256) ||
- CBS_len(&child) != 0) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
+ if (has_peer_sha256) {
+ if (CBS_len(&peer_sha256) != sizeof(ret->peer_sha256)) {
+ OPENSSL_PUT_ERROR(SSL, SSL_SESSION_parse, SSL_R_INVALID_SSL_SESSION);
goto err;
}
memcpy(ret->peer_sha256, CBS_data(&peer_sha256), sizeof(ret->peer_sha256));
@@ -605,67 +569,14 @@ static SSL_SESSION *SSL_SESSION_parse(CBS *cbs) {
ret->peer_sha256_valid = 0;
}
- if (!SSL_SESSION_parse_bounded_octet_string(
- &session, ret->original_handshake_hash,
- &ret->original_handshake_hash_len,
- sizeof(ret->original_handshake_hash), kOriginalHandshakeHashTag) ||
- !SSL_SESSION_parse_octet_string(
- &session, &ret->tlsext_signed_cert_timestamp_list,
- &ret->tlsext_signed_cert_timestamp_list_length,
- kSignedCertTimestampListTag) ||
- !SSL_SESSION_parse_octet_string(
- &session, &ret->ocsp_response, &ret->ocsp_response_length,
- kOCSPResponseTag)) {
- goto err;
- }
-
- int extended_master_secret;
- if (!CBS_get_optional_asn1_bool(&session, &extended_master_secret,
- kExtendedMasterSecretTag,
- 0 /* default to false */)) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
- goto err;
- }
- ret->extended_master_secret = !!extended_master_secret;
-
- if (!SSL_SESSION_parse_u32(&session, &ret->key_exchange_info,
- kKeyExchangeInfoTag, 0)) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
- goto err;
- }
-
- CBS cert_chain;
- int has_cert_chain;
- if (!CBS_get_optional_asn1(&session, &cert_chain, &has_cert_chain,
- kCertChainTag)) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
- goto err;
- }
- sk_X509_pop_free(ret->cert_chain, X509_free);
- ret->cert_chain = NULL;
- if (has_cert_chain) {
- ret->cert_chain = sk_X509_new_null();
- if (ret->cert_chain == NULL) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- while (CBS_len(&cert_chain) > 0) {
- X509 *x509 = parse_x509(&cert_chain);
- if (x509 == NULL) {
- goto err;
- }
- if (!sk_X509_push(ret->cert_chain, x509)) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- X509_free(x509);
- goto err;
- }
- }
- }
-
- if (CBS_len(&session) != 0) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
+ if (CBS_len(&original_handshake_hash) >
+ sizeof(ret->original_handshake_hash)) {
+ OPENSSL_PUT_ERROR(SSL, SSL_SESSION_parse, SSL_R_INVALID_SSL_SESSION);
goto err;
}
+ memcpy(ret->original_handshake_hash, CBS_data(&original_handshake_hash),
+ CBS_len(&original_handshake_hash));
+ ret->original_handshake_hash_len = CBS_len(&original_handshake_hash);
return ret;
@@ -682,7 +593,7 @@ SSL_SESSION *SSL_SESSION_from_bytes(const uint8_t *in, size_t in_len) {
return NULL;
}
if (CBS_len(&cbs) != 0) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
+ OPENSSL_PUT_ERROR(SSL, SSL_SESSION_from_bytes, SSL_R_INVALID_SSL_SESSION);
SSL_SESSION_free(ret);
return NULL;
}
@@ -691,7 +602,7 @@ SSL_SESSION *SSL_SESSION_from_bytes(const uint8_t *in, size_t in_len) {
SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a, const uint8_t **pp, long length) {
if (length < 0) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+ OPENSSL_PUT_ERROR(SSL, d2i_SSL_SESSION, ERR_R_INTERNAL_ERROR);
return NULL;
}