On the ubuntu-24.04 runner image with kernel 7.0.0-1017-azure, every
--enable-linuxkm-pie build fails with:
libwolfssl.o: error: objtool: wc_HmacSizeByType+0x55: unannotated
intra-function call
PIE builds use -mindirect-branch=thunk-inline, whose inline retpolines
are calls to a label inside the same function. On 7.0 objtool checks
the linked libwolfssl.o, which ignores OBJECT_FILES_NON_STANDARD, and
rejects them. The same builds pass on the older 6.17 runner kernel, so
the failure depends on which image a job lands on.
Pass KBUILD_EXTRA_FLAGS=FORCE_GLOBAL_OBJTOOL_OFF=1 for the PIE builds
in the Membrowse linuxkm-pie target and the Kernel Module Build
workflow. linuxkm/Kbuild then undefines CONFIG_OBJTOOL, which disables
all objtool passes since the kernel's objtool rules are gated on it.
Non-PIE builds keep objtool.
membrowse-action v1.2.16 moved the floating v1 tag to a release whose
action.yml has "${{ github.workspace }}" in an input description. The
runner rejects the github context there, so every Membrowse analyze job
fails in "Set up job" with "Unrecognized named-value: 'github'". The
onboard action has the same problem, and the comment workflow then
fails because no report was uploaded.
Pin the report, onboard and comment workflows to the v1.2.15 commit SHA,
the last release that worked, as the Zephyr workflow already does.
-- i.e., by default, disable the TLS/DTLS layer when KERNEL_MODE_DEFAULTS;
CMakeLists.txt: add WOLFSSL_KERNEL_SETTINGS and make existing
WOLFSSL_LINUXKM_DEFAULTS an alias for it, and make WOLFSSL_CRYPT_ONLY default
follow WOLFSSL_KERNEL_SETTINGS via new internal variable
WOLFSSL_CRYPT_ONLY_DEFAULT;
.github/workflows/linuxkm.yml: explicitly --disable-cryptonly in the
--enable-all scenario;
.github/workflows/fips-dev-no-post.yml: explicitly --disable-cryptonly in the
kernel-settings* scenarios.
wolfIP releases up to v1.1.0 have three Makefile rules that each run
tools/certs/mkcerts.sh, one per generated cert source. Under make -j
they run concurrently and clobber each other's files, leaving
server_cert.c without server_der, so build/test-wolfssl intermittently
fails to link. On the latest-release leg the job then asks for a
breaks-wolfip= token although wolfSSL broke nothing.
Run mkcerts.sh once before make so the cert sources already exist.
This stays harmless once wolfIP serializes the rule itself, and keeps
the released tags, which will never get that fix, building reliably.
The script is only run when present so a later wolfIP layout change
cannot fail the job here.
The fpr shift helpers have a separate implementation for targets
without WC_64BIT_CPU, which no CI job built. Add a smallest-mem leg with
-DWC_32BIT_CPU so the white-box exercises it.
falcon_native_verify_msg placed its 2*n word16 working buffer on the stack
unless WOLFSSL_SMALL_STACK was set. That buffer is sized for the highest
enabled level, so a Falcon-512 verify used 4 KB of stack for it whenever
Falcon-1024 was built in, and verify reached about 5.7 KB of stack on a
Cortex-M33/M7 while keygen and sign stay near 1.2-1.4 KB.
Verify now allocates the buffer per call, sized for the key's own level
(2 KB for Falcon-512, 4 KB for Falcon-1024), so it can return MEMORY_E;
the wc_falcon_verify_msg documentation says so. WOLFSSL_NO_MALLOC builds
keep the buffer on the stack. To keep it off the stack without an
allocator, WOLFSSL_FALCON_VERIFY_NO_MALLOC
(--enable-falcon=verify-no-malloc) holds the buffer in falcon_key
instead, sized for the highest enabled level, the same approach as
WOLFSSL_MLDSA_VERIFY_NO_MALLOC. With it, a key verifies one signature at
a time and falcon_key grows by 4*FALCON_MAX_N bytes.
On an STM32H743 a Falcon-512 verify goes from 5648 B of stack and no heap
to 1568 B of stack and 2048 B of heap, at the same speed. The peak stack
of a TLS 1.3 handshake that verifies a Falcon-512 chain drops from 6.3 KB
to 3.7 KB.
The falcon-interop backend matrix gains verify-no-malloc and
level1+dynamic-keys+verify-no-malloc legs running the full unit suite.
fips-dev-no-post.yml runs seven configs through parallel-make-check.py,
four at a time, but never installed bubblewrap. The test scripts only
re-exec under bwrap --unshare-net when it is present, so every unit.test
shared the runner's network namespace.
test.h binds its listeners with SO_REUSEADDR and SO_REUSEPORT. With
those set, a Linux UDP bind to port 0 can return a port another process
already holds, and the DTLS server rebinds its port for each resumption.
A client's ClientHello can then reach another config's DTLS server,
which answers with a fatal alert, e.g. a DTLS 1.2 -r pair failing with
"wolfSSL_connect resume error -313" while every API test passed.
Install bubblewrap and lift the AppArmor userns restriction, as the
other parallel make check workflows already do. The job installs from
the ubuntu-24.04-linuxkm bundle, so add bubblewrap to its package set
too; until that bundle is rebuilt the job falls back to the apt mirror.
SE050 and CryptoCell are supported with this.
WOLFSSL_NO_RSA_SW to disable the RSA software implementation.
WOLFSSL_NO_ECC_SW to disable the ECC software implementation.
Add an enterprise option that includes all items that would be required.
Update CMake build to match autotools. Added enterprise option.
Added CI loops for configuration options.
Add document that maps the OpenSSL configuration options to wolfSSL's.
Checked against various versions of OpenSSL.
Small memory signing walked matrix A a row at a time and copied and
transformed the polynomial of y it needed for every element of the row.
Each polynomial of y was therefore transformed k times with an identical
result: 156 transforms per ML-DSA-65 signature where 31 are needed.
Walk the matrix a column at a time instead. Every row of the matrix uses
the same column of y, so the transform is done once and the products are
accumulated down the column into w0, which is already a vector of k
polynomials. Inverting, decomposing and encoding then run as a second
pass over the rows, with w0 replaced in place and the scratch polynomial
holding w1. w is reduced before the inverse transform on both column
accumulating paths.
Vector y stays resident, so unlike the smallest memory implementation
this does not have to regenerate it, and it keeps generating y as a whole
vector so the assembly generators are still used.
With WOLFSSL_MLDSA_SIGN_SMALL_MEM_PRECALC_A the pre-calculated rows are
multiplied as a vector, and w is sized for all k rows: the ML-DSA-44
decompose kernels take no dimension and touch every row, so the rows above
the pre-calculated ones are cleared, and mldsa_vec_encode_w1() now honours
the dimension it is given. The whole-vector helpers that path drives are
gated on a new MLDSA_SIGN_VEC_HELPERS, which names the set of callers.
Under WC_MLDSA_FAULT_HARDEN the column loop checks that the polynomial of
y it reads, walked independently of the column index, lies inside y.
Memory is unchanged: w0 was already held for the hints and the row
accumulator becomes the scratch the transform runs in.
WOLFSSL_MLDSA_SMALL_MEM_POLY64 no longer applies to signing as a 64-bit
accumulator would now be needed for every row of w, which also returns
the 2KB it was allocating. The option now only affects small memory key
generation and verification; the option list says so.
Signatures are unchanged. Signing is 12 to 29 percent quicker with the C
code and 6 to 12 percent quicker with AVX-512, which makes it faster than
the smallest memory implementation on every target rather than only where
the assembly runs. Add pq-all rows for PRECALC_A split part way, saturated
past k, and on the Intel assembly paths, and a -Wconversion row.
Small memory signing kept vector w1 as k full polynomials although it is
only ever consumed in its encoded form, once by the commit hash and once
by MakeHint, which only tests each coefficient for zero. Keep the encoded
w1 and build it a polynomial at a time from a single scratch polynomial
of w. This also removes the separate w1 encode buffer that was allocated
and freed on every rejection attempt.
Add WOLFSSL_MLDSA_SIGN_SMALLEST_MEM. It generates matrix A a column at a
time so that one polynomial of y is held instead of the whole vector and
is transformed once rather than once per row, decomposes w into w0 in
place, and regenerates y for the z calculation. It cannot be combined with
the PRECALC options, and WOLFSSL_MLDSA_SMALL_MEM_POLY64 has no effect on
signing in this mode. The z polynomial, which is not live at either
expansion, serves as the mask expansion scratch, so the signer makes one
allocation per signature.
Because y is derived twice per rejection round, bind the two derivations:
each polynomial of y is checksummed when it is first expanded and checked
when it is regenerated for z, and a mismatch fails with BAD_COND_E rather
than producing z from a different mask than the commitment used. The
checksum is a pair of Fletcher style sums, which catch any change to one
or two coefficients of a y polynomial without multiplying the secret
coefficients, as a multiply chain is not constant time on every core. The
checksums are zeroized on return. The key's SHAKE object, whose last use
regenerates a polynomial of y and would otherwise leave rho'' recoverable
from the key, is re-initialized, which clears its state but keeps the hash
type a crypto callback free needs.
Small memory key generation held t as a full vector for one final vector
encode. Encode t a polynomial at a time and overlay t and the single
decoded s2 polynomial on the s2 vector, which is dead once s2 has been
encoded into the private key.
Peak heap, in bytes, measured with a counting allocator:
sign before sign after smallest keygen before after
ML-DSA-44 16200 13896 9800 14152 10056
ML-DSA-65 21320 16968 11848 19272 13128
ML-DSA-87 27464 21320 14152 25416 17224
Signatures are unchanged. Add a signing KAT to testwolfcrypt: signing is
deterministic given the key seed and the signing seed, so every signer must
produce the same bytes, and the test compares a SHAKE-256 digest of the
signature with the default signer's. tests/api holds full signing KATs,
but unit.test is not built in the --enable-cryptonly CI rows that cover
the small and smallest memory signers.
Problems found while making these changes are fixed here too:
- mldsa_vec_expand_mask dispatched to AVX2 generators that only handle
dimensions 4, 5 and 7, and silently left y untouched for any other
dimension. Test the dimension before saving the vector registers and
fall through to the C implementation otherwise.
- WOLFSSL_MLDSA_SIGN_SMALL_MEM_PRECALC_A greater than k indexed A, w0
and w1 past their allocations, as the loops used the raw macro rather
than min(macro, k).
- WOLFSSL_MLDSA_SIGN_CHECK_W0 passed two arguments to the three argument
mldsa_vec_check_low, so the option never compiled with small memory
signing.
- WOLFSSL_MLDSA_VERIFY_SMALLEST_MEM did not build alongside small memory
signing, as mldsa_vec_ntt_full and mldsa_vec_check_low were unused.
- WOLFSSL_MLDSA_VERIFY_SMALLEST_MEM sized z at l polynomials while only
ever using one.
Add pq-all and -Wconversion CI rows for the smallest memory signer, with
and without the y and w0 checks and verification.