Expand description

QUIC cryptography primitives and traits

Decryption flow

The lifecycle of a protected and encrypted payload follows the following flow:

            +----------------+
            |ProtectedPayload|
            +-------+--------+
                    |
                    | unprotect()
                    |
         +----------+------------+
         |                       |
         |                       v
         |             +---------+-----------+
         |             |TruncatedPacketNumber|
         v             +---------+-----------+
+--------+--------+              |
|EncryptedPayload |              | expand(largest_acknowledged_packet_number)
+--------+--------+              v
         |                 +-----+------+
         |                 |PacketNumber|
         |                 +-----+------+
         |                       |
         +----------+------------+
                    |
                    |  decrypt()
                    v
             +------+---------+
             |CleartextPayload|
             +----------------+

The implementation of the decryption flow looks like the following:

let crypto = ..; // initialize crypto keys
let protected_payload = ..; // decode the payload from the incoming packet
let header_len = ..; // decode packet to derive header_len
let largest_acknowledged_packet_number = ..; // fetch the largest packet number from connection state

let (truncated_packet_number, encrypted_payload) = crate::crypto::unprotect(
    &crypto,
    largest_acknowledged_packet_number.space(),
    header_len,
    protected_payload,
)?;

let packet_number = truncated_packet_number.expand(largest_acknowledged_packet_number)?;

let cleartext_payload = crate::crypto::decrypt(
    &crypto,
    packet_number,
    encrypted_payload,
)?;

Encryption flow

Inversely, a cleartext payload follows the following flow:

+----------------+                        +------------+
|CleartextPayload|                        |PacketNumber|
+-------+--------+                        +------+-----+
        |                                        |
        |                         +--------------+-----------------------------------+
        |                         |                                                  |
        |                         |   truncate(largest_acknowledged_packet_number)   |
        |                         |                                                  |
        |                         |                                                  |
        |   encode()   +----------+----------+                                       |
        +<-------------+TruncatedPacketNumber|                                       |
        |              +----------+----------+                                       |
        |                         |                                                  |
        |                         | len()                                            |
        |                         v                                                  |
        |   apply_mask()  +-------+-------+                                          |
        <-----------------+PacketNumberLen|                                          |
        |                 +--+----+-------+                                          |
        |                    |    |                                                  |
        +--------------------(----+---------------+----------------------------------+
                             |                    |
                             |                    |  encrypt()
                             |                    |
                             |           +--------+-------+
                             |           |EncryptedPayload|
                             |           +--------+-------+
                             |                    |
                             |                    |
                             +-----------+--------+
                                         |
                                         | protect()
                                         |
                                 +-------+--------+
                                 |ProtectedPayload|
                                 +----------------+

The implementation of the encryption flow looks like the following:

let crypto = ..; // initialize crypto keys
let cleartext_payload = ..; // encode an outgoing packet
let header_len = ..; // encode packet to derive header_len
let packet_number = ..; // use the packet number from the outgoing packet
let largest_acknowledged_packet_number = ..; // fetch the largest packet number from connection state

let truncated_packet_number = packet_number.truncate(largest_acknowledged_packet_number).unwrap();
cleartext_payload[header_len..].encode(truncated_packet_number);
let packet_number_len = truncated_packet_number.len();
cleartext_payload[0] &= packet_number_len.into_packet_tag_mask();

let (encrypted_payload, remaining_payload) = crate::crypto::encrypt(
    &crypto,
    packet_number,
    packet_number_len,
    header_len,
    cleartext_payload,
)?;

let protected_payload =
    crate::crypto::protect(&crypto, encrypted_payload)?;

Re-exports

pub use retry::RetryKey;
pub use application::*;
pub use error::*;
pub use handshake::*;
pub use header_crypto::*;
pub use initial::*;
pub use key::*;
pub use one_rtt::*;
pub use packet_protection::*;
pub use payload::*;
pub use zero_rtt::*;

Modules

Traits

Trait which aggregates all Crypto types

Functions

Decrypts a EncryptedPayload into clear text
Encrypts a cleartext payload with a crypto key into a EncryptedPayload
Protects an EncryptedPayload into a ProtectedPayload
Removes packet protection from a ProtectedPayload into a EncryptedPayload and associated TruncatedPacketNumber