{
STACK_OF(SSL_CIPHER) *sk;
const SSL_CIPHER *c;
+ CERT *ct = s->cert;
unsigned char *p,*d;
int i,al=SSL_AD_INTERNAL_ERROR,ok;
unsigned int j;
SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_UNKNOWN_CIPHER_RETURNED);
goto f_err;
}
- /* TLS v1.2 only ciphersuites require v1.2 or later */
- if ((c->algorithm_ssl & SSL_TLSV1_2) &&
- (TLS1_get_version(s) < TLS1_2_VERSION))
+ /* If it is a disabled cipher we didn't send it in client hello,
+ * so return an error.
+ */
+ if (c->algorithm_ssl & ct->mask_ssl ||
+ c->algorithm_mkey & ct->mask_k ||
+ c->algorithm_auth & ct->mask_a)
{
al=SSL_AD_ILLEGAL_PARAMETER;
SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_WRONG_CIPHER_RETURNED);
* and the ECParameters in this case is just three bytes.
*/
param_len=3;
- if ((param_len > n) ||
- (*p != NAMED_CURVE_TYPE) ||
- ((curve_nid = tls1_ec_curve_id2nid(*(p + 2))) == 0))
+ /* Check curve is one of our prefrences, if not server has
+ * sent an invalid curve.
+ */
+ if (!tls1_check_curve(s, p, param_len))
+ {
+ al=SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_WRONG_CURVE);
+ goto f_err;
+ }
+
+ if ((curve_nid = tls1_ec_curve_id2nid(*(p + 2))) == 0)
{
al=SSL_AD_INTERNAL_ERROR;
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS);
{
if (TLS1_get_version(s) >= TLS1_2_VERSION)
{
- int sigalg = tls12_get_sigid(pkey);
- /* Should never happen */
- if (sigalg == -1)
- {
- SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
+ int rv = tls12_check_peer_sigalg(&md, s, p, pkey);
+ if (rv == -1)
goto err;
- }
- /* Check key type is consistent with signature */
- if (sigalg != (int)p[1])
- {
- SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_WRONG_SIGNATURE_TYPE);
- al=SSL_AD_DECODE_ERROR;
- goto f_err;
- }
- md = tls12_get_hash(p[0]);
- if (md == NULL)
+ else if (rv == 0)
{
- SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_UNKNOWN_DIGEST);
- al=SSL_AD_DECODE_ERROR;
+ al = SSL_AD_DECODE_ERROR;
goto f_err;
}
#ifdef SSL_DEBUG
/* get the certificate types */
ctype_num= *(p++);
+ if (s->cert->ctypes)
+ {
+ OPENSSL_free(s->cert->ctypes);
+ s->cert->ctypes = NULL;
+ }
if (ctype_num > SSL3_CT_NUMBER)
+ {
+ /* If we exceed static buffer copy all to cert structure */
+ s->cert->ctypes = OPENSSL_malloc(ctype_num);
+ memcpy(s->cert->ctypes, p, ctype_num);
+ s->cert->ctype_num = (size_t)ctype_num;
ctype_num=SSL3_CT_NUMBER;
+ }
for (i=0; i<ctype_num; i++)
s->s3->tmp.ctype[i]= p[i];
- p+=ctype_num;
+ p+=p[-1];
if (TLS1_get_version(s) >= TLS1_2_VERSION)
{
n2s(p, llen);
SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,SSL_R_DATA_LENGTH_TOO_LONG);
goto err;
}
+ /* 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 ((llen & 1) || !tls1_process_sigalgs(s, p, llen))
{
ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECODE_ERROR);
}
/* Check a certificate can be used for client authentication. Currently
- * just check cert exists and if static DH client certificates can be used.
+ * check cert exists, if we have a suitable digest for TLS 1.2 and if
+ * static DH client certificates can be used.
*/
static int ssl3_check_client_certificate(SSL *s)
{
unsigned long alg_k;
if (!s->cert || !s->cert->key->x509 || !s->cert->key->privatekey)
return 0;
+ /* If no suitable signature algorithm can't use certificate */
+ if (TLS1_get_version(s) >= TLS1_2_VERSION && !s->cert->key->digest)
+ return 0;
alg_k=s->s3->tmp.new_cipher->algorithm_mkey;
/* See if we can use client certificate for fixed DH */
if (alg_k & (SSL_kDHr|SSL_kDHd))
if (s->state == SSL3_ST_CW_CERT_A)
{
+ /* Let cert callback update client certificates if required */
+ if (s->cert->cert_cb
+ && s->cert->cert_cb(s, s->cert->cert_cb_arg) <= 0)
+ {
+ ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_INTERNAL_ERROR);
+ return 0;
+ }
if (ssl3_check_client_certificate(s))
s->state=SSL3_ST_CW_CERT_C;
else