Skip to content

Commit bdad2c5

Browse files
feggemkannwischer
authored andcommitted
Document signing secret-key validity precondition
Signing APIs assume a valid, bit-packed secret key and do not perform full serialized-key validation (t0, tr, s1, s2). Callers importing serialized keys can validate them via pk_from_sk before signing. * Add @warning notices to all sign* / signature* / pre_hash sign entry points in mldsa_native.h and mldsa/src/sign.h, and reword the sk parameter descriptions to "assumed to be valid". * Expand the Wycheproof client comment for the InvalidPrivateKey skip: FIPS 204 does not require signing to validate serialized private keys, full validation covers t0 and tr and is exposed through pk_from_sk, and those vectors are still tested via pkFromSk. Signed-off-by: Fredrik Dahlgren <fredrik.dahlgren@trailofbits.com> [hbecker: rebase+squash, adjust commit message] Signed-off-by: Hanno Becker <beckphan@amazon.co.uk>
1 parent b67d7f1 commit bdad2c5

3 files changed

Lines changed: 54 additions & 11 deletions

File tree

mldsa/mldsa_native.h

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,10 @@ int MLD_API_NAMESPACE(keypair)(
246246
*
247247
* @spec{Implements @[FIPS204, Algorithm 7, ML-DSA.Sign_internal].}
248248
*
249+
* @warning This function does not perform secret key validation.
250+
* Callers importing serialized keys can use crypto_sign_pk_from_sk
251+
* to validate them before signing.
252+
*
249253
* @param[out] sig Output signature.
250254
* @param[out] siglen Pointer to output length of signature.
251255
* @param[in] m Pointer to message to be signed (when
@@ -258,7 +262,7 @@ int MLD_API_NAMESPACE(keypair)(
258262
* @param prelen Length of prefix string. Ignored when
259263
* externalmu != 0.
260264
* @param[in] rnd Random seed.
261-
* @param[in] sk Bit-packed secret key.
265+
* @param[in] sk Bit-packed secret key; assumed to be valid.
262266
* @param externalmu 0: m/mlen is the raw message; mu = H(tr, pre, m) is
263267
* computed internally.
264268
* non-zero: m points to a precomputed mu of
@@ -298,13 +302,17 @@ int MLD_API_NAMESPACE(signature_internal)(
298302
*
299303
* @spec{Implements @[FIPS204, Algorithm 2, ML-DSA.Sign].}
300304
*
305+
* @warning This function does not perform secret key validation.
306+
* Callers importing serialized keys can use crypto_sign_pk_from_sk
307+
* to validate them before signing.
308+
*
301309
* @param[out] sig Output signature.
302310
* @param[out] siglen Pointer to output length of signature.
303311
* @param[in] m Pointer to message to be signed.
304312
* @param mlen Length of message.
305313
* @param[in] ctx Pointer to context string. May be NULL if ctxlen == 0.
306314
* @param ctxlen Length of context string. Should be <= 255.
307-
* @param[in] sk Bit-packed secret key.
315+
* @param[in] sk Bit-packed secret key; assumed to be valid.
308316
* @param context Application context. Only present when
309317
* MLD_CONFIG_CONTEXT_PARAMETER is defined; type set by
310318
* MLD_CONFIG_CONTEXT_PARAMETER_TYPE.
@@ -340,10 +348,14 @@ int MLD_API_NAMESPACE(signature)(
340348
*
341349
* @spec{Implements @[FIPS204, Algorithm 2, ML-DSA.Sign external mu variant].}
342350
*
351+
* @warning This function does not perform secret key validation.
352+
* Callers importing serialized keys can use crypto_sign_pk_from_sk
353+
* to validate them before signing.
354+
*
343355
* @param[out] sig Output signature.
344356
* @param[out] siglen Pointer to output length of signature.
345357
* @param[in] mu Precomputed message representative.
346-
* @param[in] sk Bit-packed secret key.
358+
* @param[in] sk Bit-packed secret key; assumed to be valid.
347359
* @param context Application context. Only present when
348360
* MLD_CONFIG_CONTEXT_PARAMETER is defined; type set by
349361
* MLD_CONFIG_CONTEXT_PARAMETER_TYPE.
@@ -516,14 +528,18 @@ int MLD_API_NAMESPACE(verify_extmu)(
516528
* @warning This is an unstable API that may change in the future. If you need
517529
* a stable API use signature_pre_hash_shake256.
518530
*
531+
* @warning This function does not perform secret key validation.
532+
* Callers importing serialized keys can use crypto_sign_pk_from_sk
533+
* to validate them before signing.
534+
*
519535
* @param[out] sig Output signature.
520536
* @param[out] siglen Pointer to output length of signature.
521537
* @param[in] ph Pointer to pre-hashed message.
522538
* @param phlen Length of pre-hashed message.
523539
* @param[in] ctx Pointer to context string.
524540
* @param ctxlen Length of context string.
525541
* @param[in] rnd Random seed.
526-
* @param[in] sk Bit-packed secret key.
542+
* @param[in] sk Bit-packed secret key; assumed to be valid.
527543
* @param hashalg Hash algorithm constant (one of MLD_PREHASH_*).
528544
* @param context Application context. Only present when
529545
* MLD_CONFIG_CONTEXT_PARAMETER is defined; type set by
@@ -607,14 +623,18 @@ int MLD_API_NAMESPACE(verify_pre_hash_internal)(
607623
* @spec{Implements @[FIPS204, Algorithm 4, HashML-DSA.Sign] with SHAKE256 as
608624
* the pre-hash.}
609625
*
626+
* @warning This function does not perform secret key validation.
627+
* Callers importing serialized keys can use crypto_sign_pk_from_sk
628+
* to validate them before signing.
629+
*
610630
* @param[out] sig Output signature.
611631
* @param[out] siglen Pointer to output length of signature.
612632
* @param[in] m Pointer to message to be hashed and signed.
613633
* @param mlen Length of message.
614634
* @param[in] ctx Pointer to context string.
615635
* @param ctxlen Length of context string.
616636
* @param[in] rnd Random seed.
617-
* @param[in] sk Bit-packed secret key.
637+
* @param[in] sk Bit-packed secret key; assumed to be valid.
618638
* @param context Application context. Only present when
619639
* MLD_CONFIG_CONTEXT_PARAMETER is defined; type set by
620640
* MLD_CONFIG_CONTEXT_PARAMETER_TYPE.

mldsa/src/sign.h

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,10 @@ __contract__(
180180
*
181181
* @spec{Implements @[FIPS204, Algorithm 7, ML-DSA.Sign_internal].}
182182
*
183+
* @warning This function does not perform secret key validation.
184+
* Callers importing serialized keys can use mld_sign_pk_from_sk
185+
* to validate them before signing.
186+
*
183187
* @param[out] sig Output signature.
184188
* @param[out] siglen Pointer to output length of signature.
185189
* @param[in] m Pointer to message to be signed (when
@@ -192,7 +196,7 @@ __contract__(
192196
* @param prelen Length of prefix string. Ignored when
193197
* externalmu != 0.
194198
* @param[in] rnd Random seed.
195-
* @param[in] sk Bit-packed secret key.
199+
* @param[in] sk Bit-packed secret key; assumed to be valid.
196200
* @param externalmu 0: m/mlen is the raw message; mu = H(tr, pre, m) is
197201
* computed internally.
198202
* non-zero: m points to a precomputed mu of
@@ -246,13 +250,17 @@ __contract__(
246250
*
247251
* @spec{Implements @[FIPS204, Algorithm 2, ML-DSA.Sign].}
248252
*
253+
* @warning This function does not perform secret key validation.
254+
* Callers importing serialized keys can use mld_sign_pk_from_sk
255+
* to validate them before signing.
256+
*
249257
* @param[out] sig Output signature.
250258
* @param[out] siglen Pointer to output length of signature.
251259
* @param[in] m Pointer to message to be signed.
252260
* @param mlen Length of message.
253261
* @param[in] ctx Pointer to context string. May be NULL if ctxlen == 0.
254262
* @param ctxlen Length of context string. Should be <= 255.
255-
* @param[in] sk Bit-packed secret key.
263+
* @param[in] sk Bit-packed secret key; assumed to be valid.
256264
* @param context Application context. Only present when
257265
* MLD_CONFIG_CONTEXT_PARAMETER is defined; type set by
258266
* MLD_CONFIG_CONTEXT_PARAMETER_TYPE.
@@ -298,10 +306,14 @@ __contract__(
298306
*
299307
* @spec{Implements @[FIPS204, Algorithm 2, ML-DSA.Sign external mu variant].}
300308
*
309+
* @warning This function does not perform secret key validation.
310+
* Callers importing serialized keys can use mld_sign_pk_from_sk
311+
* to validate them before signing.
312+
*
301313
* @param[out] sig Output signature.
302314
* @param[out] siglen Pointer to output length of signature.
303315
* @param[in] mu Precomputed message representative.
304-
* @param[in] sk Bit-packed secret key.
316+
* @param[in] sk Bit-packed secret key; assumed to be valid.
305317
* @param context Application context. Only present when
306318
* MLD_CONFIG_CONTEXT_PARAMETER is defined; type set by
307319
* MLD_CONFIG_CONTEXT_PARAMETER_TYPE.
@@ -479,14 +491,18 @@ __contract__(
479491
* @warning This is an unstable API that may change in the future. If you need
480492
* a stable API use mld_sign_signature_pre_hash_shake256.
481493
*
494+
* @warning This function does not perform secret key validation.
495+
* Callers importing serialized keys can use mld_sign_pk_from_sk
496+
* to validate them before signing.
497+
*
482498
* @param[out] sig Output signature.
483499
* @param[out] siglen Pointer to output length of signature.
484500
* @param[in] ph Pointer to pre-hashed message.
485501
* @param phlen Length of pre-hashed message.
486502
* @param[in] ctx Pointer to context string.
487503
* @param ctxlen Length of context string.
488504
* @param[in] rnd Random seed.
489-
* @param[in] sk Bit-packed secret key.
505+
* @param[in] sk Bit-packed secret key; assumed to be valid.
490506
* @param hashalg Hash algorithm constant (one of MLD_PREHASH_*).
491507
* @param context Application context. Only present when
492508
* MLD_CONFIG_CONTEXT_PARAMETER is defined; type set by
@@ -584,14 +600,18 @@ __contract__(
584600
* @spec{Implements @[FIPS204, Algorithm 4, HashML-DSA.Sign] with SHAKE256 as
585601
* the pre-hash.}
586602
*
603+
* @warning This function does not perform secret key validation.
604+
* Callers importing serialized keys can use mld_sign_pk_from_sk
605+
* to validate them before signing.
606+
*
587607
* @param[out] sig Output signature.
588608
* @param[out] siglen Pointer to output length of signature.
589609
* @param[in] m Pointer to message to be hashed and signed.
590610
* @param mlen Length of message.
591611
* @param[in] ctx Pointer to context string.
592612
* @param ctxlen Length of context string.
593613
* @param[in] rnd Random seed.
594-
* @param[in] sk Bit-packed secret key.
614+
* @param[in] sk Bit-packed secret key; assumed to be valid.
595615
* @param context Application context. Only present when
596616
* MLD_CONFIG_CONTEXT_PARAMETER is defined; type set by
597617
* MLD_CONFIG_CONTEXT_PARAMETER_TYPE.

test/wycheproof/wycheproof_client.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,10 @@ class TestResult(Enum):
167167
def check_sign_result(tc, out):
168168
if tc["result"] == "invalid":
169169
flags = tc.get("flags", [])
170-
# InvalidPrivateKey: signing does not validate sk; tested via pk_from_sk
170+
# FIPS 204 does not require signing to validate serialized private keys.
171+
# Checking only s1/s2 would be incomplete: full validation also checks
172+
# t0 and tr and is exposed through pk_from_sk. These InvalidPrivateKey
173+
# vectors are skipped for signing and still tested through pkFromSk.
171174
if "InvalidPrivateKey" in flags:
172175
return TestResult.SKIPPED
173176
# If new invalid-flag classes appear, fail loudly so we can handle them.

0 commit comments

Comments
 (0)