Skip to content

Commit 34df758

Browse files
Code review feedback
1 parent e886d50 commit 34df758

3 files changed

Lines changed: 62 additions & 12 deletions

File tree

doc/dox_comments/header_files/dsa.h

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,56 @@ int wc_DsaSign(const byte* digest, byte* out,
162162
int wc_DsaVerify(const byte* digest, const byte* sig,
163163
DsaKey* key, int* answer);
164164

165+
/*!
166+
\ingroup DSA
167+
168+
\brief This function validates DSA domain parameters and the public
169+
key contained in the given DsaKey. It performs the following checks
170+
(a subset of the requirements in FIPS 186-4 and NIST SP 800-89):
171+
p > 1 and q > 1; q divides (p - 1); 1 < g < p; 1 < y < p; g^q mod p
172+
== 1 (so the multiplicative order of g divides q); and y^q mod p == 1
173+
(so the multiplicative order of y divides q). The verify
174+
routines (wc_DsaVerify, wc_DsaVerify_ex) call this internally before
175+
any signature math runs, but the function is also exposed so callers
176+
can validate keys at import or decode time.
177+
178+
\return 0 Returned when the key and domain parameters pass validation.
179+
\return BAD_FUNC_ARG Returned when key is NULL, or when the key fails
180+
any of the validation checks listed above.
181+
\return MEMORY_E Returned on memory allocation failure (small-stack
182+
builds only).
183+
\return MP_INIT_E Returned when mp_int initialization fails.
184+
\return Other negative MP error codes (e.g. MP_EXPTMOD_E) Returned on
185+
internal big-integer failures.
186+
187+
Note: this function does not run primality tests on p or q. Full
188+
FIPS 186-4 domain-parameter validation additionally requires that p
189+
and q be prime; callers that need that level of assurance should use
190+
wc_DsaImportParamsRawCheck() (which validates p) and/or run
191+
mp_prime_is_prime_ex() on q at import time.
192+
193+
\param key pointer to a DsaKey structure populated with p, q, g, and y
194+
195+
_Example_
196+
\code
197+
DsaKey key;
198+
int ret;
199+
wc_InitDsaKey(&key);
200+
// ... import or decode the public key into &key ...
201+
ret = wc_DsaCheckPubKey(&key);
202+
if (ret != 0) {
203+
// domain parameters or public key are invalid; reject
204+
}
205+
wc_FreeDsaKey(&key);
206+
\endcode
207+
208+
\sa wc_DsaVerify
209+
\sa wc_DsaPublicKeyDecode
210+
\sa wc_DsaImportParamsRaw
211+
\sa wc_DsaImportParamsRawCheck
212+
*/
213+
int wc_DsaCheckPubKey(DsaKey* key);
214+
165215
/*!
166216
\ingroup DSA
167217

tests/api/test_dsa.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -665,8 +665,9 @@ int test_wc_DsaCheckPubKey(void)
665665
ExpectIntEQ(mp_copy(&key.p, &key.g), 0);
666666
ExpectIntEQ(wc_DsaCheckPubKey(&key), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
667667

668-
/* g in range [2, p-1] but NOT in the order-q subgroup.
669-
* g = 2 will generate a subgroup of order != q, so 2^q mod p != 1. */
668+
/* g in range [2, p-1] but ord(g) does not divide q.
669+
* For our FIPS-style p, 2 has order (p-1)/k for small k and (p-1)/q
670+
* is not 1, so 2^q mod p != 1 and the check rejects. */
670671
ExpectIntEQ(mp_set(&key.g, 2), 0);
671672
ExpectIntEQ(wc_DsaCheckPubKey(&key), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
672673

@@ -688,7 +689,7 @@ int test_wc_DsaCheckPubKey(void)
688689
ExpectIntEQ(mp_copy(&key.p, &key.y), 0);
689690
ExpectIntEQ(wc_DsaCheckPubKey(&key), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
690691

691-
/* y in range but NOT in the order-q subgroup: y = 2. */
692+
/* y in range but ord(y) does not divide q: y = 2 fails y^q mod p == 1. */
692693
ExpectIntEQ(mp_set(&key.y, 2), 0);
693694
ExpectIntEQ(wc_DsaCheckPubKey(&key), WC_NO_ERR_TRACE(BAD_FUNC_ARG));
694695

wolfcrypt/src/dsa.c

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,8 @@ void wc_FreeDsaKey(DsaKey* key)
101101
* - q divides (p - 1) (FIPS 186-4 A.1.1.2)
102102
* - 1 < g < p
103103
* - 1 < y < p
104-
* - g^q mod p == 1 (g generates the order-q subgroup)
105-
* - y^q mod p == 1 (y is in the order-q subgroup)
104+
* - g^q mod p == 1 (i.e. ord(g) divides q)
105+
* - y^q mod p == 1 (i.e. ord(y) divides q)
106106
*
107107
* Note: this routine does not run primality tests on p or q. Full FIPS
108108
* 186-4 domain-parameter validation additionally requires that p and q be
@@ -1135,6 +1135,12 @@ int wc_DsaVerify_ex(const byte* digest, word32 digestSz, const byte* sig,
11351135
return BAD_LENGTH_E;
11361136
}
11371137

1138+
/* Validate domain parameters and public key before doing any
1139+
* signature math. */
1140+
ret = wc_DsaCheckPubKey(key);
1141+
if (ret != 0)
1142+
return ret;
1143+
11381144
do {
11391145
#ifdef WOLFSSL_SMALL_STACK
11401146
w = (mp_int *)XMALLOC(sizeof *w, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
@@ -1166,13 +1172,6 @@ int wc_DsaVerify_ex(const byte* digest, word32 digestSz, const byte* sig,
11661172
break;
11671173
}
11681174

1169-
/* Validate domain parameters and public key before doing any
1170-
* signature math. */
1171-
ret = wc_DsaCheckPubKey(key);
1172-
if (ret != 0) {
1173-
break;
1174-
}
1175-
11761175
/* set r and s from signature */
11771176
if (mp_read_unsigned_bin(r, sig, (word32)qSz) != MP_OKAY ||
11781177
mp_read_unsigned_bin(s, sig + qSz, (word32)qSz) != MP_OKAY) {

0 commit comments

Comments
 (0)