From 8bb46362b703762a9cf2fc564f8f8669c42f091f Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Thu, 16 Jul 2026 08:48:55 +0000 Subject: [PATCH 1/2] Use byte ctxLen in wc_dilithium_verify_ctx_msg cdef (F-4014) The CFFI cdef declared wc_dilithium_verify_ctx_msg with word32 ctxLen while the sign variants use byte ctxLen. wolfSSL's real API (wc_MlDsaKey_VerifyCtx in wolfcrypt/wc_mldsa.h, which the wc_dilithium_verify_ctx_msg macro forwards to) takes byte ctxLen, matching FIPS 204's 255-byte context cap. The mismatched cdef made CFFI marshal a 4-byte word32 into a 1-byte slot, silently truncating any ctxLen > 255 to its low byte. Declare ctxLen as byte to match the sign cdef and the underlying API. --- scripts/build_ffi.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/build_ffi.py b/scripts/build_ffi.py index 82087b3..6807edf 100644 --- a/scripts/build_ffi.py +++ b/scripts/build_ffi.py @@ -1350,7 +1350,7 @@ def build_ffi(local_wolfssl, features): int wc_dilithium_import_public(const byte* in, word32 inLen, dilithium_key* key); int wc_dilithium_sign_ctx_msg(const byte* ctx, byte ctxLen, const byte* msg, word32 msgLen, byte* sig, word32* sigLen, dilithium_key* key, WC_RNG* rng); int wc_dilithium_sign_ctx_msg_with_seed(const byte* ctx, byte ctxLen, const byte* msg, word32 msgLen, byte* sig, word32* sigLen, dilithium_key* key, const byte* seed); - int wc_dilithium_verify_ctx_msg(const byte* sig, word32 sigLen, const byte* ctx, word32 ctxLen, const byte* msg, word32 msgLen, int* res, dilithium_key* key); + int wc_dilithium_verify_ctx_msg(const byte* sig, word32 sigLen, const byte* ctx, byte ctxLen, const byte* msg, word32 msgLen, int* res, dilithium_key* key); typedef dilithium_key MlDsaKey; int wc_MlDsaKey_GetPrivLen(MlDsaKey* key, int* len); int wc_MlDsaKey_GetPubLen(MlDsaKey* key, int* len); From 2fea30cd32ee09e4e2090f43d3227d5f3fea45c0 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Thu, 16 Jul 2026 13:44:55 +0000 Subject: [PATCH 2/2] Validate ctx length in MlDsa.verify (F-4014) MlDsa.sign/sign_with_seed reject a context longer than 255 bytes with ValueError, but verify did not. With ctxLen now correctly declared as byte in the cdef, an over-long ctx would surface as a low-level CFFI OverflowError instead of the consistent ValueError callers get from the signing paths. Reject len(ctx) > 255 with ValueError in verify, matching sign. --- wolfcrypt/ciphers.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/wolfcrypt/ciphers.py b/wolfcrypt/ciphers.py index b7b8c05..d66071e 100644 --- a/wolfcrypt/ciphers.py +++ b/wolfcrypt/ciphers.py @@ -2364,6 +2364,10 @@ def verify(self, signature: BytesOrStr, message: BytesOrStr, ctx: BytesOrStr | N if ctx is not None: ctx_bytestype = t2b(ctx) + if len(ctx_bytestype) > 255: + raise ValueError( + f"context length {len(ctx_bytestype)} too large: must be 255 or less" + ) ret = _lib.wc_dilithium_verify_ctx_msg( sig_bytestype, len(sig_bytestype),