Browse Source

Early callback support.

kris/onging/CECPQ3_patch15
Adam Langley 10 years ago
parent
commit
dc9b141127
7 changed files with 339 additions and 128 deletions
  1. +73
    -35
      ssl/s3_srvr.c
  2. +36
    -0
      ssl/ssl.h
  3. +2
    -0
      ssl/ssl_error.c
  4. +3
    -0
      ssl/ssl_lib.c
  5. +5
    -3
      ssl/ssl_locl.h
  6. +10
    -14
      ssl/ssl_sess.c
  7. +210
    -76
      ssl/t1_lib.c

+ 73
- 35
ssl/s3_srvr.c View File

@@ -146,7 +146,8 @@
* OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
* OTHERWISE. */

#define REUSE_CIPHER_BUG
/* Undefined in Google code. We've never enabled this workaround
* #define REUSE_CIPHER_BUG */
#define NETSCAPE_HANG_BUG

#include <stdio.h>
@@ -329,10 +330,14 @@ int ssl3_accept(SSL *s)
s->shutdown=0;
ret=ssl3_get_client_hello(s);
if (ret == PENDING_SESSION) {
s->state = SSL3_ST_SR_CLNT_HELLO_D;
s->rwstate = SSL_PENDING_SESSION;
goto end;
}
if (ret == CERTIFICATE_SELECTION_PENDING)
{
s->rwstate = SSL_CERTIFICATE_SELECTION_PENDING;
goto end;
}
if (ret <= 0) goto end;
s->renegotiate = 2;
s->state=SSL3_ST_SW_SRVR_HELLO_A;
@@ -914,9 +919,7 @@ int ssl3_get_client_hello(SSL *s)
unsigned char *p,*d;
SSL_CIPHER *c;
STACK_OF(SSL_CIPHER) *ciphers=NULL;

if (s->state == SSL3_ST_SR_CLNT_HELLO_C)
goto retry_cert;
struct ssl_early_callback_ctx early_ctx;

/* We do this so that we will respond with our native type.
* If we are TLSv1 and we get SSLv3, we will respond with TLSv1,
@@ -924,13 +927,11 @@ int ssl3_get_client_hello(SSL *s)
* If we are SSLv3, we will respond with SSLv3, even if prompted with
* TLSv1.
*/
if (s->state == SSL3_ST_SR_CLNT_HELLO_A
)
{
switch (s->state) {
case SSL3_ST_SR_CLNT_HELLO_A:
s->state=SSL3_ST_SR_CLNT_HELLO_B;
}
if (s->state != SSL3_ST_SR_CLNT_HELLO_D)
{
/* fallthrough */
case SSL3_ST_SR_CLNT_HELLO_B:
s->first_packet=1;
n=s->method->ssl_get_message(s,
SSL3_ST_SR_CLNT_HELLO_B,
@@ -941,14 +942,67 @@ int ssl3_get_client_hello(SSL *s)

if (!ok) return((int)n);
s->first_packet=0;
}
else
{
/* We have previously parsed the ClientHello message, and can't
* call ssl_get_message again without hashing the message into
* the Finished digest again. */

/* If we require cookies and this ClientHello doesn't
* contain one, just return since we do not want to
* allocate any memory yet. So check cookie length...
*/
if (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE)
{
unsigned int session_length, cookie_length;
p = (unsigned char *) s->init_msg;

if (n < 2 + SSL3_RANDOM_SIZE)
return 1;
session_length = *(p + 2 + SSL3_RANDOM_SIZE);
if (n < 2 + SSL3_RANDOM_SIZE + 1 + session_length)
return 1;
cookie_length =
*(p + 2 + SSL3_RANDOM_SIZE + 1 + session_length);
if (cookie_length == 0)
return 1;
}
s->state = SSL3_ST_SR_CLNT_HELLO_C;
/* fallthrough */
case SSL3_ST_SR_CLNT_HELLO_C:
case SSL3_ST_SR_CLNT_HELLO_D:
/* We have previously parsed the ClientHello message,
* and can't call ssl_get_message again without hashing
* the message into the Finished digest again. */
n = s->init_num;
}

memset(&early_ctx, 0, sizeof(early_ctx));
early_ctx.ssl = s;
early_ctx.client_hello = s->init_msg;
early_ctx.client_hello_len = n;
if (!ssl_early_callback_init(&early_ctx))
{
al = SSL_AD_DECODE_ERROR;
OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_CLIENTHELLO_PARSE_FAILED);
goto f_err;
}

if (s->state == SSL3_ST_SR_CLNT_HELLO_C &&
s->ctx->select_certificate_cb != NULL)
{
int ret;

s->state = SSL3_ST_SR_CLNT_HELLO_D;
ret = s->ctx->select_certificate_cb(&early_ctx);
if (ret == 0)
return CERTIFICATE_SELECTION_PENDING;
else if (ret == -1)
{
/* Connection rejected. */
al = SSL_AD_ACCESS_DENIED;
OPENSSL_PUT_ERROR(SSL, ssl3_get_client_hello, SSL_R_CONNECTION_REJECTED);
goto f_err;
}
}
s->state = SSL3_ST_SR_CLNT_HELLO_D;
default:
return -1;
}

