moonbitstack/moontls/msg does not have a README file

    Hello

    pub(all) struct Hello {
    random : Bytes
    session_id : Bytes
    suites : Array[Int]
    extensions : Array[
    Ext
    ]
    } derive(Eq,
    Debug
    )

    A ClientHello (RFC 8446 §4.1.2), less the fixed legacy fields.

    legacy_version and legacy_compression_methods are not carried because TLS 1.3 fixes them: the version is 0x0303 whatever is negotiated (the supported_versions extension does the negotiating) and the only compression method is null. Writing them out would be four fields that can never differ.

    Hello::equal

    fn Hello::equal(Hello, Hello) -> Bool

    Hello::not_equal

    fn Hello::not_equal(x : Hello, y : Hello) -> Bool

    Hello::to_repr

    Kind

    pub(all) enum Kind {
    ClientHello
    ServerHello
    NewSessionTicket
    EncryptedExtensions
    Certificate
    CertificateRequest
    CertificateVerify
    Finished
    KeyUpdate
    Other(Int)
    } derive(Eq,
    Debug
    )

    Which handshake message this is (RFC 8446 §4, and IANA's TLS HandshakeType registry).

    Other keeps a type this package has no codec for. A handshake message is framed by a type and a 24-bit length, so one it does not understand can still be measured, skipped and fed to the transcript — which is what a receiver has to do, since the transcript hash covers every message whether or not it was understood.

    Kind::code

    fn Kind::code(self : Kind) -> Int

    The octet this message type goes on the wire as.

    Kind::equal

    fn Kind::equal(Kind, Kind) -> Bool

    Kind::not_equal

    fn Kind::not_equal(x : Kind, y : Kind) -> Bool

    Kind::of

    fn Kind::of(code : Int) -> Kind

    The message type an octet names. Never fails: one without a codec here becomes Other.

    Kind::to_repr

    Server

    pub(all) struct Server {
    random : Bytes
    session_id : Bytes
    suite : Int
    extensions : Array[
    Ext
    ]
    } derive(Eq,
    Debug
    )

    A ServerHello (RFC 8446 §4.1.3): one chosen cipher suite, no compression.

    Server::equal

    fn Server::equal(Server, Server) -> Bool

    Server::not_equal

    fn Server::not_equal(x : Server, y : Server) -> Bool

    Server::to_repr

    certificate

    fn certificate(certs : ArrayView[Bytes], context? : BytesView) -> Bytes

    Encode a Certificate body (RFC 8446 §4.4.2): the certificate_request_context, then the certificate_list — each entry a three-octet-length DER certificate and a two-octet-length extensions block.

    context is empty when a server sends its certificate unprompted, which is every case until client certificates land. The DER is carried opaque: what is in a certificate is mooncred's question, not the handshake's.

    certificate_verify

    fn certificate_verify(signature : BytesView, scheme : Int) -> Bytes

    Encode a CertificateVerify body: the SignatureScheme and the two-octet- length-prefixed signature (RFC 8446 §4.4.3).

    scheme is the code the signature was made under, which the verifier reads back to decide what to check it with; it is a parameter because the certificate's key decides it, not this package.

    client_context

    let client_context : String

    The client's CertificateVerify context string (RFC 8446 §4.4.3).

    encrypted_extensions

    fn encrypted_extensions(exts : ArrayView[
    Ext
    ]) -> Bytes

    An EncryptedExtensions body (RFC 8446 §4.3.1): an extension list, and the first message the server sends under handshake encryption.

    It carries every negotiated extension not needed to establish the cryptographic context — the selected ALPN protocol, and for a QUIC server the quic_transport_parameters RFC 9001 §8.2 requires.

    finished

    fn finished(verify_data : BytesView) -> Bytes

    A Finished body (RFC 8446 §4.4.4): the verify_data and nothing else.

    Computing it is keys' job — @keys.finished — because it is the key schedule that says what is MACed under what.

    frame

    fn frame(kind : Kind, body : BytesView) -> Bytes

    Frame a handshake body: the message type, then a 24-bit big-endian length (RFC 8446 §4).

    hello

    fn hello(ch : Hello) -> Bytes

    Encode a ClientHello as a whole handshake message.

    read_certificate

    fn read_certificate(body : BytesView) -> (Bytes, Array[Bytes])?

    Decode a Certificate body into its certificate_request_context and the DER certificates, skipping each entry's extensions. None on a truncated message.

    read_certificate_verify

    fn read_certificate_verify(body : BytesView) -> (Int, Bytes)?

    Decode a CertificateVerify body into its scheme and signature, or None if the length does not describe what is there.

    read_encrypted_extensions

    fn read_encrypted_extensions(body : BytesView) -> Array[
    Ext
    ]?

    Decode an EncryptedExtensions body, or None if it is truncated.

    read_hello

    fn read_hello(body : BytesView) -> Hello?

    Decode a ClientHello from a handshake body (RFC 8446 §4.1.2).

    read_server_hello

    fn read_server_hello(body : BytesView) -> Server?

    Decode a ServerHello from a handshake body (RFC 8446 §4.1.3).

    server_context

    let server_context : String

    The server's CertificateVerify context string (RFC 8446 §4.4.3).

    server_hello

    fn server_hello(sh : Server) -> Bytes

    Encode a ServerHello as a whole handshake message.

    signed

    fn signed(context : String, transcript : BytesView) -> Bytes

    What a CertificateVerify signs (RFC 8446 §4.4.3): 64 octets of 0x20, the context string, a single 0x00 separator, then the transcript hash through the Certificate message.

    The 64 spaces and the context string are what stop a signature made for one role, or for an earlier version of the protocol, from counting as one made for another.

    unframe

    fn unframe(view : BytesView) -> (Kind, Bytes)?

    One handshake message's type and body, or None while the view is short of a whole message.

    The framing is all this reads. What a body means is the codec for that type, below — which is why a message this package has no codec for still comes back rather than failing.

    Source Files