feat(crypto): AES-GCM via AES-NI + PCLMULQDQ (rv2 8 phase B, ids 113/114)
- aes_gcm_seal/open, AES-128 and AES-256 (variant by key length 16/32),
nonce 12 bytes, out = ciphertext||tag; open returns nil on auth failure
- hardware path only (phase B): AES-NI key schedule (128/256) + block, GHASH
via PCLMULQDQ with the fast GF(2^128) reduction, GCM mode (J0, CTR from
counter 2, GHASH over aad|pad|ct|pad|len, tag = GHASH ^ AES(J0))
- constant-time by hardware; target-attributed functions + __builtin_cpu_supports
gate so the binary stays portable -- no AES-NI traps with a clear message
(bitsliced software + ARMv8 paths are phase C)
- wiring: wob.h ids + WO_B_MAX 114; builtin.c crypto range; loader arity 4;
emit.ml (ids/arity/return/name); types.ml (register + return type)
- VERIFIED: matches NIST SP 800-38D cases 4 (AES-128) and 16 (AES-256) and the
python cryptography reference byte-for-byte; KAT-gated in test_crypto (36/0);
ASan/UBSan clean; runtime battery + compiler 557/0 green
(cherry picked from commit f12a745a3c1313847f9d7f65e53bcd8093758af9)