xref: /dragonfly/crypto/libressl/ssl/ssl_transcript.c (revision 961e30ea7dc61d1112b778ea4981eac68129fb86)
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
tls1_transcript_hash_init(SSL * s)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
tls1_transcript_hash_update(SSL * s,const unsigned char * buf,size_t len)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
tls1_transcript_hash_value(SSL * s,unsigned char * out,size_t len,size_t * outlen)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
tls1_transcript_hash_free(SSL * s)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
tls1_transcript_init(SSL * s)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
tls1_transcript_free(SSL * s)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
tls1_transcript_reset(SSL * s)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
tls1_transcript_append(SSL * s,const unsigned char * buf,size_t len)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
tls1_transcript_data(SSL * s,const unsigned char ** data,size_t * len)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
tls1_transcript_freeze(SSL * s)176 tls1_transcript_freeze(SSL *s)
177 {
178           s->s3->flags |= TLS1_FLAGS_FREEZE_TRANSCRIPT;
179 }
180 
181 void
tls1_transcript_unfreeze(SSL * s)182 tls1_transcript_unfreeze(SSL *s)
183 {
184           s->s3->flags &= ~TLS1_FLAGS_FREEZE_TRANSCRIPT;
185 }
186 
187 int
tls1_transcript_record(SSL * s,const unsigned char * buf,size_t len)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