Repository navigation
linuxkm: register a wolfCrypt single-block "aes" crypto_cipher - #11612
MarkAtwood wants to merge 1 commit into
Conversation
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Decryption-disabled and restricted-key-size configurations are not handled correctly.
Review effort: Balanced
Findings: 1
Open (2)
What changed in this PR
Registers a bare single-block AES implementation with the Linux Kernel Crypto API for ESSIV and similar consumers.
Changes:
- Adds AES cipher registration, encryption/decryption, and KATs.
- Adds feature gates and configure options.
- Imports the required kernel cipher API.
| File | Description |
|---|---|
linuxkm/lkcapi_glue.c |
Registers and unregisters the cipher. |
linuxkm/lkcapi_aes_glue.c |
Implements and tests single-block AES. |
linuxkm/linuxkm_wc_port.h |
Includes the internal cipher API. |
configure.ac |
Adds aes registration controls. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| * essiv(cbc(aes),sha256), which encrypts each sector IV with it. Without it, | ||
| * dm-crypt aes-cbc-essiv volumes run IV generation outside wolfCrypt. | ||
| */ | ||
| #ifdef HAVE_AES_ECB |
| static const struct { | ||
| unsigned int key_len; | ||
| const u8 *ct; | ||
| } kat[] = { { 16, ct128 }, { 32, ct256 } }; |
|
88baecd to
f42f110
Compare
f42f110 to
1131e01
Compare
1131e01 to
dd4723c
Compare
|
retest this please |
dd4723c to
959405b
Compare
959405b to
0efc335
Compare
douzzer
left a comment
There was a problem hiding this comment.
Alas the problem this PR is trying to solve is harder than it looks.
struct cipher_alg can't be used in a FIPS call stack because it has void slots
for .cia_encrypt and .cia_decrypt -- must-succeed APIs -- which are incompatible
with FIPS-required refusal of service in the degraded state.
What this means in practice: wolfCrypt can supply the implementation for the
cipher_alg block cipher, but only by using direct function calls that are not
wrapped by FIPS shims, and never with strict FIPS compliance.
The PR's call to km_AesSetKeyCommon() from km_AesDirectSetKey() is correct as-is,
because cipher_alg.cia_setkey does return an integer error code as needed.
However, the PR's implementation of km_AesDirectCrypt() zeroes the output buffer
on any failure from wc_AesEcbEncrypt() or wc_AesEcbDecrypt() (FIPS-wrapped
service functions). This converts degraded state into a vulnerability: a
legitimate consumer composed over the bare cipher (e.g. the xcbc template under
IPsec) computes its result from zeroed blocks and returns success, so the result
becomes a key-independent function of the message -- computable offline by an
adversary able to force or detect degraded state, whose forgeries then verify.
To avoid introducing this serious and otherwise irremediable vulnerability,
km_AesDirectCrypt() must call the non-FIPS wc_AesEncryptDirect() and
wc_AesDecryptDirect(), which succeed unconditionally in practice (there are no
NMI block cipher consumers in the kernel, and all other contexts are fulfilled
unconditionally). Even then, the impossibility of propagating an error to the
caller by itself precludes FIPS compliance, hence the need (which remains) for
fallthrough failure handling with rate-limited system logging. And note that
the new glue needs to be gated on defined(WOLFSSL_AES_DIRECT), which is defined
in all current and historical FIPS profiles.
Ultimately, this PR does not change the FIPS status of dm-crypt aes-cbc-essiv
volumes. The approved service is the cbc(aes) data path, which accepts
caller-supplied IVs as FIPS permits for CBC; the essiv IV derivation was never
an approved service, whether computed by the kernel's aes-lib (status quo) or by
wolfCrypt (this PR). No call stack that reaches cryptography through a void
interface can be claimed as an approved service.
0efc335 to
e4db874
Compare
|
switched to wc_AesEncryptDirect/wc_AesDecryptDirect, falls through to aes-lib on failure, no more zeroing, gated on WOLFSSL_AES_DIRECT. tested on 7.0 with and without a forced failure, essiv and xcbc match reference vectors. details in the description. |


Description
dm-crypt essiv (aes-cbc-essiv:sha256, the LUKS1 default) and xcbc get the bare
aescipher via crypto_alloc_cipher("aes"), linuxkm didn't register one so those stayed on the kernel's aes-lib. this adds a single-blockaescrypto_cipher on wc_AesEncryptDirect/wc_AesDecryptDirect.cia_encrypt/cia_decrypt are void and can't refuse service, so it's not an approved FIPS service. if a Direct call fails (v7 with a fatal signal pending, or an unaligned src on aesni) it falls through to the kernel aes-lib with a ratelimited log, same as wc__get_random_bytes. gated on WOLFSSL_AES_DIRECT, HAVE_AES_DECRYPT, 5.4+ and CONFIG_CRYPTO_LIB_AES, and
aes/-aeswork in --enable-linuxkm-lkcapi-register.Testing
ubuntu 26.04, 7.0.0-1016-aws, =aes, =all and =all --enable-aesni. fips-197 c.1-c.3, rfc 3566 xcbc cases 1-7, and dm-crypt essiv at 2048/2048 sectors vs pyca all pass, also with -DTEST_WC_LINUXKM_AESDIRECT_FALLTHROUGH forcing the aes-lib path.
Checklist