LCOV - code coverage report
Current view: top level - waltz/quic/crypto - fd_quic_crypto_suites.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 17 17 100.0 %
Date: 2025-01-08 12:08:44 Functions: 0 0 -

          Line data    Source code
       1             : #ifndef HEADER_fd_src_waltz_quic_crypto_fd_quic_crypto_suites_h
       2             : #define HEADER_fd_src_waltz_quic_crypto_fd_quic_crypto_suites_h
       3             : 
       4             : #include "../fd_quic_enum.h"
       5             : #include "../../../ballet/aes/fd_aes_gcm.h"
       6             : 
       7             : /* Defines the crypto suites used by QUIC v1.
       8             : 
       9             :    QUIC v2 is defined here:
      10             :      https://www.rfc-editor.org/rfc/rfc9001.html#name-header-protection
      11             :      https://www.rfc-editor.org/rfc/rfc8446.html#page-133
      12             : 
      13             :    The suites are defined thusly:
      14             : 
      15             :        +------------------------------+-------------+
      16             :        | Description                  | Value       |
      17             :        +------------------------------+-------------+
      18             :        | TLS_AES_128_GCM_SHA256       | {0x13,0x01} |
      19             :        | TLS_AES_256_GCM_SHA384       | {0x13,0x02} |
      20             :        | TLS_CHACHA20_POLY1305_SHA256 | {0x13,0x03} |
      21             :        | TLS_AES_128_CCM_SHA256       | {0x13,0x04} |
      22             :        | TLS_AES_128_CCM_8_SHA256     | {0x13,0x05} |
      23             :        +------------------------------+-------------+
      24             : 
      25             :    Notes:
      26             :      TLS_AES_128_CCM_SHA256 does not seem to be mentioned in rfc9001, so is excluded
      27             :      TLS_AES_128_CCM_8_SHA256 has no packet-header encryption defined, and so must be excluded
      28             : 
      29             :      The remainder are defined below */
      30             : 
      31             : typedef struct fd_quic_crypto_keys    fd_quic_crypto_keys_t;
      32             : typedef struct fd_quic_crypto_secrets fd_quic_crypto_secrets_t;
      33             : 
      34   172818117 : #define FD_QUIC_CRYPTO_TAG_SZ    16
      35    30319279 : #define FD_QUIC_CRYPTO_SAMPLE_SZ 16
      36             : 
      37             : struct fd_quic_crypto_keys {
      38             :   /* packet protection: */
      39             :   uchar pkt_key[FD_AES_128_KEY_SZ];
      40             :   uchar iv     [FD_AES_GCM_IV_SZ ];
      41             :   uchar hp_key [FD_AES_128_KEY_SZ];
      42             : };
      43             : 
      44             : /* define enums for encryption levels */
      45   108427510 : #define fd_quic_enc_level_initial_id    0
      46             : #define fd_quic_enc_level_early_data_id 1
      47   106442207 : #define fd_quic_enc_level_handshake_id  2
      48   207440926 : #define fd_quic_enc_level_appdata_id    3
      49             : #define FD_QUIC_NUM_ENC_LEVELS          4
      50             : 
      51             : /* labels defined in rfc9001 */
      52       24588 : #define FD_QUIC_CRYPTO_LABEL_CLIENT_IN "client in"
      53       24588 : #define FD_QUIC_CRYPTO_LABEL_SERVER_IN "server in"
      54             : 
      55      193920 : #define FD_QUIC_CRYPTO_LABEL_QUIC_KEY "quic key"
      56      193920 : #define FD_QUIC_CRYPTO_LABEL_QUIC_IV  "quic iv"
      57      145416 : #define FD_QUIC_CRYPTO_LABEL_QUIC_HP  "quic hp"
      58             : 
      59       48504 : #define FD_QUIC_CRYPTO_LABEL_KEY_UPDATE "quic ku"
      60             : 
      61             : /* each of these has "-1" to avoid counting the implied terminating NUL byte */
      62       12294 : #define FD_QUIC_CRYPTO_LABEL_CLIENT_IN_LEN ( sizeof( FD_QUIC_CRYPTO_LABEL_CLIENT_IN ) - 1 )
      63       12294 : #define FD_QUIC_CRYPTO_LABEL_SERVER_IN_LEN ( sizeof( FD_QUIC_CRYPTO_LABEL_SERVER_IN ) - 1 )
      64             : 
      65       96960 : #define FD_QUIC_CRYPTO_LABEL_QUIC_KEY_LEN  ( sizeof( FD_QUIC_CRYPTO_LABEL_QUIC_KEY ) - 1 )
      66       96960 : #define FD_QUIC_CRYPTO_LABEL_QUIC_IV_LEN   ( sizeof( FD_QUIC_CRYPTO_LABEL_QUIC_IV ) - 1 )
      67       72708 : #define FD_QUIC_CRYPTO_LABEL_QUIC_HP_LEN   ( sizeof( FD_QUIC_CRYPTO_LABEL_QUIC_HP ) - 1 )
      68             : 
      69       24252 : #define FD_QUIC_CRYPTO_LABEL_KEY_UPDATE_LEN ( sizeof( FD_QUIC_CRYPTO_LABEL_KEY_UPDATE ) - 1 )
      70             : 
      71             : struct fd_quic_crypto_secrets {
      72             :   uchar initial_secret[FD_QUIC_INITIAL_SECRET_SZ];
      73             : 
      74             :   /* secret[enc_level][dir][FD_QUIC_SECRET_SZ]
      75             :      a secret for each encryption level,
      76             :      and each direction (dir=0 is incoming, dir=1 is outgoing) */
      77             :   uchar secret[FD_QUIC_NUM_ENC_LEVELS][2][FD_QUIC_SECRET_SZ];
      78             : 
      79             :   /* new secret for switching keys during key update */
      80             :   uchar new_secret[2][FD_QUIC_SECRET_SZ];
      81             : };
      82             : 
      83             : /* fd_quic_gen_initial_secrets generates initial secrets for the given conn ID.
      84             :    Does not generate keys.  Sets secrets->initial_secrets, secrets->secret[0][0],
      85             :    (incoming secret) and secret->secret[0][1] (outgoing secret).  is_server is
      86             :    1 if the current QUIC instance runs from the perspective of the server, 0
      87             :    otherwise.
      88             : 
      89             :    Key schedule:
      90             : 
      91             :      initial_salt (hardcoded constant)
      92             :       |
      93             :       v
      94             :      initial_secret = HKDF-Extract(.,conn_id)
      95             :       |
      96             :       +---> initial_client_secret = HKDF-Expand-Label(., "client in", "", 32)
      97             :       |
      98             :       +---> initial_server_secret = HKDF-Expand-Label(., "server in", "", 32) */
      99             : 
     100             : void
     101             : fd_quic_gen_initial_secrets(
     102             :     fd_quic_crypto_secrets_t * secrets,
     103             :     uchar const *              conn_id,
     104             :     ulong                      conn_id_sz,
     105             :     int                        is_server );
     106             : 
     107             : /* fd_quic_gen_keys derives the IV, a header protection key, and a packet
     108             :    protection key from a secret.  Thus *keys is fully initialized.  This
     109             :    function is called twice per encryption level (for incoming and for
     110             :    outgoing keys).
     111             : 
     112             :    Key schedule:
     113             : 
     114             :      secret
     115             :       |
     116             :       +---> header protection key = HKDF-Expand-Label(.,"quic-hp")
     117             :       +---> packet protection IV  = HKDF-Expand-Label(.,"quic-iv")
     118             :       +---> packet protection key = HKDF-Expand-Label(.,"quic-key") */
     119             : 
     120             : void
     121             : fd_quic_gen_keys(
     122             :     fd_quic_crypto_keys_t * keys,
     123             :     uchar const             secret[ 32 ] );
     124             : 
     125             : /* fd_quic_key_update_derive derives the IVs and packet protection keys
     126             :    for the next key update.  Header protection keys are not updated.
     127             :    Key updates are periodic key rotations that some QUIC peers do out of
     128             :    caution.  Key updates are deterministic and can be computed infinitely
     129             :    far in advance if the client and server secrets are known.
     130             : 
     131             :    Key schedule:
     132             : 
     133             :      client/server secret n
     134             :       |
     135             :       v
     136             :      client/server secret n+1 = HKDF-Expand-Label(.,"quic-ku")
     137             :       |
     138             :       +---> server packet protection IV  = HKDF-Expand-Label(.,"quic-iv")
     139             :       +---> server packet protection key = HKDF-Expand-Label(.,"quic-key") */
     140             : 
     141             : void
     142             : fd_quic_key_update_derive( fd_quic_crypto_secrets_t * secrets,
     143             :                            fd_quic_crypto_keys_t      new_keys[2] );
     144             : 
     145             : 
     146             : /* encrypt a packet according to rfc9001 packet protection and header protection
     147             : 
     148             :    may fail in the following scenarios:
     149             :      the receiving buffer is too small
     150             :      the decryption functions report failure (fd_tls)
     151             : 
     152             :    returns
     153             :      FD_QUIC_SUCCESS   if the operation succeeded
     154             :      FD_QUIC_FAILED    otherwise
     155             : 
     156             :    args
     157             :     out       destination for the full packet
     158             :     out_sz    size of the output buffer, and also returned size of the written bytes
     159             :     hdr       the input plain text header
     160             :     hdr_sz    the size of the input header
     161             :     pkt       the input plain text payload
     162             :     pkt_sz    the size of the input payload
     163             :     keys      the keys to use
     164             :    */
     165             : int
     166             : fd_quic_crypto_encrypt(
     167             :     uchar *                        const out,
     168             :     ulong *                        const out_sz,
     169             :     uchar const *                  const hdr,
     170             :     ulong                          const hdr_sz,
     171             :     uchar const *                  const pkt,
     172             :     ulong                          const pkt_sz,
     173             :     fd_quic_crypto_keys_t const *  const pkt_keys,
     174             :     fd_quic_crypto_keys_t const *  const hp_keys,
     175             :     ulong                          const pkt_number );
     176             : 
     177             : 
     178             : /* decrypt a quic protected packet
     179             : 
     180             :    may fail in the following scenarios:
     181             :      the receiving buffer is too small
     182             :      the decryption functions report failure (fd_tls)
     183             :      the decrypted data is corrupt
     184             : 
     185             :    returns
     186             :      FD_QUIC_SUCCESS   if the operation succeeded
     187             :      FD_QUIC_FAILED    otherwise
     188             : 
     189             :    args
     190             :      buf                buffer containing a QUIC packet with a decrypted
     191             :                         header, and encrypted payload, and the auth tag
     192             :                         of size FD_QUIC_CRYPTO_TAG_SZ.  On return, the
     193             :                         payload will be decrypted.
     194             :      buf_sz             the size of the QUIC packet
     195             :      pkt_number_off     the offset of the packet number within the cipher text
     196             :                         this must be determined from unprotected header data
     197             :      keys               the keys needed to decrypt */
     198             : 
     199             : int
     200             : fd_quic_crypto_decrypt(
     201             :     uchar *                        buf,
     202             :     ulong                          buf_sz,
     203             :     ulong                          pkt_number_off,
     204             :     ulong                          pkt_number,
     205             :     fd_quic_crypto_keys_t const *  keys );
     206             : 
     207             : 
     208             : /* decrypt a quic protected packet header
     209             : 
     210             :    this removes header protection (HP)
     211             : 
     212             :    may fail in the following scenarios:
     213             :      the receiving buffer is too small
     214             :      the decryption functions report failure (fd_tls)
     215             :      the decrypted data is corrupt
     216             : 
     217             :    returns
     218             :      FD_QUIC_SUCCESS   if the operation succeeded
     219             :      FD_QUIC_FAILED    otherwise
     220             : 
     221             :    args
     222             :      buf                buffer containing an encrypted QUIC packet.
     223             :                         On return, the header is decrypted, the rest
     224             :                         still encrypted
     225             :      buf_sz             size of the QUIC packet
     226             :      pkt_number_off     the offset of the packet number within the cipher text
     227             :                         this must be determined from unprotected header data
     228             :      keys               the keys needed to decrypt */
     229             : 
     230             : int
     231             : fd_quic_crypto_decrypt_hdr(
     232             :     uchar *                        buf,
     233             :     ulong                          buf_sz,
     234             :     ulong                          pkt_number_off,
     235             :     fd_quic_crypto_keys_t const *  keys );
     236             : 
     237             : #endif /* HEADER_fd_src_waltz_quic_crypto_fd_quic_crypto_suites_h */

Generated by: LCOV version 1.14