summaryrefslogtreecommitdiff
path: root/ssl/s3_both.c
diff options
context:
space:
mode:
Diffstat (limited to 'ssl/s3_both.c')
-rw-r--r--ssl/s3_both.c114
1 files changed, 92 insertions, 22 deletions
diff --git a/ssl/s3_both.c b/ssl/s3_both.c
index 8ce6b3b..6604fc7 100644
--- a/ssl/s3_both.c
+++ b/ssl/s3_both.c
@@ -118,8 +118,10 @@
#include <openssl/buf.h>
#include <openssl/evp.h>
#include <openssl/mem.h>
+#include <openssl/md5.h>
#include <openssl/obj.h>
#include <openssl/rand.h>
+#include <openssl/sha.h>
#include <openssl/x509.h>
#include "ssl_locl.h"
@@ -166,6 +168,14 @@ int ssl3_send_finished(SSL *s, int a, int b, const char *sender, int slen)
memcpy(p, s->s3->tmp.finish_md, i);
l=i;
+ /* Log the master secret, if logging is enabled. */
+ if (!ssl_ctx_log_master_secret(s->ctx,
+ s->s3->client_random, SSL3_RANDOM_SIZE,
+ s->session->master_key, s->session->master_key_length))
+ {
+ return 0;
+ }
+
/* Copy the finished so we can use it for
renegotiation checks */
if(s->type == SSL_ST_CONNECT)
@@ -191,7 +201,6 @@ int ssl3_send_finished(SSL *s, int a, int b, const char *sender, int slen)
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)
{
@@ -216,7 +225,6 @@ static void ssl3_take_mac(SSL *s)
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)
{
@@ -224,21 +232,20 @@ 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,
b,
SSL3_MT_FINISHED,
64, /* should actually be 36+4 :-) */
+ SSL_GET_MESSAGE_DONT_HASH_MESSAGE,
&ok);
if (!ok) return((int)n);
+ /* Snapshot the finished hash before incorporating the new message. */
+ ssl3_take_mac(s);
+ ssl3_hash_current_message(s);
+
/* If this occurs, we have missed a message.
* TODO(davidben): Is this check now redundant with
* SSL3_FLAGS_EXPECT_CCS? */
@@ -337,7 +344,7 @@ unsigned long ssl3_output_cert_chain(SSL *s, CERT_PKEY *cpk)
* The first four bytes (msg_type and length) are read in state 'st1',
* the body is read in state 'stn'.
*/
-long ssl3_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok)
+long ssl3_get_message(SSL *s, int st1, int stn, int mt, long max, int hash_message, int *ok)
{
unsigned char *p;
unsigned long l;
@@ -346,6 +353,10 @@ long ssl3_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok)
if (s->s3->tmp.reuse_message)
{
+ /* A SSL_GET_MESSAGE_DONT_HASH_MESSAGE call cannot be combined
+ * with reuse_message; the SSL_GET_MESSAGE_DONT_HASH_MESSAGE
+ * would have to have been applied to the previous call. */
+ assert(hash_message != SSL_GET_MESSAGE_DONT_HASH_MESSAGE);
s->s3->tmp.reuse_message=0;
if ((mt >= 0) && (s->s3->tmp.message_type != mt))
{
@@ -461,16 +472,9 @@ long ssl3_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok)
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. */
- if (*((unsigned char*) s->init_buf->data) != SSL3_MT_ENCRYPTED_EXTENSIONS)
- ssl3_finish_mac(s, (unsigned char *)s->init_buf->data, s->init_num + 4);
+ if (hash_message != SSL_GET_MESSAGE_DONT_HASH_MESSAGE)
+ ssl3_hash_current_message(s);
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);
*ok=1;
@@ -482,6 +486,73 @@ err:
return(-1);
}
+void ssl3_hash_current_message(SSL *s)
+ {
+ /* The handshake header (different size between DTLS and TLS) is included in the hash. */
+ size_t header_len = s->init_msg - (uint8_t *)s->init_buf->data;
+ ssl3_finish_mac(s, (uint8_t *)s->init_buf->data, s->init_num + header_len);
+ }
+
+/* ssl3_cert_verify_hash is documented as needing EVP_MAX_MD_SIZE because that
+ * is sufficient pre-TLS1.2 as well. */
+OPENSSL_COMPILE_ASSERT(EVP_MAX_MD_SIZE > MD5_DIGEST_LENGTH + SHA_DIGEST_LENGTH,
+ combined_tls_hash_fits_in_max);
+
+int ssl3_cert_verify_hash(SSL *s, uint8_t *out, size_t *out_len, const EVP_MD **out_md, EVP_PKEY *pkey)
+ {
+ /* For TLS v1.2 send signature algorithm and signature using
+ * agreed digest and cached handshake records. Otherwise, use
+ * SHA1 or MD5 + SHA1 depending on key type. */
+ if (SSL_USE_SIGALGS(s))
+ {
+ const uint8_t *hdata;
+ size_t hdatalen;
+ EVP_MD_CTX mctx;
+ unsigned len;
+
+ if (!BIO_mem_contents(s->s3->handshake_buffer, &hdata, &hdatalen))
+ {
+ OPENSSL_PUT_ERROR(SSL, ssl3_cert_verify_hash, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ EVP_MD_CTX_init(&mctx);
+ if (!EVP_DigestInit_ex(&mctx, *out_md, NULL)
+ || !EVP_DigestUpdate(&mctx, hdata, hdatalen)
+ || !EVP_DigestFinal(&mctx, out, &len))
+ {
+ OPENSSL_PUT_ERROR(SSL, ssl3_cert_verify_hash, ERR_R_EVP_LIB);
+ EVP_MD_CTX_cleanup(&mctx);
+ return 0;
+ }
+ *out_len = len;
+ }
+ else if (pkey->type == EVP_PKEY_RSA)
+ {
+ if (s->method->ssl3_enc->cert_verify_mac(s, NID_md5, out) == 0 ||
+ s->method->ssl3_enc->cert_verify_mac(s,
+ NID_sha1, out + MD5_DIGEST_LENGTH) == 0)
+ return 0;
+ *out_len = MD5_DIGEST_LENGTH + SHA_DIGEST_LENGTH;
+ /* Using a NULL signature MD makes EVP_PKEY_sign perform
+ * a raw RSA signature, rather than wrapping in a
+ * DigestInfo. */
+ *out_md = NULL;
+ }
+ else if (pkey->type == EVP_PKEY_EC)
+ {
+ if (s->method->ssl3_enc->cert_verify_mac(s, NID_sha1, out) == 0)
+ return 0;
+ *out_len = SHA_DIGEST_LENGTH;
+ *out_md = EVP_sha1();
+ }
+ else
+ {
+ OPENSSL_PUT_ERROR(SSL, ssl3_cert_verify_hash, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ return 1;
+ }
+
int ssl_cert_type(X509 *x, EVP_PKEY *pkey)
{
EVP_PKEY *pk;
@@ -498,12 +569,10 @@ int ssl_cert_type(X509 *x, EVP_PKEY *pkey)
{
ret=SSL_PKEY_RSA_ENC;
}
-#ifndef OPENSSL_NO_EC
else if (i == EVP_PKEY_EC)
{
ret = SSL_PKEY_ECC;
}
-#endif
err:
if(!pkey) EVP_PKEY_free(pk);
@@ -627,8 +696,9 @@ int ssl3_setup_write_buffer(SSL *s)
len = s->max_send_fragment
+ SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD
+ headerlen + align;
- if (!(s->options & SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS))
- len += headerlen + align
+ /* Account for 1/n-1 record splitting. */
+ if (s->mode & SSL_MODE_CBC_RECORD_SPLITTING)
+ len += headerlen + align + 1
+ SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD;
if ((p=OPENSSL_malloc(len)) == NULL)