#include <openssl/objects.h>
#include <openssl/evp.h>
#include <openssl/hmac.h>
+#ifdef OPENSSL_NO_EC2M
+#include <openssl/ec.h>
+#endif
#include <openssl/ocsp.h>
#include <openssl/rand.h>
#include "ssl_locl.h"
static const unsigned char eccurves_default[] =
{
+#ifndef OPENSSL_NO_EC2M
0,14, /* sect571r1 (14) */
0,13, /* sect571k1 (13) */
+#endif
0,25, /* secp521r1 (25) */
0,28, /* brainpool512r1 (28) */
+#ifndef OPENSSL_NO_EC2M
0,11, /* sect409k1 (11) */
0,12, /* sect409r1 (12) */
+#endif
0,27, /* brainpoolP384r1 (27) */
0,24, /* secp384r1 (24) */
+#ifndef OPENSSL_NO_EC2M
0,9, /* sect283k1 (9) */
0,10, /* sect283r1 (10) */
+#endif
0,26, /* brainpoolP256r1 (26) */
0,22, /* secp256k1 (22) */
0,23, /* secp256r1 (23) */
+#ifndef OPENSSL_NO_EC2M
0,8, /* sect239k1 (8) */
0,6, /* sect233k1 (6) */
0,7, /* sect233r1 (7) */
+#endif
0,20, /* secp224k1 (20) */
0,21, /* secp224r1 (21) */
+#ifndef OPENSSL_NO_EC2M
0,4, /* sect193r1 (4) */
0,5, /* sect193r2 (5) */
+#endif
0,18, /* secp192k1 (18) */
0,19, /* secp192r1 (19) */
+#ifndef OPENSSL_NO_EC2M
0,1, /* sect163k1 (1) */
0,2, /* sect163r1 (2) */
0,3, /* sect163r2 (3) */
+#endif
0,15, /* secp160k1 (15) */
0,16, /* secp160r1 (16) */
0,17, /* secp160r2 (17) */
0, TLSEXT_curve_P_384
};
+#ifdef OPENSSL_FIPS
+/* Brainpool not allowed in FIPS mode */
+static const unsigned char fips_curves_default[] =
+ {
+#ifndef OPENSSL_NO_EC2M
+ 0,14, /* sect571r1 (14) */
+ 0,13, /* sect571k1 (13) */
+#endif
+ 0,25, /* secp521r1 (25) */
+#ifndef OPENSSL_NO_EC2M
+ 0,11, /* sect409k1 (11) */
+ 0,12, /* sect409r1 (12) */
+#endif
+ 0,24, /* secp384r1 (24) */
+#ifndef OPENSSL_NO_EC2M
+ 0,9, /* sect283k1 (9) */
+ 0,10, /* sect283r1 (10) */
+#endif
+ 0,22, /* secp256k1 (22) */
+ 0,23, /* secp256r1 (23) */
+#ifndef OPENSSL_NO_EC2M
+ 0,8, /* sect239k1 (8) */
+ 0,6, /* sect233k1 (6) */
+ 0,7, /* sect233r1 (7) */
+#endif
+ 0,20, /* secp224k1 (20) */
+ 0,21, /* secp224r1 (21) */
+#ifndef OPENSSL_NO_EC2M
+ 0,4, /* sect193r1 (4) */
+ 0,5, /* sect193r2 (5) */
+#endif
+ 0,18, /* secp192k1 (18) */
+ 0,19, /* secp192r1 (19) */
+#ifndef OPENSSL_NO_EC2M
+ 0,1, /* sect163k1 (1) */
+ 0,2, /* sect163r1 (2) */
+ 0,3, /* sect163r2 (3) */
+#endif
+ 0,15, /* secp160k1 (15) */
+ 0,16, /* secp160r1 (16) */
+ 0,17, /* secp160r2 (17) */
+ };
+#endif
+
int tls1_ec_curve_id2nid(int curve_id)
{
- /* ECC curves from draft-ietf-tls-ecc-12.txt (Oct. 17, 2005) */
+ /* ECC curves from RFC 4492 and RFC 7027 */
if ((curve_id < 1) || ((unsigned int)curve_id >
sizeof(nid_list)/sizeof(nid_list[0])))
return 0;
int tls1_ec_nid2curve_id(int nid)
{
- /* ECC curves from draft-ietf-tls-ecc-12.txt (Oct. 17, 2005) */
+ /* ECC curves from RFC 4492 and RFC 7027 */
switch (nid)
{
case NID_sect163k1: /* sect163k1 (1) */
}
if (!*pcurves)
{
+#ifdef OPENSSL_FIPS
+ if (FIPS_mode())
+ {
+ *pcurves = fips_curves_default;
+ *pcurveslen = sizeof(fips_curves_default);
+ return;
+ }
+#endif
*pcurves = eccurves_default;
*pcurveslen = sizeof(eccurves_default);
}
* while curve ids < 32
*/
unsigned long dup_list = 0;
+#ifdef OPENSSL_NO_EC2M
+ EC_GROUP *curve;
+#endif
+
clist = OPENSSL_malloc(ncurves * 2);
if (!clist)
return 0;
unsigned long idmask;
int id;
id = tls1_ec_nid2curve_id(curves[i]);
+#ifdef OPENSSL_FIPS
+ /* NB: 25 is last curve ID supported by FIPS module */
+ if (FIPS_mode() && id > 25)
+ {
+ OPENSSL_free(clist);
+ return 0;
+ }
+#endif
+#ifdef OPENSSL_NO_EC2M
+ curve = EC_GROUP_new_by_curve_name(curves[i]);
+ if(!curve ||
+ EC_METHOD_get_field_type(EC_GROUP_method_of(curve))
+ == NID_X9_62_characteristic_two_field)
+ {
+ if(curve) EC_GROUP_free(curve);
+ OPENSSL_free(clist);
+ return 0;
+ }
+ else
+ EC_GROUP_free(curve);
+#endif
idmask = 1L << id;
if (!id || (dup_list & idmask))
{
return 1;
}
-#define MAX_CURVELIST 25
+#define MAX_CURVELIST 28
typedef struct
{
c->mask_k |= SSL_kPSK;
}
#endif /* OPENSSL_NO_PSK */
+#ifndef OPENSSL_NO_SRP
+ if (!(s->srp_ctx.srp_Mask & SSL_kSRP))
+ {
+ c->mask_a |= SSL_aSRP;
+ c->mask_k |= SSL_kSRP;
+ }
+#endif
c->valid = 1;
}
-/* byte_compare is a compare function for qsort(3) that compares bytes. */
-static int byte_compare(const void *in_a, const void *in_b)
- {
- unsigned char a = *((const unsigned char*) in_a);
- unsigned char b = *((const unsigned char*) in_b);
-
- if (a > b)
- return 1;
- else if (a < b)
- return -1;
- return 0;
-}
-
-unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned char *limit)
+unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *buf, unsigned char *limit, int *al)
{
int extdatalen=0;
- unsigned char *ret = p;
+ unsigned char *orig = buf;
+ unsigned char *ret = buf;
#ifndef OPENSSL_NO_EC
/* See if we support any ECC ciphersuites */
int using_ecc = 0;
/* don't add extensions for SSLv3 unless doing secure renegotiation */
if (s->client_version == SSL3_VERSION
&& !s->s3->send_connection_binding)
- return p;
+ return orig;
ret+=2;
return NULL;
}
- if((limit - p - 4 - el) < 0) return NULL;
+ if((limit - ret - 4 - el) < 0) return NULL;
s2n(TLSEXT_TYPE_renegotiate,ret);
s2n(el,ret);
s2n(TLSEXT_TYPE_elliptic_curves,ret);
s2n(plistlen + 2, ret);
-
- /* NB: draft-ietf-tls-ecc-12.txt uses a one-byte prefix for
- * elliptic_curve_list, but the examples use two bytes.
- * http://www1.ietf.org/mail-archive/web/tls/current/msg00538.html
- * resolves this to two bytes.
- */
s2n(plistlen, ret);
memcpy(ret, plist, plistlen);
ret+=plistlen;
#ifndef OPENSSL_NO_HEARTBEATS
/* Add Heartbeat extension */
+ if ((limit - ret - 4 - 1) < 0)
+ return NULL;
s2n(TLSEXT_TYPE_heartbeat,ret);
s2n(1,ret);
/* Set mode:
ret += s->alpn_client_proto_list_len;
}
- if(SSL_get_srtp_profiles(s))
+ if(SSL_IS_DTLS(s) && SSL_get_srtp_profiles(s))
{
int el;
ssl_add_clienthello_use_srtp_ext(s, 0, &el, 0);
- if((limit - p - 4 - el) < 0) return NULL;
+ if((limit - ret - 4 - el) < 0) return NULL;
s2n(TLSEXT_TYPE_use_srtp,ret);
s2n(el,ret);
}
ret += el;
}
-
- /* Add TLS extension Server_Authz_DataFormats to the ClientHello */
- /* 2 bytes for extension type */
- /* 2 bytes for extension length */
- /* 1 byte for the list length */
- /* 1 byte for the list (we only support audit proofs) */
- if (s->ctx->tlsext_authz_server_audit_proof_cb != NULL)
- {
- const unsigned short ext_len = 2;
- const unsigned char list_len = 1;
-
- if (limit < ret + 6)
- return NULL;
-
- s2n(TLSEXT_TYPE_server_authz, ret);
- /* Extension length: 2 bytes */
- s2n(ext_len, ret);
- *(ret++) = list_len;
- *(ret++) = TLSEXT_AUTHZDATAFORMAT_audit_proof;
- }
-
+ custom_ext_init(&s->cert->cli_ext);
/* Add custom TLS Extensions to ClientHello */
- if (s->ctx->custom_cli_ext_records_count)
- {
- size_t i;
- custom_cli_ext_record* record;
+ if (!custom_ext_add(s, 0, &ret, limit, al))
+ return NULL;
- for (i = 0; i < s->ctx->custom_cli_ext_records_count; i++)
+ /* Add padding to workaround bugs in F5 terminators.
+ * See https://tools.ietf.org/html/draft-agl-tls-padding-03
+ *
+ * NB: because this code works out the length of all existing
+ * extensions it MUST always appear last.
+ */
+ if (s->options & SSL_OP_TLSEXT_PADDING)
+ {
+ int hlen = ret - (unsigned char *)s->init_buf->data;
+ /* The code in s23_clnt.c to build ClientHello messages
+ * includes the 5-byte record header in the buffer, while
+ * the code in s3_clnt.c does not.
+ */
+ if (s->state == SSL23_ST_CW_CLNT_HELLO_A)
+ hlen -= 5;
+ if (hlen > 0xff && hlen < 0x200)
{
- const unsigned char* out = NULL;
- unsigned short outlen = 0;
+ hlen = 0x200 - hlen;
+ if (hlen >= 4)
+ hlen -= 4;
+ else
+ hlen = 0;
- record = &s->ctx->custom_cli_ext_records[i];
- /* NULL callback sends empty extension */
- /* -1 from callback omits extension */
- if (record->fn1)
- {
- int cb_retval = 0;
- cb_retval = record->fn1(s, record->ext_type,
- &out, &outlen,
- record->arg);
- if (cb_retval == 0)
- return NULL; /* error */
- if (cb_retval == -1)
- continue; /* skip this extension */
- }
- if (limit < ret + 4 + outlen)
- return NULL;
- s2n(record->ext_type, ret);
- s2n(outlen, ret);
- memcpy(ret, out, outlen);
- ret += outlen;
+ s2n(TLSEXT_TYPE_padding, ret);
+ s2n(hlen, ret);
+ memset(ret, 0, hlen);
+ ret += hlen;
}
}
- if ((extdatalen = ret-p-2) == 0)
- return p;
+ if ((extdatalen = ret-orig-2)== 0)
+ return orig;
- s2n(extdatalen,p);
+ s2n(extdatalen, orig);
return ret;
}
-unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned char *limit)
+unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *buf, unsigned char *limit, int *al)
{
int extdatalen=0;
- unsigned char *ret = p;
+ unsigned char *orig = buf;
+ unsigned char *ret = buf;
#ifndef OPENSSL_NO_NEXTPROTONEG
int next_proto_neg_seen;
#endif
#endif
/* don't add extensions for SSLv3, unless doing secure renegotiation */
if (s->version == SSL3_VERSION && !s->s3->send_connection_binding)
- return p;
+ return orig;
ret+=2;
if (ret>=limit) return NULL; /* this really never occurs, but ... */
return NULL;
}
- if((limit - p - 4 - el) < 0) return NULL;
+ if((limit - ret - 4 - el) < 0) return NULL;
s2n(TLSEXT_TYPE_renegotiate,ret);
s2n(el,ret);
}
#endif
- if(s->srtp_profile)
+ if(SSL_IS_DTLS(s) && s->srtp_profile)
{
int el;
ssl_add_serverhello_use_srtp_ext(s, 0, &el, 0);
- if((limit - p - 4 - el) < 0) return NULL;
+ if((limit - ret - 4 - el) < 0) return NULL;
s2n(TLSEXT_TYPE_use_srtp,ret);
s2n(el,ret);
/* Add Heartbeat extension if we've received one */
if (s->tlsext_heartbeat & SSL_TLSEXT_HB_ENABLED)
{
+ if ((limit - ret - 4 - 1) < 0)
+ return NULL;
s2n(TLSEXT_TYPE_heartbeat,ret);
s2n(1,ret);
/* Set mode:
}
}
#endif
-
- /* If the client supports authz then see whether we have any to offer
- * to it. */
- if (s->s3->tlsext_authz_client_types_len)
- {
- size_t authz_length;
- /* By now we already know the new cipher, so we can look ahead
- * to see whether the cert we are going to send
- * has any authz data attached to it. */
- const unsigned char* authz = ssl_get_authz_data(s, &authz_length);
- const unsigned char* const orig_authz = authz;
- size_t i;
- unsigned authz_count = 0;
-
- /* The authz data contains a number of the following structures:
- * uint8_t authz_type
- * uint16_t length
- * uint8_t data[length]
- *
- * First we walk over it to find the number of authz elements. */
- for (i = 0; i < authz_length; i++)
- {
- unsigned short length;
- unsigned char type;
-
- type = *(authz++);
- if (memchr(s->s3->tlsext_authz_client_types,
- type,
- s->s3->tlsext_authz_client_types_len) != NULL)
- authz_count++;
-
- n2s(authz, length);
- /* n2s increments authz by 2 */
- i += 2;
- authz += length;
- i += length;
- }
-
- if (authz_count)
- {
- /* Add TLS extension server_authz to the ServerHello message
- * 2 bytes for extension type
- * 2 bytes for extension length
- * 1 byte for the list length
- * n bytes for the list */
- const unsigned short ext_len = 1 + authz_count;
-
- if ((long)(limit - ret - 4 - ext_len) < 0) return NULL;
- s2n(TLSEXT_TYPE_server_authz, ret);
- s2n(ext_len, ret);
- *(ret++) = authz_count;
- s->s3->tlsext_authz_promised_to_client = 1;
- }
-
- authz = orig_authz;
- for (i = 0; i < authz_length; i++)
- {
- unsigned short length;
- unsigned char type;
-
- authz_count++;
- type = *(authz++);
- if (memchr(s->s3->tlsext_authz_client_types,
- type,
- s->s3->tlsext_authz_client_types_len) != NULL)
- *(ret++) = type;
- n2s(authz, length);
- /* n2s increments authz by 2 */
- i += 2;
- authz += length;
- i += length;
- }
- }
-
- /* If custom types were sent in ClientHello, add ServerHello responses */
- if (s->s3->tlsext_custom_types_count)
- {
- size_t i;
-
- for (i = 0; i < s->s3->tlsext_custom_types_count; i++)
- {
- size_t j;
- custom_srv_ext_record *record;
-
- for (j = 0; j < s->ctx->custom_srv_ext_records_count; j++)
- {
- record = &s->ctx->custom_srv_ext_records[j];
- if (s->s3->tlsext_custom_types[i] == record->ext_type)
- {
- const unsigned char *out = NULL;
- unsigned short outlen = 0;
- int cb_retval = 0;
-
- /* NULL callback or -1 omits extension */
- if (!record->fn2)
- break;
- cb_retval = record->fn2(s, record->ext_type,
- &out, &outlen,
- record->arg);
- if (cb_retval == 0)
- return NULL; /* error */
- if (cb_retval == -1)
- break; /* skip this extension */
- if (limit < ret + 4 + outlen)
- return NULL;
- s2n(record->ext_type, ret);
- s2n(outlen, ret);
- memcpy(ret, out, outlen);
- ret += outlen;
- break;
- }
- }
- }
- }
+ if (!custom_ext_add(s, 1, &ret, limit, al))
+ return NULL;
if (s->s3->alpn_selected)
{
ret += len;
}
- if ((extdatalen = ret-p-2)== 0)
- return p;
+ if ((extdatalen = ret-orig-2)== 0)
+ return orig;
- s2n(extdatalen,p);
+ s2n(extdatalen, orig);
return ret;
}
unsigned short len;
unsigned char *data = *p;
int renegotiate_seen = 0;
- size_t i;
s->servername_done = 0;
s->tlsext_status_type = -1;
s->s3->next_proto_neg_seen = 0;
#endif
- /* Clear observed custom extensions */
- s->s3->tlsext_custom_types_count = 0;
- if (s->s3->tlsext_custom_types != NULL)
- {
- OPENSSL_free(s->s3->tlsext_custom_types);
- s->s3->tlsext_custom_types = NULL;
- }
-
if (s->s3->alpn_selected)
{
OPENSSL_free(s->s3->alpn_selected);
OPENSSL_free(s->cert->peer_sigalgs);
s->cert->peer_sigalgs = NULL;
}
- /* Clear any shared sigtnature algorithms */
- if (s->cert->shared_sigalgs)
- {
- OPENSSL_free(s->cert->shared_sigalgs);
- s->cert->shared_sigalgs = NULL;
- }
- /* Clear certificate digests and validity flags */
- for (i = 0; i < SSL_PKEY_NUM; i++)
- {
- s->cert->pkeys[i].digest = NULL;
- s->cert->pkeys[i].valid_flags = 0;
- }
if (data >= (d+n-2))
goto ri_check;
*al = SSL_AD_DECODE_ERROR;
return 0;
}
- if (!tls1_process_sigalgs(s, data, dsize))
+ if (!tls1_save_sigalgs(s, data, dsize))
{
*al = SSL_AD_DECODE_ERROR;
return 0;
}
- /* If sigalgs received and no shared algorithms fatal
- * error.
- */
- if (s->cert->peer_sigalgs && !s->cert->shared_sigalgs)
- {
- SSLerr(SSL_F_SSL_SCAN_CLIENTHELLO_TLSEXT,
- SSL_R_NO_SHARED_SIGATURE_ALGORITHMS);
- *al = SSL_AD_ILLEGAL_PARAMETER;
- return 0;
- }
}
- else if (type == TLSEXT_TYPE_status_request
- && s->ctx->tlsext_status_cb)
+ else if (type == TLSEXT_TYPE_status_request)
{
if (size < 5)
{
if (tls1_alpn_handle_client_hello(s, data, size, al) != 0)
return 0;
+#ifndef OPENSSL_NO_NEXTPROTONEG
/* ALPN takes precedence over NPN. */
s->s3->next_proto_neg_seen = 0;
+#endif
}
/* session ticket processed earlier */
- else if (type == TLSEXT_TYPE_use_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))
return 0;
}
- else if (type == TLSEXT_TYPE_server_authz)
- {
- unsigned char *sdata = data;
- unsigned char server_authz_dataformatlist_length;
-
- if (size == 0)
- {
- *al = TLS1_AD_DECODE_ERROR;
- return 0;
- }
-
- server_authz_dataformatlist_length = *(sdata++);
-
- if (server_authz_dataformatlist_length != size - 1)
- {
- *al = TLS1_AD_DECODE_ERROR;
- return 0;
- }
-
- /* Successful session resumption uses the same authz
- * information as the original session so we ignore this
- * in the case of a session resumption. */
- if (!s->hit)
- {
- if (s->s3->tlsext_authz_client_types != NULL)
- OPENSSL_free(s->s3->tlsext_authz_client_types);
- s->s3->tlsext_authz_client_types =
- OPENSSL_malloc(server_authz_dataformatlist_length);
- if (!s->s3->tlsext_authz_client_types)
- {
- *al = TLS1_AD_INTERNAL_ERROR;
- return 0;
- }
-
- s->s3->tlsext_authz_client_types_len =
- server_authz_dataformatlist_length;
- memcpy(s->s3->tlsext_authz_client_types,
- sdata,
- server_authz_dataformatlist_length);
-
- /* Sort the types in order to check for duplicates. */
- qsort(s->s3->tlsext_authz_client_types,
- server_authz_dataformatlist_length,
- 1 /* element size */,
- byte_compare);
-
- for (i = 0; i < server_authz_dataformatlist_length; i++)
- {
- if (i > 0 &&
- s->s3->tlsext_authz_client_types[i] ==
- s->s3->tlsext_authz_client_types[i-1])
- {
- *al = TLS1_AD_DECODE_ERROR;
- return 0;
- }
- }
- }
- }
-
- /* If this ClientHello extension was unhandled and this is
- * a nonresumed connection, check whether the extension is a
- * custom TLS Extension (has a custom_srv_ext_record), and if
- * so call the callback and record the extension number so that
- * an appropriate ServerHello may be later returned.
- */
- else if (!s->hit && s->ctx->custom_srv_ext_records_count)
- {
- custom_srv_ext_record *record;
-
- for (i=0; i < s->ctx->custom_srv_ext_records_count; i++)
- {
- record = &s->ctx->custom_srv_ext_records[i];
- if (type == record->ext_type)
- {
- size_t j;
-
- /* Error on duplicate TLS Extensions */
- for (j = 0; j < s->s3->tlsext_custom_types_count; j++)
- {
- if (type == s->s3->tlsext_custom_types[j])
- {
- *al = TLS1_AD_DECODE_ERROR;
- return 0;
- }
- }
-
- /* NULL callback still notes the extension */
- if (record->fn1 && !record->fn1(s, type, data, size, al, record->arg))
- return 0;
-
- /* Add the (non-duplicated) entry */
- s->s3->tlsext_custom_types_count++;
- s->s3->tlsext_custom_types = OPENSSL_realloc(
- s->s3->tlsext_custom_types,
- s->s3->tlsext_custom_types_count * 2);
- if (s->s3->tlsext_custom_types == NULL)
- {
- s->s3->tlsext_custom_types = 0;
- *al = TLS1_AD_INTERNAL_ERROR;
- return 0;
- }
- s->s3->tlsext_custom_types[
- s->s3->tlsext_custom_types_count - 1] = type;
- }
- }
- }
-
data+=size;
}
SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED);
return 0;
}
- /* If no signature algorithms extension set default values */
- if (!s->cert->peer_sigalgs)
- ssl_cert_set_default_md(s->cert);
+
+ return 1;
+ }
+
+/*
+ * Parse any custom extensions found. "data" is the start of the extension data
+ * and "limit" is the end of the record. TODO: add strict syntax checking.
+ */
+
+static int ssl_scan_clienthello_custom_tlsext(SSL *s, const unsigned char *data, const unsigned char *limit, int *al)
+ {
+ unsigned short type, size, len;
+ /* If resumed session or no custom extensions nothing to do */
+ if (s->hit || s->cert->srv_ext.meths_count == 0)
+ return 1;
+
+ if (data >= limit - 2)
+ return 1;
+ n2s(data, len);
+
+ if (data > limit - len)
+ return 1;
+
+ while (data <= limit - 4)
+ {
+ n2s(data, type);
+ n2s(data, size);
+
+ if (data+size > limit)
+ return 1;
+ if (custom_ext_parse(s, 1 /* server */, type, data, size, al) <= 0)
+ return 0;
+
+ data+=size;
+ }
return 1;
}
int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, int n)
{
int al = -1;
+ unsigned char *ptmp = *p;
+ /*
+ * Internally supported extensions are parsed first so SNI can be handled
+ * before custom extensions. An application processing SNI will typically
+ * switch the parent context using SSL_set_SSL_CTX and custom extensions
+ * need to be handled by the new SSL_CTX structure.
+ */
if (ssl_scan_clienthello_tlsext(s, p, d, n, &al) <= 0)
{
ssl3_send_alert(s,SSL3_AL_FATAL,al);
SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_TLSEXT,SSL_R_CLIENTHELLO_TLSEXT);
return 0;
}
+
+ custom_ext_init(&s->cert->srv_ext);
+ if (ssl_scan_clienthello_custom_tlsext(s, ptmp, d + n, &al) <= 0)
+ {
+ ssl3_send_alert(s,SSL3_AL_FATAL,al);
+ return 0;
+ }
+
return 1;
}
*al = TLS1_AD_DECODE_ERROR;
return 0;
}
- s->session->tlsext_ecpointformatlist_length = 0;
- if (s->session->tlsext_ecpointformatlist != NULL) OPENSSL_free(s->session->tlsext_ecpointformatlist);
- if ((s->session->tlsext_ecpointformatlist = OPENSSL_malloc(ecpointformatlist_length)) == NULL)
+ if (!s->hit)
{
- *al = TLS1_AD_INTERNAL_ERROR;
- return 0;
+ s->session->tlsext_ecpointformatlist_length = 0;
+ if (s->session->tlsext_ecpointformatlist != NULL) OPENSSL_free(s->session->tlsext_ecpointformatlist);
+ if ((s->session->tlsext_ecpointformatlist = OPENSSL_malloc(ecpointformatlist_length)) == NULL)
+ {
+ *al = TLS1_AD_INTERNAL_ERROR;
+ return 0;
+ }
+ s->session->tlsext_ecpointformatlist_length = ecpointformatlist_length;
+ memcpy(s->session->tlsext_ecpointformatlist, sdata, ecpointformatlist_length);
}
- s->session->tlsext_ecpointformatlist_length = ecpointformatlist_length;
- memcpy(s->session->tlsext_ecpointformatlist, sdata, ecpointformatlist_length);
#if 0
fprintf(stderr,"ssl_parse_serverhello_tlsext s->session->tlsext_ecpointformatlist ");
sdata = s->session->tlsext_ecpointformatlist;
}
}
#endif
- else if (type == TLSEXT_TYPE_use_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;
}
-
- else if (type == TLSEXT_TYPE_server_authz)
- {
- /* We only support audit proofs. It's an error to send
- * an authz hello extension if the client
- * didn't request a proof. */
- unsigned char *sdata = data;
- unsigned char server_authz_dataformatlist_length;
-
- if (!s->ctx->tlsext_authz_server_audit_proof_cb)
- {
- *al = TLS1_AD_UNSUPPORTED_EXTENSION;
- return 0;
- }
-
- if (!size)
- {
- *al = TLS1_AD_DECODE_ERROR;
- return 0;
- }
-
- server_authz_dataformatlist_length = *(sdata++);
- if (server_authz_dataformatlist_length != size - 1)
- {
- *al = TLS1_AD_DECODE_ERROR;
- return 0;
- }
-
- /* We only support audit proofs, so a legal ServerHello
- * authz list contains exactly one entry. */
- if (server_authz_dataformatlist_length != 1 ||
- sdata[0] != TLSEXT_AUTHZDATAFORMAT_audit_proof)
- {
- *al = TLS1_AD_UNSUPPORTED_EXTENSION;
- return 0;
- }
-
- s->s3->tlsext_authz_server_promised = 1;
- }
-
/* If this extension type was not otherwise handled, but
* matches a custom_cli_ext_record, then send it to the c
* callback */
- else if (s->ctx->custom_cli_ext_records_count)
- {
- size_t i;
- custom_cli_ext_record* record;
-
- for (i = 0; i < s->ctx->custom_cli_ext_records_count; i++)
- {
- record = &s->ctx->custom_cli_ext_records[i];
- if (record->ext_type == type)
- {
- if (record->fn2 && !record->fn2(s, type, data, size, al, record->arg))
- return 0;
- break;
- }
- }
- }
+ else if (custom_ext_parse(s, 0, type, data, size, al) <= 0)
+ return 0;
data += size;
}
}
}
+int tls1_set_server_sigalgs(SSL *s)
+ {
+ int al;
+ size_t i;
+ /* Clear any shared sigtnature algorithms */
+ if (s->cert->shared_sigalgs)
+ {
+ OPENSSL_free(s->cert->shared_sigalgs);
+ s->cert->shared_sigalgs = NULL;
+ }
+ /* Clear certificate digests and validity flags */
+ for (i = 0; i < SSL_PKEY_NUM; i++)
+ {
+ s->cert->pkeys[i].digest = NULL;
+ s->cert->pkeys[i].valid_flags = 0;
+ }
+
+ /* If sigalgs received process it. */
+ if (s->cert->peer_sigalgs)
+ {
+ if (!tls1_process_sigalgs(s))
+ {
+ SSLerr(SSL_F_TLS1_SET_SERVER_SIGALGS,
+ ERR_R_MALLOC_FAILURE);
+ al = SSL_AD_INTERNAL_ERROR;
+ goto err;
+ }
+ /* Fatal error is no shared signature algorithms */
+ if (!s->cert->shared_sigalgs)
+ {
+ SSLerr(SSL_F_TLS1_SET_SERVER_SIGALGS,
+ SSL_R_NO_SHARED_SIGATURE_ALGORITHMS);
+ al = SSL_AD_ILLEGAL_PARAMETER;
+ goto err;
+ }
+ }
+ else
+ ssl_cert_set_default_md(s->cert);
+ return 1;
+ err:
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
+ return 0;
+ }
+
int ssl_check_clienthello_tlsext_late(SSL *s)
{
int ret = SSL_TLSEXT_ERR_OK;
HMAC_Final(&hctx, tick_hmac, NULL);
HMAC_CTX_cleanup(&hctx);
if (CRYPTO_memcmp(tick_hmac, etick + eticklen, mlen))
+ {
+ EVP_CIPHER_CTX_cleanup(&ctx);
return 2;
+ }
/* Attempt to decrypt session data */
/* Move p after IV to start of encrypted ticket, update length */
p = etick + 16 + EVP_CIPHER_CTX_iv_length(&ctx);
}
EVP_DecryptUpdate(&ctx, sdec, &slen, p, eticklen);
if (EVP_DecryptFinal(&ctx, sdec + slen, &mlen) <= 0)
+ {
+ EVP_CIPHER_CTX_cleanup(&ctx);
+ OPENSSL_free(sdec);
return 2;
+ }
slen += mlen;
EVP_CIPHER_CTX_cleanup(&ctx);
p = sdec;
TLS_SIGALGS *salgs = NULL;
CERT *c = s->cert;
unsigned int is_suiteb = tls1_suiteb(s);
+ if (c->shared_sigalgs)
+ {
+ OPENSSL_free(c->shared_sigalgs);
+ c->shared_sigalgs = NULL;
+ }
/* If client use client signature algorithms if not NULL */
if (!s->server && c->client_sigalgs && !is_suiteb)
{
/* Set preferred digest for each key type */
-int tls1_process_sigalgs(SSL *s, const unsigned char *data, int dsize)
+int tls1_save_sigalgs(SSL *s, const unsigned char *data, int dsize)
{
- int idx;
- size_t i;
- const EVP_MD *md;
CERT *c = s->cert;
- TLS_SIGALGS *sigptr;
/* Extension ignored for inappropriate versions */
if (!SSL_USE_SIGALGS(s))
return 1;
if (!c)
return 0;
+ if (c->peer_sigalgs)
+ OPENSSL_free(c->peer_sigalgs);
c->peer_sigalgs = OPENSSL_malloc(dsize);
if (!c->peer_sigalgs)
return 0;
c->peer_sigalgslen = dsize;
memcpy(c->peer_sigalgs, data, dsize);
+ return 1;
+ }
- tls1_set_shared_sigalgs(s);
+int tls1_process_sigalgs(SSL *s)
+ {
+ int idx;
+ size_t i;
+ const EVP_MD *md;
+ CERT *c = s->cert;
+ TLS_SIGALGS *sigptr;
+ if (!tls1_set_shared_sigalgs(s))
+ return 0;
#ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL
if (s->cert->cert_flags & SSL_CERT_FLAG_BROKEN_PROTOCOL)
unsigned int payload;
unsigned int padding = 16; /* Use minimum padding */
- /* Read type and payload length first */
- hbtype = *p++;
- n2s(p, payload);
- pl = p;
-
if (s->msg_callback)
s->msg_callback(0, s->version, TLS1_RT_HEARTBEAT,
&s->s3->rrec.data[0], s->s3->rrec.length,
s, s->msg_callback_arg);
+ /* Read type and payload length first */
+ if (1 + 2 + 16 > s->s3->rrec.length)
+ return 0; /* silently discard */
+ hbtype = *p++;
+ n2s(p, payload);
+ if (1 + 2 + payload + 16 > s->s3->rrec.length)
+ return 0; /* silently discard per RFC 6520 sec. 4 */
+ pl = p;
+
if (hbtype == TLS1_HB_REQUEST)
{
unsigned char *buffer, *bp;