diff options
author | Joel Sing <jsing@cvs.openbsd.org> | 2018-11-08 22:28:53 +0000 |
---|---|---|
committer | Joel Sing <jsing@cvs.openbsd.org> | 2018-11-08 22:28:53 +0000 |
commit | b5c0171116390d8c026d9339e8818fc11d3ac528 (patch) | |
tree | c69d3877512ba3c6448cf3fad9d054e9fe107479 /lib | |
parent | f0d1394b9bcd3fb89a4ce301cdb802c772b3ec32 (diff) |
Clean up and simplify the handshake transcript code.
This provides a cleaner, simpler and more readable API, with code that uses
a BUF_MEM instead of a BIO.
ok beck@ ("hurry up") and tb@.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libssl/d1_both.c | 6 | ||||
-rw-r--r-- | lib/libssl/s3_lib.c | 9 | ||||
-rw-r--r-- | lib/libssl/ssl3.h | 4 | ||||
-rw-r--r-- | lib/libssl/ssl_both.c | 6 | ||||
-rw-r--r-- | lib/libssl/ssl_clnt.c | 46 | ||||
-rw-r--r-- | lib/libssl/ssl_locl.h | 17 | ||||
-rw-r--r-- | lib/libssl/ssl_packet.c | 4 | ||||
-rw-r--r-- | lib/libssl/ssl_srvr.c | 74 | ||||
-rw-r--r-- | lib/libssl/t1_enc.c | 57 | ||||
-rw-r--r-- | lib/libssl/t1_hash.c | 87 |
10 files changed, 144 insertions, 166 deletions
diff --git a/lib/libssl/d1_both.c b/lib/libssl/d1_both.c index 95157630f50..f75604ef68d 100644 --- a/lib/libssl/d1_both.c +++ b/lib/libssl/d1_both.c @@ -1,4 +1,4 @@ -/* $OpenBSD: d1_both.c,v 1.55 2018/09/05 16:58:59 jsing Exp $ */ +/* $OpenBSD: d1_both.c,v 1.56 2018/11/08 22:28:52 jsing Exp $ */ /* * DTLS implementation written by Nagendra Modadugu * (nagendra@cs.stanford.edu) for the OpenSSL project 2005. @@ -360,7 +360,7 @@ dtls1_do_write(SSL *s, int type) xlen = ret - DTLS1_HM_HEADER_LENGTH; } - tls1_finish_mac(s, p, xlen); + tls1_transcript_record(s, p, xlen); } if (ret == s->internal->init_num) { @@ -436,7 +436,7 @@ again: msg_len += DTLS1_HM_HEADER_LENGTH; - tls1_finish_mac(s, p, msg_len); + tls1_transcript_record(s, p, msg_len); if (s->internal->msg_callback) s->internal->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, p, msg_len, s, s->internal->msg_callback_arg); diff --git a/lib/libssl/s3_lib.c b/lib/libssl/s3_lib.c index 356f43a356a..091713d12a4 100644 --- a/lib/libssl/s3_lib.c +++ b/lib/libssl/s3_lib.c @@ -1,4 +1,4 @@ -/* $OpenBSD: s3_lib.c,v 1.175 2018/11/08 20:55:18 jsing Exp $ */ +/* $OpenBSD: s3_lib.c,v 1.176 2018/11/08 22:28:52 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -1567,8 +1567,7 @@ ssl3_free(SSL *s) sk_X509_NAME_pop_free(S3I(s)->tmp.ca_names, X509_NAME_free); - BIO_free(S3I(s)->handshake_buffer); - + tls1_transcript_free(s); tls1_handshake_hash_free(s); free(S3I(s)->alpn_selected); @@ -1602,9 +1601,7 @@ ssl3_clear(SSL *s) rlen = S3I(s)->rbuf.len; wlen = S3I(s)->wbuf.len; - BIO_free(S3I(s)->handshake_buffer); - S3I(s)->handshake_buffer = NULL; - + tls1_transcript_free(s); tls1_handshake_hash_free(s); free(S3I(s)->alpn_selected); diff --git a/lib/libssl/ssl3.h b/lib/libssl/ssl3.h index 726fb9db0b1..cadf7fd3872 100644 --- a/lib/libssl/ssl3.h +++ b/lib/libssl/ssl3.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl3.h,v 1.48 2018/10/24 18:04:50 jsing Exp $ */ +/* $OpenBSD: ssl3.h,v 1.49 2018/11/08 22:28:52 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -350,7 +350,7 @@ typedef struct ssl3_buffer_st { #define SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS 0x0001 #define TLS1_FLAGS_SKIP_CERT_VERIFY 0x0010 -#define TLS1_FLAGS_KEEP_HANDSHAKE 0x0020 +#define TLS1_FLAGS_FREEZE_TRANSCRIPT 0x0020 #define SSL3_FLAGS_CCS_OK 0x0080 #ifndef OPENSSL_NO_SSL_INTERN diff --git a/lib/libssl/ssl_both.c b/lib/libssl/ssl_both.c index 81fd1f80c5e..77ab26e8b53 100644 --- a/lib/libssl/ssl_both.c +++ b/lib/libssl/ssl_both.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl_both.c,v 1.13 2018/10/24 18:04:50 jsing Exp $ */ +/* $OpenBSD: ssl_both.c,v 1.14 2018/11/08 22:28:52 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -146,7 +146,7 @@ ssl3_do_write(SSL *s, int type) * Should not be done for 'Hello Request's, but in that case * we'll ignore the result anyway. */ - tls1_finish_mac(s, + tls1_transcript_record(s, (unsigned char *)&s->internal->init_buf->data[s->internal->init_off], ret); if (ret == s->internal->init_num) { @@ -557,7 +557,7 @@ ssl3_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok) /* Feed this message into MAC computation. */ if (s->internal->mac_packet) { - tls1_finish_mac(s, (unsigned char *)s->internal->init_buf->data, + tls1_transcript_record(s, (unsigned char *)s->internal->init_buf->data, s->internal->init_num + 4); if (s->internal->msg_callback) diff --git a/lib/libssl/ssl_clnt.c b/lib/libssl/ssl_clnt.c index 22e41da953c..c2aa7e81900 100644 --- a/lib/libssl/ssl_clnt.c +++ b/lib/libssl/ssl_clnt.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl_clnt.c,v 1.36 2018/11/08 20:55:18 jsing Exp $ */ +/* $OpenBSD: ssl_clnt.c,v 1.37 2018/11/08 22:28:52 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -244,7 +244,7 @@ ssl3_connect(SSL *s) /* don't push the buffering BIO quite yet */ if (!SSL_IS_DTLS(s)) { - if (!tls1_init_finished_mac(s)) { + if (!tls1_transcript_init(s)) { ret = -1; goto end; } @@ -269,7 +269,7 @@ ssl3_connect(SSL *s) if (SSL_IS_DTLS(s)) { /* every DTLS ClientHello resets Finished MAC */ - if (!tls1_init_finished_mac(s)) { + if (!tls1_transcript_init(s)) { ret = -1; goto end; } @@ -583,7 +583,7 @@ ssl3_connect(SSL *s) /* clean a few things up */ tls1_cleanup_key_block(s); - if (S3I(s)->handshake_buffer != NULL) { + if (S3I(s)->handshake_transcript != NULL) { SSLerror(s, ERR_R_INTERNAL_ERROR); ret = -1; goto end; @@ -988,11 +988,8 @@ ssl3_get_server_hello(SSL *s) * client authentication. */ alg_k = S3I(s)->hs.new_cipher->algorithm_mkey; - if (!(SSL_USE_SIGALGS(s) || (alg_k & SSL_kGOST)) && - !tls1_digest_cached_records(s)) { - al = SSL_AD_INTERNAL_ERROR; - goto f_err; - } + if (!(SSL_USE_SIGALGS(s) || (alg_k & SSL_kGOST))) + tls1_transcript_free(s); if (!CBS_get_u8(&cbs, &compression_method)) goto truncated; @@ -1619,10 +1616,7 @@ ssl3_get_certificate_request(SSL *s) * If we get here we don't need any cached handshake records * as we wont be doing client auth. */ - if (S3I(s)->handshake_buffer) { - if (!tls1_digest_cached_records(s)) - goto err; - } + tls1_transcript_free(s); return (1); } @@ -2372,12 +2366,12 @@ ssl3_send_client_verify(SSL *s) unsigned char data[MD5_DIGEST_LENGTH + SHA_DIGEST_LENGTH]; unsigned char *signature = NULL; unsigned int signature_len; + const unsigned char *hdata; + size_t hdatalen; EVP_PKEY_CTX *pctx = NULL; EVP_PKEY *pkey; EVP_MD_CTX mctx; const EVP_MD *md; - long hdatalen; - void *hdata; EVP_MD_CTX_init(&mctx); @@ -2404,10 +2398,7 @@ ssl3_send_client_verify(SSL *s) goto err; if (!SSL_USE_SIGALGS(s)) { - if (S3I(s)->handshake_buffer) { - if (!tls1_digest_cached_records(s)) - goto err; - } + tls1_transcript_free(s); if (!tls1_handshake_hash_value(s, data, sizeof(data), NULL)) goto err; @@ -2418,10 +2409,9 @@ ssl3_send_client_verify(SSL *s) * using agreed digest and cached handshake records. */ if (SSL_USE_SIGALGS(s)) { - hdatalen = BIO_get_mem_data(S3I(s)->handshake_buffer, - &hdata); md = s->cert->key->digest; - if (hdatalen <= 0 || + + if (!tls1_transcript_data(s, &hdata, &hdatalen) || !tls12_get_hashandsig(&cert_verify, pkey, md)) { SSLerror(s, ERR_R_INTERNAL_ERROR); goto err; @@ -2433,8 +2423,7 @@ ssl3_send_client_verify(SSL *s) SSLerror(s, ERR_R_EVP_LIB); goto err; } - if (!tls1_digest_cached_records(s)) - goto err; + tls1_transcript_free(s); } else if (pkey->type == EVP_PKEY_RSA) { if (RSA_sign(NID_md5_sha1, data, MD5_DIGEST_LENGTH + SHA_DIGEST_LENGTH, signature, @@ -2457,8 +2446,7 @@ ssl3_send_client_verify(SSL *s) size_t sigsize; int nid; - hdatalen = BIO_get_mem_data(S3I(s)->handshake_buffer, &hdata); - if (hdatalen <= 0) { + if (!tls1_transcript_data(s, &hdata, &hdatalen)) { SSLerror(s, ERR_R_INTERNAL_ERROR); goto err; } @@ -2482,8 +2470,7 @@ ssl3_send_client_verify(SSL *s) if (sigsize > UINT_MAX) goto err; signature_len = sigsize; - if (!tls1_digest_cached_records(s)) - goto err; + tls1_transcript_free(s); #endif } else { SSLerror(s, ERR_R_INTERNAL_ERROR); @@ -2563,8 +2550,7 @@ ssl3_send_client_certificate(SSL *s) S3I(s)->tmp.cert_req = 2; /* There is no client certificate to verify. */ - if (!tls1_digest_cached_records(s)) - goto err; + tls1_transcript_free(s); } /* Ok, we have a cert */ diff --git a/lib/libssl/ssl_locl.h b/lib/libssl/ssl_locl.h index 32766de1cfc..3b08f8c7723 100644 --- a/lib/libssl/ssl_locl.h +++ b/lib/libssl/ssl_locl.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl_locl.h,v 1.221 2018/11/08 20:55:18 jsing Exp $ */ +/* $OpenBSD: ssl_locl.h,v 1.222 2018/11/08 22:28:52 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -780,8 +780,8 @@ typedef struct ssl3_state_internal_st { int wpend_ret; /* number of bytes submitted */ const unsigned char *wpend_buf; - /* used during startup, digest all incoming/outgoing packets */ - BIO *handshake_buffer; + /* Transcript of handshake messages that have been sent and received. */ + BUF_MEM *handshake_transcript; /* Rolling hash of handshake messages. */ EVP_MD_CTX *handshake_hash; @@ -1238,11 +1238,14 @@ int tls1_handshake_hash_value(SSL *s, const unsigned char *out, size_t len, size_t *outlen); void tls1_handshake_hash_free(SSL *s); -int tls1_init_finished_mac(SSL *s); -int tls1_finish_mac(SSL *s, const unsigned char *buf, int len); -void tls1_free_digest_list(SSL *s); +int tls1_transcript_init(SSL *s); +void tls1_transcript_free(SSL *s); +int tls1_transcript_append(SSL *s, const unsigned char *buf, size_t len); +int tls1_transcript_data(SSL *s, const unsigned char **data, size_t *len); +void tls1_transcript_freeze(SSL *s); +int tls1_transcript_record(SSL *s, const unsigned char *buf, size_t len); + void tls1_cleanup_key_block(SSL *s); -int tls1_digest_cached_records(SSL *s); int tls1_change_cipher_state(SSL *s, int which); int tls1_setup_key_block(SSL *s); int tls1_enc(SSL *s, int snd); diff --git a/lib/libssl/ssl_packet.c b/lib/libssl/ssl_packet.c index ca5afb7d93c..d8fb409d81f 100644 --- a/lib/libssl/ssl_packet.c +++ b/lib/libssl/ssl_packet.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl_packet.c,v 1.7 2018/10/24 18:04:50 jsing Exp $ */ +/* $OpenBSD: ssl_packet.c,v 1.8 2018/11/08 22:28:52 jsing Exp $ */ /* * Copyright (c) 2016, 2017 Joel Sing <jsing@openbsd.org> * @@ -120,7 +120,7 @@ ssl_convert_sslv2_client_hello(SSL *s) if (n != record_length + 2) return n; - tls1_finish_mac(s, s->internal->packet + 2, + tls1_transcript_record(s, s->internal->packet + 2, s->internal->packet_length - 2); s->internal->mac_packet = 0; diff --git a/lib/libssl/ssl_srvr.c b/lib/libssl/ssl_srvr.c index e7f1f5c9ec0..af9152d3dea 100644 --- a/lib/libssl/ssl_srvr.c +++ b/lib/libssl/ssl_srvr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl_srvr.c,v 1.50 2018/11/08 20:55:18 jsing Exp $ */ +/* $OpenBSD: ssl_srvr.c,v 1.51 2018/11/08 22:28:52 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -248,7 +248,8 @@ ssl3_accept(SSL *s) ret = -1; goto end; } - if (!tls1_init_finished_mac(s)) { + + if (!tls1_transcript_init(s)) { ret = -1; goto end; } @@ -293,7 +294,7 @@ ssl3_accept(SSL *s) S3I(s)->hs.state = SSL3_ST_SW_FLUSH; s->internal->init_num = 0; - if (!tls1_init_finished_mac(s)) { + if (!tls1_transcript_init(s)) { ret = -1; goto end; } @@ -366,7 +367,7 @@ ssl3_accept(SSL *s) S3I(s)->hs.next_state = SSL3_ST_SR_CLNT_HELLO_A; /* HelloVerifyRequest resets Finished MAC. */ - if (!tls1_init_finished_mac(s)) { + if (!tls1_transcript_init(s)) { ret = -1; goto end; } @@ -467,12 +468,9 @@ ssl3_accept(SSL *s) skip = 1; S3I(s)->tmp.cert_request = 0; S3I(s)->hs.state = SSL3_ST_SW_SRVR_DONE_A; - if (!SSL_IS_DTLS(s) && S3I(s)->handshake_buffer) { - if (!tls1_digest_cached_records(s)) { - ret = -1; - goto end; - } - } + + if (!SSL_IS_DTLS(s)) + tls1_transcript_free(s); } else { S3I(s)->tmp.cert_request = 1; if (SSL_IS_DTLS(s)) @@ -565,33 +563,20 @@ ssl3_accept(SSL *s) if (!s->session->peer) break; /* - * For sigalgs freeze the handshake buffer - * at this point and digest cached records. + * Freeze the transcript for use during client + * certificate verification. */ - if (!S3I(s)->handshake_buffer) { - SSLerror(s, ERR_R_INTERNAL_ERROR); - ret = -1; - goto end; - } - s->s3->flags |= TLS1_FLAGS_KEEP_HANDSHAKE; - if (!tls1_digest_cached_records(s)) { - ret = -1; - goto end; - } + tls1_transcript_freeze(s); } else { S3I(s)->hs.state = SSL3_ST_SR_CERT_VRFY_A; s->internal->init_num = 0; + tls1_transcript_free(s); + /* * We need to get hashes here so if there is * a client cert, it can be verified. */ - if (S3I(s)->handshake_buffer) { - if (!tls1_digest_cached_records(s)) { - ret = -1; - goto end; - } - } if (!tls1_handshake_hash_value(s, S3I(s)->tmp.cert_verify_md, sizeof(S3I(s)->tmp.cert_verify_md), @@ -701,7 +686,7 @@ ssl3_accept(SSL *s) /* clean a few things up */ tls1_cleanup_key_block(s); - if (S3I(s)->handshake_buffer != NULL) { + if (S3I(s)->handshake_transcript != NULL) { SSLerror(s, ERR_R_INTERNAL_ERROR); ret = -1; goto end; @@ -1125,12 +1110,8 @@ ssl3_get_client_hello(SSL *s) alg_k = S3I(s)->hs.new_cipher->algorithm_mkey; if (!(SSL_USE_SIGALGS(s) || (alg_k & SSL_kGOST)) || - !(s->verify_mode & SSL_VERIFY_PEER)) { - if (!tls1_digest_cached_records(s)) { - al = SSL_AD_INTERNAL_ERROR; - goto f_err; - } - } + !(s->verify_mode & SSL_VERIFY_PEER)) + tls1_transcript_free(s); /* * We now have the following setup. @@ -2110,10 +2091,10 @@ ssl3_get_cert_verify(SSL *s) EVP_MD_CTX mctx; uint8_t hash_id, sig_id; int al, ok, sigalg, verify; + const unsigned char *hdata; + size_t hdatalen; int type = 0; int ret = 0; - long hdatalen; - void *hdata; long n; EVP_MD_CTX_init(&mctx); @@ -2214,8 +2195,7 @@ ssl3_get_cert_verify(SSL *s) } if (SSL_USE_SIGALGS(s)) { - hdatalen = BIO_get_mem_data(S3I(s)->handshake_buffer, &hdata); - if (hdatalen <= 0) { + if (!tls1_transcript_data(s, &hdata, &hdatalen)) { SSLerror(s, ERR_R_INTERNAL_ERROR); al = SSL_AD_INTERNAL_ERROR; goto f_err; @@ -2265,8 +2245,7 @@ ssl3_get_cert_verify(SSL *s) EVP_PKEY_CTX *pctx; int nid; - hdatalen = BIO_get_mem_data(S3I(s)->handshake_buffer, &hdata); - if (hdatalen <= 0) { + if (!tls1_transcript_data(s, &hdata, &hdatalen)) { SSLerror(s, ERR_R_INTERNAL_ERROR); al = SSL_AD_INTERNAL_ERROR; goto f_err; @@ -2321,11 +2300,7 @@ ssl3_get_cert_verify(SSL *s) ssl3_send_alert(s, SSL3_AL_FATAL, al); } end: - if (S3I(s)->handshake_buffer) { - BIO_free(S3I(s)->handshake_buffer); - S3I(s)->handshake_buffer = NULL; - s->s3->flags &= ~TLS1_FLAGS_KEEP_HANDSHAKE; - } + tls1_transcript_free(s); err: EVP_MD_CTX_cleanup(&mctx); EVP_PKEY_free(pkey); @@ -2427,11 +2402,8 @@ ssl3_get_client_certificate(SSL *s) al = SSL_AD_HANDSHAKE_FAILURE; goto f_err; } - /* No client certificate so digest cached records */ - if (S3I(s)->handshake_buffer && !tls1_digest_cached_records(s)) { - al = SSL_AD_INTERNAL_ERROR; - goto f_err; - } + /* No client certificate so free transcript. */ + tls1_transcript_free(s); } else { i = ssl_verify_cert_chain(s, sk); if (i <= 0) { diff --git a/lib/libssl/t1_enc.c b/lib/libssl/t1_enc.c index 2a38d8de6a2..33158e160ea 100644 --- a/lib/libssl/t1_enc.c +++ b/lib/libssl/t1_enc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: t1_enc.c,v 1.115 2018/10/24 18:04:50 jsing Exp $ */ +/* $OpenBSD: t1_enc.c,v 1.116 2018/11/08 22:28:52 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -157,61 +157,6 @@ tls1_cleanup_key_block(SSL *s) S3I(s)->hs.key_block_len = 0; } -int -tls1_init_finished_mac(SSL *s) -{ - BIO_free(S3I(s)->handshake_buffer); - - S3I(s)->handshake_buffer = BIO_new(BIO_s_mem()); - if (S3I(s)->handshake_buffer == NULL) - return (0); - - (void)BIO_set_close(S3I(s)->handshake_buffer, BIO_CLOSE); - - return (1); -} - -int -tls1_finish_mac(SSL *s, const unsigned char *buf, int len) -{ - if (len < 0) - return 0; - - if (!tls1_handshake_hash_update(s, buf, len)) - return 0; - - if (S3I(s)->handshake_buffer && - !(s->s3->flags & TLS1_FLAGS_KEEP_HANDSHAKE)) { - BIO_write(S3I(s)->handshake_buffer, (void *)buf, len); - return 1; - } - - return 1; -} - -int -tls1_digest_cached_records(SSL *s) -{ - long hdatalen; - void *hdata; - - hdatalen = BIO_get_mem_data(S3I(s)->handshake_buffer, &hdata); - if (hdatalen <= 0) { - SSLerror(s, SSL_R_BAD_HANDSHAKE_LENGTH); - goto err; - } - - if (!(s->s3->flags & TLS1_FLAGS_KEEP_HANDSHAKE)) { - BIO_free(S3I(s)->handshake_buffer); - S3I(s)->handshake_buffer = NULL; - } - - return 1; - - err: - return 0; -} - void tls1_record_sequence_increment(unsigned char *seq) { diff --git a/lib/libssl/t1_hash.c b/lib/libssl/t1_hash.c index a7e46601e83..f514c5290ed 100644 --- a/lib/libssl/t1_hash.c +++ b/lib/libssl/t1_hash.c @@ -1,4 +1,4 @@ -/* $OpenBSD: t1_hash.c,v 1.3 2018/09/05 16:58:59 jsing Exp $ */ +/* $OpenBSD: t1_hash.c,v 1.4 2018/11/08 22:28:52 jsing Exp $ */ /* * Copyright (c) 2017 Joel Sing <jsing@openbsd.org> * @@ -22,9 +22,9 @@ int tls1_handshake_hash_init(SSL *s) { + const unsigned char *data; const EVP_MD *md; - long dlen; - void *data; + size_t len; tls1_handshake_hash_free(s); @@ -42,12 +42,11 @@ tls1_handshake_hash_init(SSL *s) goto err; } - dlen = BIO_get_mem_data(S3I(s)->handshake_buffer, &data); - if (dlen <= 0) { + if (!tls1_transcript_data(s, &data, &len)) { SSLerror(s, SSL_R_BAD_HANDSHAKE_LENGTH); goto err; } - if (!tls1_handshake_hash_update(s, data, dlen)) { + if (!tls1_handshake_hash_update(s, data, len)) { SSLerror(s, ERR_R_EVP_LIB); goto err; } @@ -109,3 +108,79 @@ tls1_handshake_hash_free(SSL *s) EVP_MD_CTX_free(S3I(s)->handshake_hash); S3I(s)->handshake_hash = NULL; } + +int +tls1_transcript_init(SSL *s) +{ + if (S3I(s)->handshake_transcript != NULL) + return 0; + + if ((S3I(s)->handshake_transcript = BUF_MEM_new()) == NULL) + return 0; + + s->s3->flags &= ~TLS1_FLAGS_FREEZE_TRANSCRIPT; + + return 1; +} + +void +tls1_transcript_free(SSL *s) +{ + BUF_MEM_free(S3I(s)->handshake_transcript); + S3I(s)->handshake_transcript = NULL; +} + +int +tls1_transcript_append(SSL *s, const unsigned char *buf, size_t len) +{ + size_t olen, nlen; + + if (S3I(s)->handshake_transcript == NULL) + return 1; + + if (s->s3->flags & TLS1_FLAGS_FREEZE_TRANSCRIPT) + return 1; + + olen = S3I(s)->handshake_transcript->length; + nlen = olen + len; + + if (nlen < olen) + return 0; + + if (BUF_MEM_grow(S3I(s)->handshake_transcript, nlen) == 0) + return 0; + + memcpy(S3I(s)->handshake_transcript->data + olen, buf, len); + + return 1; +} + +int +tls1_transcript_data(SSL *s, const unsigned char **data, size_t *len) +{ + if (S3I(s)->handshake_transcript == NULL) + return 0; + + *data = S3I(s)->handshake_transcript->data; + *len = S3I(s)->handshake_transcript->length; + + return 1; +} + +void +tls1_transcript_freeze(SSL *s) +{ + s->s3->flags |= TLS1_FLAGS_FREEZE_TRANSCRIPT; +} + +int +tls1_transcript_record(SSL *s, const unsigned char *buf, size_t len) +{ + if (!tls1_handshake_hash_update(s, buf, len)) + return 0; + + if (!tls1_transcript_append(s, buf, len)) + return 0; + + return 1; +} |