X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=ssl%2Fs3_both.c;h=0a259b1f4f6cbbace47c844b0428a1157fe0e15e;hp=a6d869df59e862be10547a97afd1168b7196ea44;hb=8d65fdb62e517281350372775b5f93fcc8489681;hpb=a3a06e6543bf05511cc2f508ad555a281c801326 diff --git a/ssl/s3_both.c b/ssl/s3_both.c index a6d869df59..0a259b1f4f 100644 --- a/ssl/s3_both.c +++ b/ssl/s3_both.c @@ -150,20 +150,20 @@ int ssl3_do_write(SSL *s, int type) int ssl3_send_finished(SSL *s, int a, int b, const char *sender, int slen) { - unsigned char *p,*d; + unsigned char *p; int i; unsigned long l; if (s->state == a) { - d=(unsigned char *)s->init_buf->data; - p= &(d[4]); + p = ssl_handshake_start(s); i=s->method->ssl3_enc->final_finish_mac(s, sender,slen,s->s3->tmp.finish_md); + if (i == 0) + return 0; s->s3->tmp.finish_md_len = i; memcpy(p, s->s3->tmp.finish_md, i); - p+=i; l=i; /* Copy the finished so we can use it for @@ -189,18 +189,40 @@ int ssl3_send_finished(SSL *s, int a, int b, const char *sender, int slen) */ l&=0xffff; #endif - - *(d++)=SSL3_MT_FINISHED; - l2n3(l,d); - s->init_num=(int)l+4; - s->init_off=0; - + ssl_set_handshake_header(s, SSL3_MT_FINISHED, l); s->state=b; } /* SSL3_ST_SEND_xxxxxx_HELLO_B */ - return(ssl3_do_write(s,SSL3_RT_HANDSHAKE)); + return ssl_do_write(s); + } + +#ifndef OPENSSL_NO_NEXTPROTONEG +/* ssl3_take_mac calculates the Finished MAC for the handshakes messages seen to far. */ +static void ssl3_take_mac(SSL *s) + { + const char *sender; + int slen; + /* If no new cipher setup return immediately: other functions will + * set the appropriate error. + */ + if (s->s3->tmp.new_cipher == NULL) + return; + if (s->state & SSL_ST_CONNECT) + { + sender=s->method->ssl3_enc->server_finished_label; + slen=s->method->ssl3_enc->server_finished_label_len; + } + else + { + sender=s->method->ssl3_enc->client_finished_label; + slen=s->method->ssl3_enc->client_finished_label_len; + } + + s->s3->tmp.peer_finish_md_len = s->method->ssl3_enc->final_finish_mac(s, + sender,slen,s->s3->tmp.peer_finish_md); } +#endif int ssl3_get_finished(SSL *s, int a, int b) { @@ -208,9 +230,11 @@ int ssl3_get_finished(SSL *s, int a, int b) long n; unsigned char *p; +#ifdef OPENSSL_NO_NEXTPROTONEG /* the mac has already been generated when we received the * change cipher spec message and is in s->s3->tmp.peer_finish_md */ +#endif n=s->method->ssl_get_message(s, a, @@ -240,7 +264,7 @@ int ssl3_get_finished(SSL *s, int a, int b) goto f_err; } - if (memcmp(p, s->s3->tmp.peer_finish_md, i) != 0) + if (CRYPTO_memcmp(p, s->s3->tmp.peer_finish_md, i) != 0) { al=SSL_AD_DECRYPT_ERROR; SSLerr(SSL_F_SSL3_GET_FINISHED,SSL_R_DIGEST_CHECK_FAILED); @@ -296,94 +320,20 @@ int ssl3_send_change_cipher_spec(SSL *s, int a, int b) return(ssl3_do_write(s,SSL3_RT_CHANGE_CIPHER_SPEC)); } -static int ssl3_add_cert_to_buf(BUF_MEM *buf, unsigned long *l, X509 *x) +unsigned long ssl3_output_cert_chain(SSL *s, CERT_PKEY *cpk) { - int n; unsigned char *p; + unsigned long l = 3 + SSL_HM_HEADER_LENGTH(s); - n=i2d_X509(x,NULL); - if (!BUF_MEM_grow_clean(buf,(int)(n+(*l)+3))) - { - SSLerr(SSL_F_SSL3_ADD_CERT_TO_BUF,ERR_R_BUF_LIB); - return(-1); - } - p=(unsigned char *)&(buf->data[*l]); - l2n3(n,p); - i2d_X509(x,&p); - *l+=n+3; - - return(0); - } - -unsigned long ssl3_output_cert_chain(SSL *s, X509 *x) - { - unsigned char *p; - int i; - unsigned long l=7; - BUF_MEM *buf; - int no_chain; - - if ((s->mode & SSL_MODE_NO_AUTO_CHAIN) || s->ctx->extra_certs) - no_chain = 1; - else - no_chain = 0; - - /* TLSv1 sends a chain with nothing in it, instead of an alert */ - buf=s->init_buf; - if (!BUF_MEM_grow_clean(buf,10)) - { - SSLerr(SSL_F_SSL3_OUTPUT_CERT_CHAIN,ERR_R_BUF_LIB); - return(0); - } - if (x != NULL) - { - if (no_chain) - { - if (ssl3_add_cert_to_buf(buf, &l, x)) - return(0); - } - else - { - X509_STORE_CTX xs_ctx; - - if (!X509_STORE_CTX_init(&xs_ctx,s->ctx->cert_store,x,NULL)) - { - SSLerr(SSL_F_SSL3_OUTPUT_CERT_CHAIN,ERR_R_X509_LIB); - return(0); - } - X509_verify_cert(&xs_ctx); - /* Don't leave errors in the queue */ - ERR_clear_error(); - for (i=0; i < sk_X509_num(xs_ctx.chain); i++) - { - x = sk_X509_value(xs_ctx.chain, i); - - if (ssl3_add_cert_to_buf(buf, &l, x)) - { - X509_STORE_CTX_cleanup(&xs_ctx); - return 0; - } - } - X509_STORE_CTX_cleanup(&xs_ctx); - } - } - /* Thawte special :-) */ - for (i=0; ictx->extra_certs); i++) - { - x=sk_X509_value(s->ctx->extra_certs,i); - if (ssl3_add_cert_to_buf(buf, &l, x)) - return(0); - } + if (!ssl_add_cert_chain(s, cpk, &l)) + return 0; - l-=7; - p=(unsigned char *)&(buf->data[4]); - l2n3(l,p); - l+=3; - p=(unsigned char *)&(buf->data[0]); - *(p++)=SSL3_MT_CERTIFICATE; + l -= 3 + SSL_HM_HEADER_LENGTH(s); + p = ssl_handshake_start(s); l2n3(l,p); - l+=4; - return(l); + l += 3; + ssl_set_handshake_header(s, SSL3_MT_CERTIFICATE, l); + return l + SSL_HM_HEADER_LENGTH(s); } /* Obtain handshake message of message type 'mt' (any if mt == -1), @@ -514,6 +464,15 @@ long ssl3_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok) s->init_num += i; n -= i; } + +#ifndef OPENSSL_NO_NEXTPROTONEG + /* If receiving Finished, record MAC of prior handshake messages for + * Finished verification. */ + if (*s->init_buf->data == SSL3_MT_FINISHED) + ssl3_take_mac(s); +#endif + + /* Feed this message into MAC computation. */ ssl3_finish_mac(s, (unsigned char *)s->init_buf->data, s->init_num + 4); if (s->msg_callback) s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, s->init_buf->data, (size_t)s->init_num + 4, s, s->msg_callback_arg); @@ -560,6 +519,18 @@ int ssl_cert_type(X509 *x, EVP_PKEY *pkey) { ret = SSL_PKEY_GOST01; } + else if (x && (i == EVP_PKEY_DH || i == EVP_PKEY_DHX)) + { + /* For DH two cases: DH certificate signed with RSA and + * DH certificate signed with DSA. + */ + i = X509_certificate_type(x, pk); + if (i & EVP_PKS_RSA) + ret = SSL_PKEY_DH_RSA; + else if (i & EVP_PKS_DSA) + ret = SSL_PKEY_DH_DSA; + } + err: if(!pkey) EVP_PKEY_free(pk); return(ret);