Browse Source

Remove |X509| things from SSL_SESSION.

|SSL_SESSION_from_bytes| now takes an |SSL_CTX*|, from which it uses the
|X509_METHOD| and buffer pool. This is our API so we can do this.

This also requires adding an |SSL_CTX*| argument to |SSL_SESSION_new|
for the same reason. However, |SSL_SESSION_new| already has very few
callers (and none in third-party code that I can see) so I think we can
get away with this.

Change-Id: I1337cd2bd8cff03d4b9405ea3146b3b59584aa72
Reviewed-on: https://boringssl-review.googlesource.com/13584
Reviewed-by: Adam Langley <alangley@gmail.com>
Commit-Queue: Adam Langley <alangley@gmail.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
kris/onging/CECPQ3_patch15
Adam Langley 7 years ago
committed by CQ bot account: commit-bot@chromium.org
parent
commit
46db7af2c9
16 changed files with 243 additions and 133 deletions
  1. +10
    -1
      fuzz/session.cc
  2. +7
    -5
      include/openssl/ssl.h
  3. +1
    -1
      ssl/handshake_client.c
  4. +5
    -5
      ssl/handshake_server.c
  5. +23
    -6
      ssl/internal.h
  6. +9
    -29
      ssl/ssl_asn1.c
  7. +0
    -11
      ssl/ssl_file.c
  8. +15
    -63
      ssl/ssl_session.c
  9. +28
    -5
      ssl/ssl_test.cc
  10. +117
    -0
      ssl/ssl_x509.c
  11. +2
    -1
      ssl/t1_lib.c
  12. +1
    -1
      ssl/test/bssl_shim.cc
  13. +1
    -1
      ssl/tls13_both.c
  14. +2
    -3
      ssl/tls13_client.c
  15. +1
    -1
      ssl/tls13_server.c
  16. +21
    -0
      ssl/tls_method.c

+ 10
- 1
fuzz/session.cc View File

@@ -17,9 +17,18 @@
#include <openssl/mem.h> #include <openssl/mem.h>
#include <openssl/ssl.h> #include <openssl/ssl.h>


struct GlobalState {
GlobalState() : ctx(SSL_CTX_new(TLS_method())) {}

bssl::UniquePtr<SSL_CTX> ctx;
};

static GlobalState g_state;

extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) { extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) {
// Parse in our session. // Parse in our session.
bssl::UniquePtr<SSL_SESSION> session(SSL_SESSION_from_bytes(buf, len));
bssl::UniquePtr<SSL_SESSION> session(
SSL_SESSION_from_bytes(buf, len, g_state.ctx.get()));


// If the format was invalid, just return. // If the format was invalid, just return.
if (!session) { if (!session) {


+ 7
- 5
include/openssl/ssl.h View File

@@ -1570,9 +1570,9 @@ DECLARE_LHASH_OF(SSL_SESSION)
DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION) DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION)


/* SSL_SESSION_new returns a newly-allocated blank |SSL_SESSION| or NULL on /* SSL_SESSION_new returns a newly-allocated blank |SSL_SESSION| or NULL on
* error. This may be useful in writing tests but otherwise should not be
* used outside the library. */
OPENSSL_EXPORT SSL_SESSION *SSL_SESSION_new(void);
* error. This may be useful when writing tests but should otherwise not be
* used. */
OPENSSL_EXPORT SSL_SESSION *SSL_SESSION_new(const SSL_CTX *ctx);


/* SSL_SESSION_up_ref increments the reference count of |session| and returns /* SSL_SESSION_up_ref increments the reference count of |session| and returns
* one. */ * one. */
@@ -1597,8 +1597,8 @@ OPENSSL_EXPORT int SSL_SESSION_to_bytes_for_ticket(const SSL_SESSION *in,


/* SSL_SESSION_from_bytes parses |in_len| bytes from |in| as an SSL_SESSION. It /* SSL_SESSION_from_bytes parses |in_len| bytes from |in| as an SSL_SESSION. It
* returns a newly-allocated |SSL_SESSION| on success or NULL on error. */ * returns a newly-allocated |SSL_SESSION| on success or NULL on error. */
OPENSSL_EXPORT SSL_SESSION *SSL_SESSION_from_bytes(const uint8_t *in,
size_t in_len);
OPENSSL_EXPORT SSL_SESSION *SSL_SESSION_from_bytes(
const uint8_t *in, size_t in_len, const SSL_CTX *ctx);


/* SSL_SESSION_get_version returns a string describing the TLS version |session| /* SSL_SESSION_get_version returns a string describing the TLS version |session|
* was established at. For example, "TLSv1.2" or "SSLv3". */ * was established at. For example, "TLSv1.2" or "SSLv3". */
@@ -3734,6 +3734,8 @@ struct ssl_session_st {
* certificate. */ * certificate. */
STACK_OF(CRYPTO_BUFFER) *certs; STACK_OF(CRYPTO_BUFFER) *certs;


const SSL_X509_METHOD *x509_method;

/* x509_peer is the peer's certificate. */ /* x509_peer is the peer's certificate. */
X509 *x509_peer; X509 *x509_peer;




+ 1
- 1
ssl/handshake_client.c View File

@@ -1077,7 +1077,7 @@ static int ssl3_get_server_certificate(SSL_HANDSHAKE *hs) {


if (sk_CRYPTO_BUFFER_num(ssl->s3->new_session->certs) == 0 || if (sk_CRYPTO_BUFFER_num(ssl->s3->new_session->certs) == 0 ||
CBS_len(&cbs) != 0 || CBS_len(&cbs) != 0 ||
!ssl_session_x509_cache_objects(ssl->s3->new_session)) {
!ssl->ctx->x509_method->session_cache_objects(ssl->s3->new_session)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
return -1; return -1;


+ 5
- 5
ssl/handshake_server.c View File

@@ -483,10 +483,10 @@ int ssl3_accept(SSL_HANDSHAKE *hs) {
* now. */ * now. */
if (ssl->s3->new_session != NULL && if (ssl->s3->new_session != NULL &&
ssl->retain_only_sha256_of_client_certs) { ssl->retain_only_sha256_of_client_certs) {
X509_free(ssl->s3->new_session->x509_peer);
ssl->s3->new_session->x509_peer = NULL;
sk_X509_pop_free(ssl->s3->new_session->x509_chain, X509_free);
ssl->s3->new_session->x509_chain = NULL;
sk_CRYPTO_BUFFER_pop_free(ssl->s3->new_session->certs,
CRYPTO_BUFFER_free);
ssl->s3->new_session->certs = NULL;
ssl->ctx->x509_method->session_clear(ssl->s3->new_session);
} }


SSL_SESSION_free(ssl->s3->established_session); SSL_SESSION_free(ssl->s3->established_session);
@@ -1472,7 +1472,7 @@ static int ssl3_get_client_certificate(SSL_HANDSHAKE *hs) {
} }


if (CBS_len(&certificate_msg) != 0 || if (CBS_len(&certificate_msg) != 0 ||
!ssl_session_x509_cache_objects(ssl->s3->new_session)) {
!ssl->ctx->x509_method->session_cache_objects(ssl->s3->new_session)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
return -1; return -1;


+ 23
- 6
ssl/internal.h View File

@@ -804,12 +804,6 @@ void ssl_write_buffer_clear(SSL *ssl);
* configured and zero otherwise. */ * configured and zero otherwise. */
int ssl_has_certificate(const SSL *ssl); int ssl_has_certificate(const SSL *ssl);


/* ssl_session_x509_cache_objects fills out |sess->x509_peer| and
* |sess->x509_chain| from |sess->certs| and erases
* |sess->x509_chain_without_leaf|. It returns one on success or zero on
* error. */
int ssl_session_x509_cache_objects(SSL_SESSION *sess);

/* ssl_parse_cert_chain parses a certificate list from |cbs| in the format used /* ssl_parse_cert_chain parses a certificate list from |cbs| in the format used
* by a TLS Certificate message. On success, it returns a newly-allocated * by a TLS Certificate message. On success, it returns a newly-allocated
* |CRYPTO_BUFFER| list and advances |cbs|. Otherwise, it returns NULL and sets * |CRYPTO_BUFFER| list and advances |cbs|. Otherwise, it returns NULL and sets
@@ -1433,8 +1427,22 @@ struct ssl_x509_method_st {
/* cert_flush_cached_chain drops any cached |X509|-based leaf certificate /* cert_flush_cached_chain drops any cached |X509|-based leaf certificate
* from |cert|. */ * from |cert|. */
void (*cert_flush_cached_leaf)(CERT *cert); void (*cert_flush_cached_leaf)(CERT *cert);

/* session_cache_objects fills out |sess->x509_peer| and |sess->x509_chain|
* from |sess->certs| and erases |sess->x509_chain_without_leaf|. It returns
* one on success or zero on error. */
int (*session_cache_objects)(SSL_SESSION *session);
/* session_dup duplicates any needed fields from |session| to |new_session|.
* It returns one on success or zero on error. */
int (*session_dup)(SSL_SESSION *new_session, const SSL_SESSION *session);
/* session_clear frees any X509-related state from |session|. */
void (*session_clear)(SSL_SESSION *session);
}; };


/* ssl_noop_x509_method is implements the |ssl_x509_method_st| functions by
* doing nothing. */
extern const struct ssl_x509_method_st ssl_noop_x509_method;

/* ssl_crypto_x509_method provides the |ssl_x509_method_st| functions using /* ssl_crypto_x509_method provides the |ssl_x509_method_st| functions using
* crypto/x509. */ * crypto/x509. */
extern const struct ssl_x509_method_st ssl_crypto_x509_method; extern const struct ssl_x509_method_st ssl_crypto_x509_method;
@@ -1911,6 +1919,15 @@ int ssl_cert_check_private_key(const CERT *cert, const EVP_PKEY *privkey);
int ssl_get_new_session(SSL_HANDSHAKE *hs, int is_server); int ssl_get_new_session(SSL_HANDSHAKE *hs, int is_server);
int ssl_encrypt_ticket(SSL *ssl, CBB *out, const SSL_SESSION *session); int ssl_encrypt_ticket(SSL *ssl, CBB *out, const SSL_SESSION *session);


/* ssl_session_new returns a newly-allocated blank |SSL_SESSION| or NULL on
* error. */
SSL_SESSION *ssl_session_new(const SSL_X509_METHOD *x509_method);

/* SSL_SESSION_parse parses an |SSL_SESSION| from |cbs| and advances |cbs| over
* the parsed data. */
SSL_SESSION *SSL_SESSION_parse(CBS *cbs, const SSL_X509_METHOD *x509_method,
CRYPTO_BUFFER_POOL *pool);

/* ssl_session_is_context_valid returns one if |session|'s session ID context /* ssl_session_is_context_valid returns one if |session|'s session ID context
* matches the one set on |ssl| and zero otherwise. */ * matches the one set on |ssl| and zero otherwise. */
int ssl_session_is_context_valid(const SSL *ssl, const SSL_SESSION *session); int ssl_session_is_context_valid(const SSL *ssl, const SSL_SESSION *session);


+ 9
- 29
ssl/ssl_asn1.c View File

@@ -575,8 +575,9 @@ static int SSL_SESSION_parse_u16(CBS *cbs, uint16_t *out, unsigned tag,
return 1; return 1;
} }


static SSL_SESSION *SSL_SESSION_parse(CBS *cbs) {
SSL_SESSION *ret = SSL_SESSION_new();
SSL_SESSION *SSL_SESSION_parse(CBS *cbs, const SSL_X509_METHOD *x509_method,
CRYPTO_BUFFER_POOL *pool) {
SSL_SESSION *ret = ssl_session_new(x509_method);
if (ret == NULL) { if (ret == NULL) {
goto err; goto err;
} }
@@ -738,7 +739,7 @@ static SSL_SESSION *SSL_SESSION_parse(CBS *cbs) {


if (has_peer) { if (has_peer) {
/* TODO(agl): this should use the |SSL_CTX|'s pool. */ /* TODO(agl): this should use the |SSL_CTX|'s pool. */
CRYPTO_BUFFER *buffer = CRYPTO_BUFFER_new_from_CBS(&peer, NULL);
CRYPTO_BUFFER *buffer = CRYPTO_BUFFER_new_from_CBS(&peer, pool);
if (buffer == NULL || if (buffer == NULL ||
!sk_CRYPTO_BUFFER_push(ret->certs, buffer)) { !sk_CRYPTO_BUFFER_push(ret->certs, buffer)) {
CRYPTO_BUFFER_free(buffer); CRYPTO_BUFFER_free(buffer);
@@ -756,7 +757,7 @@ static SSL_SESSION *SSL_SESSION_parse(CBS *cbs) {
} }


/* TODO(agl): this should use the |SSL_CTX|'s pool. */ /* TODO(agl): this should use the |SSL_CTX|'s pool. */
CRYPTO_BUFFER *buffer = CRYPTO_BUFFER_new_from_CBS(&cert, NULL);
CRYPTO_BUFFER *buffer = CRYPTO_BUFFER_new_from_CBS(&cert, pool);
if (buffer == NULL || if (buffer == NULL ||
!sk_CRYPTO_BUFFER_push(ret->certs, buffer)) { !sk_CRYPTO_BUFFER_push(ret->certs, buffer)) {
CRYPTO_BUFFER_free(buffer); CRYPTO_BUFFER_free(buffer);
@@ -766,7 +767,7 @@ static SSL_SESSION *SSL_SESSION_parse(CBS *cbs) {
} }
} }


if (!ssl_session_x509_cache_objects(ret)) {
if (!x509_method->session_cache_objects(ret)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION); OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
goto err; goto err;
} }
@@ -811,10 +812,11 @@ err:
return NULL; return NULL;
} }


SSL_SESSION *SSL_SESSION_from_bytes(const uint8_t *in, size_t in_len) {
SSL_SESSION *SSL_SESSION_from_bytes(const uint8_t *in, size_t in_len,
const SSL_CTX *ctx) {
CBS cbs; CBS cbs;
CBS_init(&cbs, in, in_len); CBS_init(&cbs, in, in_len);
SSL_SESSION *ret = SSL_SESSION_parse(&cbs);
SSL_SESSION *ret = SSL_SESSION_parse(&cbs, ctx->x509_method, ctx->pool);
if (ret == NULL) { if (ret == NULL) {
return NULL; return NULL;
} }
@@ -825,25 +827,3 @@ SSL_SESSION *SSL_SESSION_from_bytes(const uint8_t *in, size_t in_len) {
} }
return ret; return ret;
} }

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);
return NULL;
}

CBS cbs;
CBS_init(&cbs, *pp, length);

SSL_SESSION *ret = SSL_SESSION_parse(&cbs);
if (ret == NULL) {
return NULL;
}

if (a) {
SSL_SESSION_free(*a);
*a = ret;
}
*pp = CBS_data(&cbs);
return ret;
}

+ 0
- 11
ssl/ssl_file.c View File

@@ -573,14 +573,3 @@ void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx, pem_password_cb *cb) {
void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX *ctx, void *data) { void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX *ctx, void *data) {
ctx->default_passwd_callback_userdata = data; ctx->default_passwd_callback_userdata = data;
} }

SSL_SESSION *d2i_SSL_SESSION_bio(BIO *bio, SSL_SESSION **out) {
return ASN1_d2i_bio_of(SSL_SESSION, SSL_SESSION_new, d2i_SSL_SESSION, bio,
out);
}

int i2d_SSL_SESSION_bio(BIO *bio, const SSL_SESSION *session) {
return ASN1_i2d_bio_of(SSL_SESSION, i2d_SSL_SESSION, bio, session);
}

IMPLEMENT_PEM_rw(SSL_SESSION, SSL_SESSION, PEM_STRING_SSL_SESSION, SSL_SESSION)

+ 15
- 63
ssl/ssl_session.c View File

@@ -160,7 +160,7 @@ static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *session);
static void SSL_SESSION_list_add(SSL_CTX *ctx, SSL_SESSION *session); static void SSL_SESSION_list_add(SSL_CTX *ctx, SSL_SESSION *session);
static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *session, int lock); static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *session, int lock);


