@@ -46,6 +46,23 @@ struct test_object_hash
46
46
47
47
test_object_hash () = delete ;
48
48
49
+ // Construct this hash test object by setting the result only.
50
+ // There is no message and there is no length available for
51
+ // this hash test object.
52
+
53
+ explicit test_object_hash (const std::string& str_result)
54
+ : my_result // LCOV_EXCL_LINE
55
+ {
56
+ [&str_result]()
57
+ {
58
+ const auto byte_data { detail::convert_hex_string_to_byte_container (str_result) };
59
+ return message_type (byte_data.cbegin (), byte_data.cend ());
60
+ }()
61
+ }
62
+ { }
63
+
64
+ // Construct this hash test object with all of message, length and result.
65
+
49
66
explicit test_object_hash (const std::string& str_data, const std::string& str_result)
50
67
: my_length { str_data.size () / static_cast <size_type>(UINT8_C (2 )) },
51
68
my_msg
@@ -61,7 +78,7 @@ struct test_object_hash
61
78
[&str_result]()
62
79
{
63
80
const auto byte_data { detail::convert_hex_string_to_byte_container (str_result) };
64
- return message_type (byte_data.cbegin (), byte_data.cend ());
81
+ return message_type (byte_data.cbegin (), byte_data.cend ());
65
82
}()
66
83
}
67
84
{ }
@@ -73,7 +90,7 @@ struct test_object_hash
73
90
74
91
using test_vector_container_type = std::deque<test_object_hash>;
75
92
76
- auto where_file (const std::string& test_vectors_filename) -> std::string
93
+ auto where_file_shabytesvectors (const std::string& test_vectors_filename) -> std::string
77
94
{
78
95
// Try to open the file in each of the known relative paths
79
96
// in order to find out where it is located.
@@ -159,10 +176,12 @@ auto parse_file_vectors(const std::string& test_vectors_filename, test_vector_co
159
176
{
160
177
bool result_parse_is_ok { false };
161
178
162
- const std::string test_vectors_filename_relative { where_file (test_vectors_filename) };
179
+ const std::string test_vectors_filename_relative { where_file_shabytesvectors (test_vectors_filename) };
163
180
164
181
const bool result_filename_plausible_is_ok { (!test_vectors_filename_relative.empty ()) };
165
182
183
+ BOOST_TEST (result_filename_plausible_is_ok);
184
+
166
185
if (result_filename_plausible_is_ok)
167
186
{
168
187
std::string str_message { };
@@ -232,6 +251,77 @@ auto parse_file_vectors(const std::string& test_vectors_filename, test_vector_co
232
251
}
233
252
}
234
253
254
+ BOOST_TEST (result_parse_is_ok);
255
+
256
+ return result_parse_is_ok;
257
+ }
258
+
259
+ auto parse_file_monte (const std::string& test_monte_filename, test_vector_container_type& test_vectors_to_get) -> bool
260
+ {
261
+ bool result_parse_is_ok { false };
262
+
263
+ const std::string test_vectors_filename_relative { where_file_shabytesvectors (test_monte_filename) };
264
+
265
+ const bool result_filename_plausible_is_ok { (!test_vectors_filename_relative.empty ()) };
266
+
267
+ BOOST_TEST (result_filename_plausible_is_ok);
268
+
269
+ if (result_filename_plausible_is_ok)
270
+ {
271
+ std::string str_result { };
272
+
273
+ // Read the file for creating the test cases.
274
+ std::ifstream in (test_vectors_filename_relative.c_str ());
275
+
276
+ const bool file_is_open = in.is_open ();
277
+
278
+ unsigned count { };
279
+
280
+ if (file_is_open)
281
+ {
282
+ result_parse_is_ok = true ;
283
+
284
+ std::string line { };
285
+ std::string result { };
286
+
287
+ while (getline (in, line))
288
+ {
289
+ const std::string::size_type pos_cnt = line.find (" COUNT =" , 0U );
290
+ const std::string::size_type pos_md = line.find (" MD =" , 0U );
291
+
292
+ const bool line_is_representation_is_cnt = (pos_cnt != std::string::npos);
293
+ const bool line_is_representation_is_md = (pos_md != std::string::npos);
294
+
295
+ // Get the next count.
296
+ if (line_is_representation_is_cnt)
297
+ {
298
+ const std::string str_cnt = line.substr (8U , line.length () - 8U );
299
+
300
+ const unsigned long count_from_file = std::strtoul (str_cnt.c_str (), nullptr , 10U );
301
+
302
+ count = static_cast <unsigned >(count_from_file);
303
+ }
304
+
305
+ // Get the next (expected) result.
306
+ if (line_is_representation_is_md)
307
+ {
308
+ result = line.substr (5U , line.length () - 5U );
309
+
310
+ // Add the new test object to v.
311
+ const test_object_hash test_obj (result);
312
+
313
+ test_vectors_to_get.push_back (test_obj);
314
+ }
315
+ }
316
+
317
+ in.close ();
318
+
319
+ result_parse_is_ok = ((!test_vectors_to_get.empty ()) && (count == 99U ) && result_parse_is_ok);
320
+ }
321
+ }
322
+
323
+ BOOST_TEST (result_parse_is_ok);
324
+
235
325
return result_parse_is_ok;
236
326
}
237
327
@@ -246,6 +336,8 @@ auto test_vectors_oneshot(const test_vector_container_type& test_vectors) -> boo
246
336
using local_hasher_type = HasherType;
247
337
using local_result_type = typename local_hasher_type::return_type;
248
338
339
+ BOOST_TEST ((!test_vectors.empty ()));
340
+
249
341
bool result_is_ok { true };
250
342
251
343
for (const auto & test_vector : test_vectors)
@@ -267,6 +359,9 @@ auto test_vectors_oneshot(const test_vector_container_type& test_vectors) -> boo
267
359
268
360
// Make pass 2 through the messages.
269
361
// Use the triple-combination of init/process/get-result functions.
362
+ // Even though this is not required in CAVS testing, it is
363
+ // done in order to ensure that the init() function properly
364
+ // puts the hasher-object into its initialized state.
270
365
271
366
this_hash.init ();
272
367
@@ -287,6 +382,95 @@ auto test_vectors_oneshot(const test_vector_container_type& test_vectors) -> boo
287
382
return result_is_ok;
288
383
}
289
384
385
+ template <typename HasherType>
386
+ auto test_vectors_monte (const nist::cavs::test_vector_container_type& test_vectors_monte, const std::vector<std::uint8_t >& seed_init) -> bool
387
+ {
388
+ using local_hasher_type = HasherType;
389
+ using local_result_type = typename local_hasher_type::return_type;
390
+
391
+ using local_array_type = local_result_type;
392
+
393
+ // Obtain the test-specific initial seed.
394
+ local_array_type Seed { };
395
+
396
+ const std::size_t
397
+ copy_len
398
+ {
399
+ (std::min)(static_cast <std::size_t >(Seed.size ()), static_cast <std::size_t >(seed_init.size ()))
400
+ };
401
+
402
+ std::copy
403
+ (
404
+ seed_init.cbegin (),
405
+ seed_init.cbegin () + static_cast <typename std::vector<std::uint8_t >::difference_type>(copy_len),
406
+ Seed.begin ()
407
+ );
408
+
409
+ bool result_is_ok { (!test_vectors_monte.empty ()) };
410
+
411
+ if (result_is_ok)
412
+ {
413
+ local_array_type MD[3U ] { { }, { }, { } };
414
+
415
+ local_array_type MDi { };
416
+ local_array_type MDj { };
417
+
418
+ constexpr local_array_type dummy_array { };
419
+
420
+ // See pseudocode on page 9 of "The Secure Hash Algorithm Validation System (SHAVS)".
421
+
422
+ for (std::size_t j { }; j < 100U ; ++j)
423
+ {
424
+ MD[0U ] = MD[1U ] = MD[2U ] = Seed;
425
+
426
+ for (std::size_t i { 3U } ; i < 1003U ; ++i)
427
+ {
428
+ using local_wide_array_type = boost::crypt::array<std::uint8_t , dummy_array.size () * 3U >;
429
+
430
+ std::vector<std::uint8_t > result_vector;
431
+
432
+ result_vector.reserve (dummy_array.size () * 3U );
433
+
434
+ result_vector.insert (result_vector.end (), MD[0U ].cbegin (), MD[0U ].cend ());
435
+ result_vector.insert (result_vector.end (), MD[1U ].cbegin (), MD[1U ].cend ());
436
+ result_vector.insert (result_vector.end (), MD[2U ].cbegin (), MD[2U ].cend ());
437
+
438
+ local_wide_array_type Mi { };
439
+
440
+ std::copy (result_vector.cbegin (), result_vector.cend (), Mi.begin ());
441
+
442
+ local_hasher_type this_hash { };
443
+
444
+ this_hash.init ();
445
+
446
+ this_hash.process_bytes (Mi.data (), Mi.size ());
447
+
448
+ MDi = this_hash.get_digest ();
449
+
450
+ MD[0U ] = MD[1U ];
451
+ MD[1U ] = MD[2U ];
452
+ MD[2U ] = MDi;
453
+ }
454
+
455
+ MDj = Seed = MDi;
456
+
457
+ const bool result_this_monte_step_is_ok =
458
+ std::equal
459
+ (
460
+ MDj.cbegin (),
461
+ MDj.cend (),
462
+ test_vectors_monte[j].my_result .cbegin ()
463
+ );
464
+
465
+ result_is_ok = (result_this_monte_step_is_ok && result_is_ok);
466
+
467
+ BOOST_TEST (result_this_monte_step_is_ok);
468
+ }
469
+ }
470
+
471
+ return result_is_ok;
472
+ }
473
+
290
474
} // namespace cavs
291
475
} // namespace nist
292
476
0 commit comments