Newer
Older
}
if (peer == NULL)
{
SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_NO_CLIENT_CERT_RECEIVED);
al=SSL_AD_UNEXPECTED_MESSAGE;
goto f_err;
}
if (!(type & EVP_PKT_SIGN))
{
SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE);
al=SSL_AD_ILLEGAL_PARAMETER;
goto f_err;
}
if (s->s3->change_cipher_spec)
{
SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_CCS_RECEIVED_EARLY);
al=SSL_AD_UNEXPECTED_MESSAGE;
goto f_err;
}
/* we now have a signature that we need to verify */
p=(unsigned char *)s->init_msg;
/* Check for broken implementations of GOST ciphersuites */
/* If key is GOST and n is exactly 64, it is bare
* signature without length field */
if (n==64 && (pkey->type==NID_id_GostR3410_94 ||
pkey->type == NID_id_GostR3410_2001) )
i=64;
}
else
{
Dr. Stephen Henson
committed
if (TLS1_get_version(s) >= TLS1_2_VERSION)
Dr. Stephen Henson
committed
{
int sigalg = tls12_get_sigid(pkey);
/* Should never happen */
if (sigalg == -1)
{
SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,ERR_R_INTERNAL_ERROR);
al=SSL_AD_INTERNAL_ERROR;
goto f_err;
}
/* Check key type is consistent with signature */
if (sigalg != (int)p[1])
{
SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_WRONG_SIGNATURE_TYPE);
al=SSL_AD_DECODE_ERROR;
goto f_err;
}
md = tls12_get_hash(p[0]);
if (md == NULL)
{
SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_UNKNOWN_DIGEST);
Dr. Stephen Henson
committed
al=SSL_AD_DECODE_ERROR;
goto f_err;
}
#ifdef SSL_DEBUG
fprintf(stderr, "USING TLSv1.2 HASH %s\n", EVP_MD_name(md));
#endif
p += 2;
n -= 2;
}
n2s(p,i);
n-=2;
if (i > n)
{
SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_LENGTH_MISMATCH);
al=SSL_AD_DECODE_ERROR;
goto f_err;
}
}
j=EVP_PKEY_size(pkey);
if ((i > j) || (n > j) || (n <= 0))
{
SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_WRONG_SIGNATURE_SIZE);
al=SSL_AD_DECODE_ERROR;
goto f_err;
}
Dr. Stephen Henson
committed
if (TLS1_get_version(s) >= TLS1_2_VERSION)
Dr. Stephen Henson
committed
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
{
long hdatalen = 0;
void *hdata;
hdatalen = BIO_get_mem_data(s->s3->handshake_buffer, &hdata);
if (hdatalen <= 0)
{
SSLerr(SSL_F_SSL3_GET_CERT_VERIFY, ERR_R_INTERNAL_ERROR);
al=SSL_AD_INTERNAL_ERROR;
goto f_err;
}
#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
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
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
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
/* 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));
}
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
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));
}
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
# 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