SSL_SESSION *SSL_SESSION_new(void) {
SSL_SESSION *ssl_session_new(const SSL_X509_METHOD *x509_method) {
SSL_SESSION *session = OPENSSL_malloc(sizeof(SSL_SESSION)); SSL_SESSION *session = OPENSSL_malloc(sizeof(SSL_SESSION));
if (session == NULL) { if (session == NULL) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
@@ -168,6 +168,7 @@ SSL_SESSION *SSL_SESSION_new(void) {
} }
OPENSSL_memset(session, 0, sizeof(SSL_SESSION)); OPENSSL_memset(session, 0, sizeof(SSL_SESSION));


session->x509_method = x509_method;
session->verify_result = X509_V_ERR_INVALID_CALL; session->verify_result = X509_V_ERR_INVALID_CALL;
session->references = 1; session->references = 1;
session->timeout = SSL_DEFAULT_SESSION_TIMEOUT; session->timeout = SSL_DEFAULT_SESSION_TIMEOUT;
@@ -177,8 +178,12 @@ SSL_SESSION *SSL_SESSION_new(void) {
return session; 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 *SSL_SESSION_dup(SSL_SESSION *session, int dup_flags) {
SSL_SESSION *new_session = SSL_SESSION_new();
SSL_SESSION *new_session = ssl_session_new(session->x509_method);
if (new_session == NULL) { if (new_session == NULL) {
goto err; goto err;
} }
@@ -214,16 +219,11 @@ SSL_SESSION *SSL_SESSION_dup(SSL_SESSION *session, int dup_flags) {
CRYPTO_BUFFER_up_ref(buffer); CRYPTO_BUFFER_up_ref(buffer);
} }
} }
if (session->x509_peer != NULL) {
X509_up_ref(session->x509_peer);
new_session->x509_peer = session->x509_peer;
}
if (session->x509_chain != NULL) {
new_session->x509_chain = X509_chain_up_ref(session->x509_chain);
if (new_session->x509_chain == NULL) {
goto err;
}

if (!session->x509_method->session_dup(new_session, session)) {
goto err;
} }

new_session->verify_result = session->verify_result; new_session->verify_result = session->verify_result;


new_session->ocsp_response_length = session->ocsp_response_length; new_session->ocsp_response_length = session->ocsp_response_length;
@@ -367,9 +367,7 @@ void SSL_SESSION_free(SSL_SESSION *session) {
OPENSSL_cleanse(session->master_key, sizeof(session->master_key)); OPENSSL_cleanse(session->master_key, sizeof(session->master_key));
OPENSSL_cleanse(session->session_id, sizeof(session->session_id)); OPENSSL_cleanse(session->session_id, sizeof(session->session_id));
sk_CRYPTO_BUFFER_pop_free(session->certs, CRYPTO_BUFFER_free); sk_CRYPTO_BUFFER_pop_free(session->certs, CRYPTO_BUFFER_free);
X509_free(session->x509_peer);
sk_X509_pop_free(session->x509_chain, X509_free);
sk_X509_pop_free(session->x509_chain_without_leaf, X509_free);
session->x509_method->session_clear(session);
OPENSSL_free(session->tlsext_hostname); OPENSSL_free(session->tlsext_hostname);
OPENSSL_free(session->tlsext_tick); OPENSSL_free(session->tlsext_tick);
OPENSSL_free(session->tlsext_signed_cert_timestamp_list); OPENSSL_free(session->tlsext_signed_cert_timestamp_list);
@@ -511,7 +509,7 @@ int ssl_get_new_session(SSL_HANDSHAKE *hs, int is_server) {
return 0; return 0;
} }


SSL_SESSION *session = SSL_SESSION_new();
SSL_SESSION *session = ssl_session_new(ssl->ctx->x509_method);
if (session == NULL) { if (session == NULL) {
return 0; return 0;
} }
@@ -573,53 +571,6 @@ err:
return 0; return 0;
} }


