Newer
Older
Dr. Stephen Henson
committed
#ifdef SSL_DEBUG
fprintf(stderr, "Using TLS 1.2 with client verify alg %s\n",
EVP_MD_name(md));
#endif
if (!EVP_VerifyInit_ex(&mctx, md, NULL)
|| !EVP_VerifyUpdate(&mctx, hdata, hdatalen))
{
SSLerr(SSL_F_SSL3_GET_CERT_VERIFY, ERR_R_EVP_LIB);
al=SSL_AD_INTERNAL_ERROR;
goto f_err;
}
if (EVP_VerifyFinal(&mctx, p , i, pkey) <= 0)
{
al=SSL_AD_DECRYPT_ERROR;
SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_BAD_SIGNATURE);
goto f_err;
}
}
else
#ifndef OPENSSL_NO_RSA
if (pkey->type == EVP_PKEY_RSA)
{
i=RSA_verify(NID_md5_sha1, s->s3->tmp.cert_verify_md,
Dr. Stephen Henson
committed
MD5_DIGEST_LENGTH+SHA_DIGEST_LENGTH, p, i,
pkey->pkey.rsa);
al=SSL_AD_DECRYPT_ERROR;
SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_BAD_RSA_DECRYPT);
goto f_err;
}
Dr. Stephen Henson
committed
if (i == 0)
al=SSL_AD_DECRYPT_ERROR;
SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_BAD_RSA_SIGNATURE);
goto f_err;
}
}
else
#endif
#ifndef OPENSSL_NO_DSA
if (pkey->type == EVP_PKEY_DSA)
{
j=DSA_verify(pkey->save_type,
&(s->s3->tmp.cert_verify_md[MD5_DIGEST_LENGTH]),
SHA_DIGEST_LENGTH,p,i,pkey->pkey.dsa);
if (j <= 0)
{
/* bad signature */
al=SSL_AD_DECRYPT_ERROR;
SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_BAD_DSA_SIGNATURE);
goto f_err;
}
}
else
if (pkey->type == EVP_PKEY_EC)
{
j=ECDSA_verify(pkey->save_type,
&(s->s3->tmp.cert_verify_md[MD5_DIGEST_LENGTH]),
if (j <= 0)
{
/* bad signature */
al=SSL_AD_DECRYPT_ERROR;
SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,
SSL_R_BAD_ECDSA_SIGNATURE);
goto f_err;
}
}
else
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
if (pkey->type == NID_id_GostR3410_94 || pkey->type == NID_id_GostR3410_2001)
{ unsigned char signature[64];
int idx;
EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new(pkey,NULL);
EVP_PKEY_verify_init(pctx);
if (i!=64) {
fprintf(stderr,"GOST signature length is %d",i);
}
for (idx=0;idx<64;idx++) {
signature[63-idx]=p[idx];
}
j=EVP_PKEY_verify(pctx,signature,64,s->s3->tmp.cert_verify_md,32);
EVP_PKEY_CTX_free(pctx);
if (j<=0)
{
al=SSL_AD_DECRYPT_ERROR;
SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,
SSL_R_BAD_ECDSA_SIGNATURE);
goto f_err;
}
}
else
SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,ERR_R_INTERNAL_ERROR);
al=SSL_AD_UNSUPPORTED_CERTIFICATE;
goto f_err;
}
ret=1;
if (0)
{
f_err:
ssl3_send_alert(s,SSL3_AL_FATAL,al);
}
end:
Dr. Stephen Henson
committed
if (s->s3->handshake_buffer)
{
BIO_free(s->s3->handshake_buffer);
s->s3->handshake_buffer = NULL;
s->s3->flags &= ~TLS1_FLAGS_KEEP_HANDSHAKE;
}
EVP_MD_CTX_cleanup(&mctx);
EVP_PKEY_free(pkey);
return(ret);
}
{
int i,ok,al,ret= -1;
X509 *x=NULL;
unsigned long l,nc,llen,n;
const unsigned char *p,*q;
unsigned char *d;
SSL3_ST_SR_CERT_A,
SSL3_ST_SR_CERT_B,
-1,
s->max_cert_list,
&ok);
if (!ok) return((int)n);
if (s->s3->tmp.message_type == SSL3_MT_CLIENT_KEY_EXCHANGE)
{
if ( (s->verify_mode & SSL_VERIFY_PEER) &&
(s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT))
{
SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE);
al=SSL_AD_HANDSHAKE_FAILURE;
goto f_err;
}
/* If tls asked for a client cert, the client must return a 0 list */
if ((s->version > SSL3_VERSION) && s->s3->tmp.cert_request)
{
SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST);
al=SSL_AD_UNEXPECTED_MESSAGE;
goto f_err;
}
s->s3->tmp.reuse_message=1;
return(1);
}
if (s->s3->tmp.message_type != SSL3_MT_CERTIFICATE)
{
al=SSL_AD_UNEXPECTED_MESSAGE;
SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_WRONG_MESSAGE_TYPE);
goto f_err;
}
p=d=(unsigned char *)s->init_msg;
{
SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,ERR_R_MALLOC_FAILURE);
goto err;
}
n2l3(p,llen);
if (llen+3 != n)
{
al=SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_LENGTH_MISMATCH);
goto f_err;
}
for (nc=0; nc<llen; )
{
n2l3(p,l);
if ((l+nc+3) > llen)
{
al=SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_CERT_LENGTH_MISMATCH);
goto f_err;
}
q=p;
x=d2i_X509(NULL,&p,l);
if (x == NULL)
{
SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,ERR_R_ASN1_LIB);
goto err;
}
if (p != (q+l))
{
al=SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_CERT_LENGTH_MISMATCH);
goto f_err;
}
{
SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,ERR_R_MALLOC_FAILURE);
goto err;
}
x=NULL;
nc+=l+3;
}
/* TLS does not mind 0 certs returned */
if (s->version == SSL3_VERSION)
{
al=SSL_AD_HANDSHAKE_FAILURE;
SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_NO_CERTIFICATES_RETURNED);
goto f_err;
}
/* Fail for TLS only if we required a certificate */
else if ((s->verify_mode & SSL_VERIFY_PEER) &&
(s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT))
{
SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE);
al=SSL_AD_HANDSHAKE_FAILURE;
goto f_err;
}
Dr. Stephen Henson
committed
/* No client certificate so digest cached records */
if (s->s3->handshake_buffer && !ssl3_digest_cached_records(s))
{
al=SSL_AD_INTERNAL_ERROR;
goto f_err;
}
i=ssl_verify_cert_chain(s,sk);
{
al=ssl_verify_alarm_type(s->verify_result);
SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_NO_CERTIFICATE_RETURNED);
goto f_err;
}
if (s->session->peer != NULL) /* This should not be needed */
X509_free(s->session->peer);
s->session->verify_result = s->verify_result;
/* With the current implementation, sess_cert will always be NULL
* when we arrive here. */
if (s->session->sess_cert == NULL)
{
s->session->sess_cert = ssl_sess_cert_new();
if (s->session->sess_cert == NULL)
{
SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE, ERR_R_MALLOC_FAILURE);
goto err;
}
}
if (s->session->sess_cert->cert_chain != NULL)
sk_X509_pop_free(s->session->sess_cert->cert_chain, X509_free);
s->session->sess_cert->cert_chain=sk;
/* Inconsistency alert: cert_chain does *not* include the
* peer's own certificate, while we do include it in s3_clnt.c */
ret=1;
if (0)
{
f_err:
ssl3_send_alert(s,SSL3_AL_FATAL,al);
}
err:
if (x != NULL) X509_free(x);
if (sk != NULL) sk_X509_pop_free(sk,X509_free);
return(ret);
}
{
unsigned long l;
X509 *x;
if (s->state == SSL3_ST_SW_CERT_A)
{
x=ssl_get_server_send_cert(s);
if (x == NULL)
{
/* VRS: allow null cert if auth == KRB5 */
if ((s->s3->tmp.new_cipher->algorithm_auth != SSL_aKRB5) ||
(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kKRB5))
{
SSLerr(SSL_F_SSL3_SEND_SERVER_CERTIFICATE,ERR_R_INTERNAL_ERROR);
return(0);
}
}
l=ssl3_output_cert_chain(s,x);
s->state=SSL3_ST_SW_CERT_B;
s->init_num=(int)l;
s->init_off=0;
}
/* SSL3_ST_SW_CERT_B */
return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
}
/* send a new session ticket (not necessarily for a new session) */
Dr. Stephen Henson
committed
int ssl3_send_newsession_ticket(SSL *s)
{
if (s->state == SSL3_ST_SW_SESSION_TICKET_A)
{
unsigned char *p, *senc, *macstart;
const unsigned char *const_p;
int len, slen_full, slen;
SSL_SESSION *sess;
Dr. Stephen Henson
committed
unsigned int hlen;
EVP_CIPHER_CTX ctx;
HMAC_CTX hctx;
SSL_CTX *tctx = s->initial_ctx;
unsigned char iv[EVP_MAX_IV_LENGTH];
unsigned char key_name[16];
Dr. Stephen Henson
committed
/* get session encoding length */
Dr. Stephen Henson
committed
/* Some length values are 16 bits, so forget it if session is
* too long
*/
if (slen_full > 0xFF00)
return -1;
senc = OPENSSL_malloc(slen_full);
if (!senc)
return -1;
p = senc;
i2d_SSL_SESSION(s->session, &p);
/* create a fresh copy (not shared with other threads) to clean up */
const_p = senc;
sess = d2i_SSL_SESSION(NULL, &const_p, slen_full);
if (sess == NULL)
{
OPENSSL_free(senc);
Dr. Stephen Henson
committed
return -1;
}
sess->session_id_length = 0; /* ID is irrelevant for the ticket */
slen = i2d_SSL_SESSION(sess, NULL);
if (slen > slen_full) /* shouldn't ever happen */
{
OPENSSL_free(senc);
return -1;
}
p = senc;
i2d_SSL_SESSION(sess, &p);
SSL_SESSION_free(sess);
Dr. Stephen Henson
committed
/* Grow buffer if need be: the length calculation is as
* follows 1 (size of message name) + 3 (message length
* bytes) + 4 (ticket lifetime hint) + 2 (ticket length) +
* 16 (key name) + max_iv_len (iv length) +
* session_length + max_enc_block_size (max encrypted session
* length) + max_md_size (HMAC).
*/
if (!BUF_MEM_grow(s->init_buf,
26 + EVP_MAX_IV_LENGTH + EVP_MAX_BLOCK_LENGTH +
EVP_MAX_MD_SIZE + slen))
return -1;
p=(unsigned char *)s->init_buf->data;
/* do the header */
*(p++)=SSL3_MT_NEWSESSION_TICKET;
/* Skip message length for now */
p += 3;
EVP_CIPHER_CTX_init(&ctx);
HMAC_CTX_init(&hctx);
/* Initialize HMAC and cipher contexts. If callback present
* it does all the work otherwise use generated values
* from parent ctx.
*/
if (tctx->tlsext_ticket_key_cb)
if (tctx->tlsext_ticket_key_cb(s, key_name, iv, &ctx,
&hctx, 1) < 0)
{
OPENSSL_free(senc);
return -1;
}
}
else
{
RAND_pseudo_bytes(iv, 16);
EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL,
tctx->tlsext_tick_aes_key, iv);
HMAC_Init_ex(&hctx, tctx->tlsext_tick_hmac_key, 16,
memcpy(key_name, tctx->tlsext_tick_key_name, 16);
/* Ticket lifetime hint (advisory only):
* We leave this unspecified for resumed session (for simplicity),
* and guess that tickets for new sessions will live as long
* as their sessions. */
l2n(s->hit ? 0 : s->session->timeout, p);
Dr. Stephen Henson
committed
/* Skip ticket length for now */
p += 2;
/* Output key name */
macstart = p;
Dr. Stephen Henson
committed
p += 16;
/* output IV */
memcpy(p, iv, EVP_CIPHER_CTX_iv_length(&ctx));
p += EVP_CIPHER_CTX_iv_length(&ctx);
Dr. Stephen Henson
committed
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
/* Encrypt session data */
EVP_EncryptUpdate(&ctx, p, &len, senc, slen);
p += len;
EVP_EncryptFinal(&ctx, p, &len);
p += len;
EVP_CIPHER_CTX_cleanup(&ctx);
HMAC_Update(&hctx, macstart, p - macstart);
HMAC_Final(&hctx, p, &hlen);
HMAC_CTX_cleanup(&hctx);
p += hlen;
/* Now write out lengths: p points to end of data written */
/* Total length */
len = p - (unsigned char *)s->init_buf->data;
p=(unsigned char *)s->init_buf->data + 1;
l2n3(len - 4, p); /* Message length */
p += 4;
s2n(len - 10, p); /* Ticket length */
/* number of bytes to write */
s->init_num= len;
s->state=SSL3_ST_SW_SESSION_TICKET_B;
s->init_off=0;
OPENSSL_free(senc);
}
/* SSL3_ST_SW_SESSION_TICKET_B */
return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
}
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
int ssl3_send_cert_status(SSL *s)
{
if (s->state == SSL3_ST_SW_CERT_STATUS_A)
{
unsigned char *p;
/* Grow buffer if need be: the length calculation is as
* follows 1 (message type) + 3 (message length) +
* 1 (ocsp response type) + 3 (ocsp response length)
* + (ocsp response)
*/
if (!BUF_MEM_grow(s->init_buf, 8 + s->tlsext_ocsp_resplen))
return -1;
p=(unsigned char *)s->init_buf->data;
/* do the header */
*(p++)=SSL3_MT_CERTIFICATE_STATUS;
/* message length */
l2n3(s->tlsext_ocsp_resplen + 4, p);
/* status type */
*(p++)= s->tlsext_status_type;
/* length of OCSP response */
l2n3(s->tlsext_ocsp_resplen, p);
/* actual response */
memcpy(p, s->tlsext_ocsp_resp, s->tlsext_ocsp_resplen);
/* number of bytes to write */
s->init_num = 8 + s->tlsext_ocsp_resplen;
s->state=SSL3_ST_SW_CERT_STATUS_B;
s->init_off = 0;
}
/* SSL3_ST_SW_CERT_STATUS_B */
return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
}
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
# ifndef OPENSSL_NO_NEXTPROTONEG
/* ssl3_get_next_proto reads a Next Protocol Negotiation handshake message. It
* sets the next_proto member in s if found */
int ssl3_get_next_proto(SSL *s)
{
int ok;
int proto_len, padding_len;
long n;
const unsigned char *p;
/* Clients cannot send a NextProtocol message if we didn't see the
* extension in their ClientHello */
if (!s->s3->next_proto_neg_seen)
{
SSLerr(SSL_F_SSL3_GET_NEXT_PROTO,SSL_R_GOT_NEXT_PROTO_WITHOUT_EXTENSION);
return -1;
}
n=s->method->ssl_get_message(s,
SSL3_ST_SR_NEXT_PROTO_A,
SSL3_ST_SR_NEXT_PROTO_B,
SSL3_MT_NEXT_PROTO,
514, /* See the payload format below */
&ok);
if (!ok)
return((int)n);
/* s->state doesn't reflect whether ChangeCipherSpec has been received
* in this handshake, but s->s3->change_cipher_spec does (will be reset
* by ssl3_get_finished). */
if (!s->s3->change_cipher_spec)
{
SSLerr(SSL_F_SSL3_GET_NEXT_PROTO,SSL_R_GOT_NEXT_PROTO_BEFORE_A_CCS);
return -1;
}
if (n < 2)
return 0; /* The body must be > 1 bytes long */
p=(unsigned char *)s->init_msg;
/* The payload looks like:
* uint8 proto_len;
* uint8 proto[proto_len];
* uint8 padding_len;
* uint8 padding[padding_len];
*/
proto_len = p[0];
if (proto_len + 2 > s->init_num)
return 0;
padding_len = p[proto_len + 1];
if (proto_len + padding_len + 2 != s->init_num)
return 0;
s->next_proto_negotiated = OPENSSL_malloc(proto_len);
if (!s->next_proto_negotiated)
{
SSLerr(SSL_F_SSL3_GET_NEXT_PROTO,ERR_R_MALLOC_FAILURE);
return 0;
}
memcpy(s->next_proto_negotiated, p + 1, proto_len);
s->next_proto_negotiated_len = proto_len;
return 1;
}
# endif