/src/boringssl/ssl/ssl_transcript.cc
Line | Count | Source |
1 | | // Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. |
2 | | // Copyright 2005 Nokia. All rights reserved. |
3 | | // |
4 | | // Licensed under the Apache License, Version 2.0 (the "License"); |
5 | | // you may not use this file except in compliance with the License. |
6 | | // You may obtain a copy of the License at |
7 | | // |
8 | | // https://www.apache.org/licenses/LICENSE-2.0 |
9 | | // |
10 | | // Unless required by applicable law or agreed to in writing, software |
11 | | // distributed under the License is distributed on an "AS IS" BASIS, |
12 | | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | | // See the License for the specific language governing permissions and |
14 | | // limitations under the License. |
15 | | |
16 | | #include <openssl/ssl.h> |
17 | | |
18 | | #include <string_view> |
19 | | |
20 | | #include <openssl/buf.h> |
21 | | #include <openssl/digest.h> |
22 | | #include <openssl/err.h> |
23 | | |
24 | | #include "internal.h" |
25 | | |
26 | | |
27 | | BSSL_NAMESPACE_BEGIN |
28 | | |
29 | 337k | SSLTranscript::SSLTranscript(bool is_dtls) : is_dtls_(is_dtls) {} |
30 | | |
31 | 337k | SSLTranscript::~SSLTranscript() {} |
32 | | |
33 | 170k | bool SSLTranscript::Init() { |
34 | 170k | buffer_.reset(BUF_MEM_new()); |
35 | 170k | if (!buffer_) { |
36 | 0 | return false; |
37 | 0 | } |
38 | | |
39 | 170k | hash_.Reset(); |
40 | 170k | return true; |
41 | 170k | } |
42 | | |
43 | 78.2k | bool SSLTranscript::InitHash(uint16_t version, const SSL_CIPHER *cipher) { |
44 | 78.2k | version_ = version; |
45 | 78.2k | const EVP_MD *md = ssl_get_handshake_digest(version, cipher); |
46 | 78.2k | if (Digest() == md) { |
47 | | // No need to re-hash the buffer. |
48 | 6.57k | return true; |
49 | 6.57k | } |
50 | 71.6k | if (!HashBuffer(hash_.get(), md)) { |
51 | 0 | return false; |
52 | 0 | } |
53 | 71.6k | if (is_dtls_ && version_ >= TLS1_3_VERSION) { |
54 | | // In DTLS 1.3, prior to the call to InitHash, the message (if present) in |
55 | | // the buffer has the DTLS 1.2 header. After the call to InitHash, the TLS |
56 | | // 1.3 header is written by SSLTranscript::Update. If the buffer isn't freed |
57 | | // here, it would have a mix of different header formats and using it would |
58 | | // yield wrong results. However, there's no need for the buffer once the |
59 | | // version and the digest for the cipher suite are known, so the buffer is |
60 | | // freed here to avoid potential misuse of the SSLTranscript object. |
61 | 5.64k | FreeBuffer(); |
62 | 5.64k | } |
63 | 71.6k | return true; |
64 | 71.6k | } |
65 | | |
66 | 72.0k | bool SSLTranscript::HashBuffer(EVP_MD_CTX *ctx, const EVP_MD *digest) const { |
67 | 72.0k | if (!EVP_DigestInit_ex(ctx, digest, nullptr)) { |
68 | 0 | return false; |
69 | 0 | } |
70 | 72.0k | if (!is_dtls_ || version_ < TLS1_3_VERSION) { |
71 | 66.3k | return EVP_DigestUpdate(ctx, buffer_->data, buffer_->length); |
72 | 66.3k | } |
73 | | |
74 | | // If the version is DTLS 1.3 and we still have a buffer, then there should be |
75 | | // at most a single DTLSHandshake message in the buffer, for the ClientHello. |
76 | | // On the server side, the version (DTLS 1.3) and cipher suite are chosen in |
77 | | // response to the first ClientHello, and InitHash is called before that |
78 | | // ClientHello is added to the SSLTranscript, so the buffer is empty if this |
79 | | // SSLTranscript is on the server. |
80 | 5.64k | if (buffer_->length == 0) { |
81 | 3.25k | return true; |
82 | 3.25k | } |
83 | | |
84 | | // On the client side, we can receive either a ServerHello or |
85 | | // HelloRetryRequest in response to the ClientHello. Regardless of which |
86 | | // message we receive, the client code calls InitHash before updating the |
87 | | // transcript with that message, so the ClientHello is the only message in the |
88 | | // buffer. In DTLS 1.3, we need to skip the message_seq, fragment_offset, and |
89 | | // fragment_length fields from the DTLSHandshake message in the buffer. The |
90 | | // structure of a DTLSHandshake message is as follows (RFC 9147, section 5.2): |
91 | | // |
92 | | // struct { |
93 | | // HandshakeType msg_type; /* handshake type */ |
94 | | // uint24 length; /* bytes in message */ |
95 | | // uint16 message_seq; /* DTLS-required field */ |
96 | | // uint24 fragment_offset; /* DTLS-required field */ |
97 | | // uint24 fragment_length; /* DTLS-required field */ |
98 | | // select (msg_type) { |
99 | | // /* omitted for brevity */ |
100 | | // } body; |
101 | | // } DTLSHandshake; |
102 | 2.38k | CBS buf, header; |
103 | 2.38k | CBS_init(&buf, reinterpret_cast<uint8_t *>(buffer_->data), buffer_->length); |
104 | 2.38k | if (!CBS_get_bytes(&buf, &header, 4) || // |
105 | 2.38k | !CBS_skip(&buf, 8) || // |
106 | 2.38k | !EVP_DigestUpdate(ctx, CBS_data(&header), CBS_len(&header)) || // |
107 | 2.38k | !EVP_DigestUpdate(ctx, CBS_data(&buf), CBS_len(&buf))) { |
108 | 0 | return false; |
109 | 0 | } |
110 | 2.38k | return true; |
111 | 2.38k | } |
112 | | |
113 | 68.3k | void SSLTranscript::FreeBuffer() { buffer_.reset(); } |
114 | | |
115 | 88.9k | size_t SSLTranscript::DigestLen() const { return EVP_MD_size(Digest()); } |
116 | | |
117 | 395k | const EVP_MD *SSLTranscript::Digest() const { |
118 | 395k | return EVP_MD_CTX_get0_md(hash_.get()); |
119 | 395k | } |
120 | | |
121 | 1.52k | bool SSLTranscript::UpdateForHelloRetryRequest() { |
122 | 1.52k | if (buffer_) { |
123 | 176 | buffer_->length = 0; |
124 | 176 | } |
125 | | |
126 | 1.52k | uint8_t old_hash[EVP_MAX_MD_SIZE]; |
127 | 1.52k | size_t hash_len; |
128 | 1.52k | if (!GetHash(old_hash, &hash_len)) { |
129 | 0 | return false; |
130 | 0 | } |
131 | 1.52k | const uint8_t header[4] = {SSL3_MT_MESSAGE_HASH, 0, 0, |
132 | 1.52k | static_cast<uint8_t>(hash_len)}; |
133 | 1.52k | if (!EVP_DigestInit_ex(hash_.get(), Digest(), nullptr) || |
134 | 1.52k | !AddToBufferOrHash(header) || |
135 | 1.52k | !AddToBufferOrHash(Span(old_hash, hash_len))) { |
136 | 0 | return false; |
137 | 0 | } |
138 | 1.52k | return true; |
139 | 1.52k | } |
140 | | |
141 | | bool SSLTranscript::CopyToHashContext(EVP_MD_CTX *ctx, |
142 | 851 | const EVP_MD *digest) const { |
143 | 851 | const EVP_MD *transcript_digest = Digest(); |
144 | 851 | if (transcript_digest != nullptr && |
145 | 480 | EVP_MD_type(transcript_digest) == EVP_MD_type(digest)) { |
146 | 480 | return EVP_MD_CTX_copy_ex(ctx, hash_.get()); |
147 | 480 | } |
148 | | |
149 | 371 | if (buffer_) { |
150 | 371 | return HashBuffer(ctx, digest); |
151 | 371 | } |
152 | | |
153 | 0 | OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); |
154 | 0 | return false; |
155 | 371 | } |
156 | | |
157 | 638k | bool SSLTranscript::Update(Span<const uint8_t> in) { |
158 | 638k | if (!is_dtls_ || version_ < TLS1_3_VERSION) { |
159 | 610k | return AddToBufferOrHash(in); |
160 | 610k | } |
161 | 28.1k | if (in.size() < DTLS1_HM_HEADER_LENGTH) { |
162 | 0 | return false; |
163 | 0 | } |
164 | | // The message passed into Update is the whole Handshake or DTLSHandshake |
165 | | // message, including the msg_type and length. In DTLS, the DTLSHandshake |
166 | | // message also has message_seq, fragment_offset, and fragment_length |
167 | | // fields. In DTLS 1.3, those fields are omitted so that the same |
168 | | // transcript format as TLS 1.3 is used. This means we write the 1-byte |
169 | | // msg_type, 3-byte length, then skip 2+3+3 bytes for the DTLS-specific |
170 | | // fields that get omitted. |
171 | 28.1k | if (!AddToBufferOrHash(in.first<4>()) || |
172 | 28.1k | !AddToBufferOrHash(in.subspan<12>())) { |
173 | 0 | return false; |
174 | 0 | } |
175 | 28.1k | return true; |
176 | 28.1k | } |
177 | | |
178 | 669k | bool SSLTranscript::AddToBufferOrHash(Span<const uint8_t> in) { |
179 | | // Depending on the state of the handshake, either the handshake buffer may be |
180 | | // active, the rolling hash, or both. |
181 | 669k | if (buffer_ && // |
182 | 388k | !BUF_MEM_append(buffer_.get(), in.data(), in.size())) { |
183 | 0 | return false; |
184 | 0 | } |
185 | | |
186 | 669k | if (EVP_MD_CTX_md(hash_.get()) != nullptr) { |
187 | 605k | EVP_DigestUpdate(hash_.get(), in.data(), in.size()); |
188 | 605k | } |
189 | | |
190 | 669k | return true; |
191 | 669k | } |
192 | | |
193 | 242k | bool SSLTranscript::GetHash(uint8_t *out, size_t *out_len) const { |
194 | 242k | ScopedEVP_MD_CTX ctx; |
195 | 242k | unsigned len; |
196 | 242k | if (!EVP_MD_CTX_copy_ex(ctx.get(), hash_.get()) || |
197 | 242k | !EVP_DigestFinal_ex(ctx.get(), out, &len)) { |
198 | 0 | return false; |
199 | 0 | } |
200 | 242k | *out_len = len; |
201 | 242k | return true; |
202 | 242k | } |
203 | | |
204 | | bool SSLTranscript::GetFinishedMAC(uint8_t *out, size_t *out_len, |
205 | | const SSL_SESSION *session, |
206 | 99.3k | bool from_server) const { |
207 | 99.3k | uint8_t digest[EVP_MAX_MD_SIZE]; |
208 | 99.3k | size_t digest_len; |
209 | 99.3k | if (!GetHash(digest, &digest_len)) { |
210 | 0 | return false; |
211 | 0 | } |
212 | | |
213 | 99.3k | std::string_view label = from_server ? "server finished" : "client finished"; |
214 | 99.3k | static const size_t kFinishedLen = 12; |
215 | 99.3k | if (!tls1_prf(Digest(), Span(out, kFinishedLen), session->secret, label, |
216 | 99.3k | Span(digest, digest_len), {})) { |
217 | 0 | return false; |
218 | 0 | } |
219 | | |
220 | 99.3k | *out_len = kFinishedLen; |
221 | 99.3k | return true; |
222 | 99.3k | } |
223 | | |
224 | | BSSL_NAMESPACE_END |