parseTLSClientHello parses TLS 1.3 ClientHello.
(data []byte)
| 691 | |
| 692 | // parseTLSClientHello parses TLS 1.3 ClientHello. |
| 693 | func parseTLSClientHello(data []byte) (*handler.ClientHello, error) { |
| 694 | if len(data) < 6 { |
| 695 | return nil, fmt.Errorf("TLS record too short: got %d bytes", len(data)) |
| 696 | } |
| 697 | |
| 698 | // Check handshake type (ClientHello = 0x01) |
| 699 | // Other types: ServerHello=0x02, Certificate=0x0b, etc. |
| 700 | if data[0] != 0x01 { |
| 701 | // Provide more context about what we got |
| 702 | typeStr := fmt.Sprintf("%d (0x%02x)", data[0], data[0]) |
| 703 | if data[0] == 0x00 { |
| 704 | typeStr = "HelloRequest(0)" |
| 705 | } else if data[0] == 0x02 { |
| 706 | typeStr = "ServerHello(2)" |
| 707 | } |
| 708 | // Safe slice for logging |
| 709 | logLen := 6 |
| 710 | if len(data) < logLen { |
| 711 | logLen = len(data) |
| 712 | } |
| 713 | return nil, fmt.Errorf("expected ClientHello(1), got handshake type %s, data[0:%d]=%x", typeStr, logLen, data[0:logLen]) |
| 714 | } |
| 715 | |
| 716 | // Handshake length (3 bytes) |
| 717 | hsLen := int(data[1])<<16 | int(data[2])<<8 | int(data[3]) |
| 718 | if len(data) < 4+hsLen { |
| 719 | return nil, errors.New("ClientHello truncated") |
| 720 | } |
| 721 | |
| 722 | offset := 4 |
| 723 | |
| 724 | // Client Version (2 bytes) |
| 725 | offset += 2 |
| 726 | |
| 727 | // Random (32 bytes) |
| 728 | offset += 32 |
| 729 | |
| 730 | // Session ID Length |
| 731 | if offset >= len(data) { |
| 732 | return nil, errors.New("ClientHello too short for session ID") |
| 733 | } |
| 734 | sessionIDLen := int(data[offset]) |
| 735 | offset++ |
| 736 | offset += sessionIDLen |
| 737 | |
| 738 | // Cipher Suites Length (2 bytes) |
| 739 | if offset+2 > len(data) { |
| 740 | return nil, errors.New("ClientHello too short for cipher suites") |
| 741 | } |
| 742 | cipherSuitesLen := int(data[offset])<<8 | int(data[offset+1]) |
| 743 | offset += 2 |
| 744 | offset += cipherSuitesLen |
| 745 | |
| 746 | // Compression Methods Length |
| 747 | if offset >= len(data) { |
| 748 | return nil, errors.New("ClientHello too short for compression") |
| 749 | } |
| 750 | compressionLen := int(data[offset]) |
no test coverage detected