35bool pc_aesccm_seal_tag(
const uint8_t *key,
size_t key_len,
const uint8_t *nonce,
size_t nonce_len,
const uint8_t *aad,
36 size_t aad_len,
const uint8_t *pt,
size_t pt_len, uint8_t *ct_out,
37 uint8_t tag_out[PC_AESCCM_TAG_LEN])
39 if (!key || !nonce || !ct_out || !tag_out || (key_len != 16 && key_len != 32))
43 SecureBorrow ws_b(
sizeof(mbedtls_ccm_context),
alignof(mbedtls_ccm_context));
44 const pc_span &ws = ws_b.span();
49 mbedtls_ccm_context *c =
reinterpret_cast<mbedtls_ccm_context *
>(ws.
buf);
51 if (mbedtls_ccm_setkey(c, MBEDTLS_CIPHER_ID_AES, key, (
unsigned)(key_len * 8)) != 0)
57 mbedtls_ccm_encrypt_and_tag(c, pt_len, nonce, nonce_len, aad, aad_len, pt, ct_out, tag_out, PC_AESCCM_TAG_LEN);
62bool pc_aesccm_open_tag(
const uint8_t *key,
size_t key_len,
const uint8_t *nonce,
size_t nonce_len,
const uint8_t *aad,
63 size_t aad_len,
const uint8_t *ct,
size_t ct_len,
const uint8_t tag[PC_AESCCM_TAG_LEN],
66 if (!key || !nonce || !ct || !out || !tag || (key_len != 16 && key_len != 32))
70 SecureBorrow ws_b(
sizeof(mbedtls_ccm_context),
alignof(mbedtls_ccm_context));
71 const pc_span &ws = ws_b.span();
76 mbedtls_ccm_context *c =
reinterpret_cast<mbedtls_ccm_context *
>(ws.
buf);
78 if (mbedtls_ccm_setkey(c, MBEDTLS_CIPHER_ID_AES, key, (
unsigned)(key_len * 8)) != 0)
84 int rc = mbedtls_ccm_auth_decrypt(c, ct_len, nonce, nonce_len, aad, aad_len, ct, out, tag, PC_AESCCM_TAG_LEN);
88 memset(out, 0, ct_len);
115 "CcmWork outgrew PC_WORK_AESCCM - raise it in protocore_config.h, which derives PC_SECURE_ARENA_SIZE from it");
117inline void ccm_key_init(CcmWork *w,
const uint8_t *key,
size_t key_len)
131inline void ecb(
const CcmWork *w,
const uint8_t in[16], uint8_t out[16])
137inline void ctr_block(uint8_t A[16],
const uint8_t *nonce,
size_t nonce_len,
size_t i)
139 const size_t L = 15 - nonce_len;
141 A[0] = (uint8_t)(L - 1);
142 memcpy(A + 1, nonce, nonce_len);
143 for (
size_t j = 0; j < L; j++)
145 A[15 - j] = (uint8_t)((i >> (8 * j)) & 0xff);
150void cbc_mac(CcmWork *w,
const uint8_t *nonce,
size_t nonce_len,
const uint8_t *aad,
size_t aad_len,
const uint8_t *pt,
153 const size_t L = 15 - nonce_len;
157 memset(w->blk, 0, 16);
158 w->blk[0] = (uint8_t)((aad_len > 0 ? 0x40 : 0x00) | (((PC_AESCCM_TAG_LEN - 2) / 2) << 3) | (L - 1));
159 memcpy(w->blk + 1, nonce, nonce_len);
160 for (
size_t j = 0; j < L; j++)
162 w->blk[15 - j] = (uint8_t)((pt_len >> (8 * j)) & 0xff);
164 for (
int i = 0; i < 16; i++)
166 w->X[i] ^= w->blk[i];
174 memset(w->blk, 0, 16);
175 w->blk[0] = (uint8_t)((aad_len >> 8) & 0xff);
176 w->blk[1] = (uint8_t)(aad_len & 0xff);
179 while (off < aad_len)
181 size_t take = 16 - fill;
182 if (take > aad_len - off)
184 take = aad_len - off;
186 memcpy(w->blk + fill, aad + off, take);
189 for (
int i = 0; i < 16; i++)
191 w->X[i] ^= w->blk[i];
194 memset(w->blk, 0, 16);
203 memset(w->blk, 0, 16);
204 size_t take = pt_len - off;
209 memcpy(w->blk, pt + off, take);
210 for (
int i = 0; i < 16; i++)
212 w->X[i] ^= w->blk[i];
220void ctr_crypt(CcmWork *w,
const uint8_t *nonce,
size_t nonce_len,
size_t i0,
const uint8_t *in,
size_t len,
227 ctr_block(w->A, nonce, nonce_len, i);
229 size_t take = len - off;
234 for (
size_t j = 0; j < take; j++)
236 out[off + j] = in[off + j] ^ w->S[j];
245void tag_encrypt(CcmWork *w,
const uint8_t *nonce,
size_t nonce_len, uint8_t out_tag[PC_AESCCM_TAG_LEN])
247 ctr_block(w->A, nonce, nonce_len, 0);
249 for (
int i = 0; i < PC_AESCCM_TAG_LEN; i++)
251 out_tag[i] = (uint8_t)(w->X[i] ^ w->S[i]);
256bool pc_aesccm_seal_tag(
const uint8_t *key,
size_t key_len,
const uint8_t *nonce,
size_t nonce_len,
const uint8_t *aad,
257 size_t aad_len,
const uint8_t *pt,
size_t pt_len, uint8_t *ct_out,
258 uint8_t tag_out[PC_AESCCM_TAG_LEN])
260 if (!key || !nonce || !ct_out || !tag_out || (key_len != 16 && key_len != 32) || nonce_len < 7 || nonce_len > 13)
265 const pc_span &ws = ws_b.span();
270 CcmWork *w =
reinterpret_cast<CcmWork *
>(ws.
buf);
271 ccm_key_init(w, key, key_len);
272 cbc_mac(w, nonce, nonce_len, aad, aad_len, pt, pt_len);
273 ctr_crypt(w, nonce, nonce_len, 1, pt, pt_len, ct_out);
274 tag_encrypt(w, nonce, nonce_len, tag_out);
278bool pc_aesccm_open_tag(
const uint8_t *key,
size_t key_len,
const uint8_t *nonce,
size_t nonce_len,
const uint8_t *aad,
279 size_t aad_len,
const uint8_t *ct,
size_t ct_len,
const uint8_t tag[PC_AESCCM_TAG_LEN],
282 if (!key || !nonce || !ct || !out || !tag || (key_len != 16 && key_len != 32) || nonce_len < 7 || nonce_len > 13)
287 const pc_span &ws = ws_b.span();
292 CcmWork *w =
reinterpret_cast<CcmWork *
>(ws.
buf);
293 ccm_key_init(w, key, key_len);
294 ctr_crypt(w, nonce, nonce_len, 1, ct, ct_len, out);
295 cbc_mac(w, nonce, nonce_len, aad, aad_len, out, ct_len);
296 tag_encrypt(w, nonce, nonce_len, w->blk);
297 if (!pc_ct_eq(w->blk, tag, PC_AESCCM_TAG_LEN))
299 memset(out, 0, ct_len);
Compact table-free software AES key schedule + single-block encrypt (FIPS 197) - one source of truth.
void pc_aes_key_expand(const uint8_t *key, int nk, uint32_t *rk)
AES key expansion (FIPS 197 sec 5.2). nk key words (4=AES-128, 8=AES-256); rk receives 4*(nk + 7) rou...
void pc_aes_encrypt_block(const uint32_t *rk, int nr, const uint8_t in[16], uint8_t out[16])
AES single-block encrypt (FIPS 197 sec 5.1), nr rounds (10=AES-128, 14=AES-256). State is column-majo...
AEAD AES-CCM (NIST SP 800-38C / RFC 3610), 128- and 256-bit keys, detached tag.
A secure borrow whose acquire and release are one call each.
Per-translation-unit optimization override for hot, pure-integer crypto.
Constant-time comparison for secret-dependent checks.
Secure pool accessor - borrows that hold key material.
bool pc_span_ok(const pc_span &s)
True when the span refers to real storage and every write so far has fit.
A writable byte region: the storage, the capacity that belongs to it, and what has been produced into...
uint8_t * buf
first byte, or nullptr when the region could not be obtained