static int tls_decrypt_ticket(SSL *s, const unsigned char *tick, int ticklen,
const unsigned char *sess_id, int sesslen,
SSL_SESSION **psess);
-static int ssl_check_clienthello_tlsext(SSL *s);
+static int ssl_check_clienthello_tlsext_early(SSL *s);
int ssl_check_serverhello_tlsext(SSL *s);
#endif
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 */
return 1;
}
+static void tls1_get_formatlist(SSL *s, const unsigned char **pformats,
+ size_t *pformatslen)
+ {
+ /* If we have a custom point format list use it otherwise
+ * use default */
+ if (s->tlsext_ecpointformatlist)
+ {
+ *pformats = s->tlsext_ecpointformatlist;
+ *pformatslen = s->tlsext_ecpointformatlist_length;
+ }
+ else
+ {
+ *pformats = ecformats_default;
+ /* For Suite B we don't support char2 fields */
+ if (tls1_suiteb(s))
+ *pformatslen = sizeof(ecformats_default) - 1;
+ else
+ *pformatslen = sizeof(ecformats_default);
+ }
+ }
+
/* Check cert parameters compatible with extensions: currently just checks
* EC certificates have compatible curves and compression.
*/
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_PROTCOL)
+ 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,
c->mask_a = 0;
c->mask_k = 0;
/* If less than TLS 1.2 don't allow TLS 1.2 only ciphers */
- if (TLS1_get_version(s) < TLS1_2_VERSION)
+ if (TLS1_get_client_version(s) < TLS1_2_VERSION)
c->mask_ssl = SSL_TLSV1_2;
else
c->mask_ssl = 0;
long lenmax;
const unsigned char *plist;
size_t plistlen;
- /* If we have a custom point format list use it otherwise
- * use default */
- plist = s->tlsext_ecpointformatlist;
- if (plist)
- plistlen = s->tlsext_ecpointformatlist_length;
- else
- {
- plist = ecformats_default;
- plistlen = sizeof(ecformats_default);
- }
+
+ tls1_get_formatlist(s, &plist, &plistlen);
if ((lenmax = limit - ret - 5) < 0) return NULL;
if (plistlen > (size_t)lenmax) return NULL;
/* 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 */
#ifndef OPENSSL_NO_NEXTPROTONEG
int next_proto_neg_seen;
#endif
+ 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);
/* don't add extensions for SSLv3, unless doing secure renegotiation */
if (s->version == SSL3_VERSION && !s->s3->send_connection_binding)
}
#ifndef OPENSSL_NO_EC
- if (s->tlsext_ecpointformatlist != NULL &&
- s->version != DTLS1_VERSION)
+ if (using_ecc && s->version != DTLS1_VERSION)
{
+ const unsigned char *plist;
+ size_t plistlen;
/* Add TLS extension ECPointFormats to the ServerHello message */
long lenmax;
+ tls1_get_formatlist(s, &plist, &plistlen);
+
if ((lenmax = limit - ret - 5) < 0) return NULL;
- if (s->tlsext_ecpointformatlist_length > (unsigned long)lenmax) return NULL;
- if (s->tlsext_ecpointformatlist_length > 255)
+ if (plistlen > (size_t)lenmax) return NULL;
+ if (plistlen > 255)
{
SSLerr(SSL_F_SSL_ADD_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
return NULL;
}
s2n(TLSEXT_TYPE_ec_point_formats,ret);
- s2n(s->tlsext_ecpointformatlist_length + 1,ret);
- *(ret++) = (unsigned char) s->tlsext_ecpointformatlist_length;
- memcpy(ret, s->tlsext_ecpointformatlist, s->tlsext_ecpointformatlist_length);
- ret+=s->tlsext_ecpointformatlist_length;
+ s2n(plistlen + 1,ret);
+ *(ret++) = (unsigned char) plistlen;
+ memcpy(ret, plist, plistlen);
+ ret+=plistlen;
}
/* Currently the server should not respond with a SupportedCurves extension */
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;
int ellipticcurvelist_length = (*(sdata++) << 8);
ellipticcurvelist_length += (*(sdata++));
- if (ellipticcurvelist_length != size - 2)
+ if (ellipticcurvelist_length != size - 2 ||
+ ellipticcurvelist_length < 1)
{
*al = TLS1_AD_DECODE_ERROR;
return 0;
return 0;
}
- if (ssl_check_clienthello_tlsext(s) <= 0)
+ if (ssl_check_clienthello_tlsext_early(s) <= 0)
{
SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_TLSEXT,SSL_R_CLIENTHELLO_TLSEXT);
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;
int ssl_prepare_serverhello_tlsext(SSL *s)
{
-#ifndef OPENSSL_NO_EC
- /* If we are server and using an ECC cipher suite, send the point formats we support
- * if the client sent us an ECPointsFormat extension. Note that the server is not
- * supposed to send an EllipticCurves extension.
- */
-
- 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);
-
- if (using_ecc)
- {
- if (s->tlsext_ecpointformatlist != NULL) OPENSSL_free(s->tlsext_ecpointformatlist);
- if ((s->tlsext_ecpointformatlist = OPENSSL_malloc(3)) == NULL)
- {
- SSLerr(SSL_F_SSL_PREPARE_SERVERHELLO_TLSEXT,ERR_R_MALLOC_FAILURE);
- return -1;
- }
- s->tlsext_ecpointformatlist_length = 3;
- s->tlsext_ecpointformatlist[0] = TLSEXT_ECPOINTFORMAT_uncompressed;
- s->tlsext_ecpointformatlist[1] = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime;
- s->tlsext_ecpointformatlist[2] = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2;
- }
-#endif /* OPENSSL_NO_EC */
-
return 1;
}
-static int ssl_check_clienthello_tlsext(SSL *s)
+static int ssl_check_clienthello_tlsext_early(SSL *s)
{
int ret=SSL_TLSEXT_ERR_NOACK;
int al = SSL_AD_UNRECOGNIZED_NAME;
else if (s->initial_ctx != NULL && s->initial_ctx->tlsext_servername_callback != 0)
ret = s->initial_ctx->tlsext_servername_callback(s, &al, s->initial_ctx->tlsext_servername_arg);
- /* If status request then ask callback what to do.
- * Note: this must be called after servername callbacks in case
- * the certificate has changed.
- */
- if ((s->tlsext_status_type != -1) && s->ctx && s->ctx->tlsext_status_cb)
- {
- int r;
- r = s->ctx->tlsext_status_cb(s, s->ctx->tlsext_status_arg);
- switch (r)
- {
- /* We don't want to send a status request response */
- case SSL_TLSEXT_ERR_NOACK:
- s->tlsext_status_expected = 0;
- break;
- /* status request response should be sent */
- case SSL_TLSEXT_ERR_OK:
- if (s->tlsext_ocsp_resp)
- s->tlsext_status_expected = 1;
- else
- s->tlsext_status_expected = 0;
- break;
- /* something bad happened */
- case SSL_TLSEXT_ERR_ALERT_FATAL:
- ret = SSL_TLSEXT_ERR_ALERT_FATAL;
- al = SSL_AD_INTERNAL_ERROR;
- goto err;
- }
- }
- else
- s->tlsext_status_expected = 0;
-
#ifdef TLSEXT_TYPE_opaque_prf_input
{
/* This sort of belongs into ssl_prepare_serverhello_tlsext(),
* but we might be sending an alert in response to the client hello,
- * so this has to happen here in ssl_check_clienthello_tlsext(). */
+ * so this has to happen here in
+ * ssl_check_clienthello_tlsext_early(). */
int r = 1;
}
}
-#endif
err:
+#endif
switch (ret)
{
case SSL_TLSEXT_ERR_ALERT_FATAL:
}
}
+int ssl_check_clienthello_tlsext_late(SSL *s)
+ {
+ int ret = SSL_TLSEXT_ERR_OK;
+ int al;
+
+ /* If status request then ask callback what to do.
+ * Note: this must be called after servername callbacks in case
+ * the certificate has changed, and must be called after the cipher
+ * has been chosen because this may influence which certificate is sent
+ */
+ if ((s->tlsext_status_type != -1) && s->ctx && s->ctx->tlsext_status_cb)
+ {
+ int r;
+ CERT_PKEY *certpkey;
+ certpkey = ssl_get_server_send_pkey(s);
+ /* If no certificate can't return certificate status */
+ if (certpkey == NULL)
+ {
+ s->tlsext_status_expected = 0;
+ return 1;
+ }
+ /* Set current certificate to one we will use so
+ * SSL_get_certificate et al can pick it up.
+ */
+ s->cert->key = certpkey;
+ r = s->ctx->tlsext_status_cb(s, s->ctx->tlsext_status_arg);
+ switch (r)
+ {
+ /* We don't want to send a status request response */
+ case SSL_TLSEXT_ERR_NOACK:
+ s->tlsext_status_expected = 0;
+ break;
+ /* status request response should be sent */
+ case SSL_TLSEXT_ERR_OK:
+ if (s->tlsext_ocsp_resp)
+ s->tlsext_status_expected = 1;
+ else
+ s->tlsext_status_expected = 0;
+ break;
+ /* something bad happened */
+ case SSL_TLSEXT_ERR_ALERT_FATAL:
+ ret = SSL_TLSEXT_ERR_ALERT_FATAL;
+ al = SSL_AD_INTERNAL_ERROR;
+ goto err;
+ }
+ }
+ else
+ s->tlsext_status_expected = 0;
+
+ err:
+ switch (ret)
+ {
+ case SSL_TLSEXT_ERR_ALERT_FATAL:
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
+ return -1;
+
+ case SSL_TLSEXT_ERR_ALERT_WARNING:
+ ssl3_send_alert(s, SSL3_AL_WARNING, al);
+ return 1;
+
+ default:
+ return 1;
+ }
+ }
+
int ssl_check_serverhello_tlsext(SSL *s)
{
int ret=SSL_TLSEXT_ERR_NOACK;
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_PROTCOL)
+ if (s->cert->cert_flags & SSL_CERT_FLAG_BROKEN_PROTOCOL)
{
/* Use first set signature preference to force message
* digest, ignoring any peer preferences.
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);
}
goto end;
#ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL
/* Allow any certificate to pass test */
- if (s->cert->cert_flags & SSL_CERT_FLAG_BROKEN_PROTCOL)
+ 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;