int tls_parse_ctos_supported_groups(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx) { PACKET supported_groups_list; /* Each group is 2 bytes and we must have at least 1. */ if (!PACKET_as_length_prefixed_2(pkt, &supported_groups_list) || PACKET_remaining(&supported_groups_list) == 0 || (PACKET_remaining(&supported_groups_list) % 2) != 0) { SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_SUPPORTED_GROUPS, SSL_R_BAD_EXTENSION); return 0; } if (!s->hit || SSL_IS_TLS13(s)) { OPENSSL_free(s->session->ext.supportedgroups); s->session->ext.supportedgroups = NULL; s->session->ext.supportedgroups_len = 0; if (!tls1_save_u16(&supported_groups_list, &s->session->ext.supportedgroups, &s->session->ext.supportedgroups_len)) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_SUPPORTED_GROUPS, ERR_R_INTERNAL_ERROR); return 0; } } return 1; }
int tls_parse_stoc_sct(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx, int *al) { /* * Only take it if we asked for it - i.e if there is no CT validation * callback set, then a custom extension MAY be processing it, so we * need to let control continue to flow to that. */ if (s->ct_validation_callback != NULL) { size_t size = PACKET_remaining(pkt); /* Simply copy it off for later processing */ OPENSSL_free(s->ext.scts); s->ext.scts = NULL; s->ext.scts_len = size; if (size > 0) { s->ext.scts = OPENSSL_malloc(size); if (s->ext.scts == NULL || !PACKET_copy_bytes(pkt, s->ext.scts, size)) { *al = SSL_AD_INTERNAL_ERROR; return 0; } } } else { if (custom_ext_parse(s, 0, TLSEXT_TYPE_signed_certificate_timestamp, PACKET_data(pkt), PACKET_remaining(pkt), al) <= 0) return 0; } return 1; }
int tls_parse_ctos_supported_groups(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx, int *al) { PACKET supported_groups_list; /* Each group is 2 bytes and we must have at least 1. */ if (!PACKET_as_length_prefixed_2(pkt, &supported_groups_list) || PACKET_remaining(&supported_groups_list) == 0 || (PACKET_remaining(&supported_groups_list) % 2) != 0) { *al = SSL_AD_DECODE_ERROR; return 0; } if (!s->hit || SSL_IS_TLS13(s)) { OPENSSL_free(s->session->ext.supportedgroups); s->session->ext.supportedgroups = NULL; s->session->ext.supportedgroups_len = 0; if (!PACKET_memdup(&supported_groups_list, &s->session->ext.supportedgroups, &s->session->ext.supportedgroups_len)) { *al = SSL_AD_INTERNAL_ERROR; return 0; } } return 1; }
static int test_PACKET_get_length_prefixed_1() { unsigned char buf[BUF_LEN]; const size_t len = 16; unsigned int i; PACKET pkt, short_pkt, subpkt; buf[0] = len; for (i = 1; i < BUF_LEN; i++) { buf[i] = (i * 2) & 0xff; } if ( !PACKET_buf_init(&pkt, buf, BUF_LEN) || !PACKET_buf_init(&short_pkt, buf, len) || !PACKET_get_length_prefixed_1(&pkt, &subpkt) || PACKET_remaining(&subpkt) != len || !PACKET_get_net_2(&subpkt, &i) || i != 0x0204 || PACKET_get_length_prefixed_1(&short_pkt, &subpkt) || PACKET_remaining(&short_pkt) != len) { fprintf(stderr, "test_PACKET_get_length_prefixed_1() failed\n"); return 0; } return 1; }
/* * Save the ALPN extension in a ClientHello.|pkt| holds the contents of the ALPN * extension, not including type and length. |al| is a pointer to the alert * value to send in the event of a failure. Returns: 1 on success, 0 on error. */ int tls_parse_ctos_alpn(SSL *s, PACKET *pkt, int *al) { PACKET protocol_list, save_protocol_list, protocol; if (s->s3->tmp.finish_md_len != 0) return 1; if (!PACKET_as_length_prefixed_2(pkt, &protocol_list) || PACKET_remaining(&protocol_list) < 2) { *al = SSL_AD_DECODE_ERROR; return 0; } save_protocol_list = protocol_list; do { /* Protocol names can't be empty. */ if (!PACKET_get_length_prefixed_1(&protocol_list, &protocol) || PACKET_remaining(&protocol) == 0) { *al = SSL_AD_DECODE_ERROR; return 0; } } while (PACKET_remaining(&protocol_list) != 0); if (!PACKET_memdup(&save_protocol_list, &s->s3->alpn_proposed, &s->s3->alpn_proposed_len)) { *al = TLS1_AD_INTERNAL_ERROR; return 0; } return 1; }
/* * Save the ALPN extension in a ClientHello.|pkt| holds the contents of the ALPN * extension, not including type and length. |al| is a pointer to the alert * value to send in the event of a failure. Returns: 1 on success, 0 on error. */ int tls_parse_ctos_alpn(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx, int *al) { PACKET protocol_list, save_protocol_list, protocol; if (!SSL_IS_FIRST_HANDSHAKE(s)) return 1; if (!PACKET_as_length_prefixed_2(pkt, &protocol_list) || PACKET_remaining(&protocol_list) < 2) { *al = SSL_AD_DECODE_ERROR; return 0; } save_protocol_list = protocol_list; do { /* Protocol names can't be empty. */ if (!PACKET_get_length_prefixed_1(&protocol_list, &protocol) || PACKET_remaining(&protocol) == 0) { *al = SSL_AD_DECODE_ERROR; return 0; } } while (PACKET_remaining(&protocol_list) != 0); OPENSSL_free(s->s3->alpn_proposed); s->s3->alpn_proposed = NULL; s->s3->alpn_proposed_len = 0; if (!PACKET_memdup(&save_protocol_list, &s->s3->alpn_proposed, &s->s3->alpn_proposed_len)) { *al = SSL_AD_INTERNAL_ERROR; return 0; } return 1; }
int tls_parse_stoc_alpn(SSL *s, PACKET *pkt, int *al) { size_t len; /* We must have requested it. */ if (!s->s3->alpn_sent) { *al = SSL_AD_UNSUPPORTED_EXTENSION; return 0; } /*- * The extension data consists of: * uint16 list_length * uint8 proto_length; * uint8 proto[proto_length]; */ if (!PACKET_get_net_2_len(pkt, &len) || PACKET_remaining(pkt) != len || !PACKET_get_1_len(pkt, &len) || PACKET_remaining(pkt) != len) { *al = SSL_AD_DECODE_ERROR; return 0; } OPENSSL_free(s->s3->alpn_selected); s->s3->alpn_selected = OPENSSL_malloc(len); if (s->s3->alpn_selected == NULL) { *al = SSL_AD_INTERNAL_ERROR; return 0; } if (!PACKET_copy_bytes(pkt, s->s3->alpn_selected, len)) { *al = SSL_AD_DECODE_ERROR; return 0; } s->s3->alpn_selected_len = len; return 1; }
static int test_PACKET_get_length_prefixed_3() { unsigned char buf[1024]; const size_t len = 516; /* 0x000204 */ unsigned int i; PACKET pkt, short_pkt, subpkt; for (i = 0; i < 1024; i++) { buf[i] = (i * 2) & 0xff; } if ( !PACKET_buf_init(&pkt, buf, 1024) || !PACKET_buf_init(&short_pkt, buf, len) || !PACKET_get_length_prefixed_3(&pkt, &subpkt) || PACKET_remaining(&subpkt) != len || !PACKET_get_net_2(&subpkt, &i) || i != 0x0608 || PACKET_get_length_prefixed_3(&short_pkt, &subpkt) || PACKET_remaining(&short_pkt) != len) { fprintf(stderr, "test_PACKET_get_length_prefixed_3() failed\n"); return 0; } return 1; }
/*- * The servername extension is treated as follows: * * - Only the hostname type is supported with a maximum length of 255. * - The servername is rejected if too long or if it contains zeros, * in which case an fatal alert is generated. * - The servername field is maintained together with the session cache. * - When a session is resumed, the servername call back invoked in order * to allow the application to position itself to the right context. * - The servername is acknowledged if it is new for a session or when * it is identical to a previously used for the same session. * Applications can control the behaviour. They can at any time * set a 'desirable' servername for a new SSL object. This can be the * case for example with HTTPS when a Host: header field is received and * a renegotiation is requested. In this case, a possible servername * presented in the new client hello is only acknowledged if it matches * the value of the Host: field. * - Applications must use SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION * if they provide for changing an explicit servername context for the * session, i.e. when the session has been established with a servername * extension. * - On session reconnect, the servername extension may be absent. */ int tls_parse_ctos_server_name(SSL *s, PACKET *pkt, int *al) { unsigned int servname_type; PACKET sni, hostname; if (!PACKET_as_length_prefixed_2(pkt, &sni) /* ServerNameList must be at least 1 byte long. */ || PACKET_remaining(&sni) == 0) { *al = SSL_AD_DECODE_ERROR; return 0; } /* * Although the server_name extension was intended to be * extensible to new name types, RFC 4366 defined the * syntax inextensibly and OpenSSL 1.0.x parses it as * such. * RFC 6066 corrected the mistake but adding new name types * is nevertheless no longer feasible, so act as if no other * SNI types can exist, to simplify parsing. * * Also note that the RFC permits only one SNI value per type, * i.e., we can only have a single hostname. */ if (!PACKET_get_1(&sni, &servname_type) || servname_type != TLSEXT_NAMETYPE_host_name || !PACKET_as_length_prefixed_2(&sni, &hostname)) { *al = SSL_AD_DECODE_ERROR; return 0; } if (!s->hit) { if (PACKET_remaining(&hostname) > TLSEXT_MAXLEN_host_name) { *al = TLS1_AD_UNRECOGNIZED_NAME; return 0; } if (PACKET_contains_zero_byte(&hostname)) { *al = TLS1_AD_UNRECOGNIZED_NAME; return 0; } if (!PACKET_strndup(&hostname, &s->session->tlsext_hostname)) { *al = TLS1_AD_INTERNAL_ERROR; return 0; } s->servername_done = 1; } else { /* * TODO(openssl-team): if the SNI doesn't match, we MUST * fall back to a full handshake. */ s->servername_done = s->session->tlsext_hostname && PACKET_equal(&hostname, s->session->tlsext_hostname, strlen(s->session->tlsext_hostname)); } return 1; }
int tls_parse_stoc_key_share(SSL *s, PACKET *pkt, int *al) { unsigned int group_id; PACKET encoded_pt; EVP_PKEY *ckey = s->s3->tmp.pkey, *skey = NULL; /* Sanity check */ if (ckey == NULL) { *al = SSL_AD_INTERNAL_ERROR; SSLerr(SSL_F_TLS_PARSE_STOC_KEY_SHARE, ERR_R_INTERNAL_ERROR); return 0; } if (!PACKET_get_net_2(pkt, &group_id)) { *al = SSL_AD_HANDSHAKE_FAILURE; SSLerr(SSL_F_TLS_PARSE_STOC_KEY_SHARE, SSL_R_LENGTH_MISMATCH); return 0; } if (group_id != s->s3->group_id) { /* * This isn't for the group that we sent in the original * key_share! */ *al = SSL_AD_HANDSHAKE_FAILURE; SSLerr(SSL_F_TLS_PARSE_STOC_KEY_SHARE, SSL_R_BAD_KEY_SHARE); return 0; } if (!PACKET_as_length_prefixed_2(pkt, &encoded_pt) || PACKET_remaining(&encoded_pt) == 0) { *al = SSL_AD_DECODE_ERROR; SSLerr(SSL_F_TLS_PARSE_STOC_KEY_SHARE, SSL_R_LENGTH_MISMATCH); return 0; } skey = ssl_generate_pkey(ckey); if (skey == NULL) { *al = SSL_AD_INTERNAL_ERROR; SSLerr(SSL_F_TLS_PARSE_STOC_KEY_SHARE, ERR_R_MALLOC_FAILURE); return 0; } if (!EVP_PKEY_set1_tls_encodedpoint(skey, PACKET_data(&encoded_pt), PACKET_remaining(&encoded_pt))) { *al = SSL_AD_DECODE_ERROR; SSLerr(SSL_F_TLS_PARSE_STOC_KEY_SHARE, SSL_R_BAD_ECPOINT); return 0; } if (ssl_derive(s, ckey, skey, 1) == 0) { *al = SSL_AD_INTERNAL_ERROR; SSLerr(SSL_F_TLS_PARSE_STOC_KEY_SHARE, ERR_R_INTERNAL_ERROR); EVP_PKEY_free(skey); return 0; } EVP_PKEY_free(skey); return 1; }
/* * ssl_next_proto_validate validates a Next Protocol Negotiation block. No * elements of zero length are allowed and the set of elements must exactly * fill the length of the block. Returns 1 on success or 0 on failure. */ static int ssl_next_proto_validate(PACKET *pkt) { PACKET tmp_protocol; while (PACKET_remaining(pkt)) { if (!PACKET_get_length_prefixed_1(pkt, &tmp_protocol) || PACKET_remaining(&tmp_protocol) == 0) return 0; } return 1; }
static int test_PACKET_remaining(PACKET *pkt) { if ( PACKET_remaining(pkt) != BUF_LEN || !PACKET_forward(pkt, BUF_LEN - 1) || PACKET_remaining(pkt) != 1 || !PACKET_forward(pkt, 1) || PACKET_remaining(pkt) != 0) { fprintf(stderr, "test_PACKET_remaining() failed\n"); return 0; } return 1; }
static int test_PACKET_remaining() { PACKET pkt; if (!TEST_true(PACKET_buf_init(&pkt, smbuf, sizeof(smbuf)) || !TEST_size_t_eq(PACKET_remaining(&pkt), BUF_LEN) || !TEST_true(PACKET_forward(&pkt, BUF_LEN - 1)) || !TEST_size_t_eq(PACKET_remaining(&pkt), 1) || !TEST_true(PACKET_forward(&pkt, 1)) || !TEST_size_t_eq(PACKET_remaining(&pkt), 0))) return 0; return 1; }
static int get_sni_from_client_hello(BIO *bio, char **sni) { long len; unsigned char *data; PACKET pkt = {0}, pkt2 = {0}, pkt3 = {0}, pkt4 = {0}, pkt5 = {0}; unsigned int servname_type = 0, type = 0; int ret = 0; len = BIO_get_mem_data(bio, (char **)&data); if (!TEST_true(PACKET_buf_init(&pkt, data, len)) /* Skip the record header */ || !PACKET_forward(&pkt, SSL3_RT_HEADER_LENGTH) /* Skip the handshake message header */ || !TEST_true(PACKET_forward(&pkt, SSL3_HM_HEADER_LENGTH)) /* Skip client version and random */ || !TEST_true(PACKET_forward(&pkt, CLIENT_VERSION_LEN + SSL3_RANDOM_SIZE)) /* Skip session id */ || !TEST_true(PACKET_get_length_prefixed_1(&pkt, &pkt2)) /* Skip ciphers */ || !TEST_true(PACKET_get_length_prefixed_2(&pkt, &pkt2)) /* Skip compression */ || !TEST_true(PACKET_get_length_prefixed_1(&pkt, &pkt2)) /* Extensions len */ || !TEST_true(PACKET_as_length_prefixed_2(&pkt, &pkt2))) goto end; /* Loop through all extensions for SNI */ while (PACKET_remaining(&pkt2)) { if (!TEST_true(PACKET_get_net_2(&pkt2, &type)) || !TEST_true(PACKET_get_length_prefixed_2(&pkt2, &pkt3))) goto end; if (type == TLSEXT_TYPE_server_name) { if (!TEST_true(PACKET_get_length_prefixed_2(&pkt3, &pkt4)) || !TEST_uint_ne(PACKET_remaining(&pkt4), 0) || !TEST_true(PACKET_get_1(&pkt4, &servname_type)) || !TEST_uint_eq(servname_type, TLSEXT_NAMETYPE_host_name) || !TEST_true(PACKET_get_length_prefixed_2(&pkt4, &pkt5)) || !TEST_uint_le(PACKET_remaining(&pkt5), TLSEXT_MAXLEN_host_name) || !TEST_false(PACKET_contains_zero_byte(&pkt5)) || !TEST_true(PACKET_strndup(&pkt5, sni))) goto end; ret = 1; goto end; } } end: return ret; }
static int test_PACKET_buf_init() { unsigned char buf1[BUF_LEN]; PACKET pkt; /* Also tests PACKET_remaining() */ if (!TEST_true(PACKET_buf_init(&pkt, buf1, 4)) || !TEST_size_t_eq(PACKET_remaining(&pkt), 4) || !TEST_true(PACKET_buf_init(&pkt, buf1, BUF_LEN)) || !TEST_size_t_eq(PACKET_remaining(&pkt), BUF_LEN) || !TEST_false(PACKET_buf_init(&pkt, buf1, -1))) return 0; return 1; }
/* * Parse the server's renegotiation binding and abort if it's not right */ int ssl_parse_serverhello_renegotiate_ext(SSL *s, PACKET *pkt, int *al) { unsigned int expected_len = s->s3->previous_client_finished_len + s->s3->previous_server_finished_len; unsigned int ilen; const unsigned char *data; /* Check for logic errors */ OPENSSL_assert(!expected_len || s->s3->previous_client_finished_len); OPENSSL_assert(!expected_len || s->s3->previous_server_finished_len); /* Parse the length byte */ if (!PACKET_get_1(pkt, &ilen)) { SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT, SSL_R_RENEGOTIATION_ENCODING_ERR); *al = SSL_AD_ILLEGAL_PARAMETER; return 0; } /* Consistency check */ if (PACKET_remaining(pkt) != ilen) { SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT, SSL_R_RENEGOTIATION_ENCODING_ERR); *al = SSL_AD_ILLEGAL_PARAMETER; return 0; } /* Check that the extension matches */ if (ilen != expected_len) { SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT, SSL_R_RENEGOTIATION_MISMATCH); *al = SSL_AD_HANDSHAKE_FAILURE; return 0; } if (!PACKET_get_bytes(pkt, &data, s->s3->previous_client_finished_len) || memcmp(data, s->s3->previous_client_finished, s->s3->previous_client_finished_len) != 0) { SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT, SSL_R_RENEGOTIATION_MISMATCH); *al = SSL_AD_HANDSHAKE_FAILURE; return 0; } if (!PACKET_get_bytes(pkt, &data, s->s3->previous_server_finished_len) || memcmp(data, s->s3->previous_server_finished, s->s3->previous_server_finished_len) != 0) { SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT, SSL_R_RENEGOTIATION_MISMATCH); *al = SSL_AD_ILLEGAL_PARAMETER; return 0; } #ifdef OPENSSL_RI_DEBUG fprintf(stderr, "%s RI extension received by client\n", ilen ? "Non-empty" : "Empty"); #endif s->s3->send_connection_binding = 1; return 1; }
/* * Process a psk_kex_modes extension received in the ClientHello. |pkt| contains * the raw PACKET data for the extension. Returns 1 on success or 0 on failure. */ int tls_parse_ctos_psk_kex_modes(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx) { #ifndef OPENSSL_NO_TLS1_3 PACKET psk_kex_modes; unsigned int mode; if (!PACKET_as_length_prefixed_1(pkt, &psk_kex_modes) || PACKET_remaining(&psk_kex_modes) == 0) { SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_PSK_KEX_MODES, SSL_R_BAD_EXTENSION); return 0; } while (PACKET_get_1(&psk_kex_modes, &mode)) { if (mode == TLSEXT_KEX_MODE_KE_DHE) s->ext.psk_kex_mode |= TLSEXT_KEX_MODE_FLAG_KE_DHE; else if (mode == TLSEXT_KEX_MODE_KE && (s->options & SSL_OP_ALLOW_NO_DHE_KEX) != 0) s->ext.psk_kex_mode |= TLSEXT_KEX_MODE_FLAG_KE; } #endif return 1; }
int tls_parse_stoc_ec_pt_formats(SSL *s, PACKET *pkt, int *al) { unsigned int ecpointformatlist_length; PACKET ecptformatlist; if (!PACKET_as_length_prefixed_1(pkt, &ecptformatlist)) { *al = SSL_AD_DECODE_ERROR; return 0; } if (!s->hit) { ecpointformatlist_length = PACKET_remaining(&ecptformatlist); s->session->tlsext_ecpointformatlist_length = 0; OPENSSL_free(s->session->tlsext_ecpointformatlist); s->session->tlsext_ecpointformatlist = OPENSSL_malloc(ecpointformatlist_length); if (s->session->tlsext_ecpointformatlist == NULL) { *al = SSL_AD_INTERNAL_ERROR; return 0; } s->session->tlsext_ecpointformatlist_length = ecpointformatlist_length; if (!PACKET_copy_bytes(&ecptformatlist, s->session->tlsext_ecpointformatlist, ecpointformatlist_length)) { *al = SSL_AD_INTERNAL_ERROR; return 0; } } return 1; }
static int test_PACKET_remaining(unsigned char buf[BUF_LEN]) { PACKET pkt; if ( !PACKET_buf_init(&pkt, buf, BUF_LEN) || PACKET_remaining(&pkt) != BUF_LEN || !PACKET_forward(&pkt, BUF_LEN - 1) || PACKET_remaining(&pkt) != 1 || !PACKET_forward(&pkt, 1) || PACKET_remaining(&pkt) != 0) { fprintf(stderr, "test_PACKET_remaining() failed\n"); return 0; } return 1; }
int tls_parse_stoc_status_request(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx, int *al) { /* * MUST only be sent if we've requested a status * request message. In TLS <= 1.2 it must also be empty. */ if (s->ext.status_type == TLSEXT_STATUSTYPE_nothing || (!SSL_IS_TLS13(s) && PACKET_remaining(pkt) > 0)) { *al = SSL_AD_UNSUPPORTED_EXTENSION; return 0; } if (SSL_IS_TLS13(s)) { /* We only know how to handle this if it's for the first Certificate in * the chain. We ignore any other repsonses. */ if (chainidx != 0) return 1; return tls_process_cert_status_body(s, pkt, al); } /* Set flag to expect CertificateStatus message */ s->ext.status_expected = 1; return 1; }
int tls_parse_stoc_ec_pt_formats(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx, int *al) { unsigned int ecpointformats_len; PACKET ecptformatlist; if (!PACKET_as_length_prefixed_1(pkt, &ecptformatlist)) { *al = SSL_AD_DECODE_ERROR; return 0; } if (!s->hit) { ecpointformats_len = PACKET_remaining(&ecptformatlist); s->session->ext.ecpointformats_len = 0; OPENSSL_free(s->session->ext.ecpointformats); s->session->ext.ecpointformats = OPENSSL_malloc(ecpointformats_len); if (s->session->ext.ecpointformats == NULL) { *al = SSL_AD_INTERNAL_ERROR; return 0; } s->session->ext.ecpointformats_len = ecpointformats_len; if (!PACKET_copy_bytes(&ecptformatlist, s->session->ext.ecpointformats, ecpointformats_len)) { *al = SSL_AD_INTERNAL_ERROR; return 0; } } return 1; }
/* * Parse the server's renegotiation binding and abort if it's not right */ int tls_parse_stoc_renegotiate(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx, int *al) { size_t expected_len = s->s3->previous_client_finished_len + s->s3->previous_server_finished_len; size_t ilen; const unsigned char *data; /* Check for logic errors */ assert(expected_len == 0 || s->s3->previous_client_finished_len != 0); assert(expected_len == 0 || s->s3->previous_server_finished_len != 0); /* Parse the length byte */ if (!PACKET_get_1_len(pkt, &ilen)) { SSLerr(SSL_F_TLS_PARSE_STOC_RENEGOTIATE, SSL_R_RENEGOTIATION_ENCODING_ERR); *al = SSL_AD_ILLEGAL_PARAMETER; return 0; } /* Consistency check */ if (PACKET_remaining(pkt) != ilen) { SSLerr(SSL_F_TLS_PARSE_STOC_RENEGOTIATE, SSL_R_RENEGOTIATION_ENCODING_ERR); *al = SSL_AD_ILLEGAL_PARAMETER; return 0; } /* Check that the extension matches */ if (ilen != expected_len) { SSLerr(SSL_F_TLS_PARSE_STOC_RENEGOTIATE, SSL_R_RENEGOTIATION_MISMATCH); *al = SSL_AD_HANDSHAKE_FAILURE; return 0; } if (!PACKET_get_bytes(pkt, &data, s->s3->previous_client_finished_len) || memcmp(data, s->s3->previous_client_finished, s->s3->previous_client_finished_len) != 0) { SSLerr(SSL_F_TLS_PARSE_STOC_RENEGOTIATE, SSL_R_RENEGOTIATION_MISMATCH); *al = SSL_AD_HANDSHAKE_FAILURE; return 0; } if (!PACKET_get_bytes(pkt, &data, s->s3->previous_server_finished_len) || memcmp(data, s->s3->previous_server_finished, s->s3->previous_server_finished_len) != 0) { SSLerr(SSL_F_TLS_PARSE_STOC_RENEGOTIATE, SSL_R_RENEGOTIATION_MISMATCH); *al = SSL_AD_ILLEGAL_PARAMETER; return 0; } s->s3->send_connection_binding = 1; return 1; }
int tls_parse_ctos_sig_algs(SSL *s, PACKET *pkt, int *al) { PACKET supported_sig_algs; if (!PACKET_as_length_prefixed_2(pkt, &supported_sig_algs) || (PACKET_remaining(&supported_sig_algs) % 2) != 0 || PACKET_remaining(&supported_sig_algs) == 0) { *al = SSL_AD_DECODE_ERROR; return 0; } if (!s->hit && !tls1_save_sigalgs(s, PACKET_data(&supported_sig_algs), PACKET_remaining(&supported_sig_algs))) { *al = TLS1_AD_INTERNAL_ERROR; return 0; } return 1; }
int tls_parse_stoc_session_ticket(SSL *s, PACKET *pkt, int *al) { if (s->tls_session_ticket_ext_cb != NULL && !s->tls_session_ticket_ext_cb(s, PACKET_data(pkt), PACKET_remaining(pkt), s->tls_session_ticket_ext_cb_arg)) { *al = SSL_AD_INTERNAL_ERROR; return 0; } if (!tls_use_ticket(s) || PACKET_remaining(pkt) > 0) { *al = SSL_AD_UNSUPPORTED_EXTENSION; return 0; } s->tlsext_ticket_expected = 1; return 1; }
int tls_parse_ctos_early_data(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx, int *al) { if (PACKET_remaining(pkt) != 0) { *al = SSL_AD_DECODE_ERROR; return 0; } return 1; }
static int test_PACKET_null_init() { PACKET pkt; PACKET_null_init(&pkt); if (!TEST_size_t_eq(PACKET_remaining(&pkt), 0) || !TEST_false(PACKET_forward(&pkt, 1))) return 0; return 1; }
static int test_PACKET_copy_bytes(PACKET *pkt, size_t start) { unsigned char bytes[4]; if ( !PACKET_goto_bookmark(pkt, start) || !PACKET_copy_bytes(pkt, bytes, 4) || bytes[0] != 2 || bytes[1] != 4 || bytes[2] != 6 || bytes[3] != 8 || PACKET_remaining(pkt) != BUF_LEN - 4 || !PACKET_forward(pkt, BUF_LEN - 8) || !PACKET_copy_bytes(pkt, bytes, 4) || bytes[0] != 0xf8 || bytes[1] != 0xfa || bytes[2] != 0xfc || bytes[3] != 0xfe || PACKET_remaining(pkt)) { fprintf(stderr, "test_PACKET_copy_bytes() failed\n"); return 0; } return 1; }
int tls_parse_stoc_session_ticket(SSL *s, PACKET *pkt, unsigned int context, X509 *x, size_t chainidx, int *al) { if (s->ext.session_ticket_cb != NULL && !s->ext.session_ticket_cb(s, PACKET_data(pkt), PACKET_remaining(pkt), s->ext.session_ticket_cb_arg)) { *al = SSL_AD_INTERNAL_ERROR; return 0; } if (!tls_use_ticket(s) || PACKET_remaining(pkt) > 0) { *al = SSL_AD_UNSUPPORTED_EXTENSION; return 0; } s->ext.ticket_expected = 1; return 1; }
static int test_PACKET_get_sub_packet() { PACKET pkt, subpkt; unsigned long i; if (!TEST_true(PACKET_buf_init(&pkt, smbuf, BUF_LEN)) || !TEST_true(PACKET_get_sub_packet(&pkt, &subpkt, 4)) || !TEST_true(PACKET_get_net_4(&subpkt, &i)) || !TEST_ulong_eq(i, 0x02040608UL) || !TEST_size_t_eq(PACKET_remaining(&subpkt), 0) || !TEST_true(PACKET_forward(&pkt, BUF_LEN - 8)) || !TEST_true(PACKET_get_sub_packet(&pkt, &subpkt, 4)) || !TEST_true(PACKET_get_net_4(&subpkt, &i)) || !TEST_ulong_eq(i, 0xf8fafcfeUL) || !TEST_size_t_eq(PACKET_remaining(&subpkt), 0) || !TEST_false(PACKET_get_sub_packet(&pkt, &subpkt, 4))) return 0; return 1; }
static int test_PACKET_copy_bytes(unsigned char buf[BUF_LEN]) { unsigned char bytes[4]; PACKET pkt; if ( !PACKET_buf_init(&pkt, buf, BUF_LEN) || !PACKET_copy_bytes(&pkt, bytes, 4) || bytes[0] != 2 || bytes[1] != 4 || bytes[2] != 6 || bytes[3] != 8 || PACKET_remaining(&pkt) != BUF_LEN - 4 || !PACKET_forward(&pkt, BUF_LEN - 8) || !PACKET_copy_bytes(&pkt, bytes, 4) || bytes[0] != 0xf8 || bytes[1] != 0xfa || bytes[2] != 0xfc || bytes[3] != 0xfe || PACKET_remaining(&pkt)) { fprintf(stderr, "test_PACKET_copy_bytes() failed\n"); return 0; } return 1; }