c->mask_a = 0;
c->mask_k = 0;
/* Don't allow TLS 1.2 only ciphers if we don't suppport them */
- if (!SSL_USE_TLS1_2_CIPHERS(s))
+ if (!SSL_CLIENT_USE_TLS1_2_CIPHERS(s))
c->mask_ssl = SSL_TLSV1_2;
else
c->mask_ssl = 0;
*(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;
}
}
+ /* 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;
}
}
+ /* 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;
}
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;
}