*/
#include <stdio.h>
+#include <stdlib.h>
#include <openssl/objects.h>
#include <openssl/evp.h>
#include <openssl/hmac.h>
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);
+static int ssl_check_serverhello_tlsext(SSL *s);
SSL3_ENC_METHOD const TLSv1_enc_data = {
tls1_enc,
*/
int tls1_check_ec_tmp_key(SSL *s, unsigned long cid)
{
-# 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.
return ssl_security(s, SSL_SECOP_TICKET, 0, 0, NULL);
}
+static int compare_uint(const void *p1, const void *p2) {
+ unsigned int u1 = *((const unsigned int *)p1);
+ unsigned int u2 = *((const unsigned int *)p2);
+ if (u1 < u2)
+ return -1;
+ else if (u1 > u2)
+ return 1;
+ else
+ return 0;
+}
+
+/*
+ * Per http://tools.ietf.org/html/rfc5246#section-7.4.1.4, there may not be
+ * more than one extension of the same type in a ClientHello or ServerHello.
+ * This function does an initial scan over the extensions block to filter those
+ * out. It returns 1 if all extensions are unique, and 0 if the extensions
+ * contain duplicates, could not be successfully parsed, or an internal error
+ * occurred.
+ */
+static int tls1_check_duplicate_extensions(const PACKET *packet) {
+ PACKET extensions = *packet;
+ size_t num_extensions = 0, i = 0;
+ unsigned int *extension_types = NULL;
+ int ret = 0;
+
+ /* First pass: count the extensions. */
+ while (PACKET_remaining(&extensions) > 0) {
+ unsigned int type;
+ PACKET extension;
+ if (!PACKET_get_net_2(&extensions, &type) ||
+ !PACKET_get_length_prefixed_2(&extensions, &extension)) {
+ goto done;
+ }
+ num_extensions++;
+ }
+
+ if (num_extensions <= 1)
+ return 1;
+
+ extension_types = OPENSSL_malloc(sizeof(unsigned int) * num_extensions);
+ if (extension_types == NULL) {
+ SSLerr(SSL_F_TLS1_CHECK_DUPLICATE_EXTENSIONS, ERR_R_MALLOC_FAILURE);
+ goto done;
+ }
+
+ /* Second pass: gather the extension types. */
+ extensions = *packet;
+ for (i = 0; i < num_extensions; i++) {
+ PACKET extension;
+ if (!PACKET_get_net_2(&extensions, &extension_types[i]) ||
+ !PACKET_get_length_prefixed_2(&extensions, &extension)) {
+ /* This should not happen. */
+ SSLerr(SSL_F_TLS1_CHECK_DUPLICATE_EXTENSIONS, ERR_R_INTERNAL_ERROR);
+ goto done;
+ }
+ }
+
+ if (PACKET_remaining(&extensions) != 0) {
+ SSLerr(SSL_F_TLS1_CHECK_DUPLICATE_EXTENSIONS, ERR_R_INTERNAL_ERROR);
+ goto done;
+ }
+ /* Sort the extensions and make sure there are no duplicates. */
+ qsort(extension_types, num_extensions, sizeof(unsigned int), compare_uint);
+ for (i = 1; i < num_extensions; i++) {
+ if (extension_types[i - 1] == extension_types[i])
+ goto done;
+ }
+ ret = 1;
+ done:
+ OPENSSL_free(extension_types);
+ return ret;
+}
+
unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *buf,
unsigned char *limit, int *al)
{
if (PACKET_remaining(pkt) != len)
goto err;
+ if (!tls1_check_duplicate_extensions(pkt))
+ goto err;
+
while (PACKET_get_net_2(pkt, &type) && PACKET_get_net_2(pkt, &size)) {
PACKET subpkt;
return 0;
}
+ if (!tls1_check_duplicate_extensions(pkt)) {
+ *al = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+
while (PACKET_get_net_2(pkt, &type) && PACKET_get_net_2(pkt, &size)) {
const unsigned char *data;
PACKET spkt;
if (!tls1_set_shared_sigalgs(s))
return 0;
-#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]);
- pmd[idx] = md;
- pvalid[idx] = CERT_PKEY_EXPLICIT_SIGN;
- if (idx == SSL_PKEY_RSA_SIGN) {
- pvalid[SSL_PKEY_RSA_ENC] = CERT_PKEY_EXPLICIT_SIGN;
- pmd[SSL_PKEY_RSA_ENC] = md;
- }
- }
- }
-#endif
-
for (i = 0, sigptr = c->shared_sigalgs;
i < c->shared_sigalgslen; i++, sigptr++) {
idx = tls12_get_pkey_idx(sigptr->rsign);
/* 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;
- *pvalid = rv;
- return rv;
- }
-#endif
} else {
if (!x || !pk)
return 0;