int ssl_session_x509_cache_objects(SSL_SESSION *sess) {
STACK_OF(X509) *chain = NULL;
const size_t num_certs = sk_CRYPTO_BUFFER_num(sess->certs);

if (num_certs > 0) {
chain = sk_X509_new_null();
if (chain == NULL) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
goto err;
}
}

X509 *leaf = NULL;
for (size_t i = 0; i < num_certs; i++) {
X509 *x509 = X509_parse_from_buffer(sk_CRYPTO_BUFFER_value(sess->certs, i));
if (x509 == NULL) {
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
goto err;
}
if (!sk_X509_push(chain, x509)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
X509_free(x509);
goto err;
}
if (i == 0) {
leaf = x509;
}
}

sk_X509_pop_free(sess->x509_chain, X509_free);
sess->x509_chain = chain;
sk_X509_pop_free(sess->x509_chain_without_leaf, X509_free);
sess->x509_chain_without_leaf = NULL;

X509_free(sess->x509_peer);
if (leaf != NULL) {
X509_up_ref(leaf);
}
sess->x509_peer = leaf;

return 1;

err:
sk_X509_pop_free(chain, X509_free);
return 0;
}

int ssl_encrypt_ticket(SSL *ssl, CBB *out, const SSL_SESSION *session) { int ssl_encrypt_ticket(SSL *ssl, CBB *out, const SSL_SESSION *session) {
int ret = 0; int ret = 0;


@@ -753,7 +704,8 @@ int ssl_session_is_resumable(const SSL *ssl, const SSL_SESSION *session) {
/* If the session contains a client certificate (either the full /* If the session contains a client certificate (either the full
* certificate or just the hash) then require that the form of the * certificate or just the hash) then require that the form of the
* certificate matches the current configuration. */ * certificate matches the current configuration. */
((session->x509_peer == NULL && !session->peer_sha256_valid) ||
((sk_CRYPTO_BUFFER_num(session->certs) == 0 &&
!session->peer_sha256_valid) ||
session->peer_sha256_valid == session->peer_sha256_valid ==
ssl->retain_only_sha256_of_client_certs); ssl->retain_only_sha256_of_client_certs);
} }


+ 28
- 5
ssl/ssl_test.cc View File

@@ -634,7 +634,12 @@ static bool TestSSL_SESSIONEncoding(const char *input_b64) {
} }


