Index: openssl/ssl/t1_enc.c |
diff --git a/openssl/ssl/t1_enc.c b/openssl/ssl/t1_enc.c |
index 87b70218653e21553d9f3ba967744b46b96c51ac..d30ce6137ed38873eb717c4a503b6c37239b857b 100644 |
--- a/openssl/ssl/t1_enc.c |
+++ b/openssl/ssl/t1_enc.c |
@@ -1147,53 +1147,79 @@ int tls1_cert_verify_mac(SSL *s, int md_nid, unsigned char *out) |
return((int)ret); |
} |
+/* tls1_handshake_digest calculates the current handshake hash and writes it to |
+ * |out|, which has space for |out_len| bytes. It returns the number of bytes |
+ * written or -1 in the event of an error. This function works on a copy of the |
+ * underlying digests so can be called multiple times and prior to the final |
+ * update etc. */ |
+int tls1_handshake_digest(SSL *s, unsigned char *out, size_t out_len) |
+ { |
+ const EVP_MD *md; |
+ EVP_MD_CTX ctx; |
+ int i, err = 0, len = 0; |
+ long mask; |
+ |
+ EVP_MD_CTX_init(&ctx); |
+ |
+ for (i = 0; ssl_get_handshake_digest(i, &mask, &md); i++) |
+ { |
+ int hash_size; |
+ unsigned int digest_len; |
+ EVP_MD_CTX *hdgst = s->s3->handshake_dgst[i]; |
+ |
+ if ((mask & ssl_get_algorithm2(s)) == 0) |
+ continue; |
+ |
+ hash_size = EVP_MD_size(md); |
+ if (!hdgst || hash_size < 0 || (size_t)hash_size > out_len) |
+ { |
+ err = 1; |
+ break; |
+ } |
+ |
+ if (!EVP_MD_CTX_copy_ex(&ctx, hdgst) || |
+ !EVP_DigestFinal_ex(&ctx, out, &digest_len) || |
+ digest_len != (unsigned int)hash_size) /* internal error */ |
+ { |
+ err = 1; |
+ break; |
+ } |
+ out += digest_len; |
+ out_len -= digest_len; |
+ len += digest_len; |
+ } |
+ |
+ EVP_MD_CTX_cleanup(&ctx); |
+ |
+ if (err != 0) |
+ return -1; |
+ return len; |
+ } |
+ |
int tls1_final_finish_mac(SSL *s, |
const char *str, int slen, unsigned char *out) |
{ |
- unsigned int i; |
- EVP_MD_CTX ctx; |
unsigned char buf[2*EVP_MAX_MD_SIZE]; |
- unsigned char *q,buf2[12]; |
- int idx; |
- long mask; |
+ unsigned char buf2[12]; |
int err=0; |
- const EVP_MD *md; |
+ int digests_len; |
- q=buf; |
- |
- if (s->s3->handshake_buffer) |
+ if (s->s3->handshake_buffer) |
if (!ssl3_digest_cached_records(s)) |
return 0; |
- EVP_MD_CTX_init(&ctx); |
- |
- for (idx=0;ssl_get_handshake_digest(idx,&mask,&md);idx++) |
+ digests_len = tls1_handshake_digest(s, buf, sizeof(buf)); |
+ if (digests_len < 0) |
{ |
- if (mask & ssl_get_algorithm2(s)) |
- { |
- int hashsize = EVP_MD_size(md); |
- if (hashsize < 0 || hashsize > (int)(sizeof buf - (size_t)(q-buf))) |
- { |
- /* internal error: 'buf' is too small for this cipersuite! */ |
- err = 1; |
- } |
- else |
- { |
- EVP_MD_CTX_copy_ex(&ctx,s->s3->handshake_dgst[idx]); |
- EVP_DigestFinal_ex(&ctx,q,&i); |
- if (i != (unsigned int)hashsize) /* can't really happen */ |
- err = 1; |
- q+=i; |
- } |
- } |
+ err = 1; |
+ digests_len = 0; |
} |
- |
+ |
if (!tls1_PRF(ssl_get_algorithm2(s), |
- str,slen, buf,(int)(q-buf), NULL,0, NULL,0, NULL,0, |
+ str,slen, buf, digests_len, NULL,0, NULL,0, NULL,0, |
s->session->master_key,s->session->master_key_length, |
out,buf2,sizeof buf2)) |
err = 1; |
- EVP_MD_CTX_cleanup(&ctx); |
if (err) |
return 0; |