*/
#include <stdio.h>
-#include <time.h>
-#include <openssl/bio.h>
#include <openssl/objects.h>
#include <openssl/evp.h>
#include <openssl/hmac.h>
#include <openssl/ocsp.h>
-#include <openssl/o_time.h>
#include <openssl/rand.h>
+#ifndef OPENSSL_NO_DH
+#include <openssl/dh.h>
+#include <openssl/bn.h>
+#endif
#include "ssl_locl.h"
const char tls1_version_str[]="TLSv1" OPENSSL_VERSION_PTEXT;
int ssl_check_serverhello_tlsext(SSL *s);
#endif
-SSL3_ENC_METHOD TLSv1_enc_data={
+SSL3_ENC_METHOD const TLSv1_enc_data={
tls1_enc,
tls1_mac,
tls1_setup_key_block,
ssl3_handshake_write
};
-SSL3_ENC_METHOD TLSv1_1_enc_data={
+SSL3_ENC_METHOD const TLSv1_1_enc_data={
tls1_enc,
tls1_mac,
tls1_setup_key_block,
ssl3_handshake_write
};
-SSL3_ENC_METHOD TLSv1_2_enc_data={
+SSL3_ENC_METHOD const TLSv1_2_enc_data={
tls1_enc,
tls1_mac,
tls1_setup_key_block,
#ifndef OPENSSL_NO_EC
-static int nid_list[] =
+typedef struct
+ {
+ int nid; /* Curve NID */
+ int secbits; /* Bits of security (from SP800-57) */
+ unsigned int flags; /* Flags: currently just field type */
+ } tls_curve_info;
+
+#define TLS_CURVE_CHAR2 0x1
+#define TLS_CURVE_PRIME 0x0
+
+static const tls_curve_info nid_list[] =
{
- NID_sect163k1, /* sect163k1 (1) */
- NID_sect163r1, /* sect163r1 (2) */
- NID_sect163r2, /* sect163r2 (3) */
- NID_sect193r1, /* sect193r1 (4) */
- NID_sect193r2, /* sect193r2 (5) */
- NID_sect233k1, /* sect233k1 (6) */
- NID_sect233r1, /* sect233r1 (7) */
- NID_sect239k1, /* sect239k1 (8) */
- NID_sect283k1, /* sect283k1 (9) */
- NID_sect283r1, /* sect283r1 (10) */
- NID_sect409k1, /* sect409k1 (11) */
- NID_sect409r1, /* sect409r1 (12) */
- NID_sect571k1, /* sect571k1 (13) */
- NID_sect571r1, /* sect571r1 (14) */
- NID_secp160k1, /* secp160k1 (15) */
- NID_secp160r1, /* secp160r1 (16) */
- NID_secp160r2, /* secp160r2 (17) */
- NID_secp192k1, /* secp192k1 (18) */
- NID_X9_62_prime192v1, /* secp192r1 (19) */
- NID_secp224k1, /* secp224k1 (20) */
- NID_secp224r1, /* secp224r1 (21) */
- NID_secp256k1, /* secp256k1 (22) */
- NID_X9_62_prime256v1, /* secp256r1 (23) */
- NID_secp384r1, /* secp384r1 (24) */
- NID_secp521r1, /* secp521r1 (25) */
- NID_brainpoolP256r1, /* brainpoolP256r1 (26) */
- NID_brainpoolP384r1, /* brainpoolP384r1 (27) */
- NID_brainpoolP512r1 /* brainpool512r1 (28) */
+ {NID_sect163k1, 80, TLS_CURVE_CHAR2},/* sect163k1 (1) */
+ {NID_sect163r1, 80, TLS_CURVE_CHAR2},/* sect163r1 (2) */
+ {NID_sect163r2, 80, TLS_CURVE_CHAR2},/* sect163r2 (3) */
+ {NID_sect193r1, 80, TLS_CURVE_CHAR2},/* sect193r1 (4) */
+ {NID_sect193r2, 80, TLS_CURVE_CHAR2},/* sect193r2 (5) */
+ {NID_sect233k1, 112, TLS_CURVE_CHAR2},/* sect233k1 (6) */
+ {NID_sect233r1, 112, TLS_CURVE_CHAR2},/* sect233r1 (7) */
+ {NID_sect239k1, 112, TLS_CURVE_CHAR2},/* sect239k1 (8) */
+ {NID_sect283k1, 128, TLS_CURVE_CHAR2},/* sect283k1 (9) */
+ {NID_sect283r1, 128, TLS_CURVE_CHAR2},/* sect283r1 (10) */
+ {NID_sect409k1, 192, TLS_CURVE_CHAR2},/* sect409k1 (11) */
+ {NID_sect409r1, 192, TLS_CURVE_CHAR2},/* sect409r1 (12) */
+ {NID_sect571k1, 256, TLS_CURVE_CHAR2},/* sect571k1 (13) */
+ {NID_sect571r1, 256, TLS_CURVE_CHAR2},/* sect571r1 (14) */
+ {NID_secp160k1, 80, TLS_CURVE_PRIME},/* secp160k1 (15) */
+ {NID_secp160r1, 80, TLS_CURVE_PRIME},/* secp160r1 (16) */
+ {NID_secp160r2, 80, TLS_CURVE_PRIME},/* secp160r2 (17) */
+ {NID_secp192k1, 80, TLS_CURVE_PRIME},/* secp192k1 (18) */
+ {NID_X9_62_prime192v1, 80, TLS_CURVE_PRIME},/* secp192r1 (19) */
+ {NID_secp224k1, 112, TLS_CURVE_PRIME},/* secp224k1 (20) */
+ {NID_secp224r1, 112, TLS_CURVE_PRIME},/* secp224r1 (21) */
+ {NID_secp256k1, 128, TLS_CURVE_PRIME},/* secp256k1 (22) */
+ {NID_X9_62_prime256v1, 128, TLS_CURVE_PRIME},/* secp256r1 (23) */
+ {NID_secp384r1, 192, TLS_CURVE_PRIME},/* secp384r1 (24) */
+ {NID_secp521r1, 256, TLS_CURVE_PRIME},/* secp521r1 (25) */
+ {NID_brainpoolP256r1, 128, TLS_CURVE_PRIME}, /* brainpoolP256r1 (26) */
+ {NID_brainpoolP384r1, 192, TLS_CURVE_PRIME}, /* brainpoolP384r1 (27) */
+ {NID_brainpoolP512r1, 256, TLS_CURVE_PRIME},/* brainpool512r1 (28) */
};
int tls1_ec_curve_id2nid(int curve_id)
{
- /* ECC curves from draft-ietf-tls-ecc-12.txt (Oct. 17, 2005) */
+ /* ECC curves from RFC 4492 and RFC 7027 */
if ((curve_id < 1) || ((unsigned int)curve_id >
sizeof(nid_list)/sizeof(nid_list[0])))
return 0;
- return nid_list[curve_id-1];
+ return nid_list[curve_id-1].nid;
}
int tls1_ec_nid2curve_id(int nid)
{
- /* ECC curves from draft-ietf-tls-ecc-12.txt (Oct. 17, 2005) */
+ /* ECC curves from RFC 4492 and RFC 7027 */
switch (nid)
{
case NID_sect163k1: /* sect163k1 (1) */
return 0;
}
}
-/* Get curves list, if "sess" is set return client curves otherwise
- * preferred list
+/*
+ * Get curves list, if "sess" is set return client curves otherwise
+ * preferred list.
+ * Sets |num_curves| to the number of curves in the list, i.e.,
+ * the length of |pcurves| is 2 * num_curves.
+ * Returns 1 on success and 0 if the client curves list has invalid format.
+ * The latter indicates an internal error: we should not be accepting such
+ * lists in the first place.
+ * TODO(emilia): we should really be storing the curves list in explicitly
+ * parsed form instead. (However, this would affect binary compatibility
+ * so cannot happen in the 1.0.x series.)
*/
-static void tls1_get_curvelist(SSL *s, int sess,
+static int tls1_get_curvelist(SSL *s, int sess,
const unsigned char **pcurves,
- size_t *pcurveslen)
+ size_t *num_curves)
{
+ size_t pcurveslen = 0;
if (sess)
{
*pcurves = s->session->tlsext_ellipticcurvelist;
- *pcurveslen = s->session->tlsext_ellipticcurvelist_length;
- return;
+ pcurveslen = s->session->tlsext_ellipticcurvelist_length;
}
- /* For Suite B mode only include P-256, P-384 */
- switch (tls1_suiteb(s))
+ else
{
- case SSL_CERT_FLAG_SUITEB_128_LOS:
- *pcurves = suiteb_curves;
- *pcurveslen = sizeof(suiteb_curves);
- break;
+ /* For Suite B mode only include P-256, P-384 */
+ switch (tls1_suiteb(s))
+ {
+ case SSL_CERT_FLAG_SUITEB_128_LOS:
+ *pcurves = suiteb_curves;
+ pcurveslen = sizeof(suiteb_curves);
+ break;
- case SSL_CERT_FLAG_SUITEB_128_LOS_ONLY:
- *pcurves = suiteb_curves;
- *pcurveslen = 2;
- break;
+ case SSL_CERT_FLAG_SUITEB_128_LOS_ONLY:
+ *pcurves = suiteb_curves;
+ pcurveslen = 2;
+ break;
- case SSL_CERT_FLAG_SUITEB_192_LOS:
- *pcurves = suiteb_curves + 2;
- *pcurveslen = 2;
- break;
- default:
- *pcurves = s->tlsext_ellipticcurvelist;
- *pcurveslen = s->tlsext_ellipticcurvelist_length;
+ case SSL_CERT_FLAG_SUITEB_192_LOS:
+ *pcurves = suiteb_curves + 2;
+ pcurveslen = 2;
+ break;
+ default:
+ *pcurves = s->tlsext_ellipticcurvelist;
+ pcurveslen = s->tlsext_ellipticcurvelist_length;
+ }
+ if (!*pcurves)
+ {
+ *pcurves = eccurves_default;
+ pcurveslen = sizeof(eccurves_default);
+ }
}
- if (!*pcurves)
+
+ /* We do not allow odd length arrays to enter the system. */
+ if (pcurveslen & 1)
{
- *pcurves = eccurves_default;
- *pcurveslen = sizeof(eccurves_default);
+ SSLerr(SSL_F_TLS1_GET_CURVELIST, ERR_R_INTERNAL_ERROR);
+ *num_curves = 0;
+ return 0;
+ }
+ else
+ {
+ *num_curves = pcurveslen / 2;
+ return 1;
}
}
+
+/* See if curve is allowed by security callback */
+static int tls_curve_allowed(SSL *s, const unsigned char *curve, int op)
+ {
+ const tls_curve_info *cinfo;
+ if (curve[0])
+ return 1;
+ if ((curve[1] < 1) || ((size_t)curve[1] >
+ sizeof(nid_list)/sizeof(nid_list[0])))
+ return 0;
+ cinfo = &nid_list[curve[1]-1];
+#ifdef OPENSSL_NO_EC2M
+ if (cinfo->flags & TLS_CURVE_CHAR2)
+ return 0;
+#endif
+ return ssl_security(s, op, cinfo->secbits, cinfo->nid, (void *)curve);
+ }
+
/* Check a curve is one of our preferences */
int tls1_check_curve(SSL *s, const unsigned char *p, size_t len)
{
const unsigned char *curves;
- size_t curveslen, i;
+ size_t num_curves, i;
unsigned int suiteb_flags = tls1_suiteb(s);
if (len != 3 || p[0] != NAMED_CURVE_TYPE)
return 0;
else /* Should never happen */
return 0;
}
- tls1_get_curvelist(s, 0, &curves, &curveslen);
- for (i = 0; i < curveslen; i += 2, curves += 2)
+ if (!tls1_get_curvelist(s, 0, &curves, &num_curves))
+ return 0;
+ for (i = 0; i < num_curves; i++, curves += 2)
{
if (p[1] == curves[0] && p[2] == curves[1])
- return 1;
+ return tls_curve_allowed(s, p + 1, SSL_SECOP_CURVE_CHECK);
}
return 0;
}
-/* Return nth shared curve. If nmatch == -1 return number of
- * matches. For nmatch == -2 return the NID of the curve to use for
- * an EC tmp key.
+/*-
+ * Return |nmatch|th shared curve or NID_undef if there is no match.
+ * For nmatch == -1, return number of matches
+ * For nmatch == -2, return the NID of the curve to use for
+ * an EC tmp key, or NID_undef if there is no match.
*/
-
int tls1_shared_curve(SSL *s, int nmatch)
{
const unsigned char *pref, *supp;
- size_t preflen, supplen, i, j;
+ size_t num_pref, num_supp, i, j;
int k;
/* Can't do anything on client side */
if (s->server == 0)
/* If not Suite B just return first preference shared curve */
nmatch = 0;
}
- tls1_get_curvelist(s, !!(s->options & SSL_OP_CIPHER_SERVER_PREFERENCE),
- &supp, &supplen);
- tls1_get_curvelist(s, !(s->options & SSL_OP_CIPHER_SERVER_PREFERENCE),
- &pref, &preflen);
- preflen /= 2;
- supplen /= 2;
+ /*
+ * Avoid truncation. tls1_get_curvelist takes an int
+ * but s->options is a long...
+ */
+ if (!tls1_get_curvelist(s, (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE) != 0,
+ &supp, &num_supp))
+ /* In practice, NID_undef == 0 but let's be precise. */
+ return nmatch == -1 ? 0 : NID_undef;
+ if(!tls1_get_curvelist(s, !(s->options & SSL_OP_CIPHER_SERVER_PREFERENCE),
+ &pref, &num_pref))
+ return nmatch == -1 ? 0 : NID_undef;
k = 0;
- for (i = 0; i < preflen; i++, pref+=2)
+ for (i = 0; i < num_pref; i++, pref+=2)
{
const unsigned char *tsupp = supp;
- for (j = 0; j < supplen; j++, tsupp+=2)
+ for (j = 0; j < num_supp; j++, tsupp+=2)
{
if (pref[0] == tsupp[0] && pref[1] == tsupp[1])
{
+ if (!tls_curve_allowed(s, pref, SSL_SECOP_CURVE_SHARED))
+ continue;
if (nmatch == k)
{
int id = (pref[0] << 8) | pref[1];
}
if (nmatch == -1)
return k;
- return 0;
+ /* Out of range (nmatch > k). */
+ return NID_undef;
}
int tls1_set_curves(unsigned char **pext, size_t *pextlen,
static int tls1_check_ec_key(SSL *s,
unsigned char *curve_id, unsigned char *comp_id)
{
- const unsigned char *p;
- size_t plen, i;
+ const unsigned char *pformats, *pcurves;
+ size_t num_formats, num_curves, i;
int j;
/* If point formats extension present check it, otherwise everything
* is supported (see RFC4492).
*/
if (comp_id && s->session->tlsext_ecpointformatlist)
{
- p = s->session->tlsext_ecpointformatlist;
- plen = s->session->tlsext_ecpointformatlist_length;
- for (i = 0; i < plen; i++, p++)
+ pformats = s->session->tlsext_ecpointformatlist;
+ num_formats = s->session->tlsext_ecpointformatlist_length;
+ for (i = 0; i < num_formats; i++, pformats++)
{
- if (*comp_id == *p)
+ if (*comp_id == *pformats)
break;
}
- if (i == plen)
+ if (i == num_formats)
return 0;
}
if (!curve_id)
/* Check curve is consistent with client and server preferences */
for (j = 0; j <= 1; j++)
{
- tls1_get_curvelist(s, j, &p, &plen);
- for (i = 0; i < plen; i+=2, p+=2)
+ if (!tls1_get_curvelist(s, j, &pcurves, &num_curves))
+ return 0;
+ for (i = 0; i < num_curves; i++, pcurves += 2)
{
- if (p[0] == curve_id[0] && p[1] == curve_id[1])
+ if (pcurves[0] == curve_id[0] &&
+ pcurves[1] == curve_id[1])
break;
}
- if (i == plen)
+ if (i == num_curves)
return 0;
/* For clients can only check sent curve list */
if (!s->server)
- return 1;
+ break;
}
return 1;
}
static void tls1_get_formatlist(SSL *s, const unsigned char **pformats,
- size_t *pformatslen)
+ size_t *num_formats)
{
/* 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;
+ *num_formats = 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;
+ *num_formats = sizeof(ecformats_default) - 1;
else
- *pformatslen = sizeof(ecformats_default);
+ *num_formats = sizeof(ecformats_default);
}
}
}
return rv;
}
+#ifndef OPENSSL_NO_ECDH
/* Check EC temporary key is compatible with client extensions */
int tls1_check_ec_tmp_key(SSL *s, unsigned long cid)
{
return tls1_check_ec_key(s, curve_id, NULL);
#endif
}
+#endif /* OPENSSL_NO_ECDH */
#else
tlsext_sigalg_dsa(md) \
tlsext_sigalg_ecdsa(md)
-static unsigned char tls12_sigalgs[] = {
+static const unsigned char tls12_sigalgs[] = {
#ifndef OPENSSL_NO_SHA512
tlsext_sigalg(TLSEXT_hash_sha512)
tlsext_sigalg(TLSEXT_hash_sha384)
#endif
};
#ifndef OPENSSL_NO_ECDSA
-static unsigned char suiteb_sigalgs[] = {
+static const unsigned char suiteb_sigalgs[] = {
tlsext_sigalg_ecdsa(TLSEXT_hash_sha256)
tlsext_sigalg_ecdsa(TLSEXT_hash_sha384)
};
SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG,SSL_R_UNKNOWN_DIGEST);
return 0;
}
+ /* Make sure security callback allows algorithm */
+ if (!ssl_security(s, SSL_SECOP_SIGALG_CHECK,
+ EVP_MD_size(*pmd) * 4, EVP_MD_type(*pmd),
+ (void *)sig))
+ {
+ SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG,SSL_R_WRONG_SIGNATURE_TYPE);
+ return 0;
+ }
/* Store the digest used so applications can retrieve it if they
* wish.
*/
s->session->sess_cert->peer_key->digest = *pmd;
return 1;
}
+
/* Get a mask of disabled algorithms: an algorithm is disabled
* if it isn't supported or doesn't appear in supported signature
* algorithms. Unlike ssl_cipher_get_disabled this applies to a specific
void ssl_set_client_disabled(SSL *s)
{
CERT *c = s->cert;
- const unsigned char *sigalgs;
- size_t i, sigalgslen;
- int have_rsa = 0, have_dsa = 0, have_ecdsa = 0;
c->mask_a = 0;
c->mask_k = 0;
/* Don't allow TLS 1.2 only ciphers if we don't suppport them */
c->mask_ssl = SSL_TLSV1_2;
else
c->mask_ssl = 0;
- /* Now go through all signature algorithms seeing if we support
- * any for RSA, DSA, ECDSA. Do this for all versions not just
- * TLS 1.2.
- */
- sigalgslen = tls12_get_psigalgs(s, &sigalgs);
- for (i = 0; i < sigalgslen; i += 2, sigalgs += 2)
- {
- switch(sigalgs[1])
- {
-#ifndef OPENSSL_NO_RSA
- case TLSEXT_signature_rsa:
- have_rsa = 1;
- break;
-#endif
-#ifndef OPENSSL_NO_DSA
- case TLSEXT_signature_dsa:
- have_dsa = 1;
- break;
-#endif
-#ifndef OPENSSL_NO_ECDSA
- case TLSEXT_signature_ecdsa:
- have_ecdsa = 1;
- break;
-#endif
- }
- }
- /* Disable auth and static DH if we don't include any appropriate
+ ssl_set_sig_mask(&c->mask_a, s, SSL_SECOP_SIGALG_MASK);
+ /* Disable static DH if we don't include any appropriate
* signature algorithms.
*/
- if (!have_rsa)
- {
- c->mask_a |= SSL_aRSA;
+ if (c->mask_a & SSL_aRSA)
c->mask_k |= SSL_kDHr|SSL_kECDHr;
- }
- if (!have_dsa)
- {
- c->mask_a |= SSL_aDSS;
+ if (c->mask_a & SSL_aDSS)
c->mask_k |= SSL_kDHd;
- }
- if (!have_ecdsa)
- {
- c->mask_a |= SSL_aECDSA;
+ if (c->mask_a & SSL_aECDSA)
c->mask_k |= SSL_kECDHe;
- }
#ifndef OPENSSL_NO_KRB5
if (!kssl_tgt_is_available(s->kssl_ctx))
{
c->mask_k |= SSL_kPSK;
}
#endif /* OPENSSL_NO_PSK */
+#ifndef OPENSSL_NO_SRP
+ if (!(s->srp_ctx.srp_Mask & SSL_kSRP))
+ {
+ c->mask_a |= SSL_aSRP;
+ c->mask_k |= SSL_kSRP;
+ }
+#endif
c->valid = 1;
}
-unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned char *limit, int *al)
+int ssl_cipher_disabled(SSL *s, const SSL_CIPHER *c, int op)
+ {
+ CERT *ct = s->cert;
+ if (c->algorithm_ssl & ct->mask_ssl || c->algorithm_mkey & ct->mask_k || c->algorithm_auth & ct->mask_a)
+ return 1;
+ return !ssl_security(s, op, c->strength_bits, 0, (void *)c);
+ }
+
+static int tls_use_ticket(SSL *s)
+ {
+ if (s->options & SSL_OP_NO_TICKET)
+ return 0;
+ return ssl_security(s, SSL_SECOP_TICKET, 0, 0, NULL);
+ }
+
+unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *buf, unsigned char *limit, int *al)
{
int extdatalen=0;
- unsigned char *ret = p;
+ unsigned char *orig = buf;
+ unsigned char *ret = buf;
#ifndef OPENSSL_NO_EC
/* See if we support any ECC ciphersuites */
int using_ecc = 0;
}
#endif
- /* don't add extensions for SSLv3 unless doing secure renegotiation */
- if (s->client_version == SSL3_VERSION
- && !s->s3->send_connection_binding)
- return p;
-
ret+=2;
if (ret>=limit) return NULL; /* this really never occurs, but ... */
+ /* Add RI if renegotiating */
+ if (s->renegotiate)
+ {
+ int el;
+
+ if(!ssl_add_clienthello_renegotiate_ext(s, 0, &el, 0))
+ {
+ SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
+ return NULL;
+ }
+
+ if((limit - ret - 4 - el) < 0) return NULL;
+
+ s2n(TLSEXT_TYPE_renegotiate,ret);
+ s2n(el,ret);
+
+ if(!ssl_add_clienthello_renegotiate_ext(s, ret, &el, el))
+ {
+ SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
+ return NULL;
+ }
+
+ ret += el;
+ }
+ /* Only add RI for SSLv3 */
+ if (s->client_version == SSL3_VERSION)
+ goto done;
+
if (s->tlsext_hostname != NULL)
{
/* Add TLS extension servername to the Client Hello message */
unsigned long size_str;
long lenmax;
- /* check for enough space.
- 4 for the servername type and entension length
- 2 for servernamelist length
- 1 for the hostname type
- 2 for hostname length
- + hostname length
- */
+ /*-
+ * check for enough space.
+ * 4 for the servername type and entension length
+ * 2 for servernamelist length
+ * 1 for the hostname type
+ * 2 for hostname length
+ * + hostname length
+ */
if ((lenmax = limit - ret - 9) < 0
|| (size_str = strlen(s->tlsext_hostname)) > (unsigned long)lenmax)
ret+=size_str;
}
- /* Add RI if renegotiating */
- if (s->renegotiate)
- {
- int el;
-
- if(!ssl_add_clienthello_renegotiate_ext(s, 0, &el, 0))
- {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
- return NULL;
- }
-
- if((limit - p - 4 - el) < 0) return NULL;
-
- s2n(TLSEXT_TYPE_renegotiate,ret);
- s2n(el,ret);
-
- if(!ssl_add_clienthello_renegotiate_ext(s, ret, &el, el))
- {
- SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
- return NULL;
- }
-
- ret += el;
- }
-
#ifndef OPENSSL_NO_SRP
/* Add SRP username if there is one */
if (s->srp_ctx.login != NULL)
return NULL;
}
- /* check for enough space.
- 4 for the srp type type and entension length
- 1 for the srp user identity
- + srp user identity length
- */
+ /*-
+ * check for enough space.
+ * 4 for the srp type type and entension length
+ * 1 for the srp user identity
+ * + srp user identity length
+ */
if ((limit - ret - 5 - login_len) < 0) return NULL;
/* fill in the extension */
{
/* Add TLS extension ECPointFormats to the ClientHello message */
long lenmax;
- const unsigned char *plist;
- size_t plistlen;
+ const unsigned char *pcurves, *pformats;
+ size_t num_curves, num_formats, curves_list_len;
+ size_t i;
+ unsigned char *etmp;
- tls1_get_formatlist(s, &plist, &plistlen);
+ tls1_get_formatlist(s, &pformats, &num_formats);
if ((lenmax = limit - ret - 5) < 0) return NULL;
- if (plistlen > (size_t)lenmax) return NULL;
- if (plistlen > 255)
+ if (num_formats > (size_t)lenmax) return NULL;
+ if (num_formats > 255)
{
SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
return NULL;
}
s2n(TLSEXT_TYPE_ec_point_formats,ret);
- s2n(plistlen + 1,ret);
- *(ret++) = (unsigned char)plistlen ;
- memcpy(ret, plist, plistlen);
- ret+=plistlen;
+ /* The point format list has 1-byte length. */
+ s2n(num_formats + 1,ret);
+ *(ret++) = (unsigned char)num_formats ;
+ memcpy(ret, pformats, num_formats);
+ ret+=num_formats;
/* Add TLS extension EllipticCurves to the ClientHello message */
- plist = s->tlsext_ellipticcurvelist;
- tls1_get_curvelist(s, 0, &plist, &plistlen);
+ pcurves = s->tlsext_ellipticcurvelist;
+ if (!tls1_get_curvelist(s, 0, &pcurves, &num_curves))
+ return NULL;
if ((lenmax = limit - ret - 6) < 0) return NULL;
- if (plistlen > (size_t)lenmax) return NULL;
- if (plistlen > 65532)
+ if (num_curves > (size_t)lenmax / 2) return NULL;
+ if (num_curves > 65532 / 2)
{
SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
return NULL;
}
+
s2n(TLSEXT_TYPE_elliptic_curves,ret);
- s2n(plistlen + 2, ret);
+ etmp = ret + 4;
+ /* Copy curve ID if supported */
+ for (i = 0; i < num_curves; i++, pcurves += 2)
+ {
+ if (tls_curve_allowed(s, pcurves, SSL_SECOP_CURVE_SUPPORTED))
+ {
+ *etmp++ = pcurves[0];
+ *etmp++ = pcurves[1];
+ }
+ }
- /* NB: draft-ietf-tls-ecc-12.txt uses a one-byte prefix for
- * elliptic_curve_list, but the examples use two bytes.
- * http://www1.ietf.org/mail-archive/web/tls/current/msg00538.html
- * resolves this to two bytes.
- */
- s2n(plistlen, ret);
- memcpy(ret, plist, plistlen);
- ret+=plistlen;
+ curves_list_len = etmp - ret - 4;
+
+ s2n(curves_list_len + 2, ret);
+ s2n(curves_list_len, ret);
+ ret += curves_list_len;
}
#endif /* OPENSSL_NO_EC */
- if (!(SSL_get_options(s) & SSL_OP_NO_TICKET))
+ if (tls_use_ticket(s))
{
int ticklen;
if (!s->new_session && s->session && s->session->tlsext_tick)
{
size_t salglen;
const unsigned char *salg;
+ unsigned char *etmp;
salglen = tls12_get_psigalgs(s, &salg);
if ((size_t)(limit - ret) < salglen + 6)
return NULL;
s2n(TLSEXT_TYPE_signature_algorithms,ret);
- s2n(salglen + 2, ret);
- s2n(salglen, ret);
- memcpy(ret, salg, salglen);
+ etmp = ret;
+ /* Skip over lengths for now */
+ ret += 4;
+ salglen = tls12_copy_sigalgs(s, ret, salg, salglen);
+ /* Fill in lengths */
+ s2n(salglen + 2, etmp);
+ s2n(salglen, etmp);
ret += salglen;
}
{
size_t col = s->s3->client_opaque_prf_input_len;
- if ((long)(limit - ret - 6 - col < 0))
+ if ((long)(limit - ret - 6 - col) < 0)
return NULL;
if (col > 0xFFFD) /* can't happen */
return NULL;
#ifndef OPENSSL_NO_HEARTBEATS
/* Add Heartbeat extension */
+ if ((limit - ret - 4 - 1) < 0)
+ return NULL;
s2n(TLSEXT_TYPE_heartbeat,ret);
s2n(1,ret);
- /* Set mode:
+ /*-
+ * Set mode:
* 1: peer may send requests
* 2: peer not allowed to send requests
*/
ret += s->alpn_client_proto_list_len;
}
- if(SSL_get_srtp_profiles(s))
+#ifndef OPENSSL_NO_SRTP
+ if(SSL_IS_DTLS(s) && SSL_get_srtp_profiles(s))
{
int el;
ssl_add_clienthello_use_srtp_ext(s, 0, &el, 0);
- if((limit - p - 4 - el) < 0) return NULL;
+ if((limit - ret - 4 - el) < 0) return NULL;
s2n(TLSEXT_TYPE_use_srtp,ret);
s2n(el,ret);
}
ret += el;
}
-
+#endif
+ custom_ext_init(&s->cert->cli_ext);
/* 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, al,
- 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 (!custom_ext_add(s, 0, &ret, limit, al))
+ return NULL;
#ifdef TLSEXT_TYPE_encrypt_then_mac
s2n(TLSEXT_TYPE_encrypt_then_mac,ret);
s2n(0,ret);
#endif
-#ifdef TLSEXT_TYPE_padding
+
/* Add padding to workaround bugs in F5 terminators.
- * See https://tools.ietf.org/html/draft-agl-tls-padding-02
+ * See https://tools.ietf.org/html/draft-agl-tls-padding-03
*
* 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;
- /* 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;
- if (hlen >= 4)
- hlen -= 4;
- else
- hlen = 0;
+ if (s->options & SSL_OP_TLSEXT_PADDING)
+ {
+ 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;
+ if (hlen >= 4)
+ hlen -= 4;
+ else
+ hlen = 0;
- s2n(TLSEXT_TYPE_padding, ret);
- s2n(hlen, ret);
- memset(ret, 0, hlen);
- ret += hlen;
+ s2n(TLSEXT_TYPE_padding, ret);
+ s2n(hlen, ret);
+ memset(ret, 0, hlen);
+ ret += hlen;
+ }
}
- }
-#endif
- if ((extdatalen = ret-p-2) == 0)
- return p;
+ done:
+
+ if ((extdatalen = ret-orig-2)== 0)
+ return orig;
- s2n(extdatalen,p);
+ s2n(extdatalen, orig);
return ret;
}
-unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned char *limit, int *al)
+unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *buf, unsigned char *limit, int *al)
{
int extdatalen=0;
- unsigned char *ret = p;
- size_t i;
- custom_srv_ext_record *record;
+ unsigned char *orig = buf;
+ unsigned char *ret = buf;
#ifndef OPENSSL_NO_NEXTPROTONEG
int next_proto_neg_seen;
#endif
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 */
- if (s->version == SSL3_VERSION && !s->s3->send_connection_binding)
- return p;
ret+=2;
if (ret>=limit) return NULL; /* this really never occurs, but ... */
- if (!s->hit && s->servername_done == 1 && s->session->tlsext_hostname != NULL)
- {
- if ((long)(limit - ret - 4) < 0) return NULL;
-
- s2n(TLSEXT_TYPE_server_name,ret);
- s2n(0,ret);
- }
-
if(s->s3->send_connection_binding)
{
int el;
return NULL;
}
- if((limit - p - 4 - el) < 0) return NULL;
+ if((limit - ret - 4 - el) < 0) return NULL;
s2n(TLSEXT_TYPE_renegotiate,ret);
s2n(el,ret);
ret += el;
}
+ /* Only add RI for SSLv3 */
+ if (s->version == SSL3_VERSION)
+ goto done;
+
+ if (!s->hit && s->servername_done == 1 && s->session->tlsext_hostname != NULL)
+ {
+ if ((long)(limit - ret - 4) < 0) return NULL;
+
+ s2n(TLSEXT_TYPE_server_name,ret);
+ s2n(0,ret);
+ }
+
#ifndef OPENSSL_NO_EC
if (using_ecc)
{
/* Currently the server should not respond with a SupportedCurves extension */
#endif /* OPENSSL_NO_EC */
- if (s->tlsext_ticket_expected
- && !(SSL_get_options(s) & SSL_OP_NO_TICKET))
+ if (s->tlsext_ticket_expected && tls_use_ticket(s))
{
if ((long)(limit - ret - 4) < 0) return NULL;
s2n(TLSEXT_TYPE_session_ticket,ret);
}
#endif
- if(s->srtp_profile)
+#ifndef OPENSSL_NO_SRTP
+ if(SSL_IS_DTLS(s) && s->srtp_profile)
{
int el;
ssl_add_serverhello_use_srtp_ext(s, 0, &el, 0);
- if((limit - p - 4 - el) < 0) return NULL;
+ if((limit - ret - 4 - el) < 0) return NULL;
s2n(TLSEXT_TYPE_use_srtp,ret);
s2n(el,ret);
}
ret+=el;
}
+#endif
if (((s->s3->tmp.new_cipher->id & 0xFFFF)==0x80 || (s->s3->tmp.new_cipher->id & 0xFFFF)==0x81)
&& (SSL_get_options(s) & SSL_OP_CRYPTOPRO_TLSEXT_BUG))
/* Add Heartbeat extension if we've received one */
if (s->tlsext_heartbeat & SSL_TLSEXT_HB_ENABLED)
{
+ if ((limit - ret - 4 - 1) < 0)
+ return NULL;
s2n(TLSEXT_TYPE_heartbeat,ret);
s2n(1,ret);
- /* Set mode:
+ /*-
+ * Set mode:
* 1: peer may send requests
* 2: peer not allowed to send requests
*/
}
}
#endif
-
- for (i = 0; i < s->ctx->custom_srv_ext_records_count; i++)
- {
- const unsigned char *out = NULL;
- unsigned short outlen = 0;
- int cb_retval = 0;
-
- record = &s->ctx->custom_srv_ext_records[i];
-
- /* NULL callback or -1 omits extension */
- if (!record->fn2)
- continue;
- cb_retval = record->fn2(s, record->ext_type,
- &out, &outlen, al,
- 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 (!custom_ext_add(s, 1, &ret, limit, al))
+ return NULL;
#ifdef TLSEXT_TYPE_encrypt_then_mac
if (s->s3->flags & TLS1_FLAGS_ENCRYPT_THEN_MAC)
{
- /* Don't use encrypt_then_mac if AEAD: might want
- * to disable for other ciphersuites too.
+ /* Don't use encrypt_then_mac if AEAD or RC4
+ * might want to disable for other cases too.
*/
- if (s->s3->tmp.new_cipher->algorithm_mac == SSL_AEAD)
+ if (s->s3->tmp.new_cipher->algorithm_mac == SSL_AEAD
+ || s->s3->tmp.new_cipher->algorithm_enc == SSL_RC4)
s->s3->flags &= ~TLS1_FLAGS_ENCRYPT_THEN_MAC;
else
{
ret += len;
}
- if ((extdatalen = ret-p-2)== 0)
- return p;
+ done:
+
+ if ((extdatalen = ret-orig-2)== 0)
+ return orig;
- s2n(extdatalen,p);
+ s2n(extdatalen, orig);
return ret;
}
}
#ifndef OPENSSL_NO_EC
-/* ssl_check_for_safari attempts to fingerprint Safari using OS X
+/*-
+ * 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,
}
#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;
unsigned short len;
unsigned char *data = *p;
int renegotiate_seen = 0;
- size_t i;
s->servername_done = 0;
s->tlsext_status_type = -1;
s->s3->alpn_selected = NULL;
}
- /* Clear observed custom extensions */
- s->s3->serverinfo_client_tlsext_custom_types_count = 0;
- if (s->s3->serverinfo_client_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 |
SSL_TLSEXT_HB_DONT_SEND_REQUESTS);
OPENSSL_free(s->cert->peer_sigalgs);
s->cert->peer_sigalgs = NULL;
}
- /* Clear any shared sigtnature algorithms */
- if (s->cert->shared_sigalgs)
- {
- OPENSSL_free(s->cert->shared_sigalgs);
- s->cert->shared_sigalgs = NULL;
- }
- /* Clear certificate digests and validity flags */
- for (i = 0; i < SSL_PKEY_NUM; i++)
- {
- s->cert->pkeys[i].digest = NULL;
- s->cert->pkeys[i].valid_flags = 0;
- }
#ifdef TLSEXT_TYPE_encrypt_then_mac
s->s3->flags &= ~TLS1_FLAGS_ENCRYPT_THEN_MAC;
#endif
+#ifndef OPENSSL_NO_SRP
+ if (s->srp_ctx.login != NULL)
+ {
+ OPENSSL_free(s->srp_ctx.login);
+ s->srp_ctx.login = NULL;
+ }
+#endif
+
+ s->srtp_profile = NULL;
+
if (data >= (d+n-2))
goto ri_check;
n2s(data,len);
if (s->tlsext_debug_cb)
s->tlsext_debug_cb(s, 0, type, data, size,
s->tlsext_debug_arg);
-/* The servername extension is treated as follows:
-
- - Only the hostname type is supported with a maximum length of 255.
- - The servername is rejected if too long or if it contains zeros,
- in which case an fatal alert is generated.
- - The servername field is maintained together with the session cache.
- - When a session is resumed, the servername call back invoked in order
- to allow the application to position itself to the right context.
- - The servername is acknowledged if it is new for a session or when
- it is identical to a previously used for the same session.
- Applications can control the behaviour. They can at any time
- set a 'desirable' servername for a new SSL object. This can be the
- case for example with HTTPS when a Host: header field is received and
- a renegotiation is requested. In this case, a possible servername
- presented in the new client hello is only acknowledged if it matches
- the value of the Host: field.
- - Applications must use SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION
- if they provide for changing an explicit servername context for the session,
- i.e. when the session has been established with a servername extension.
- - On session reconnect, the servername extension may be absent.
-
-*/
-
- if (type == TLSEXT_TYPE_server_name)
+ if (type == TLSEXT_TYPE_renegotiate)
+ {
+ if(!ssl_parse_clienthello_renegotiate_ext(s, data, size, al))
+ return 0;
+ renegotiate_seen = 1;
+ }
+ else if (s->version == SSL3_VERSION)
+ {}
+/*-
+ * The servername extension is treated as follows:
+ *
+ * - Only the hostname type is supported with a maximum length of 255.
+ * - The servername is rejected if too long or if it contains zeros,
+ * in which case an fatal alert is generated.
+ * - The servername field is maintained together with the session cache.
+ * - When a session is resumed, the servername call back invoked in order
+ * to allow the application to position itself to the right context.
+ * - The servername is acknowledged if it is new for a session or when
+ * it is identical to a previously used for the same session.
+ * Applications can control the behaviour. They can at any time
+ * set a 'desirable' servername for a new SSL object. This can be the
+ * case for example with HTTPS when a Host: header field is received and
+ * a renegotiation is requested. In this case, a possible servername
+ * presented in the new client hello is only acknowledged if it matches
+ * the value of the Host: field.
+ * - Applications must use SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION
+ * if they provide for changing an explicit servername context for the
+ * session, i.e. when the session has been established with a servername
+ * extension.
+ * - On session reconnect, the servername extension may be absent.
+ *
+ */
+
+ else if (type == TLSEXT_TYPE_server_name)
{
unsigned char *sdata;
int servname_type;
ellipticcurvelist_length += (*(sdata++));
if (ellipticcurvelist_length != size - 2 ||
- ellipticcurvelist_length < 1)
+ ellipticcurvelist_length < 1 ||
+ /* Each NamedCurve is 2 bytes. */
+ ellipticcurvelist_length & 1)
{
*al = TLS1_AD_DECODE_ERROR;
return 0;
if (s->s3->client_opaque_prf_input != NULL) /* shouldn't really happen */
OPENSSL_free(s->s3->client_opaque_prf_input);
+
+ /* dummy byte just to get non-NULL */
if (s->s3->client_opaque_prf_input_len == 0)
- s->s3->client_opaque_prf_input = OPENSSL_malloc(1); /* dummy byte just to get non-NULL */
+ s->s3->client_opaque_prf_input = OPENSSL_malloc(1);
else
s->s3->client_opaque_prf_input = BUF_memdup(sdata, s->s3->client_opaque_prf_input_len);
if (s->s3->client_opaque_prf_input == NULL)
return 0;
}
}
- else if (type == TLSEXT_TYPE_renegotiate)
- {
- if(!ssl_parse_clienthello_renegotiate_ext(s, data, size, al))
- return 0;
- renegotiate_seen = 1;
- }
else if (type == TLSEXT_TYPE_signature_algorithms)
{
int dsize;
*al = SSL_AD_DECODE_ERROR;
return 0;
}
- if (!tls1_process_sigalgs(s, data, dsize))
+ if (!tls1_save_sigalgs(s, data, dsize))
{
*al = SSL_AD_DECODE_ERROR;
return 0;
}
- /* If sigalgs received and no shared algorithms fatal
- * error.
- */
- if (s->cert->peer_sigalgs && !s->cert->shared_sigalgs)
- {
- SSLerr(SSL_F_SSL_SCAN_CLIENTHELLO_TLSEXT,
- SSL_R_NO_SHARED_SIGATURE_ALGORITHMS);
- *al = SSL_AD_ILLEGAL_PARAMETER;
- return 0;
- }
}
else if (type == TLSEXT_TYPE_status_request)
{
s->s3->tmp.finish_md_len == 0 &&
s->s3->alpn_selected == NULL)
{
- /* We shouldn't accept this extension on a
+ /*-
+ * We shouldn't accept this extension on a
* renegotiation.
*
* s->new_session will be set on renegotiation, but we
* there's some other reason to disallow resuming an
* earlier session -- the current code won't be doing
* anything like that, but this might change).
-
+ *
* A valid sign that there's been a previous handshake
* in this connection is if s->s3->tmp.finish_md_len >
* 0. (We are talking about a check that will happen
* in the Hello protocol round, well before a new
- * Finished message could have been computed.) */
+ * Finished message could have been computed.)
+ */
s->s3->next_proto_neg_seen = 1;
}
#endif
}
/* session ticket processed earlier */
- else if (type == TLSEXT_TYPE_use_srtp)
+#ifndef OPENSSL_NO_SRTP
+ else if (SSL_IS_DTLS(s) && SSL_get_srtp_profiles(s)
+ && type == TLSEXT_TYPE_use_srtp)
{
if(ssl_parse_clienthello_use_srtp_ext(s, data, size,
al))
return 0;
}
+#endif
+#ifdef TLSEXT_TYPE_encrypt_then_mac
+ else if (type == TLSEXT_TYPE_encrypt_then_mac)
+ s->s3->flags |= TLS1_FLAGS_ENCRYPT_THEN_MAC;
+#endif
/* 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)
- {
- if (record->fn1 && !record->fn1(s, type, data, size, al, record->arg))
- return 0;
- }
- }
+ */
+ else if (!s->hit)
+ {
+ if (custom_ext_parse(s, 1, type, data, size, al) <= 0)
+ return 0;
}
-#ifdef TLSEXT_TYPE_encrypt_then_mac
- else if (type == TLSEXT_TYPE_encrypt_then_mac)
- s->s3->flags |= TLS1_FLAGS_ENCRYPT_THEN_MAC;
-#endif
data+=size;
}
SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED);
return 0;
}
- /* If no signature algorithms extension set default values */
- if (!s->cert->peer_sigalgs)
- ssl_cert_set_default_md(s->cert);
return 1;
}
int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, int n)
{
int al = -1;
+ custom_ext_init(&s->cert->srv_ext);
if (ssl_scan_clienthello_tlsext(s, p, d, n, &al) <= 0)
{
ssl3_send_alert(s,SSL3_AL_FATAL,al);
#ifndef OPENSSL_NO_NEXTPROTONEG
s->s3->next_proto_neg_seen = 0;
#endif
+ s->tlsext_ticket_expected = 0;
if (s->s3->alpn_selected)
{
s->tlsext_debug_cb(s, 1, type, data, size,
s->tlsext_debug_arg);
- if (type == TLSEXT_TYPE_server_name)
+
+ if (type == TLSEXT_TYPE_renegotiate)
+ {
+ if(!ssl_parse_serverhello_renegotiate_ext(s, data, size, al))
+ return 0;
+ renegotiate_seen = 1;
+ }
+ else if (s->version == SSL3_VERSION)
+ {}
+ else if (type == TLSEXT_TYPE_server_name)
{
if (s->tlsext_hostname == NULL || size > 0)
{
*al = TLS1_AD_DECODE_ERROR;
return 0;
}
- s->session->tlsext_ecpointformatlist_length = 0;
- if (s->session->tlsext_ecpointformatlist != NULL) OPENSSL_free(s->session->tlsext_ecpointformatlist);
- if ((s->session->tlsext_ecpointformatlist = OPENSSL_malloc(ecpointformatlist_length)) == NULL)
+ if (!s->hit)
{
- *al = TLS1_AD_INTERNAL_ERROR;
- return 0;
+ s->session->tlsext_ecpointformatlist_length = 0;
+ if (s->session->tlsext_ecpointformatlist != NULL) OPENSSL_free(s->session->tlsext_ecpointformatlist);
+ if ((s->session->tlsext_ecpointformatlist = OPENSSL_malloc(ecpointformatlist_length)) == NULL)
+ {
+ *al = TLS1_AD_INTERNAL_ERROR;
+ return 0;
+ }
+ s->session->tlsext_ecpointformatlist_length = ecpointformatlist_length;
+ memcpy(s->session->tlsext_ecpointformatlist, sdata, ecpointformatlist_length);
}
- s->session->tlsext_ecpointformatlist_length = ecpointformatlist_length;
- memcpy(s->session->tlsext_ecpointformatlist, sdata, ecpointformatlist_length);
#if 0
fprintf(stderr,"ssl_parse_serverhello_tlsext s->session->tlsext_ecpointformatlist ");
sdata = s->session->tlsext_ecpointformatlist;
*al = TLS1_AD_INTERNAL_ERROR;
return 0;
}
- if ((SSL_get_options(s) & SSL_OP_NO_TICKET)
- || (size > 0))
+ if (!tls_use_ticket(s) || (size > 0))
{
*al = TLS1_AD_UNSUPPORTED_EXTENSION;
return 0;
*al = TLS1_AD_DECODE_ERROR;
return 0;
}
- /* The extension data consists of:
+ /*-
+ * The extension data consists of:
* uint16 list_length
* uint8 proto_length;
- * uint8 proto[proto_length]; */
+ * uint8 proto[proto_length];
+ */
len = data[0];
len <<= 8;
len |= data[1];
memcpy(s->s3->alpn_selected, data + 3, len);
s->s3->alpn_selected_len = len;
}
-
- else if (type == TLSEXT_TYPE_renegotiate)
- {
- if(!ssl_parse_serverhello_renegotiate_ext(s, data, size, al))
- return 0;
- renegotiate_seen = 1;
- }
#ifndef OPENSSL_NO_HEARTBEATS
else if (type == TLSEXT_TYPE_heartbeat)
{
}
}
#endif
- else if (type == TLSEXT_TYPE_use_srtp)
+#ifndef OPENSSL_NO_SRTP
+ else if (SSL_IS_DTLS(s) && type == TLSEXT_TYPE_use_srtp)
{
if(ssl_parse_serverhello_use_srtp_ext(s, data, size,
al))
return 0;
}
- /* 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;
- }
- }
- }
+#endif
#ifdef TLSEXT_TYPE_encrypt_then_mac
else if (type == TLSEXT_TYPE_encrypt_then_mac)
{
/* Ignore if inappropriate ciphersuite */
- if (s->s3->tmp.new_cipher->algorithm_mac != SSL_AEAD)
+ if (s->s3->tmp.new_cipher->algorithm_mac != SSL_AEAD
+ && s->s3->tmp.new_cipher->algorithm_enc != SSL_RC4)
s->s3->flags |= TLS1_FLAGS_ENCRYPT_THEN_MAC;
}
#endif
+ /* If this extension type was not otherwise handled, but
+ * matches a custom_cli_ext_record, then send it to the c
+ * callback */
+ else if (custom_ext_parse(s, 0, type, data, size, al) <= 0)
+ return 0;
data += size;
}
}
}
+int tls1_set_server_sigalgs(SSL *s)
+ {
+ int al;
+ size_t i;
+ /* Clear any shared sigtnature algorithms */
+ if (s->cert->shared_sigalgs)
+ {
+ OPENSSL_free(s->cert->shared_sigalgs);
+ s->cert->shared_sigalgs = NULL;
+ }
+ /* Clear certificate digests and validity flags */
+ for (i = 0; i < SSL_PKEY_NUM; i++)
+ {
+ s->cert->pkeys[i].digest = NULL;
+ s->cert->pkeys[i].valid_flags = 0;
+ }
+
+ /* If sigalgs received process it. */
+ if (s->cert->peer_sigalgs)
+ {
+ if (!tls1_process_sigalgs(s))
+ {
+ SSLerr(SSL_F_TLS1_SET_SERVER_SIGALGS,
+ ERR_R_MALLOC_FAILURE);
+ al = SSL_AD_INTERNAL_ERROR;
+ goto err;
+ }
+ /* Fatal error is no shared signature algorithms */
+ if (!s->cert->shared_sigalgs)
+ {
+ SSLerr(SSL_F_TLS1_SET_SERVER_SIGALGS,
+ SSL_R_NO_SHARED_SIGATURE_ALGORITHMS);
+ al = SSL_AD_ILLEGAL_PARAMETER;
+ goto err;
+ }
+ }
+ else
+ ssl_cert_set_default_md(s->cert);
+ return 1;
+ err:
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
+ return 0;
+ }
+
int ssl_check_clienthello_tlsext_late(SSL *s)
{
int ret = SSL_TLSEXT_ERR_OK;
return 1;
}
-/* Since the server cache lookup is done early on in the processing of the
+/*-
+ * Since the server cache lookup is done early on in the processing of the
* ClientHello, and other operations depend on the result, we need to handle
* any TLS session ticket extension at the same time.
*
/* If tickets disabled behave as if no ticket present
* to permit stateful resumption.
*/
- if (SSL_get_options(s) & SSL_OP_NO_TICKET)
+ if (!tls_use_ticket(s))
return 0;
if ((s->version <= SSL3_VERSION) || !limit)
return 0;
return 0;
}
-/* tls_decrypt_ticket attempts to decrypt a session ticket.
+/*-
+ * tls_decrypt_ticket attempts to decrypt a session ticket.
*
* etick: points to the body of the session ticket extension.
* eticklen: the length of the session tickets extenion.
HMAC_Final(&hctx, tick_hmac, NULL);
HMAC_CTX_cleanup(&hctx);
if (CRYPTO_memcmp(tick_hmac, etick + eticklen, mlen))
+ {
+ EVP_CIPHER_CTX_cleanup(&ctx);
return 2;
+ }
/* Attempt to decrypt session data */
/* Move p after IV to start of encrypted ticket, update length */
p = etick + 16 + EVP_CIPHER_CTX_iv_length(&ctx);
}
EVP_DecryptUpdate(&ctx, sdec, &slen, p, eticklen);
if (EVP_DecryptFinal(&ctx, sdec + slen, &mlen) <= 0)
+ {
+ EVP_CIPHER_CTX_cleanup(&ctx);
+ OPENSSL_free(sdec);
return 2;
+ }
slen += mlen;
EVP_CIPHER_CTX_cleanup(&ctx);
p = sdec;
int id;
} tls12_lookup;
-static tls12_lookup tls12_md[] = {
+static const tls12_lookup tls12_md[] = {
{NID_md5, TLSEXT_hash_md5},
{NID_sha1, TLSEXT_hash_sha1},
{NID_sha224, TLSEXT_hash_sha224},
{NID_sha512, TLSEXT_hash_sha512}
};
-static tls12_lookup tls12_sig[] = {
+static const tls12_lookup tls12_sig[] = {
{EVP_PKEY_RSA, TLSEXT_signature_rsa},
{EVP_PKEY_DSA, TLSEXT_signature_dsa},
{EVP_PKEY_EC, TLSEXT_signature_ecdsa}
};
-static int tls12_find_id(int nid, tls12_lookup *table, size_t tlen)
+static int tls12_find_id(int nid, const tls12_lookup *table, size_t tlen)
{
size_t i;
for (i = 0; i < tlen; i++)
return -1;
}
-static int tls12_find_nid(int id, tls12_lookup *table, size_t tlen)
+static int tls12_find_nid(int id, const tls12_lookup *table, size_t tlen)
{
size_t i;
for (i = 0; i < tlen; i++)
sizeof(tls12_sig)/sizeof(tls12_lookup));
}
-const EVP_MD *tls12_get_hash(unsigned char hash_alg)
+typedef struct
{
- switch(hash_alg)
- {
-#ifndef OPENSSL_NO_MD5
- case TLSEXT_hash_md5:
-#ifdef OPENSSL_FIPS
- if (FIPS_mode())
- return NULL;
+ int nid;
+ int secbits;
+ const EVP_MD *(*mfunc)(void);
+ } tls12_hash_info;
+
+static const tls12_hash_info tls12_md_info[] = {
+#ifdef OPENSSL_NO_MD5
+ {NID_md5, 64, 0},
+#else
+ {NID_md5, 64, EVP_md5},
#endif
- return EVP_md5();
+#ifdef OPENSSL_NO_SHA
+ {NID_sha1, 80, 0},
+#else
+ {NID_sha1, 80, EVP_sha1},
#endif
-#ifndef OPENSSL_NO_SHA
- case TLSEXT_hash_sha1:
- return EVP_sha1();
+#ifdef OPENSSL_NO_SHA256
+ {NID_sha224, 112, 0},
+ {NID_sha256, 128, 0},
+#else
+ {NID_sha224, 112, EVP_sha224},
+ {NID_sha256, 128, EVP_sha256},
#endif
-#ifndef OPENSSL_NO_SHA256
- case TLSEXT_hash_sha224:
- return EVP_sha224();
-
- case TLSEXT_hash_sha256:
- return EVP_sha256();
+#ifdef OPENSSL_NO_SHA512
+ {NID_sha384, 192, 0},
+ {NID_sha512, 256, 0}
+#else
+ {NID_sha384, 192, EVP_sha384},
+ {NID_sha512, 256, EVP_sha512}
#endif
-#ifndef OPENSSL_NO_SHA512
- case TLSEXT_hash_sha384:
- return EVP_sha384();
+};
- case TLSEXT_hash_sha512:
- return EVP_sha512();
-#endif
- default:
+static const tls12_hash_info *tls12_get_hash_info(unsigned char hash_alg)
+ {
+ if (hash_alg == 0)
return NULL;
+ if (hash_alg > sizeof(tls12_md_info)/sizeof(tls12_md_info[0]))
+ return NULL;
+ return tls12_md_info + hash_alg - 1;
+ }
- }
+const EVP_MD *tls12_get_hash(unsigned char hash_alg)
+ {
+ const tls12_hash_info *inf;
+ if (hash_alg == TLSEXT_hash_md5 && FIPS_mode())
+ return NULL;
+ inf = tls12_get_hash_info(hash_alg);
+ if (!inf || !inf->mfunc)
+ return NULL;
+ return inf->mfunc();
}
static int tls12_get_pkey_idx(unsigned char sig_alg)
*psignhash_nid = NID_undef;
}
}
+/* Check to see if a signature algorithm is allowed */
+static int tls12_sigalg_allowed(SSL *s, int op, const unsigned char *ptmp)
+ {
+ /* See if we have an entry in the hash table and it is enabled */
+ const tls12_hash_info *hinf = tls12_get_hash_info(ptmp[0]);
+ if (!hinf || !hinf->mfunc)
+ return 0;
+ /* See if public key algorithm allowed */
+ if (tls12_get_pkey_idx(ptmp[1]) == -1)
+ return 0;
+ /* Finally see if security callback allows it */
+ return ssl_security(s, op, hinf->secbits, hinf->nid, (void *)ptmp);
+ }
+
+/* Get a mask of disabled public key algorithms based on supported
+ * signature algorithms. For example if no signature algorithm supports RSA
+ * then RSA is disabled.
+ */
+
+void ssl_set_sig_mask(unsigned long *pmask_a, SSL *s, int op)
+ {
+ const unsigned char *sigalgs;
+ size_t i, sigalgslen;
+ int have_rsa = 0, have_dsa = 0, have_ecdsa = 0;
+ /* Now go through all signature algorithms seeing if we support
+ * any for RSA, DSA, ECDSA. Do this for all versions not just
+ * TLS 1.2. To keep down calls to security callback only check
+ * if we have to.
+ */
+ sigalgslen = tls12_get_psigalgs(s, &sigalgs);
+ for (i = 0; i < sigalgslen; i += 2, sigalgs += 2)
+ {
+ switch(sigalgs[1])
+ {
+#ifndef OPENSSL_NO_RSA
+ case TLSEXT_signature_rsa:
+ if (!have_rsa && tls12_sigalg_allowed(s, op, sigalgs))
+ have_rsa = 1;
+ break;
+#endif
+#ifndef OPENSSL_NO_DSA
+ case TLSEXT_signature_dsa:
+ if (!have_dsa && tls12_sigalg_allowed(s, op, sigalgs))
+ have_dsa = 1;
+ break;
+#endif
+#ifndef OPENSSL_NO_ECDSA
+ case TLSEXT_signature_ecdsa:
+ if (!have_ecdsa && tls12_sigalg_allowed(s, op, sigalgs))
+ have_ecdsa = 1;
+ break;
+#endif
+ }
+ }
+ if (!have_rsa)
+ *pmask_a |= SSL_aRSA;
+ if (!have_dsa)
+ *pmask_a |= SSL_aDSS;
+ if (!have_ecdsa)
+ *pmask_a |= SSL_aECDSA;
+ }
+
+size_t tls12_copy_sigalgs(SSL *s, unsigned char *out,
+ const unsigned char *psig, size_t psiglen)
+ {
+ unsigned char *tmpout = out;
+ size_t i;
+ for (i = 0; i < psiglen; i += 2, psig += 2)
+ {
+ if (tls12_sigalg_allowed(s, SSL_SECOP_SIGALG_SUPPORTED, psig))
+ {
+ *tmpout++ = psig[0];
+ *tmpout++ = psig[1];
+ }
+ }
+ return tmpout - out;
+ }
+
/* Given preference and allowed sigalgs set shared sigalgs */
-static int tls12_do_shared_sigalgs(TLS_SIGALGS *shsig,
+static int tls12_shared_sigalgs(SSL *s, TLS_SIGALGS *shsig,
const unsigned char *pref, size_t preflen,
const unsigned char *allow, size_t allowlen)
{
for (i = 0, ptmp = pref; i < preflen; i+=2, ptmp+=2)
{
/* Skip disabled hashes or signature algorithms */
- if (tls12_get_hash(ptmp[0]) == NULL)
- continue;
- if (tls12_get_pkey_idx(ptmp[1]) == -1)
+ if (!tls12_sigalg_allowed(s, SSL_SECOP_SIGALG_SHARED, ptmp))
continue;
for (j = 0, atmp = allow; j < allowlen; j+=2, atmp+=2)
{
TLS_SIGALGS *salgs = NULL;
CERT *c = s->cert;
unsigned int is_suiteb = tls1_suiteb(s);
+ if (c->shared_sigalgs)
+ {
+ OPENSSL_free(c->shared_sigalgs);
+ c->shared_sigalgs = NULL;
+ }
/* If client use client signature algorithms if not NULL */
if (!s->server && c->client_sigalgs && !is_suiteb)
{
pref = c->peer_sigalgs;
preflen = c->peer_sigalgslen;
}
- nmatch = tls12_do_shared_sigalgs(NULL, pref, preflen, allow, allowlen);
+ nmatch = tls12_shared_sigalgs(s, NULL, pref, preflen, allow, allowlen);
if (!nmatch)
return 1;
salgs = OPENSSL_malloc(nmatch * sizeof(TLS_SIGALGS));
if (!salgs)
return 0;
- nmatch = tls12_do_shared_sigalgs(salgs, pref, preflen, allow, allowlen);
+ nmatch = tls12_shared_sigalgs(s, salgs, pref, preflen, allow, allowlen);
c->shared_sigalgs = salgs;
c->shared_sigalgslen = nmatch;
return 1;
/* Set preferred digest for each key type */
-int tls1_process_sigalgs(SSL *s, const unsigned char *data, int dsize)
+int tls1_save_sigalgs(SSL *s, const unsigned char *data, int dsize)
{
- int idx;
- size_t i;
- const EVP_MD *md;
CERT *c = s->cert;
- TLS_SIGALGS *sigptr;
/* Extension ignored for inappropriate versions */
if (!SSL_USE_SIGALGS(s))
return 1;
if (!c)
return 0;
+ if (c->peer_sigalgs)
+ OPENSSL_free(c->peer_sigalgs);
c->peer_sigalgs = OPENSSL_malloc(dsize);
if (!c->peer_sigalgs)
return 0;
c->peer_sigalgslen = dsize;
memcpy(c->peer_sigalgs, data, dsize);
+ return 1;
+ }
- tls1_set_shared_sigalgs(s);
+int tls1_process_sigalgs(SSL *s)
+ {
+ int idx;
+ size_t i;
+ const EVP_MD *md;
+ CERT *c = s->cert;
+ TLS_SIGALGS *sigptr;
+ if (!tls1_set_shared_sigalgs(s))
+ return 0;
#ifdef OPENSSL_SSL_DEBUG_BROKEN_PROTOCOL
if (s->cert->cert_flags & SSL_CERT_FLAG_BROKEN_PROTOCOL)
unsigned int payload;
unsigned int padding = 16; /* Use minimum padding */
- /* Read type and payload length first */
- hbtype = *p++;
- n2s(p, payload);
- pl = p;
-
if (s->msg_callback)
s->msg_callback(0, s->version, TLS1_RT_HEARTBEAT,
&s->s3->rrec.data[0], s->s3->rrec.length,
s, s->msg_callback_arg);
+ /* Read type and payload length first */
+ if (1 + 2 + 16 > s->s3->rrec.length)
+ return 0; /* silently discard */
+ hbtype = *p++;
+ n2s(p, payload);
+ if (1 + 2 + payload + 16 > s->s3->rrec.length)
+ return 0; /* silently discard per RFC 6520 sec. 4 */
+ pl = p;
+
if (hbtype == TLS1_HB_REQUEST)
{
unsigned char *buffer, *bp;
* payload, plus padding
*/
buffer = OPENSSL_malloc(1 + 2 + payload + padding);
+ if (buffer == NULL)
+ {
+ SSLerr(SSL_F_TLS1_PROCESS_HEARTBEAT,ERR_R_MALLOC_FAILURE);
+ return -1;
+ }
bp = buffer;
/* Enter response type, length and copy payload */
*/
OPENSSL_assert(payload + padding <= 16381);
- /* Create HeartBeat message, we just use a sequence number
+ /*-
+ * Create HeartBeat message, we just use a sequence number
* as payload to distuingish different messages and add
* some random stuff.
* - Message Type, 1 byte
* - Padding
*/
buf = OPENSSL_malloc(1 + 2 + payload + padding);
+ if (buf == NULL)
+ {
+ SSLerr(SSL_F_TLS1_HEARTBEAT,ERR_R_MALLOC_FAILURE);
+ return -1;
+ }
p = buf;
/* Message Type */
*p++ = TLS1_HB_REQUEST;
if (check_flags)
check_flags |= CERT_PKEY_SUITEB;
ok = X509_chain_check_suiteb(NULL, x, chain, suiteb_flags);
- if (ok != X509_V_OK)
- {
- if (check_flags)
- rv |= CERT_PKEY_SUITEB;
- else
- goto end;
- }
+ if (ok == X509_V_OK)
+ rv |= CERT_PKEY_SUITEB;
+ else if (!check_flags)
+ goto end;
}
/* Check all signature algorithms are consistent with
#endif
-/* RFC6962 Signed Certificate Timestamp List X.509 extension parser */
-int i2r_sctlist(X509V3_EXT_METHOD *method, ASN1_OCTET_STRING *oct,
- BIO *out, int indent)
+#ifndef OPENSSL_NO_DH
+DH *ssl_get_auto_dh(SSL *s)
{
- BN_ULLONG timestamp;
- struct tm tm1;
- time_t unix_epoch = 0;
- unsigned char* data = oct->data;
- char month[4];
- unsigned short listlen, sctlen = 0, fieldlen;
- int signhash_nid;
-
- if (oct->length < 2)
- return 0;
- n2s(data, listlen);
- if (listlen != oct->length - 2)
- return 0;
-
- while (listlen > 0)
+ int dh_secbits = 80;
+ if (s->cert->dh_tmp_auto == 2)
+ return DH_get_1024_160();
+ if (s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL)
{
- if (listlen < 2)
- return 0;
- n2s(data, sctlen);
- listlen -= 2;
-
- if ((sctlen < 1) || (sctlen > listlen))
- return 0;
- listlen -= sctlen;
-
- BIO_printf(out, "%*sSigned Certificate Timestamp:", indent,
- "");
+ if (s->s3->tmp.new_cipher->strength_bits == 256)
+ dh_secbits = 128;
+ else
+ dh_secbits = 80;
+ }
+ else
+ {
+ CERT_PKEY *cpk = ssl_get_server_send_pkey(s);
+ dh_secbits = EVP_PKEY_security_bits(cpk->privatekey);
+ }
- if (*data == 0) /* SCT v1 */
+ if (dh_secbits >= 128)
+ {
+ DH *dhp = DH_new();
+ if (!dhp)
+ return NULL;
+ dhp->g = BN_new();
+ if (dhp->g)
+ BN_set_word(dhp->g, 2);
+ if (dh_secbits >= 192)
+ dhp->p = get_rfc3526_prime_8192(NULL);
+ else
+ dhp->p = get_rfc3526_prime_3072(NULL);
+ if (!dhp->p || !dhp->g)
{
- /* Fixed-length header:
- * struct {
- * (1 byte) Version sct_version;
- * (32 bytes) LogID id;
- * (8 bytes) uint64 timestamp;
- * (2 bytes + ?) CtExtensions extensions;
- */
- if (sctlen < 43)
- return 0;
- sctlen -= 43;
-
- BIO_printf(out, "\n%*sVersion : v1(0)", indent + 4,
- "");
-
- BIO_printf(out, "\n%*sLog ID : ", indent + 4, "");
- BIO_hex_string(out, indent + 16, 16, data + 1, 32);
-
- data += 33;
- n2l8(data, timestamp);
- OPENSSL_gmtime(&unix_epoch, &tm1);
- OPENSSL_gmtime_adj(&tm1, timestamp / 86400000,
- (timestamp % 86400000) / 1000);
- strftime(month, 4, "%b", &tm1);
- BIO_printf(out, "\n%*sTimestamp : ", indent + 4, "");
- BIO_printf(out, "%s %2d %02d:%02d:%02d.%03u %d UTC",
- month, tm1.tm_mday, tm1.tm_hour,
- tm1.tm_min, tm1.tm_sec,
- (unsigned int)(timestamp % 1000),
- tm1.tm_year + 1900);
-
- n2s(data, fieldlen);
- if (sctlen < fieldlen)
- return 0;
- sctlen -= fieldlen;
- BIO_printf(out, "\n%*sExtensions: ", indent + 4, "");
- if (fieldlen == 0)
- BIO_printf(out, "none");
- else
- BIO_hex_string(out, indent + 16, 16, data,
- fieldlen);
- data += fieldlen;
-
- /* digitally-signed struct header:
- * (1 byte) Hash algorithm
- * (1 byte) Signature algorithm
- * (2 bytes + ?) Signature
- */
- if (sctlen < 4)
- return 0;
- sctlen -= 4;
-
- tls1_lookup_sigalg(NULL, NULL, &signhash_nid, data);
- data += 2;
- n2s(data, fieldlen);
- if (sctlen != fieldlen)
- return 0;
- BIO_printf(out, "\n%*sSignature : ", indent + 4, "");
- BIO_printf(out, "%s", OBJ_nid2ln(signhash_nid));
- BIO_printf(out, "\n%*s ", indent + 4, "");
- BIO_hex_string(out, indent + 16, 16, data, fieldlen);
- if (listlen > 0) BIO_printf(out, "\n");
- data += fieldlen;
+ DH_free(dhp);
+ return NULL;
}
+ return dhp;
}
+ if (dh_secbits >= 112)
+ return DH_get_2048_224();
+ return DH_get_1024_160();
+ }
+#endif
- return 1;
+static int ssl_security_cert_key(SSL *s, SSL_CTX *ctx, X509 *x, int op)
+ {
+ int secbits;
+ EVP_PKEY *pkey = X509_get_pubkey(x);
+ if (pkey)
+ {
+ secbits = EVP_PKEY_security_bits(pkey);
+ EVP_PKEY_free(pkey);
+ }
+ else
+ secbits = -1;
+ if (s)
+ return ssl_security(s, op, secbits, 0, x);
+ else
+ return ssl_ctx_security(ctx, op, secbits, 0, x);
}
-static X509V3_EXT_METHOD ext_method_ct_precert_scts =
+static int ssl_security_cert_sig(SSL *s, SSL_CTX *ctx, X509 *x, int op)
{
- NID_ct_precert_scts, 0, ASN1_ITEM_ref(ASN1_OCTET_STRING),
- 0, 0, 0, 0, 0, 0, 0, 0, (X509V3_EXT_I2R)i2r_sctlist, NULL, NULL
- };
+ /* Lookup signature algorithm digest */
+ int secbits = -1, md_nid = NID_undef, sig_nid;
+ sig_nid = X509_get_signature_nid(x);
+ if (sig_nid && OBJ_find_sigid_algs(sig_nid, &md_nid, NULL))
+ {
+ const EVP_MD *md;
+ if (md_nid && (md = EVP_get_digestbynid(md_nid)))
+ secbits = EVP_MD_size(md) * 4;
+ }
+ if (s)
+ return ssl_security(s, op, secbits, md_nid, x);
+ else
+ return ssl_ctx_security(ctx, op, secbits, md_nid, x);
+ }
-static X509V3_EXT_METHOD ext_method_ct_cert_scts =
+int ssl_security_cert(SSL *s, SSL_CTX *ctx, X509 *x, int vfy, int is_ee)
{
- NID_ct_cert_scts, 0, ASN1_ITEM_ref(ASN1_OCTET_STRING),
- 0, 0, 0, 0, 0, 0, 0, 0, (X509V3_EXT_I2R)i2r_sctlist, NULL, NULL
- };
+ if (vfy)
+ vfy = SSL_SECOP_PEER;
+ if (is_ee)
+ {
+ if (!ssl_security_cert_key(s, ctx, x, SSL_SECOP_EE_KEY | vfy))
+ return SSL_R_EE_KEY_TOO_SMALL;
+ }
+ else
+ {
+ if (!ssl_security_cert_key(s, ctx, x, SSL_SECOP_CA_KEY | vfy))
+ return SSL_R_CA_KEY_TOO_SMALL;
+ }
+ if (!ssl_security_cert_sig(s, ctx, x, SSL_SECOP_CA_MD | vfy))
+ return SSL_R_CA_MD_TOO_WEAK;
+ return 1;
+ }
-int X509V3_EXT_add_rfc6962(void)
+/* Check security of a chain, if sk includes the end entity certificate
+ * then x is NULL. If vfy is 1 then we are verifying a peer chain and
+ * not sending one to the peer.
+ * Return values: 1 if ok otherwise error code to use
+ */
+
+int ssl_security_cert_chain(SSL *s, STACK_OF(X509) *sk, X509 *x, int vfy)
{
- if (!X509V3_EXT_add(&ext_method_ct_precert_scts))
- return 0;
- if (!X509V3_EXT_add(&ext_method_ct_cert_scts))
- return 0;
+ int rv, start_idx, i;
+ if (x == NULL)
+ {
+ x = sk_X509_value(sk, 0);
+ start_idx = 1;
+ }
+ else
+ start_idx = 0;
+
+ rv = ssl_security_cert(s, NULL, x, vfy, 1);
+ if (rv != 1)
+ return rv;
+
+ for (i = start_idx; i < sk_X509_num(sk); i++)
+ {
+ x = sk_X509_value(sk, i);
+ rv = ssl_security_cert(s, NULL, x, vfy, 0);
+ if (rv != 1)
+ return rv;
+ }
return 1;
}