本日重點:ht_sign、xmss_sign 和 KAT rng.c
ht_sign
的 input 有 SK.seed, PK.seed,這兩個都必須要透過 approved RBG 產生亂數,因為還沒有把 CC310/CC312 整合進來,同時也因為簽章後會使用 Known Answer Tests (KAT) 比對簽章結果,所以乾脆就先用 KAT 的 rng.c
取代目前取亂數的function。
NIST 會提供 KAT,壓縮檔包括 rng.c
換成 KAT 的 rng.c 之後,compile 的時候發現他依賴 openssl
這樣我在 nrf52840 就沒辦法用 KAT rng.c,雖然我還是能在 x86 上跑,但我不想要這樣的結果,我還是希望 nrf52840 和 nRF5340 都能用 KAT rng.c,所以我把 openssl 的依賴換掉,因此我要提供一份 AES256_ECB
的 source code。
除此之外,要在 KAT rng.c 裡把兩個 function (handleErrors
和 AES256_ECB
) 予以 comment。
這裡我直接讓 chatGPT 產生 AES256_ECB
的 source code,畢竟這是用於 KAT,未來也會走 approved RBG,所以不在這裡花太多時間重造輪子。
AES256_ECB
的 implementation 我放在 kat 之下,然後修改 Makefile
# Only use KAT rng.c when make KAT_RNG=1
ifeq ($(KAT_RNG),1)
RNG_SRC := kat/rng.c kat/kat_rng.c kat/aes256.c
else
RNG_SRC := $(PLATFORM)/rng.c
endif
make KAT_RNG=1
就是用 KAT 的 rng.c
相關原始碼參考 連結
ci.yml 也要改,暫時把 x86、nrf52840 和 nRF5340 都用 KAT_RNG=1
jobs:
build-and-test:
...
steps:
...
- name: Build x86, then run
run: |
make TARGET=x86 KAT_RNG=1
- name: Build nrf52840
run: |
make TARGET=nrf52840 NRFXLIB_DIR="${NRFXLIB_DIR}" KAT_RNG=1
- name: Build nRF5340 DK
run: |
make TARGET=nrf5340dk NRFXLIB_DIR="${NRFXLIB_DIR}" KAT_RNG=1
然後,GitHub Actions 能看到取亂數的結果。由於 x86、nrf52840 和 nRF5340 的 rng_bytes 都是一個空的 implementation,所以能取得亂數就表示目前是用 KAT rng.c
再看一次 ht_sign
和 xmss_node
的演算法
xmss_sign
的 line 2 就是 idx 除以 (2^j),然後取整數,最後 XOR 1
,就是 (idx >> j) ^ 1u,所以xmss_sign
的程式大概是這樣 (在 SLH-DSA-SHA2-128s 的參數集,h' = 9)
void xmss_sign(uint8_t out[704],
const uint8_t M[16],
const uint8_t sk_seed[16],
unsigned int idx,
const uint8_t pk_seed[16],
const uint8_t adrs[32])
{
// h` = 9
uint8_t auth[9][SPX_N];
for(int j = 0; j < 9; ++j)
{
unsigned int k = (idx >> j) ^ 1u;
xmss_node(auth+j, sk_seed, k, j, pk_seed, adrs);
}
set_type_and_clear(adrs, WOTS_HASH);
set_key_pair_addr(adrs, idx);
// size of sig is len * n bytes
// len = 35, for SLH-DSA-SHA2-128s
wots_sign(out, M, sk_seed, pk_seed, adrs);
// out ← WOTS+ signature ∥ AUTH
memcpy(out + 35, (uint8_t *)auth[0][0], sizeof(auth));
}
memcpy(out + 35, ...
這裡的 35 是這樣算出來的,參考 FIPS 第 17 頁
len = len1 + len2 = 32 + 3 = 35
ht_sign
是在 slh_sign_internal
裡被呼叫,我想準備一組input來測 ht_sign
,所以我們再一次的來看 slh_sign_internal
會傳什麼給 ht_sign
algorithm 19 的 line 3 (PRF_msg
) 和 line 5 (H_msg
),這兩個 function 的定義在第 45、46 頁
PRF_msg
和 H_msg
的產出最終會成為 ht_sign
的最後兩個參數 idx_tree、idx_leaf,其中會用到 HMAC-SHA-256、MGF1-SHA-256 的計算,HMAC-SHA-256、MGF1-SHA-256我們明天再說。