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
*/
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)
{
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,
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);
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; i<sk_X509_num(s->ctx->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),
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);
{
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);