#!/usr/bin/env python3 """TLS 1.3 record-layer KAT vectors (RFC 8446 ยง5.2). For a fixed key/iv/seq/ plaintext/content-type, compute the full wire record with python's AEAD as the oracle, for both AES-128-GCM and ChaCha20-Poly1305. Emits C literals.""" from cryptography.hazmat.primitives.ciphers.aead import AESGCM, ChaCha20Poly1305 def nonce(iv, seq): n = bytearray(iv) for i in range(8): n[4 + i] ^= (seq >> (8 * (7 - i))) & 0xff return bytes(n) def record(aead, key, iv, seq, ct, pt): inner = pt + bytes([ct]) # no padding payload_len = len(inner) + 16 hdr = bytes([23, 3, 3, payload_len >> 8, payload_len & 0xff]) enc = aead(key).encrypt(nonce(iv, seq), inner, hdr) return hdr + enc def hexlit(b): return '"' + "".join("\\x%02x" % x for x in b) + '"' # AES-128-GCM: 16-byte key, ChaCha: 32-byte key. Shared iv/seq/pt/type. aes_key = bytes.fromhex("000102030405060708090a0b0c0d0e0f") cha_key = bytes.fromhex("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f") iv = bytes.fromhex("cafebabecafebabecafebabe") seq = 0x0102030405060708 pt = b"hello writeonce tls" ct = 22 # handshake r_aes = record(AESGCM, aes_key, iv, seq, ct, pt) r_cha = record(ChaCha20Poly1305, cha_key, iv, seq, ct, pt) print("/* Generated by scratchpad/gen_tls_record.py (python cryptography). */") print("#define TLSREC_IV %s" % hexlit(iv)) print("#define TLSREC_AESKEY %s" % hexlit(aes_key)) print("#define TLSREC_CHAKEY %s" % hexlit(cha_key)) print("#define TLSREC_SEQ 0x%016xULL" % seq) print("#define TLSREC_CT %d" % ct) print("#define TLSREC_PT %s" % hexlit(pt)) print("#define TLSREC_PTLEN %d" % len(pt)) print("#define TLSREC_AES %s" % hexlit(r_aes)) print("#define TLSREC_AESLEN %d" % len(r_aes)) print("#define TLSREC_CHA %s" % hexlit(r_cha)) print("#define TLSREC_CHALEN %d" % len(r_cha))