#endif
#include "ssl_locl.h"
-const char tls1_version_str[] = "TLSv1" OPENSSL_VERSION_PTEXT;
-
-#ifndef OPENSSL_NO_TLSEXT
static int tls_decrypt_ticket(SSL *s, const unsigned char *tick, int ticklen,
const unsigned char *sess_id, int sesslen,
SSL_SESSION **psess);
static int ssl_check_clienthello_tlsext_early(SSL *s);
int ssl_check_serverhello_tlsext(SSL *s);
-#endif
SSL3_ENC_METHOD const TLSv1_enc_data = {
tls1_enc,
void tls1_free(SSL *s)
{
-#ifndef OPENSSL_NO_TLSEXT
OPENSSL_free(s->tlsext_session_ticket);
-#endif /* OPENSSL_NO_TLSEXT */
ssl3_free(s);
}
TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2
};
-static const unsigned char eccurves_default[] = {
- 0, 14, /* sect571r1 (14) */
- 0, 13, /* sect571k1 (13) */
+/* The client's default curves / the server's 'auto' curves. */
+static const unsigned char eccurves_auto[] = {
+ /* Prefer P-256 which has the fastest and most secure implementations. */
+ 0, 23, /* secp256r1 (23) */
+ /* Other >= 256-bit prime curves. */
0, 25, /* secp521r1 (25) */
0, 28, /* brainpool512r1 (28) */
- 0, 11, /* sect409k1 (11) */
- 0, 12, /* sect409r1 (12) */
0, 27, /* brainpoolP384r1 (27) */
0, 24, /* secp384r1 (24) */
+ 0, 26, /* brainpoolP256r1 (26) */
+ 0, 22, /* secp256k1 (22) */
+ /* >= 256-bit binary curves. */
+ 0, 14, /* sect571r1 (14) */
+ 0, 13, /* sect571k1 (13) */
+ 0, 11, /* sect409k1 (11) */
+ 0, 12, /* sect409r1 (12) */
0, 9, /* sect283k1 (9) */
0, 10, /* sect283r1 (10) */
+};
+
+static const unsigned char eccurves_all[] = {
+ /* Prefer P-256 which has the fastest and most secure implementations. */
+ 0, 23, /* secp256r1 (23) */
+ /* Other >= 256-bit prime curves. */
+ 0, 25, /* secp521r1 (25) */
+ 0, 28, /* brainpool512r1 (28) */
+ 0, 27, /* brainpoolP384r1 (27) */
+ 0, 24, /* secp384r1 (24) */
0, 26, /* brainpoolP256r1 (26) */
0, 22, /* secp256k1 (22) */
- 0, 23, /* secp256r1 (23) */
+ /* >= 256-bit binary curves. */
+ 0, 14, /* sect571r1 (14) */
+ 0, 13, /* sect571k1 (13) */
+ 0, 11, /* sect409k1 (11) */
+ 0, 12, /* sect409r1 (12) */
+ 0, 9, /* sect283k1 (9) */
+ 0, 10, /* sect283r1 (10) */
+ /*
+ * Remaining curves disabled by default but still permitted if set
+ * via an explicit callback or parameters.
+ */
+ 0, 20, /* secp224k1 (20) */
+ 0, 21, /* secp224r1 (21) */
+ 0, 18, /* secp192k1 (18) */
+ 0, 19, /* secp192r1 (19) */
+ 0, 15, /* secp160k1 (15) */
+ 0, 16, /* secp160r1 (16) */
+ 0, 17, /* secp160r2 (17) */
0, 8, /* sect239k1 (8) */
0, 6, /* sect233k1 (6) */
0, 7, /* sect233r1 (7) */
- 0, 20, /* secp224k1 (20) */
- 0, 21, /* secp224r1 (21) */
0, 4, /* sect193r1 (4) */
0, 5, /* sect193r2 (5) */
- 0, 18, /* secp192k1 (18) */
- 0, 19, /* secp192r1 (19) */
0, 1, /* sect163k1 (1) */
0, 2, /* sect163r1 (2) */
0, 3, /* sect163r2 (3) */
- 0, 15, /* secp160k1 (15) */
- 0, 16, /* secp160r1 (16) */
- 0, 17, /* secp160r2 (17) */
};
+
static const unsigned char suiteb_curves[] = {
0, TLSEXT_curve_P_256,
0, TLSEXT_curve_P_384
pcurveslen = s->tlsext_ellipticcurvelist_length;
}
if (!*pcurves) {
- *pcurves = eccurves_default;
- pcurveslen = sizeof(eccurves_default);
+ if (!s->server || (s->cert && s->cert->ecdh_tmp_auto)) {
+ *pcurves = eccurves_auto;
+ pcurveslen = sizeof(eccurves_auto);
+ } else {
+ *pcurves = eccurves_all;
+ pcurveslen = sizeof(eccurves_all);
+ }
}
}
(s, !(s->options & SSL_OP_CIPHER_SERVER_PREFERENCE), &pref,
&num_pref))
return nmatch == -1 ? 0 : NID_undef;
+
+ /*
+ * If the client didn't send the elliptic_curves extension all of them
+ * are allowed.
+ */
+ if (num_supp == 0 && (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE) != 0) {
+ supp = eccurves_all;
+ num_supp = sizeof(eccurves_all) / 2;
+ } else if (num_pref == 0 &&
+ (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE) == 0) {
+ pref = eccurves_all;
+ num_pref = sizeof(eccurves_all) / 2;
+ }
+
k = 0;
for (i = 0; i < num_pref; i++, pref += 2) {
const unsigned char *tsupp = supp;
#endif /* OPENSSL_NO_EC */
-#ifndef OPENSSL_NO_TLSEXT
-
/*
* List of supported signature algorithms and hashes. Should make this
* customisable at some point, for now include everything we support.
*/
-# ifdef OPENSSL_NO_RSA
-# define tlsext_sigalg_rsa(md) /* */
-# else
-# define tlsext_sigalg_rsa(md) md, TLSEXT_signature_rsa,
-# endif
+#ifdef OPENSSL_NO_RSA
+# define tlsext_sigalg_rsa(md) /* */
+#else
+# define tlsext_sigalg_rsa(md) md, TLSEXT_signature_rsa,
+#endif
-# ifdef OPENSSL_NO_DSA
-# define tlsext_sigalg_dsa(md) /* */
-# else
-# define tlsext_sigalg_dsa(md) md, TLSEXT_signature_dsa,
-# endif
+#ifdef OPENSSL_NO_DSA
+# define tlsext_sigalg_dsa(md) /* */
+#else
+# define tlsext_sigalg_dsa(md) md, TLSEXT_signature_dsa,
+#endif
-# ifdef OPENSSL_NO_EC
-# define tlsext_sigalg_ecdsa(md) /* */
-# else
-# define tlsext_sigalg_ecdsa(md) md, TLSEXT_signature_ecdsa,
-# endif
+#ifdef OPENSSL_NO_EC
+# define tlsext_sigalg_ecdsa(md) /* */
+#else
+# define tlsext_sigalg_ecdsa(md) md, TLSEXT_signature_ecdsa,
+#endif
-# define tlsext_sigalg(md) \
+#define tlsext_sigalg(md) \
tlsext_sigalg_rsa(md) \
tlsext_sigalg_dsa(md) \
tlsext_sigalg_ecdsa(md)
tlsext_sigalg(TLSEXT_hash_sha1)
};
-# ifndef OPENSSL_NO_EC
+#ifndef OPENSSL_NO_EC
static const unsigned char suiteb_sigalgs[] = {
tlsext_sigalg_ecdsa(TLSEXT_hash_sha256)
tlsext_sigalg_ecdsa(TLSEXT_hash_sha384)
};
-# endif
+#endif
size_t tls12_get_psigalgs(SSL *s, const unsigned char **psigs)
{
/*
* If Suite B mode use Suite B sigalgs only, ignore any other
* preferences.
*/
-# ifndef OPENSSL_NO_EC
+#ifndef OPENSSL_NO_EC
switch (tls1_suiteb(s)) {
case SSL_CERT_FLAG_SUITEB_128_LOS:
*psigs = suiteb_sigalgs;
*psigs = suiteb_sigalgs + 2;
return 2;
}
-# endif
+#endif
/* If server use client authentication sigalgs if not NULL */
if (s->server && s->cert->client_sigalgs) {
*psigs = s->cert->client_sigalgs;
SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG, SSL_R_WRONG_SIGNATURE_TYPE);
return 0;
}
-# ifndef OPENSSL_NO_EC
+#ifndef OPENSSL_NO_EC
if (pkey->type == EVP_PKEY_EC) {
unsigned char curve_id[2], comp_id;
/* Check compression and curve matches extensions */
}
} else if (tls1_suiteb(s))
return 0;
-# endif
+#endif
/* Check signature matches a type we sent */
sent_sigslen = tls12_get_psigalgs(s, &sent_sigs);
/* with PSK there must be client callback set */
if (!s->psk_client_callback) {
s->s3->tmp.mask_a |= SSL_aPSK;
- s->s3->tmp.mask_k |= SSL_kPSK;
+ s->s3->tmp.mask_k |= SSL_PSK;
}
-# endif /* OPENSSL_NO_PSK */
-# ifndef OPENSSL_NO_SRP
+#endif /* OPENSSL_NO_PSK */
+#ifndef OPENSSL_NO_SRP
if (!(s->srp_ctx.srp_Mask & SSL_kSRP)) {
s->s3->tmp.mask_a |= SSL_aSRP;
s->s3->tmp.mask_k |= SSL_kSRP;
}
-# endif
+#endif
}
int ssl_cipher_disabled(SSL *s, const SSL_CIPHER *c, int op)
int extdatalen = 0;
unsigned char *orig = buf;
unsigned char *ret = buf;
-# ifndef OPENSSL_NO_EC
+#ifndef OPENSSL_NO_EC
/* See if we support any ECC ciphersuites */
int using_ecc = 0;
if (s->version >= TLS1_VERSION || SSL_IS_DTLS(s)) {
alg_k = c->algorithm_mkey;
alg_a = c->algorithm_auth;
- if ((alg_k & (SSL_kECDHE | SSL_kECDHr | SSL_kECDHe)
+ if ((alg_k & (SSL_kECDHE | SSL_kECDHr | SSL_kECDHe | SSL_kECDHEPSK)
|| (alg_a & SSL_aECDSA))) {
using_ecc = 1;
break;
}
}
}
-# endif
+#endif
ret += 2;
memcpy(ret, s->tlsext_hostname, size_str);
ret += size_str;
}
-# ifndef OPENSSL_NO_SRP
+#ifndef OPENSSL_NO_SRP
/* Add SRP username if there is one */
if (s->srp_ctx.login != NULL) { /* Add TLS extension SRP username to the
* Client Hello message */
memcpy(ret, s->srp_ctx.login, login_len);
ret += login_len;
}
-# endif
+#endif
-# ifndef OPENSSL_NO_EC
+#ifndef OPENSSL_NO_EC
if (using_ecc) {
/*
* Add TLS extension ECPointFormats to the ClientHello message
s2n(curves_list_len, ret);
ret += curves_list_len;
}
-# endif /* OPENSSL_NO_EC */
+#endif /* OPENSSL_NO_EC */
if (tls_use_ticket(s)) {
int ticklen;
if (extlen > 0)
i2d_X509_EXTENSIONS(s->tlsext_ocsp_exts, &ret);
}
-# ifndef OPENSSL_NO_HEARTBEATS
+#ifndef OPENSSL_NO_HEARTBEATS
/* Add Heartbeat extension */
if ((limit - ret - 4 - 1) < 0)
return NULL;
*(ret++) = SSL_TLSEXT_HB_DONT_SEND_REQUESTS;
else
*(ret++) = SSL_TLSEXT_HB_ENABLED;
-# endif
+#endif
-# ifndef OPENSSL_NO_NEXTPROTONEG
+#ifndef OPENSSL_NO_NEXTPROTONEG
if (s->ctx->next_proto_select_cb && !s->s3->tmp.finish_md_len) {
/*
* The client advertises an emtpy extension to indicate its support
s2n(TLSEXT_TYPE_next_proto_neg, ret);
s2n(0, ret);
}
-# endif
+#endif
if (s->alpn_client_proto_list && !s->s3->tmp.finish_md_len) {
if ((size_t)(limit - ret) < 6 + s->alpn_client_proto_list_len)
memcpy(ret, s->alpn_client_proto_list, s->alpn_client_proto_list_len);
ret += s->alpn_client_proto_list_len;
}
-# ifndef OPENSSL_NO_SRTP
+#ifndef OPENSSL_NO_SRTP
if (SSL_IS_DTLS(s) && SSL_get_srtp_profiles(s)) {
int el;
}
ret += el;
}
-# endif
+#endif
custom_ext_init(&s->cert->cli_ext);
/* Add custom TLS Extensions to ClientHello */
if (!custom_ext_add(s, 0, &ret, limit, al))
return NULL;
-# ifdef TLSEXT_TYPE_encrypt_then_mac
+#ifdef TLSEXT_TYPE_encrypt_then_mac
s2n(TLSEXT_TYPE_encrypt_then_mac, ret);
s2n(0, ret);
-# endif
+#endif
s2n(TLSEXT_TYPE_extended_master_secret, ret);
s2n(0, ret);
int extdatalen = 0;
unsigned char *orig = buf;
unsigned char *ret = buf;
-# ifndef OPENSSL_NO_NEXTPROTONEG
+#ifndef OPENSSL_NO_NEXTPROTONEG
int next_proto_neg_seen;
-# endif
-# ifndef OPENSSL_NO_EC
+#endif
+#ifndef OPENSSL_NO_EC
unsigned long alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
unsigned long alg_a = s->s3->tmp.new_cipher->algorithm_auth;
int using_ecc = (alg_k & (SSL_kECDHE | SSL_kECDHr | SSL_kECDHe))
|| (alg_a & SSL_aECDSA);
using_ecc = using_ecc && (s->session->tlsext_ecpointformatlist != NULL);
-# endif
+#endif
ret += 2;
if (ret >= limit)
s2n(TLSEXT_TYPE_server_name, ret);
s2n(0, ret);
}
-# ifndef OPENSSL_NO_EC
+#ifndef OPENSSL_NO_EC
if (using_ecc) {
const unsigned char *plist;
size_t plistlen;
* Currently the server should not respond with a SupportedCurves
* extension
*/
-# endif /* OPENSSL_NO_EC */
+#endif /* OPENSSL_NO_EC */
if (s->tlsext_ticket_expected && tls_use_ticket(s)) {
if ((long)(limit - ret - 4) < 0)
s2n(0, ret);
}
-# ifndef OPENSSL_NO_SRTP
+#ifndef OPENSSL_NO_SRTP
if (SSL_IS_DTLS(s) && s->srtp_profile) {
int el;
}
ret += el;
}
-# endif
+#endif
if (((s->s3->tmp.new_cipher->id & 0xFFFF) == 0x80
|| (s->s3->tmp.new_cipher->id & 0xFFFF) == 0x81)
ret += 36;
}
-# ifndef OPENSSL_NO_HEARTBEATS
+#ifndef OPENSSL_NO_HEARTBEATS
/* Add Heartbeat extension if we've received one */
if (s->tlsext_heartbeat & SSL_TLSEXT_HB_ENABLED) {
if ((limit - ret - 4 - 1) < 0)
*(ret++) = SSL_TLSEXT_HB_ENABLED;
}
-# endif
+#endif
-# ifndef OPENSSL_NO_NEXTPROTONEG
+#ifndef OPENSSL_NO_NEXTPROTONEG
next_proto_neg_seen = s->s3->next_proto_neg_seen;
s->s3->next_proto_neg_seen = 0;
if (next_proto_neg_seen && s->ctx->next_protos_advertised_cb) {
s->s3->next_proto_neg_seen = 1;
}
}
-# endif
+#endif
if (!custom_ext_add(s, 1, &ret, limit, al))
return NULL;
-# ifdef TLSEXT_TYPE_encrypt_then_mac
+#ifdef TLSEXT_TYPE_encrypt_then_mac
if (s->s3->flags & TLS1_FLAGS_ENCRYPT_THEN_MAC) {
/*
* Don't use encrypt_then_mac if AEAD or RC4 might want to disable
s2n(0, ret);
}
}
-# endif
+#endif
if (!s->hit && s->session->flags & SSL_SESS_FLAG_EXTMS) {
s2n(TLSEXT_TYPE_extended_master_secret, ret);
s2n(0, ret);
* alert value to send in the event of a non-zero return. returns: 0 on
* success.
*/
-static int tls1_alpn_handle_client_hello(SSL *s, const unsigned char *data,
- unsigned data_len, int *al)
+static int tls1_alpn_handle_client_hello(SSL *s, PACKET *pkt, int *al)
{
- unsigned i;
- unsigned proto_len;
+ unsigned int data_len;
+ unsigned int proto_len;
const unsigned char *selected;
+ unsigned char *data;
unsigned char selected_len;
int r;
if (s->ctx->alpn_select_cb == NULL)
return 0;
- if (data_len < 2)
- goto parse_error;
-
/*
* data should contain a uint16 length followed by a series of 8-bit,
* length-prefixed strings.
*/
- i = ((unsigned)data[0]) << 8 | ((unsigned)data[1]);
- data_len -= 2;
- data += 2;
- if (data_len != i)
+ if (!PACKET_get_net_2(pkt, &data_len)
+ || PACKET_remaining(pkt) != data_len
+ || !PACKET_peek_bytes(pkt, &data, data_len))
goto parse_error;
- if (data_len < 2)
- goto parse_error;
-
- for (i = 0; i < data_len;) {
- proto_len = data[i];
- i++;
-
- if (proto_len == 0)
+ do {
+ if (!PACKET_get_1(pkt, &proto_len)
+ || proto_len == 0
+ || !PACKET_forward(pkt, proto_len))
goto parse_error;
-
- if (i + proto_len < i || i + proto_len > data_len)
- goto parse_error;
-
- i += proto_len;
- }
+ } while (PACKET_remaining(pkt));
r = s->ctx->alpn_select_cb(s, &selected, &selected_len, data, data_len,
s->ctx->alpn_select_cb_arg);
return -1;
}
-# ifndef OPENSSL_NO_EC
+#ifndef OPENSSL_NO_EC
/*-
* ssl_check_for_safari attempts to fingerprint Safari using OS X
* SecureTransport using the TLS extension block in |d|, of length |n|.
* Sadly we cannot differentiate 10.6, 10.7 and 10.8.4 (which work), from
* 10.8..10.8.3 (which don't work).
*/
-static void ssl_check_for_safari(SSL *s, const unsigned char *data,
- const unsigned char *d, int n)
+static void ssl_check_for_safari(SSL *s, PACKET *pkt)
{
- unsigned short type, size;
+ unsigned int type, size;
+ unsigned char *eblock1, *eblock2;
+
static const unsigned char kSafariExtensionsBlock[] = {
0x00, 0x0a, /* elliptic_curves extension */
0x00, 0x08, /* 8 bytes */
0x02, 0x03, /* SHA-1/ECDSA */
};
- if (data >= (d + n - 2))
- return;
- data += 2;
-
- if (data > (d + n - 4))
+ if (!PACKET_forward(pkt, 2)
+ || !PACKET_get_net_2(pkt, &type)
+ || !PACKET_get_net_2(pkt, &size)
+ || !PACKET_forward(pkt, size))
return;
- n2s(data, type);
- n2s(data, size);
if (type != TLSEXT_TYPE_server_name)
return;
- if (data + size > d + n)
- return;
- data += size;
-
if (TLS1_get_client_version(s) >= TLS1_2_VERSION) {
const size_t len1 = sizeof(kSafariExtensionsBlock);
const size_t len2 = sizeof(kSafariTLS12ExtensionsBlock);
- if (data + len1 + len2 != d + n)
+ if (!PACKET_get_bytes(pkt, &eblock1, len1)
+ || !PACKET_get_bytes(pkt, &eblock2, len2)
+ || PACKET_remaining(pkt))
return;
- if (memcmp(data, kSafariExtensionsBlock, len1) != 0)
+ if (memcmp(eblock1, kSafariExtensionsBlock, len1) != 0)
return;
- if (memcmp(data + len1, kSafariTLS12ExtensionsBlock, len2) != 0)
+ if (memcmp(eblock2, kSafariTLS12ExtensionsBlock, len2) != 0)
return;
} else {
const size_t len = sizeof(kSafariExtensionsBlock);
- if (data + len != d + n)
+ if (!PACKET_get_bytes(pkt, &eblock1, len)
+ || PACKET_remaining(pkt))
return;
- if (memcmp(data, kSafariExtensionsBlock, len) != 0)
+ if (memcmp(eblock1, kSafariExtensionsBlock, len) != 0)
return;
}
s->s3->is_probably_safari = 1;
}
-# endif /* !OPENSSL_NO_EC */
+#endif /* !OPENSSL_NO_EC */
-static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p,
- unsigned char *d, int n, int *al)
+static int ssl_scan_clienthello_tlsext(SSL *s, PACKET *pkt, int *al)
{
- unsigned short type;
- unsigned short size;
- unsigned short len;
- unsigned char *data = *p;
+ unsigned int type;
+ unsigned int size;
+ unsigned int len;
+ unsigned char *data;
int renegotiate_seen = 0;
s->servername_done = 0;
s->tlsext_status_type = -1;
-# ifndef OPENSSL_NO_NEXTPROTONEG
+#ifndef OPENSSL_NO_NEXTPROTONEG
s->s3->next_proto_neg_seen = 0;
-# endif
+#endif
OPENSSL_free(s->s3->alpn_selected);
s->s3->alpn_selected = NULL;
-# ifndef OPENSSL_NO_HEARTBEATS
+#ifndef OPENSSL_NO_HEARTBEATS
s->tlsext_heartbeat &= ~(SSL_TLSEXT_HB_ENABLED |
SSL_TLSEXT_HB_DONT_SEND_REQUESTS);
-# endif
+#endif
-# ifndef OPENSSL_NO_EC
+#ifndef OPENSSL_NO_EC
if (s->options & SSL_OP_SAFARI_ECDHE_ECDSA_BUG)
- ssl_check_for_safari(s, data, d, n);
-# endif /* !OPENSSL_NO_EC */
+ ssl_check_for_safari(s, pkt);
+# endif /* !OPENSSL_NO_EC */
/* Clear any signature algorithms extension received */
OPENSSL_free(s->s3->tmp.peer_sigalgs);
s->s3->tmp.peer_sigalgs = NULL;
-# ifdef TLSEXT_TYPE_encrypt_then_mac
+#ifdef TLSEXT_TYPE_encrypt_then_mac
s->s3->flags &= ~TLS1_FLAGS_ENCRYPT_THEN_MAC;
-# endif
+#endif
-# ifndef OPENSSL_NO_SRP
+#ifndef OPENSSL_NO_SRP
OPENSSL_free(s->srp_ctx.login);
s->srp_ctx.login = NULL;
-# endif
+#endif
s->srtp_profile = NULL;
- if (data >= (d + n - 2))
+ if (PACKET_remaining(pkt) == 0)
goto ri_check;
- n2s(data, len);
- if (data > (d + n - len))
- goto ri_check;
+ if (!PACKET_get_net_2(pkt, &len))
+ goto err;
- while (data <= (d + n - 4)) {
- n2s(data, type);
- n2s(data, size);
+ while (PACKET_get_net_2(pkt, &type) && PACKET_get_net_2(pkt, &size)) {
+ PACKET subpkt;
+
+ if (!PACKET_peek_bytes(pkt, &data, size))
+ goto err;
- if (data + size > (d + n))
- goto ri_check;
if (s->tlsext_debug_cb)
s->tlsext_debug_cb(s, 0, type, data, size, s->tlsext_debug_arg);
+
+ if (!PACKET_get_sub_packet(pkt, &subpkt, size))
+ goto err;
+
if (type == TLSEXT_TYPE_renegotiate) {
- if (!ssl_parse_clienthello_renegotiate_ext(s, data, size, al))
+ if (!ssl_parse_clienthello_renegotiate_ext(s, &subpkt, al))
return 0;
renegotiate_seen = 1;
} else if (s->version == SSL3_VERSION) {
else if (type == TLSEXT_TYPE_server_name) {
unsigned char *sdata;
- int servname_type;
- int dsize;
+ unsigned int servname_type;
+ unsigned int dsize;
+ PACKET ssubpkt;
- if (size < 2) {
- *al = SSL_AD_DECODE_ERROR;
- return 0;
- }
- n2s(data, dsize);
- size -= 2;
- if (dsize > size) {
- *al = SSL_AD_DECODE_ERROR;
- return 0;
- }
+ if (!PACKET_get_net_2(&subpkt, &dsize)
+ || !PACKET_get_sub_packet(&subpkt, &ssubpkt, dsize))
+ goto err;
- sdata = data;
- while (dsize > 3) {
- servname_type = *(sdata++);
- n2s(sdata, len);
- dsize -= 3;
+ while (PACKET_remaining(&ssubpkt) > 3) {
+ if (!PACKET_get_1(&ssubpkt, &servname_type)
+ || !PACKET_get_net_2(&ssubpkt, &len)
+ || PACKET_remaining(&ssubpkt) < len)
+ goto err;
- if (len > dsize) {
- *al = SSL_AD_DECODE_ERROR;
- return 0;
- }
if (s->servername_done == 0)
switch (servname_type) {
case TLSEXT_NAMETYPE_host_name:
if (!s->hit) {
- if (s->session->tlsext_hostname) {
- *al = SSL_AD_DECODE_ERROR;
- return 0;
- }
+ if (s->session->tlsext_hostname)
+ goto err;
+
if (len > TLSEXT_MAXLEN_host_name) {
*al = TLS1_AD_UNRECOGNIZED_NAME;
return 0;
*al = TLS1_AD_INTERNAL_ERROR;
return 0;
}
- memcpy(s->session->tlsext_hostname, sdata, len);
+ if (!PACKET_copy_bytes(&ssubpkt,
+ (unsigned char *)s->session
+ ->tlsext_hostname,
+ len)) {
+ *al = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
s->session->tlsext_hostname[len] = '\0';
if (strlen(s->session->tlsext_hostname) != len) {
OPENSSL_free(s->session->tlsext_hostname);
}
s->servername_done = 1;
- } else
+ } else {
+ if (!PACKET_get_bytes(&ssubpkt, &sdata, len)) {
+ *al = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
s->servername_done = s->session->tlsext_hostname
&& strlen(s->session->tlsext_hostname) == len
&& strncmp(s->session->tlsext_hostname,
(char *)sdata, len) == 0;
+ }
break;
default:
break;
}
-
- dsize -= len;
- }
- if (dsize != 0) {
- *al = SSL_AD_DECODE_ERROR;
- return 0;
}
+ /* We shouldn't have any bytes left */
+ if (PACKET_remaining(&ssubpkt) != 0)
+ goto err;
}
-# ifndef OPENSSL_NO_SRP
+#ifndef OPENSSL_NO_SRP
else if (type == TLSEXT_TYPE_srp) {
- if (size <= 0 || ((len = data[0])) != (size - 1)) {
- *al = SSL_AD_DECODE_ERROR;
- return 0;
- }
- if (s->srp_ctx.login != NULL) {
- *al = SSL_AD_DECODE_ERROR;
- return 0;
- }
+ if (!PACKET_get_1(&subpkt, &len)
+ || s->srp_ctx.login != NULL)
+ goto err;
+
if ((s->srp_ctx.login = OPENSSL_malloc(len + 1)) == NULL)
return -1;
- memcpy(s->srp_ctx.login, &data[1], len);
+ if (!PACKET_copy_bytes(&subpkt, (unsigned char *)s->srp_ctx.login,
+ len))
+ goto err;
s->srp_ctx.login[len] = '\0';
- if (strlen(s->srp_ctx.login) != len) {
- *al = SSL_AD_DECODE_ERROR;
- return 0;
- }
+ if (strlen(s->srp_ctx.login) != len
+ || PACKET_remaining(&subpkt))
+ goto err;
}
-# endif
+#endif
-# ifndef OPENSSL_NO_EC
+#ifndef OPENSSL_NO_EC
else if (type == TLSEXT_TYPE_ec_point_formats) {
- unsigned char *sdata = data;
- int ecpointformatlist_length = *(sdata++);
+ unsigned int ecpointformatlist_length;
+
+ if (!PACKET_get_1(&subpkt, &ecpointformatlist_length)
+ || ecpointformatlist_length == 0)
+ goto err;
- if (ecpointformatlist_length != size - 1 ||
- ecpointformatlist_length < 1) {
- *al = TLS1_AD_DECODE_ERROR;
- return 0;
- }
if (!s->hit) {
OPENSSL_free(s->session->tlsext_ecpointformatlist);
s->session->tlsext_ecpointformatlist = NULL;
}
s->session->tlsext_ecpointformatlist_length =
ecpointformatlist_length;
- memcpy(s->session->tlsext_ecpointformatlist, sdata,
- ecpointformatlist_length);
+ if (!PACKET_copy_bytes(&subpkt,
+ s->session->tlsext_ecpointformatlist,
+ ecpointformatlist_length))
+ goto err;
+ } else if (!PACKET_forward(&subpkt, ecpointformatlist_length)) {
+ goto err;
}
- } else if (type == TLSEXT_TYPE_elliptic_curves) {
- unsigned char *sdata = data;
- int ellipticcurvelist_length = (*(sdata++) << 8);
- ellipticcurvelist_length += (*(sdata++));
-
- if (ellipticcurvelist_length != size - 2 ||
- ellipticcurvelist_length < 1 ||
- /* Each NamedCurve is 2 bytes. */
- ellipticcurvelist_length & 1) {
+ /* We should have consumed all the bytes by now */
+ if (PACKET_remaining(&subpkt)) {
*al = TLS1_AD_DECODE_ERROR;
return 0;
}
+ } else if (type == TLSEXT_TYPE_elliptic_curves) {
+ unsigned int ellipticcurvelist_length;
+
+ /* Each NamedCurve is 2 bytes and we must have at least 1 */
+ if (!PACKET_get_net_2(&subpkt, &ellipticcurvelist_length)
+ || ellipticcurvelist_length == 0
+ || (ellipticcurvelist_length & 1) != 0)
+ goto err;
+
if (!s->hit) {
- if (s->session->tlsext_ellipticcurvelist) {
- *al = TLS1_AD_DECODE_ERROR;
- return 0;
- }
+ if (s->session->tlsext_ellipticcurvelist)
+ goto err;
+
s->session->tlsext_ellipticcurvelist_length = 0;
if ((s->session->tlsext_ellipticcurvelist =
OPENSSL_malloc(ellipticcurvelist_length)) == NULL) {
}
s->session->tlsext_ellipticcurvelist_length =
ellipticcurvelist_length;
- memcpy(s->session->tlsext_ellipticcurvelist, sdata,
- ellipticcurvelist_length);
+ if (!PACKET_copy_bytes(&subpkt,
+ s->session->tlsext_ellipticcurvelist,
+ ellipticcurvelist_length))
+ goto err;
+ } else if (!PACKET_forward(&subpkt, ellipticcurvelist_length)) {
+ goto err;
+ }
+ /* We should have consumed all the bytes by now */
+ if (PACKET_remaining(&subpkt)) {
+ goto err;
}
}
-# endif /* OPENSSL_NO_EC */
+#endif /* OPENSSL_NO_EC */
else if (type == TLSEXT_TYPE_session_ticket) {
- if (s->tls_session_ticket_ext_cb &&
- !s->tls_session_ticket_ext_cb(s, data, size,
- s->tls_session_ticket_ext_cb_arg))
- {
+ if (!PACKET_forward(&subpkt, size)
+ || (s->tls_session_ticket_ext_cb &&
+ !s->tls_session_ticket_ext_cb(s, data, size,
+ s->tls_session_ticket_ext_cb_arg))) {
*al = TLS1_AD_INTERNAL_ERROR;
return 0;
}
} else if (type == TLSEXT_TYPE_signature_algorithms) {
- int dsize;
- if (s->s3->tmp.peer_sigalgs || size < 2) {
- *al = SSL_AD_DECODE_ERROR;
- return 0;
- }
- n2s(data, dsize);
- size -= 2;
- if (dsize != size || dsize & 1 || !dsize) {
- *al = SSL_AD_DECODE_ERROR;
- return 0;
- }
- if (!tls1_save_sigalgs(s, data, dsize)) {
- *al = SSL_AD_DECODE_ERROR;
- return 0;
+ unsigned int dsize;
+
+ if (s->s3->tmp.peer_sigalgs
+ || !PACKET_get_net_2(&subpkt, &dsize)
+ || (dsize & 1) != 0
+ || (dsize == 0)
+ || !PACKET_get_bytes(&subpkt, &data, dsize)
+ || PACKET_remaining(&subpkt) != 0
+ || !tls1_save_sigalgs(s, data, dsize)) {
+ goto err;
}
} else if (type == TLSEXT_TYPE_status_request) {
+ PACKET ssubpkt;
- if (size < 5) {
- *al = SSL_AD_DECODE_ERROR;
- return 0;
- }
+ if (!PACKET_get_1(&subpkt,
+ (unsigned int *)&s->tlsext_status_type))
+ goto err;
- s->tlsext_status_type = *data++;
- size--;
if (s->tlsext_status_type == TLSEXT_STATUSTYPE_ocsp) {
const unsigned char *sdata;
- int dsize;
+ unsigned int dsize;
/* Read in responder_id_list */
- n2s(data, dsize);
- size -= 2;
- if (dsize > size) {
- *al = SSL_AD_DECODE_ERROR;
- return 0;
- }
- while (dsize > 0) {
+ if (!PACKET_get_net_2(&subpkt, &dsize)
+ || !PACKET_get_sub_packet(&subpkt, &ssubpkt, dsize))
+ goto err;
+
+ while (PACKET_remaining(&ssubpkt)) {
OCSP_RESPID *id;
- int idsize;
- if (dsize < 4) {
- *al = SSL_AD_DECODE_ERROR;
- return 0;
- }
- n2s(data, idsize);
- dsize -= 2 + idsize;
- size -= 2 + idsize;
- if (dsize < 0) {
- *al = SSL_AD_DECODE_ERROR;
- return 0;
+ unsigned int idsize;
+
+ if (PACKET_remaining(&ssubpkt) < 4
+ || !PACKET_get_net_2(&ssubpkt, &idsize)
+ || !PACKET_get_bytes(&ssubpkt, &data, idsize)) {
+ goto err;
}
sdata = data;
data += idsize;
id = d2i_OCSP_RESPID(NULL, &sdata, idsize);
- if (!id) {
- *al = SSL_AD_DECODE_ERROR;
- return 0;
- }
+ if (!id)
+ goto err;
if (data != sdata) {
OCSP_RESPID_free(id);
- *al = SSL_AD_DECODE_ERROR;
- return 0;
+ goto err;
}
if (!s->tlsext_ocsp_ids
&& !(s->tlsext_ocsp_ids =
}
/* Read in request_extensions */
- if (size < 2) {
- *al = SSL_AD_DECODE_ERROR;
- return 0;
- }
- n2s(data, dsize);
- size -= 2;
- if (dsize != size) {
- *al = SSL_AD_DECODE_ERROR;
- return 0;
+ if (!PACKET_get_net_2(&subpkt, &dsize)
+ || !PACKET_get_bytes(&subpkt, &data, dsize)
+ || PACKET_remaining(&subpkt)) {
+ goto err;
}
sdata = data;
if (dsize > 0) {
X509_EXTENSION_free);
s->tlsext_ocsp_exts =
d2i_X509_EXTENSIONS(NULL, &sdata, dsize);
- if (!s->tlsext_ocsp_exts || (data + dsize != sdata)) {
- *al = SSL_AD_DECODE_ERROR;
- return 0;
- }
+ if (!s->tlsext_ocsp_exts || (data + dsize != sdata))
+ goto err;
}
}
/*
else
s->tlsext_status_type = -1;
}
-# ifndef OPENSSL_NO_HEARTBEATS
+#ifndef OPENSSL_NO_HEARTBEATS
else if (type == TLSEXT_TYPE_heartbeat) {
- switch (data[0]) {
+ unsigned int hbtype;
+
+ if (!PACKET_get_1(&subpkt, &hbtype)
+ || PACKET_remaining(&subpkt)) {
+ *al = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+ switch (hbtype) {
case 0x01: /* Client allows us to send HB requests */
s->tlsext_heartbeat |= SSL_TLSEXT_HB_ENABLED;
break;
return 0;
}
}
-# endif
-# ifndef OPENSSL_NO_NEXTPROTONEG
+#endif
+#ifndef OPENSSL_NO_NEXTPROTONEG
else if (type == TLSEXT_TYPE_next_proto_neg &&
s->s3->tmp.finish_md_len == 0 &&
s->s3->alpn_selected == NULL) {
*/
s->s3->next_proto_neg_seen = 1;
}
-# endif
+#endif
else if (type == TLSEXT_TYPE_application_layer_protocol_negotiation &&
s->ctx->alpn_select_cb && s->s3->tmp.finish_md_len == 0) {
- if (tls1_alpn_handle_client_hello(s, data, size, al) != 0)
+ if (tls1_alpn_handle_client_hello(s, &subpkt, al) != 0)
return 0;
-# ifndef OPENSSL_NO_NEXTPROTONEG
+#ifndef OPENSSL_NO_NEXTPROTONEG
/* ALPN takes precedence over NPN. */
s->s3->next_proto_neg_seen = 0;
-# endif
+#endif
}
/* session ticket processed earlier */
-# ifndef OPENSSL_NO_SRTP
+#ifndef OPENSSL_NO_SRTP
else if (SSL_IS_DTLS(s) && SSL_get_srtp_profiles(s)
&& type == TLSEXT_TYPE_use_srtp) {
- if (ssl_parse_clienthello_use_srtp_ext(s, data, size, al))
+ if (ssl_parse_clienthello_use_srtp_ext(s, &subpkt, al))
return 0;
}
-# endif
-# ifdef TLSEXT_TYPE_encrypt_then_mac
+#endif
+#ifdef TLSEXT_TYPE_encrypt_then_mac
else if (type == TLSEXT_TYPE_encrypt_then_mac)
s->s3->flags |= TLS1_FLAGS_ENCRYPT_THEN_MAC;
-# endif
+#endif
else if (type == TLSEXT_TYPE_extended_master_secret) {
if (!s->hit)
s->session->flags |= SSL_SESS_FLAG_EXTMS;
if (custom_ext_parse(s, 1, type, data, size, al) <= 0)
return 0;
}
-
- data += size;
}
- *p = data;
+ /* Spurious data on the end */
+ if (PACKET_remaining(pkt) != 0)
+ goto err;
ri_check:
}
return 1;
+err:
+ *al = SSL_AD_DECODE_ERROR;
+ return 0;
}
-int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d,
- int n)
+int ssl_parse_clienthello_tlsext(SSL *s, PACKET *pkt)
{
int al = -1;
custom_ext_init(&s->cert->srv_ext);
- if (ssl_scan_clienthello_tlsext(s, p, d, n, &al) <= 0) {
+ if (ssl_scan_clienthello_tlsext(s, pkt, &al) <= 0) {
ssl3_send_alert(s, SSL3_AL_FATAL, al);
return 0;
}
return 1;
}
-# ifndef OPENSSL_NO_NEXTPROTONEG
+#ifndef OPENSSL_NO_NEXTPROTONEG
/*
* 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.
*/
-static char ssl_next_proto_validate(unsigned char *d, unsigned len)
+static char ssl_next_proto_validate(PACKET *pkt)
{
- unsigned int off = 0;
+ unsigned int len;
- while (off < len) {
- if (d[off] == 0)
+ while (PACKET_remaining(pkt)) {
+ if (!PACKET_get_1(pkt, &len)
+ || !PACKET_forward(pkt, len))
return 0;
- off += d[off];
- off++;
}
- return off == len;
+ return 1;
}
-# endif
+#endif
-static int ssl_scan_serverhello_tlsext(SSL *s, unsigned char **p,
- unsigned char *d, int n, int *al)
+static int ssl_scan_serverhello_tlsext(SSL *s, PACKET *pkt, int *al)
{
- unsigned short length;
- unsigned short type;
- unsigned short size;
- unsigned char *data = *p;
+ unsigned int length, type, size;
int tlsext_servername = 0;
int renegotiate_seen = 0;
-# ifndef OPENSSL_NO_NEXTPROTONEG
+#ifndef OPENSSL_NO_NEXTPROTONEG
s->s3->next_proto_neg_seen = 0;
-# endif
+#endif
s->tlsext_ticket_expected = 0;
OPENSSL_free(s->s3->alpn_selected);
s->s3->alpn_selected = NULL;
-# ifndef OPENSSL_NO_HEARTBEATS
+#ifndef OPENSSL_NO_HEARTBEATS
s->tlsext_heartbeat &= ~(SSL_TLSEXT_HB_ENABLED |
SSL_TLSEXT_HB_DONT_SEND_REQUESTS);
-# endif
+#endif
-# ifdef TLSEXT_TYPE_encrypt_then_mac
+#ifdef TLSEXT_TYPE_encrypt_then_mac
s->s3->flags &= ~TLS1_FLAGS_ENCRYPT_THEN_MAC;
-# endif
+#endif
- if (data >= (d + n - 2))
+ if (!PACKET_get_net_2(pkt, &length))
goto ri_check;
- n2s(data, length);
- if (data + length != d + n) {
+ if (PACKET_remaining(pkt) != length) {
*al = SSL_AD_DECODE_ERROR;
return 0;
}
- while (data <= (d + n - 4)) {
- n2s(data, type);
- n2s(data, size);
+ while (PACKET_get_net_2(pkt, &type) && PACKET_get_net_2(pkt, &size)) {
+ unsigned char *data;
+ PACKET spkt;
- if (data + size > (d + n))
+ if (!PACKET_get_sub_packet(pkt, &spkt, size)
+ || !PACKET_peek_bytes(&spkt, &data, size))
goto ri_check;
if (s->tlsext_debug_cb)
s->tlsext_debug_cb(s, 1, type, data, size, s->tlsext_debug_arg);
if (type == TLSEXT_TYPE_renegotiate) {
- if (!ssl_parse_serverhello_renegotiate_ext(s, data, size, al))
+ if (!ssl_parse_serverhello_renegotiate_ext(s, &spkt, al))
return 0;
renegotiate_seen = 1;
} else if (s->version == SSL3_VERSION) {
}
tlsext_servername = 1;
}
-# ifndef OPENSSL_NO_EC
+#ifndef OPENSSL_NO_EC
else if (type == TLSEXT_TYPE_ec_point_formats) {
- unsigned char *sdata = data;
- int ecpointformatlist_length = *(sdata++);
-
- if (ecpointformatlist_length != size - 1) {
+ unsigned int ecpointformatlist_length;
+ if (!PACKET_get_1(&spkt, &ecpointformatlist_length)
+ || ecpointformatlist_length != size - 1) {
*al = TLS1_AD_DECODE_ERROR;
return 0;
}
}
s->session->tlsext_ecpointformatlist_length =
ecpointformatlist_length;
- memcpy(s->session->tlsext_ecpointformatlist, sdata,
- ecpointformatlist_length);
+ if (!PACKET_copy_bytes(&spkt,
+ s->session->tlsext_ecpointformatlist,
+ ecpointformatlist_length)) {
+ *al = TLS1_AD_DECODE_ERROR;
+ return 0;
+ }
+
}
}
-# endif /* OPENSSL_NO_EC */
+#endif /* OPENSSL_NO_EC */
else if (type == TLSEXT_TYPE_session_ticket) {
if (s->tls_session_ticket_ext_cb &&
/* Set flag to expect CertificateStatus message */
s->tlsext_status_expected = 1;
}
-# ifndef OPENSSL_NO_NEXTPROTONEG
+#ifndef OPENSSL_NO_NEXTPROTONEG
else if (type == TLSEXT_TYPE_next_proto_neg &&
s->s3->tmp.finish_md_len == 0) {
unsigned char *selected;
unsigned char selected_len;
-
/* We must have requested it. */
if (s->ctx->next_proto_select_cb == NULL) {
*al = TLS1_AD_UNSUPPORTED_EXTENSION;
return 0;
}
/* The data must be valid */
- if (!ssl_next_proto_validate(data, size)) {
+ if (!ssl_next_proto_validate(&spkt)) {
*al = TLS1_AD_DECODE_ERROR;
return 0;
}
s->next_proto_negotiated_len = selected_len;
s->s3->next_proto_neg_seen = 1;
}
-# endif
+#endif
else if (type == TLSEXT_TYPE_application_layer_protocol_negotiation) {
unsigned len;
-
/* We must have requested it. */
if (s->alpn_client_proto_list == NULL) {
*al = TLS1_AD_UNSUPPORTED_EXTENSION;
return 0;
}
- if (size < 4) {
- *al = TLS1_AD_DECODE_ERROR;
- return 0;
- }
/*-
* The extension data consists of:
* uint16 list_length
* uint8 proto_length;
* uint8 proto[proto_length];
*/
- len = data[0];
- len <<= 8;
- len |= data[1];
- if (len != (unsigned)size - 2) {
- *al = TLS1_AD_DECODE_ERROR;
- return 0;
- }
- len = data[2];
- if (len != (unsigned)size - 3) {
+ if (!PACKET_get_net_2(&spkt, &len)
+ || PACKET_remaining(&spkt) != len
+ || !PACKET_get_1(&spkt, &len)
+ || PACKET_remaining(&spkt) != len) {
*al = TLS1_AD_DECODE_ERROR;
return 0;
}
*al = TLS1_AD_INTERNAL_ERROR;
return 0;
}
- memcpy(s->s3->alpn_selected, data + 3, len);
+ if (!PACKET_copy_bytes(&spkt, s->s3->alpn_selected, len)) {
+ *al = TLS1_AD_DECODE_ERROR;
+ return 0;
+ }
s->s3->alpn_selected_len = len;
}
-# ifndef OPENSSL_NO_HEARTBEATS
+#ifndef OPENSSL_NO_HEARTBEATS
else if (type == TLSEXT_TYPE_heartbeat) {
- switch (data[0]) {
+ unsigned int hbtype;
+ if (!PACKET_get_1(&spkt, &hbtype)) {
+ *al = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+ switch (hbtype) {
case 0x01: /* Server allows us to send HB requests */
s->tlsext_heartbeat |= SSL_TLSEXT_HB_ENABLED;
break;
return 0;
}
}
-# endif
-# ifndef OPENSSL_NO_SRTP
+#endif
+#ifndef OPENSSL_NO_SRTP
else if (SSL_IS_DTLS(s) && type == TLSEXT_TYPE_use_srtp) {
- if (ssl_parse_serverhello_use_srtp_ext(s, data, size, al))
+ if (ssl_parse_serverhello_use_srtp_ext(s, &spkt, al))
return 0;
}
-# endif
-# ifdef TLSEXT_TYPE_encrypt_then_mac
+#endif
+#ifdef TLSEXT_TYPE_encrypt_then_mac
else if (type == TLSEXT_TYPE_encrypt_then_mac) {
/* Ignore if inappropriate ciphersuite */
if (s->s3->tmp.new_cipher->algorithm_mac != SSL_AEAD
&& s->s3->tmp.new_cipher->algorithm_enc != SSL_RC4)
s->s3->flags |= TLS1_FLAGS_ENCRYPT_THEN_MAC;
}
-# endif
+#endif
else if (type == TLSEXT_TYPE_extended_master_secret) {
if (!s->hit)
s->session->flags |= SSL_SESS_FLAG_EXTMS;
*/
else if (custom_ext_parse(s, 0, type, data, size, al) <= 0)
return 0;
-
- data += size;
}
- if (data != d + n) {
+ if (PACKET_remaining(pkt) != 0) {
*al = SSL_AD_DECODE_ERROR;
return 0;
}
}
}
- *p = data;
-
ri_check:
/*
int ret = SSL_TLSEXT_ERR_NOACK;
int al = SSL_AD_UNRECOGNIZED_NAME;
-# ifndef OPENSSL_NO_EC
+#ifndef OPENSSL_NO_EC
/*
* The handling of the ECPointFormats extension is done elsewhere, namely
* in ssl3_choose_cipher in s3_lib.c.
* The handling of the EllipticCurves extension is done elsewhere, namely
* in ssl3_choose_cipher in s3_lib.c.
*/
-# endif
+#endif
if (s->ctx != NULL && s->ctx->tlsext_servername_callback != 0)
ret =
int ret = SSL_TLSEXT_ERR_NOACK;
int al = SSL_AD_UNRECOGNIZED_NAME;
-# ifndef OPENSSL_NO_EC
+#ifndef OPENSSL_NO_EC
/*
* If we are client and using an elliptic curve cryptography cipher
* suite, then if server returns an EC point formats lists extension it
}
}
ret = SSL_TLSEXT_ERR_OK;
-# endif /* OPENSSL_NO_EC */
+#endif /* OPENSSL_NO_EC */
if (s->ctx != NULL && s->ctx->tlsext_servername_callback != 0)
ret =
}
}
-int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char *d,
- int n)
+int ssl_parse_serverhello_tlsext(SSL *s, PACKET *pkt)
{
int al = -1;
if (s->version < SSL3_VERSION)
return 1;
- if (ssl_scan_serverhello_tlsext(s, p, d, n, &al) <= 0) {
+ if (ssl_scan_serverhello_tlsext(s, pkt, &al) <= 0) {
ssl3_send_alert(s, SSL3_AL_FATAL, al);
return 0;
}
* 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, PACKET *pkt, unsigned char *session_id,
+ int len, SSL_SESSION **ret)
{
- /* Point after session ID in client hello */
- const unsigned char *p = session_id + len;
- unsigned short i;
+ unsigned int i;
+ size_t bookmark = 0;
+ int retv = -1;
*ret = NULL;
s->tlsext_ticket_expected = 0;
*/
if (!tls_use_ticket(s))
return 0;
- if ((s->version <= SSL3_VERSION) || !limit)
+ if ((s->version <= SSL3_VERSION))
return 0;
- if (p >= limit)
+
+ if (!PACKET_get_bookmark(pkt, &bookmark)) {
return -1;
+ }
+
/* Skip past DTLS cookie */
if (SSL_IS_DTLS(s)) {
- i = *(p++);
- p += i;
- if (p >= limit)
- return -1;
+ if (!PACKET_get_1(pkt, &i)
+ || !PACKET_forward(pkt, i)) {
+ retv = -1;
+ goto end;
+ }
}
- /* 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;
+ /* Skip past cipher list and compression algorithm list */
+ if (!PACKET_get_net_2(pkt, &i)
+ || !PACKET_forward(pkt, i)
+ || !PACKET_get_1(pkt, &i)
+ || !PACKET_forward(pkt, i)) {
+ retv = -1;
+ goto end;
+ }
+
/* Now at start of extensions */
- if ((p + 2) >= limit)
- return 0;
- n2s(p, i);
- while ((p + 4) <= limit) {
- unsigned short type, size;
- n2s(p, type);
- n2s(p, size);
- if (p + size > limit)
- return 0;
+ if (!PACKET_get_net_2(pkt, &i)) {
+ retv = 0;
+ goto end;
+ }
+ while (PACKET_remaining (pkt) >= 4) {
+ unsigned int type, size;
+
+ if (!PACKET_get_net_2(pkt, &type)
+ || !PACKET_get_net_2(pkt, &size)) {
+ /* Shouldn't ever happen */
+ retv = -1;
+ goto end;
+ }
+ if (PACKET_remaining(pkt) < size) {
+ retv = 0;
+ goto end;
+ }
if (type == TLSEXT_TYPE_session_ticket) {
int r;
+ unsigned char *etick;
+
if (size == 0) {
/*
* The client will accept a ticket but doesn't currently have
* one.
*/
s->tlsext_ticket_expected = 1;
- return 1;
+ retv = 1;
+ goto end;
}
if (s->tls_session_secret_cb) {
/*
* abbreviated handshake based on external mechanism to
* calculate the master secret later.
*/
- return 2;
+ retv = 2;
+ goto end;
+ }
+ if (!PACKET_get_bytes(pkt, &etick, size)) {
+ /* Shouldn't ever happen */
+ retv = -1;
+ goto end;
}
- r = tls_decrypt_ticket(s, p, size, session_id, len, ret);
+ r = tls_decrypt_ticket(s, etick, size, session_id, len, ret);
switch (r) {
case 2: /* ticket couldn't be decrypted */
s->tlsext_ticket_expected = 1;
- return 2;
+ retv = 2;
+ break;
case 3: /* ticket was decrypted */
- return r;
+ retv = r;
+ break;
case 4: /* ticket decrypted but need to renew */
s->tlsext_ticket_expected = 1;
- return 3;
+ retv = 3;
+ break;
default: /* fatal error */
- return -1;
+ retv = -1;
+ break;
+ }
+ goto end;
+ } else {
+ if (!PACKET_forward(pkt, size)) {
+ retv = -1;
+ goto end;
}
}
- p += size;
}
- return 0;
+ retv = 0;
+end:
+ if (!PACKET_goto_bookmark(pkt, bookmark))
+ return -1;
+ return retv;
}
/*-
} tls12_hash_info;
static const tls12_hash_info tls12_md_info[] = {
-# ifdef OPENSSL_NO_MD5
+#ifdef OPENSSL_NO_MD5
{NID_md5, 64, 0},
-# else
+#else
{NID_md5, 64, EVP_md5},
-# endif
+#endif
{NID_sha1, 80, EVP_sha1},
{NID_sha224, 112, EVP_sha224},
{NID_sha256, 128, EVP_sha256},
static int tls12_get_pkey_idx(unsigned char sig_alg)
{
switch (sig_alg) {
-# ifndef OPENSSL_NO_RSA
+#ifndef OPENSSL_NO_RSA
case TLSEXT_signature_rsa:
return SSL_PKEY_RSA_SIGN;
-# endif
-# ifndef OPENSSL_NO_DSA
+#endif
+#ifndef OPENSSL_NO_DSA
case TLSEXT_signature_dsa:
return SSL_PKEY_DSA_SIGN;
-# endif
-# ifndef OPENSSL_NO_EC
+#endif
+#ifndef OPENSSL_NO_EC
case TLSEXT_signature_ecdsa:
return SSL_PKEY_ECC;
-# endif
+#endif
}
return -1;
}
sigalgslen = tls12_get_psigalgs(s, &sigalgs);
for (i = 0; i < sigalgslen; i += 2, sigalgs += 2) {
switch (sigalgs[1]) {
-# ifndef OPENSSL_NO_RSA
+#ifndef OPENSSL_NO_RSA
case TLSEXT_signature_rsa:
if (!have_rsa && tls12_sigalg_allowed(s, op, sigalgs))
have_rsa = 1;
break;
-# endif
-# ifndef OPENSSL_NO_DSA
+#endif
+#ifndef OPENSSL_NO_DSA
case TLSEXT_signature_dsa:
if (!have_dsa && tls12_sigalg_allowed(s, op, sigalgs))
have_dsa = 1;
break;
-# endif
-# ifndef OPENSSL_NO_EC
+#endif
+#ifndef OPENSSL_NO_EC
case TLSEXT_signature_ecdsa:
if (!have_ecdsa && tls12_sigalg_allowed(s, op, sigalgs))
have_ecdsa = 1;
break;
-# endif
+#endif
}
}
if (!have_rsa)
size_t i;
const EVP_MD *md;
const EVP_MD **pmd = s->s3->tmp.md;
- int *pvalid = s->s3->tmp.valid_flags;
+ uint32_t *pvalid = s->s3->tmp.valid_flags;
CERT *c = s->cert;
TLS_SIGALGS *sigptr;
if (!tls1_set_shared_sigalgs(s))
return 0;
-# ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL
+#ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL
if (s->cert->cert_flags & SSL_CERT_FLAG_BROKEN_PROTOCOL) {
/*
* Use first set signature preference to force message digest,
}
}
}
-# endif
+#endif
for (i = 0, sigptr = c->shared_sigalgs;
i < c->shared_sigalgslen; i++, sigptr++) {
* Set any remaining keys to default values. NOTE: if alg is not
* supported it stays as NULL.
*/
-# ifndef OPENSSL_NO_DSA
+#ifndef OPENSSL_NO_DSA
if (pmd[SSL_PKEY_DSA_SIGN] == NULL)
pmd[SSL_PKEY_DSA_SIGN] = EVP_sha1();
-# endif
-# ifndef OPENSSL_NO_RSA
+#endif
+#ifndef OPENSSL_NO_RSA
if (pmd[SSL_PKEY_RSA_SIGN] == NULL) {
pmd[SSL_PKEY_RSA_SIGN] = EVP_sha1();
pmd[SSL_PKEY_RSA_ENC] = EVP_sha1();
}
-# endif
-# ifndef OPENSSL_NO_EC
+#endif
+#ifndef OPENSSL_NO_EC
if (pmd[SSL_PKEY_ECC] == NULL)
pmd[SSL_PKEY_ECC] = EVP_sha1();
-# endif
+#endif
}
return 1;
}
return s->cert->shared_sigalgslen;
}
-# ifndef OPENSSL_NO_HEARTBEATS
+#ifndef OPENSSL_NO_HEARTBEATS
int tls1_process_heartbeat(SSL *s, unsigned char *p, unsigned int length)
{
unsigned char *pl;
OPENSSL_free(buf);
return ret;
}
-# endif
+#endif
-# define MAX_SIGALGLEN (TLSEXT_hash_num * TLSEXT_signature_num * 2)
+#define MAX_SIGALGLEN (TLSEXT_hash_num * TLSEXT_signature_num * 2)
typedef struct {
size_t sigalgcnt;
int sigalgs[MAX_SIGALGLEN];
} sig_cb_st;
+static void get_sigorhash(int *psig, int *phash, const char *str)
+{
+ if (strcmp(str, "RSA") == 0) {
+ *psig = EVP_PKEY_RSA;
+ } else if (strcmp(str, "DSA") == 0) {
+ *psig = EVP_PKEY_DSA;
+ } else if (strcmp(str, "ECDSA") == 0) {
+ *psig = EVP_PKEY_EC;
+ } else {
+ *phash = OBJ_sn2nid(str);
+ if (*phash == NID_undef)
+ *phash = OBJ_ln2nid(str);
+ }
+}
+
static int sig_cb(const char *elem, int len, void *arg)
{
sig_cb_st *sarg = arg;
size_t i;
char etmp[20], *p;
- int sig_alg, hash_alg;
+ int sig_alg = NID_undef, hash_alg = NID_undef;
if (elem == NULL)
return 0;
if (sarg->sigalgcnt == MAX_SIGALGLEN)
if (!*p)
return 0;
- if (strcmp(etmp, "RSA") == 0)
- sig_alg = EVP_PKEY_RSA;
- else if (strcmp(etmp, "DSA") == 0)
- sig_alg = EVP_PKEY_DSA;
- else if (strcmp(etmp, "ECDSA") == 0)
- sig_alg = EVP_PKEY_EC;
- else
- return 0;
+ get_sigorhash(&sig_alg, &hash_alg, etmp);
+ get_sigorhash(&sig_alg, &hash_alg, p);
- hash_alg = OBJ_sn2nid(p);
- if (hash_alg == NID_undef)
- hash_alg = OBJ_ln2nid(p);
- if (hash_alg == NID_undef)
+ if (sig_alg == NID_undef || hash_alg == NID_undef)
return 0;
for (i = 0; i < sarg->sigalgcnt; i += 2) {
/* Flags which need to be set for a certificate when stict mode not set */
-# define CERT_PKEY_VALID_FLAGS \
+#define CERT_PKEY_VALID_FLAGS \
(CERT_PKEY_EE_SIGNATURE|CERT_PKEY_EE_PARAM)
/* Strict mode flags */
-# define CERT_PKEY_STRICT_FLAGS \
+#define CERT_PKEY_STRICT_FLAGS \
(CERT_PKEY_VALID_FLAGS|CERT_PKEY_CA_SIGNATURE|CERT_PKEY_CA_PARAM \
| CERT_PKEY_ISSUER_NAME|CERT_PKEY_CERT_TYPE)
int check_flags = 0, strict_mode;
CERT_PKEY *cpk = NULL;
CERT *c = s->cert;
- int *pvalid;
+ uint32_t *pvalid;
unsigned int suiteb_flags = tls1_suiteb(s);
/* idx == -1 means checking server chains */
if (idx != -1) {
/* If no cert or key, forget it */
if (!x || !pk)
goto end;
-# ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL
+#ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL
/* Allow any certificate to pass test */
if (s->cert->cert_flags & SSL_CERT_FLAG_BROKEN_PROTOCOL) {
rv = CERT_PKEY_STRICT_FLAGS | CERT_PKEY_EXPLICIT_SIGN |
*pvalid = rv;
return rv;
}
-# endif
+#endif
} else {
if (!x || !pk)
return 0;
return tls1_check_chain(s, x, pk, chain, -1);
}
-#endif
#ifndef OPENSSL_NO_DH
DH *ssl_get_auto_dh(SSL *s)
int dh_secbits = 80;
if (s->cert->dh_tmp_auto == 2)
return DH_get_1024_160();
- if (s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL) {
+ if (s->s3->tmp.new_cipher->algorithm_auth & (SSL_aNULL | SSL_aPSK)) {
if (s->s3->tmp.new_cipher->strength_bits == 256)
dh_secbits = 128;
else