1 /* $OpenBSD: ssl_transcript.c,v 1.8 2022/07/22 19:54:46 jsing Exp $ */
2 /*
3  * Copyright (c) 2017 Joel Sing <jsing@openbsd.org>
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 #include <openssl/ssl.h>
19 
20 #include "ssl_locl.h"
21 #include "tls_internal.h"
22 
23 int
24 tls1_transcript_hash_init(SSL *s)
25 {
26 	const unsigned char *data;
27 	const EVP_MD *md;
28 	size_t len;
29 
30 	tls1_transcript_hash_free(s);
31 
32 	if (!ssl_get_handshake_evp_md(s, &md)) {
33 		SSLerrorx(ERR_R_INTERNAL_ERROR);
34 		goto err;
35 	}
36 
37 	if ((s->s3->handshake_hash = EVP_MD_CTX_new()) == NULL) {
38 		SSLerror(s, ERR_R_MALLOC_FAILURE);
39 		goto err;
40 	}
41 	if (!EVP_DigestInit_ex(s->s3->handshake_hash, md, NULL)) {
42 		SSLerror(s, ERR_R_EVP_LIB);
43 		goto err;
44 	}
45 
46 	if (!tls1_transcript_data(s, &data, &len)) {
47 		SSLerror(s, SSL_R_BAD_HANDSHAKE_LENGTH);
48 		goto err;
49 	}
50 	if (!tls1_transcript_hash_update(s, data, len)) {
51 		SSLerror(s, ERR_R_EVP_LIB);
52 		goto err;
53 	}
54 
55 	return 1;
56 
57  err:
58 	tls1_transcript_hash_free(s);
59 
60 	return 0;
61 }
62 
63 int
64 tls1_transcript_hash_update(SSL *s, const unsigned char *buf, size_t len)
65 {
66 	if (s->s3->handshake_hash == NULL)
67 		return 1;
68 
69 	return EVP_DigestUpdate(s->s3->handshake_hash, buf, len);
70 }
71 
72 int
73 tls1_transcript_hash_value(SSL *s, unsigned char *out, size_t len,
74     size_t *outlen)
75 {
76 	EVP_MD_CTX *mdctx = NULL;
77 	unsigned int mdlen;
78 	int ret = 0;
79 
80 	if (s->s3->handshake_hash == NULL)
81 		goto err;
82 
83 	if (EVP_MD_CTX_size(s->s3->handshake_hash) > len)
84 		goto err;
85 
86 	if ((mdctx = EVP_MD_CTX_new()) == NULL) {
87 		SSLerror(s, ERR_R_MALLOC_FAILURE);
88 		goto err;
89 	}
90 	if (!EVP_MD_CTX_copy_ex(mdctx, s->s3->handshake_hash)) {
91 		SSLerror(s, ERR_R_EVP_LIB);
92 		goto err;
93 	}
94 	if (!EVP_DigestFinal_ex(mdctx, out, &mdlen)) {
95 		SSLerror(s, ERR_R_EVP_LIB);
96 		goto err;
97 	}
98 	if (outlen != NULL)
99 		*outlen = mdlen;
100 
101 	ret = 1;
102 
103  err:
104 	EVP_MD_CTX_free(mdctx);
105 
106 	return (ret);
107 }
108 
109 void
110 tls1_transcript_hash_free(SSL *s)
111 {
112 	EVP_MD_CTX_free(s->s3->handshake_hash);
113 	s->s3->handshake_hash = NULL;
114 }
115 
116 int
117 tls1_transcript_init(SSL *s)
118 {
119 	if (s->s3->handshake_transcript != NULL)
120 		return 0;
121 
122 	if ((s->s3->handshake_transcript = tls_buffer_new(0)) == NULL)
123 		return 0;
124 
125 	tls1_transcript_reset(s);
126 
127 	return 1;
128 }
129 
130 void
131 tls1_transcript_free(SSL *s)
132 {
133 	tls_buffer_free(s->s3->handshake_transcript);
134 	s->s3->handshake_transcript = NULL;
135 }
136 
137 void
138 tls1_transcript_reset(SSL *s)
139 {
140 	tls_buffer_clear(s->s3->handshake_transcript);
141 
142 	tls1_transcript_unfreeze(s);
143 }
144 
145 int
146 tls1_transcript_append(SSL *s, const unsigned char *buf, size_t len)
147 {
148 	if (s->s3->handshake_transcript == NULL)
149 		return 1;
150 
151 	if (s->s3->flags & TLS1_FLAGS_FREEZE_TRANSCRIPT)
152 		return 1;
153 
154 	return tls_buffer_append(s->s3->handshake_transcript, buf, len);
155 }
156 
157 int
158 tls1_transcript_data(SSL *s, const unsigned char **data, size_t *len)
159 {
160 	CBS cbs;
161 
162 	if (s->s3->handshake_transcript == NULL)
163 		return 0;
164 
165 	if (!tls_buffer_data(s->s3->handshake_transcript, &cbs))
166 		return 0;
167 
168 	/* XXX - change to caller providing a CBS argument. */
169 	*data = CBS_data(&cbs);
170 	*len = CBS_len(&cbs);
171 
172 	return 1;
173 }
174 
175 void
176 tls1_transcript_freeze(SSL *s)
177 {
178 	s->s3->flags |= TLS1_FLAGS_FREEZE_TRANSCRIPT;
179 }
180 
181 void
182 tls1_transcript_unfreeze(SSL *s)
183 {
184 	s->s3->flags &= ~TLS1_FLAGS_FREEZE_TRANSCRIPT;
185 }
186 
187 int
188 tls1_transcript_record(SSL *s, const unsigned char *buf, size_t len)
189 {
190 	if (!tls1_transcript_hash_update(s, buf, len))
191 		return 0;
192 
193 	if (!tls1_transcript_append(s, buf, len))
194 		return 0;
195 
196 	return 1;
197 }
198