ncb.nidcnt = 0;
if (!CONF_parse_list(str, ':', 1, nid_cb, &ncb))
return 0;
+ if (pext == NULL)
+ return 1;
return tls1_set_curves(pext, pextlen, ncb.nid_arr, ncb.nidcnt);
}
/* For an EC key set TLS id and required compression based on parameters */
{
unsigned char curve_id[2];
EC_KEY *ec = s->cert->ecdh_tmp;
+#ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL
+ /* Allow any curve: not just those peer supports */
+ if (s->cert->cert_flags & SSL_CERT_FLAG_BROKEN_PROTOCOL)
+ return 1;
+#endif
/* If Suite B, AES128 MUST use P-256 and AES256 MUST use P-384,
* no other curves permitted.
*/
#endif
}
+#else
+
+static int tls1_check_cert_param(SSL *s, X509 *x, int set_ee_md)
+ {
+ return 1;
+ }
+
#endif /* OPENSSL_NO_EC */
#ifndef OPENSSL_NO_TLSEXT
tlsext_sigalg_rsa(TLSEXT_hash_md5)
#endif
};
-
+#ifndef OPENSSL_NO_ECDSA
static unsigned char suiteb_sigalgs[] = {
tlsext_sigalg_ecdsa(TLSEXT_hash_sha256)
tlsext_sigalg_ecdsa(TLSEXT_hash_sha384)
};
-
+#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
switch (tls1_suiteb(s))
{
case SSL_CERT_FLAG_SUITEB_128_LOS:
*psigs = suiteb_sigalgs + 2;
return 2;
}
-
+#endif
/* If server use client authentication sigalgs if not NULL */
if (s->server && s->cert->client_sigalgs)
{
SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG,SSL_R_WRONG_SIGNATURE_TYPE);
return 0;
}
+#ifndef OPENSSL_NO_EC
if (pkey->type == EVP_PKEY_EC)
{
unsigned char curve_id[2], comp_id;
if (!tls1_set_ec_id(curve_id, &comp_id, pkey->pkey.ec))
return 0;
if (!s->server && !tls1_check_ec_key(s, curve_id, &comp_id))
+ {
+ SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG,SSL_R_WRONG_CURVE);
return 0;
+ }
/* If Suite B only P-384+SHA384 or P-256+SHA-256 allowed */
if (tls1_suiteb(s))
{
}
else if (tls1_suiteb(s))
return 0;
+#endif
/* Check signature matches a type we sent */
sent_sigslen = tls12_get_psigalgs(s, &sent_sigs);
/* 1 byte for the list (we only support audit proofs) */
if (s->ctx->tlsext_authz_server_audit_proof_cb != NULL)
{
- size_t lenmax;
const unsigned short ext_len = 2;
const unsigned char list_len = 1;
- if ((lenmax = limit - ret - 6) < 0) return NULL;
+ if (limit < ret + 6)
+ return NULL;
s2n(TLSEXT_TYPE_server_authz, ret);
/* Extension length: 2 bytes */
*(ret++) = TLSEXT_AUTHZDATAFORMAT_audit_proof;
}
+ /* Add custom TLS Extensions to ClientHello */
+ 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++)
+ {
+ const unsigned char* out = NULL;
+ unsigned short outlen = 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;
+ }
+ }
+
if ((extdatalen = ret-p-2) == 0)
return p;
#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);
using_ecc = using_ecc && (s->session->tlsext_ecpointformatlist != NULL);
-
+#endif
/* don't add extensions for SSLv3, unless doing secure renegotiation */
if (s->version == SSL3_VERSION && !s->s3->send_connection_binding)
return p;
}
}
+ /* 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 ((extdatalen = ret-p-2)== 0)
return p;
return ret;
}
+#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|.
+ * Safari, since 10.6, sends exactly these extensions, in this order:
+ * SNI,
+ * elliptic_curves
+ * ec_point_formats
+ *
+ * We wish to fingerprint Safari because they broke ECDHE-ECDSA support in 10.8,
+ * but they advertise support. So enabling ECDHE-ECDSA ciphers breaks them.
+ * 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) {
+ unsigned short type, size;
+ static const unsigned char kSafariExtensionsBlock[] = {
+ 0x00, 0x0a, /* elliptic_curves extension */
+ 0x00, 0x08, /* 8 bytes */
+ 0x00, 0x06, /* 6 bytes of curve ids */
+ 0x00, 0x17, /* P-256 */
+ 0x00, 0x18, /* P-384 */
+ 0x00, 0x19, /* P-521 */
+
+ 0x00, 0x0b, /* ec_point_formats */
+ 0x00, 0x02, /* 2 bytes */
+ 0x01, /* 1 point format */
+ 0x00, /* uncompressed */
+ };
+
+ /* The following is only present in TLS 1.2 */
+ static const unsigned char kSafariTLS12ExtensionsBlock[] = {
+ 0x00, 0x0d, /* signature_algorithms */
+ 0x00, 0x0c, /* 12 bytes */
+ 0x00, 0x0a, /* 10 bytes */
+ 0x05, 0x01, /* SHA-384/RSA */
+ 0x04, 0x01, /* SHA-256/RSA */
+ 0x02, 0x01, /* SHA-1/RSA */
+ 0x04, 0x03, /* SHA-256/ECDSA */
+ 0x02, 0x03, /* SHA-1/ECDSA */
+ };
+
+ if (data >= (d+n-2))
+ return;
+ data += 2;
+
+ if (data > (d+n-4))
+ 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)
+ return;
+ if (memcmp(data, kSafariExtensionsBlock, len1) != 0)
+ return;
+ if (memcmp(data + len1, kSafariTLS12ExtensionsBlock, len2) != 0)
+ return;
+ }
+ else
+ {
+ const size_t len = sizeof(kSafariExtensionsBlock);
+
+ if (data + len != d+n)
+ return;
+ if (memcmp(data, kSafariExtensionsBlock, len) != 0)
+ return;
+ }
+
+ s->s3->is_probably_safari = 1;
+}
+#endif /* !OPENSSL_NO_EC */
+
static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, int n, int *al)
{
unsigned short type;
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;
+ }
+
#ifndef OPENSSL_NO_HEARTBEATS
s->tlsext_heartbeat &= ~(SSL_TLSEXT_HB_ENABLED |
SSL_TLSEXT_HB_DONT_SEND_REQUESTS);
#endif
+
+#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 */
+
/* Clear any signature algorithms extension received */
if (s->cert->peer_sigalgs)
{
unsigned char *sdata = data;
int ecpointformatlist_length = *(sdata++);
- if (ecpointformatlist_length != size - 1)
+ if (ecpointformatlist_length != size - 1 ||
+ ecpointformatlist_length < 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;
}
unsigned char *sdata = data;
int ecpointformatlist_length = *(sdata++);
- if (ecpointformatlist_length != size - 1 ||
- ecpointformatlist_length < 1)
+ if (ecpointformatlist_length != size - 1)
{
*al = TLS1_AD_DECODE_ERROR;
return 0;
unsigned char selected_len;
/* We must have requested it. */
- if ((s->ctx->next_proto_select_cb == NULL))
+ if (s->ctx->next_proto_select_cb == NULL)
{
*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;
+ }
+ }
+ }
data += size;
}
switch (ret)
{
case SSL_TLSEXT_ERR_ALERT_FATAL:
- ssl3_send_alert(s, SSL3_AL_FATAL,al);
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
return -1;
case SSL_TLSEXT_ERR_ALERT_WARNING:
- ssl3_send_alert(s, SSL3_AL_WARNING,al);
+ ssl3_send_alert(s, SSL3_AL_WARNING, al);
return 1;
default:
HMAC_Update(&hctx, etick, eticklen);
HMAC_Final(&hctx, tick_hmac, NULL);
HMAC_CTX_cleanup(&hctx);
- if (memcmp(tick_hmac, etick + eticklen, mlen))
+ if (CRYPTO_memcmp(tick_hmac, etick + eticklen, mlen))
return 2;
/* Attempt to decrypt session data */
/* Move p after IV to start of encrypted ticket, update length */
tls1_set_shared_sigalgs(s);
+#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, ignoring any peer preferences.
+ */
+ const unsigned char *sigs = NULL;
+ if (s->server)
+ sigs = c->conf_sigalgs;
+ else
+ sigs = c->client_sigalgs;
+ if (sigs)
+ {
+ idx = tls12_get_pkey_idx(sigs[1]);
+ md = tls12_get_hash(sigs[0]);
+ c->pkeys[idx].digest = md;
+ c->pkeys[idx].valid_flags = CERT_PKEY_EXPLICIT_SIGN;
+ if (idx == SSL_PKEY_RSA_SIGN)
+ {
+ c->pkeys[SSL_PKEY_RSA_ENC].valid_flags = CERT_PKEY_EXPLICIT_SIGN;
+ c->pkeys[SSL_PKEY_RSA_ENC].digest = md;
+ }
+ }
+ }
+#endif
+
for (i = 0, sigptr = c->shared_sigalgs;
i < c->shared_sigalgslen; i++, sigptr++)
{
sig.sigalgcnt = 0;
if (!CONF_parse_list(str, ':', 1, sig_cb, &sig))
return 0;
+ if (c == NULL)
+ return 1;
return tls1_set_sigalgs(c, sig.sigalgs, sig.sigalgcnt, client);
}
/* If no cert or key, forget it */
if (!x || !pk)
goto end;
+#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|CERT_PKEY_VALID|CERT_PKEY_SIGN;
+ cpk->valid_flags = rv;
+ return rv;
+ }
+#endif
}
else
{