@@ -209,6 +209,151 @@ static int sakke_xor_in_v_oob_test(void)
209209}
210210#endif
211211
212+ #ifdef WOLFCRYPT_HAVE_SAKKE
213+ /* Verify sakke_hash_to_range produces the full RFC 6508 5.1 mask for
214+ * ssvSz=48 with SHA-256, and that the public APIs reject ssvSz=0. The
215+ * old broken offset math left ssv[16..31] never XORed; encapsulating
216+ * an all-zero ssv exposes the gap (those bytes stay zero under the
217+ * bug, become random mask material once fixed). */
218+ static int sakke_mask_correctness_test (void )
219+ {
220+ SakkeKey key ;
221+ WC_RNG rng ;
222+ byte id [] = "user@example.com" ;
223+ word16 ssvSz = 48 ;
224+ word16 ssvSzZero = 0 ;
225+ word16 ssvSzTooBig = 0xFFFF ; /* exceeds n for any supported curve */
226+ word16 authSz = 0 ;
227+ byte ssv [48 ];
228+ byte * auth = NULL ;
229+ ecc_point * rsk = NULL ;
230+ int ret ;
231+ int i ;
232+ int allZero = 1 ;
233+ int rc = 0 ;
234+
235+ if (wc_InitRng (& rng ) != 0 ) {
236+ printf ("sakke_correctness: SKIP (rng init)\n" );
237+ return 0 ;
238+ }
239+ if (wc_InitSakkeKey_ex (& key , 128 , ECC_SAKKE_1 , NULL , INVALID_DEVID ) != 0 ) {
240+ wc_FreeRng (& rng );
241+ printf ("sakke_correctness: SKIP (sakke key init)\n" );
242+ return 0 ;
243+ }
244+ if (wc_MakeSakkeKey (& key , & rng ) != 0 ) {
245+ wc_FreeSakkeKey (& key );
246+ wc_FreeRng (& rng );
247+ printf ("sakke_correctness: SKIP (sakke key gen)\n" );
248+ return 0 ;
249+ }
250+ if (wc_SetSakkeIdentity (& key , id , sizeof (id ) - 1 ) != 0 ) {
251+ wc_FreeSakkeKey (& key );
252+ wc_FreeRng (& rng );
253+ printf ("sakke_correctness: SKIP (set identity)\n" );
254+ return 0 ;
255+ }
256+
257+ ret = wc_MakeSakkeEncapsulatedSSV (& key , WC_HASH_TYPE_SHA256 , ssv , ssvSz ,
258+ NULL , & authSz );
259+ if (ret != WC_NO_ERR_TRACE (LENGTH_ONLY_E )) {
260+ printf ("sakke_correctness: SKIP (auth size query)\n" );
261+ goto cleanup ;
262+ }
263+ auth = (byte * )XMALLOC (authSz , NULL , DYNAMIC_TYPE_TMP_BUFFER );
264+ if (auth == NULL ) {
265+ printf ("sakke_correctness: SKIP (alloc)\n" );
266+ goto cleanup ;
267+ }
268+
269+ XMEMSET (ssv , 0 , ssvSz );
270+ ret = wc_MakeSakkeEncapsulatedSSV (& key , WC_HASH_TYPE_SHA256 , ssv , ssvSz ,
271+ auth , & authSz );
272+ if (ret != 0 ) {
273+ printf ("sakke_correctness: FAIL (encap ret=%d)\n" , ret );
274+ rc = -1 ;
275+ goto cleanup ;
276+ }
277+ for (i = 16 ; i < 32 ; i ++ ) {
278+ if (ssv [i ] != 0 ) { allZero = 0 ; break ; }
279+ }
280+ if (allZero ) {
281+ printf ("sakke_correctness: FAIL (ssv[16..31] not XORed)\n" );
282+ rc = -1 ;
283+ goto cleanup ;
284+ }
285+
286+ ret = wc_MakeSakkeEncapsulatedSSV (& key , WC_HASH_TYPE_SHA256 , ssv , ssvSzZero ,
287+ auth , & authSz );
288+ if (ret != WC_NO_ERR_TRACE (BAD_FUNC_ARG )) {
289+ printf ("sakke_correctness: FAIL (encap ssvSz=0 ret=%d)\n" , ret );
290+ rc = -1 ;
291+ goto cleanup ;
292+ }
293+ ret = wc_DeriveSakkeSSV (& key , WC_HASH_TYPE_SHA256 , ssv , ssvSzZero ,
294+ auth , authSz );
295+ if (ret != WC_NO_ERR_TRACE (BAD_FUNC_ARG )) {
296+ printf ("sakke_correctness: FAIL (derive ssvSz=0 ret=%d)\n" , ret );
297+ rc = -1 ;
298+ goto cleanup ;
299+ }
300+
301+ /* ssvSz > n on encap: reachable directly because encap doesn't
302+ * require RSK to be set. */
303+ ret = wc_MakeSakkeEncapsulatedSSV (& key , WC_HASH_TYPE_SHA256 , ssv ,
304+ ssvSzTooBig , auth , & authSz );
305+ if (ret != WC_NO_ERR_TRACE (BAD_FUNC_ARG )) {
306+ printf ("sakke_correctness: FAIL (encap ssvSz>n ret=%d)\n" , ret );
307+ rc = -1 ;
308+ goto cleanup ;
309+ }
310+
311+ /* ssvSz > n on derive: the check sits below the !rsk.set gate, so
312+ * we must populate RSK first or derive returns BAD_STATE_E and the
313+ * range check is never reached. Use this key as both KMS and
314+ * recipient. */
315+ rsk = wc_ecc_new_point ();
316+ if (rsk == NULL ) {
317+ printf ("sakke_correctness: SKIP (rsk alloc)\n" );
318+ goto cleanup ;
319+ }
320+ if (wc_MakeSakkeRsk (& key , id , sizeof (id ) - 1 , rsk ) != 0 ) {
321+ printf ("sakke_correctness: SKIP (make rsk)\n" );
322+ goto cleanup ;
323+ }
324+ if (wc_SetSakkeRsk (& key , rsk , NULL , 0 ) != 0 ) {
325+ printf ("sakke_correctness: SKIP (set rsk)\n" );
326+ goto cleanup ;
327+ }
328+ ret = wc_DeriveSakkeSSV (& key , WC_HASH_TYPE_SHA256 , ssv , ssvSzTooBig ,
329+ auth , authSz );
330+ if (ret != WC_NO_ERR_TRACE (BAD_FUNC_ARG )) {
331+ printf ("sakke_correctness: FAIL (derive ssvSz>n ret=%d)\n" , ret );
332+ rc = -1 ;
333+ goto cleanup ;
334+ }
335+
336+ printf ("sakke_correctness: PASS\n" );
337+
338+ cleanup :
339+ if (rsk != NULL ) {
340+ wc_ecc_del_point (rsk );
341+ }
342+ if (auth != NULL ) {
343+ XFREE (auth , NULL , DYNAMIC_TYPE_TMP_BUFFER );
344+ }
345+ wc_FreeSakkeKey (& key );
346+ wc_FreeRng (& rng );
347+ return rc ;
348+ }
349+ #else
350+ static int sakke_mask_correctness_test (void )
351+ {
352+ printf ("sakke_correctness: SKIP (WOLFCRYPT_HAVE_SAKKE not defined)\n" );
353+ return 0 ;
354+ }
355+ #endif
356+
212357int allTesting = 1 ;
213358int apiTesting = 1 ;
214359int myoptind = 0 ;
@@ -444,6 +589,11 @@ int unit_test(int argc, char** argv)
444589 fflush (stdout );
445590 goto exit ;
446591 }
592+ if (sakke_mask_correctness_test () != 0 ) {
593+ ret = -1 ;
594+ fflush (stdout );
595+ goto exit ;
596+ }
447597 fflush (stdout );
448598
449599 XMEMSET (& wc_args , 0 , sizeof (wc_args ));
0 commit comments