return 0;
}
}
-/* Get curves list, if "sess" is set return client curves otherwise
- * preferred list
+/*
+ * Get curves list, if "sess" is set return client curves otherwise
+ * preferred list.
+ * Sets |num_curves| to the number of curves in the list, i.e.,
+ * the length of |pcurves| is 2 * num_curves.
+ * Returns 1 on success and 0 if the client curves list has invalid format.
+ * The latter indicates an internal error: we should not be accepting such
+ * lists in the first place.
+ * TODO(emilia): we should really be storing the curves list in explicitly
+ * parsed form instead. (However, this would affect binary compatibility
+ * so cannot happen in the 1.0.x series.)
*/
-static void tls1_get_curvelist(SSL *s, int sess,
+static int tls1_get_curvelist(SSL *s, int sess,
const unsigned char **pcurves,
- size_t *pcurveslen)
+ size_t *num_curves)
{
+ size_t pcurveslen = 0;
if (sess)
{
*pcurves = s->session->tlsext_ellipticcurvelist;
- *pcurveslen = s->session->tlsext_ellipticcurvelist_length;
- return;
+ pcurveslen = s->session->tlsext_ellipticcurvelist_length;
}
- /* For Suite B mode only include P-256, P-384 */
- switch (tls1_suiteb(s))
+ else
{
- case SSL_CERT_FLAG_SUITEB_128_LOS:
- *pcurves = suiteb_curves;
- *pcurveslen = sizeof(suiteb_curves);
- break;
+ /* For Suite B mode only include P-256, P-384 */
+ switch (tls1_suiteb(s))
+ {
+ case SSL_CERT_FLAG_SUITEB_128_LOS:
+ *pcurves = suiteb_curves;
+ pcurveslen = sizeof(suiteb_curves);
+ break;
- case SSL_CERT_FLAG_SUITEB_128_LOS_ONLY:
- *pcurves = suiteb_curves;
- *pcurveslen = 2;
- break;
+ case SSL_CERT_FLAG_SUITEB_128_LOS_ONLY:
+ *pcurves = suiteb_curves;
+ pcurveslen = 2;
+ break;
- case SSL_CERT_FLAG_SUITEB_192_LOS:
- *pcurves = suiteb_curves + 2;
- *pcurveslen = 2;
- break;
- default:
- *pcurves = s->tlsext_ellipticcurvelist;
- *pcurveslen = s->tlsext_ellipticcurvelist_length;
+ case SSL_CERT_FLAG_SUITEB_192_LOS:
+ *pcurves = suiteb_curves + 2;
+ pcurveslen = 2;
+ break;
+ default:
+ *pcurves = s->tlsext_ellipticcurvelist;
+ pcurveslen = s->tlsext_ellipticcurvelist_length;
+ }
+ if (!*pcurves)
+ {
+ *pcurves = eccurves_default;
+ pcurveslen = sizeof(eccurves_default);
+ }
+ }
+
+ /* We do not allow odd length arrays to enter the system. */
+ if (pcurveslen & 1)
+ {
+ SSLerr(SSL_F_TLS1_GET_CURVELIST, ERR_R_INTERNAL_ERROR);
+ *num_curves = 0;
+ return 0;
}
- if (!*pcurves)
+ else
{
- *pcurves = eccurves_default;
- *pcurveslen = sizeof(eccurves_default);
+ *num_curves = pcurveslen / 2;
+ return 1;
}
}
int tls1_check_curve(SSL *s, const unsigned char *p, size_t len)
{
const unsigned char *curves;
- size_t curveslen, i;
+ size_t num_curves, i;
unsigned int suiteb_flags = tls1_suiteb(s);
if (len != 3 || p[0] != NAMED_CURVE_TYPE)
return 0;
else /* Should never happen */
return 0;
}
- tls1_get_curvelist(s, 0, &curves, &curveslen);
- for (i = 0; i < curveslen; i += 2, curves += 2)
+ if (!tls1_get_curvelist(s, 0, &curves, &num_curves))
+ return 0;
+ for (i = 0; i < num_curves; i++, curves += 2)
{
if (p[1] == curves[0] && p[2] == curves[1])
return tls_curve_allowed(s, p + 1, SSL_SECOP_CURVE_CHECK);
return 0;
}
-/* Return nth shared curve. If nmatch == -1 return number of
- * matches. For nmatch == -2 return the NID of the curve to use for
- * an EC tmp key.
+/*-
+ * Return |nmatch|th shared curve or NID_undef if there is no match.
+ * For nmatch == -1, return number of matches
+ * For nmatch == -2, return the NID of the curve to use for
+ * an EC tmp key, or NID_undef if there is no match.
*/
-
int tls1_shared_curve(SSL *s, int nmatch)
{
const unsigned char *pref, *supp;
- size_t preflen, supplen, i, j;
+ size_t num_pref, num_supp, i, j;
int k;
/* Can't do anything on client side */
if (s->server == 0)
/* If not Suite B just return first preference shared curve */
nmatch = 0;
}
- tls1_get_curvelist(s, !!(s->options & SSL_OP_CIPHER_SERVER_PREFERENCE),
- &supp, &supplen);
- tls1_get_curvelist(s, !(s->options & SSL_OP_CIPHER_SERVER_PREFERENCE),
- &pref, &preflen);
- preflen /= 2;
- supplen /= 2;
+ /*
+ * Avoid truncation. tls1_get_curvelist takes an int
+ * but s->options is a long...
+ */
+ if (!tls1_get_curvelist(s, (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE) != 0,
+ &supp, &num_supp))
+ /* In practice, NID_undef == 0 but let's be precise. */
+ return nmatch == -1 ? 0 : NID_undef;
+ if(!tls1_get_curvelist(s, !(s->options & SSL_OP_CIPHER_SERVER_PREFERENCE),
+ &pref, &num_pref))
+ return nmatch == -1 ? 0 : NID_undef;
k = 0;
- for (i = 0; i < preflen; i++, pref+=2)
+ for (i = 0; i < num_pref; i++, pref+=2)
{
const unsigned char *tsupp = supp;
- for (j = 0; j < supplen; j++, tsupp+=2)
+ for (j = 0; j < num_supp; j++, tsupp+=2)
{
if (pref[0] == tsupp[0] && pref[1] == tsupp[1])
{
}
if (nmatch == -1)
return k;
- return 0;
+ /* Out of range (nmatch > k). */
+ return NID_undef;
}
int tls1_set_curves(unsigned char **pext, size_t *pextlen,
static int tls1_check_ec_key(SSL *s,
unsigned char *curve_id, unsigned char *comp_id)
{
- const unsigned char *p;
- size_t plen, i;
+ const unsigned char *pformats, *pcurves;
+ size_t num_formats, num_curves, i;
int j;
/* If point formats extension present check it, otherwise everything
* is supported (see RFC4492).
*/
if (comp_id && s->session->tlsext_ecpointformatlist)
{
- p = s->session->tlsext_ecpointformatlist;
- plen = s->session->tlsext_ecpointformatlist_length;
- for (i = 0; i < plen; i++, p++)
+ pformats = s->session->tlsext_ecpointformatlist;
+ num_formats = s->session->tlsext_ecpointformatlist_length;
+ for (i = 0; i < num_formats; i++, pformats++)
{
- if (*comp_id == *p)
+ if (*comp_id == *pformats)
break;
}
- if (i == plen)
+ if (i == num_formats)
return 0;
}
if (!curve_id)
/* Check curve is consistent with client and server preferences */
for (j = 0; j <= 1; j++)
{
- tls1_get_curvelist(s, j, &p, &plen);
- for (i = 0; i < plen; i+=2, p+=2)
+ if (!tls1_get_curvelist(s, j, &pcurves, &num_curves))
+ return 0;
+ for (i = 0; i < num_curves; i++, pcurves += 2)
{
- if (p[0] == curve_id[0] && p[1] == curve_id[1])
+ if (pcurves[0] == curve_id[0] &&
+ pcurves[1] == curve_id[1])
break;
}
- if (i == plen)
+ if (i == num_curves)
return 0;
/* For clients can only check sent curve list */
if (!s->server)
}
static void tls1_get_formatlist(SSL *s, const unsigned char **pformats,
- size_t *pformatslen)
+ size_t *num_formats)
{
/* If we have a custom point format list use it otherwise
* use default */
if (s->tlsext_ecpointformatlist)
{
*pformats = s->tlsext_ecpointformatlist;
- *pformatslen = s->tlsext_ecpointformatlist_length;
+ *num_formats = s->tlsext_ecpointformatlist_length;
}
else
{
*pformats = ecformats_default;
/* For Suite B we don't support char2 fields */
if (tls1_suiteb(s))
- *pformatslen = sizeof(ecformats_default) - 1;
+ *num_formats = sizeof(ecformats_default) - 1;
else
- *pformatslen = sizeof(ecformats_default);
+ *num_formats = sizeof(ecformats_default);
}
}
}
return rv;
}
+#ifndef OPENSSL_NO_ECDH
/* Check EC temporary key is compatible with client extensions */
int tls1_check_ec_tmp_key(SSL *s, unsigned long cid)
{
return tls1_check_ec_key(s, curve_id, NULL);
#endif
}
+#endif /* OPENSSL_NO_ECDH */
#else
tlsext_sigalg_dsa(md) \
tlsext_sigalg_ecdsa(md)
-static unsigned char tls12_sigalgs[] = {
+static const unsigned char tls12_sigalgs[] = {
#ifndef OPENSSL_NO_SHA512
tlsext_sigalg(TLSEXT_hash_sha512)
tlsext_sigalg(TLSEXT_hash_sha384)
#endif
};
#ifndef OPENSSL_NO_ECDSA
-static unsigned char suiteb_sigalgs[] = {
+static const unsigned char suiteb_sigalgs[] = {
tlsext_sigalg_ecdsa(TLSEXT_hash_sha256)
tlsext_sigalg_ecdsa(TLSEXT_hash_sha384)
};
unsigned long size_str;
long lenmax;
- /* check for enough space.
- 4 for the servername type and entension length
- 2 for servernamelist length
- 1 for the hostname type
- 2 for hostname length
- + hostname length
- */
+ /*-
+ * check for enough space.
+ * 4 for the servername type and entension length
+ * 2 for servernamelist length
+ * 1 for the hostname type
+ * 2 for hostname length
+ * + hostname length
+ */
if ((lenmax = limit - ret - 9) < 0
|| (size_str = strlen(s->tlsext_hostname)) > (unsigned long)lenmax)
return NULL;
}
- /* check for enough space.
- 4 for the srp type type and entension length
- 1 for the srp user identity
- + srp user identity length
- */
+ /*-
+ * check for enough space.
+ * 4 for the srp type type and entension length
+ * 1 for the srp user identity
+ * + srp user identity length
+ */
if ((limit - ret - 5 - login_len) < 0) return NULL;
/* fill in the extension */
{
/* Add TLS extension ECPointFormats to the ClientHello message */
long lenmax;
- const unsigned char *plist;
- size_t plistlen;
+ const unsigned char *pcurves, *pformats;
+ size_t num_curves, num_formats, curves_list_len;
size_t i;
unsigned char *etmp;
- tls1_get_formatlist(s, &plist, &plistlen);
+ tls1_get_formatlist(s, &pformats, &num_formats);
if ((lenmax = limit - ret - 5) < 0) return NULL;
- if (plistlen > (size_t)lenmax) return NULL;
- if (plistlen > 255)
+ if (num_formats > (size_t)lenmax) return NULL;
+ if (num_formats > 255)
{
SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
return NULL;
}
s2n(TLSEXT_TYPE_ec_point_formats,ret);
- s2n(plistlen + 1,ret);
- *(ret++) = (unsigned char)plistlen ;
- memcpy(ret, plist, plistlen);
- ret+=plistlen;
+ /* The point format list has 1-byte length. */
+ s2n(num_formats + 1,ret);
+ *(ret++) = (unsigned char)num_formats ;
+ memcpy(ret, pformats, num_formats);
+ ret+=num_formats;
/* Add TLS extension EllipticCurves to the ClientHello message */
- plist = s->tlsext_ellipticcurvelist;
- tls1_get_curvelist(s, 0, &plist, &plistlen);
+ pcurves = s->tlsext_ellipticcurvelist;
+ if (!tls1_get_curvelist(s, 0, &pcurves, &num_curves))
+ return NULL;
if ((lenmax = limit - ret - 6) < 0) return NULL;
- if (plistlen > (size_t)lenmax) return NULL;
- if (plistlen > 65532)
+ if (num_curves > (size_t)lenmax / 2) return NULL;
+ if (num_curves > 65532 / 2)
{
SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
return NULL;
s2n(TLSEXT_TYPE_elliptic_curves,ret);
etmp = ret + 4;
/* Copy curve ID if supported */
- for (i = 0; i < plistlen; i += 2, plist += 2)
+ for (i = 0; i < num_curves; i++, pcurves += 2)
{
- if (tls_curve_allowed(s, plist, SSL_SECOP_CURVE_SUPPORTED))
+ if (tls_curve_allowed(s, pcurves, SSL_SECOP_CURVE_SUPPORTED))
{
- *etmp++ = plist[0];
- *etmp++ = plist[1];
+ *etmp++ = pcurves[0];
+ *etmp++ = pcurves[1];
}
}
- plistlen = etmp - ret - 4;
+ curves_list_len = etmp - ret - 4;
- s2n(plistlen + 2, ret);
- s2n(plistlen, ret);
- ret+=plistlen;
+ s2n(curves_list_len + 2, ret);
+ s2n(curves_list_len, ret);
+ ret += curves_list_len;
}
#endif /* OPENSSL_NO_EC */
return NULL;
s2n(TLSEXT_TYPE_heartbeat,ret);
s2n(1,ret);
- /* Set mode:
+ /*-
+ * Set mode:
* 1: peer may send requests
* 2: peer not allowed to send requests
*/
ret += s->alpn_client_proto_list_len;
}
+#ifndef OPENSSL_NO_SRTP
if(SSL_IS_DTLS(s) && SSL_get_srtp_profiles(s))
{
int el;
}
ret += el;
}
+#endif
custom_ext_init(&s->cert->cli_ext);
/* Add custom TLS Extensions to ClientHello */
if (!custom_ext_add(s, 0, &ret, limit, al))
}
#endif
+#ifndef OPENSSL_NO_SRTP
if(SSL_IS_DTLS(s) && s->srtp_profile)
{
int el;
}
ret+=el;
}
+#endif
if (((s->s3->tmp.new_cipher->id & 0xFFFF)==0x80 || (s->s3->tmp.new_cipher->id & 0xFFFF)==0x81)
&& (SSL_get_options(s) & SSL_OP_CRYPTOPRO_TLSEXT_BUG))
return NULL;
s2n(TLSEXT_TYPE_heartbeat,ret);
s2n(1,ret);
- /* Set mode:
+ /*-
+ * Set mode:
* 1: peer may send requests
* 2: peer not allowed to send requests
*/
}
#ifndef OPENSSL_NO_EC
-/* ssl_check_for_safari attempts to fingerprint Safari using OS X
+/*-
+ * ssl_check_for_safari attempts to fingerprint Safari using OS X
* SecureTransport using the TLS extension block in |d|, of length |n|.
* Safari, since 10.6, sends exactly these extensions, in this order:
* SNI,
s->s3->flags &= ~TLS1_FLAGS_ENCRYPT_THEN_MAC;
#endif
+#ifndef OPENSSL_NO_SRP
+ if (s->srp_ctx.login != NULL)
+ {
+ OPENSSL_free(s->srp_ctx.login);
+ s->srp_ctx.login = NULL;
+ }
+#endif
+
+ s->srtp_profile = NULL;
+
if (data >= (d+n-2))
goto ri_check;
n2s(data,len);
}
else if (s->version == SSL3_VERSION)
{}
-/* 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.
-
-*/
+/*-
+ * 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.
+ *
+ */
else if (type == TLSEXT_TYPE_server_name)
{
ellipticcurvelist_length += (*(sdata++));
if (ellipticcurvelist_length != size - 2 ||
- ellipticcurvelist_length < 1)
+ ellipticcurvelist_length < 1 ||
+ /* Each NamedCurve is 2 bytes. */
+ ellipticcurvelist_length & 1)
{
*al = TLS1_AD_DECODE_ERROR;
return 0;
if (s->s3->client_opaque_prf_input != NULL) /* shouldn't really happen */
OPENSSL_free(s->s3->client_opaque_prf_input);
+
+ /* dummy byte just to get non-NULL */
if (s->s3->client_opaque_prf_input_len == 0)
- s->s3->client_opaque_prf_input = OPENSSL_malloc(1); /* dummy byte just to get non-NULL */
+ s->s3->client_opaque_prf_input = OPENSSL_malloc(1);
else
s->s3->client_opaque_prf_input = BUF_memdup(sdata, s->s3->client_opaque_prf_input_len);
if (s->s3->client_opaque_prf_input == NULL)
s->s3->tmp.finish_md_len == 0 &&
s->s3->alpn_selected == NULL)
{
- /* We shouldn't accept this extension on a
+ /*-
+ * We shouldn't accept this extension on a
* renegotiation.
*
* s->new_session will be set on renegotiation, but we
* there's some other reason to disallow resuming an
* earlier session -- the current code won't be doing
* anything like that, but this might change).
-
+ *
* A valid sign that there's been a previous handshake
* in this connection is if s->s3->tmp.finish_md_len >
* 0. (We are talking about a check that will happen
* in the Hello protocol round, well before a new
- * Finished message could have been computed.) */
+ * Finished message could have been computed.)
+ */
s->s3->next_proto_neg_seen = 1;
}
#endif
}
/* session ticket processed earlier */
+#ifndef OPENSSL_NO_SRTP
else if (SSL_IS_DTLS(s) && SSL_get_srtp_profiles(s)
&& type == TLSEXT_TYPE_use_srtp)
{
al))
return 0;
}
+#endif
#ifdef TLSEXT_TYPE_encrypt_then_mac
else if (type == TLSEXT_TYPE_encrypt_then_mac)
s->s3->flags |= TLS1_FLAGS_ENCRYPT_THEN_MAC;
*al = TLS1_AD_DECODE_ERROR;
return 0;
}
- /* The extension data consists of:
+ /*-
+ * The extension data consists of:
* uint16 list_length
* uint8 proto_length;
- * uint8 proto[proto_length]; */
+ * uint8 proto[proto_length];
+ */
len = data[0];
len <<= 8;
len |= data[1];
}
}
#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))
return 0;
}
+#endif
#ifdef TLSEXT_TYPE_encrypt_then_mac
else if (type == TLSEXT_TYPE_encrypt_then_mac)
{
return 1;
}
-/* Since the server cache lookup is done early on in the processing of the
+/*-
+ * Since the server cache lookup is done early on in the processing of the
* ClientHello, and other operations depend on the result, we need to handle
* any TLS session ticket extension at the same time.
*
return 0;
}
-/* tls_decrypt_ticket attempts to decrypt a session ticket.
+/*-
+ * tls_decrypt_ticket attempts to decrypt a session ticket.
*
* etick: points to the body of the session ticket extension.
* eticklen: the length of the session tickets extenion.
int id;
} tls12_lookup;
-static tls12_lookup tls12_md[] = {
+static const tls12_lookup tls12_md[] = {
{NID_md5, TLSEXT_hash_md5},
{NID_sha1, TLSEXT_hash_sha1},
{NID_sha224, TLSEXT_hash_sha224},
{NID_sha512, TLSEXT_hash_sha512}
};
-static tls12_lookup tls12_sig[] = {
+static const tls12_lookup tls12_sig[] = {
{EVP_PKEY_RSA, TLSEXT_signature_rsa},
{EVP_PKEY_DSA, TLSEXT_signature_dsa},
{EVP_PKEY_EC, TLSEXT_signature_ecdsa}
};
-static int tls12_find_id(int nid, tls12_lookup *table, size_t tlen)
+static int tls12_find_id(int nid, const tls12_lookup *table, size_t tlen)
{
size_t i;
for (i = 0; i < tlen; i++)
return -1;
}
-static int tls12_find_nid(int id, tls12_lookup *table, size_t tlen)
+static int tls12_find_nid(int id, const tls12_lookup *table, size_t tlen)
{
size_t i;
for (i = 0; i < tlen; i++)
const EVP_MD *tls12_get_hash(unsigned char hash_alg)
{
const tls12_hash_info *inf;
-#ifndef OPENSSL_FIPS
if (hash_alg == TLSEXT_hash_md5 && FIPS_mode())
return NULL;
-#endif
inf = tls12_get_hash_info(hash_alg);
if (!inf || !inf->mfunc)
return NULL;
* payload, plus padding
*/
buffer = OPENSSL_malloc(1 + 2 + payload + padding);
+ if (buffer == NULL)
+ {
+ SSLerr(SSL_F_TLS1_PROCESS_HEARTBEAT,ERR_R_MALLOC_FAILURE);
+ return -1;
+ }
bp = buffer;
/* Enter response type, length and copy payload */
*/
OPENSSL_assert(payload + padding <= 16381);
- /* Create HeartBeat message, we just use a sequence number
+ /*-
+ * Create HeartBeat message, we just use a sequence number
* as payload to distuingish different messages and add
* some random stuff.
* - Message Type, 1 byte
* - Padding
*/
buf = OPENSSL_malloc(1 + 2 + payload + padding);
+ if (buf == NULL)
+ {
+ SSLerr(SSL_F_TLS1_HEARTBEAT,ERR_R_MALLOC_FAILURE);
+ return -1;
+ }
p = buf;
/* Message Type */
*p++ = TLS1_HB_REQUEST;
if (check_flags)
check_flags |= CERT_PKEY_SUITEB;
ok = X509_chain_check_suiteb(NULL, x, chain, suiteb_flags);
- if (ok != X509_V_OK)
- {
- if (check_flags)
- rv |= CERT_PKEY_SUITEB;
- else
- goto end;
- }
+ if (ok == X509_V_OK)
+ rv |= CERT_PKEY_SUITEB;
+ else if (!check_flags)
+ goto end;
}
/* Check all signature algorithms are consistent with