- new tls.c/tls.h on the crypto ladder: wo_tls_record_seal/open (RFC 8446 §5.2) — TLSInnerPlaintext (content||type, no padding), 5-byte header as AEAD additional-data, per-record nonce = iv XOR seq big-endian (§5.3) - suite dispatch: TLS_AES_128_GCM_SHA256 (mandatory) + TLS_CHACHA20_POLY1305_SHA256 (AES-NI-less fallback), over phase-A AEAD - open() strips trailing zero padding to recover the inner content type; rejects a length-field lie before the AEAD, and auth failure after - KAT vs python AEAD oracle (test/gen_tls_record.py): sealed record byte-for-byte both suites, open() recovers it, 5-seq round-trip, tamper + wrong-seq + bad-suite rejected. test_tls 51 pass, ASan/UBSan Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> (cherry picked from commit 5021a99f8359f78a642bb0cc2b28ab66f6b624e2)
45 lines
1.8 KiB
Python
45 lines
1.8 KiB
Python
#!/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))
|