// Verify the SSL_SESSION decodes. // Verify the SSL_SESSION decodes.
bssl::UniquePtr<SSL_SESSION> session(SSL_SESSION_from_bytes(input.data(), input.size()));
bssl::UniquePtr<SSL_CTX> ssl_ctx(SSL_CTX_new(TLS_method()));
if (!ssl_ctx) {
return false;
}
bssl::UniquePtr<SSL_SESSION> session(
SSL_SESSION_from_bytes(input.data(), input.size(), ssl_ctx.get()));
if (!session) { if (!session) {
fprintf(stderr, "SSL_SESSION_from_bytes failed\n"); fprintf(stderr, "SSL_SESSION_from_bytes failed\n");
return false; return false;
@@ -703,7 +708,12 @@ static bool TestBadSSL_SESSIONEncoding(const char *input_b64) {
} }


// Verify that the SSL_SESSION fails to decode. // Verify that the SSL_SESSION fails to decode.
bssl::UniquePtr<SSL_SESSION> session(SSL_SESSION_from_bytes(input.data(), input.size()));
bssl::UniquePtr<SSL_CTX> ssl_ctx(SSL_CTX_new(TLS_method()));
if (!ssl_ctx) {
return false;
}
bssl::UniquePtr<SSL_SESSION> session(
SSL_SESSION_from_bytes(input.data(), input.size(), ssl_ctx.get()));
if (session) { if (session) {
fprintf(stderr, "SSL_SESSION_from_bytes unexpectedly succeeded\n"); fprintf(stderr, "SSL_SESSION_from_bytes unexpectedly succeeded\n");
return false; return false;
@@ -795,8 +805,13 @@ static bssl::UniquePtr<SSL_SESSION> CreateSessionWithTicket(uint16_t version,
if (!DecodeBase64(&der, kOpenSSLSession)) { if (!DecodeBase64(&der, kOpenSSLSession)) {
return nullptr; return nullptr;
} }

bssl::UniquePtr<SSL_CTX> ssl_ctx(SSL_CTX_new(TLS_method()));
if (!ssl_ctx) {
return nullptr;
}
bssl::UniquePtr<SSL_SESSION> session( bssl::UniquePtr<SSL_SESSION> session(
SSL_SESSION_from_bytes(der.data(), der.size()));
SSL_SESSION_from_bytes(der.data(), der.size(), ssl_ctx.get()));
if (!session) { if (!session) {
return nullptr; return nullptr;
} }
@@ -989,7 +1004,11 @@ static bool ExpectCache(SSL_CTX *ctx,
} }


static bssl::UniquePtr<SSL_SESSION> CreateTestSession(uint32_t number) { static bssl::UniquePtr<SSL_SESSION> CreateTestSession(uint32_t number) {
bssl::UniquePtr<SSL_SESSION> ret(SSL_SESSION_new());
bssl::UniquePtr<SSL_CTX> ssl_ctx(SSL_CTX_new(TLS_method()));
if (!ssl_ctx) {
return nullptr;
}
bssl::UniquePtr<SSL_SESSION> ret(SSL_SESSION_new(ssl_ctx.get()));
if (!ret) { if (!ret) {
return nullptr; return nullptr;
} }
@@ -2166,8 +2185,12 @@ static bool GetServerTicketTime(long *out, const SSL_SESSION *session) {
len = static_cast<size_t>(len1 + len2); len = static_cast<size_t>(len1 + len2);
#endif #endif


bssl::UniquePtr<SSL_CTX> ssl_ctx(SSL_CTX_new(TLS_method()));
if (!ssl_ctx) {
return false;
}
bssl::UniquePtr<SSL_SESSION> server_session( bssl::UniquePtr<SSL_SESSION> server_session(
SSL_SESSION_from_bytes(plaintext.get(), len));
SSL_SESSION_from_bytes(plaintext.get(), len, ssl_ctx.get()));
if (!server_session) { if (!server_session) {
return false; return false;
} }


+ 117
- 0
ssl/ssl_x509.c View File

@@ -142,6 +142,10 @@


#include <assert.h> #include <assert.h>


#include <openssl/asn1.h>
#include <openssl/bytestring.h>
#include <openssl/err.h>
#include <openssl/pem.h>
#include <openssl/stack.h> #include <openssl/stack.h>
#include <openssl/x509.h> #include <openssl/x509.h>
#include <openssl/x509v3.h> #include <openssl/x509v3.h>
@@ -334,10 +338,85 @@ static void ssl_crypto_x509_clear(CERT *cert) {
cert->x509_stash = NULL; cert->x509_stash = NULL;
} }


static int ssl_crypto_x509_session_cache_objects(SSL_SESSION *sess) {
STACK_OF(X509) *chain = NULL;
const size_t num_certs = sk_CRYPTO_BUFFER_num(sess->certs);

if (num_certs > 0) {
chain = sk_X509_new_null();
if (chain == NULL) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
goto err;
}
}

X509 *leaf = NULL;
for (size_t i = 0; i < num_certs; i++) {
X509 *x509 = X509_parse_from_buffer(sk_CRYPTO_BUFFER_value(sess->certs, i));
if (x509 == NULL) {
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
goto err;
}
if (!sk_X509_push(chain, x509)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
X509_free(x509);
goto err;
}
if (i == 0) {
leaf = x509;
}
}

sk_X509_pop_free(sess->x509_chain, X509_free);
sess->x509_chain = chain;
sk_X509_pop_free(sess->x509_chain_without_leaf, X509_free);
sess->x509_chain_without_leaf = NULL;

X509_free(sess->x509_peer);
if (leaf != NULL) {
X509_up_ref(leaf);
}
sess->x509_peer = leaf;

return 1;

err:
sk_X509_pop_free(chain, X509_free);
return 0;
}

static int ssl_crypto_x509_session_dup(SSL_SESSION *new_session,
const SSL_SESSION *session) {
if (session->x509_peer != NULL) {
X509_up_ref(session->x509_peer);
new_session->x509_peer = session->x509_peer;
}
if (session->x509_chain != NULL) {
new_session->x509_chain = X509_chain_up_ref(session->x509_chain);
if (new_session->x509_chain == NULL) {
return 0;
}
}

return 1;
}

static void ssl_crypto_x509_session_clear(SSL_SESSION *session) {
X509_free(session->x509_peer);
session->x509_peer = NULL;
sk_X509_pop_free(session->x509_chain, X509_free);
session->x509_chain = NULL;
sk_X509_pop_free(session->x509_chain_without_leaf, X509_free);
session->x509_chain_without_leaf = NULL;
}

const SSL_X509_METHOD ssl_crypto_x509_method = { const SSL_X509_METHOD ssl_crypto_x509_method = {
ssl_crypto_x509_clear, ssl_crypto_x509_clear,
ssl_crypto_x509_flush_cached_chain, ssl_crypto_x509_flush_cached_chain,
ssl_crypto_x509_flush_cached_leaf, ssl_crypto_x509_flush_cached_leaf,
ssl_crypto_x509_session_cache_objects,
ssl_crypto_x509_session_dup,
ssl_crypto_x509_session_clear,
}; };


/* x509_to_buffer returns a |CRYPTO_BUFFER| that contains the serialised /* x509_to_buffer returns a |CRYPTO_BUFFER| that contains the serialised
@@ -696,3 +775,41 @@ int SSL_get0_chain_certs(const SSL *ssl, STACK_OF(X509) **out_chain) {
*out_chain = ssl->cert->x509_chain; *out_chain = ssl->cert->x509_chain;
return 1; return 1;
} }

static SSL_SESSION *ssl_session_new_with_crypto_x509(void) {
return ssl_session_new(&ssl_crypto_x509_method);
}

SSL_SESSION *d2i_SSL_SESSION_bio(BIO *bio, SSL_SESSION **out) {
return ASN1_d2i_bio_of(SSL_SESSION, ssl_session_new_with_crypto_x509,
d2i_SSL_SESSION, bio, out);
}

int i2d_SSL_SESSION_bio(BIO *bio, const SSL_SESSION *session) {
return ASN1_i2d_bio_of(SSL_SESSION, i2d_SSL_SESSION, bio, session);
}

IMPLEMENT_PEM_rw(SSL_SESSION, SSL_SESSION, PEM_STRING_SSL_SESSION, SSL_SESSION)

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);
return NULL;
}

CBS cbs;
CBS_init(&cbs, *pp, length);

SSL_SESSION *ret = SSL_SESSION_parse(&cbs, &ssl_crypto_x509_method,
NULL /* no buffer pool */);
if (ret == NULL) {
return NULL;
}

if (a) {
SSL_SESSION_free(*a);
*a = ret;
}
*pp = CBS_data(&cbs);
return ret;
}

+ 2
- 1
ssl/t1_lib.c View File

@@ -3213,7 +3213,8 @@ int tls_process_ticket(SSL *ssl, SSL_SESSION **out_session,
#endif #endif


/* Decode the session. */ /* Decode the session. */
SSL_SESSION *session = SSL_SESSION_from_bytes(plaintext, plaintext_len);
SSL_SESSION *session =
SSL_SESSION_from_bytes(plaintext, plaintext_len, ssl->ctx);
if (session == NULL) { if (session == NULL) {
ERR_clear_error(); /* Don't leave an error on the queue. */ ERR_clear_error(); /* Don't leave an error on the queue. */
goto done; goto done;


+ 1
- 1
ssl/test/bssl_shim.cc View File

@@ -1477,7 +1477,7 @@ static bool CheckHandshakeProperties(SSL *ssl, bool is_resume) {
} }


if (expected_sha256_client_cert && if (expected_sha256_client_cert &&
SSL_get_session(ssl)->x509_peer != nullptr) {
SSL_get_session(ssl)->certs != nullptr) {
fprintf(stderr, "Have both client cert and SHA-256 hash: is_resume:%d.\n", fprintf(stderr, "Have both client cert and SHA-256 hash: is_resume:%d.\n",
is_resume); is_resume);
return false; return false;


+ 1
- 1
ssl/tls13_both.c View File

@@ -307,7 +307,7 @@ int tls13_process_certificate(SSL_HANDSHAKE *hs, int allow_anonymous) {
ssl->s3->new_session->certs = certs; ssl->s3->new_session->certs = certs;
certs = NULL; certs = NULL;


if (!ssl_session_x509_cache_objects(ssl->s3->new_session)) {
if (!ssl->ctx->x509_method->session_cache_objects(ssl->s3->new_session)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
goto err; goto err;


+ 2
- 3
ssl/tls13_client.c View File

@@ -615,9 +615,8 @@ enum ssl_hs_wait_t tls13_client_handshake(SSL_HANDSHAKE *hs) {


int tls13_process_new_session_ticket(SSL *ssl) { int tls13_process_new_session_ticket(SSL *ssl) {
int ret = 0; int ret = 0;
SSL_SESSION *session =
SSL_SESSION_dup(ssl->s3->established_session,
SSL_SESSION_INCLUDE_NONAUTH);
SSL_SESSION *session = SSL_SESSION_dup(ssl->s3->established_session,
SSL_SESSION_INCLUDE_NONAUTH);
if (session == NULL) { if (session == NULL) {
return 0; return 0;
} }


+ 1
- 1
ssl/tls13_server.c View File

@@ -495,7 +495,7 @@ static enum ssl_hs_wait_t do_process_client_certificate(SSL_HANDSHAKE *hs) {
static enum ssl_hs_wait_t do_process_client_certificate_verify( static enum ssl_hs_wait_t do_process_client_certificate_verify(
SSL_HANDSHAKE *hs) { SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl; SSL *const ssl = hs->ssl;
if (ssl->s3->new_session->x509_peer == NULL) {
if (sk_CRYPTO_BUFFER_num(ssl->s3->new_session->certs) == 0) {
/* Skip this state. */ /* Skip this state. */
hs->tls13_state = state_process_channel_id; hs->tls13_state = state_process_channel_id;
return ssl_hs_ok; return ssl_hs_ok;


+ 21
- 0
ssl/tls_method.c View File

@@ -257,3 +257,24 @@ const SSL_METHOD *TLS_server_method(void) {
const SSL_METHOD *TLS_client_method(void) { const SSL_METHOD *TLS_client_method(void) {
return TLS_method(); return TLS_method();
} }

static void ssl_noop_x509_clear(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) {}

const SSL_X509_METHOD ssl_noop_x509_method = {
ssl_noop_x509_clear,
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,
};

Loading…
Cancel
Save