@@ -362,12 +362,14 @@ index d4c22b4..4bd8609 100644
362362 void reed_muller_encode(uint64_t* cdw, const uint64_t* msg);
363363 void reed_muller_decode(uint64_t* msg, const uint64_t* cdw);
364364diff --git a/src/common/symmetric.c b/src/common/symmetric.c
365- index b963673..5169d9e 100644
365+ index b963673..d0a8c23 100644
366366--- a/src/common/symmetric.c
367367+++ b/src/common/symmetric.c
368- @@ -7,12 +7,26 @@
368+ @@ -6,13 +6,28 @@
369+
369370 #include "symmetric.h"
370371 #include <stdint.h>
372+ + #include <string.h>
371373
372374+ #ifdef USE_OQS_RANDOMBYTES
373375+ #include <oqs/rand.h>
@@ -393,7 +395,7 @@ index b963673..5169d9e 100644
393395
394396 /**
395397 * @brief SHAKE-256 with incremental API and domain separation
396- @@ -26,11 +40 ,11 @@ shake256incctx shake256_prng_ctx;
398+ @@ -26,11 +41 ,11 @@ shake256incctx shake256_prng_ctx;
397399 */
398400 void prng_init(uint8_t *entropy_input, uint8_t *personalization_string, uint32_t enlen, uint32_t perlen) {
399401 uint8_t domain = HQC_PRNG_DOMAIN;
@@ -410,7 +412,7 @@ index b963673..5169d9e 100644
410412 }
411413
412414 /**
413- @@ -42,8 +56 ,9 @@ void prng_init(uint8_t *entropy_input, uint8_t *personalization_string, uint32_t
415+ @@ -42,8 +57 ,9 @@ void prng_init(uint8_t *entropy_input, uint8_t *personalization_string, uint32_t
414416 * @param[in] outlen length of output in bytes
415417 */
416418 void prng_get_bytes(uint8_t *output, uint32_t outlen) {
@@ -421,7 +423,7 @@ index b963673..5169d9e 100644
421423
422424 /**
423425 * @brief Initializes a SHAKE256 XOF context with a given seed.
424- @@ -54,10 +69 ,10 @@ void prng_get_bytes(uint8_t *output, uint32_t outlen) {
426+ @@ -54,10 +70 ,10 @@ void prng_get_bytes(uint8_t *output, uint32_t outlen) {
425427 */
426428 void xof_init(shake256_xof_ctx *xof_ctx, const uint8_t *seed, uint32_t seed_size) {
427429 uint8_t xof_domain = HQC_XOF_DOMAIN;
@@ -436,7 +438,7 @@ index b963673..5169d9e 100644
436438 }
437439
438440 /**
439- @@ -72,7 +87 ,14 @@ void xof_init(shake256_xof_ctx *xof_ctx, const uint8_t *seed, uint32_t seed_size
441+ @@ -72,7 +88 ,14 @@ void xof_init(shake256_xof_ctx *xof_ctx, const uint8_t *seed, uint32_t seed_size
440442 * The context must have been initialized beforehand using `xof_init()`.
441443 */
442444 void xof_get_bytes(shake256_xof_ctx *xof_ctx, uint8_t *output, uint32_t output_size) {
@@ -452,7 +454,7 @@ index b963673..5169d9e 100644
452454 }
453455
454456 /**
455- @@ -87,10 +109 ,11 @@ void xof_get_bytes(shake256_xof_ctx *xof_ctx, uint8_t *output, uint32_t output_s
457+ @@ -87,10 +110 ,11 @@ void xof_get_bytes(shake256_xof_ctx *xof_ctx, uint8_t *output, uint32_t output_s
456458 void hash_i(uint8_t *output, const uint8_t *seed) {
457459 sha3_512_ctx i_hash_ctx = {0};
458460 uint8_t i_domain = HQC_I_FCT_DOMAIN;
@@ -468,7 +470,7 @@ index b963673..5169d9e 100644
468470 }
469471
470472 /**
471- @@ -102,10 +125 ,11 @@ void hash_i(uint8_t *output, const uint8_t *seed) {
473+ @@ -102,10 +126 ,11 @@ void hash_i(uint8_t *output, const uint8_t *seed) {
472474 void hash_h(uint8_t *output, const uint8_t ek_kem[PUBLIC_KEY_BYTES]) {
473475 sha3_256_ctx h_hash_ctx = {0};
474476 uint8_t h_domain = HQC_H_FCT_DOMAIN;
@@ -484,27 +486,44 @@ index b963673..5169d9e 100644
484486 }
485487
486488 /**
487- @@ -120,12 +144,13 @@ void hash_g(uint8_t *output, const uint8_t hash_ek_kem[SEED_BYTES], const uint8_
489+ @@ -118,14 +143,29 @@ void hash_h(uint8_t *output, const uint8_t ek_kem[PUBLIC_KEY_BYTES]) {
490+ */
491+ void hash_g(uint8_t *output, const uint8_t hash_ek_kem[SEED_BYTES], const uint8_t m[PARAM_SECURITY_BYTES],
488492 const uint8_t salt[SALT_BYTES]) {
489- sha3_512_ctx g_hash_ctx = {0};
493+ - sha3_512_ctx g_hash_ctx = {0};
494+ + /* TODO: For liboqs integration, hash_g implementation has been modified
495+ + * There are some unexpected dispatch errors under liboqs/src/common/sha3
496+ + * that causes intermittent GitHub Action test failures. Due to the
497+ + * difficulty of debugging on GitHub action, I chose this shortcut of
498+ + * replacing incremental API with a single hash over a continuous strip of
499+ + * memory. There might be performance and stack memory usage penalty
500+ + * associated with this approach, but I deemed it acceptable.
501+ + *
502+ + * FIX: we need to eventually figure out what happened with Keccak dispatch
503+ + * and restore the usage of incremental API
504+ + */
490505 uint8_t i_domain = HQC_G_FCT_DOMAIN;
491506- sha3_512_inc_init(&g_hash_ctx);
492507- sha3_512_inc_absorb(&g_hash_ctx, hash_ek_kem, SEED_BYTES);
493508- sha3_512_inc_absorb(&g_hash_ctx, m, PARAM_SECURITY_BYTES);
494509- sha3_512_inc_absorb(&g_hash_ctx, salt, SALT_BYTES);
495510- sha3_512_inc_absorb(&g_hash_ctx, &i_domain, 1);
496511- sha3_512_inc_finalize(output, &g_hash_ctx);
497- + OQS_SHA3_sha3_512_inc_init(&g_hash_ctx);
498- + OQS_SHA3_sha3_512_inc_absorb(&g_hash_ctx, hash_ek_kem, SEED_BYTES);
499- + OQS_SHA3_sha3_512_inc_absorb(&g_hash_ctx, m, PARAM_SECURITY_BYTES);
500- + OQS_SHA3_sha3_512_inc_absorb(&g_hash_ctx, salt, SALT_BYTES);
501- + OQS_SHA3_sha3_512_inc_absorb(&g_hash_ctx, &i_domain, 1);
502- + OQS_SHA3_sha3_512_inc_finalize(output, &g_hash_ctx);
503- + OQS_SHA3_sha3_512_inc_ctx_release(&g_hash_ctx);
512+ + uint8_t input[SEED_BYTES + PARAM_SECURITY_BYTES + SALT_BYTES + 1];
513+ + size_t offset = 0;
514+ + memcpy(input + offset, hash_ek_kem, SEED_BYTES);
515+ + offset += SEED_BYTES;
516+ + memcpy(input + offset, m, PARAM_SECURITY_BYTES);
517+ + offset += PARAM_SECURITY_BYTES;
518+ + memcpy(input + offset, salt, SALT_BYTES);
519+ + offset += SALT_BYTES;
520+ + memcpy(input + offset, &i_domain, 1);
521+ +
522+ + OQS_SHA3_sha3_512(output, input, sizeof(input));
504523 }
505524
506525 /**
507- @@ -140,12 +165 ,13 @@ void hash_j(uint8_t *output, const uint8_t hash_ek_kem[SEED_BYTES], const uint8_
526+ @@ -140,12 +180 ,13 @@ void hash_j(uint8_t *output, const uint8_t hash_ek_kem[SEED_BYTES], const uint8_
508527 const ciphertext_kem_t *c_kem) {
509528 sha3_256_ctx k_hash_ctx = {0};
510529 uint8_t k_domain = HQC_J_FCT_DOMAIN;
0 commit comments