int tls_construct_server_hello(SSL *s)
{
- unsigned char *buf;
- unsigned char *p, *d;
- int i, sl;
- int al = 0;
- unsigned long l;
-
- buf = (unsigned char *)s->init_buf->data;
-
- /* Do the message type and length last */
- d = p = ssl_handshake_start(s);
-
- *(p++) = s->version >> 8;
- *(p++) = s->version & 0xff;
+ int sl;
+ int al = SSL_AD_INTERNAL_ERROR;
+ int compm;
+ size_t len;
+ WPACKET pkt;
- /*
- * Random stuff. Filling of the server_random takes place in
- * tls_process_client_hello()
- */
- memcpy(p, s->s3->server_random, SSL3_RANDOM_SIZE);
- p += SSL3_RANDOM_SIZE;
+ if (!WPACKET_init(&pkt, s->init_buf)
+ || !ssl_set_handshake_header2(s, &pkt, SSL3_MT_SERVER_HELLO)
+ || !WPACKET_put_bytes_u16(&pkt, s->version)
+ /*
+ * Random stuff. Filling of the server_random takes place in
+ * tls_process_client_hello()
+ */
+ || !WPACKET_memcpy(&pkt, s->s3->server_random, SSL3_RANDOM_SIZE)) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_HELLO, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
/*-
* There are several cases for the session ID to send
sl = s->session->session_id_length;
if (sl > (int)sizeof(s->session->session_id)) {
SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_HELLO, ERR_R_INTERNAL_ERROR);
- ossl_statem_set_error(s);
- return 0;
+ goto err;
}
- *(p++) = sl;
- memcpy(p, s->session->session_id, sl);
- p += sl;
- /* put the cipher */
- i = ssl3_put_cipher_by_char_old(s->s3->tmp.new_cipher, p);
- p += i;
-
- /* put the compression method */
+ /* set up the compression method */
#ifdef OPENSSL_NO_COMP
- *(p++) = 0;
+ compm = 0;
#else
if (s->s3->tmp.new_compression == NULL)
- *(p++) = 0;
+ compm = 0;
else
- *(p++) = s->s3->tmp.new_compression->id;
+ compm = s->s3->tmp.new_compression->id;
#endif
- if (ssl_prepare_serverhello_tlsext(s) <= 0) {
- SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_HELLO, SSL_R_SERVERHELLO_TLSEXT);
- ossl_statem_set_error(s);
- return 0;
- }
- if ((p =
- ssl_add_serverhello_tlsext(s, p, buf + SSL3_RT_MAX_PLAIN_LENGTH,
- &al)) == NULL) {
- ssl3_send_alert(s, SSL3_AL_FATAL, al);
- SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_HELLO, ERR_R_INTERNAL_ERROR);
- ossl_statem_set_error(s);
- return 0;
- }
-
- /* do the header */
- l = (p - d);
- if (!ssl_set_handshake_header(s, SSL3_MT_SERVER_HELLO, l)) {
+ if (!WPACKET_sub_memcpy_u8(&pkt, s->session->session_id, sl)
+ || !s->method->put_cipher_by_char(s->s3->tmp.new_cipher, &pkt, &len)
+ || !WPACKET_put_bytes_u8(&pkt, compm)
+ || !ssl_prepare_serverhello_tlsext(s)
+ || !ssl_add_serverhello_tlsext(s, &pkt, &al)
+ || !ssl_close_construct_packet(s, &pkt)) {
SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_HELLO, ERR_R_INTERNAL_ERROR);
- ossl_statem_set_error(s);
- return 0;
+ goto err;
}
return 1;
+ err:
+ WPACKET_cleanup(&pkt);
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+ ossl_statem_set_error(s);
+ return 0;
}
int tls_construct_server_done(SSL *s)
return 1;
}
-unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *buf,
- unsigned char *limit, int *al)
+int ssl_add_serverhello_tlsext(SSL *s, WPACKET *pkt, int *al)
{
- int extdatalen = 0;
- unsigned char *orig = buf;
- unsigned char *ret = buf;
#ifndef OPENSSL_NO_NEXTPROTONEG
int next_proto_neg_seen;
#endif
using_ecc = using_ecc && (s->session->tlsext_ecpointformatlist != NULL);
#endif
- ret += 2;
- if (ret >= limit)
- return NULL; /* this really never occurs, but ... */
-
- if (s->s3->send_connection_binding) {
- int el;
-
- if (!ssl_add_serverhello_renegotiate_ext(s, 0, &el, 0)) {
- SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
- return NULL;
- }
-
- if ((limit - ret - 4 - el) < 0)
- return NULL;
-
- s2n(TLSEXT_TYPE_renegotiate, ret);
- s2n(el, ret);
-
- if (!ssl_add_serverhello_renegotiate_ext(s, ret, &el, el)) {
- SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
- return NULL;
- }
+ if (!WPACKET_start_sub_packet_u16(pkt)
+ || !WPACKET_set_flags(pkt, WPACKET_FLAGS_ABANDON_ON_ZERO_LENGTH)) {
+ SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
- ret += el;
+ if (s->s3->send_connection_binding &&
+ !ssl_add_serverhello_renegotiate_ext(s, pkt)) {
+ SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
+ return 0;
}
/* Only add RI for SSLv3 */
goto done;
if (!s->hit && s->servername_done == 1
- && s->session->tlsext_hostname != NULL) {
- if ((long)(limit - ret - 4) < 0)
- return NULL;
-
- s2n(TLSEXT_TYPE_server_name, ret);
- s2n(0, ret);
+ && s->session->tlsext_hostname != NULL) {
+ if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_server_name)
+ || !WPACKET_put_bytes_u16(pkt, 0)) {
+ SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
}
#ifndef OPENSSL_NO_EC
if (using_ecc) {
/*
* Add TLS extension ECPointFormats to the ServerHello message
*/
- long lenmax;
-
tls1_get_formatlist(s, &plist, &plistlen);
- if ((lenmax = limit - ret - 5) < 0)
- return NULL;
- if (plistlen > (size_t)lenmax)
- return NULL;
- if (plistlen > 255) {
+ if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_ec_point_formats)
+ || !WPACKET_start_sub_packet_u16(pkt)
+ || !WPACKET_sub_memcpy_u8(pkt, plist, plistlen)
+ || !WPACKET_close(pkt)) {
SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
- return NULL;
+ return 0;
}
-
- s2n(TLSEXT_TYPE_ec_point_formats, ret);
- s2n(plistlen + 1, ret);
- *(ret++) = (unsigned char)plistlen;
- memcpy(ret, plist, plistlen);
- ret += plistlen;
-
}
/*
* Currently the server should not respond with a SupportedCurves
#endif /* OPENSSL_NO_EC */
if (s->tlsext_ticket_expected && tls_use_ticket(s)) {
- if ((long)(limit - ret - 4) < 0)
- return NULL;
- s2n(TLSEXT_TYPE_session_ticket, ret);
- s2n(0, ret);
+ if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_session_ticket)
+ || !WPACKET_put_bytes_u16(pkt, 0)) {
+ SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
} else {
/*
* if we don't add the above TLSEXT, we can't add a session ticket
}
if (s->tlsext_status_expected) {
- if ((long)(limit - ret - 4) < 0)
- return NULL;
- s2n(TLSEXT_TYPE_status_request, ret);
- s2n(0, ret);
+ if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_status_request)
+ || !WPACKET_put_bytes_u16(pkt, 0)) {
+ SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
}
#ifndef OPENSSL_NO_SRTP
if (SSL_IS_DTLS(s) && s->srtp_profile) {
- int el;
-
- /* Returns 0 on success!! */
- if (ssl_add_serverhello_use_srtp_ext(s, 0, &el, 0)) {
- SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
- return NULL;
- }
- if ((limit - ret - 4 - el) < 0)
- return NULL;
-
- s2n(TLSEXT_TYPE_use_srtp, ret);
- s2n(el, ret);
-
- if (ssl_add_serverhello_use_srtp_ext(s, ret, &el, el)) {
+ if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_use_srtp)
+ || !WPACKET_start_sub_packet_u16(pkt)
+ || !WPACKET_put_bytes_u16(pkt, 2)
+ || !WPACKET_put_bytes_u16(pkt, s->srtp_profile->id)
+ || !WPACKET_put_bytes_u8(pkt, 0)
+ || !WPACKET_close(pkt)) {
SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
- return NULL;
+ return 0;
}
- ret += el;
}
#endif
0x2a, 0x85, 0x03, 0x02, 0x02, 0x16, 0x30, 0x08,
0x06, 0x06, 0x2a, 0x85, 0x03, 0x02, 0x02, 0x17
};
- if (limit - ret < 36)
- return NULL;
- memcpy(ret, cryptopro_ext, 36);
- ret += 36;
-
+ if (!WPACKET_memcpy(pkt, cryptopro_ext, sizeof(cryptopro_ext))) {
+ SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
}
#ifndef OPENSSL_NO_HEARTBEATS
/* Add Heartbeat extension if we've received one */
if (SSL_IS_DTLS(s) && (s->tlsext_heartbeat & SSL_DTLSEXT_HB_ENABLED)) {
- if ((limit - ret - 4 - 1) < 0)
- return NULL;
- s2n(TLSEXT_TYPE_heartbeat, ret);
- s2n(1, ret);
/*-
* Set mode:
* 1: peer may send requests
* 2: peer not allowed to send requests
*/
if (s->tlsext_heartbeat & SSL_DTLSEXT_HB_DONT_RECV_REQUESTS)
- *(ret++) = SSL_DTLSEXT_HB_DONT_SEND_REQUESTS;
+ mode = SSL_DTLSEXT_HB_DONT_SEND_REQUESTS;
else
- *(ret++) = SSL_DTLSEXT_HB_ENABLED;
+ mode = SSL_DTLSEXT_HB_ENABLED;
+
+ if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_heartbeat)
+ || !WPACKET_start_sub_packet_u16(pkt)
+ || !WPACKET_put_bytes_u8(pkt, mode)
+ || !WPACKET_close(pkt)) {
+ SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
}
#endif
s->
ctx->next_protos_advertised_cb_arg);
if (r == SSL_TLSEXT_ERR_OK) {
- if ((long)(limit - ret - 4 - npalen) < 0)
- return NULL;
- s2n(TLSEXT_TYPE_next_proto_neg, ret);
- s2n(npalen, ret);
- memcpy(ret, npa, npalen);
- ret += npalen;
+ if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_next_proto_neg)
+ || !WPACKET_sub_memcpy_u16(pkt, npa, npalen)) {
+ SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
s->s3->next_proto_neg_seen = 1;
}
}
#endif
- if (!custom_ext_add_old(s, 1, &ret, limit, al))
- return NULL;
+ if (!custom_ext_add(s, 1, pkt, al)) {
+ SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
if (s->s3->flags & TLS1_FLAGS_ENCRYPT_THEN_MAC) {
/*
* Don't use encrypt_then_mac if AEAD or RC4 might want to disable
|| s->s3->tmp.new_cipher->algorithm_enc == SSL_eGOST2814789CNT12)
s->s3->flags &= ~TLS1_FLAGS_ENCRYPT_THEN_MAC;
else {
- s2n(TLSEXT_TYPE_encrypt_then_mac, ret);
- s2n(0, ret);
+ if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_encrypt_then_mac)
+ || !WPACKET_put_bytes_u16(pkt, 0)) {
+ SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
}
}
if (s->s3->flags & TLS1_FLAGS_RECEIVED_EXTMS) {
- s2n(TLSEXT_TYPE_extended_master_secret, ret);
- s2n(0, ret);
+ if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_extended_master_secret)
+ || !WPACKET_put_bytes_u16(pkt, 0)) {
+ SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
}
if (s->s3->alpn_selected != NULL) {
- const unsigned char *selected = s->s3->alpn_selected;
- unsigned int len = s->s3->alpn_selected_len;
-
- if ((long)(limit - ret - 4 - 2 - 1 - len) < 0)
- return NULL;
- s2n(TLSEXT_TYPE_application_layer_protocol_negotiation, ret);
- s2n(3 + len, ret);
- s2n(1 + len, ret);
- *ret++ = len;
- memcpy(ret, selected, len);
- ret += len;
+ if (!WPACKET_put_bytes_u16(pkt,
+ TLSEXT_TYPE_application_layer_protocol_negotiation)
+ || !WPACKET_start_sub_packet_u16(pkt)
+ || !WPACKET_start_sub_packet_u16(pkt)
+ || !WPACKET_sub_memcpy_u8(pkt, s->s3->alpn_selected,
+ s->s3->alpn_selected_len)
+ || !WPACKET_close(pkt)
+ || !WPACKET_close(pkt)) {
+ SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
}
done:
-
- if ((extdatalen = ret - orig - 2) == 0)
- return orig;
-
- s2n(extdatalen, orig);
- return ret;
+ if (!WPACKET_close(pkt)) {
+ SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ return 1;
}
/*