d=p=(unsigned char *)s->init_msg;

@@ -972,21 +1026,6 @@ int ssl3_get_client_hello(SSL *s)
goto f_err;
}

/* If we require cookies and this ClientHello doesn't
* contain one, just return since we do not want to
* allocate any memory yet. So check cookie length...
*/
if (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE)
{
unsigned int session_length, cookie_length;
session_length = *(p + SSL3_RANDOM_SIZE);
cookie_length = *(p + SSL3_RANDOM_SIZE + session_length + 1);

if (cookie_length == 0)
return 1;
}

/* load the client random */
memcpy(s->s3->client_random,p,SSL3_RANDOM_SIZE);
p+=SSL3_RANDOM_SIZE;
@@ -1013,7 +1052,7 @@ int ssl3_get_client_hello(SSL *s)
}
else
{
i=ssl_get_prev_session(s, p, j, d + n);
i=ssl_get_prev_session(s, &early_ctx);
if (i == 1)
{ /* previous session */
s->hit=1;
@@ -1301,7 +1340,6 @@ int ssl3_get_client_hello(SSL *s)
}
ciphers=NULL;
/* Let cert callback update server certificates if required */
retry_cert:
if (s->cert->cert_cb)
{
int rv = s->cert->cert_cb(s, s->cert->cert_cb_arg);


+ 36
- 0
ssl/ssl.h View File

@@ -865,6 +865,30 @@ typedef struct ssl_aead_ctx_st SSL_AEAD_CTX;
typedef int (*GEN_SESSION_CB)(const SSL *ssl, unsigned char *id,
unsigned int *id_len);

/* ssl_early_callback_ctx is passed to certain callbacks that are called very
* early on during the server handshake. At this point, much of the SSL*
* hasn't been filled out and only the ClientHello can be depended on. */
struct ssl_early_callback_ctx
{
SSL *ssl;
const unsigned char *client_hello; size_t client_hello_len;
const unsigned char *session_id; size_t session_id_len;
const unsigned char *cipher_suites; size_t cipher_suites_len;
const unsigned char *compression_methods;size_t compression_methods_len;
const unsigned char *extensions; size_t extensions_len;
};

/* SSL_early_callback_ctx_extension_get searches the extensions in |ctx| for
* an extension of the given type. If not found, it returns zero. Otherwise
* it sets |out_data| to point to the extension contents (not including the type
* and length bytes), sets |out_len| to the length of the extension contents
* and returns one. */
char
SSL_early_callback_ctx_extension_get(const struct ssl_early_callback_ctx *ctx,
uint16_t extension_type,
const unsigned char **out_data,
size_t *out_len);

typedef struct ssl_comp_st SSL_COMP;

#ifndef OPENSSL_NO_SSL_INTERN
@@ -1051,6 +1075,13 @@ struct ssl_ctx_st

X509_VERIFY_PARAM *param;

/* select_certificate_cb is called before most ClientHello processing
* and before the decision whether to resume a session is made.
* It may return one to continue the handshake or zero to cause the
* handshake loop to return with an error and cause SSL_get_error to
* return SSL_ERROR_PENDING_CERTIFICATE. */
int (*select_certificate_cb) (const struct ssl_early_callback_ctx *);

#if 0
int purpose; /* Purpose setting */
int trust; /* Trust setting */
@@ -1353,6 +1384,7 @@ int SSL_CTX_set_custom_srv_ext(SSL_CTX *ctx, unsigned short ext_type,
#define SSL_X509_LOOKUP 4
#define SSL_CHANNEL_ID_LOOKUP 5
#define SSL_PENDING_SESSION 7
#define SSL_CERTIFICATE_SELECTION_PENDING 8

/* These will only be used when doing non-blocking IO */
#define SSL_want_nothing(s) (SSL_want(s) == SSL_NOTHING)
@@ -1361,6 +1393,7 @@ int SSL_CTX_set_custom_srv_ext(SSL_CTX *ctx, unsigned short ext_type,
#define SSL_want_x509_lookup(s) (SSL_want(s) == SSL_X509_LOOKUP)
#define SSL_want_channel_id_lookup(s) (SSL_want(s) == SSL_CHANNEL_ID_LOOKUP)
#define SSL_want_session(s) (SSL_want(s) == SSL_PENDING_SESSION)
#define SSL_want_certificate(s) (SSL_want(s) == SSL_CERTIFICATE_SELECTION_PENDING)

#define SSL_MAC_FLAG_READ_MAC_STREAM 1
#define SSL_MAC_FLAG_WRITE_MAC_STREAM 2
@@ -1787,6 +1820,7 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION)
#define SSL_ERROR_WANT_ACCEPT 8
#define SSL_ERROR_WANT_CHANNEL_ID_LOOKUP 9
#define SSL_ERROR_PENDING_SESSION 11
#define SSL_ERROR_PENDING_CERTIFICATE 12

#define SSL_CTRL_NEED_TMP_RSA 1
#define SSL_CTRL_SET_TMP_RSA 2
@@ -3059,5 +3093,7 @@ void ERR_load_SSL_strings(void);
#define SSL_R_UNEXPECTED_OPERATOR_IN_GROUP 434
#define SSL_R_MIXED_SPECIAL_OPERATOR_WITH_GROUPS 435
#define SSL_R_INAPPROPRIATE_FALLBACK 436
#define SSL_R_CLIENTHELLO_PARSE_FAILED 437
#define SSL_R_CONNECTION_REJECTED 438

#endif

+ 2
- 0
ssl/ssl_error.c View File

@@ -260,6 +260,7 @@ const ERR_STRING_DATA SSL_error_string_data[] = {
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_CIPHER_CODE_WRONG_LENGTH), "CIPHER_CODE_WRONG_LENGTH"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_CIPHER_OR_HASH_UNAVAILABLE), "CIPHER_OR_HASH_UNAVAILABLE"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_CIPHER_TABLE_SRC_ERROR), "CIPHER_TABLE_SRC_ERROR"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_CLIENTHELLO_PARSE_FAILED), "CLIENTHELLO_PARSE_FAILED"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_CLIENTHELLO_TLSEXT), "CLIENTHELLO_TLSEXT"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_COMPRESSED_LENGTH_TOO_LONG), "COMPRESSED_LENGTH_TOO_LONG"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_COMPRESSION_DISABLED), "COMPRESSION_DISABLED"},
@@ -267,6 +268,7 @@ const ERR_STRING_DATA SSL_error_string_data[] = {
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_COMPRESSION_ID_NOT_WITHIN_PRIVATE_RANGE), "COMPRESSION_ID_NOT_WITHIN_PRIVATE_RANGE"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_COMPRESSION_LIBRARY_ERROR), "COMPRESSION_LIBRARY_ERROR"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_CONNECTION_ID_IS_DIFFERENT), "CONNECTION_ID_IS_DIFFERENT"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_CONNECTION_REJECTED), "CONNECTION_REJECTED"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_CONNECTION_TYPE_NOT_SET), "CONNECTION_TYPE_NOT_SET"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_COOKIE_MISMATCH), "COOKIE_MISMATCH"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_D2I_ECDSA_SIG), "D2I_ECDSA_SIG"},


