authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2024-11-04 20:45:18-05:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2024-11-07 20:25:26-05:00
log485f20a10ab489274b71b0d3106dcf81dbe3ac15
treef32b757c41e3895ccb6297fd83b9bab47c719cf5
parent90a761c18659919f466715714395ce27425c45f7

std.crypto.tls: remove hardcoded initial loop

This was preventing TLSv1.2 from working in some cases, because servers are allowed to send multiple handshake messages in the first handshake record, whereas this inital loop was assuming that it only contained a server hello.

1 files changed, 142 insertions(+), 171 deletions(-)

lib/std/crypto/tls/Client.zig+142-171
...@@ -214,158 +214,7 @@ pub fn init(stream: anytype, ca_bundle: Certificate.Bundle, host: []const u8) In...@@ -214,158 +214,7 @@ pub fn init(stream: anytype, ca_bundle: Certificate.Bundle, host: []const u8) In
214 try stream.writevAll(&iovecs);214 try stream.writevAll(&iovecs);
215 }215 }
216216
217 const client_hello_bytes1 = cleartext_header[tls.record_header_len..];
218
219 var tls_version: tls.ProtocolVersion = undefined;217 var tls_version: tls.ProtocolVersion = undefined;
220 var cipher_suite_tag: tls.CipherSuite = undefined;
221 var handshake_cipher: tls.HandshakeCipher = undefined;
222 var handshake_buffer: [8000]u8 = undefined;
223 var d: tls.Decoder = .{ .buf = &handshake_buffer };
224 {
225 try d.readAtLeastOurAmt(stream, tls.record_header_len);
226 const ct = d.decode(tls.ContentType);
227 d.skip(2); // legacy_record_version
228 const record_len = d.decode(u16);
229 try d.readAtLeast(stream, record_len);
230 const server_hello_fragment = d.buf[d.idx..][0..record_len];
231 var ptd = try d.sub(record_len);
232 switch (ct) {
233 .alert => {
234 try ptd.ensure(2);
235 const level = ptd.decode(tls.AlertLevel);
236 const desc = ptd.decode(tls.AlertDescription);
237 _ = level;
238
239 // if this isn't a error alert, then it's a closure alert, which makes no sense in a handshake
240 try desc.toError();
241 // TODO: handle server-side closures
242 return error.TlsUnexpectedMessage;
243 },
244 .handshake => {
245 try ptd.ensure(4);
246 const handshake_type = ptd.decode(tls.HandshakeType);
247 if (handshake_type != .server_hello) return error.TlsUnexpectedMessage;
248 const length = ptd.decode(u24);
249 var hsd = try ptd.sub(length);
250 try hsd.ensure(2 + 32 + 1);
251 const legacy_version = hsd.decode(u16);
252 @memcpy(&server_hello_rand, hsd.array(32));
253 if (mem.eql(u8, &server_hello_rand, &tls.hello_retry_request_sequence)) {
254 // This is a HelloRetryRequest message. This client implementation
255 // does not expect to get one.
256 return error.TlsUnexpectedMessage;
257 }
258 const legacy_session_id_echo_len = hsd.decode(u8);
259 try hsd.ensure(legacy_session_id_echo_len + 2 + 1);
260 const legacy_session_id_echo = hsd.slice(legacy_session_id_echo_len);
261 cipher_suite_tag = hsd.decode(tls.CipherSuite);
262 hsd.skip(1); // legacy_compression_method
263 var supported_version: ?u16 = null;
264 if (!hsd.eof()) {
265 try hsd.ensure(2);
266 const extensions_size = hsd.decode(u16);
267 var all_extd = try hsd.sub(extensions_size);
268 while (!all_extd.eof()) {
269 try all_extd.ensure(2 + 2);
270 const et = all_extd.decode(tls.ExtensionType);
271 const ext_size = all_extd.decode(u16);
272 var extd = try all_extd.sub(ext_size);
273 switch (et) {
274 .supported_versions => {
275 if (supported_version) |_| return error.TlsIllegalParameter;
276 try extd.ensure(2);
277 supported_version = extd.decode(u16);
278 },
279 .key_share => {
280 if (key_share.getSharedSecret()) |_| return error.TlsIllegalParameter;
281 try extd.ensure(4);
282 const named_group = extd.decode(tls.NamedGroup);
283 const key_size = extd.decode(u16);
284 try extd.ensure(key_size);
285 try key_share.exchange(named_group, extd.slice(key_size));
286 },
287 else => {},
288 }
289 }
290 }
291
292 tls_version = @enumFromInt(supported_version orelse legacy_version);
293 switch (tls_version) {
294 .tls_1_3 => if (!mem.eql(u8, legacy_session_id_echo, &legacy_session_id)) return error.TlsIllegalParameter,
295 .tls_1_2 => if (mem.eql(u8, server_hello_rand[24..31], "DOWNGRD") and
296 server_hello_rand[31] >> 1 == 0x00) return error.TlsIllegalParameter,
297 else => return error.TlsIllegalParameter,
298 }
299
300 switch (cipher_suite_tag) {
301 inline .AES_128_GCM_SHA256,
302 .AES_256_GCM_SHA384,
303 .CHACHA20_POLY1305_SHA256,
304 .AEGIS_256_SHA512,
305 .AEGIS_128L_SHA256,
306
307 .ECDHE_RSA_WITH_AES_128_GCM_SHA256,
308 .ECDHE_RSA_WITH_AES_256_GCM_SHA384,
309 .ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
310 => |tag| {
311 handshake_cipher = @unionInit(tls.HandshakeCipher, @tagName(tag.with()), .{
312 .transcript_hash = .init(.{}),
313 .version = undefined,
314 });
315 const p = &@field(handshake_cipher, @tagName(tag.with()));
316 p.transcript_hash.update(client_hello_bytes1); // Client Hello part 1
317 p.transcript_hash.update(host); // Client Hello part 2
318 p.transcript_hash.update(server_hello_fragment);
319 },
320
321 else => return error.TlsIllegalParameter,
322 }
323 switch (tls_version) {
324 .tls_1_3 => switch (cipher_suite_tag) {
325 inline .AES_128_GCM_SHA256,
326 .AES_256_GCM_SHA384,
327 .CHACHA20_POLY1305_SHA256,
328 .AEGIS_256_SHA512,
329 .AEGIS_128L_SHA256,
330 => |tag| {
331 const sk = key_share.getSharedSecret() orelse return error.TlsIllegalParameter;
332 const p = &@field(handshake_cipher, @tagName(tag.with()));
333 const P = @TypeOf(p.*).A;
334 const hello_hash = p.transcript_hash.peek();
335 const zeroes = [1]u8{0} ** P.Hash.digest_length;
336 const early_secret = P.Hkdf.extract(&[1]u8{0}, &zeroes);
337 const empty_hash = tls.emptyHash(P.Hash);
338 p.version = .{ .tls_1_3 = undefined };
339 const pv = &p.version.tls_1_3;
340 const hs_derived_secret = hkdfExpandLabel(P.Hkdf, early_secret, "derived", &empty_hash, P.Hash.digest_length);
341 pv.handshake_secret = P.Hkdf.extract(&hs_derived_secret, sk);
342 const ap_derived_secret = hkdfExpandLabel(P.Hkdf, pv.handshake_secret, "derived", &empty_hash, P.Hash.digest_length);
343 pv.master_secret = P.Hkdf.extract(&ap_derived_secret, &zeroes);
344 const client_secret = hkdfExpandLabel(P.Hkdf, pv.handshake_secret, "c hs traffic", &hello_hash, P.Hash.digest_length);
345 const server_secret = hkdfExpandLabel(P.Hkdf, pv.handshake_secret, "s hs traffic", &hello_hash, P.Hash.digest_length);
346 pv.client_finished_key = hkdfExpandLabel(P.Hkdf, client_secret, "finished", "", P.Hmac.key_length);
347 pv.server_finished_key = hkdfExpandLabel(P.Hkdf, server_secret, "finished", "", P.Hmac.key_length);
348 pv.client_handshake_key = hkdfExpandLabel(P.Hkdf, client_secret, "key", "", P.AEAD.key_length);
349 pv.server_handshake_key = hkdfExpandLabel(P.Hkdf, server_secret, "key", "", P.AEAD.key_length);
350 pv.client_handshake_iv = hkdfExpandLabel(P.Hkdf, client_secret, "iv", "", P.AEAD.nonce_length);
351 pv.server_handshake_iv = hkdfExpandLabel(P.Hkdf, server_secret, "iv", "", P.AEAD.nonce_length);
352 },
353 else => return error.TlsIllegalParameter,
354 },
355 .tls_1_2 => switch (cipher_suite_tag) {
356 .ECDHE_RSA_WITH_AES_128_GCM_SHA256,
357 .ECDHE_RSA_WITH_AES_256_GCM_SHA384,
358 .ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
359 => {},
360 else => return error.TlsIllegalParameter,
361 },
362 else => return error.TlsIllegalParameter,
363 }
364 },
365 else => return error.TlsUnexpectedMessage,
366 }
367 }
368
369 // This is used for two purposes:218 // This is used for two purposes:
370 // * Detect whether a certificate is the first one presented, in which case219 // * Detect whether a certificate is the first one presented, in which case
371 // we need to verify the host name.220 // we need to verify the host name.
...@@ -384,13 +233,11 @@ pub fn init(stream: anytype, ca_bundle: Certificate.Bundle, host: []const u8) In...@@ -384,13 +233,11 @@ pub fn init(stream: anytype, ca_bundle: Certificate.Bundle, host: []const u8) In
384 /// Application cipher is in use233 /// Application cipher is in use
385 application,234 application,
386 };235 };
387 var pending_cipher_state: CipherState = switch (tls_version) {236 var pending_cipher_state: CipherState = .cleartext;
388 .tls_1_3 => .handshake,237 var cipher_state = pending_cipher_state;
389 .tls_1_2 => .cleartext,
390 else => unreachable,
391 };
392 var cipher_state: CipherState = .cleartext;
393 const HandshakeState = enum {238 const HandshakeState = enum {
239 /// In this state we expect only a server hello message.
240 hello,
394 /// In this state we expect only an encrypted_extensions message.241 /// In this state we expect only an encrypted_extensions message.
395 encrypted_extensions,242 encrypted_extensions,
396 /// In this state we expect certificate handshake messages.243 /// In this state we expect certificate handshake messages.
...@@ -404,15 +251,14 @@ pub fn init(stream: anytype, ca_bundle: Certificate.Bundle, host: []const u8) In...@@ -404,15 +251,14 @@ pub fn init(stream: anytype, ca_bundle: Certificate.Bundle, host: []const u8) In
404 /// In this state, we expect only the finished handshake message.251 /// In this state, we expect only the finished handshake message.
405 finished,252 finished,
406 };253 };
407 var handshake_state: HandshakeState = switch (tls_version) {254 var handshake_state: HandshakeState = .hello;
408 .tls_1_3 => .encrypted_extensions,255 var handshake_cipher: tls.HandshakeCipher = undefined;
409 .tls_1_2 => .certificate,
410 else => unreachable,
411 };
412 var cleartext_bufs: [2][8000]u8 = undefined;
413 var main_cert_pub_key: CertificatePublicKey = undefined;256 var main_cert_pub_key: CertificatePublicKey = undefined;
414 const now_sec = std.time.timestamp();257 const now_sec = std.time.timestamp();
415258
259 var cleartext_bufs: [2][8000]u8 = undefined;
260 var handshake_buffer: [8000]u8 = undefined;
261 var d: tls.Decoder = .{ .buf = &handshake_buffer };
416 while (true) {262 while (true) {
417 try d.readAtLeastOurAmt(stream, tls.record_header_len);263 try d.readAtLeastOurAmt(stream, tls.record_header_len);
418 const record_header = d.buf[d.idx..][0..tls.record_header_len];264 const record_header = d.buf[d.idx..][0..tls.record_header_len];
...@@ -526,11 +372,132 @@ pub fn init(stream: anytype, ca_bundle: Certificate.Bundle, host: []const u8) In...@@ -526,11 +372,132 @@ pub fn init(stream: anytype, ca_bundle: Certificate.Bundle, host: []const u8) In
526 var hsd = try ctd.sub(handshake_len);372 var hsd = try ctd.sub(handshake_len);
527 const wrapped_handshake = ctd.buf[ctd.idx - handshake_len - 4 .. ctd.idx];373 const wrapped_handshake = ctd.buf[ctd.idx - handshake_len - 4 .. ctd.idx];
528 switch (handshake_type) {374 switch (handshake_type) {
375 .server_hello => {
376 if (cipher_state != .cleartext) return error.TlsUnexpectedMessage;
377 if (handshake_state != .hello) return error.TlsUnexpectedMessage;
378 try hsd.ensure(2 + 32 + 1);
379 const legacy_version = hsd.decode(u16);
380 @memcpy(&server_hello_rand, hsd.array(32));
381 if (mem.eql(u8, &server_hello_rand, &tls.hello_retry_request_sequence)) {
382 // This is a HelloRetryRequest message. This client implementation
383 // does not expect to get one.
384 return error.TlsUnexpectedMessage;
385 }
386 const legacy_session_id_echo_len = hsd.decode(u8);
387 try hsd.ensure(legacy_session_id_echo_len + 2 + 1);
388 const legacy_session_id_echo = hsd.slice(legacy_session_id_echo_len);
389 const cipher_suite_tag = hsd.decode(tls.CipherSuite);
390 hsd.skip(1); // legacy_compression_method
391 var supported_version: ?u16 = null;
392 if (!hsd.eof()) {
393 try hsd.ensure(2);
394 const extensions_size = hsd.decode(u16);
395 var all_extd = try hsd.sub(extensions_size);
396 while (!all_extd.eof()) {
397 try all_extd.ensure(2 + 2);
398 const et = all_extd.decode(tls.ExtensionType);
399 const ext_size = all_extd.decode(u16);
400 var extd = try all_extd.sub(ext_size);
401 switch (et) {
402 .supported_versions => {
403 if (supported_version) |_| return error.TlsIllegalParameter;
404 try extd.ensure(2);
405 supported_version = extd.decode(u16);
406 },
407 .key_share => {
408 if (key_share.getSharedSecret()) |_| return error.TlsIllegalParameter;
409 try extd.ensure(4);
410 const named_group = extd.decode(tls.NamedGroup);
411 const key_size = extd.decode(u16);
412 try extd.ensure(key_size);
413 try key_share.exchange(named_group, extd.slice(key_size));
414 },
415 else => {},
416 }
417 }
418 }
419
420 tls_version = @enumFromInt(supported_version orelse legacy_version);
421 switch (tls_version) {
422 .tls_1_3 => if (!mem.eql(u8, legacy_session_id_echo, &legacy_session_id)) return error.TlsIllegalParameter,
423 .tls_1_2 => if (mem.eql(u8, server_hello_rand[24..31], "DOWNGRD") and
424 server_hello_rand[31] >> 1 == 0x00) return error.TlsIllegalParameter,
425 else => return error.TlsIllegalParameter,
426 }
427
428 switch (cipher_suite_tag) {
429 inline .AES_128_GCM_SHA256,
430 .AES_256_GCM_SHA384,
431 .CHACHA20_POLY1305_SHA256,
432 .AEGIS_256_SHA512,
433 .AEGIS_128L_SHA256,
434
435 .ECDHE_RSA_WITH_AES_128_GCM_SHA256,
436 .ECDHE_RSA_WITH_AES_256_GCM_SHA384,
437 .ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
438 => |tag| {
439 handshake_cipher = @unionInit(tls.HandshakeCipher, @tagName(tag.with()), .{
440 .transcript_hash = .init(.{}),
441 .version = undefined,
442 });
443 const p = &@field(handshake_cipher, @tagName(tag.with()));
444 p.transcript_hash.update(cleartext_header[tls.record_header_len..]); // Client Hello part 1
445 p.transcript_hash.update(host); // Client Hello part 2
446 p.transcript_hash.update(wrapped_handshake);
447 },
448
449 else => return error.TlsIllegalParameter,
450 }
451 switch (tls_version) {
452 .tls_1_3 => {
453 switch (cipher_suite_tag) {
454 inline .AES_128_GCM_SHA256,
455 .AES_256_GCM_SHA384,
456 .CHACHA20_POLY1305_SHA256,
457 .AEGIS_256_SHA512,
458 .AEGIS_128L_SHA256,
459 => |tag| {
460 const sk = key_share.getSharedSecret() orelse return error.TlsIllegalParameter;
461 const p = &@field(handshake_cipher, @tagName(tag.with()));
462 const P = @TypeOf(p.*).A;
463 const hello_hash = p.transcript_hash.peek();
464 const zeroes = [1]u8{0} ** P.Hash.digest_length;
465 const early_secret = P.Hkdf.extract(&[1]u8{0}, &zeroes);
466 const empty_hash = tls.emptyHash(P.Hash);
467 p.version = .{ .tls_1_3 = undefined };
468 const pv = &p.version.tls_1_3;
469 const hs_derived_secret = hkdfExpandLabel(P.Hkdf, early_secret, "derived", &empty_hash, P.Hash.digest_length);
470 pv.handshake_secret = P.Hkdf.extract(&hs_derived_secret, sk);
471 const ap_derived_secret = hkdfExpandLabel(P.Hkdf, pv.handshake_secret, "derived", &empty_hash, P.Hash.digest_length);
472 pv.master_secret = P.Hkdf.extract(&ap_derived_secret, &zeroes);
473 const client_secret = hkdfExpandLabel(P.Hkdf, pv.handshake_secret, "c hs traffic", &hello_hash, P.Hash.digest_length);
474 const server_secret = hkdfExpandLabel(P.Hkdf, pv.handshake_secret, "s hs traffic", &hello_hash, P.Hash.digest_length);
475 pv.client_finished_key = hkdfExpandLabel(P.Hkdf, client_secret, "finished", "", P.Hmac.key_length);
476 pv.server_finished_key = hkdfExpandLabel(P.Hkdf, server_secret, "finished", "", P.Hmac.key_length);
477 pv.client_handshake_key = hkdfExpandLabel(P.Hkdf, client_secret, "key", "", P.AEAD.key_length);
478 pv.server_handshake_key = hkdfExpandLabel(P.Hkdf, server_secret, "key", "", P.AEAD.key_length);
479 pv.client_handshake_iv = hkdfExpandLabel(P.Hkdf, client_secret, "iv", "", P.AEAD.nonce_length);
480 pv.server_handshake_iv = hkdfExpandLabel(P.Hkdf, server_secret, "iv", "", P.AEAD.nonce_length);
481 },
482 else => return error.TlsIllegalParameter,
483 }
484 pending_cipher_state = .handshake;
485 handshake_state = .encrypted_extensions;
486 },
487 .tls_1_2 => switch (cipher_suite_tag) {
488 .ECDHE_RSA_WITH_AES_128_GCM_SHA256,
489 .ECDHE_RSA_WITH_AES_256_GCM_SHA384,
490 .ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
491 => handshake_state = .certificate,
492 else => return error.TlsIllegalParameter,
493 },
494 else => return error.TlsIllegalParameter,
495 }
496 },
529 .encrypted_extensions => {497 .encrypted_extensions => {
530 if (tls_version != .tls_1_3) return error.TlsUnexpectedMessage;498 if (tls_version != .tls_1_3) return error.TlsUnexpectedMessage;
531 if (cipher_state != .handshake) return error.TlsUnexpectedMessage;499 if (cipher_state != .handshake) return error.TlsUnexpectedMessage;
532 if (handshake_state != .encrypted_extensions) return error.TlsUnexpectedMessage;500 if (handshake_state != .encrypted_extensions) return error.TlsUnexpectedMessage;
533 handshake_state = .certificate;
534 switch (handshake_cipher) {501 switch (handshake_cipher) {
535 inline else => |*p| p.transcript_hash.update(wrapped_handshake),502 inline else => |*p| p.transcript_hash.update(wrapped_handshake),
536 }503 }
...@@ -548,16 +515,18 @@ pub fn init(stream: anytype, ca_bundle: Certificate.Bundle, host: []const u8) In...@@ -548,16 +515,18 @@ pub fn init(stream: anytype, ca_bundle: Certificate.Bundle, host: []const u8) In
548 else => {},515 else => {},
549 }516 }
550 }517 }
518 handshake_state = .certificate;
551 },519 },
552 .certificate => cert: {520 .certificate => cert: {
553 switch (handshake_cipher) {521 if (cipher_state == .application) return error.TlsUnexpectedMessage;
554 inline else => |*p| p.transcript_hash.update(wrapped_handshake),
555 }
556 switch (handshake_state) {522 switch (handshake_state) {
557 .certificate => {},523 .certificate => {},
558 .trust_chain_established => break :cert,524 .trust_chain_established => break :cert,
559 else => return error.TlsUnexpectedMessage,525 else => return error.TlsUnexpectedMessage,
560 }526 }
527 switch (handshake_cipher) {
528 inline else => |*p| p.transcript_hash.update(wrapped_handshake),
529 }
561530
562 switch (tls_version) {531 switch (tls_version) {
563 .tls_1_3 => {532 .tls_1_3 => {
...@@ -614,7 +583,7 @@ pub fn init(stream: anytype, ca_bundle: Certificate.Bundle, host: []const u8) In...@@ -614,7 +583,7 @@ pub fn init(stream: anytype, ca_bundle: Certificate.Bundle, host: []const u8) In
614 if (tls_version != .tls_1_2) return error.TlsUnexpectedMessage;583 if (tls_version != .tls_1_2) return error.TlsUnexpectedMessage;
615 if (cipher_state != .cleartext) return error.TlsUnexpectedMessage;584 if (cipher_state != .cleartext) return error.TlsUnexpectedMessage;
616 switch (handshake_state) {585 switch (handshake_state) {
617 .trust_chain_established => handshake_state = .server_hello_done,586 .trust_chain_established => {},
618 .certificate => return error.TlsCertificateNotVerified,587 .certificate => return error.TlsCertificateNotVerified,
619 else => return error.TlsUnexpectedMessage,588 else => return error.TlsUnexpectedMessage,
620 }589 }
...@@ -631,12 +600,12 @@ pub fn init(stream: anytype, ca_bundle: Certificate.Bundle, host: []const u8) In...@@ -631,12 +600,12 @@ pub fn init(stream: anytype, ca_bundle: Certificate.Bundle, host: []const u8) In
631 const server_pub_key = hsd.slice(key_size);600 const server_pub_key = hsd.slice(key_size);
632 try main_cert_pub_key.verifySignature(&hsd, &.{ &client_hello_rand, &server_hello_rand, hsd.buf[0..hsd.idx] });601 try main_cert_pub_key.verifySignature(&hsd, &.{ &client_hello_rand, &server_hello_rand, hsd.buf[0..hsd.idx] });
633 try key_share.exchange(named_group, server_pub_key);602 try key_share.exchange(named_group, server_pub_key);
603 handshake_state = .server_hello_done;
634 },604 },
635 .server_hello_done => {605 .server_hello_done => {
636 if (tls_version != .tls_1_2) return error.TlsUnexpectedMessage;606 if (tls_version != .tls_1_2) return error.TlsUnexpectedMessage;
637 if (cipher_state != .cleartext) return error.TlsUnexpectedMessage;607 if (cipher_state != .cleartext) return error.TlsUnexpectedMessage;
638 if (handshake_state != .server_hello_done) return error.TlsUnexpectedMessage;608 if (handshake_state != .server_hello_done) return error.TlsUnexpectedMessage;
639 handshake_state = .finished;
640609
641 const client_key_exchange_msg = .{@intFromEnum(tls.ContentType.handshake)} ++610 const client_key_exchange_msg = .{@intFromEnum(tls.ContentType.handshake)} ++
642 int(u16, @intFromEnum(tls.ProtocolVersion.tls_1_2)) ++611 int(u16, @intFromEnum(tls.ProtocolVersion.tls_1_2)) ++
...@@ -680,7 +649,6 @@ pub fn init(stream: anytype, ca_bundle: Certificate.Bundle, host: []const u8) In...@@ -680,7 +649,6 @@ pub fn init(stream: anytype, ca_bundle: Certificate.Bundle, host: []const u8) In
680 .app_cipher = std.mem.bytesToValue(P.Tls_1_2, &key_block),649 .app_cipher = std.mem.bytesToValue(P.Tls_1_2, &key_block),
681 } };650 } };
682 const pv = &p.version.tls_1_2;651 const pv = &p.version.tls_1_2;
683 pending_cipher_state = .application;
684 const nonce: [P.AEAD.nonce_length]u8 = if (builtin.zig_backend == .stage2_x86_64 and652 const nonce: [P.AEAD.nonce_length]u8 = if (builtin.zig_backend == .stage2_x86_64 and
685 P.AEAD.nonce_length > comptime std.simd.suggestVectorLength(u8) orelse 1)653 P.AEAD.nonce_length > comptime std.simd.suggestVectorLength(u8) orelse 1)
686 nonce: {654 nonce: {
...@@ -715,12 +683,14 @@ pub fn init(stream: anytype, ca_bundle: Certificate.Bundle, host: []const u8) In...@@ -715,12 +683,14 @@ pub fn init(stream: anytype, ca_bundle: Certificate.Bundle, host: []const u8) In
715 },683 },
716 }684 }
717 write_seq += 1;685 write_seq += 1;
686 pending_cipher_state = .application;
687 handshake_state = .finished;
718 },688 },
719 .certificate_verify => {689 .certificate_verify => {
720 if (tls_version != .tls_1_3) return error.TlsUnexpectedMessage;690 if (tls_version != .tls_1_3) return error.TlsUnexpectedMessage;
721 if (cipher_state != .handshake) return error.TlsUnexpectedMessage;691 if (cipher_state != .handshake) return error.TlsUnexpectedMessage;
722 switch (handshake_state) {692 switch (handshake_state) {
723 .trust_chain_established => handshake_state = .finished,693 .trust_chain_established => {},
724 .certificate => return error.TlsCertificateNotVerified,694 .certificate => return error.TlsCertificateNotVerified,
725 else => return error.TlsUnexpectedMessage,695 else => return error.TlsUnexpectedMessage,
726 }696 }
...@@ -733,6 +703,7 @@ pub fn init(stream: anytype, ca_bundle: Certificate.Bundle, host: []const u8) In...@@ -733,6 +703,7 @@ pub fn init(stream: anytype, ca_bundle: Certificate.Bundle, host: []const u8) In
733 p.transcript_hash.update(wrapped_handshake);703 p.transcript_hash.update(wrapped_handshake);
734 },704 },
735 }705 }
706 handshake_state = .finished;
736 },707 },
737 .finished => {708 .finished => {
738 if (cipher_state == .cleartext) return error.TlsUnexpectedMessage;709 if (cipher_state == .cleartext) return error.TlsUnexpectedMessage;