return 1;
}
-#define MAX_CURVELIST 25
+#define MAX_CURVELIST 28
typedef struct
{
c->valid = 1;
}
-unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned char *limit)
+unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned char *limit, int *al)
{
int extdatalen=0;
unsigned char *ret = p;
alg_k = c->algorithm_mkey;
alg_a = c->algorithm_auth;
- if ((alg_k & (SSL_kEECDH|SSL_kECDHr|SSL_kECDHe)
+ if ((alg_k & (SSL_kECDHE|SSL_kECDHr|SSL_kECDHe)
|| (alg_a & SSL_aECDSA)))
{
using_ecc = 1;
{
int cb_retval = 0;
cb_retval = record->fn1(s, record->ext_type,
- &out, &outlen,
+ &out, &outlen, al,
record->arg);
if (cb_retval == 0)
return NULL; /* error */
s2n(TLSEXT_TYPE_encrypt_then_mac,ret);
s2n(0,ret);
#endif
-#ifdef TLSEXT_TYPE_wtf
- {
- /* Work out length which would be used in the TLS record:
- * NB this should ALWAYS appear after all other extensions.
+#ifdef TLSEXT_TYPE_padding
+ /* Add padding to workaround bugs in F5 terminators.
+ * See https://tools.ietf.org/html/draft-agl-tls-padding-02
+ *
+ * NB: because this code works out the length of all existing
+ * extensions it MUST always appear last.
*/
- int hlen = ret - (unsigned char *)s->init_buf->data - 3;
+ {
+ 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)
{
hlen = 0x200 - hlen;
- s2n(TLSEXT_TYPE_wtf,ret);
- s2n(hlen,ret);
+ if (hlen >= 4)
+ hlen -= 4;
+ else
+ hlen = 0;
+
+ s2n(TLSEXT_TYPE_padding, ret);
+ s2n(hlen, ret);
memset(ret, 0, hlen);
ret += hlen;
}
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 *p, unsigned char *limit, int *al)
{
int extdatalen=0;
unsigned char *ret = p;
+ size_t i;
+ custom_srv_ext_record *record;
#ifndef OPENSSL_NO_NEXTPROTONEG
int next_proto_neg_seen;
#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_kEECDH|SSL_kECDHr|SSL_kECDHe)) || (alg_a & SSL_aECDSA);
+ 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
/* don't add extensions for SSLv3, unless doing secure renegotiation */
}
#endif
- /* If custom types were sent in ClientHello, add ServerHello responses */
- if (s->s3->tlsext_custom_types_count)
+ for (i = 0; i < s->ctx->custom_srv_ext_records_count; i++)
{
- size_t i;
+ const unsigned char *out = NULL;
+ unsigned short outlen = 0;
+ int cb_retval = 0;
- for (i = 0; i < s->s3->tlsext_custom_types_count; i++)
- {
- size_t j;
- custom_srv_ext_record *record;
+ record = &s->ctx->custom_srv_ext_records[i];
- 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;
- }
- }
- }
+ /* NULL callback or -1 omits extension */
+ if (!record->fn2)
+ break;
+ cb_retval = record->fn2(s, record->ext_type,
+ &out, &outlen, al,
+ 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;
}
#ifdef TLSEXT_TYPE_encrypt_then_mac
if (s->s3->flags & TLS1_FLAGS_ENCRYPT_THEN_MAC)
}
/* Clear observed custom extensions */
- s->s3->tlsext_custom_types_count = 0;
- if (s->s3->tlsext_custom_types != NULL)
+ s->s3->serverinfo_client_tlsext_custom_types_count = 0;
+ if (s->s3->serverinfo_client_tlsext_custom_types != NULL)
{
- OPENSSL_free(s->s3->tlsext_custom_types);
- s->s3->tlsext_custom_types = NULL;
- }
+ OPENSSL_free(s->s3->serverinfo_client_tlsext_custom_types);
+ s->s3->serverinfo_client_tlsext_custom_types = NULL;
+ }
#ifndef OPENSSL_NO_HEARTBEATS
s->tlsext_heartbeat &= ~(SSL_TLSEXT_HB_ENABLED |
return 0;
}
}
- else if (type == TLSEXT_TYPE_status_request
- && s->ctx->tlsext_status_cb)
+ else if (type == TLSEXT_TYPE_status_request)
{
if (size < 5)
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;
}
}
}
unsigned long alg_a = s->s3->tmp.new_cipher->algorithm_auth;
if ((s->tlsext_ecpointformatlist != NULL) && (s->tlsext_ecpointformatlist_length > 0) &&
(s->session->tlsext_ecpointformatlist != NULL) && (s->session->tlsext_ecpointformatlist_length > 0) &&
- ((alg_k & (SSL_kEECDH|SSL_kECDHr|SSL_kECDHe)) || (alg_a & SSL_aECDSA)))
+ ((alg_k & (SSL_kECDHE|SSL_kECDHr|SSL_kECDHe)) || (alg_a & SSL_aECDSA)))
{
/* we are using an ECC cipher */
size_t i;