ProtoCore v1.0.16
Deterministic, zero-heap network stack for embedded targets
Loading...
Searching...
No Matches
aesccm.h
Go to the documentation of this file.
1// ProtoCore v1.0.16 - Copyright (C) 2026 Douglas Quigg (dstroy0) <dquigg123@gmail.com>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4#ifndef PROTOCORE_AESCCM_H
5#define PROTOCORE_AESCCM_H
6
7#include "protocore_config.h" // the entry point: protocore_types.h for the widths
8
10
11/**
12 * @file aesccm.h
13 * @brief AEAD AES-CCM (NIST SP 800-38C / RFC 3610), 128- and 256-bit keys, detached tag.
14 *
15 * CCM = CTR encryption + CBC-MAC authentication under one key. SMB 3.x offers it as
16 * SMB2_ENCRYPTION_AES128_CCM (0x0001) and SMB2_ENCRYPTION_AES256_CCM (0x0003); the transport uses an
17 * 11-byte nonce and a 16-byte tag (MS-SMB2 ยง3.1.4.3). The entries below are one surface over both arms: the
18 * SP 800-38C construction is the same on either, and the AES block under it is the part's accelerator where
19 * it carries one and the shared software block (crypto/cipher/aes_block.h) where it does not, so the whole
20 * AEAD is unit-testable off-target.
21 *
22 * The key rides with the record: a seal or an open expands it into the borrow and runs that one record
23 * under it. The tag is detached: a seal writes the ciphertext and the 16 tag bytes to separate
24 * destinations, which is where the SMB2 TRANSFORM_HEADER carries them - the Signature field holds the tag.
25 *
26 * Host-tested against reference AES-CCM vectors (nonce 11, tag 16, AES-128 and AES-256).
27 *
28 * @ref AesCcmNs::open fails closed: on a tag mismatch it zeroes @c out and @ref AesCcmNs::ok comes back
29 * false, so no unauthenticated plaintext reaches the caller.
30 *
31 * @c work is PROTOCORE_AESCCM_BORROW secure bytes the CALLER took, at an address it knows. It is not held past the
32 * call, so nothing here aliases it. The caller releases it, and the pool wipes on release; this module neither takes
33 * it, holds it, releases it, nor wipes it. The borrow IS the record context, so two records are two borrows and never
34 * collide, and the expanded key schedule dies with the release.
35 *
36 * @author Douglas Quigg (dstroy0)
37 * @date 2026
38 */
39
40/** @brief AES-CCM authentication tag length used by SMB 3.x (bytes). */
41#define PROTOCORE_AESCCM_TAG_LEN 16
42
43/** @brief Dispatch table. Addressed by offset, so the layout is asserted below. */
44typedef struct
45{
46 proto_bool (*seal)(uint8_t *, const uint8_t *, size_t, const uint8_t *, size_t, const uint8_t *, size_t,
47 const uint8_t *, size_t, uint8_t *, uint8_t *);
48 proto_bool (*open)(uint8_t *, const uint8_t *, size_t, const uint8_t *, size_t, const uint8_t *, size_t,
49 const uint8_t *, size_t, const uint8_t *, uint8_t *);
50} AesCcmNs;
52
53/**
54 * @brief CBC-MAC the record, encrypt the payload from A1, write the detached tag.
55 * @param work PROTOCORE_AES_CCM_BORROW bytes the caller took. Not held past the call.
56 * @param key 16 bytes (AES-128) or 32 bytes (AES-256)
57 * @param key_len 16 or 32
58 * @param nonce 7..13 bytes; SMB uses 11
59 * @param nonce_len its length
60 * @param aad additional authenticated data, NULL when aad_len is 0
61 * @param aad_len its length, below 0xFF00
62 * @param pt the plaintext
63 * @param pt_len its length
64 * @param ct_out pt_len ciphertext bytes; may alias pt
65 * @param tag_out PROTOCORE_AESCCM_TAG_LEN bytes
66 * @return PROTO_TRUE on success.
67 */
68proto_bool protocore_aes_ccm_seal(uint8_t *work, const uint8_t *key, size_t key_len, const uint8_t *nonce,
69 size_t nonce_len, const uint8_t *aad, size_t aad_len, const uint8_t *pt,
70 size_t pt_len, uint8_t *ct_out, uint8_t *tag_out);
71/**
72 * @brief Decrypt from A1, recompute the tag over the recovered plaintext, compare it in.
73 * @param work PROTOCORE_AES_CCM_BORROW bytes the caller took. Not held past the call.
74 * @param key 16 bytes (AES-128) or 32 bytes (AES-256)
75 * @param key_len 16 or 32
76 * @param nonce 7..13 bytes; SMB uses 11
77 * @param nonce_len its length
78 * @param aad additional authenticated data, NULL when aad_len is 0
79 * @param aad_len its length, below 0xFF00
80 * @param ct the ciphertext
81 * @param ct_len its length
82 * @param tag PROTOCORE_AESCCM_TAG_LEN bytes to verify against
83 * @param out ct_len plaintext bytes; may alias ct
84 * @return PROTO_TRUE on success.
85 */
86proto_bool protocore_aes_ccm_open(uint8_t *work, const uint8_t *key, size_t key_len, const uint8_t *nonce,
87 size_t nonce_len, const uint8_t *aad, size_t aad_len, const uint8_t *ct,
88 size_t ct_len, const uint8_t *tag, uint8_t *out);
89
90/** @brief Module namespace. */
92
94
95#endif // PROTOCORE_AESCCM_H
PROTOCORE_NS AesCcmNs AesCcm PROTOCORE_UNUSED
Module namespace.
Definition aesccm.h:91
proto_bool protocore_aes_ccm_open(uint8_t *work, const uint8_t *key, size_t key_len, const uint8_t *nonce, size_t nonce_len, const uint8_t *aad, size_t aad_len, const uint8_t *ct, size_t ct_len, const uint8_t *tag, uint8_t *out)
Decrypt from A1, recompute the tag over the recovered plaintext, compare it in.
proto_bool protocore_aes_ccm_seal(uint8_t *work, const uint8_t *key, size_t key_len, const uint8_t *nonce, size_t nonce_len, const uint8_t *aad, size_t aad_len, const uint8_t *pt, size_t pt_len, uint8_t *ct_out, uint8_t *tag_out)
CBC-MAC the record, encrypt the payload from A1, write the detached tag.
#define PROTOCORE_NS_LAYOUT(T,...)
Pin every dispatch slot of a table that is nothing but function pointers.
#define PROTOCORE_NS
Storage for a dispatch table. The const is load bearing.
Dispatch table. Addressed by offset, so the layout is asserted below.
Definition aesccm.h:45
proto_bool(* seal)(uint8_t *, const uint8_t *, size_t, const uint8_t *, size_t, const uint8_t *, size_t, const uint8_t *, size_t, uint8_t *, uint8_t *)
Definition aesccm.h:46
#define PROTOCORE_BEGIN_DECLS
Give a header's declarations C linkage, so their symbol names carry no parameter types.
Definition types.h:96
_Bool proto_bool
The truth value.
Definition types.h:64
#define PROTOCORE_END_DECLS
Definition types.h:97