+ 3
- 0
ssl/ssl_lib.c View File

@@ -2823,6 +2823,9 @@ int SSL_get_error(const SSL *s,int i)
if ((i < 0) && SSL_want_session(s))
return(SSL_ERROR_PENDING_SESSION);

if ((i < 0) && SSL_want_certificate(s))
return(SSL_ERROR_PENDING_CERTIFICATE);

if ((i < 0) && SSL_want_read(s))
{
bio=SSL_get_rbio(s);


+ 5
- 3
ssl/ssl_locl.h View File

@@ -492,6 +492,7 @@
*/

#define PENDING_SESSION -10000
#define CERTIFICATE_SELECTION_PENDING -10001

#ifndef OPENSSL_NO_EC
/* From ECC-TLS draft, used in encoding the curve type in
@@ -996,7 +997,7 @@ SESS_CERT *ssl_sess_cert_new(void);
void ssl_sess_cert_free(SESS_CERT *sc);
int ssl_set_peer_cert_type(SESS_CERT *c, int type);
int ssl_get_new_session(SSL *s, int session);
int ssl_get_prev_session(SSL *s, unsigned char *session,int len, const unsigned char *limit);
int ssl_get_prev_session(SSL *s, const struct ssl_early_callback_ctx *ctx);
int ssl_cipher_id_cmp(const void *in_a, const void *in_b);
int ssl_cipher_ptr_id_cmp(const SSL_CIPHER **ap, const SSL_CIPHER **bp);
STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s,unsigned char *p,int num,
@@ -1281,6 +1282,7 @@ int ssl_check_srvr_ecc_cert_and_alg(X509 *x, SSL *s);

SSL_COMP *ssl3_comp_find(STACK_OF(SSL_COMP) *sk, int n);

char ssl_early_callback_init(struct ssl_early_callback_ctx *ctx);
#ifndef OPENSSL_NO_EC
int tls1_ec_curve_id2nid(int curve_id);
int tls1_ec_nid2curve_id(int nid);
@@ -1323,8 +1325,8 @@ int dtls1_process_heartbeat(SSL *s);
#else
#define tlsext_tick_md EVP_sha256
#endif
int tls1_process_ticket(SSL *s, unsigned char *session_id, int len,
const unsigned char *limit, SSL_SESSION **ret);
int tls1_process_ticket(SSL *s, const struct ssl_early_callback_ctx *ctx,
SSL_SESSION **ret);

int tls12_get_sigandhash(unsigned char *p, const EVP_PKEY *pk,
const EVP_MD *md);


+ 10
- 14
ssl/ssl_sess.c View File

@@ -427,11 +427,8 @@ int ssl_get_new_session(SSL *s, int session)
/* ssl_get_prev attempts to find an SSL_SESSION to be used to resume this
* connection. It is only called by servers.
*
* session_id: points at the session ID in the ClientHello. This code will
* read past the end of this in order to parse out the session ticket
* extension, if any.
* len: the length of the session ID.
* limit: a pointer to the first byte after the ClientHello.
* ctx: contains the early callback context, which is the result of a
* shallow parse of the ClientHello.
*
* Returns:
* -1: error
@@ -443,8 +440,7 @@ int ssl_get_new_session(SSL *s, int session)
* - Both for new and resumed sessions, s->tlsext_ticket_expected is set to 1
* if the server should issue a new session ticket (to 0 otherwise).
*/
int ssl_get_prev_session(SSL *s, unsigned char *session_id, int len,
const unsigned char *limit)
int ssl_get_prev_session(SSL *s, const struct ssl_early_callback_ctx *ctx)
{
/* This is used only by servers. */

@@ -455,14 +451,14 @@ int ssl_get_prev_session(SSL *s, unsigned char *session_id, int len,
int r;
#endif

if (len > SSL_MAX_SSL_SESSION_ID_LENGTH)
if (ctx->session_id_len > SSL_MAX_SSL_SESSION_ID_LENGTH)
goto err;

if (len == 0)
if (ctx->session_id_len == 0)
try_session_cache = 0;

#ifndef OPENSSL_NO_TLSEXT
r = tls1_process_ticket(s, session_id, len, limit, &ret); /* sets s->tlsext_ticket_expected */
r = tls1_process_ticket(s, ctx, &ret); /* sets s->tlsext_ticket_expected */
switch (r)
{
case -1: /* Error during processing */
@@ -486,10 +482,10 @@ int ssl_get_prev_session(SSL *s, unsigned char *session_id, int len,
{
SSL_SESSION data;
data.ssl_version=s->version;
data.session_id_length=len;
if (len == 0)
data.session_id_length=ctx->session_id_len;
if (ctx->session_id_len == 0)
return 0;
memcpy(data.session_id,session_id,len);
memcpy(data.session_id,ctx->session_id,ctx->session_id_len);
CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX);
ret=lh_SSL_SESSION_retrieve(s->session_ctx->sessions,&data);
if (ret != NULL)
@@ -508,7 +504,7 @@ int ssl_get_prev_session(SSL *s, unsigned char *session_id, int len,
{
int copy=1;
if ((ret=s->session_ctx->get_session_cb(s,session_id,len,&copy)))
if ((ret=s->session_ctx->get_session_cb(s,(unsigned char *) ctx->session_id,ctx->session_id_len,&copy)))
{
if (ret == SSL_magic_pending_session_ptr())
{


+ 210
- 76
ssl/t1_lib.c View File

@@ -213,6 +213,176 @@ void tls1_clear(SSL *s)
s->version = s->method->version;
}

char ssl_early_callback_init(struct ssl_early_callback_ctx *ctx)
{
size_t len = ctx->client_hello_len;
const unsigned char *p = ctx->client_hello;
uint16_t *extension_types;
unsigned num_extensions;

/* Skip client version. */
if (len < 2)
return 0;
len -= 2; p += 2;

/* Skip client nonce. */
if (len < 32)
return 0;
len -= 32; p += 32;

/* Get length of session id. */
if (len < 1)
return 0;
ctx->session_id_len = *p;
p++; len--;

ctx->session_id = p;
if (len < ctx->session_id_len)
return 0;
p += ctx->session_id_len; len -= ctx->session_id_len;

/* Skip past DTLS cookie */
if (ctx->ssl->version == DTLS1_VERSION || ctx->ssl->version == DTLS1_BAD_VER)
{
unsigned cookie_len;

if (len < 1)
return 0;
cookie_len = *p;
p++; len--;
if (len < cookie_len)
return 0;
p += cookie_len; len -= cookie_len;
}

/* Skip cipher suites. */
if (len < 2)
return 0;
n2s(p, ctx->cipher_suites_len);
len -= 2;

if ((ctx->cipher_suites_len & 1) != 0)
return 0;

ctx->cipher_suites = p;
if (len < ctx->cipher_suites_len)
return 0;
p += ctx->cipher_suites_len; len -= ctx->cipher_suites_len;

/* Skip compression methods. */
if (len < 1)
return 0;
ctx->compression_methods_len = *p;
p++; len--;

ctx->compression_methods = p;
if (len < ctx->compression_methods_len)
return 0;
p += ctx->compression_methods_len; len -= ctx->compression_methods_len;

/* If the ClientHello ends here then it's valid, but doesn't have any
* extensions. (E.g. SSLv3.) */
if (len == 0)
{
ctx->extensions = NULL;
ctx->extensions_len = 0;
return 1;
}

if (len < 2)
return 0;
n2s(p, ctx->extensions_len);
len -= 2;

if (ctx->extensions_len == 0 && len == 0)
{
ctx->extensions = NULL;
return 1;
}

ctx->extensions = p;
if (len != ctx->extensions_len)
return 0;

/* Verify that the extensions have valid lengths and that there are
* no duplicates. Each extension takes, at least, four bytes, so
* we can allocate a buffer of extensions_len/4 elements and be sure
* that we have enough space for all the extension types. */
extension_types =
OPENSSL_malloc(sizeof(uint16_t) * ctx->extensions_len/4);
if (extension_types == NULL)
return 0;
num_extensions = 0;

while (len != 0)
{
uint16_t extension_type, extension_len;
unsigned i;

if (len < 4)
goto err;
n2s(p, extension_type);
n2s(p, extension_len);
len -= 4;

if (len < extension_len)
goto err;
p += extension_len; len -= extension_len;

for (i = 0; i < num_extensions; i++)
{
if (extension_types[i] == extension_type)
{
/* Duplicate extension type. */
goto err;
}
}
extension_types[num_extensions] = extension_type;
num_extensions++;
}

OPENSSL_free(extension_types);
return 1;

err:
OPENSSL_free(extension_types);
return 0;
}

char
SSL_early_callback_ctx_extension_get(const struct ssl_early_callback_ctx *ctx,
uint16_t extension_type,
const unsigned char **out_data,
size_t *out_len)
{
size_t len = ctx->extensions_len;
const unsigned char *p = ctx->extensions;

while (len != 0)
{
uint16_t ext_type, ext_len;

if (len < 4)
return 0;
n2s(p, ext_type);
n2s(p, ext_len);
len -= 4;

if (len < ext_len)
return 0;
if (ext_type == extension_type)
{
*out_data = p;
*out_len = ext_len;
return 1;
}

p += ext_len; len -= ext_len;
}

return 0;
}

#ifndef OPENSSL_NO_EC

static int nid_list[] =
@@ -3423,11 +3593,8 @@ int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in
* ClientHello, and other operations depend on the result, we need to handle
* any TLS session ticket extension at the same time.
*
* session_id: points at the session ID in the ClientHello. This code will
* read past the end of this in order to parse out the session ticket
* extension, if any.
* len: the length of the session ID.
* limit: a pointer to the first byte after the ClientHello.
* ctx: contains the early callback context, which is the result of a
* shallow parse of the ClientHello.
* ret: (output) on return, if a ticket was decrypted, then this is set to
* point to the resulting session.
*
@@ -3452,91 +3619,58 @@ int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in
* s->ctx->tlsext_ticket_key_cb asked to renew the client's ticket.
* Otherwise, s->tlsext_ticket_expected is set to 0.
*/
int tls1_process_ticket(SSL *s, unsigned char *session_id, int len,
const unsigned char *limit, SSL_SESSION **ret)
int tls1_process_ticket(SSL *s, const struct ssl_early_callback_ctx *ctx,
SSL_SESSION **ret)
{
/* Point after session ID in client hello */
const unsigned char *p = session_id + len;
unsigned short i;

*ret = NULL;
s->tlsext_ticket_expected = 0;
const unsigned char *data;
size_t len;
int r;

/* If tickets disabled behave as if no ticket present
* to permit stateful resumption.
*/
if (SSL_get_options(s) & SSL_OP_NO_TICKET)
return 0;
if ((s->version <= SSL3_VERSION) || !limit)
if ((s->version <= SSL3_VERSION) && !ctx->extensions)
return 0;
if (p >= limit)
return -1;
/* Skip past DTLS cookie */
if (SSL_IS_DTLS(s))
if (!SSL_early_callback_ctx_extension_get(
ctx, TLSEXT_TYPE_session_ticket, &data, &len))
{
i = *(p++);
p+= i;
if (p >= limit)
return -1;
}
/* Skip past cipher list */
n2s(p, i);
p+= i;
if (p >= limit)
return -1;
/* Skip past compression algorithm list */
i = *(p++);
p += i;
if (p > limit)
return -1;
/* Now at start of extensions */
if ((p + 2) >= limit)
return 0;
n2s(p, i);
while ((p + 4) <= limit)
}
if (len == 0)
{
unsigned short type, size;
n2s(p, type);
n2s(p, size);
if (p + size > limit)
return 0;
if (type == TLSEXT_TYPE_session_ticket)
{
int r;
if (size == 0)
{
/* The client will accept a ticket but doesn't
* currently have one. */
s->tlsext_ticket_expected = 1;
return 1;
}
if (s->tls_session_secret_cb)
{
/* Indicate that the ticket couldn't be
* decrypted rather than generating the session
* from ticket now, trigger abbreviated
* handshake based on external mechanism to
* calculate the master secret later. */
return 2;
}
r = tls_decrypt_ticket(s, p, size, session_id, len, ret);
switch (r)
{
case 2: /* ticket couldn't be decrypted */
s->tlsext_ticket_expected = 1;
return 2;
case 3: /* ticket was decrypted */
return r;
case 4: /* ticket decrypted but need to renew */
s->tlsext_ticket_expected = 1;
return 3;
default: /* fatal error */
return -1;
}
}
p += size;
/* The client will accept a ticket but doesn't
* currently have one. */
s->tlsext_ticket_expected = 1;
return 1;
}
if (s->tls_session_secret_cb)
{
/* Indicate that the ticket couldn't be
* decrypted rather than generating the session
* from ticket now, trigger abbreviated
* handshake based on external mechanism to
* calculate the master secret later. */
return 2;
}
r = tls_decrypt_ticket(s, data, len, ctx->session_id,
ctx->session_id_len, ret);
switch (r)
{
case 2: /* ticket couldn't be decrypted */
s->tlsext_ticket_expected = 1;
return 2;
case 3: /* ticket was decrypted */
return r;
case 4: /* ticket decrypted but need to renew */
s->tlsext_ticket_expected = 1;
return 3;
default: /* fatal error */
return -1;
}
return 0;
}

/* tls_decrypt_ticket attempts to decrypt a session ticket.


Loading…
Cancel
Save