mirror of
https://github.com/open-quantum-safe/liboqs.git
synced 2025-11-29 00:03:48 -05:00
Add SPHINCS+ SHA-256 variants
This commit is contained in:
parent
1e6ad568fd
commit
6bf57f89c9
@ -159,6 +159,42 @@ EXPORTS
|
||||
OQS_SIG_sphincs_haraka_256s_simple_keypair
|
||||
OQS_SIG_sphincs_haraka_256s_simple_sign
|
||||
OQS_SIG_sphincs_haraka_256s_simple_verify
|
||||
OQS_SIG_sphincs_sha256_128f_robust_keypair
|
||||
OQS_SIG_sphincs_sha256_128f_robust_sign
|
||||
OQS_SIG_sphincs_sha256_128f_robust_verify
|
||||
OQS_SIG_sphincs_sha256_128f_simple_keypair
|
||||
OQS_SIG_sphincs_sha256_128f_simple_sign
|
||||
OQS_SIG_sphincs_sha256_128f_simple_verify
|
||||
OQS_SIG_sphincs_sha256_128s_robust_keypair
|
||||
OQS_SIG_sphincs_sha256_128s_robust_sign
|
||||
OQS_SIG_sphincs_sha256_128s_robust_verify
|
||||
OQS_SIG_sphincs_sha256_128s_simple_keypair
|
||||
OQS_SIG_sphincs_sha256_128s_simple_sign
|
||||
OQS_SIG_sphincs_sha256_128s_simple_verify
|
||||
OQS_SIG_sphincs_sha256_192f_robust_keypair
|
||||
OQS_SIG_sphincs_sha256_192f_robust_sign
|
||||
OQS_SIG_sphincs_sha256_192f_robust_verify
|
||||
OQS_SIG_sphincs_sha256_192f_simple_keypair
|
||||
OQS_SIG_sphincs_sha256_192f_simple_sign
|
||||
OQS_SIG_sphincs_sha256_192f_simple_verify
|
||||
OQS_SIG_sphincs_sha256_192s_robust_keypair
|
||||
OQS_SIG_sphincs_sha256_192s_robust_sign
|
||||
OQS_SIG_sphincs_sha256_192s_robust_verify
|
||||
OQS_SIG_sphincs_sha256_192s_simple_keypair
|
||||
OQS_SIG_sphincs_sha256_192s_simple_sign
|
||||
OQS_SIG_sphincs_sha256_192s_simple_verify
|
||||
OQS_SIG_sphincs_sha256_256f_robust_keypair
|
||||
OQS_SIG_sphincs_sha256_256f_robust_sign
|
||||
OQS_SIG_sphincs_sha256_256f_robust_verify
|
||||
OQS_SIG_sphincs_sha256_256f_simple_keypair
|
||||
OQS_SIG_sphincs_sha256_256f_simple_sign
|
||||
OQS_SIG_sphincs_sha256_256f_simple_verify
|
||||
OQS_SIG_sphincs_sha256_256s_robust_keypair
|
||||
OQS_SIG_sphincs_sha256_256s_robust_sign
|
||||
OQS_SIG_sphincs_sha256_256s_robust_verify
|
||||
OQS_SIG_sphincs_sha256_256s_simple_keypair
|
||||
OQS_SIG_sphincs_sha256_256s_simple_sign
|
||||
OQS_SIG_sphincs_sha256_256s_simple_verify
|
||||
OQS_SIG_sphincs_shake256_128f_robust_keypair
|
||||
OQS_SIG_sphincs_shake256_128f_robust_sign
|
||||
OQS_SIG_sphincs_shake256_128f_robust_verify
|
||||
|
||||
@ -356,6 +356,114 @@
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-haraka-256s-simple_clean\hash_haraka.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-haraka-256s-simple_clean\thash_haraka_simple.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-haraka-256s-simple_clean\haraka.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\sig_sphincs_sha256_128f_robust.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-128f-robust_clean\address.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-128f-robust_clean\wots.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-128f-robust_clean\utils.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-128f-robust_clean\fors.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-128f-robust_clean\sign.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-128f-robust_clean\hash_sha256.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-128f-robust_clean\thash_sha256_robust.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-128f-robust_clean\sha256.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\sig_sphincs_sha256_128f_simple.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-128f-simple_clean\address.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-128f-simple_clean\wots.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-128f-simple_clean\utils.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-128f-simple_clean\fors.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-128f-simple_clean\sign.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-128f-simple_clean\hash_sha256.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-128f-simple_clean\thash_sha256_simple.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-128f-simple_clean\sha256.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\sig_sphincs_sha256_128s_robust.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-128s-robust_clean\address.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-128s-robust_clean\wots.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-128s-robust_clean\utils.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-128s-robust_clean\fors.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-128s-robust_clean\sign.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-128s-robust_clean\hash_sha256.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-128s-robust_clean\thash_sha256_robust.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-128s-robust_clean\sha256.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\sig_sphincs_sha256_128s_simple.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-128s-simple_clean\address.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-128s-simple_clean\wots.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-128s-simple_clean\utils.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-128s-simple_clean\fors.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-128s-simple_clean\sign.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-128s-simple_clean\hash_sha256.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-128s-simple_clean\thash_sha256_simple.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-128s-simple_clean\sha256.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\sig_sphincs_sha256_192f_robust.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-192f-robust_clean\address.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-192f-robust_clean\wots.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-192f-robust_clean\utils.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-192f-robust_clean\fors.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-192f-robust_clean\sign.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-192f-robust_clean\hash_sha256.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-192f-robust_clean\thash_sha256_robust.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-192f-robust_clean\sha256.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\sig_sphincs_sha256_192f_simple.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-192f-simple_clean\address.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-192f-simple_clean\wots.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-192f-simple_clean\utils.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-192f-simple_clean\fors.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-192f-simple_clean\sign.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-192f-simple_clean\hash_sha256.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-192f-simple_clean\thash_sha256_simple.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-192f-simple_clean\sha256.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\sig_sphincs_sha256_192s_robust.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-192s-robust_clean\address.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-192s-robust_clean\wots.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-192s-robust_clean\utils.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-192s-robust_clean\fors.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-192s-robust_clean\sign.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-192s-robust_clean\hash_sha256.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-192s-robust_clean\thash_sha256_robust.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-192s-robust_clean\sha256.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\sig_sphincs_sha256_192s_simple.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-192s-simple_clean\address.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-192s-simple_clean\wots.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-192s-simple_clean\utils.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-192s-simple_clean\fors.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-192s-simple_clean\sign.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-192s-simple_clean\hash_sha256.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-192s-simple_clean\thash_sha256_simple.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-192s-simple_clean\sha256.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\sig_sphincs_sha256_256f_robust.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-256f-robust_clean\address.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-256f-robust_clean\wots.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-256f-robust_clean\utils.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-256f-robust_clean\fors.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-256f-robust_clean\sign.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-256f-robust_clean\hash_sha256.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-256f-robust_clean\thash_sha256_robust.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-256f-robust_clean\sha256.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\sig_sphincs_sha256_256f_simple.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-256f-simple_clean\address.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-256f-simple_clean\wots.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-256f-simple_clean\utils.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-256f-simple_clean\fors.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-256f-simple_clean\sign.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-256f-simple_clean\hash_sha256.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-256f-simple_clean\thash_sha256_simple.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-256f-simple_clean\sha256.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\sig_sphincs_sha256_256s_robust.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-256s-robust_clean\address.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-256s-robust_clean\wots.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-256s-robust_clean\utils.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-256s-robust_clean\fors.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-256s-robust_clean\sign.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-256s-robust_clean\hash_sha256.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-256s-robust_clean\thash_sha256_robust.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-256s-robust_clean\sha256.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\sig_sphincs_sha256_256s_simple.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-256s-simple_clean\address.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-256s-simple_clean\wots.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-256s-simple_clean\utils.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-256s-simple_clean\fors.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-256s-simple_clean\sign.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-256s-simple_clean\hash_sha256.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-256s-simple_clean\thash_sha256_simple.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-256s-simple_clean\sha256.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\sig_sphincs_shake256_128f_robust.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-shake256-128f-robust_clean\address.c" />
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-shake256-128f-robust_clean\wots.c" />
|
||||
|
||||
@ -767,6 +767,330 @@
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-haraka-256s-simple_clean\haraka.c">
|
||||
<Filter>sphincs\haraka_256s_simple</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\sig_sphincs_sha256_128f_robust.c">
|
||||
<Filter>sphincs\sha256_128f_robust</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-128f-robust_clean\address.c">
|
||||
<Filter>sphincs\sha256_128f_robust</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-128f-robust_clean\wots.c">
|
||||
<Filter>sphincs\sha256_128f_robust</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-128f-robust_clean\utils.c">
|
||||
<Filter>sphincs\sha256_128f_robust</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-128f-robust_clean\fors.c">
|
||||
<Filter>sphincs\sha256_128f_robust</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-128f-robust_clean\sign.c">
|
||||
<Filter>sphincs\sha256_128f_robust</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-128f-robust_clean\hash_sha256.c">
|
||||
<Filter>sphincs\sha256_128f_robust</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-128f-robust_clean\thash_sha256_robust.c">
|
||||
<Filter>sphincs\sha256_128f_robust</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-128f-robust_clean\sha256.c">
|
||||
<Filter>sphincs\sha256_128f_robust</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\sig_sphincs_sha256_128f_simple.c">
|
||||
<Filter>sphincs\sha256_128f_simple</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-128f-simple_clean\address.c">
|
||||
<Filter>sphincs\sha256_128f_simple</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-128f-simple_clean\wots.c">
|
||||
<Filter>sphincs\sha256_128f_simple</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-128f-simple_clean\utils.c">
|
||||
<Filter>sphincs\sha256_128f_simple</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-128f-simple_clean\fors.c">
|
||||
<Filter>sphincs\sha256_128f_simple</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-128f-simple_clean\sign.c">
|
||||
<Filter>sphincs\sha256_128f_simple</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-128f-simple_clean\hash_sha256.c">
|
||||
<Filter>sphincs\sha256_128f_simple</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-128f-simple_clean\thash_sha256_simple.c">
|
||||
<Filter>sphincs\sha256_128f_simple</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-128f-simple_clean\sha256.c">
|
||||
<Filter>sphincs\sha256_128f_simple</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\sig_sphincs_sha256_128s_robust.c">
|
||||
<Filter>sphincs\sha256_128s_robust</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-128s-robust_clean\address.c">
|
||||
<Filter>sphincs\sha256_128s_robust</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-128s-robust_clean\wots.c">
|
||||
<Filter>sphincs\sha256_128s_robust</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-128s-robust_clean\utils.c">
|
||||
<Filter>sphincs\sha256_128s_robust</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-128s-robust_clean\fors.c">
|
||||
<Filter>sphincs\sha256_128s_robust</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-128s-robust_clean\sign.c">
|
||||
<Filter>sphincs\sha256_128s_robust</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-128s-robust_clean\hash_sha256.c">
|
||||
<Filter>sphincs\sha256_128s_robust</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-128s-robust_clean\thash_sha256_robust.c">
|
||||
<Filter>sphincs\sha256_128s_robust</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-128s-robust_clean\sha256.c">
|
||||
<Filter>sphincs\sha256_128s_robust</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\sig_sphincs_sha256_128s_simple.c">
|
||||
<Filter>sphincs\sha256_128s_simple</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-128s-simple_clean\address.c">
|
||||
<Filter>sphincs\sha256_128s_simple</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-128s-simple_clean\wots.c">
|
||||
<Filter>sphincs\sha256_128s_simple</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-128s-simple_clean\utils.c">
|
||||
<Filter>sphincs\sha256_128s_simple</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-128s-simple_clean\fors.c">
|
||||
<Filter>sphincs\sha256_128s_simple</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-128s-simple_clean\sign.c">
|
||||
<Filter>sphincs\sha256_128s_simple</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-128s-simple_clean\hash_sha256.c">
|
||||
<Filter>sphincs\sha256_128s_simple</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-128s-simple_clean\thash_sha256_simple.c">
|
||||
<Filter>sphincs\sha256_128s_simple</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-128s-simple_clean\sha256.c">
|
||||
<Filter>sphincs\sha256_128s_simple</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\sig_sphincs_sha256_192f_robust.c">
|
||||
<Filter>sphincs\sha256_192f_robust</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-192f-robust_clean\address.c">
|
||||
<Filter>sphincs\sha256_192f_robust</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-192f-robust_clean\wots.c">
|
||||
<Filter>sphincs\sha256_192f_robust</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-192f-robust_clean\utils.c">
|
||||
<Filter>sphincs\sha256_192f_robust</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-192f-robust_clean\fors.c">
|
||||
<Filter>sphincs\sha256_192f_robust</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-192f-robust_clean\sign.c">
|
||||
<Filter>sphincs\sha256_192f_robust</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-192f-robust_clean\hash_sha256.c">
|
||||
<Filter>sphincs\sha256_192f_robust</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-192f-robust_clean\thash_sha256_robust.c">
|
||||
<Filter>sphincs\sha256_192f_robust</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-192f-robust_clean\sha256.c">
|
||||
<Filter>sphincs\sha256_192f_robust</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\sig_sphincs_sha256_192f_simple.c">
|
||||
<Filter>sphincs\sha256_192f_simple</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-192f-simple_clean\address.c">
|
||||
<Filter>sphincs\sha256_192f_simple</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-192f-simple_clean\wots.c">
|
||||
<Filter>sphincs\sha256_192f_simple</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-192f-simple_clean\utils.c">
|
||||
<Filter>sphincs\sha256_192f_simple</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-192f-simple_clean\fors.c">
|
||||
<Filter>sphincs\sha256_192f_simple</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-192f-simple_clean\sign.c">
|
||||
<Filter>sphincs\sha256_192f_simple</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-192f-simple_clean\hash_sha256.c">
|
||||
<Filter>sphincs\sha256_192f_simple</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-192f-simple_clean\thash_sha256_simple.c">
|
||||
<Filter>sphincs\sha256_192f_simple</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-192f-simple_clean\sha256.c">
|
||||
<Filter>sphincs\sha256_192f_simple</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\sig_sphincs_sha256_192s_robust.c">
|
||||
<Filter>sphincs\sha256_192s_robust</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-192s-robust_clean\address.c">
|
||||
<Filter>sphincs\sha256_192s_robust</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-192s-robust_clean\wots.c">
|
||||
<Filter>sphincs\sha256_192s_robust</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-192s-robust_clean\utils.c">
|
||||
<Filter>sphincs\sha256_192s_robust</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-192s-robust_clean\fors.c">
|
||||
<Filter>sphincs\sha256_192s_robust</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-192s-robust_clean\sign.c">
|
||||
<Filter>sphincs\sha256_192s_robust</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-192s-robust_clean\hash_sha256.c">
|
||||
<Filter>sphincs\sha256_192s_robust</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-192s-robust_clean\thash_sha256_robust.c">
|
||||
<Filter>sphincs\sha256_192s_robust</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-192s-robust_clean\sha256.c">
|
||||
<Filter>sphincs\sha256_192s_robust</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\sig_sphincs_sha256_192s_simple.c">
|
||||
<Filter>sphincs\sha256_192s_simple</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-192s-simple_clean\address.c">
|
||||
<Filter>sphincs\sha256_192s_simple</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-192s-simple_clean\wots.c">
|
||||
<Filter>sphincs\sha256_192s_simple</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-192s-simple_clean\utils.c">
|
||||
<Filter>sphincs\sha256_192s_simple</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-192s-simple_clean\fors.c">
|
||||
<Filter>sphincs\sha256_192s_simple</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-192s-simple_clean\sign.c">
|
||||
<Filter>sphincs\sha256_192s_simple</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-192s-simple_clean\hash_sha256.c">
|
||||
<Filter>sphincs\sha256_192s_simple</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-192s-simple_clean\thash_sha256_simple.c">
|
||||
<Filter>sphincs\sha256_192s_simple</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-192s-simple_clean\sha256.c">
|
||||
<Filter>sphincs\sha256_192s_simple</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\sig_sphincs_sha256_256f_robust.c">
|
||||
<Filter>sphincs\sha256_256f_robust</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-256f-robust_clean\address.c">
|
||||
<Filter>sphincs\sha256_256f_robust</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-256f-robust_clean\wots.c">
|
||||
<Filter>sphincs\sha256_256f_robust</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-256f-robust_clean\utils.c">
|
||||
<Filter>sphincs\sha256_256f_robust</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-256f-robust_clean\fors.c">
|
||||
<Filter>sphincs\sha256_256f_robust</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-256f-robust_clean\sign.c">
|
||||
<Filter>sphincs\sha256_256f_robust</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-256f-robust_clean\hash_sha256.c">
|
||||
<Filter>sphincs\sha256_256f_robust</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-256f-robust_clean\thash_sha256_robust.c">
|
||||
<Filter>sphincs\sha256_256f_robust</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-256f-robust_clean\sha256.c">
|
||||
<Filter>sphincs\sha256_256f_robust</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\sig_sphincs_sha256_256f_simple.c">
|
||||
<Filter>sphincs\sha256_256f_simple</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-256f-simple_clean\address.c">
|
||||
<Filter>sphincs\sha256_256f_simple</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-256f-simple_clean\wots.c">
|
||||
<Filter>sphincs\sha256_256f_simple</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-256f-simple_clean\utils.c">
|
||||
<Filter>sphincs\sha256_256f_simple</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-256f-simple_clean\fors.c">
|
||||
<Filter>sphincs\sha256_256f_simple</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-256f-simple_clean\sign.c">
|
||||
<Filter>sphincs\sha256_256f_simple</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-256f-simple_clean\hash_sha256.c">
|
||||
<Filter>sphincs\sha256_256f_simple</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-256f-simple_clean\thash_sha256_simple.c">
|
||||
<Filter>sphincs\sha256_256f_simple</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-256f-simple_clean\sha256.c">
|
||||
<Filter>sphincs\sha256_256f_simple</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\sig_sphincs_sha256_256s_robust.c">
|
||||
<Filter>sphincs\sha256_256s_robust</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-256s-robust_clean\address.c">
|
||||
<Filter>sphincs\sha256_256s_robust</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-256s-robust_clean\wots.c">
|
||||
<Filter>sphincs\sha256_256s_robust</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-256s-robust_clean\utils.c">
|
||||
<Filter>sphincs\sha256_256s_robust</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-256s-robust_clean\fors.c">
|
||||
<Filter>sphincs\sha256_256s_robust</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-256s-robust_clean\sign.c">
|
||||
<Filter>sphincs\sha256_256s_robust</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-256s-robust_clean\hash_sha256.c">
|
||||
<Filter>sphincs\sha256_256s_robust</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-256s-robust_clean\thash_sha256_robust.c">
|
||||
<Filter>sphincs\sha256_256s_robust</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-256s-robust_clean\sha256.c">
|
||||
<Filter>sphincs\sha256_256s_robust</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\sig_sphincs_sha256_256s_simple.c">
|
||||
<Filter>sphincs\sha256_256s_simple</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-256s-simple_clean\address.c">
|
||||
<Filter>sphincs\sha256_256s_simple</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-256s-simple_clean\wots.c">
|
||||
<Filter>sphincs\sha256_256s_simple</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-256s-simple_clean\utils.c">
|
||||
<Filter>sphincs\sha256_256s_simple</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-256s-simple_clean\fors.c">
|
||||
<Filter>sphincs\sha256_256s_simple</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-256s-simple_clean\sign.c">
|
||||
<Filter>sphincs\sha256_256s_simple</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-256s-simple_clean\hash_sha256.c">
|
||||
<Filter>sphincs\sha256_256s_simple</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-256s-simple_clean\thash_sha256_simple.c">
|
||||
<Filter>sphincs\sha256_256s_simple</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\pqclean_sphincs-sha256-256s-simple_clean\sha256.c">
|
||||
<Filter>sphincs\sha256_256s_simple</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sig\sphincs\sig_sphincs_shake256_128f_robust.c">
|
||||
<Filter>sphincs\shake256_128f_robust</Filter>
|
||||
</ClCompile>
|
||||
@ -1500,6 +1824,42 @@
|
||||
<Filter Include="sphincs\haraka_256s_simple">
|
||||
<UniqueIdentifier>{40b4c623-511f-4235-be9b-9ff675457fe5}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="sphincs\sha256_128f_robust">
|
||||
<UniqueIdentifier>{f569c3b0-c6ba-4157-a858-a5fc52d51515}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="sphincs\sha256_128f_simple">
|
||||
<UniqueIdentifier>{1be5ba25-e61c-4218-a949-129b3422d6d8}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="sphincs\sha256_128s_robust">
|
||||
<UniqueIdentifier>{c2b7b42f-bebf-4a92-8f97-e12740a2f287}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="sphincs\sha256_128s_simple">
|
||||
<UniqueIdentifier>{b380048d-601c-46d6-acb8-591a2c4e1854}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="sphincs\sha256_192f_robust">
|
||||
<UniqueIdentifier>{639a3ad2-1d05-445a-b9ea-9112fe8a6e7d}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="sphincs\sha256_192f_simple">
|
||||
<UniqueIdentifier>{eea572d4-7c0a-4d63-bd4d-5d038223a922}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="sphincs\sha256_192s_robust">
|
||||
<UniqueIdentifier>{1972ed56-876a-4eca-aadd-91886adfe290}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="sphincs\sha256_192s_simple">
|
||||
<UniqueIdentifier>{10d0a3dd-b2b8-4e74-b59c-dc94ea84b7c1}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="sphincs\sha256_256f_robust">
|
||||
<UniqueIdentifier>{945476fd-8435-4df8-9b4b-c04e74aa6d03}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="sphincs\sha256_256f_simple">
|
||||
<UniqueIdentifier>{d70d780f-3ff0-4146-a6ce-8801bc157f83}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="sphincs\sha256_256s_robust">
|
||||
<UniqueIdentifier>{fd789855-13bb-40e9-a09f-9086dd62ab93}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="sphincs\sha256_256s_simple">
|
||||
<UniqueIdentifier>{4823fa89-43de-45b0-ac13-3de5345ce48b}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="sphincs\shake256_128f_robust">
|
||||
<UniqueIdentifier>{cf170e69-4718-4efd-a7ba-2388a826193c}</UniqueIdentifier>
|
||||
</Filter>
|
||||
|
||||
@ -57,6 +57,18 @@
|
||||
#define OQS_ENABLE_SIG_sphincs_haraka_256f_simple
|
||||
#define OQS_ENABLE_SIG_sphincs_haraka_256s_robust
|
||||
#define OQS_ENABLE_SIG_sphincs_haraka_256s_simple
|
||||
#define OQS_ENABLE_SIG_sphincs_sha256_128f_robust
|
||||
#define OQS_ENABLE_SIG_sphincs_sha256_128f_simple
|
||||
#define OQS_ENABLE_SIG_sphincs_sha256_128s_robust
|
||||
#define OQS_ENABLE_SIG_sphincs_sha256_128s_simple
|
||||
#define OQS_ENABLE_SIG_sphincs_sha256_192f_robust
|
||||
#define OQS_ENABLE_SIG_sphincs_sha256_192f_simple
|
||||
#define OQS_ENABLE_SIG_sphincs_sha256_192s_robust
|
||||
#define OQS_ENABLE_SIG_sphincs_sha256_192s_simple
|
||||
#define OQS_ENABLE_SIG_sphincs_sha256_256f_robust
|
||||
#define OQS_ENABLE_SIG_sphincs_sha256_256f_simple
|
||||
#define OQS_ENABLE_SIG_sphincs_sha256_256s_robust
|
||||
#define OQS_ENABLE_SIG_sphincs_sha256_256s_simple
|
||||
#define OQS_ENABLE_SIG_sphincs_shake256_128f_robust
|
||||
#define OQS_ENABLE_SIG_sphincs_shake256_128f_simple
|
||||
#define OQS_ENABLE_SIG_sphincs_shake256_128s_robust
|
||||
|
||||
@ -120,6 +120,18 @@ AC_DEFUN([CONFIG_FEATURES],
|
||||
AC_DEFINE(OQS_ENABLE_SIG_sphincs_haraka_256f_simple, 1, "Define to 1 when SHPINCS+-Haraka-256f-simple enabled")
|
||||
AC_DEFINE(OQS_ENABLE_SIG_sphincs_haraka_256s_robust, 1, "Define to 1 when SHPINCS+-Haraka-256s-robust enabled")
|
||||
AC_DEFINE(OQS_ENABLE_SIG_sphincs_haraka_256s_simple, 1, "Define to 1 when SHPINCS+-Haraka-256s-simple enabled")
|
||||
AC_DEFINE(OQS_ENABLE_SIG_sphincs_sha256_128f_robust, 1, "Define to 1 when SHPINCS+-SHA256-128f-robust enabled")
|
||||
AC_DEFINE(OQS_ENABLE_SIG_sphincs_sha256_128f_simple, 1, "Define to 1 when SHPINCS+-SHA256-128f-simple enabled")
|
||||
AC_DEFINE(OQS_ENABLE_SIG_sphincs_sha256_128s_robust, 1, "Define to 1 when SHPINCS+-SHA256-128s-robust enabled")
|
||||
AC_DEFINE(OQS_ENABLE_SIG_sphincs_sha256_128s_simple, 1, "Define to 1 when SHPINCS+-SHA256-128s-simple enabled")
|
||||
AC_DEFINE(OQS_ENABLE_SIG_sphincs_sha256_192f_robust, 1, "Define to 1 when SHPINCS+-SHA256-192f-robust enabled")
|
||||
AC_DEFINE(OQS_ENABLE_SIG_sphincs_sha256_192f_simple, 1, "Define to 1 when SHPINCS+-SHA256-192f-simple enabled")
|
||||
AC_DEFINE(OQS_ENABLE_SIG_sphincs_sha256_192s_robust, 1, "Define to 1 when SHPINCS+-SHA256-192s-robust enabled")
|
||||
AC_DEFINE(OQS_ENABLE_SIG_sphincs_sha256_192s_simple, 1, "Define to 1 when SHPINCS+-SHA256-192s-simple enabled")
|
||||
AC_DEFINE(OQS_ENABLE_SIG_sphincs_sha256_256f_robust, 1, "Define to 1 when SHPINCS+-SHA256-256f-robust enabled")
|
||||
AC_DEFINE(OQS_ENABLE_SIG_sphincs_sha256_256f_simple, 1, "Define to 1 when SHPINCS+-SHA256-256f-simple enabled")
|
||||
AC_DEFINE(OQS_ENABLE_SIG_sphincs_sha256_256s_robust, 1, "Define to 1 when SHPINCS+-SHA256-256s-robust enabled")
|
||||
AC_DEFINE(OQS_ENABLE_SIG_sphincs_sha256_256s_simple, 1, "Define to 1 when SHPINCS+-SHA256-256s-simple enabled")
|
||||
AC_DEFINE(OQS_ENABLE_SIG_sphincs_shake256_128f_robust, 1, "Define to 1 when SHPINCS+-SHAKE256-128f-robust enabled")
|
||||
AC_DEFINE(OQS_ENABLE_SIG_sphincs_shake256_128f_simple, 1, "Define to 1 when SHPINCS+-SHAKE256-128f-simple enabled")
|
||||
AC_DEFINE(OQS_ENABLE_SIG_sphincs_shake256_128s_robust, 1, "Define to 1 when SHPINCS+-SHAKE256-128s-robust enabled")
|
||||
|
||||
@ -231,6 +231,90 @@ sigs:
|
||||
implementation: clean
|
||||
sources: ['address.c', 'wots.c', 'utils.c', 'fors.c', 'sign.c', 'hash_haraka.c', 'thash_haraka_simple.c', 'haraka.c']
|
||||
visual_studio_guid: 40b4c623-511f-4235-be9b-9ff675457fe5
|
||||
-
|
||||
scheme: sha256_128f_robust
|
||||
pqclean_scheme: sphincs-sha256-128f-robust
|
||||
pretty_name_full: SHPINCS+-SHA256-128f-robust
|
||||
implementation: clean
|
||||
sources: ['address.c', 'wots.c', 'utils.c', 'fors.c', 'sign.c', 'hash_sha256.c', 'thash_sha256_robust.c', 'sha256.c']
|
||||
visual_studio_guid: f569c3b0-c6ba-4157-a858-a5fc52d51515
|
||||
-
|
||||
scheme: sha256_128f_simple
|
||||
pqclean_scheme: sphincs-sha256-128f-simple
|
||||
pretty_name_full: SHPINCS+-SHA256-128f-simple
|
||||
implementation: clean
|
||||
sources: ['address.c', 'wots.c', 'utils.c', 'fors.c', 'sign.c', 'hash_sha256.c', 'thash_sha256_simple.c', 'sha256.c']
|
||||
visual_studio_guid: 1be5ba25-e61c-4218-a949-129b3422d6d8
|
||||
-
|
||||
scheme: sha256_128s_robust
|
||||
pqclean_scheme: sphincs-sha256-128s-robust
|
||||
pretty_name_full: SHPINCS+-SHA256-128s-robust
|
||||
implementation: clean
|
||||
sources: ['address.c', 'wots.c', 'utils.c', 'fors.c', 'sign.c', 'hash_sha256.c', 'thash_sha256_robust.c', 'sha256.c']
|
||||
visual_studio_guid: c2b7b42f-bebf-4a92-8f97-e12740a2f287
|
||||
-
|
||||
scheme: sha256_128s_simple
|
||||
pqclean_scheme: sphincs-sha256-128s-simple
|
||||
pretty_name_full: SHPINCS+-SHA256-128s-simple
|
||||
implementation: clean
|
||||
sources: ['address.c', 'wots.c', 'utils.c', 'fors.c', 'sign.c', 'hash_sha256.c', 'thash_sha256_simple.c', 'sha256.c']
|
||||
visual_studio_guid: b380048d-601c-46d6-acb8-591a2c4e1854
|
||||
-
|
||||
scheme: sha256_192f_robust
|
||||
pqclean_scheme: sphincs-sha256-192f-robust
|
||||
pretty_name_full: SHPINCS+-SHA256-192f-robust
|
||||
implementation: clean
|
||||
sources: ['address.c', 'wots.c', 'utils.c', 'fors.c', 'sign.c', 'hash_sha256.c', 'thash_sha256_robust.c', 'sha256.c']
|
||||
visual_studio_guid: 639a3ad2-1d05-445a-b9ea-9112fe8a6e7d
|
||||
-
|
||||
scheme: sha256_192f_simple
|
||||
pqclean_scheme: sphincs-sha256-192f-simple
|
||||
pretty_name_full: SHPINCS+-SHA256-192f-simple
|
||||
implementation: clean
|
||||
sources: ['address.c', 'wots.c', 'utils.c', 'fors.c', 'sign.c', 'hash_sha256.c', 'thash_sha256_simple.c', 'sha256.c']
|
||||
visual_studio_guid: eea572d4-7c0a-4d63-bd4d-5d038223a922
|
||||
-
|
||||
scheme: sha256_192s_robust
|
||||
pqclean_scheme: sphincs-sha256-192s-robust
|
||||
pretty_name_full: SHPINCS+-SHA256-192s-robust
|
||||
implementation: clean
|
||||
sources: ['address.c', 'wots.c', 'utils.c', 'fors.c', 'sign.c', 'hash_sha256.c', 'thash_sha256_robust.c', 'sha256.c']
|
||||
visual_studio_guid: 1972ed56-876a-4eca-aadd-91886adfe290
|
||||
-
|
||||
scheme: sha256_192s_simple
|
||||
pqclean_scheme: sphincs-sha256-192s-simple
|
||||
pretty_name_full: SHPINCS+-SHA256-192s-simple
|
||||
implementation: clean
|
||||
sources: ['address.c', 'wots.c', 'utils.c', 'fors.c', 'sign.c', 'hash_sha256.c', 'thash_sha256_simple.c', 'sha256.c']
|
||||
visual_studio_guid: 10d0a3dd-b2b8-4e74-b59c-dc94ea84b7c1
|
||||
-
|
||||
scheme: sha256_256f_robust
|
||||
pqclean_scheme: sphincs-sha256-256f-robust
|
||||
pretty_name_full: SHPINCS+-SHA256-256f-robust
|
||||
implementation: clean
|
||||
sources: ['address.c', 'wots.c', 'utils.c', 'fors.c', 'sign.c', 'hash_sha256.c', 'thash_sha256_robust.c', 'sha256.c']
|
||||
visual_studio_guid: 945476fd-8435-4df8-9b4b-c04e74aa6d03
|
||||
-
|
||||
scheme: sha256_256f_simple
|
||||
pqclean_scheme: sphincs-sha256-256f-simple
|
||||
pretty_name_full: SHPINCS+-SHA256-256f-simple
|
||||
implementation: clean
|
||||
sources: ['address.c', 'wots.c', 'utils.c', 'fors.c', 'sign.c', 'hash_sha256.c', 'thash_sha256_simple.c', 'sha256.c']
|
||||
visual_studio_guid: d70d780f-3ff0-4146-a6ce-8801bc157f83
|
||||
-
|
||||
scheme: sha256_256s_robust
|
||||
pqclean_scheme: sphincs-sha256-256s-robust
|
||||
pretty_name_full: SHPINCS+-SHA256-256s-robust
|
||||
implementation: clean
|
||||
sources: ['address.c', 'wots.c', 'utils.c', 'fors.c', 'sign.c', 'hash_sha256.c', 'thash_sha256_robust.c', 'sha256.c']
|
||||
visual_studio_guid: fd789855-13bb-40e9-a09f-9086dd62ab93
|
||||
-
|
||||
scheme: sha256_256s_simple
|
||||
pqclean_scheme: sphincs-sha256-256s-simple
|
||||
pretty_name_full: SHPINCS+-SHA256-256s-simple
|
||||
implementation: clean
|
||||
sources: ['address.c', 'wots.c', 'utils.c', 'fors.c', 'sign.c', 'hash_sha256.c', 'thash_sha256_simple.c', 'sha256.c']
|
||||
visual_studio_guid: 4823fa89-43de-45b0-ac13-3de5345ce48b
|
||||
-
|
||||
scheme: shake256_128f_robust
|
||||
pqclean_scheme: sphincs-shake256-128f-robust
|
||||
|
||||
@ -15,7 +15,7 @@ OQS_API const char *OQS_SIG_alg_identifier(size_t i) {
|
||||
///// OQS_COPY_FROM_PQCLEAN_FRAGMENT_ALG_IDENTIFIER_START
|
||||
OQS_SIG_alg_dilithium_2, OQS_SIG_alg_dilithium_3, OQS_SIG_alg_dilithium_4,
|
||||
OQS_SIG_alg_mqdss_31_48, OQS_SIG_alg_mqdss_31_64,
|
||||
OQS_SIG_alg_sphincs_haraka_128f_robust, OQS_SIG_alg_sphincs_haraka_128f_simple, OQS_SIG_alg_sphincs_haraka_128s_robust, OQS_SIG_alg_sphincs_haraka_128s_simple, OQS_SIG_alg_sphincs_haraka_192f_robust, OQS_SIG_alg_sphincs_haraka_192f_simple, OQS_SIG_alg_sphincs_haraka_192s_robust, OQS_SIG_alg_sphincs_haraka_192s_simple, OQS_SIG_alg_sphincs_haraka_256f_robust, OQS_SIG_alg_sphincs_haraka_256f_simple, OQS_SIG_alg_sphincs_haraka_256s_robust, OQS_SIG_alg_sphincs_haraka_256s_simple, OQS_SIG_alg_sphincs_shake256_128f_robust, OQS_SIG_alg_sphincs_shake256_128f_simple, OQS_SIG_alg_sphincs_shake256_128s_robust, OQS_SIG_alg_sphincs_shake256_128s_simple, OQS_SIG_alg_sphincs_shake256_192f_robust, OQS_SIG_alg_sphincs_shake256_192f_simple, OQS_SIG_alg_sphincs_shake256_192s_robust, OQS_SIG_alg_sphincs_shake256_192s_simple, OQS_SIG_alg_sphincs_shake256_256f_robust, OQS_SIG_alg_sphincs_shake256_256f_simple, OQS_SIG_alg_sphincs_shake256_256s_robust, OQS_SIG_alg_sphincs_shake256_256s_simple,
|
||||
OQS_SIG_alg_sphincs_haraka_128f_robust, OQS_SIG_alg_sphincs_haraka_128f_simple, OQS_SIG_alg_sphincs_haraka_128s_robust, OQS_SIG_alg_sphincs_haraka_128s_simple, OQS_SIG_alg_sphincs_haraka_192f_robust, OQS_SIG_alg_sphincs_haraka_192f_simple, OQS_SIG_alg_sphincs_haraka_192s_robust, OQS_SIG_alg_sphincs_haraka_192s_simple, OQS_SIG_alg_sphincs_haraka_256f_robust, OQS_SIG_alg_sphincs_haraka_256f_simple, OQS_SIG_alg_sphincs_haraka_256s_robust, OQS_SIG_alg_sphincs_haraka_256s_simple, OQS_SIG_alg_sphincs_sha256_128f_robust, OQS_SIG_alg_sphincs_sha256_128f_simple, OQS_SIG_alg_sphincs_sha256_128s_robust, OQS_SIG_alg_sphincs_sha256_128s_simple, OQS_SIG_alg_sphincs_sha256_192f_robust, OQS_SIG_alg_sphincs_sha256_192f_simple, OQS_SIG_alg_sphincs_sha256_192s_robust, OQS_SIG_alg_sphincs_sha256_192s_simple, OQS_SIG_alg_sphincs_sha256_256f_robust, OQS_SIG_alg_sphincs_sha256_256f_simple, OQS_SIG_alg_sphincs_sha256_256s_robust, OQS_SIG_alg_sphincs_sha256_256s_simple, OQS_SIG_alg_sphincs_shake256_128f_robust, OQS_SIG_alg_sphincs_shake256_128f_simple, OQS_SIG_alg_sphincs_shake256_128s_robust, OQS_SIG_alg_sphincs_shake256_128s_simple, OQS_SIG_alg_sphincs_shake256_192f_robust, OQS_SIG_alg_sphincs_shake256_192f_simple, OQS_SIG_alg_sphincs_shake256_192s_robust, OQS_SIG_alg_sphincs_shake256_192s_simple, OQS_SIG_alg_sphincs_shake256_256f_robust, OQS_SIG_alg_sphincs_shake256_256f_simple, OQS_SIG_alg_sphincs_shake256_256s_robust, OQS_SIG_alg_sphincs_shake256_256s_simple,
|
||||
///// OQS_COPY_FROM_PQCLEAN_FRAGMENT_ALG_IDENTIFIER_END
|
||||
OQS_SIG_alg_picnic_L1_FS, OQS_SIG_alg_picnic_L1_UR, OQS_SIG_alg_picnic_L3_FS, OQS_SIG_alg_picnic_L3_UR, OQS_SIG_alg_picnic_L5_FS, OQS_SIG_alg_picnic_L5_UR, OQS_SIG_alg_picnic2_L1_FS, OQS_SIG_alg_picnic2_L3_FS, OQS_SIG_alg_picnic2_L5_FS,
|
||||
OQS_SIG_alg_qTESLA_I, OQS_SIG_alg_qTESLA_III_size, OQS_SIG_alg_qTESLA_III_speed};
|
||||
@ -138,6 +138,78 @@ OQS_API OQS_SIG *OQS_SIG_new(const char *method_name) {
|
||||
return OQS_SIG_sphincs_haraka_256s_simple_new();
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
} else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_sha256_128f_robust)) {
|
||||
#ifdef OQS_ENABLE_SIG_sphincs_sha256_128f_robust
|
||||
return OQS_SIG_sphincs_sha256_128f_robust_new();
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
} else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_sha256_128f_simple)) {
|
||||
#ifdef OQS_ENABLE_SIG_sphincs_sha256_128f_simple
|
||||
return OQS_SIG_sphincs_sha256_128f_simple_new();
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
} else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_sha256_128s_robust)) {
|
||||
#ifdef OQS_ENABLE_SIG_sphincs_sha256_128s_robust
|
||||
return OQS_SIG_sphincs_sha256_128s_robust_new();
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
} else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_sha256_128s_simple)) {
|
||||
#ifdef OQS_ENABLE_SIG_sphincs_sha256_128s_simple
|
||||
return OQS_SIG_sphincs_sha256_128s_simple_new();
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
} else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_sha256_192f_robust)) {
|
||||
#ifdef OQS_ENABLE_SIG_sphincs_sha256_192f_robust
|
||||
return OQS_SIG_sphincs_sha256_192f_robust_new();
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
} else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_sha256_192f_simple)) {
|
||||
#ifdef OQS_ENABLE_SIG_sphincs_sha256_192f_simple
|
||||
return OQS_SIG_sphincs_sha256_192f_simple_new();
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
} else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_sha256_192s_robust)) {
|
||||
#ifdef OQS_ENABLE_SIG_sphincs_sha256_192s_robust
|
||||
return OQS_SIG_sphincs_sha256_192s_robust_new();
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
} else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_sha256_192s_simple)) {
|
||||
#ifdef OQS_ENABLE_SIG_sphincs_sha256_192s_simple
|
||||
return OQS_SIG_sphincs_sha256_192s_simple_new();
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
} else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_sha256_256f_robust)) {
|
||||
#ifdef OQS_ENABLE_SIG_sphincs_sha256_256f_robust
|
||||
return OQS_SIG_sphincs_sha256_256f_robust_new();
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
} else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_sha256_256f_simple)) {
|
||||
#ifdef OQS_ENABLE_SIG_sphincs_sha256_256f_simple
|
||||
return OQS_SIG_sphincs_sha256_256f_simple_new();
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
} else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_sha256_256s_robust)) {
|
||||
#ifdef OQS_ENABLE_SIG_sphincs_sha256_256s_robust
|
||||
return OQS_SIG_sphincs_sha256_256s_robust_new();
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
} else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_sha256_256s_simple)) {
|
||||
#ifdef OQS_ENABLE_SIG_sphincs_sha256_256s_simple
|
||||
return OQS_SIG_sphincs_sha256_256s_simple_new();
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
} else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_shake256_128f_robust)) {
|
||||
#ifdef OQS_ENABLE_SIG_sphincs_shake256_128f_robust
|
||||
|
||||
@ -90,6 +90,30 @@ extern "C" {
|
||||
#define OQS_SIG_alg_sphincs_haraka_256s_robust "SHPINCS+-Haraka-256s-robust"
|
||||
/** Algorithm identifier for SHPINCS+-Haraka-256s-simple */
|
||||
#define OQS_SIG_alg_sphincs_haraka_256s_simple "SHPINCS+-Haraka-256s-simple"
|
||||
/** Algorithm identifier for SHPINCS+-SHA256-128f-robust */
|
||||
#define OQS_SIG_alg_sphincs_sha256_128f_robust "SHPINCS+-SHA256-128f-robust"
|
||||
/** Algorithm identifier for SHPINCS+-SHA256-128f-simple */
|
||||
#define OQS_SIG_alg_sphincs_sha256_128f_simple "SHPINCS+-SHA256-128f-simple"
|
||||
/** Algorithm identifier for SHPINCS+-SHA256-128s-robust */
|
||||
#define OQS_SIG_alg_sphincs_sha256_128s_robust "SHPINCS+-SHA256-128s-robust"
|
||||
/** Algorithm identifier for SHPINCS+-SHA256-128s-simple */
|
||||
#define OQS_SIG_alg_sphincs_sha256_128s_simple "SHPINCS+-SHA256-128s-simple"
|
||||
/** Algorithm identifier for SHPINCS+-SHA256-192f-robust */
|
||||
#define OQS_SIG_alg_sphincs_sha256_192f_robust "SHPINCS+-SHA256-192f-robust"
|
||||
/** Algorithm identifier for SHPINCS+-SHA256-192f-simple */
|
||||
#define OQS_SIG_alg_sphincs_sha256_192f_simple "SHPINCS+-SHA256-192f-simple"
|
||||
/** Algorithm identifier for SHPINCS+-SHA256-192s-robust */
|
||||
#define OQS_SIG_alg_sphincs_sha256_192s_robust "SHPINCS+-SHA256-192s-robust"
|
||||
/** Algorithm identifier for SHPINCS+-SHA256-192s-simple */
|
||||
#define OQS_SIG_alg_sphincs_sha256_192s_simple "SHPINCS+-SHA256-192s-simple"
|
||||
/** Algorithm identifier for SHPINCS+-SHA256-256f-robust */
|
||||
#define OQS_SIG_alg_sphincs_sha256_256f_robust "SHPINCS+-SHA256-256f-robust"
|
||||
/** Algorithm identifier for SHPINCS+-SHA256-256f-simple */
|
||||
#define OQS_SIG_alg_sphincs_sha256_256f_simple "SHPINCS+-SHA256-256f-simple"
|
||||
/** Algorithm identifier for SHPINCS+-SHA256-256s-robust */
|
||||
#define OQS_SIG_alg_sphincs_sha256_256s_robust "SHPINCS+-SHA256-256s-robust"
|
||||
/** Algorithm identifier for SHPINCS+-SHA256-256s-simple */
|
||||
#define OQS_SIG_alg_sphincs_sha256_256s_simple "SHPINCS+-SHA256-256s-simple"
|
||||
/** Algorithm identifier for SHPINCS+-SHAKE256-128f-robust */
|
||||
#define OQS_SIG_alg_sphincs_shake256_128f_robust "SHPINCS+-SHAKE256-128f-robust"
|
||||
/** Algorithm identifier for SHPINCS+-SHAKE256-128f-simple */
|
||||
@ -118,7 +142,7 @@ extern "C" {
|
||||
// EDIT-WHEN-ADDING-SIG
|
||||
///// OQS_COPY_FROM_PQCLEAN_FRAGMENT_ALGS_LENGTH_START
|
||||
/** Number of algorithm identifiers above (including default). */
|
||||
#define OQS_SIG_algs_length 42
|
||||
#define OQS_SIG_algs_length 54
|
||||
///// OQS_COPY_FROM_PQCLEAN_FRAGMENT_ALGS_LENGTH_END
|
||||
|
||||
/**
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
AUTOMAKE_OPTIONS = foreign
|
||||
noinst_LTLIBRARIES = libsigsphincs.la
|
||||
noinst_LTLIBRARIES += libsigsphincs_haraka_128f_robust.la libsigsphincs_haraka_128f_simple.la libsigsphincs_haraka_128s_robust.la libsigsphincs_haraka_128s_simple.la libsigsphincs_haraka_192f_robust.la libsigsphincs_haraka_192f_simple.la libsigsphincs_haraka_192s_robust.la libsigsphincs_haraka_192s_simple.la libsigsphincs_haraka_256f_robust.la libsigsphincs_haraka_256f_simple.la libsigsphincs_haraka_256s_robust.la libsigsphincs_haraka_256s_simple.la libsigsphincs_shake256_128f_robust.la libsigsphincs_shake256_128f_simple.la libsigsphincs_shake256_128s_robust.la libsigsphincs_shake256_128s_simple.la libsigsphincs_shake256_192f_robust.la libsigsphincs_shake256_192f_simple.la libsigsphincs_shake256_192s_robust.la libsigsphincs_shake256_192s_simple.la libsigsphincs_shake256_256f_robust.la libsigsphincs_shake256_256f_simple.la libsigsphincs_shake256_256s_robust.la libsigsphincs_shake256_256s_simple.la
|
||||
noinst_LTLIBRARIES += libsigsphincs_haraka_128f_robust.la libsigsphincs_haraka_128f_simple.la libsigsphincs_haraka_128s_robust.la libsigsphincs_haraka_128s_simple.la libsigsphincs_haraka_192f_robust.la libsigsphincs_haraka_192f_simple.la libsigsphincs_haraka_192s_robust.la libsigsphincs_haraka_192s_simple.la libsigsphincs_haraka_256f_robust.la libsigsphincs_haraka_256f_simple.la libsigsphincs_haraka_256s_robust.la libsigsphincs_haraka_256s_simple.la libsigsphincs_sha256_128f_robust.la libsigsphincs_sha256_128f_simple.la libsigsphincs_sha256_128s_robust.la libsigsphincs_sha256_128s_simple.la libsigsphincs_sha256_192f_robust.la libsigsphincs_sha256_192f_simple.la libsigsphincs_sha256_192s_robust.la libsigsphincs_sha256_192s_simple.la libsigsphincs_sha256_256f_robust.la libsigsphincs_sha256_256f_simple.la libsigsphincs_sha256_256s_robust.la libsigsphincs_sha256_256s_simple.la libsigsphincs_shake256_128f_robust.la libsigsphincs_shake256_128f_simple.la libsigsphincs_shake256_128s_robust.la libsigsphincs_shake256_128s_simple.la libsigsphincs_shake256_192f_robust.la libsigsphincs_shake256_192f_simple.la libsigsphincs_shake256_192s_robust.la libsigsphincs_shake256_192s_simple.la libsigsphincs_shake256_256f_robust.la libsigsphincs_shake256_256f_simple.la libsigsphincs_shake256_256s_robust.la libsigsphincs_shake256_256s_simple.la
|
||||
|
||||
libsigsphincs_la_LIBADD = libsigsphincs_haraka_128f_robust.la libsigsphincs_haraka_128f_simple.la libsigsphincs_haraka_128s_robust.la libsigsphincs_haraka_128s_simple.la libsigsphincs_haraka_192f_robust.la libsigsphincs_haraka_192f_simple.la libsigsphincs_haraka_192s_robust.la libsigsphincs_haraka_192s_simple.la libsigsphincs_haraka_256f_robust.la libsigsphincs_haraka_256f_simple.la libsigsphincs_haraka_256s_robust.la libsigsphincs_haraka_256s_simple.la libsigsphincs_shake256_128f_robust.la libsigsphincs_shake256_128f_simple.la libsigsphincs_shake256_128s_robust.la libsigsphincs_shake256_128s_simple.la libsigsphincs_shake256_192f_robust.la libsigsphincs_shake256_192f_simple.la libsigsphincs_shake256_192s_robust.la libsigsphincs_shake256_192s_simple.la libsigsphincs_shake256_256f_robust.la libsigsphincs_shake256_256f_simple.la libsigsphincs_shake256_256s_robust.la libsigsphincs_shake256_256s_simple.la
|
||||
libsigsphincs_la_LIBADD = libsigsphincs_haraka_128f_robust.la libsigsphincs_haraka_128f_simple.la libsigsphincs_haraka_128s_robust.la libsigsphincs_haraka_128s_simple.la libsigsphincs_haraka_192f_robust.la libsigsphincs_haraka_192f_simple.la libsigsphincs_haraka_192s_robust.la libsigsphincs_haraka_192s_simple.la libsigsphincs_haraka_256f_robust.la libsigsphincs_haraka_256f_simple.la libsigsphincs_haraka_256s_robust.la libsigsphincs_haraka_256s_simple.la libsigsphincs_sha256_128f_robust.la libsigsphincs_sha256_128f_simple.la libsigsphincs_sha256_128s_robust.la libsigsphincs_sha256_128s_simple.la libsigsphincs_sha256_192f_robust.la libsigsphincs_sha256_192f_simple.la libsigsphincs_sha256_192s_robust.la libsigsphincs_sha256_192s_simple.la libsigsphincs_sha256_256f_robust.la libsigsphincs_sha256_256f_simple.la libsigsphincs_sha256_256s_robust.la libsigsphincs_sha256_256s_simple.la libsigsphincs_shake256_128f_robust.la libsigsphincs_shake256_128f_simple.la libsigsphincs_shake256_128s_robust.la libsigsphincs_shake256_128s_simple.la libsigsphincs_shake256_192f_robust.la libsigsphincs_shake256_192f_simple.la libsigsphincs_shake256_192s_robust.la libsigsphincs_shake256_192s_simple.la libsigsphincs_shake256_256f_robust.la libsigsphincs_shake256_256f_simple.la libsigsphincs_shake256_256s_robust.la libsigsphincs_shake256_256s_simple.la
|
||||
libsigsphincs_la_SOURCES =
|
||||
|
||||
libsigsphincs_haraka_128f_robust_la_SOURCES = sig_sphincs_haraka_128f_robust.c pqclean_sphincs-haraka-128f-robust_clean/address.c pqclean_sphincs-haraka-128f-robust_clean/wots.c pqclean_sphincs-haraka-128f-robust_clean/utils.c pqclean_sphincs-haraka-128f-robust_clean/fors.c pqclean_sphincs-haraka-128f-robust_clean/sign.c pqclean_sphincs-haraka-128f-robust_clean/hash_haraka.c pqclean_sphincs-haraka-128f-robust_clean/thash_haraka_robust.c pqclean_sphincs-haraka-128f-robust_clean/haraka.c
|
||||
@ -41,6 +41,42 @@ libsigsphincs_haraka_256s_robust_la_CFLAGS = $(AM_CFLAGS) -I../../common/pqclea
|
||||
libsigsphincs_haraka_256s_simple_la_SOURCES = sig_sphincs_haraka_256s_simple.c pqclean_sphincs-haraka-256s-simple_clean/address.c pqclean_sphincs-haraka-256s-simple_clean/wots.c pqclean_sphincs-haraka-256s-simple_clean/utils.c pqclean_sphincs-haraka-256s-simple_clean/fors.c pqclean_sphincs-haraka-256s-simple_clean/sign.c pqclean_sphincs-haraka-256s-simple_clean/hash_haraka.c pqclean_sphincs-haraka-256s-simple_clean/thash_haraka_simple.c pqclean_sphincs-haraka-256s-simple_clean/haraka.c
|
||||
libsigsphincs_haraka_256s_simple_la_CFLAGS = $(AM_CFLAGS) -I../../common/pqclean_shims
|
||||
|
||||
libsigsphincs_sha256_128f_robust_la_SOURCES = sig_sphincs_sha256_128f_robust.c pqclean_sphincs-sha256-128f-robust_clean/address.c pqclean_sphincs-sha256-128f-robust_clean/wots.c pqclean_sphincs-sha256-128f-robust_clean/utils.c pqclean_sphincs-sha256-128f-robust_clean/fors.c pqclean_sphincs-sha256-128f-robust_clean/sign.c pqclean_sphincs-sha256-128f-robust_clean/hash_sha256.c pqclean_sphincs-sha256-128f-robust_clean/thash_sha256_robust.c pqclean_sphincs-sha256-128f-robust_clean/sha256.c
|
||||
libsigsphincs_sha256_128f_robust_la_CFLAGS = $(AM_CFLAGS) -I../../common/pqclean_shims
|
||||
|
||||
libsigsphincs_sha256_128f_simple_la_SOURCES = sig_sphincs_sha256_128f_simple.c pqclean_sphincs-sha256-128f-simple_clean/address.c pqclean_sphincs-sha256-128f-simple_clean/wots.c pqclean_sphincs-sha256-128f-simple_clean/utils.c pqclean_sphincs-sha256-128f-simple_clean/fors.c pqclean_sphincs-sha256-128f-simple_clean/sign.c pqclean_sphincs-sha256-128f-simple_clean/hash_sha256.c pqclean_sphincs-sha256-128f-simple_clean/thash_sha256_simple.c pqclean_sphincs-sha256-128f-simple_clean/sha256.c
|
||||
libsigsphincs_sha256_128f_simple_la_CFLAGS = $(AM_CFLAGS) -I../../common/pqclean_shims
|
||||
|
||||
libsigsphincs_sha256_128s_robust_la_SOURCES = sig_sphincs_sha256_128s_robust.c pqclean_sphincs-sha256-128s-robust_clean/address.c pqclean_sphincs-sha256-128s-robust_clean/wots.c pqclean_sphincs-sha256-128s-robust_clean/utils.c pqclean_sphincs-sha256-128s-robust_clean/fors.c pqclean_sphincs-sha256-128s-robust_clean/sign.c pqclean_sphincs-sha256-128s-robust_clean/hash_sha256.c pqclean_sphincs-sha256-128s-robust_clean/thash_sha256_robust.c pqclean_sphincs-sha256-128s-robust_clean/sha256.c
|
||||
libsigsphincs_sha256_128s_robust_la_CFLAGS = $(AM_CFLAGS) -I../../common/pqclean_shims
|
||||
|
||||
libsigsphincs_sha256_128s_simple_la_SOURCES = sig_sphincs_sha256_128s_simple.c pqclean_sphincs-sha256-128s-simple_clean/address.c pqclean_sphincs-sha256-128s-simple_clean/wots.c pqclean_sphincs-sha256-128s-simple_clean/utils.c pqclean_sphincs-sha256-128s-simple_clean/fors.c pqclean_sphincs-sha256-128s-simple_clean/sign.c pqclean_sphincs-sha256-128s-simple_clean/hash_sha256.c pqclean_sphincs-sha256-128s-simple_clean/thash_sha256_simple.c pqclean_sphincs-sha256-128s-simple_clean/sha256.c
|
||||
libsigsphincs_sha256_128s_simple_la_CFLAGS = $(AM_CFLAGS) -I../../common/pqclean_shims
|
||||
|
||||
libsigsphincs_sha256_192f_robust_la_SOURCES = sig_sphincs_sha256_192f_robust.c pqclean_sphincs-sha256-192f-robust_clean/address.c pqclean_sphincs-sha256-192f-robust_clean/wots.c pqclean_sphincs-sha256-192f-robust_clean/utils.c pqclean_sphincs-sha256-192f-robust_clean/fors.c pqclean_sphincs-sha256-192f-robust_clean/sign.c pqclean_sphincs-sha256-192f-robust_clean/hash_sha256.c pqclean_sphincs-sha256-192f-robust_clean/thash_sha256_robust.c pqclean_sphincs-sha256-192f-robust_clean/sha256.c
|
||||
libsigsphincs_sha256_192f_robust_la_CFLAGS = $(AM_CFLAGS) -I../../common/pqclean_shims
|
||||
|
||||
libsigsphincs_sha256_192f_simple_la_SOURCES = sig_sphincs_sha256_192f_simple.c pqclean_sphincs-sha256-192f-simple_clean/address.c pqclean_sphincs-sha256-192f-simple_clean/wots.c pqclean_sphincs-sha256-192f-simple_clean/utils.c pqclean_sphincs-sha256-192f-simple_clean/fors.c pqclean_sphincs-sha256-192f-simple_clean/sign.c pqclean_sphincs-sha256-192f-simple_clean/hash_sha256.c pqclean_sphincs-sha256-192f-simple_clean/thash_sha256_simple.c pqclean_sphincs-sha256-192f-simple_clean/sha256.c
|
||||
libsigsphincs_sha256_192f_simple_la_CFLAGS = $(AM_CFLAGS) -I../../common/pqclean_shims
|
||||
|
||||
libsigsphincs_sha256_192s_robust_la_SOURCES = sig_sphincs_sha256_192s_robust.c pqclean_sphincs-sha256-192s-robust_clean/address.c pqclean_sphincs-sha256-192s-robust_clean/wots.c pqclean_sphincs-sha256-192s-robust_clean/utils.c pqclean_sphincs-sha256-192s-robust_clean/fors.c pqclean_sphincs-sha256-192s-robust_clean/sign.c pqclean_sphincs-sha256-192s-robust_clean/hash_sha256.c pqclean_sphincs-sha256-192s-robust_clean/thash_sha256_robust.c pqclean_sphincs-sha256-192s-robust_clean/sha256.c
|
||||
libsigsphincs_sha256_192s_robust_la_CFLAGS = $(AM_CFLAGS) -I../../common/pqclean_shims
|
||||
|
||||
libsigsphincs_sha256_192s_simple_la_SOURCES = sig_sphincs_sha256_192s_simple.c pqclean_sphincs-sha256-192s-simple_clean/address.c pqclean_sphincs-sha256-192s-simple_clean/wots.c pqclean_sphincs-sha256-192s-simple_clean/utils.c pqclean_sphincs-sha256-192s-simple_clean/fors.c pqclean_sphincs-sha256-192s-simple_clean/sign.c pqclean_sphincs-sha256-192s-simple_clean/hash_sha256.c pqclean_sphincs-sha256-192s-simple_clean/thash_sha256_simple.c pqclean_sphincs-sha256-192s-simple_clean/sha256.c
|
||||
libsigsphincs_sha256_192s_simple_la_CFLAGS = $(AM_CFLAGS) -I../../common/pqclean_shims
|
||||
|
||||
libsigsphincs_sha256_256f_robust_la_SOURCES = sig_sphincs_sha256_256f_robust.c pqclean_sphincs-sha256-256f-robust_clean/address.c pqclean_sphincs-sha256-256f-robust_clean/wots.c pqclean_sphincs-sha256-256f-robust_clean/utils.c pqclean_sphincs-sha256-256f-robust_clean/fors.c pqclean_sphincs-sha256-256f-robust_clean/sign.c pqclean_sphincs-sha256-256f-robust_clean/hash_sha256.c pqclean_sphincs-sha256-256f-robust_clean/thash_sha256_robust.c pqclean_sphincs-sha256-256f-robust_clean/sha256.c
|
||||
libsigsphincs_sha256_256f_robust_la_CFLAGS = $(AM_CFLAGS) -I../../common/pqclean_shims
|
||||
|
||||
libsigsphincs_sha256_256f_simple_la_SOURCES = sig_sphincs_sha256_256f_simple.c pqclean_sphincs-sha256-256f-simple_clean/address.c pqclean_sphincs-sha256-256f-simple_clean/wots.c pqclean_sphincs-sha256-256f-simple_clean/utils.c pqclean_sphincs-sha256-256f-simple_clean/fors.c pqclean_sphincs-sha256-256f-simple_clean/sign.c pqclean_sphincs-sha256-256f-simple_clean/hash_sha256.c pqclean_sphincs-sha256-256f-simple_clean/thash_sha256_simple.c pqclean_sphincs-sha256-256f-simple_clean/sha256.c
|
||||
libsigsphincs_sha256_256f_simple_la_CFLAGS = $(AM_CFLAGS) -I../../common/pqclean_shims
|
||||
|
||||
libsigsphincs_sha256_256s_robust_la_SOURCES = sig_sphincs_sha256_256s_robust.c pqclean_sphincs-sha256-256s-robust_clean/address.c pqclean_sphincs-sha256-256s-robust_clean/wots.c pqclean_sphincs-sha256-256s-robust_clean/utils.c pqclean_sphincs-sha256-256s-robust_clean/fors.c pqclean_sphincs-sha256-256s-robust_clean/sign.c pqclean_sphincs-sha256-256s-robust_clean/hash_sha256.c pqclean_sphincs-sha256-256s-robust_clean/thash_sha256_robust.c pqclean_sphincs-sha256-256s-robust_clean/sha256.c
|
||||
libsigsphincs_sha256_256s_robust_la_CFLAGS = $(AM_CFLAGS) -I../../common/pqclean_shims
|
||||
|
||||
libsigsphincs_sha256_256s_simple_la_SOURCES = sig_sphincs_sha256_256s_simple.c pqclean_sphincs-sha256-256s-simple_clean/address.c pqclean_sphincs-sha256-256s-simple_clean/wots.c pqclean_sphincs-sha256-256s-simple_clean/utils.c pqclean_sphincs-sha256-256s-simple_clean/fors.c pqclean_sphincs-sha256-256s-simple_clean/sign.c pqclean_sphincs-sha256-256s-simple_clean/hash_sha256.c pqclean_sphincs-sha256-256s-simple_clean/thash_sha256_simple.c pqclean_sphincs-sha256-256s-simple_clean/sha256.c
|
||||
libsigsphincs_sha256_256s_simple_la_CFLAGS = $(AM_CFLAGS) -I../../common/pqclean_shims
|
||||
|
||||
libsigsphincs_shake256_128f_robust_la_SOURCES = sig_sphincs_shake256_128f_robust.c pqclean_sphincs-shake256-128f-robust_clean/address.c pqclean_sphincs-shake256-128f-robust_clean/wots.c pqclean_sphincs-shake256-128f-robust_clean/utils.c pqclean_sphincs-shake256-128f-robust_clean/fors.c pqclean_sphincs-shake256-128f-robust_clean/sign.c pqclean_sphincs-shake256-128f-robust_clean/hash_shake256.c pqclean_sphincs-shake256-128f-robust_clean/thash_shake256_robust.c
|
||||
libsigsphincs_shake256_128f_robust_la_CFLAGS = $(AM_CFLAGS) -I../../common/pqclean_shims
|
||||
|
||||
|
||||
116
src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/LICENSE
Normal file
116
src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/LICENSE
Normal file
@ -0,0 +1,116 @@
|
||||
CC0 1.0 Universal
|
||||
|
||||
Statement of Purpose
|
||||
|
||||
The laws of most jurisdictions throughout the world automatically confer
|
||||
exclusive Copyright and Related Rights (defined below) upon the creator and
|
||||
subsequent owner(s) (each and all, an "owner") of an original work of
|
||||
authorship and/or a database (each, a "Work").
|
||||
|
||||
Certain owners wish to permanently relinquish those rights to a Work for the
|
||||
purpose of contributing to a commons of creative, cultural and scientific
|
||||
works ("Commons") that the public can reliably and without fear of later
|
||||
claims of infringement build upon, modify, incorporate in other works, reuse
|
||||
and redistribute as freely as possible in any form whatsoever and for any
|
||||
purposes, including without limitation commercial purposes. These owners may
|
||||
contribute to the Commons to promote the ideal of a free culture and the
|
||||
further production of creative, cultural and scientific works, or to gain
|
||||
reputation or greater distribution for their Work in part through the use and
|
||||
efforts of others.
|
||||
|
||||
For these and/or other purposes and motivations, and without any expectation
|
||||
of additional consideration or compensation, the person associating CC0 with a
|
||||
Work (the "Affirmer"), to the extent that he or she is an owner of Copyright
|
||||
and Related Rights in the Work, voluntarily elects to apply CC0 to the Work
|
||||
and publicly distribute the Work under its terms, with knowledge of his or her
|
||||
Copyright and Related Rights in the Work and the meaning and intended legal
|
||||
effect of CC0 on those rights.
|
||||
|
||||
1. Copyright and Related Rights. A Work made available under CC0 may be
|
||||
protected by copyright and related or neighboring rights ("Copyright and
|
||||
Related Rights"). Copyright and Related Rights include, but are not limited
|
||||
to, the following:
|
||||
|
||||
i. the right to reproduce, adapt, distribute, perform, display, communicate,
|
||||
and translate a Work;
|
||||
|
||||
ii. moral rights retained by the original author(s) and/or performer(s);
|
||||
|
||||
iii. publicity and privacy rights pertaining to a person's image or likeness
|
||||
depicted in a Work;
|
||||
|
||||
iv. rights protecting against unfair competition in regards to a Work,
|
||||
subject to the limitations in paragraph 4(a), below;
|
||||
|
||||
v. rights protecting the extraction, dissemination, use and reuse of data in
|
||||
a Work;
|
||||
|
||||
vi. database rights (such as those arising under Directive 96/9/EC of the
|
||||
European Parliament and of the Council of 11 March 1996 on the legal
|
||||
protection of databases, and under any national implementation thereof,
|
||||
including any amended or successor version of such directive); and
|
||||
|
||||
vii. other similar, equivalent or corresponding rights throughout the world
|
||||
based on applicable law or treaty, and any national implementations thereof.
|
||||
|
||||
2. Waiver. To the greatest extent permitted by, but not in contravention of,
|
||||
applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and
|
||||
unconditionally waives, abandons, and surrenders all of Affirmer's Copyright
|
||||
and Related Rights and associated claims and causes of action, whether now
|
||||
known or unknown (including existing as well as future claims and causes of
|
||||
action), in the Work (i) in all territories worldwide, (ii) for the maximum
|
||||
duration provided by applicable law or treaty (including future time
|
||||
extensions), (iii) in any current or future medium and for any number of
|
||||
copies, and (iv) for any purpose whatsoever, including without limitation
|
||||
commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes
|
||||
the Waiver for the benefit of each member of the public at large and to the
|
||||
detriment of Affirmer's heirs and successors, fully intending that such Waiver
|
||||
shall not be subject to revocation, rescission, cancellation, termination, or
|
||||
any other legal or equitable action to disrupt the quiet enjoyment of the Work
|
||||
by the public as contemplated by Affirmer's express Statement of Purpose.
|
||||
|
||||
3. Public License Fallback. Should any part of the Waiver for any reason be
|
||||
judged legally invalid or ineffective under applicable law, then the Waiver
|
||||
shall be preserved to the maximum extent permitted taking into account
|
||||
Affirmer's express Statement of Purpose. In addition, to the extent the Waiver
|
||||
is so judged Affirmer hereby grants to each affected person a royalty-free,
|
||||
non transferable, non sublicensable, non exclusive, irrevocable and
|
||||
unconditional license to exercise Affirmer's Copyright and Related Rights in
|
||||
the Work (i) in all territories worldwide, (ii) for the maximum duration
|
||||
provided by applicable law or treaty (including future time extensions), (iii)
|
||||
in any current or future medium and for any number of copies, and (iv) for any
|
||||
purpose whatsoever, including without limitation commercial, advertising or
|
||||
promotional purposes (the "License"). The License shall be deemed effective as
|
||||
of the date CC0 was applied by Affirmer to the Work. Should any part of the
|
||||
License for any reason be judged legally invalid or ineffective under
|
||||
applicable law, such partial invalidity or ineffectiveness shall not
|
||||
invalidate the remainder of the License, and in such case Affirmer hereby
|
||||
affirms that he or she will not (i) exercise any of his or her remaining
|
||||
Copyright and Related Rights in the Work or (ii) assert any associated claims
|
||||
and causes of action with respect to the Work, in either case contrary to
|
||||
Affirmer's express Statement of Purpose.
|
||||
|
||||
4. Limitations and Disclaimers.
|
||||
|
||||
a. No trademark or patent rights held by Affirmer are waived, abandoned,
|
||||
surrendered, licensed or otherwise affected by this document.
|
||||
|
||||
b. Affirmer offers the Work as-is and makes no representations or warranties
|
||||
of any kind concerning the Work, express, implied, statutory or otherwise,
|
||||
including without limitation warranties of title, merchantability, fitness
|
||||
for a particular purpose, non infringement, or the absence of latent or
|
||||
other defects, accuracy, or the present or absence of errors, whether or not
|
||||
discoverable, all to the greatest extent permissible under applicable law.
|
||||
|
||||
c. Affirmer disclaims responsibility for clearing rights of other persons
|
||||
that may apply to the Work or any use thereof, including without limitation
|
||||
any person's Copyright and Related Rights in the Work. Further, Affirmer
|
||||
disclaims responsibility for obtaining any necessary consents, permissions
|
||||
or other rights required for any use of the Work.
|
||||
|
||||
d. Affirmer understands and acknowledges that Creative Commons is not a
|
||||
party to this document and has no duty or obligation with respect to this
|
||||
CC0 or use of the Work.
|
||||
|
||||
For more information, please see
|
||||
<http://creativecommons.org/publicdomain/zero/1.0/>
|
||||
@ -0,0 +1,78 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#include "address.h"
|
||||
#include "params.h"
|
||||
#include "utils.h"
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_addr_to_bytes(
|
||||
unsigned char *bytes, const uint32_t addr[8]) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_ull_to_bytes(
|
||||
bytes + i * 4, 4, addr[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_layer_addr(
|
||||
uint32_t addr[8], uint32_t layer) {
|
||||
addr[0] = layer;
|
||||
}
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_tree_addr(
|
||||
uint32_t addr[8], uint64_t tree) {
|
||||
addr[1] = 0;
|
||||
addr[2] = (uint32_t) (tree >> 32);
|
||||
addr[3] = (uint32_t) tree;
|
||||
}
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_type(
|
||||
uint32_t addr[8], uint32_t type) {
|
||||
addr[4] = type;
|
||||
}
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_copy_subtree_addr(
|
||||
uint32_t out[8], const uint32_t in[8]) {
|
||||
out[0] = in[0];
|
||||
out[1] = in[1];
|
||||
out[2] = in[2];
|
||||
out[3] = in[3];
|
||||
}
|
||||
|
||||
/* These functions are used for OTS addresses. */
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_keypair_addr(
|
||||
uint32_t addr[8], uint32_t keypair) {
|
||||
addr[5] = keypair;
|
||||
}
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_copy_keypair_addr(
|
||||
uint32_t out[8], const uint32_t in[8]) {
|
||||
out[0] = in[0];
|
||||
out[1] = in[1];
|
||||
out[2] = in[2];
|
||||
out[3] = in[3];
|
||||
out[5] = in[5];
|
||||
}
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_chain_addr(
|
||||
uint32_t addr[8], uint32_t chain) {
|
||||
addr[6] = chain;
|
||||
}
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_hash_addr(
|
||||
uint32_t addr[8], uint32_t hash) {
|
||||
addr[7] = hash;
|
||||
}
|
||||
|
||||
/* These functions are used for all hash tree addresses (including FORS). */
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_tree_height(
|
||||
uint32_t addr[8], uint32_t tree_height) {
|
||||
addr[6] = tree_height;
|
||||
}
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_tree_index(
|
||||
uint32_t addr[8], uint32_t tree_index) {
|
||||
addr[7] = tree_index;
|
||||
}
|
||||
@ -0,0 +1,50 @@
|
||||
#ifndef SPX_ADDRESS_H
|
||||
#define SPX_ADDRESS_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define SPX_ADDR_TYPE_WOTS 0
|
||||
#define SPX_ADDR_TYPE_WOTSPK 1
|
||||
#define SPX_ADDR_TYPE_HASHTREE 2
|
||||
#define SPX_ADDR_TYPE_FORSTREE 3
|
||||
#define SPX_ADDR_TYPE_FORSPK 4
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_addr_to_bytes(
|
||||
unsigned char *bytes, const uint32_t addr[8]);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_layer_addr(
|
||||
uint32_t addr[8], uint32_t layer);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_tree_addr(
|
||||
uint32_t addr[8], uint64_t tree);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_type(
|
||||
uint32_t addr[8], uint32_t type);
|
||||
|
||||
/* Copies the layer and tree part of one address into the other */
|
||||
void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_copy_subtree_addr(
|
||||
uint32_t out[8], const uint32_t in[8]);
|
||||
|
||||
/* These functions are used for WOTS and FORS addresses. */
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_keypair_addr(
|
||||
uint32_t addr[8], uint32_t keypair);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_chain_addr(
|
||||
uint32_t addr[8], uint32_t chain);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_hash_addr(
|
||||
uint32_t addr[8], uint32_t hash);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_copy_keypair_addr(
|
||||
uint32_t out[8], const uint32_t in[8]);
|
||||
|
||||
/* These functions are used for all hash tree addresses (including FORS). */
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_tree_height(
|
||||
uint32_t addr[8], uint32_t tree_height);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_tree_index(
|
||||
uint32_t addr[8], uint32_t tree_index);
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,78 @@
|
||||
#ifndef PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_API_H
|
||||
#define PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_API_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_CRYPTO_ALGNAME "SPHINCS+"
|
||||
|
||||
#define PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_CRYPTO_SECRETKEYBYTES 64
|
||||
#define PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_CRYPTO_PUBLICKEYBYTES 32
|
||||
#define PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_CRYPTO_BYTES 16976
|
||||
#define PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_CRYPTO_SEEDBYTES 48
|
||||
|
||||
/*
|
||||
* Returns the length of a secret key, in bytes
|
||||
*/
|
||||
size_t PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_crypto_sign_secretkeybytes(void);
|
||||
|
||||
/*
|
||||
* Returns the length of a public key, in bytes
|
||||
*/
|
||||
size_t PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_crypto_sign_publickeybytes(void);
|
||||
|
||||
/*
|
||||
* Returns the length of a signature, in bytes
|
||||
*/
|
||||
size_t PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_crypto_sign_bytes(void);
|
||||
|
||||
/*
|
||||
* Returns the length of the seed required to generate a key pair, in bytes
|
||||
*/
|
||||
size_t PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_crypto_sign_seedbytes(void);
|
||||
|
||||
/*
|
||||
* Generates a SPHINCS+ key pair given a seed.
|
||||
* Format sk: [SK_SEED || SK_PRF || PUB_SEED || root]
|
||||
* Format pk: [root || PUB_SEED]
|
||||
*/
|
||||
int PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_crypto_sign_seed_keypair(
|
||||
uint8_t *pk, uint8_t *sk, const uint8_t *seed);
|
||||
|
||||
/*
|
||||
* Generates a SPHINCS+ key pair.
|
||||
* Format sk: [SK_SEED || SK_PRF || PUB_SEED || root]
|
||||
* Format pk: [root || PUB_SEED]
|
||||
*/
|
||||
int PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_crypto_sign_keypair(
|
||||
uint8_t *pk, uint8_t *sk);
|
||||
|
||||
/**
|
||||
* Returns an array containing a detached signature.
|
||||
*/
|
||||
int PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_crypto_sign_signature(
|
||||
uint8_t *sig, size_t *siglen,
|
||||
const uint8_t *m, size_t mlen, const uint8_t *sk);
|
||||
|
||||
/**
|
||||
* Verifies a detached signature and message under a given public key.
|
||||
*/
|
||||
int PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_crypto_sign_verify(
|
||||
const uint8_t *sig, size_t siglen,
|
||||
const uint8_t *m, size_t mlen, const uint8_t *pk);
|
||||
|
||||
/**
|
||||
* Returns an array containing the signature followed by the message.
|
||||
*/
|
||||
int PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_crypto_sign(
|
||||
uint8_t *sm, size_t *smlen,
|
||||
const uint8_t *m, size_t mlen, const uint8_t *sk);
|
||||
|
||||
/**
|
||||
* Verifies a given signature-message pair under a given public key.
|
||||
*/
|
||||
int PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_crypto_sign_open(
|
||||
uint8_t *m, size_t *mlen,
|
||||
const uint8_t *sm, size_t smlen, const uint8_t *pk);
|
||||
|
||||
#endif
|
||||
169
src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/fors.c
Normal file
169
src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/fors.c
Normal file
@ -0,0 +1,169 @@
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "address.h"
|
||||
#include "fors.h"
|
||||
#include "hash.h"
|
||||
#include "hash_state.h"
|
||||
#include "thash.h"
|
||||
#include "utils.h"
|
||||
|
||||
static void fors_gen_sk(unsigned char *sk, const unsigned char *sk_seed,
|
||||
uint32_t fors_leaf_addr[8], const hash_state *hash_state_seeded) {
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_prf_addr(
|
||||
sk, sk_seed, fors_leaf_addr, hash_state_seeded);
|
||||
}
|
||||
|
||||
static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk,
|
||||
const unsigned char *pub_seed,
|
||||
uint32_t fors_leaf_addr[8],
|
||||
const hash_state *hash_state_seeded) {
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_thash_1(
|
||||
leaf, sk, pub_seed, fors_leaf_addr, hash_state_seeded);
|
||||
}
|
||||
|
||||
static void fors_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed,
|
||||
const unsigned char *pub_seed,
|
||||
uint32_t addr_idx, const uint32_t fors_tree_addr[8],
|
||||
const hash_state *hash_state_seeded) {
|
||||
uint32_t fors_leaf_addr[8] = {0};
|
||||
|
||||
/* Only copy the parts that must be kept in fors_leaf_addr. */
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_copy_keypair_addr(
|
||||
fors_leaf_addr, fors_tree_addr);
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_type(
|
||||
fors_leaf_addr, SPX_ADDR_TYPE_FORSTREE);
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_tree_index(
|
||||
fors_leaf_addr, addr_idx);
|
||||
|
||||
fors_gen_sk(leaf, sk_seed, fors_leaf_addr, hash_state_seeded);
|
||||
fors_sk_to_leaf(leaf, leaf, pub_seed, fors_leaf_addr, hash_state_seeded);
|
||||
}
|
||||
|
||||
/**
|
||||
* Interprets m as SPX_FORS_HEIGHT-bit unsigned integers.
|
||||
* Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits.
|
||||
* Assumes indices has space for SPX_FORS_TREES integers.
|
||||
*/
|
||||
static void message_to_indices(uint32_t *indices, const unsigned char *m) {
|
||||
unsigned int i, j;
|
||||
unsigned int offset = 0;
|
||||
|
||||
for (i = 0; i < SPX_FORS_TREES; i++) {
|
||||
indices[i] = 0;
|
||||
for (j = 0; j < SPX_FORS_HEIGHT; j++) {
|
||||
indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j;
|
||||
offset++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Signs a message m, deriving the secret key from sk_seed and the FTS address.
|
||||
* Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits.
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_fors_sign(
|
||||
unsigned char *sig, unsigned char *pk,
|
||||
const unsigned char *m,
|
||||
const unsigned char *sk_seed, const unsigned char *pub_seed,
|
||||
const uint32_t fors_addr[8], const hash_state *hash_state_seeded) {
|
||||
uint32_t indices[SPX_FORS_TREES];
|
||||
unsigned char roots[SPX_FORS_TREES * SPX_N];
|
||||
uint32_t fors_tree_addr[8] = {0};
|
||||
uint32_t fors_pk_addr[8] = {0};
|
||||
uint32_t idx_offset;
|
||||
unsigned int i;
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_copy_keypair_addr(
|
||||
fors_tree_addr, fors_addr);
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_copy_keypair_addr(
|
||||
fors_pk_addr, fors_addr);
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_type(
|
||||
fors_tree_addr, SPX_ADDR_TYPE_FORSTREE);
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_type(
|
||||
fors_pk_addr, SPX_ADDR_TYPE_FORSPK);
|
||||
|
||||
message_to_indices(indices, m);
|
||||
|
||||
for (i = 0; i < SPX_FORS_TREES; i++) {
|
||||
idx_offset = i * (1 << SPX_FORS_HEIGHT);
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_tree_height(
|
||||
fors_tree_addr, 0);
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_tree_index(
|
||||
fors_tree_addr, indices[i] + idx_offset);
|
||||
|
||||
/* Include the secret key part that produces the selected leaf node. */
|
||||
fors_gen_sk(sig, sk_seed, fors_tree_addr, hash_state_seeded);
|
||||
sig += SPX_N;
|
||||
|
||||
/* Compute the authentication path for this leaf node. */
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_treehash_FORS_HEIGHT(
|
||||
roots + i * SPX_N, sig, sk_seed, pub_seed,
|
||||
indices[i], idx_offset, fors_gen_leaf, fors_tree_addr,
|
||||
hash_state_seeded);
|
||||
sig += SPX_N * SPX_FORS_HEIGHT;
|
||||
}
|
||||
|
||||
/* Hash horizontally across all tree roots to derive the public key. */
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_thash_FORS_TREES(
|
||||
pk, roots, pub_seed, fors_pk_addr, hash_state_seeded);
|
||||
}
|
||||
|
||||
/**
|
||||
* Derives the FORS public key from a signature.
|
||||
* This can be used for verification by comparing to a known public key, or to
|
||||
* subsequently verify a signature on the derived public key. The latter is the
|
||||
* typical use-case when used as an FTS below an OTS in a hypertree.
|
||||
* Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits.
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_fors_pk_from_sig(
|
||||
unsigned char *pk,
|
||||
const unsigned char *sig, const unsigned char *m,
|
||||
const unsigned char *pub_seed, const uint32_t fors_addr[8],
|
||||
const hash_state *hash_state_seeded) {
|
||||
uint32_t indices[SPX_FORS_TREES];
|
||||
unsigned char roots[SPX_FORS_TREES * SPX_N];
|
||||
unsigned char leaf[SPX_N];
|
||||
uint32_t fors_tree_addr[8] = {0};
|
||||
uint32_t fors_pk_addr[8] = {0};
|
||||
uint32_t idx_offset;
|
||||
unsigned int i;
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_copy_keypair_addr(
|
||||
fors_tree_addr, fors_addr);
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_copy_keypair_addr(
|
||||
fors_pk_addr, fors_addr);
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_type(
|
||||
fors_tree_addr, SPX_ADDR_TYPE_FORSTREE);
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_type(
|
||||
fors_pk_addr, SPX_ADDR_TYPE_FORSPK);
|
||||
|
||||
message_to_indices(indices, m);
|
||||
|
||||
for (i = 0; i < SPX_FORS_TREES; i++) {
|
||||
idx_offset = i * (1 << SPX_FORS_HEIGHT);
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_tree_height(
|
||||
fors_tree_addr, 0);
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_tree_index(
|
||||
fors_tree_addr, indices[i] + idx_offset);
|
||||
|
||||
/* Derive the leaf from the included secret key part. */
|
||||
fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, hash_state_seeded);
|
||||
sig += SPX_N;
|
||||
|
||||
/* Derive the corresponding root node of this tree. */
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_compute_root(
|
||||
roots + i * SPX_N, leaf, indices[i], idx_offset, sig,
|
||||
SPX_FORS_HEIGHT, pub_seed, fors_tree_addr, hash_state_seeded);
|
||||
sig += SPX_N * SPX_FORS_HEIGHT;
|
||||
}
|
||||
|
||||
/* Hash horizontally across all tree roots to derive the public key. */
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_thash_FORS_TREES(
|
||||
pk, roots, pub_seed, fors_pk_addr, hash_state_seeded);
|
||||
}
|
||||
@ -0,0 +1,32 @@
|
||||
#ifndef SPX_FORS_H
|
||||
#define SPX_FORS_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "params.h"
|
||||
#include "hash_state.h"
|
||||
|
||||
/**
|
||||
* Signs a message m, deriving the secret key from sk_seed and the FTS address.
|
||||
* Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits.
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_fors_sign(
|
||||
unsigned char *sig, unsigned char *pk,
|
||||
const unsigned char *m,
|
||||
const unsigned char *sk_seed, const unsigned char *pub_seed,
|
||||
const uint32_t fors_addr[8], const hash_state *hash_state_seeded);
|
||||
|
||||
/**
|
||||
* Derives the FORS public key from a signature.
|
||||
* This can be used for verification by comparing to a known public key, or to
|
||||
* subsequently verify a signature on the derived public key. The latter is the
|
||||
* typical use-case when used as an FTS below an OTS in a hypertree.
|
||||
* Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits.
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_fors_pk_from_sig(
|
||||
unsigned char *pk,
|
||||
const unsigned char *sig, const unsigned char *m,
|
||||
const unsigned char *pub_seed, const uint32_t fors_addr[8],
|
||||
const hash_state *hash_state_seeded);
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,29 @@
|
||||
#ifndef SPX_HASH_H
|
||||
#define SPX_HASH_H
|
||||
|
||||
#include "hash_state.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_initialize_hash_function(
|
||||
hash_state *hash_state_seeded,
|
||||
const unsigned char *pub_seed, const unsigned char *sk_seed);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_prf_addr(
|
||||
unsigned char *out, const unsigned char *key, const uint32_t addr[8],
|
||||
const hash_state *hash_state_seeded);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_gen_message_random(
|
||||
unsigned char *R,
|
||||
const unsigned char *sk_prf, const unsigned char *optrand,
|
||||
const unsigned char *m, size_t mlen,
|
||||
const hash_state *hash_state_seeded);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_hash_message(
|
||||
unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx,
|
||||
const unsigned char *R, const unsigned char *pk,
|
||||
const unsigned char *m, size_t mlen,
|
||||
const hash_state *hash_state_seeded);
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,157 @@
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "address.h"
|
||||
#include "hash.h"
|
||||
#include "params.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include "sha2.h"
|
||||
#include "sha256.h"
|
||||
|
||||
/* For SHA256, there is no immediate reason to initialize at the start,
|
||||
so this function is an empty operation. */
|
||||
void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_initialize_hash_function(
|
||||
hash_state *hash_state_seeded,
|
||||
const unsigned char *pub_seed, const unsigned char *sk_seed) {
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_seed_state(hash_state_seeded, pub_seed);
|
||||
(void)sk_seed; /* Suppress an 'unused parameter' warning. */
|
||||
}
|
||||
|
||||
/*
|
||||
* Computes PRF(key, addr), given a secret key of SPX_N bytes and an address
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_prf_addr(
|
||||
unsigned char *out, const unsigned char *key, const uint32_t addr[8],
|
||||
const hash_state *hash_state_seeded) {
|
||||
unsigned char buf[SPX_N + SPX_SHA256_ADDR_BYTES];
|
||||
unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES];
|
||||
|
||||
memcpy(buf, key, SPX_N);
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_compress_address(buf + SPX_N, addr);
|
||||
|
||||
sha256(outbuf, buf, SPX_N + SPX_SHA256_ADDR_BYTES);
|
||||
memcpy(out, outbuf, SPX_N);
|
||||
|
||||
(void)hash_state_seeded; /* Prevent unused parameter warning. */
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the message-dependent randomness R, using a secret seed as a key
|
||||
* for HMAC, and an optional randomization value prefixed to the message.
|
||||
* This requires m to have at least SPX_SHA256_BLOCK_BYTES + SPX_N space
|
||||
* available in front of the pointer, i.e. before the message to use for the
|
||||
* prefix. This is necessary to prevent having to move the message around (and
|
||||
* allocate memory for it).
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_gen_message_random(
|
||||
unsigned char *R,
|
||||
const unsigned char *sk_prf, const unsigned char *optrand,
|
||||
const unsigned char *m, size_t mlen, const hash_state *hash_state_seeded) {
|
||||
unsigned char buf[SPX_SHA256_BLOCK_BYTES + SPX_SHA256_OUTPUT_BYTES];
|
||||
sha256ctx state;
|
||||
int i;
|
||||
|
||||
/* This implements HMAC-SHA256 */
|
||||
for (i = 0; i < SPX_N; i++) {
|
||||
buf[i] = 0x36 ^ sk_prf[i];
|
||||
}
|
||||
memset(buf + SPX_N, 0x36, SPX_SHA256_BLOCK_BYTES - SPX_N);
|
||||
|
||||
sha256_inc_init(&state);
|
||||
sha256_inc_blocks(&state, buf, 1);
|
||||
|
||||
memcpy(buf, optrand, SPX_N);
|
||||
|
||||
/* If optrand + message cannot fill up an entire block */
|
||||
if (SPX_N + mlen < SPX_SHA256_BLOCK_BYTES) {
|
||||
memcpy(buf + SPX_N, m, mlen);
|
||||
sha256_inc_finalize(buf + SPX_SHA256_BLOCK_BYTES, &state,
|
||||
buf, mlen + SPX_N);
|
||||
}
|
||||
/* Otherwise first fill a block, so that finalize only uses the message */
|
||||
else {
|
||||
memcpy(buf + SPX_N, m, SPX_SHA256_BLOCK_BYTES - SPX_N);
|
||||
sha256_inc_blocks(&state, buf, 1);
|
||||
|
||||
m += SPX_SHA256_BLOCK_BYTES - SPX_N;
|
||||
mlen -= SPX_SHA256_BLOCK_BYTES - SPX_N;
|
||||
sha256_inc_finalize(buf + SPX_SHA256_BLOCK_BYTES, &state, m, mlen);
|
||||
}
|
||||
|
||||
for (i = 0; i < SPX_N; i++) {
|
||||
buf[i] = 0x5c ^ sk_prf[i];
|
||||
}
|
||||
memset(buf + SPX_N, 0x5c, SPX_SHA256_BLOCK_BYTES - SPX_N);
|
||||
|
||||
sha256(buf, buf, SPX_SHA256_BLOCK_BYTES + SPX_SHA256_OUTPUT_BYTES);
|
||||
memcpy(R, buf, SPX_N);
|
||||
|
||||
(void)hash_state_seeded; /* Prevent unused parameter warning. */
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the message hash using R, the public key, and the message.
|
||||
* Outputs the message digest and the index of the leaf. The index is split in
|
||||
* the tree index and the leaf index, for convenient copying to an address.
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_hash_message(
|
||||
unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx,
|
||||
const unsigned char *R, const unsigned char *pk,
|
||||
const unsigned char *m, size_t mlen,
|
||||
const hash_state *hash_state_seeded) {
|
||||
#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1))
|
||||
#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8)
|
||||
#define SPX_LEAF_BITS SPX_TREE_HEIGHT
|
||||
#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8)
|
||||
#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES)
|
||||
|
||||
unsigned char seed[SPX_SHA256_OUTPUT_BYTES + 4];
|
||||
|
||||
/* Round to nearest multiple of SPX_SHA256_BLOCK_BYTES */
|
||||
#define SPX_INBLOCKS (((SPX_N + SPX_PK_BYTES + SPX_SHA256_BLOCK_BYTES - 1) & \
|
||||
-SPX_SHA256_BLOCK_BYTES) / SPX_SHA256_BLOCK_BYTES)
|
||||
unsigned char inbuf[SPX_INBLOCKS * SPX_SHA256_BLOCK_BYTES];
|
||||
|
||||
unsigned char buf[SPX_DGST_BYTES];
|
||||
unsigned char *bufp = buf;
|
||||
sha256ctx state;
|
||||
|
||||
sha256_inc_init(&state);
|
||||
|
||||
memcpy(inbuf, R, SPX_N);
|
||||
memcpy(inbuf + SPX_N, pk, SPX_PK_BYTES);
|
||||
|
||||
/* If R + pk + message cannot fill up an entire block */
|
||||
if (SPX_N + SPX_PK_BYTES + mlen < SPX_INBLOCKS * SPX_SHA256_BLOCK_BYTES) {
|
||||
memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, mlen);
|
||||
sha256_inc_finalize(seed, &state, inbuf, SPX_N + SPX_PK_BYTES + mlen);
|
||||
}
|
||||
/* Otherwise first fill a block, so that finalize only uses the message */
|
||||
else {
|
||||
memcpy(inbuf + SPX_N + SPX_PK_BYTES, m,
|
||||
SPX_INBLOCKS * SPX_SHA256_BLOCK_BYTES - SPX_N - SPX_PK_BYTES);
|
||||
sha256_inc_blocks(&state, inbuf, SPX_INBLOCKS);
|
||||
|
||||
m += SPX_INBLOCKS * SPX_SHA256_BLOCK_BYTES - SPX_N - SPX_PK_BYTES;
|
||||
mlen -= SPX_INBLOCKS * SPX_SHA256_BLOCK_BYTES - SPX_N - SPX_PK_BYTES;
|
||||
sha256_inc_finalize(seed, &state, m, mlen);
|
||||
}
|
||||
|
||||
/* By doing this in two steps, we prevent hashing the message twice;
|
||||
otherwise each iteration in MGF1 would hash the message again. */
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_mgf1(bufp, SPX_DGST_BYTES, seed, SPX_SHA256_OUTPUT_BYTES);
|
||||
|
||||
memcpy(digest, bufp, SPX_FORS_MSG_BYTES);
|
||||
bufp += SPX_FORS_MSG_BYTES;
|
||||
|
||||
*tree = PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_bytes_to_ull(bufp, SPX_TREE_BYTES);
|
||||
*tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS);
|
||||
bufp += SPX_TREE_BYTES;
|
||||
|
||||
*leaf_idx = (uint32_t)PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_bytes_to_ull(
|
||||
bufp, SPX_LEAF_BYTES);
|
||||
*leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS);
|
||||
|
||||
(void)hash_state_seeded; /* Prevent unused parameter warning. */
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
#ifndef SPX_PRIMITIVE_H
|
||||
#define SPX_PRIMITIVE_H
|
||||
|
||||
#include "sha2.h"
|
||||
#define hash_state sha256ctx
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,53 @@
|
||||
#ifndef SPX_PARAMS_H
|
||||
#define SPX_PARAMS_H
|
||||
|
||||
/* Hash output length in bytes. */
|
||||
#define SPX_N 16
|
||||
/* Height of the hypertree. */
|
||||
#define SPX_FULL_HEIGHT 60
|
||||
/* Number of subtree layer. */
|
||||
#define SPX_D 20
|
||||
/* FORS tree dimensions. */
|
||||
#define SPX_FORS_HEIGHT 9
|
||||
#define SPX_FORS_TREES 30
|
||||
/* Winternitz parameter, */
|
||||
#define SPX_WOTS_W 16
|
||||
|
||||
/* The hash function is defined by linking a different hash.c file, as opposed
|
||||
to setting a #define constant. */
|
||||
|
||||
/* For clarity */
|
||||
#define SPX_ADDR_BYTES 32
|
||||
|
||||
/* WOTS parameters. */
|
||||
#define SPX_WOTS_LOGW 4
|
||||
|
||||
#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW)
|
||||
|
||||
/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */
|
||||
#define SPX_WOTS_LEN2 3
|
||||
|
||||
#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2)
|
||||
#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N)
|
||||
#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES
|
||||
|
||||
/* Subtree size. */
|
||||
#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D)
|
||||
|
||||
/* FORS parameters. */
|
||||
#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8)
|
||||
#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N)
|
||||
#define SPX_FORS_PK_BYTES SPX_N
|
||||
|
||||
/* Resulting SPX sizes. */
|
||||
#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\
|
||||
SPX_FULL_HEIGHT * SPX_N)
|
||||
#define SPX_PK_BYTES (2 * SPX_N)
|
||||
#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES)
|
||||
|
||||
/* Optionally, signing can be made non-deterministic using optrand.
|
||||
This can help counter side-channel attacks that would benefit from
|
||||
getting a large number of traces when the signer uses the same nodes. */
|
||||
#define SPX_OPTRAND_BYTES 32
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,71 @@
|
||||
/* Based on the public domain implementation in
|
||||
* crypto_hash/sha512/ref/ from http://bench.cr.yp.to/supercop.html
|
||||
* by D. J. Bernstein */
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "sha2.h"
|
||||
#include "sha256.h"
|
||||
#include "utils.h"
|
||||
|
||||
/*
|
||||
* Compresses an address to a 22-byte sequence.
|
||||
* This reduces the number of required SHA256 compression calls, as the last
|
||||
* block of input is padded with at least 65 bits.
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_compress_address(unsigned char *out, const uint32_t addr[8]) {
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_ull_to_bytes(out, 1, addr[0]); /* drop 3 bytes of the layer field */
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_ull_to_bytes(out + 1, 4, addr[2]); /* drop the highest tree address word */
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_ull_to_bytes(out + 5, 4, addr[3]);
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_ull_to_bytes(out + 9, 1, addr[4]); /* drop 3 bytes of the type field */
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_ull_to_bytes(out + 10, 4, addr[5]);
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_ull_to_bytes(out + 14, 4, addr[6]);
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_ull_to_bytes(out + 18, 4, addr[7]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Requires 'input_plus_four_bytes' to have 'inlen' + 4 bytes, so that the last
|
||||
* four bytes can be used for the counter. Typically 'input' is merely a seed.
|
||||
* Outputs outlen number of bytes
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_mgf1(
|
||||
unsigned char *out, unsigned long outlen,
|
||||
unsigned char *input_plus_four_bytes, unsigned long inlen) {
|
||||
unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES];
|
||||
unsigned long i;
|
||||
|
||||
/* While we can fit in at least another full block of SHA256 output.. */
|
||||
for (i = 0; (i + 1)*SPX_SHA256_OUTPUT_BYTES <= outlen; i++) {
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_ull_to_bytes(input_plus_four_bytes + inlen, 4, i);
|
||||
sha256(out, input_plus_four_bytes, inlen + 4);
|
||||
out += SPX_SHA256_OUTPUT_BYTES;
|
||||
}
|
||||
/* Until we cannot anymore, and we fill the remainder. */
|
||||
if (outlen > i * SPX_SHA256_OUTPUT_BYTES) {
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_ull_to_bytes(input_plus_four_bytes + inlen, 4, i);
|
||||
sha256(outbuf, input_plus_four_bytes, inlen + 4);
|
||||
memcpy(out, outbuf, outlen - i * SPX_SHA256_OUTPUT_BYTES);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Absorb the constant pub_seed using one round of the compression function
|
||||
* This initializes hash_state_seeded, which can then be reused in thash
|
||||
**/
|
||||
void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_seed_state(sha256ctx *hash_state_seeded, const unsigned char *pub_seed) {
|
||||
uint8_t block[SPX_SHA256_BLOCK_BYTES];
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < SPX_N; ++i) {
|
||||
block[i] = pub_seed[i];
|
||||
}
|
||||
for (i = SPX_N; i < SPX_SHA256_BLOCK_BYTES; ++i) {
|
||||
block[i] = 0;
|
||||
}
|
||||
|
||||
sha256_inc_init(hash_state_seeded);
|
||||
sha256_inc_blocks(hash_state_seeded, block, 1);
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
#ifndef SPX_SHA256_H
|
||||
#define SPX_SHA256_H
|
||||
|
||||
#define SPX_SHA256_BLOCK_BYTES 64
|
||||
#define SPX_SHA256_OUTPUT_BYTES 32 /* This does not necessarily equal SPX_N */
|
||||
#define SPX_SHA256_ADDR_BYTES 22
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "sha2.h"
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_compress_address(unsigned char *out, const uint32_t addr[8]);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_mgf1(
|
||||
unsigned char *out, unsigned long outlen,
|
||||
unsigned char *input_plus_four_bytes, unsigned long inlen);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_seed_state(sha256ctx *hash_state_seeded, const unsigned char *pub_seed);
|
||||
|
||||
#endif
|
||||
353
src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/sign.c
Normal file
353
src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/sign.c
Normal file
@ -0,0 +1,353 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "address.h"
|
||||
#include "api.h"
|
||||
#include "fors.h"
|
||||
#include "hash.h"
|
||||
#include "params.h"
|
||||
#include "hash_state.h"
|
||||
#include "randombytes.h"
|
||||
#include "thash.h"
|
||||
#include "utils.h"
|
||||
#include "wots.h"
|
||||
|
||||
/**
|
||||
* Computes the leaf at a given address. First generates the WOTS key pair,
|
||||
* then computes leaf by hashing horizontally.
|
||||
*/
|
||||
static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed,
|
||||
const unsigned char *pub_seed,
|
||||
uint32_t addr_idx, const uint32_t tree_addr[8],
|
||||
const hash_state *hash_state_seeded) {
|
||||
unsigned char pk[SPX_WOTS_BYTES];
|
||||
uint32_t wots_addr[8] = {0};
|
||||
uint32_t wots_pk_addr[8] = {0};
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_type(
|
||||
wots_addr, SPX_ADDR_TYPE_WOTS);
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_type(
|
||||
wots_pk_addr, SPX_ADDR_TYPE_WOTSPK);
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_copy_subtree_addr(
|
||||
wots_addr, tree_addr);
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_keypair_addr(
|
||||
wots_addr, addr_idx);
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_wots_gen_pk(
|
||||
pk, sk_seed, pub_seed, wots_addr, hash_state_seeded);
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_copy_keypair_addr(
|
||||
wots_pk_addr, wots_addr);
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_thash_WOTS_LEN(
|
||||
leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the length of a secret key, in bytes
|
||||
*/
|
||||
size_t PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_crypto_sign_secretkeybytes(void) {
|
||||
return PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_CRYPTO_SECRETKEYBYTES;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the length of a public key, in bytes
|
||||
*/
|
||||
size_t PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_crypto_sign_publickeybytes(void) {
|
||||
return PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_CRYPTO_PUBLICKEYBYTES;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the length of a signature, in bytes
|
||||
*/
|
||||
size_t PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_crypto_sign_bytes(void) {
|
||||
return PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_CRYPTO_BYTES;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the length of the seed required to generate a key pair, in bytes
|
||||
*/
|
||||
size_t PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_crypto_sign_seedbytes(void) {
|
||||
return PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_CRYPTO_SEEDBYTES;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generates an SPX key pair given a seed of length
|
||||
* Format sk: [SK_SEED || SK_PRF || PUB_SEED || root]
|
||||
* Format pk: [PUB_SEED || root]
|
||||
*/
|
||||
int PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_crypto_sign_seed_keypair(
|
||||
uint8_t *pk, uint8_t *sk, const uint8_t *seed) {
|
||||
/* We do not need the auth path in key generation, but it simplifies the
|
||||
code to have just one treehash routine that computes both root and path
|
||||
in one function. */
|
||||
unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N];
|
||||
uint32_t top_tree_addr[8] = {0};
|
||||
hash_state hash_state_seeded;
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_layer_addr(
|
||||
top_tree_addr, SPX_D - 1);
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_type(
|
||||
top_tree_addr, SPX_ADDR_TYPE_HASHTREE);
|
||||
|
||||
/* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */
|
||||
memcpy(sk, seed, PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_CRYPTO_SEEDBYTES);
|
||||
|
||||
memcpy(pk, sk + 2 * SPX_N, SPX_N);
|
||||
|
||||
/* This hook allows the hash function instantiation to do whatever
|
||||
preparation or computation it needs, based on the public seed. */
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_initialize_hash_function(&hash_state_seeded, pk, sk);
|
||||
|
||||
/* Compute root node of the top-most subtree. */
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_treehash_TREE_HEIGHT(
|
||||
sk + 3 * SPX_N, auth_path, sk, sk + 2 * SPX_N, 0, 0,
|
||||
wots_gen_leaf, top_tree_addr, &hash_state_seeded);
|
||||
|
||||
memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generates an SPX key pair.
|
||||
* Format sk: [SK_SEED || SK_PRF || PUB_SEED || root]
|
||||
* Format pk: [PUB_SEED || root]
|
||||
*/
|
||||
int PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_crypto_sign_keypair(
|
||||
uint8_t *pk, uint8_t *sk) {
|
||||
unsigned char seed[PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_CRYPTO_SEEDBYTES];
|
||||
randombytes(seed, PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_CRYPTO_SEEDBYTES);
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_crypto_sign_seed_keypair(
|
||||
pk, sk, seed);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array containing a detached signature.
|
||||
*/
|
||||
int PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_crypto_sign_signature(
|
||||
uint8_t *sig, size_t *siglen,
|
||||
const uint8_t *m, size_t mlen, const uint8_t *sk) {
|
||||
const unsigned char *sk_seed = sk;
|
||||
const unsigned char *sk_prf = sk + SPX_N;
|
||||
const unsigned char *pk = sk + 2 * SPX_N;
|
||||
const unsigned char *pub_seed = pk;
|
||||
|
||||
unsigned char optrand[SPX_N];
|
||||
unsigned char mhash[SPX_FORS_MSG_BYTES];
|
||||
unsigned char root[SPX_N];
|
||||
uint32_t i;
|
||||
uint64_t tree;
|
||||
uint32_t idx_leaf;
|
||||
uint32_t wots_addr[8] = {0};
|
||||
uint32_t tree_addr[8] = {0};
|
||||
|
||||
hash_state hash_state_seeded;
|
||||
|
||||
/* This hook allows the hash function instantiation to do whatever
|
||||
preparation or computation it needs, based on the public seed. */
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_initialize_hash_function(
|
||||
&hash_state_seeded,
|
||||
pub_seed, sk_seed);
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_type(
|
||||
wots_addr, SPX_ADDR_TYPE_WOTS);
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_type(
|
||||
tree_addr, SPX_ADDR_TYPE_HASHTREE);
|
||||
|
||||
/* Optionally, signing can be made non-deterministic using optrand.
|
||||
This can help counter side-channel attacks that would benefit from
|
||||
getting a large number of traces when the signer uses the same nodes. */
|
||||
randombytes(optrand, SPX_N);
|
||||
/* Compute the digest randomization value. */
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_gen_message_random(
|
||||
sig, sk_prf, optrand, m, mlen, &hash_state_seeded);
|
||||
|
||||
/* Derive the message digest and leaf index from R, PK and M. */
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_hash_message(
|
||||
mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded);
|
||||
sig += SPX_N;
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_tree_addr(wots_addr, tree);
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_keypair_addr(
|
||||
wots_addr, idx_leaf);
|
||||
|
||||
/* Sign the message hash using FORS. */
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_fors_sign(
|
||||
sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded);
|
||||
sig += SPX_FORS_BYTES;
|
||||
|
||||
for (i = 0; i < SPX_D; i++) {
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_layer_addr(tree_addr, i);
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_tree_addr(tree_addr, tree);
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_copy_subtree_addr(
|
||||
wots_addr, tree_addr);
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_keypair_addr(
|
||||
wots_addr, idx_leaf);
|
||||
|
||||
/* Compute a WOTS signature. */
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_wots_sign(
|
||||
sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded);
|
||||
sig += SPX_WOTS_BYTES;
|
||||
|
||||
/* Compute the authentication path for the used WOTS leaf. */
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_treehash_TREE_HEIGHT(
|
||||
root, sig, sk_seed, pub_seed, idx_leaf, 0,
|
||||
wots_gen_leaf, tree_addr, &hash_state_seeded);
|
||||
sig += SPX_TREE_HEIGHT * SPX_N;
|
||||
|
||||
/* Update the indices for the next layer. */
|
||||
idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1));
|
||||
tree = tree >> SPX_TREE_HEIGHT;
|
||||
}
|
||||
|
||||
*siglen = SPX_BYTES;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies a detached signature and message under a given public key.
|
||||
*/
|
||||
int PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_crypto_sign_verify(
|
||||
const uint8_t *sig, size_t siglen,
|
||||
const uint8_t *m, size_t mlen, const uint8_t *pk) {
|
||||
const unsigned char *pub_seed = pk;
|
||||
const unsigned char *pub_root = pk + SPX_N;
|
||||
unsigned char mhash[SPX_FORS_MSG_BYTES];
|
||||
unsigned char wots_pk[SPX_WOTS_BYTES];
|
||||
unsigned char root[SPX_N];
|
||||
unsigned char leaf[SPX_N];
|
||||
unsigned int i;
|
||||
uint64_t tree;
|
||||
uint32_t idx_leaf;
|
||||
uint32_t wots_addr[8] = {0};
|
||||
uint32_t tree_addr[8] = {0};
|
||||
uint32_t wots_pk_addr[8] = {0};
|
||||
|
||||
hash_state hash_state_seeded;
|
||||
|
||||
if (siglen != SPX_BYTES) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* This hook allows the hash function instantiation to do whatever
|
||||
preparation or computation it needs, based on the public seed. */
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_initialize_hash_function(
|
||||
&hash_state_seeded,
|
||||
pub_seed, NULL);
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_type(
|
||||
wots_addr, SPX_ADDR_TYPE_WOTS);
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_type(
|
||||
tree_addr, SPX_ADDR_TYPE_HASHTREE);
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_type(
|
||||
wots_pk_addr, SPX_ADDR_TYPE_WOTSPK);
|
||||
|
||||
/* Derive the message digest and leaf index from R || PK || M. */
|
||||
/* The additional SPX_N is a result of the hash domain separator. */
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_hash_message(
|
||||
mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded);
|
||||
sig += SPX_N;
|
||||
|
||||
/* Layer correctly defaults to 0, so no need to set_layer_addr */
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_tree_addr(wots_addr, tree);
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_keypair_addr(
|
||||
wots_addr, idx_leaf);
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_fors_pk_from_sig(
|
||||
root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded);
|
||||
sig += SPX_FORS_BYTES;
|
||||
|
||||
/* For each subtree.. */
|
||||
for (i = 0; i < SPX_D; i++) {
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_layer_addr(tree_addr, i);
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_tree_addr(tree_addr, tree);
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_copy_subtree_addr(
|
||||
wots_addr, tree_addr);
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_keypair_addr(
|
||||
wots_addr, idx_leaf);
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_copy_keypair_addr(
|
||||
wots_pk_addr, wots_addr);
|
||||
|
||||
/* The WOTS public key is only correct if the signature was correct. */
|
||||
/* Initially, root is the FORS pk, but on subsequent iterations it is
|
||||
the root of the subtree below the currently processed subtree. */
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_wots_pk_from_sig(
|
||||
wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded);
|
||||
sig += SPX_WOTS_BYTES;
|
||||
|
||||
/* Compute the leaf node using the WOTS public key. */
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_thash_WOTS_LEN(
|
||||
leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded);
|
||||
|
||||
/* Compute the root node of this subtree. */
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_compute_root(
|
||||
root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT,
|
||||
pub_seed, tree_addr, &hash_state_seeded);
|
||||
sig += SPX_TREE_HEIGHT * SPX_N;
|
||||
|
||||
/* Update the indices for the next layer. */
|
||||
idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1));
|
||||
tree = tree >> SPX_TREE_HEIGHT;
|
||||
}
|
||||
|
||||
/* Check if the root node equals the root node in the public key. */
|
||||
if (memcmp(root, pub_root, SPX_N) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns an array containing the signature followed by the message.
|
||||
*/
|
||||
int PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_crypto_sign(
|
||||
uint8_t *sm, size_t *smlen,
|
||||
const uint8_t *m, size_t mlen, const uint8_t *sk) {
|
||||
size_t siglen;
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_crypto_sign_signature(
|
||||
sm, &siglen, m, mlen, sk);
|
||||
|
||||
memmove(sm + SPX_BYTES, m, mlen);
|
||||
*smlen = siglen + mlen;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies a given signature-message pair under a given public key.
|
||||
*/
|
||||
int PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_crypto_sign_open(
|
||||
uint8_t *m, size_t *mlen,
|
||||
const uint8_t *sm, size_t smlen, const uint8_t *pk) {
|
||||
/* The API caller does not necessarily know what size a signature should be
|
||||
but SPHINCS+ signatures are always exactly SPX_BYTES. */
|
||||
if (smlen < SPX_BYTES) {
|
||||
memset(m, 0, smlen);
|
||||
*mlen = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
*mlen = smlen - SPX_BYTES;
|
||||
|
||||
if (PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_crypto_sign_verify(
|
||||
sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) {
|
||||
memset(m, 0, smlen);
|
||||
*mlen = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* If verification was successful, move the message to the right place. */
|
||||
memmove(m, sm + SPX_BYTES, *mlen);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
#ifndef SPX_THASH_H
|
||||
#define SPX_THASH_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "hash_state.h"
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_thash_1(
|
||||
unsigned char *out, const unsigned char *in,
|
||||
const unsigned char *pub_seed, uint32_t addr[8],
|
||||
const hash_state *hash_state_seeded);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_thash_2(
|
||||
unsigned char *out, const unsigned char *in,
|
||||
const unsigned char *pub_seed, uint32_t addr[8],
|
||||
const hash_state *hash_state_seeded);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_thash_WOTS_LEN(
|
||||
unsigned char *out, const unsigned char *in,
|
||||
const unsigned char *pub_seed, uint32_t addr[8],
|
||||
const hash_state *hash_state_seeded);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_thash_FORS_TREES(
|
||||
unsigned char *out, const unsigned char *in,
|
||||
const unsigned char *pub_seed, uint32_t addr[8],
|
||||
const hash_state *hash_state_seeded);
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,82 @@
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "address.h"
|
||||
#include "params.h"
|
||||
#include "thash.h"
|
||||
|
||||
#include "sha2.h"
|
||||
#include "sha256.h"
|
||||
|
||||
/**
|
||||
* Takes an array of inblocks concatenated arrays of SPX_N bytes.
|
||||
*/
|
||||
static void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_thash(
|
||||
unsigned char *out, unsigned char *buf,
|
||||
const unsigned char *in, unsigned int inblocks,
|
||||
const unsigned char *pub_seed, uint32_t addr[8],
|
||||
const sha256ctx *hash_state_seeded) {
|
||||
|
||||
unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES];
|
||||
unsigned char *bitmask = buf + SPX_N + SPX_SHA256_ADDR_BYTES + 4;
|
||||
sha256ctx sha2_state;
|
||||
unsigned int i;
|
||||
|
||||
memcpy(buf, pub_seed, SPX_N);
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_compress_address(buf + SPX_N, addr);
|
||||
/* MGF1 requires us to have 4 extra bytes in 'buf' */
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_mgf1(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_SHA256_ADDR_BYTES);
|
||||
|
||||
/* Retrieve precomputed state containing pub_seed */
|
||||
sha256_inc_dupe_state(&sha2_state, hash_state_seeded);
|
||||
|
||||
for (i = 0; i < inblocks * SPX_N; i++) {
|
||||
buf[SPX_N + SPX_SHA256_ADDR_BYTES + i] = in[i] ^ bitmask[i];
|
||||
}
|
||||
|
||||
sha256_inc_finalize(outbuf, &sha2_state, buf + SPX_N,
|
||||
SPX_SHA256_ADDR_BYTES + inblocks * SPX_N);
|
||||
memcpy(out, outbuf, SPX_N);
|
||||
}
|
||||
|
||||
/* The wrappers below ensure that we use fixed-size buffers on the stack */
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_thash_1(
|
||||
unsigned char *out, const unsigned char *in,
|
||||
const unsigned char *pub_seed, uint32_t addr[8],
|
||||
const sha256ctx *hash_state_seeded) {
|
||||
|
||||
unsigned char buf[SPX_N + SPX_SHA256_ADDR_BYTES + 4 + 1 * SPX_N];
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_thash(
|
||||
out, buf, in, 1, pub_seed, addr, hash_state_seeded);
|
||||
}
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_thash_2(
|
||||
unsigned char *out, const unsigned char *in,
|
||||
const unsigned char *pub_seed, uint32_t addr[8],
|
||||
const sha256ctx *hash_state_seeded) {
|
||||
|
||||
unsigned char buf[SPX_N + SPX_SHA256_ADDR_BYTES + 4 + 2 * SPX_N];
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_thash(
|
||||
out, buf, in, 2, pub_seed, addr, hash_state_seeded);
|
||||
}
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_thash_WOTS_LEN(
|
||||
unsigned char *out, const unsigned char *in,
|
||||
const unsigned char *pub_seed, uint32_t addr[8],
|
||||
const sha256ctx *hash_state_seeded) {
|
||||
|
||||
unsigned char buf[SPX_N + SPX_SHA256_ADDR_BYTES + 4 + SPX_WOTS_LEN * SPX_N];
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_thash(
|
||||
out, buf, in, SPX_WOTS_LEN, pub_seed, addr, hash_state_seeded);
|
||||
}
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_thash_FORS_TREES(
|
||||
unsigned char *out, const unsigned char *in,
|
||||
const unsigned char *pub_seed, uint32_t addr[8],
|
||||
const sha256ctx *hash_state_seeded) {
|
||||
|
||||
unsigned char buf[SPX_N + SPX_SHA256_ADDR_BYTES + 4 + SPX_FORS_TREES * SPX_N];
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_thash(
|
||||
out, buf, in, SPX_FORS_TREES, pub_seed, addr, hash_state_seeded);
|
||||
}
|
||||
199
src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/utils.c
Normal file
199
src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/utils.c
Normal file
@ -0,0 +1,199 @@
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "address.h"
|
||||
#include "hash.h"
|
||||
#include "params.h"
|
||||
#include "hash_state.h"
|
||||
#include "thash.h"
|
||||
#include "utils.h"
|
||||
|
||||
/**
|
||||
* Converts the value of 'in' to 'outlen' bytes in big-endian byte order.
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_ull_to_bytes(
|
||||
unsigned char *out, size_t outlen, unsigned long long in) {
|
||||
|
||||
/* Iterate over out in decreasing order, for big-endianness. */
|
||||
for (size_t i = outlen; i > 0; i--) {
|
||||
out[i - 1] = in & 0xff;
|
||||
in = in >> 8;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the inlen bytes in 'in' from big-endian byte order to an integer.
|
||||
*/
|
||||
unsigned long long PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_bytes_to_ull(
|
||||
const unsigned char *in, size_t inlen) {
|
||||
unsigned long long retval = 0;
|
||||
|
||||
for (size_t i = 0; i < inlen; i++) {
|
||||
retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i));
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes a root node given a leaf and an auth path.
|
||||
* Expects address to be complete other than the tree_height and tree_index.
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_compute_root(
|
||||
unsigned char *root, const unsigned char *leaf,
|
||||
uint32_t leaf_idx, uint32_t idx_offset,
|
||||
const unsigned char *auth_path, uint32_t tree_height,
|
||||
const unsigned char *pub_seed, uint32_t addr[8],
|
||||
const hash_state *hash_state_seeded) {
|
||||
uint32_t i;
|
||||
unsigned char buffer[2 * SPX_N];
|
||||
|
||||
/* If leaf_idx is odd (last bit = 1), current path element is a right child
|
||||
and auth_path has to go left. Otherwise it is the other way around. */
|
||||
if (leaf_idx & 1) {
|
||||
memcpy(buffer + SPX_N, leaf, SPX_N);
|
||||
memcpy(buffer, auth_path, SPX_N);
|
||||
} else {
|
||||
memcpy(buffer, leaf, SPX_N);
|
||||
memcpy(buffer + SPX_N, auth_path, SPX_N);
|
||||
}
|
||||
auth_path += SPX_N;
|
||||
|
||||
for (i = 0; i < tree_height - 1; i++) {
|
||||
leaf_idx >>= 1;
|
||||
idx_offset >>= 1;
|
||||
/* Set the address of the node we're creating. */
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_tree_height(addr, i + 1);
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_tree_index(
|
||||
addr, leaf_idx + idx_offset);
|
||||
|
||||
/* Pick the right or left neighbor, depending on parity of the node. */
|
||||
if (leaf_idx & 1) {
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_thash_2(
|
||||
buffer + SPX_N, buffer, pub_seed, addr, hash_state_seeded);
|
||||
memcpy(buffer, auth_path, SPX_N);
|
||||
} else {
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_thash_2(
|
||||
buffer, buffer, pub_seed, addr, hash_state_seeded);
|
||||
memcpy(buffer + SPX_N, auth_path, SPX_N);
|
||||
}
|
||||
auth_path += SPX_N;
|
||||
}
|
||||
|
||||
/* The last iteration is exceptional; we do not copy an auth_path node. */
|
||||
leaf_idx >>= 1;
|
||||
idx_offset >>= 1;
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_tree_height(addr, tree_height);
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_tree_index(
|
||||
addr, leaf_idx + idx_offset);
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_thash_2(
|
||||
root, buffer, pub_seed, addr, hash_state_seeded);
|
||||
}
|
||||
|
||||
/**
|
||||
* For a given leaf index, computes the authentication path and the resulting
|
||||
* root node using Merkle's TreeHash algorithm.
|
||||
* Expects the layer and tree parts of the tree_addr to be set, as well as the
|
||||
* tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE).
|
||||
* Applies the offset idx_offset to indices before building addresses, so that
|
||||
* it is possible to continue counting indices across trees.
|
||||
*/
|
||||
static void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_treehash(
|
||||
unsigned char *root, unsigned char *auth_path,
|
||||
unsigned char *stack, unsigned int *heights,
|
||||
const unsigned char *sk_seed, const unsigned char *pub_seed,
|
||||
uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height,
|
||||
void (*gen_leaf)(
|
||||
unsigned char * /* leaf */,
|
||||
const unsigned char * /* sk_seed */,
|
||||
const unsigned char * /* pub_seed */,
|
||||
uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */,
|
||||
const hash_state * /* hash_state_seeded */),
|
||||
uint32_t tree_addr[8],
|
||||
const hash_state *hash_state_seeded) {
|
||||
|
||||
unsigned int offset = 0;
|
||||
uint32_t idx;
|
||||
uint32_t tree_idx;
|
||||
|
||||
for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) {
|
||||
/* Add the next leaf node to the stack. */
|
||||
gen_leaf(stack + offset * SPX_N,
|
||||
sk_seed, pub_seed, idx + idx_offset, tree_addr,
|
||||
hash_state_seeded);
|
||||
offset++;
|
||||
heights[offset - 1] = 0;
|
||||
|
||||
/* If this is a node we need for the auth path.. */
|
||||
if ((leaf_idx ^ 0x1) == idx) {
|
||||
memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N);
|
||||
}
|
||||
|
||||
/* While the top-most nodes are of equal height.. */
|
||||
while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) {
|
||||
/* Compute index of the new node, in the next layer. */
|
||||
tree_idx = (idx >> (heights[offset - 1] + 1));
|
||||
|
||||
/* Set the address of the node we're creating. */
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_tree_height(
|
||||
tree_addr, heights[offset - 1] + 1);
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_tree_index(
|
||||
tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1)));
|
||||
/* Hash the top-most nodes from the stack together. */
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_thash_2(
|
||||
stack + (offset - 2)*SPX_N, stack + (offset - 2)*SPX_N,
|
||||
pub_seed, tree_addr, hash_state_seeded);
|
||||
offset--;
|
||||
/* Note that the top-most node is now one layer higher. */
|
||||
heights[offset - 1]++;
|
||||
|
||||
/* If this is a node we need for the auth path.. */
|
||||
if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) {
|
||||
memcpy(auth_path + heights[offset - 1]*SPX_N,
|
||||
stack + (offset - 1)*SPX_N, SPX_N);
|
||||
}
|
||||
}
|
||||
}
|
||||
memcpy(root, stack, SPX_N);
|
||||
}
|
||||
|
||||
/* The wrappers below ensure that we use fixed-size buffers on the stack */
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_treehash_FORS_HEIGHT(
|
||||
unsigned char *root, unsigned char *auth_path,
|
||||
const unsigned char *sk_seed, const unsigned char *pub_seed,
|
||||
uint32_t leaf_idx, uint32_t idx_offset,
|
||||
void (*gen_leaf)(
|
||||
unsigned char * /* leaf */,
|
||||
const unsigned char * /* sk_seed */,
|
||||
const unsigned char * /* pub_seed */,
|
||||
uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */,
|
||||
const hash_state * /* hash_state_seeded */),
|
||||
uint32_t tree_addr[8], const hash_state *hash_state_seeded) {
|
||||
|
||||
unsigned char stack[(SPX_FORS_HEIGHT + 1)*SPX_N];
|
||||
unsigned int heights[SPX_FORS_HEIGHT + 1];
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_treehash(
|
||||
root, auth_path, stack, heights, sk_seed, pub_seed,
|
||||
leaf_idx, idx_offset, SPX_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded);
|
||||
}
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_treehash_TREE_HEIGHT(
|
||||
unsigned char *root, unsigned char *auth_path,
|
||||
const unsigned char *sk_seed, const unsigned char *pub_seed,
|
||||
uint32_t leaf_idx, uint32_t idx_offset,
|
||||
void (*gen_leaf)(
|
||||
unsigned char * /* leaf */,
|
||||
const unsigned char * /* sk_seed */,
|
||||
const unsigned char * /* pub_seed */,
|
||||
uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */,
|
||||
const hash_state * /* hash_state_seeded */),
|
||||
uint32_t tree_addr[8], const hash_state *hash_state_seeded) {
|
||||
|
||||
unsigned char stack[(SPX_TREE_HEIGHT + 1)*SPX_N];
|
||||
unsigned int heights[SPX_TREE_HEIGHT + 1];
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_treehash(
|
||||
root, auth_path, stack, heights, sk_seed, pub_seed,
|
||||
leaf_idx, idx_offset, SPX_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded);
|
||||
}
|
||||
@ -0,0 +1,64 @@
|
||||
#ifndef SPX_UTILS_H
|
||||
#define SPX_UTILS_H
|
||||
|
||||
#include "params.h"
|
||||
#include "hash_state.h"
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* Converts the value of 'in' to 'outlen' bytes in big-endian byte order.
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_ull_to_bytes(
|
||||
unsigned char *out, size_t outlen, unsigned long long in);
|
||||
|
||||
/**
|
||||
* Converts the inlen bytes in 'in' from big-endian byte order to an integer.
|
||||
*/
|
||||
unsigned long long PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_bytes_to_ull(
|
||||
const unsigned char *in, size_t inlen);
|
||||
|
||||
/**
|
||||
* Computes a root node given a leaf and an auth path.
|
||||
* Expects address to be complete other than the tree_height and tree_index.
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_compute_root(
|
||||
unsigned char *root, const unsigned char *leaf,
|
||||
uint32_t leaf_idx, uint32_t idx_offset,
|
||||
const unsigned char *auth_path, uint32_t tree_height,
|
||||
const unsigned char *pub_seed, uint32_t addr[8],
|
||||
const hash_state *hash_state_seeded);
|
||||
|
||||
/**
|
||||
* For a given leaf index, computes the authentication path and the resulting
|
||||
* root node using Merkle's TreeHash algorithm.
|
||||
* Expects the layer and tree parts of the tree_addr to be set, as well as the
|
||||
* tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE).
|
||||
* Applies the offset idx_offset to indices before building addresses, so that
|
||||
* it is possible to continue counting indices across trees.
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_treehash_FORS_HEIGHT(
|
||||
unsigned char *root, unsigned char *auth_path,
|
||||
const unsigned char *sk_seed, const unsigned char *pub_seed,
|
||||
uint32_t leaf_idx, uint32_t idx_offset,
|
||||
void (*gen_leaf)(
|
||||
unsigned char * /* leaf */,
|
||||
const unsigned char * /* sk_seed */,
|
||||
const unsigned char * /* pub_seed */,
|
||||
uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */,
|
||||
const hash_state * /* hash_state_seeded */),
|
||||
uint32_t tree_addr[8], const hash_state *hash_state_seeded);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_treehash_TREE_HEIGHT(
|
||||
unsigned char *root, unsigned char *auth_path,
|
||||
const unsigned char *sk_seed, const unsigned char *pub_seed,
|
||||
uint32_t leaf_idx, uint32_t idx_offset,
|
||||
void (*gen_leaf)(
|
||||
unsigned char * /* leaf */,
|
||||
const unsigned char * /* sk_seed */,
|
||||
const unsigned char * /* pub_seed */,
|
||||
uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */,
|
||||
const hash_state * /* hash_state_seeded */),
|
||||
uint32_t tree_addr[8], const hash_state *hash_state_seeded);
|
||||
|
||||
#endif
|
||||
167
src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/wots.c
Normal file
167
src/sig/sphincs/pqclean_sphincs-sha256-128f-robust_clean/wots.c
Normal file
@ -0,0 +1,167 @@
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "address.h"
|
||||
#include "hash.h"
|
||||
#include "params.h"
|
||||
#include "hash_state.h"
|
||||
#include "thash.h"
|
||||
#include "utils.h"
|
||||
#include "wots.h"
|
||||
|
||||
// TODO clarify address expectations, and make them more uniform.
|
||||
// TODO i.e. do we expect types to be set already?
|
||||
// TODO and do we expect modifications or copies?
|
||||
|
||||
/**
|
||||
* Computes the starting value for a chain, i.e. the secret key.
|
||||
* Expects the address to be complete up to the chain address.
|
||||
*/
|
||||
static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed,
|
||||
uint32_t wots_addr[8],
|
||||
const hash_state *hash_state_seeded) {
|
||||
/* Make sure that the hash address is actually zeroed. */
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_hash_addr(wots_addr, 0);
|
||||
|
||||
/* Generate sk element. */
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_prf_addr(sk, sk_seed, wots_addr, hash_state_seeded);
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the chaining function.
|
||||
* out and in have to be n-byte arrays.
|
||||
*
|
||||
* Interprets in as start-th value of the chain.
|
||||
* addr has to contain the address of the chain.
|
||||
*/
|
||||
static void gen_chain(unsigned char *out, const unsigned char *in,
|
||||
unsigned int start, unsigned int steps,
|
||||
const unsigned char *pub_seed, uint32_t addr[8],
|
||||
const hash_state *hash_state_seeded) {
|
||||
uint32_t i;
|
||||
|
||||
/* Initialize out with the value at position 'start'. */
|
||||
memcpy(out, in, SPX_N);
|
||||
|
||||
/* Iterate 'steps' calls to the hash function. */
|
||||
for (i = start; i < (start + steps) && i < SPX_WOTS_W; i++) {
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_hash_addr(addr, i);
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_thash_1(
|
||||
out, out, pub_seed, addr, hash_state_seeded);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* base_w algorithm as described in draft.
|
||||
* Interprets an array of bytes as integers in base w.
|
||||
* This only works when log_w is a divisor of 8.
|
||||
*/
|
||||
static void base_w(unsigned int *output, const size_t out_len,
|
||||
const unsigned char *input) {
|
||||
size_t in = 0;
|
||||
size_t out = 0;
|
||||
unsigned char total = 0;
|
||||
unsigned int bits = 0;
|
||||
size_t consumed;
|
||||
|
||||
for (consumed = 0; consumed < out_len; consumed++) {
|
||||
if (bits == 0) {
|
||||
total = input[in];
|
||||
in++;
|
||||
bits += 8;
|
||||
}
|
||||
bits -= SPX_WOTS_LOGW;
|
||||
output[out] = (unsigned int)((total >> bits) & (SPX_WOTS_W - 1));
|
||||
out++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Computes the WOTS+ checksum over a message (in base_w). */
|
||||
static void wots_checksum(unsigned int *csum_base_w,
|
||||
const unsigned int *msg_base_w) {
|
||||
unsigned int csum = 0;
|
||||
unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8];
|
||||
unsigned int i;
|
||||
|
||||
/* Compute checksum. */
|
||||
for (i = 0; i < SPX_WOTS_LEN1; i++) {
|
||||
csum += SPX_WOTS_W - 1 - msg_base_w[i];
|
||||
}
|
||||
|
||||
/* Convert checksum to base_w. */
|
||||
/* Make sure expected empty zero bits are the least significant bits. */
|
||||
csum = csum << (8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8));
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_ull_to_bytes(
|
||||
csum_bytes, sizeof(csum_bytes), csum);
|
||||
base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes);
|
||||
}
|
||||
|
||||
/* Takes a message and derives the matching chain lengths. */
|
||||
static void chain_lengths(unsigned int *lengths, const unsigned char *msg) {
|
||||
base_w(lengths, SPX_WOTS_LEN1, msg);
|
||||
wots_checksum(lengths + SPX_WOTS_LEN1, lengths);
|
||||
}
|
||||
|
||||
/**
|
||||
* WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key
|
||||
* elements and computes the corresponding public key.
|
||||
* It requires the seed pub_seed (used to generate bitmasks and hash keys)
|
||||
* and the address of this WOTS key pair.
|
||||
*
|
||||
* Writes the computed public key to 'pk'.
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_wots_gen_pk(
|
||||
unsigned char *pk, const unsigned char *sk_seed,
|
||||
const unsigned char *pub_seed, uint32_t addr[8],
|
||||
const hash_state *hash_state_seeded) {
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < SPX_WOTS_LEN; i++) {
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_chain_addr(addr, i);
|
||||
wots_gen_sk(pk + i * SPX_N, sk_seed, addr, hash_state_seeded);
|
||||
gen_chain(pk + i * SPX_N, pk + i * SPX_N,
|
||||
0, SPX_WOTS_W - 1, pub_seed, addr, hash_state_seeded);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'.
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_wots_sign(
|
||||
unsigned char *sig, const unsigned char *msg,
|
||||
const unsigned char *sk_seed, const unsigned char *pub_seed,
|
||||
uint32_t addr[8], const hash_state *hash_state_seeded) {
|
||||
unsigned int lengths[SPX_WOTS_LEN];
|
||||
uint32_t i;
|
||||
|
||||
chain_lengths(lengths, msg);
|
||||
|
||||
for (i = 0; i < SPX_WOTS_LEN; i++) {
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_chain_addr(addr, i);
|
||||
wots_gen_sk(sig + i * SPX_N, sk_seed, addr, hash_state_seeded);
|
||||
gen_chain(sig + i * SPX_N, sig + i * SPX_N, 0, lengths[i], pub_seed, addr, hash_state_seeded);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes a WOTS signature and an n-byte message, computes a WOTS public key.
|
||||
*
|
||||
* Writes the computed public key to 'pk'.
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_wots_pk_from_sig(
|
||||
unsigned char *pk,
|
||||
const unsigned char *sig, const unsigned char *msg,
|
||||
const unsigned char *pub_seed, uint32_t addr[8],
|
||||
const hash_state *hash_state_seeded) {
|
||||
unsigned int lengths[SPX_WOTS_LEN];
|
||||
uint32_t i;
|
||||
|
||||
chain_lengths(lengths, msg);
|
||||
|
||||
for (i = 0; i < SPX_WOTS_LEN; i++) {
|
||||
PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_set_chain_addr(addr, i);
|
||||
gen_chain(pk + i * SPX_N, sig + i * SPX_N,
|
||||
lengths[i], SPX_WOTS_W - 1 - lengths[i], pub_seed, addr,
|
||||
hash_state_seeded);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,41 @@
|
||||
#ifndef SPX_WOTS_H
|
||||
#define SPX_WOTS_H
|
||||
|
||||
#include "params.h"
|
||||
#include "hash_state.h"
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* WOTS key generation. Takes a 32 byte seed for the private key, expands it to
|
||||
* a full WOTS private key and computes the corresponding public key.
|
||||
* It requires the seed pub_seed (used to generate bitmasks and hash keys)
|
||||
* and the address of this WOTS key pair.
|
||||
*
|
||||
* Writes the computed public key to 'pk'.
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_wots_gen_pk(
|
||||
unsigned char *pk, const unsigned char *sk_seed,
|
||||
const unsigned char *pub_seed, uint32_t addr[8],
|
||||
const hash_state *hash_state_seeded);
|
||||
|
||||
/**
|
||||
* Takes a n-byte message and the 32-byte seed for the private key to compute a
|
||||
* signature that is placed at 'sig'.
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_wots_sign(
|
||||
unsigned char *sig, const unsigned char *msg,
|
||||
const unsigned char *sk_seed, const unsigned char *pub_seed,
|
||||
uint32_t addr[8], const hash_state *hash_state_seeded);
|
||||
|
||||
/**
|
||||
* Takes a WOTS signature and an n-byte message, computes a WOTS public key.
|
||||
*
|
||||
* Writes the computed public key to 'pk'.
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_wots_pk_from_sig(
|
||||
unsigned char *pk,
|
||||
const unsigned char *sig, const unsigned char *msg,
|
||||
const unsigned char *pub_seed, uint32_t addr[8],
|
||||
const hash_state *hash_state_seeded);
|
||||
|
||||
#endif
|
||||
116
src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/LICENSE
Normal file
116
src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/LICENSE
Normal file
@ -0,0 +1,116 @@
|
||||
CC0 1.0 Universal
|
||||
|
||||
Statement of Purpose
|
||||
|
||||
The laws of most jurisdictions throughout the world automatically confer
|
||||
exclusive Copyright and Related Rights (defined below) upon the creator and
|
||||
subsequent owner(s) (each and all, an "owner") of an original work of
|
||||
authorship and/or a database (each, a "Work").
|
||||
|
||||
Certain owners wish to permanently relinquish those rights to a Work for the
|
||||
purpose of contributing to a commons of creative, cultural and scientific
|
||||
works ("Commons") that the public can reliably and without fear of later
|
||||
claims of infringement build upon, modify, incorporate in other works, reuse
|
||||
and redistribute as freely as possible in any form whatsoever and for any
|
||||
purposes, including without limitation commercial purposes. These owners may
|
||||
contribute to the Commons to promote the ideal of a free culture and the
|
||||
further production of creative, cultural and scientific works, or to gain
|
||||
reputation or greater distribution for their Work in part through the use and
|
||||
efforts of others.
|
||||
|
||||
For these and/or other purposes and motivations, and without any expectation
|
||||
of additional consideration or compensation, the person associating CC0 with a
|
||||
Work (the "Affirmer"), to the extent that he or she is an owner of Copyright
|
||||
and Related Rights in the Work, voluntarily elects to apply CC0 to the Work
|
||||
and publicly distribute the Work under its terms, with knowledge of his or her
|
||||
Copyright and Related Rights in the Work and the meaning and intended legal
|
||||
effect of CC0 on those rights.
|
||||
|
||||
1. Copyright and Related Rights. A Work made available under CC0 may be
|
||||
protected by copyright and related or neighboring rights ("Copyright and
|
||||
Related Rights"). Copyright and Related Rights include, but are not limited
|
||||
to, the following:
|
||||
|
||||
i. the right to reproduce, adapt, distribute, perform, display, communicate,
|
||||
and translate a Work;
|
||||
|
||||
ii. moral rights retained by the original author(s) and/or performer(s);
|
||||
|
||||
iii. publicity and privacy rights pertaining to a person's image or likeness
|
||||
depicted in a Work;
|
||||
|
||||
iv. rights protecting against unfair competition in regards to a Work,
|
||||
subject to the limitations in paragraph 4(a), below;
|
||||
|
||||
v. rights protecting the extraction, dissemination, use and reuse of data in
|
||||
a Work;
|
||||
|
||||
vi. database rights (such as those arising under Directive 96/9/EC of the
|
||||
European Parliament and of the Council of 11 March 1996 on the legal
|
||||
protection of databases, and under any national implementation thereof,
|
||||
including any amended or successor version of such directive); and
|
||||
|
||||
vii. other similar, equivalent or corresponding rights throughout the world
|
||||
based on applicable law or treaty, and any national implementations thereof.
|
||||
|
||||
2. Waiver. To the greatest extent permitted by, but not in contravention of,
|
||||
applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and
|
||||
unconditionally waives, abandons, and surrenders all of Affirmer's Copyright
|
||||
and Related Rights and associated claims and causes of action, whether now
|
||||
known or unknown (including existing as well as future claims and causes of
|
||||
action), in the Work (i) in all territories worldwide, (ii) for the maximum
|
||||
duration provided by applicable law or treaty (including future time
|
||||
extensions), (iii) in any current or future medium and for any number of
|
||||
copies, and (iv) for any purpose whatsoever, including without limitation
|
||||
commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes
|
||||
the Waiver for the benefit of each member of the public at large and to the
|
||||
detriment of Affirmer's heirs and successors, fully intending that such Waiver
|
||||
shall not be subject to revocation, rescission, cancellation, termination, or
|
||||
any other legal or equitable action to disrupt the quiet enjoyment of the Work
|
||||
by the public as contemplated by Affirmer's express Statement of Purpose.
|
||||
|
||||
3. Public License Fallback. Should any part of the Waiver for any reason be
|
||||
judged legally invalid or ineffective under applicable law, then the Waiver
|
||||
shall be preserved to the maximum extent permitted taking into account
|
||||
Affirmer's express Statement of Purpose. In addition, to the extent the Waiver
|
||||
is so judged Affirmer hereby grants to each affected person a royalty-free,
|
||||
non transferable, non sublicensable, non exclusive, irrevocable and
|
||||
unconditional license to exercise Affirmer's Copyright and Related Rights in
|
||||
the Work (i) in all territories worldwide, (ii) for the maximum duration
|
||||
provided by applicable law or treaty (including future time extensions), (iii)
|
||||
in any current or future medium and for any number of copies, and (iv) for any
|
||||
purpose whatsoever, including without limitation commercial, advertising or
|
||||
promotional purposes (the "License"). The License shall be deemed effective as
|
||||
of the date CC0 was applied by Affirmer to the Work. Should any part of the
|
||||
License for any reason be judged legally invalid or ineffective under
|
||||
applicable law, such partial invalidity or ineffectiveness shall not
|
||||
invalidate the remainder of the License, and in such case Affirmer hereby
|
||||
affirms that he or she will not (i) exercise any of his or her remaining
|
||||
Copyright and Related Rights in the Work or (ii) assert any associated claims
|
||||
and causes of action with respect to the Work, in either case contrary to
|
||||
Affirmer's express Statement of Purpose.
|
||||
|
||||
4. Limitations and Disclaimers.
|
||||
|
||||
a. No trademark or patent rights held by Affirmer are waived, abandoned,
|
||||
surrendered, licensed or otherwise affected by this document.
|
||||
|
||||
b. Affirmer offers the Work as-is and makes no representations or warranties
|
||||
of any kind concerning the Work, express, implied, statutory or otherwise,
|
||||
including without limitation warranties of title, merchantability, fitness
|
||||
for a particular purpose, non infringement, or the absence of latent or
|
||||
other defects, accuracy, or the present or absence of errors, whether or not
|
||||
discoverable, all to the greatest extent permissible under applicable law.
|
||||
|
||||
c. Affirmer disclaims responsibility for clearing rights of other persons
|
||||
that may apply to the Work or any use thereof, including without limitation
|
||||
any person's Copyright and Related Rights in the Work. Further, Affirmer
|
||||
disclaims responsibility for obtaining any necessary consents, permissions
|
||||
or other rights required for any use of the Work.
|
||||
|
||||
d. Affirmer understands and acknowledges that Creative Commons is not a
|
||||
party to this document and has no duty or obligation with respect to this
|
||||
CC0 or use of the Work.
|
||||
|
||||
For more information, please see
|
||||
<http://creativecommons.org/publicdomain/zero/1.0/>
|
||||
@ -0,0 +1,78 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#include "address.h"
|
||||
#include "params.h"
|
||||
#include "utils.h"
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_addr_to_bytes(
|
||||
unsigned char *bytes, const uint32_t addr[8]) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_ull_to_bytes(
|
||||
bytes + i * 4, 4, addr[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_layer_addr(
|
||||
uint32_t addr[8], uint32_t layer) {
|
||||
addr[0] = layer;
|
||||
}
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_tree_addr(
|
||||
uint32_t addr[8], uint64_t tree) {
|
||||
addr[1] = 0;
|
||||
addr[2] = (uint32_t) (tree >> 32);
|
||||
addr[3] = (uint32_t) tree;
|
||||
}
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_type(
|
||||
uint32_t addr[8], uint32_t type) {
|
||||
addr[4] = type;
|
||||
}
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_copy_subtree_addr(
|
||||
uint32_t out[8], const uint32_t in[8]) {
|
||||
out[0] = in[0];
|
||||
out[1] = in[1];
|
||||
out[2] = in[2];
|
||||
out[3] = in[3];
|
||||
}
|
||||
|
||||
/* These functions are used for OTS addresses. */
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_keypair_addr(
|
||||
uint32_t addr[8], uint32_t keypair) {
|
||||
addr[5] = keypair;
|
||||
}
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_copy_keypair_addr(
|
||||
uint32_t out[8], const uint32_t in[8]) {
|
||||
out[0] = in[0];
|
||||
out[1] = in[1];
|
||||
out[2] = in[2];
|
||||
out[3] = in[3];
|
||||
out[5] = in[5];
|
||||
}
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_chain_addr(
|
||||
uint32_t addr[8], uint32_t chain) {
|
||||
addr[6] = chain;
|
||||
}
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_hash_addr(
|
||||
uint32_t addr[8], uint32_t hash) {
|
||||
addr[7] = hash;
|
||||
}
|
||||
|
||||
/* These functions are used for all hash tree addresses (including FORS). */
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_tree_height(
|
||||
uint32_t addr[8], uint32_t tree_height) {
|
||||
addr[6] = tree_height;
|
||||
}
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_tree_index(
|
||||
uint32_t addr[8], uint32_t tree_index) {
|
||||
addr[7] = tree_index;
|
||||
}
|
||||
@ -0,0 +1,50 @@
|
||||
#ifndef SPX_ADDRESS_H
|
||||
#define SPX_ADDRESS_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define SPX_ADDR_TYPE_WOTS 0
|
||||
#define SPX_ADDR_TYPE_WOTSPK 1
|
||||
#define SPX_ADDR_TYPE_HASHTREE 2
|
||||
#define SPX_ADDR_TYPE_FORSTREE 3
|
||||
#define SPX_ADDR_TYPE_FORSPK 4
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_addr_to_bytes(
|
||||
unsigned char *bytes, const uint32_t addr[8]);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_layer_addr(
|
||||
uint32_t addr[8], uint32_t layer);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_tree_addr(
|
||||
uint32_t addr[8], uint64_t tree);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_type(
|
||||
uint32_t addr[8], uint32_t type);
|
||||
|
||||
/* Copies the layer and tree part of one address into the other */
|
||||
void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_copy_subtree_addr(
|
||||
uint32_t out[8], const uint32_t in[8]);
|
||||
|
||||
/* These functions are used for WOTS and FORS addresses. */
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_keypair_addr(
|
||||
uint32_t addr[8], uint32_t keypair);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_chain_addr(
|
||||
uint32_t addr[8], uint32_t chain);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_hash_addr(
|
||||
uint32_t addr[8], uint32_t hash);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_copy_keypair_addr(
|
||||
uint32_t out[8], const uint32_t in[8]);
|
||||
|
||||
/* These functions are used for all hash tree addresses (including FORS). */
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_tree_height(
|
||||
uint32_t addr[8], uint32_t tree_height);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_tree_index(
|
||||
uint32_t addr[8], uint32_t tree_index);
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,78 @@
|
||||
#ifndef PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_API_H
|
||||
#define PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_API_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_CRYPTO_ALGNAME "SPHINCS+"
|
||||
|
||||
#define PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_CRYPTO_SECRETKEYBYTES 64
|
||||
#define PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_CRYPTO_PUBLICKEYBYTES 32
|
||||
#define PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_CRYPTO_BYTES 16976
|
||||
#define PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_CRYPTO_SEEDBYTES 48
|
||||
|
||||
/*
|
||||
* Returns the length of a secret key, in bytes
|
||||
*/
|
||||
size_t PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_crypto_sign_secretkeybytes(void);
|
||||
|
||||
/*
|
||||
* Returns the length of a public key, in bytes
|
||||
*/
|
||||
size_t PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_crypto_sign_publickeybytes(void);
|
||||
|
||||
/*
|
||||
* Returns the length of a signature, in bytes
|
||||
*/
|
||||
size_t PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_crypto_sign_bytes(void);
|
||||
|
||||
/*
|
||||
* Returns the length of the seed required to generate a key pair, in bytes
|
||||
*/
|
||||
size_t PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_crypto_sign_seedbytes(void);
|
||||
|
||||
/*
|
||||
* Generates a SPHINCS+ key pair given a seed.
|
||||
* Format sk: [SK_SEED || SK_PRF || PUB_SEED || root]
|
||||
* Format pk: [root || PUB_SEED]
|
||||
*/
|
||||
int PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_crypto_sign_seed_keypair(
|
||||
uint8_t *pk, uint8_t *sk, const uint8_t *seed);
|
||||
|
||||
/*
|
||||
* Generates a SPHINCS+ key pair.
|
||||
* Format sk: [SK_SEED || SK_PRF || PUB_SEED || root]
|
||||
* Format pk: [root || PUB_SEED]
|
||||
*/
|
||||
int PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_crypto_sign_keypair(
|
||||
uint8_t *pk, uint8_t *sk);
|
||||
|
||||
/**
|
||||
* Returns an array containing a detached signature.
|
||||
*/
|
||||
int PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_crypto_sign_signature(
|
||||
uint8_t *sig, size_t *siglen,
|
||||
const uint8_t *m, size_t mlen, const uint8_t *sk);
|
||||
|
||||
/**
|
||||
* Verifies a detached signature and message under a given public key.
|
||||
*/
|
||||
int PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_crypto_sign_verify(
|
||||
const uint8_t *sig, size_t siglen,
|
||||
const uint8_t *m, size_t mlen, const uint8_t *pk);
|
||||
|
||||
/**
|
||||
* Returns an array containing the signature followed by the message.
|
||||
*/
|
||||
int PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_crypto_sign(
|
||||
uint8_t *sm, size_t *smlen,
|
||||
const uint8_t *m, size_t mlen, const uint8_t *sk);
|
||||
|
||||
/**
|
||||
* Verifies a given signature-message pair under a given public key.
|
||||
*/
|
||||
int PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_crypto_sign_open(
|
||||
uint8_t *m, size_t *mlen,
|
||||
const uint8_t *sm, size_t smlen, const uint8_t *pk);
|
||||
|
||||
#endif
|
||||
169
src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/fors.c
Normal file
169
src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/fors.c
Normal file
@ -0,0 +1,169 @@
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "address.h"
|
||||
#include "fors.h"
|
||||
#include "hash.h"
|
||||
#include "hash_state.h"
|
||||
#include "thash.h"
|
||||
#include "utils.h"
|
||||
|
||||
static void fors_gen_sk(unsigned char *sk, const unsigned char *sk_seed,
|
||||
uint32_t fors_leaf_addr[8], const hash_state *hash_state_seeded) {
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_prf_addr(
|
||||
sk, sk_seed, fors_leaf_addr, hash_state_seeded);
|
||||
}
|
||||
|
||||
static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk,
|
||||
const unsigned char *pub_seed,
|
||||
uint32_t fors_leaf_addr[8],
|
||||
const hash_state *hash_state_seeded) {
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_thash_1(
|
||||
leaf, sk, pub_seed, fors_leaf_addr, hash_state_seeded);
|
||||
}
|
||||
|
||||
static void fors_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed,
|
||||
const unsigned char *pub_seed,
|
||||
uint32_t addr_idx, const uint32_t fors_tree_addr[8],
|
||||
const hash_state *hash_state_seeded) {
|
||||
uint32_t fors_leaf_addr[8] = {0};
|
||||
|
||||
/* Only copy the parts that must be kept in fors_leaf_addr. */
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_copy_keypair_addr(
|
||||
fors_leaf_addr, fors_tree_addr);
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_type(
|
||||
fors_leaf_addr, SPX_ADDR_TYPE_FORSTREE);
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_tree_index(
|
||||
fors_leaf_addr, addr_idx);
|
||||
|
||||
fors_gen_sk(leaf, sk_seed, fors_leaf_addr, hash_state_seeded);
|
||||
fors_sk_to_leaf(leaf, leaf, pub_seed, fors_leaf_addr, hash_state_seeded);
|
||||
}
|
||||
|
||||
/**
|
||||
* Interprets m as SPX_FORS_HEIGHT-bit unsigned integers.
|
||||
* Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits.
|
||||
* Assumes indices has space for SPX_FORS_TREES integers.
|
||||
*/
|
||||
static void message_to_indices(uint32_t *indices, const unsigned char *m) {
|
||||
unsigned int i, j;
|
||||
unsigned int offset = 0;
|
||||
|
||||
for (i = 0; i < SPX_FORS_TREES; i++) {
|
||||
indices[i] = 0;
|
||||
for (j = 0; j < SPX_FORS_HEIGHT; j++) {
|
||||
indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j;
|
||||
offset++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Signs a message m, deriving the secret key from sk_seed and the FTS address.
|
||||
* Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits.
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_fors_sign(
|
||||
unsigned char *sig, unsigned char *pk,
|
||||
const unsigned char *m,
|
||||
const unsigned char *sk_seed, const unsigned char *pub_seed,
|
||||
const uint32_t fors_addr[8], const hash_state *hash_state_seeded) {
|
||||
uint32_t indices[SPX_FORS_TREES];
|
||||
unsigned char roots[SPX_FORS_TREES * SPX_N];
|
||||
uint32_t fors_tree_addr[8] = {0};
|
||||
uint32_t fors_pk_addr[8] = {0};
|
||||
uint32_t idx_offset;
|
||||
unsigned int i;
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_copy_keypair_addr(
|
||||
fors_tree_addr, fors_addr);
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_copy_keypair_addr(
|
||||
fors_pk_addr, fors_addr);
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_type(
|
||||
fors_tree_addr, SPX_ADDR_TYPE_FORSTREE);
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_type(
|
||||
fors_pk_addr, SPX_ADDR_TYPE_FORSPK);
|
||||
|
||||
message_to_indices(indices, m);
|
||||
|
||||
for (i = 0; i < SPX_FORS_TREES; i++) {
|
||||
idx_offset = i * (1 << SPX_FORS_HEIGHT);
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_tree_height(
|
||||
fors_tree_addr, 0);
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_tree_index(
|
||||
fors_tree_addr, indices[i] + idx_offset);
|
||||
|
||||
/* Include the secret key part that produces the selected leaf node. */
|
||||
fors_gen_sk(sig, sk_seed, fors_tree_addr, hash_state_seeded);
|
||||
sig += SPX_N;
|
||||
|
||||
/* Compute the authentication path for this leaf node. */
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_treehash_FORS_HEIGHT(
|
||||
roots + i * SPX_N, sig, sk_seed, pub_seed,
|
||||
indices[i], idx_offset, fors_gen_leaf, fors_tree_addr,
|
||||
hash_state_seeded);
|
||||
sig += SPX_N * SPX_FORS_HEIGHT;
|
||||
}
|
||||
|
||||
/* Hash horizontally across all tree roots to derive the public key. */
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_thash_FORS_TREES(
|
||||
pk, roots, pub_seed, fors_pk_addr, hash_state_seeded);
|
||||
}
|
||||
|
||||
/**
|
||||
* Derives the FORS public key from a signature.
|
||||
* This can be used for verification by comparing to a known public key, or to
|
||||
* subsequently verify a signature on the derived public key. The latter is the
|
||||
* typical use-case when used as an FTS below an OTS in a hypertree.
|
||||
* Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits.
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_fors_pk_from_sig(
|
||||
unsigned char *pk,
|
||||
const unsigned char *sig, const unsigned char *m,
|
||||
const unsigned char *pub_seed, const uint32_t fors_addr[8],
|
||||
const hash_state *hash_state_seeded) {
|
||||
uint32_t indices[SPX_FORS_TREES];
|
||||
unsigned char roots[SPX_FORS_TREES * SPX_N];
|
||||
unsigned char leaf[SPX_N];
|
||||
uint32_t fors_tree_addr[8] = {0};
|
||||
uint32_t fors_pk_addr[8] = {0};
|
||||
uint32_t idx_offset;
|
||||
unsigned int i;
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_copy_keypair_addr(
|
||||
fors_tree_addr, fors_addr);
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_copy_keypair_addr(
|
||||
fors_pk_addr, fors_addr);
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_type(
|
||||
fors_tree_addr, SPX_ADDR_TYPE_FORSTREE);
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_type(
|
||||
fors_pk_addr, SPX_ADDR_TYPE_FORSPK);
|
||||
|
||||
message_to_indices(indices, m);
|
||||
|
||||
for (i = 0; i < SPX_FORS_TREES; i++) {
|
||||
idx_offset = i * (1 << SPX_FORS_HEIGHT);
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_tree_height(
|
||||
fors_tree_addr, 0);
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_tree_index(
|
||||
fors_tree_addr, indices[i] + idx_offset);
|
||||
|
||||
/* Derive the leaf from the included secret key part. */
|
||||
fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, hash_state_seeded);
|
||||
sig += SPX_N;
|
||||
|
||||
/* Derive the corresponding root node of this tree. */
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_compute_root(
|
||||
roots + i * SPX_N, leaf, indices[i], idx_offset, sig,
|
||||
SPX_FORS_HEIGHT, pub_seed, fors_tree_addr, hash_state_seeded);
|
||||
sig += SPX_N * SPX_FORS_HEIGHT;
|
||||
}
|
||||
|
||||
/* Hash horizontally across all tree roots to derive the public key. */
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_thash_FORS_TREES(
|
||||
pk, roots, pub_seed, fors_pk_addr, hash_state_seeded);
|
||||
}
|
||||
@ -0,0 +1,32 @@
|
||||
#ifndef SPX_FORS_H
|
||||
#define SPX_FORS_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "params.h"
|
||||
#include "hash_state.h"
|
||||
|
||||
/**
|
||||
* Signs a message m, deriving the secret key from sk_seed and the FTS address.
|
||||
* Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits.
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_fors_sign(
|
||||
unsigned char *sig, unsigned char *pk,
|
||||
const unsigned char *m,
|
||||
const unsigned char *sk_seed, const unsigned char *pub_seed,
|
||||
const uint32_t fors_addr[8], const hash_state *hash_state_seeded);
|
||||
|
||||
/**
|
||||
* Derives the FORS public key from a signature.
|
||||
* This can be used for verification by comparing to a known public key, or to
|
||||
* subsequently verify a signature on the derived public key. The latter is the
|
||||
* typical use-case when used as an FTS below an OTS in a hypertree.
|
||||
* Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits.
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_fors_pk_from_sig(
|
||||
unsigned char *pk,
|
||||
const unsigned char *sig, const unsigned char *m,
|
||||
const unsigned char *pub_seed, const uint32_t fors_addr[8],
|
||||
const hash_state *hash_state_seeded);
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,29 @@
|
||||
#ifndef SPX_HASH_H
|
||||
#define SPX_HASH_H
|
||||
|
||||
#include "hash_state.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_initialize_hash_function(
|
||||
hash_state *hash_state_seeded,
|
||||
const unsigned char *pub_seed, const unsigned char *sk_seed);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_prf_addr(
|
||||
unsigned char *out, const unsigned char *key, const uint32_t addr[8],
|
||||
const hash_state *hash_state_seeded);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_gen_message_random(
|
||||
unsigned char *R,
|
||||
const unsigned char *sk_prf, const unsigned char *optrand,
|
||||
const unsigned char *m, size_t mlen,
|
||||
const hash_state *hash_state_seeded);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_hash_message(
|
||||
unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx,
|
||||
const unsigned char *R, const unsigned char *pk,
|
||||
const unsigned char *m, size_t mlen,
|
||||
const hash_state *hash_state_seeded);
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,157 @@
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "address.h"
|
||||
#include "hash.h"
|
||||
#include "params.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include "sha2.h"
|
||||
#include "sha256.h"
|
||||
|
||||
/* For SHA256, there is no immediate reason to initialize at the start,
|
||||
so this function is an empty operation. */
|
||||
void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_initialize_hash_function(
|
||||
hash_state *hash_state_seeded,
|
||||
const unsigned char *pub_seed, const unsigned char *sk_seed) {
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_seed_state(hash_state_seeded, pub_seed);
|
||||
(void)sk_seed; /* Suppress an 'unused parameter' warning. */
|
||||
}
|
||||
|
||||
/*
|
||||
* Computes PRF(key, addr), given a secret key of SPX_N bytes and an address
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_prf_addr(
|
||||
unsigned char *out, const unsigned char *key, const uint32_t addr[8],
|
||||
const hash_state *hash_state_seeded) {
|
||||
unsigned char buf[SPX_N + SPX_SHA256_ADDR_BYTES];
|
||||
unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES];
|
||||
|
||||
memcpy(buf, key, SPX_N);
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_compress_address(buf + SPX_N, addr);
|
||||
|
||||
sha256(outbuf, buf, SPX_N + SPX_SHA256_ADDR_BYTES);
|
||||
memcpy(out, outbuf, SPX_N);
|
||||
|
||||
(void)hash_state_seeded; /* Prevent unused parameter warning. */
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the message-dependent randomness R, using a secret seed as a key
|
||||
* for HMAC, and an optional randomization value prefixed to the message.
|
||||
* This requires m to have at least SPX_SHA256_BLOCK_BYTES + SPX_N space
|
||||
* available in front of the pointer, i.e. before the message to use for the
|
||||
* prefix. This is necessary to prevent having to move the message around (and
|
||||
* allocate memory for it).
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_gen_message_random(
|
||||
unsigned char *R,
|
||||
const unsigned char *sk_prf, const unsigned char *optrand,
|
||||
const unsigned char *m, size_t mlen, const hash_state *hash_state_seeded) {
|
||||
unsigned char buf[SPX_SHA256_BLOCK_BYTES + SPX_SHA256_OUTPUT_BYTES];
|
||||
sha256ctx state;
|
||||
int i;
|
||||
|
||||
/* This implements HMAC-SHA256 */
|
||||
for (i = 0; i < SPX_N; i++) {
|
||||
buf[i] = 0x36 ^ sk_prf[i];
|
||||
}
|
||||
memset(buf + SPX_N, 0x36, SPX_SHA256_BLOCK_BYTES - SPX_N);
|
||||
|
||||
sha256_inc_init(&state);
|
||||
sha256_inc_blocks(&state, buf, 1);
|
||||
|
||||
memcpy(buf, optrand, SPX_N);
|
||||
|
||||
/* If optrand + message cannot fill up an entire block */
|
||||
if (SPX_N + mlen < SPX_SHA256_BLOCK_BYTES) {
|
||||
memcpy(buf + SPX_N, m, mlen);
|
||||
sha256_inc_finalize(buf + SPX_SHA256_BLOCK_BYTES, &state,
|
||||
buf, mlen + SPX_N);
|
||||
}
|
||||
/* Otherwise first fill a block, so that finalize only uses the message */
|
||||
else {
|
||||
memcpy(buf + SPX_N, m, SPX_SHA256_BLOCK_BYTES - SPX_N);
|
||||
sha256_inc_blocks(&state, buf, 1);
|
||||
|
||||
m += SPX_SHA256_BLOCK_BYTES - SPX_N;
|
||||
mlen -= SPX_SHA256_BLOCK_BYTES - SPX_N;
|
||||
sha256_inc_finalize(buf + SPX_SHA256_BLOCK_BYTES, &state, m, mlen);
|
||||
}
|
||||
|
||||
for (i = 0; i < SPX_N; i++) {
|
||||
buf[i] = 0x5c ^ sk_prf[i];
|
||||
}
|
||||
memset(buf + SPX_N, 0x5c, SPX_SHA256_BLOCK_BYTES - SPX_N);
|
||||
|
||||
sha256(buf, buf, SPX_SHA256_BLOCK_BYTES + SPX_SHA256_OUTPUT_BYTES);
|
||||
memcpy(R, buf, SPX_N);
|
||||
|
||||
(void)hash_state_seeded; /* Prevent unused parameter warning. */
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the message hash using R, the public key, and the message.
|
||||
* Outputs the message digest and the index of the leaf. The index is split in
|
||||
* the tree index and the leaf index, for convenient copying to an address.
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_hash_message(
|
||||
unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx,
|
||||
const unsigned char *R, const unsigned char *pk,
|
||||
const unsigned char *m, size_t mlen,
|
||||
const hash_state *hash_state_seeded) {
|
||||
#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1))
|
||||
#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8)
|
||||
#define SPX_LEAF_BITS SPX_TREE_HEIGHT
|
||||
#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8)
|
||||
#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES)
|
||||
|
||||
unsigned char seed[SPX_SHA256_OUTPUT_BYTES + 4];
|
||||
|
||||
/* Round to nearest multiple of SPX_SHA256_BLOCK_BYTES */
|
||||
#define SPX_INBLOCKS (((SPX_N + SPX_PK_BYTES + SPX_SHA256_BLOCK_BYTES - 1) & \
|
||||
-SPX_SHA256_BLOCK_BYTES) / SPX_SHA256_BLOCK_BYTES)
|
||||
unsigned char inbuf[SPX_INBLOCKS * SPX_SHA256_BLOCK_BYTES];
|
||||
|
||||
unsigned char buf[SPX_DGST_BYTES];
|
||||
unsigned char *bufp = buf;
|
||||
sha256ctx state;
|
||||
|
||||
sha256_inc_init(&state);
|
||||
|
||||
memcpy(inbuf, R, SPX_N);
|
||||
memcpy(inbuf + SPX_N, pk, SPX_PK_BYTES);
|
||||
|
||||
/* If R + pk + message cannot fill up an entire block */
|
||||
if (SPX_N + SPX_PK_BYTES + mlen < SPX_INBLOCKS * SPX_SHA256_BLOCK_BYTES) {
|
||||
memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, mlen);
|
||||
sha256_inc_finalize(seed, &state, inbuf, SPX_N + SPX_PK_BYTES + mlen);
|
||||
}
|
||||
/* Otherwise first fill a block, so that finalize only uses the message */
|
||||
else {
|
||||
memcpy(inbuf + SPX_N + SPX_PK_BYTES, m,
|
||||
SPX_INBLOCKS * SPX_SHA256_BLOCK_BYTES - SPX_N - SPX_PK_BYTES);
|
||||
sha256_inc_blocks(&state, inbuf, SPX_INBLOCKS);
|
||||
|
||||
m += SPX_INBLOCKS * SPX_SHA256_BLOCK_BYTES - SPX_N - SPX_PK_BYTES;
|
||||
mlen -= SPX_INBLOCKS * SPX_SHA256_BLOCK_BYTES - SPX_N - SPX_PK_BYTES;
|
||||
sha256_inc_finalize(seed, &state, m, mlen);
|
||||
}
|
||||
|
||||
/* By doing this in two steps, we prevent hashing the message twice;
|
||||
otherwise each iteration in MGF1 would hash the message again. */
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_mgf1(bufp, SPX_DGST_BYTES, seed, SPX_SHA256_OUTPUT_BYTES);
|
||||
|
||||
memcpy(digest, bufp, SPX_FORS_MSG_BYTES);
|
||||
bufp += SPX_FORS_MSG_BYTES;
|
||||
|
||||
*tree = PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_bytes_to_ull(bufp, SPX_TREE_BYTES);
|
||||
*tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS);
|
||||
bufp += SPX_TREE_BYTES;
|
||||
|
||||
*leaf_idx = (uint32_t)PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_bytes_to_ull(
|
||||
bufp, SPX_LEAF_BYTES);
|
||||
*leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS);
|
||||
|
||||
(void)hash_state_seeded; /* Prevent unused parameter warning. */
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
#ifndef SPX_PRIMITIVE_H
|
||||
#define SPX_PRIMITIVE_H
|
||||
|
||||
#include "sha2.h"
|
||||
#define hash_state sha256ctx
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,53 @@
|
||||
#ifndef SPX_PARAMS_H
|
||||
#define SPX_PARAMS_H
|
||||
|
||||
/* Hash output length in bytes. */
|
||||
#define SPX_N 16
|
||||
/* Height of the hypertree. */
|
||||
#define SPX_FULL_HEIGHT 60
|
||||
/* Number of subtree layer. */
|
||||
#define SPX_D 20
|
||||
/* FORS tree dimensions. */
|
||||
#define SPX_FORS_HEIGHT 9
|
||||
#define SPX_FORS_TREES 30
|
||||
/* Winternitz parameter, */
|
||||
#define SPX_WOTS_W 16
|
||||
|
||||
/* The hash function is defined by linking a different hash.c file, as opposed
|
||||
to setting a #define constant. */
|
||||
|
||||
/* For clarity */
|
||||
#define SPX_ADDR_BYTES 32
|
||||
|
||||
/* WOTS parameters. */
|
||||
#define SPX_WOTS_LOGW 4
|
||||
|
||||
#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW)
|
||||
|
||||
/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */
|
||||
#define SPX_WOTS_LEN2 3
|
||||
|
||||
#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2)
|
||||
#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N)
|
||||
#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES
|
||||
|
||||
/* Subtree size. */
|
||||
#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D)
|
||||
|
||||
/* FORS parameters. */
|
||||
#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8)
|
||||
#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N)
|
||||
#define SPX_FORS_PK_BYTES SPX_N
|
||||
|
||||
/* Resulting SPX sizes. */
|
||||
#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\
|
||||
SPX_FULL_HEIGHT * SPX_N)
|
||||
#define SPX_PK_BYTES (2 * SPX_N)
|
||||
#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES)
|
||||
|
||||
/* Optionally, signing can be made non-deterministic using optrand.
|
||||
This can help counter side-channel attacks that would benefit from
|
||||
getting a large number of traces when the signer uses the same nodes. */
|
||||
#define SPX_OPTRAND_BYTES 32
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,71 @@
|
||||
/* Based on the public domain implementation in
|
||||
* crypto_hash/sha512/ref/ from http://bench.cr.yp.to/supercop.html
|
||||
* by D. J. Bernstein */
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "sha2.h"
|
||||
#include "sha256.h"
|
||||
#include "utils.h"
|
||||
|
||||
/*
|
||||
* Compresses an address to a 22-byte sequence.
|
||||
* This reduces the number of required SHA256 compression calls, as the last
|
||||
* block of input is padded with at least 65 bits.
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_compress_address(unsigned char *out, const uint32_t addr[8]) {
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_ull_to_bytes(out, 1, addr[0]); /* drop 3 bytes of the layer field */
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_ull_to_bytes(out + 1, 4, addr[2]); /* drop the highest tree address word */
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_ull_to_bytes(out + 5, 4, addr[3]);
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_ull_to_bytes(out + 9, 1, addr[4]); /* drop 3 bytes of the type field */
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_ull_to_bytes(out + 10, 4, addr[5]);
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_ull_to_bytes(out + 14, 4, addr[6]);
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_ull_to_bytes(out + 18, 4, addr[7]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Requires 'input_plus_four_bytes' to have 'inlen' + 4 bytes, so that the last
|
||||
* four bytes can be used for the counter. Typically 'input' is merely a seed.
|
||||
* Outputs outlen number of bytes
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_mgf1(
|
||||
unsigned char *out, unsigned long outlen,
|
||||
unsigned char *input_plus_four_bytes, unsigned long inlen) {
|
||||
unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES];
|
||||
unsigned long i;
|
||||
|
||||
/* While we can fit in at least another full block of SHA256 output.. */
|
||||
for (i = 0; (i + 1)*SPX_SHA256_OUTPUT_BYTES <= outlen; i++) {
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_ull_to_bytes(input_plus_four_bytes + inlen, 4, i);
|
||||
sha256(out, input_plus_four_bytes, inlen + 4);
|
||||
out += SPX_SHA256_OUTPUT_BYTES;
|
||||
}
|
||||
/* Until we cannot anymore, and we fill the remainder. */
|
||||
if (outlen > i * SPX_SHA256_OUTPUT_BYTES) {
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_ull_to_bytes(input_plus_four_bytes + inlen, 4, i);
|
||||
sha256(outbuf, input_plus_four_bytes, inlen + 4);
|
||||
memcpy(out, outbuf, outlen - i * SPX_SHA256_OUTPUT_BYTES);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Absorb the constant pub_seed using one round of the compression function
|
||||
* This initializes hash_state_seeded, which can then be reused in thash
|
||||
**/
|
||||
void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_seed_state(sha256ctx *hash_state_seeded, const unsigned char *pub_seed) {
|
||||
uint8_t block[SPX_SHA256_BLOCK_BYTES];
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < SPX_N; ++i) {
|
||||
block[i] = pub_seed[i];
|
||||
}
|
||||
for (i = SPX_N; i < SPX_SHA256_BLOCK_BYTES; ++i) {
|
||||
block[i] = 0;
|
||||
}
|
||||
|
||||
sha256_inc_init(hash_state_seeded);
|
||||
sha256_inc_blocks(hash_state_seeded, block, 1);
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
#ifndef SPX_SHA256_H
|
||||
#define SPX_SHA256_H
|
||||
|
||||
#define SPX_SHA256_BLOCK_BYTES 64
|
||||
#define SPX_SHA256_OUTPUT_BYTES 32 /* This does not necessarily equal SPX_N */
|
||||
#define SPX_SHA256_ADDR_BYTES 22
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "sha2.h"
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_compress_address(unsigned char *out, const uint32_t addr[8]);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_mgf1(
|
||||
unsigned char *out, unsigned long outlen,
|
||||
unsigned char *input_plus_four_bytes, unsigned long inlen);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_seed_state(sha256ctx *hash_state_seeded, const unsigned char *pub_seed);
|
||||
|
||||
#endif
|
||||
353
src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/sign.c
Normal file
353
src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/sign.c
Normal file
@ -0,0 +1,353 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "address.h"
|
||||
#include "api.h"
|
||||
#include "fors.h"
|
||||
#include "hash.h"
|
||||
#include "params.h"
|
||||
#include "hash_state.h"
|
||||
#include "randombytes.h"
|
||||
#include "thash.h"
|
||||
#include "utils.h"
|
||||
#include "wots.h"
|
||||
|
||||
/**
|
||||
* Computes the leaf at a given address. First generates the WOTS key pair,
|
||||
* then computes leaf by hashing horizontally.
|
||||
*/
|
||||
static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed,
|
||||
const unsigned char *pub_seed,
|
||||
uint32_t addr_idx, const uint32_t tree_addr[8],
|
||||
const hash_state *hash_state_seeded) {
|
||||
unsigned char pk[SPX_WOTS_BYTES];
|
||||
uint32_t wots_addr[8] = {0};
|
||||
uint32_t wots_pk_addr[8] = {0};
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_type(
|
||||
wots_addr, SPX_ADDR_TYPE_WOTS);
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_type(
|
||||
wots_pk_addr, SPX_ADDR_TYPE_WOTSPK);
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_copy_subtree_addr(
|
||||
wots_addr, tree_addr);
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_keypair_addr(
|
||||
wots_addr, addr_idx);
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_wots_gen_pk(
|
||||
pk, sk_seed, pub_seed, wots_addr, hash_state_seeded);
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_copy_keypair_addr(
|
||||
wots_pk_addr, wots_addr);
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_thash_WOTS_LEN(
|
||||
leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the length of a secret key, in bytes
|
||||
*/
|
||||
size_t PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_crypto_sign_secretkeybytes(void) {
|
||||
return PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_CRYPTO_SECRETKEYBYTES;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the length of a public key, in bytes
|
||||
*/
|
||||
size_t PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_crypto_sign_publickeybytes(void) {
|
||||
return PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_CRYPTO_PUBLICKEYBYTES;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the length of a signature, in bytes
|
||||
*/
|
||||
size_t PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_crypto_sign_bytes(void) {
|
||||
return PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_CRYPTO_BYTES;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the length of the seed required to generate a key pair, in bytes
|
||||
*/
|
||||
size_t PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_crypto_sign_seedbytes(void) {
|
||||
return PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_CRYPTO_SEEDBYTES;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generates an SPX key pair given a seed of length
|
||||
* Format sk: [SK_SEED || SK_PRF || PUB_SEED || root]
|
||||
* Format pk: [PUB_SEED || root]
|
||||
*/
|
||||
int PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_crypto_sign_seed_keypair(
|
||||
uint8_t *pk, uint8_t *sk, const uint8_t *seed) {
|
||||
/* We do not need the auth path in key generation, but it simplifies the
|
||||
code to have just one treehash routine that computes both root and path
|
||||
in one function. */
|
||||
unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N];
|
||||
uint32_t top_tree_addr[8] = {0};
|
||||
hash_state hash_state_seeded;
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_layer_addr(
|
||||
top_tree_addr, SPX_D - 1);
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_type(
|
||||
top_tree_addr, SPX_ADDR_TYPE_HASHTREE);
|
||||
|
||||
/* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */
|
||||
memcpy(sk, seed, PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_CRYPTO_SEEDBYTES);
|
||||
|
||||
memcpy(pk, sk + 2 * SPX_N, SPX_N);
|
||||
|
||||
/* This hook allows the hash function instantiation to do whatever
|
||||
preparation or computation it needs, based on the public seed. */
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_initialize_hash_function(&hash_state_seeded, pk, sk);
|
||||
|
||||
/* Compute root node of the top-most subtree. */
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_treehash_TREE_HEIGHT(
|
||||
sk + 3 * SPX_N, auth_path, sk, sk + 2 * SPX_N, 0, 0,
|
||||
wots_gen_leaf, top_tree_addr, &hash_state_seeded);
|
||||
|
||||
memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generates an SPX key pair.
|
||||
* Format sk: [SK_SEED || SK_PRF || PUB_SEED || root]
|
||||
* Format pk: [PUB_SEED || root]
|
||||
*/
|
||||
int PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_crypto_sign_keypair(
|
||||
uint8_t *pk, uint8_t *sk) {
|
||||
unsigned char seed[PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_CRYPTO_SEEDBYTES];
|
||||
randombytes(seed, PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_CRYPTO_SEEDBYTES);
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_crypto_sign_seed_keypair(
|
||||
pk, sk, seed);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array containing a detached signature.
|
||||
*/
|
||||
int PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_crypto_sign_signature(
|
||||
uint8_t *sig, size_t *siglen,
|
||||
const uint8_t *m, size_t mlen, const uint8_t *sk) {
|
||||
const unsigned char *sk_seed = sk;
|
||||
const unsigned char *sk_prf = sk + SPX_N;
|
||||
const unsigned char *pk = sk + 2 * SPX_N;
|
||||
const unsigned char *pub_seed = pk;
|
||||
|
||||
unsigned char optrand[SPX_N];
|
||||
unsigned char mhash[SPX_FORS_MSG_BYTES];
|
||||
unsigned char root[SPX_N];
|
||||
uint32_t i;
|
||||
uint64_t tree;
|
||||
uint32_t idx_leaf;
|
||||
uint32_t wots_addr[8] = {0};
|
||||
uint32_t tree_addr[8] = {0};
|
||||
|
||||
hash_state hash_state_seeded;
|
||||
|
||||
/* This hook allows the hash function instantiation to do whatever
|
||||
preparation or computation it needs, based on the public seed. */
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_initialize_hash_function(
|
||||
&hash_state_seeded,
|
||||
pub_seed, sk_seed);
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_type(
|
||||
wots_addr, SPX_ADDR_TYPE_WOTS);
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_type(
|
||||
tree_addr, SPX_ADDR_TYPE_HASHTREE);
|
||||
|
||||
/* Optionally, signing can be made non-deterministic using optrand.
|
||||
This can help counter side-channel attacks that would benefit from
|
||||
getting a large number of traces when the signer uses the same nodes. */
|
||||
randombytes(optrand, SPX_N);
|
||||
/* Compute the digest randomization value. */
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_gen_message_random(
|
||||
sig, sk_prf, optrand, m, mlen, &hash_state_seeded);
|
||||
|
||||
/* Derive the message digest and leaf index from R, PK and M. */
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_hash_message(
|
||||
mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded);
|
||||
sig += SPX_N;
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_tree_addr(wots_addr, tree);
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_keypair_addr(
|
||||
wots_addr, idx_leaf);
|
||||
|
||||
/* Sign the message hash using FORS. */
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_fors_sign(
|
||||
sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded);
|
||||
sig += SPX_FORS_BYTES;
|
||||
|
||||
for (i = 0; i < SPX_D; i++) {
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_layer_addr(tree_addr, i);
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_tree_addr(tree_addr, tree);
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_copy_subtree_addr(
|
||||
wots_addr, tree_addr);
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_keypair_addr(
|
||||
wots_addr, idx_leaf);
|
||||
|
||||
/* Compute a WOTS signature. */
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_wots_sign(
|
||||
sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded);
|
||||
sig += SPX_WOTS_BYTES;
|
||||
|
||||
/* Compute the authentication path for the used WOTS leaf. */
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_treehash_TREE_HEIGHT(
|
||||
root, sig, sk_seed, pub_seed, idx_leaf, 0,
|
||||
wots_gen_leaf, tree_addr, &hash_state_seeded);
|
||||
sig += SPX_TREE_HEIGHT * SPX_N;
|
||||
|
||||
/* Update the indices for the next layer. */
|
||||
idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1));
|
||||
tree = tree >> SPX_TREE_HEIGHT;
|
||||
}
|
||||
|
||||
*siglen = SPX_BYTES;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies a detached signature and message under a given public key.
|
||||
*/
|
||||
int PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_crypto_sign_verify(
|
||||
const uint8_t *sig, size_t siglen,
|
||||
const uint8_t *m, size_t mlen, const uint8_t *pk) {
|
||||
const unsigned char *pub_seed = pk;
|
||||
const unsigned char *pub_root = pk + SPX_N;
|
||||
unsigned char mhash[SPX_FORS_MSG_BYTES];
|
||||
unsigned char wots_pk[SPX_WOTS_BYTES];
|
||||
unsigned char root[SPX_N];
|
||||
unsigned char leaf[SPX_N];
|
||||
unsigned int i;
|
||||
uint64_t tree;
|
||||
uint32_t idx_leaf;
|
||||
uint32_t wots_addr[8] = {0};
|
||||
uint32_t tree_addr[8] = {0};
|
||||
uint32_t wots_pk_addr[8] = {0};
|
||||
|
||||
hash_state hash_state_seeded;
|
||||
|
||||
if (siglen != SPX_BYTES) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* This hook allows the hash function instantiation to do whatever
|
||||
preparation or computation it needs, based on the public seed. */
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_initialize_hash_function(
|
||||
&hash_state_seeded,
|
||||
pub_seed, NULL);
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_type(
|
||||
wots_addr, SPX_ADDR_TYPE_WOTS);
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_type(
|
||||
tree_addr, SPX_ADDR_TYPE_HASHTREE);
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_type(
|
||||
wots_pk_addr, SPX_ADDR_TYPE_WOTSPK);
|
||||
|
||||
/* Derive the message digest and leaf index from R || PK || M. */
|
||||
/* The additional SPX_N is a result of the hash domain separator. */
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_hash_message(
|
||||
mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded);
|
||||
sig += SPX_N;
|
||||
|
||||
/* Layer correctly defaults to 0, so no need to set_layer_addr */
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_tree_addr(wots_addr, tree);
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_keypair_addr(
|
||||
wots_addr, idx_leaf);
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_fors_pk_from_sig(
|
||||
root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded);
|
||||
sig += SPX_FORS_BYTES;
|
||||
|
||||
/* For each subtree.. */
|
||||
for (i = 0; i < SPX_D; i++) {
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_layer_addr(tree_addr, i);
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_tree_addr(tree_addr, tree);
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_copy_subtree_addr(
|
||||
wots_addr, tree_addr);
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_keypair_addr(
|
||||
wots_addr, idx_leaf);
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_copy_keypair_addr(
|
||||
wots_pk_addr, wots_addr);
|
||||
|
||||
/* The WOTS public key is only correct if the signature was correct. */
|
||||
/* Initially, root is the FORS pk, but on subsequent iterations it is
|
||||
the root of the subtree below the currently processed subtree. */
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_wots_pk_from_sig(
|
||||
wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded);
|
||||
sig += SPX_WOTS_BYTES;
|
||||
|
||||
/* Compute the leaf node using the WOTS public key. */
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_thash_WOTS_LEN(
|
||||
leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded);
|
||||
|
||||
/* Compute the root node of this subtree. */
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_compute_root(
|
||||
root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT,
|
||||
pub_seed, tree_addr, &hash_state_seeded);
|
||||
sig += SPX_TREE_HEIGHT * SPX_N;
|
||||
|
||||
/* Update the indices for the next layer. */
|
||||
idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1));
|
||||
tree = tree >> SPX_TREE_HEIGHT;
|
||||
}
|
||||
|
||||
/* Check if the root node equals the root node in the public key. */
|
||||
if (memcmp(root, pub_root, SPX_N) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns an array containing the signature followed by the message.
|
||||
*/
|
||||
int PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_crypto_sign(
|
||||
uint8_t *sm, size_t *smlen,
|
||||
const uint8_t *m, size_t mlen, const uint8_t *sk) {
|
||||
size_t siglen;
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_crypto_sign_signature(
|
||||
sm, &siglen, m, mlen, sk);
|
||||
|
||||
memmove(sm + SPX_BYTES, m, mlen);
|
||||
*smlen = siglen + mlen;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies a given signature-message pair under a given public key.
|
||||
*/
|
||||
int PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_crypto_sign_open(
|
||||
uint8_t *m, size_t *mlen,
|
||||
const uint8_t *sm, size_t smlen, const uint8_t *pk) {
|
||||
/* The API caller does not necessarily know what size a signature should be
|
||||
but SPHINCS+ signatures are always exactly SPX_BYTES. */
|
||||
if (smlen < SPX_BYTES) {
|
||||
memset(m, 0, smlen);
|
||||
*mlen = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
*mlen = smlen - SPX_BYTES;
|
||||
|
||||
if (PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_crypto_sign_verify(
|
||||
sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) {
|
||||
memset(m, 0, smlen);
|
||||
*mlen = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* If verification was successful, move the message to the right place. */
|
||||
memmove(m, sm + SPX_BYTES, *mlen);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
#ifndef SPX_THASH_H
|
||||
#define SPX_THASH_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "hash_state.h"
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_thash_1(
|
||||
unsigned char *out, const unsigned char *in,
|
||||
const unsigned char *pub_seed, uint32_t addr[8],
|
||||
const hash_state *hash_state_seeded);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_thash_2(
|
||||
unsigned char *out, const unsigned char *in,
|
||||
const unsigned char *pub_seed, uint32_t addr[8],
|
||||
const hash_state *hash_state_seeded);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_thash_WOTS_LEN(
|
||||
unsigned char *out, const unsigned char *in,
|
||||
const unsigned char *pub_seed, uint32_t addr[8],
|
||||
const hash_state *hash_state_seeded);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_thash_FORS_TREES(
|
||||
unsigned char *out, const unsigned char *in,
|
||||
const unsigned char *pub_seed, uint32_t addr[8],
|
||||
const hash_state *hash_state_seeded);
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,75 @@
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "address.h"
|
||||
#include "params.h"
|
||||
#include "thash.h"
|
||||
|
||||
#include "sha2.h"
|
||||
#include "sha256.h"
|
||||
|
||||
/**
|
||||
* Takes an array of inblocks concatenated arrays of SPX_N bytes.
|
||||
*/
|
||||
static void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_thash(
|
||||
unsigned char *out, unsigned char *buf,
|
||||
const unsigned char *in, unsigned int inblocks,
|
||||
const unsigned char *pub_seed, uint32_t addr[8],
|
||||
const sha256ctx *hash_state_seeded) {
|
||||
|
||||
unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES];
|
||||
sha256ctx sha2_state;
|
||||
|
||||
(void)pub_seed; /* Suppress an 'unused parameter' warning. */
|
||||
|
||||
/* Retrieve precomputed state containing pub_seed */
|
||||
sha256_inc_dupe_state(&sha2_state, hash_state_seeded);
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_compress_address(buf, addr);
|
||||
memcpy(buf + SPX_SHA256_ADDR_BYTES, in, inblocks * SPX_N);
|
||||
|
||||
sha256_inc_finalize(outbuf, &sha2_state, buf, SPX_SHA256_ADDR_BYTES + inblocks * SPX_N);
|
||||
memcpy(out, outbuf, SPX_N);
|
||||
}
|
||||
|
||||
/* The wrappers below ensure that we use fixed-size buffers on the stack */
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_thash_1(
|
||||
unsigned char *out, const unsigned char *in,
|
||||
const unsigned char *pub_seed, uint32_t addr[8],
|
||||
const sha256ctx *hash_state_seeded) {
|
||||
|
||||
unsigned char buf[SPX_SHA256_ADDR_BYTES + 1 * SPX_N];
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_thash(
|
||||
out, buf, in, 1, pub_seed, addr, hash_state_seeded);
|
||||
}
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_thash_2(
|
||||
unsigned char *out, const unsigned char *in,
|
||||
const unsigned char *pub_seed, uint32_t addr[8],
|
||||
const sha256ctx *hash_state_seeded) {
|
||||
|
||||
unsigned char buf[SPX_SHA256_ADDR_BYTES + 2 * SPX_N];
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_thash(
|
||||
out, buf, in, 2, pub_seed, addr, hash_state_seeded);
|
||||
}
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_thash_WOTS_LEN(
|
||||
unsigned char *out, const unsigned char *in,
|
||||
const unsigned char *pub_seed, uint32_t addr[8],
|
||||
const sha256ctx *hash_state_seeded) {
|
||||
|
||||
unsigned char buf[SPX_SHA256_ADDR_BYTES + SPX_WOTS_LEN * SPX_N];
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_thash(
|
||||
out, buf, in, SPX_WOTS_LEN, pub_seed, addr, hash_state_seeded);
|
||||
}
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_thash_FORS_TREES(
|
||||
unsigned char *out, const unsigned char *in,
|
||||
const unsigned char *pub_seed, uint32_t addr[8],
|
||||
const sha256ctx *hash_state_seeded) {
|
||||
|
||||
unsigned char buf[SPX_SHA256_ADDR_BYTES + SPX_FORS_TREES * SPX_N];
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_thash(
|
||||
out, buf, in, SPX_FORS_TREES, pub_seed, addr, hash_state_seeded);
|
||||
}
|
||||
199
src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/utils.c
Normal file
199
src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/utils.c
Normal file
@ -0,0 +1,199 @@
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "address.h"
|
||||
#include "hash.h"
|
||||
#include "params.h"
|
||||
#include "hash_state.h"
|
||||
#include "thash.h"
|
||||
#include "utils.h"
|
||||
|
||||
/**
|
||||
* Converts the value of 'in' to 'outlen' bytes in big-endian byte order.
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_ull_to_bytes(
|
||||
unsigned char *out, size_t outlen, unsigned long long in) {
|
||||
|
||||
/* Iterate over out in decreasing order, for big-endianness. */
|
||||
for (size_t i = outlen; i > 0; i--) {
|
||||
out[i - 1] = in & 0xff;
|
||||
in = in >> 8;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the inlen bytes in 'in' from big-endian byte order to an integer.
|
||||
*/
|
||||
unsigned long long PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_bytes_to_ull(
|
||||
const unsigned char *in, size_t inlen) {
|
||||
unsigned long long retval = 0;
|
||||
|
||||
for (size_t i = 0; i < inlen; i++) {
|
||||
retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i));
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes a root node given a leaf and an auth path.
|
||||
* Expects address to be complete other than the tree_height and tree_index.
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_compute_root(
|
||||
unsigned char *root, const unsigned char *leaf,
|
||||
uint32_t leaf_idx, uint32_t idx_offset,
|
||||
const unsigned char *auth_path, uint32_t tree_height,
|
||||
const unsigned char *pub_seed, uint32_t addr[8],
|
||||
const hash_state *hash_state_seeded) {
|
||||
uint32_t i;
|
||||
unsigned char buffer[2 * SPX_N];
|
||||
|
||||
/* If leaf_idx is odd (last bit = 1), current path element is a right child
|
||||
and auth_path has to go left. Otherwise it is the other way around. */
|
||||
if (leaf_idx & 1) {
|
||||
memcpy(buffer + SPX_N, leaf, SPX_N);
|
||||
memcpy(buffer, auth_path, SPX_N);
|
||||
} else {
|
||||
memcpy(buffer, leaf, SPX_N);
|
||||
memcpy(buffer + SPX_N, auth_path, SPX_N);
|
||||
}
|
||||
auth_path += SPX_N;
|
||||
|
||||
for (i = 0; i < tree_height - 1; i++) {
|
||||
leaf_idx >>= 1;
|
||||
idx_offset >>= 1;
|
||||
/* Set the address of the node we're creating. */
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_tree_height(addr, i + 1);
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_tree_index(
|
||||
addr, leaf_idx + idx_offset);
|
||||
|
||||
/* Pick the right or left neighbor, depending on parity of the node. */
|
||||
if (leaf_idx & 1) {
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_thash_2(
|
||||
buffer + SPX_N, buffer, pub_seed, addr, hash_state_seeded);
|
||||
memcpy(buffer, auth_path, SPX_N);
|
||||
} else {
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_thash_2(
|
||||
buffer, buffer, pub_seed, addr, hash_state_seeded);
|
||||
memcpy(buffer + SPX_N, auth_path, SPX_N);
|
||||
}
|
||||
auth_path += SPX_N;
|
||||
}
|
||||
|
||||
/* The last iteration is exceptional; we do not copy an auth_path node. */
|
||||
leaf_idx >>= 1;
|
||||
idx_offset >>= 1;
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_tree_height(addr, tree_height);
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_tree_index(
|
||||
addr, leaf_idx + idx_offset);
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_thash_2(
|
||||
root, buffer, pub_seed, addr, hash_state_seeded);
|
||||
}
|
||||
|
||||
/**
|
||||
* For a given leaf index, computes the authentication path and the resulting
|
||||
* root node using Merkle's TreeHash algorithm.
|
||||
* Expects the layer and tree parts of the tree_addr to be set, as well as the
|
||||
* tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE).
|
||||
* Applies the offset idx_offset to indices before building addresses, so that
|
||||
* it is possible to continue counting indices across trees.
|
||||
*/
|
||||
static void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_treehash(
|
||||
unsigned char *root, unsigned char *auth_path,
|
||||
unsigned char *stack, unsigned int *heights,
|
||||
const unsigned char *sk_seed, const unsigned char *pub_seed,
|
||||
uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height,
|
||||
void (*gen_leaf)(
|
||||
unsigned char * /* leaf */,
|
||||
const unsigned char * /* sk_seed */,
|
||||
const unsigned char * /* pub_seed */,
|
||||
uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */,
|
||||
const hash_state * /* hash_state_seeded */),
|
||||
uint32_t tree_addr[8],
|
||||
const hash_state *hash_state_seeded) {
|
||||
|
||||
unsigned int offset = 0;
|
||||
uint32_t idx;
|
||||
uint32_t tree_idx;
|
||||
|
||||
for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) {
|
||||
/* Add the next leaf node to the stack. */
|
||||
gen_leaf(stack + offset * SPX_N,
|
||||
sk_seed, pub_seed, idx + idx_offset, tree_addr,
|
||||
hash_state_seeded);
|
||||
offset++;
|
||||
heights[offset - 1] = 0;
|
||||
|
||||
/* If this is a node we need for the auth path.. */
|
||||
if ((leaf_idx ^ 0x1) == idx) {
|
||||
memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N);
|
||||
}
|
||||
|
||||
/* While the top-most nodes are of equal height.. */
|
||||
while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) {
|
||||
/* Compute index of the new node, in the next layer. */
|
||||
tree_idx = (idx >> (heights[offset - 1] + 1));
|
||||
|
||||
/* Set the address of the node we're creating. */
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_tree_height(
|
||||
tree_addr, heights[offset - 1] + 1);
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_tree_index(
|
||||
tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1)));
|
||||
/* Hash the top-most nodes from the stack together. */
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_thash_2(
|
||||
stack + (offset - 2)*SPX_N, stack + (offset - 2)*SPX_N,
|
||||
pub_seed, tree_addr, hash_state_seeded);
|
||||
offset--;
|
||||
/* Note that the top-most node is now one layer higher. */
|
||||
heights[offset - 1]++;
|
||||
|
||||
/* If this is a node we need for the auth path.. */
|
||||
if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) {
|
||||
memcpy(auth_path + heights[offset - 1]*SPX_N,
|
||||
stack + (offset - 1)*SPX_N, SPX_N);
|
||||
}
|
||||
}
|
||||
}
|
||||
memcpy(root, stack, SPX_N);
|
||||
}
|
||||
|
||||
/* The wrappers below ensure that we use fixed-size buffers on the stack */
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_treehash_FORS_HEIGHT(
|
||||
unsigned char *root, unsigned char *auth_path,
|
||||
const unsigned char *sk_seed, const unsigned char *pub_seed,
|
||||
uint32_t leaf_idx, uint32_t idx_offset,
|
||||
void (*gen_leaf)(
|
||||
unsigned char * /* leaf */,
|
||||
const unsigned char * /* sk_seed */,
|
||||
const unsigned char * /* pub_seed */,
|
||||
uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */,
|
||||
const hash_state * /* hash_state_seeded */),
|
||||
uint32_t tree_addr[8], const hash_state *hash_state_seeded) {
|
||||
|
||||
unsigned char stack[(SPX_FORS_HEIGHT + 1)*SPX_N];
|
||||
unsigned int heights[SPX_FORS_HEIGHT + 1];
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_treehash(
|
||||
root, auth_path, stack, heights, sk_seed, pub_seed,
|
||||
leaf_idx, idx_offset, SPX_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded);
|
||||
}
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_treehash_TREE_HEIGHT(
|
||||
unsigned char *root, unsigned char *auth_path,
|
||||
const unsigned char *sk_seed, const unsigned char *pub_seed,
|
||||
uint32_t leaf_idx, uint32_t idx_offset,
|
||||
void (*gen_leaf)(
|
||||
unsigned char * /* leaf */,
|
||||
const unsigned char * /* sk_seed */,
|
||||
const unsigned char * /* pub_seed */,
|
||||
uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */,
|
||||
const hash_state * /* hash_state_seeded */),
|
||||
uint32_t tree_addr[8], const hash_state *hash_state_seeded) {
|
||||
|
||||
unsigned char stack[(SPX_TREE_HEIGHT + 1)*SPX_N];
|
||||
unsigned int heights[SPX_TREE_HEIGHT + 1];
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_treehash(
|
||||
root, auth_path, stack, heights, sk_seed, pub_seed,
|
||||
leaf_idx, idx_offset, SPX_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded);
|
||||
}
|
||||
@ -0,0 +1,64 @@
|
||||
#ifndef SPX_UTILS_H
|
||||
#define SPX_UTILS_H
|
||||
|
||||
#include "params.h"
|
||||
#include "hash_state.h"
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* Converts the value of 'in' to 'outlen' bytes in big-endian byte order.
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_ull_to_bytes(
|
||||
unsigned char *out, size_t outlen, unsigned long long in);
|
||||
|
||||
/**
|
||||
* Converts the inlen bytes in 'in' from big-endian byte order to an integer.
|
||||
*/
|
||||
unsigned long long PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_bytes_to_ull(
|
||||
const unsigned char *in, size_t inlen);
|
||||
|
||||
/**
|
||||
* Computes a root node given a leaf and an auth path.
|
||||
* Expects address to be complete other than the tree_height and tree_index.
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_compute_root(
|
||||
unsigned char *root, const unsigned char *leaf,
|
||||
uint32_t leaf_idx, uint32_t idx_offset,
|
||||
const unsigned char *auth_path, uint32_t tree_height,
|
||||
const unsigned char *pub_seed, uint32_t addr[8],
|
||||
const hash_state *hash_state_seeded);
|
||||
|
||||
/**
|
||||
* For a given leaf index, computes the authentication path and the resulting
|
||||
* root node using Merkle's TreeHash algorithm.
|
||||
* Expects the layer and tree parts of the tree_addr to be set, as well as the
|
||||
* tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE).
|
||||
* Applies the offset idx_offset to indices before building addresses, so that
|
||||
* it is possible to continue counting indices across trees.
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_treehash_FORS_HEIGHT(
|
||||
unsigned char *root, unsigned char *auth_path,
|
||||
const unsigned char *sk_seed, const unsigned char *pub_seed,
|
||||
uint32_t leaf_idx, uint32_t idx_offset,
|
||||
void (*gen_leaf)(
|
||||
unsigned char * /* leaf */,
|
||||
const unsigned char * /* sk_seed */,
|
||||
const unsigned char * /* pub_seed */,
|
||||
uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */,
|
||||
const hash_state * /* hash_state_seeded */),
|
||||
uint32_t tree_addr[8], const hash_state *hash_state_seeded);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_treehash_TREE_HEIGHT(
|
||||
unsigned char *root, unsigned char *auth_path,
|
||||
const unsigned char *sk_seed, const unsigned char *pub_seed,
|
||||
uint32_t leaf_idx, uint32_t idx_offset,
|
||||
void (*gen_leaf)(
|
||||
unsigned char * /* leaf */,
|
||||
const unsigned char * /* sk_seed */,
|
||||
const unsigned char * /* pub_seed */,
|
||||
uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */,
|
||||
const hash_state * /* hash_state_seeded */),
|
||||
uint32_t tree_addr[8], const hash_state *hash_state_seeded);
|
||||
|
||||
#endif
|
||||
167
src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/wots.c
Normal file
167
src/sig/sphincs/pqclean_sphincs-sha256-128f-simple_clean/wots.c
Normal file
@ -0,0 +1,167 @@
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "address.h"
|
||||
#include "hash.h"
|
||||
#include "params.h"
|
||||
#include "hash_state.h"
|
||||
#include "thash.h"
|
||||
#include "utils.h"
|
||||
#include "wots.h"
|
||||
|
||||
// TODO clarify address expectations, and make them more uniform.
|
||||
// TODO i.e. do we expect types to be set already?
|
||||
// TODO and do we expect modifications or copies?
|
||||
|
||||
/**
|
||||
* Computes the starting value for a chain, i.e. the secret key.
|
||||
* Expects the address to be complete up to the chain address.
|
||||
*/
|
||||
static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed,
|
||||
uint32_t wots_addr[8],
|
||||
const hash_state *hash_state_seeded) {
|
||||
/* Make sure that the hash address is actually zeroed. */
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_hash_addr(wots_addr, 0);
|
||||
|
||||
/* Generate sk element. */
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_prf_addr(sk, sk_seed, wots_addr, hash_state_seeded);
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the chaining function.
|
||||
* out and in have to be n-byte arrays.
|
||||
*
|
||||
* Interprets in as start-th value of the chain.
|
||||
* addr has to contain the address of the chain.
|
||||
*/
|
||||
static void gen_chain(unsigned char *out, const unsigned char *in,
|
||||
unsigned int start, unsigned int steps,
|
||||
const unsigned char *pub_seed, uint32_t addr[8],
|
||||
const hash_state *hash_state_seeded) {
|
||||
uint32_t i;
|
||||
|
||||
/* Initialize out with the value at position 'start'. */
|
||||
memcpy(out, in, SPX_N);
|
||||
|
||||
/* Iterate 'steps' calls to the hash function. */
|
||||
for (i = start; i < (start + steps) && i < SPX_WOTS_W; i++) {
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_hash_addr(addr, i);
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_thash_1(
|
||||
out, out, pub_seed, addr, hash_state_seeded);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* base_w algorithm as described in draft.
|
||||
* Interprets an array of bytes as integers in base w.
|
||||
* This only works when log_w is a divisor of 8.
|
||||
*/
|
||||
static void base_w(unsigned int *output, const size_t out_len,
|
||||
const unsigned char *input) {
|
||||
size_t in = 0;
|
||||
size_t out = 0;
|
||||
unsigned char total = 0;
|
||||
unsigned int bits = 0;
|
||||
size_t consumed;
|
||||
|
||||
for (consumed = 0; consumed < out_len; consumed++) {
|
||||
if (bits == 0) {
|
||||
total = input[in];
|
||||
in++;
|
||||
bits += 8;
|
||||
}
|
||||
bits -= SPX_WOTS_LOGW;
|
||||
output[out] = (unsigned int)((total >> bits) & (SPX_WOTS_W - 1));
|
||||
out++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Computes the WOTS+ checksum over a message (in base_w). */
|
||||
static void wots_checksum(unsigned int *csum_base_w,
|
||||
const unsigned int *msg_base_w) {
|
||||
unsigned int csum = 0;
|
||||
unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8];
|
||||
unsigned int i;
|
||||
|
||||
/* Compute checksum. */
|
||||
for (i = 0; i < SPX_WOTS_LEN1; i++) {
|
||||
csum += SPX_WOTS_W - 1 - msg_base_w[i];
|
||||
}
|
||||
|
||||
/* Convert checksum to base_w. */
|
||||
/* Make sure expected empty zero bits are the least significant bits. */
|
||||
csum = csum << (8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8));
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_ull_to_bytes(
|
||||
csum_bytes, sizeof(csum_bytes), csum);
|
||||
base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes);
|
||||
}
|
||||
|
||||
/* Takes a message and derives the matching chain lengths. */
|
||||
static void chain_lengths(unsigned int *lengths, const unsigned char *msg) {
|
||||
base_w(lengths, SPX_WOTS_LEN1, msg);
|
||||
wots_checksum(lengths + SPX_WOTS_LEN1, lengths);
|
||||
}
|
||||
|
||||
/**
|
||||
* WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key
|
||||
* elements and computes the corresponding public key.
|
||||
* It requires the seed pub_seed (used to generate bitmasks and hash keys)
|
||||
* and the address of this WOTS key pair.
|
||||
*
|
||||
* Writes the computed public key to 'pk'.
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_wots_gen_pk(
|
||||
unsigned char *pk, const unsigned char *sk_seed,
|
||||
const unsigned char *pub_seed, uint32_t addr[8],
|
||||
const hash_state *hash_state_seeded) {
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < SPX_WOTS_LEN; i++) {
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_chain_addr(addr, i);
|
||||
wots_gen_sk(pk + i * SPX_N, sk_seed, addr, hash_state_seeded);
|
||||
gen_chain(pk + i * SPX_N, pk + i * SPX_N,
|
||||
0, SPX_WOTS_W - 1, pub_seed, addr, hash_state_seeded);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'.
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_wots_sign(
|
||||
unsigned char *sig, const unsigned char *msg,
|
||||
const unsigned char *sk_seed, const unsigned char *pub_seed,
|
||||
uint32_t addr[8], const hash_state *hash_state_seeded) {
|
||||
unsigned int lengths[SPX_WOTS_LEN];
|
||||
uint32_t i;
|
||||
|
||||
chain_lengths(lengths, msg);
|
||||
|
||||
for (i = 0; i < SPX_WOTS_LEN; i++) {
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_chain_addr(addr, i);
|
||||
wots_gen_sk(sig + i * SPX_N, sk_seed, addr, hash_state_seeded);
|
||||
gen_chain(sig + i * SPX_N, sig + i * SPX_N, 0, lengths[i], pub_seed, addr, hash_state_seeded);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes a WOTS signature and an n-byte message, computes a WOTS public key.
|
||||
*
|
||||
* Writes the computed public key to 'pk'.
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_wots_pk_from_sig(
|
||||
unsigned char *pk,
|
||||
const unsigned char *sig, const unsigned char *msg,
|
||||
const unsigned char *pub_seed, uint32_t addr[8],
|
||||
const hash_state *hash_state_seeded) {
|
||||
unsigned int lengths[SPX_WOTS_LEN];
|
||||
uint32_t i;
|
||||
|
||||
chain_lengths(lengths, msg);
|
||||
|
||||
for (i = 0; i < SPX_WOTS_LEN; i++) {
|
||||
PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_set_chain_addr(addr, i);
|
||||
gen_chain(pk + i * SPX_N, sig + i * SPX_N,
|
||||
lengths[i], SPX_WOTS_W - 1 - lengths[i], pub_seed, addr,
|
||||
hash_state_seeded);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,41 @@
|
||||
#ifndef SPX_WOTS_H
|
||||
#define SPX_WOTS_H
|
||||
|
||||
#include "params.h"
|
||||
#include "hash_state.h"
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* WOTS key generation. Takes a 32 byte seed for the private key, expands it to
|
||||
* a full WOTS private key and computes the corresponding public key.
|
||||
* It requires the seed pub_seed (used to generate bitmasks and hash keys)
|
||||
* and the address of this WOTS key pair.
|
||||
*
|
||||
* Writes the computed public key to 'pk'.
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_wots_gen_pk(
|
||||
unsigned char *pk, const unsigned char *sk_seed,
|
||||
const unsigned char *pub_seed, uint32_t addr[8],
|
||||
const hash_state *hash_state_seeded);
|
||||
|
||||
/**
|
||||
* Takes a n-byte message and the 32-byte seed for the private key to compute a
|
||||
* signature that is placed at 'sig'.
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_wots_sign(
|
||||
unsigned char *sig, const unsigned char *msg,
|
||||
const unsigned char *sk_seed, const unsigned char *pub_seed,
|
||||
uint32_t addr[8], const hash_state *hash_state_seeded);
|
||||
|
||||
/**
|
||||
* Takes a WOTS signature and an n-byte message, computes a WOTS public key.
|
||||
*
|
||||
* Writes the computed public key to 'pk'.
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_wots_pk_from_sig(
|
||||
unsigned char *pk,
|
||||
const unsigned char *sig, const unsigned char *msg,
|
||||
const unsigned char *pub_seed, uint32_t addr[8],
|
||||
const hash_state *hash_state_seeded);
|
||||
|
||||
#endif
|
||||
116
src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/LICENSE
Normal file
116
src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/LICENSE
Normal file
@ -0,0 +1,116 @@
|
||||
CC0 1.0 Universal
|
||||
|
||||
Statement of Purpose
|
||||
|
||||
The laws of most jurisdictions throughout the world automatically confer
|
||||
exclusive Copyright and Related Rights (defined below) upon the creator and
|
||||
subsequent owner(s) (each and all, an "owner") of an original work of
|
||||
authorship and/or a database (each, a "Work").
|
||||
|
||||
Certain owners wish to permanently relinquish those rights to a Work for the
|
||||
purpose of contributing to a commons of creative, cultural and scientific
|
||||
works ("Commons") that the public can reliably and without fear of later
|
||||
claims of infringement build upon, modify, incorporate in other works, reuse
|
||||
and redistribute as freely as possible in any form whatsoever and for any
|
||||
purposes, including without limitation commercial purposes. These owners may
|
||||
contribute to the Commons to promote the ideal of a free culture and the
|
||||
further production of creative, cultural and scientific works, or to gain
|
||||
reputation or greater distribution for their Work in part through the use and
|
||||
efforts of others.
|
||||
|
||||
For these and/or other purposes and motivations, and without any expectation
|
||||
of additional consideration or compensation, the person associating CC0 with a
|
||||
Work (the "Affirmer"), to the extent that he or she is an owner of Copyright
|
||||
and Related Rights in the Work, voluntarily elects to apply CC0 to the Work
|
||||
and publicly distribute the Work under its terms, with knowledge of his or her
|
||||
Copyright and Related Rights in the Work and the meaning and intended legal
|
||||
effect of CC0 on those rights.
|
||||
|
||||
1. Copyright and Related Rights. A Work made available under CC0 may be
|
||||
protected by copyright and related or neighboring rights ("Copyright and
|
||||
Related Rights"). Copyright and Related Rights include, but are not limited
|
||||
to, the following:
|
||||
|
||||
i. the right to reproduce, adapt, distribute, perform, display, communicate,
|
||||
and translate a Work;
|
||||
|
||||
ii. moral rights retained by the original author(s) and/or performer(s);
|
||||
|
||||
iii. publicity and privacy rights pertaining to a person's image or likeness
|
||||
depicted in a Work;
|
||||
|
||||
iv. rights protecting against unfair competition in regards to a Work,
|
||||
subject to the limitations in paragraph 4(a), below;
|
||||
|
||||
v. rights protecting the extraction, dissemination, use and reuse of data in
|
||||
a Work;
|
||||
|
||||
vi. database rights (such as those arising under Directive 96/9/EC of the
|
||||
European Parliament and of the Council of 11 March 1996 on the legal
|
||||
protection of databases, and under any national implementation thereof,
|
||||
including any amended or successor version of such directive); and
|
||||
|
||||
vii. other similar, equivalent or corresponding rights throughout the world
|
||||
based on applicable law or treaty, and any national implementations thereof.
|
||||
|
||||
2. Waiver. To the greatest extent permitted by, but not in contravention of,
|
||||
applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and
|
||||
unconditionally waives, abandons, and surrenders all of Affirmer's Copyright
|
||||
and Related Rights and associated claims and causes of action, whether now
|
||||
known or unknown (including existing as well as future claims and causes of
|
||||
action), in the Work (i) in all territories worldwide, (ii) for the maximum
|
||||
duration provided by applicable law or treaty (including future time
|
||||
extensions), (iii) in any current or future medium and for any number of
|
||||
copies, and (iv) for any purpose whatsoever, including without limitation
|
||||
commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes
|
||||
the Waiver for the benefit of each member of the public at large and to the
|
||||
detriment of Affirmer's heirs and successors, fully intending that such Waiver
|
||||
shall not be subject to revocation, rescission, cancellation, termination, or
|
||||
any other legal or equitable action to disrupt the quiet enjoyment of the Work
|
||||
by the public as contemplated by Affirmer's express Statement of Purpose.
|
||||
|
||||
3. Public License Fallback. Should any part of the Waiver for any reason be
|
||||
judged legally invalid or ineffective under applicable law, then the Waiver
|
||||
shall be preserved to the maximum extent permitted taking into account
|
||||
Affirmer's express Statement of Purpose. In addition, to the extent the Waiver
|
||||
is so judged Affirmer hereby grants to each affected person a royalty-free,
|
||||
non transferable, non sublicensable, non exclusive, irrevocable and
|
||||
unconditional license to exercise Affirmer's Copyright and Related Rights in
|
||||
the Work (i) in all territories worldwide, (ii) for the maximum duration
|
||||
provided by applicable law or treaty (including future time extensions), (iii)
|
||||
in any current or future medium and for any number of copies, and (iv) for any
|
||||
purpose whatsoever, including without limitation commercial, advertising or
|
||||
promotional purposes (the "License"). The License shall be deemed effective as
|
||||
of the date CC0 was applied by Affirmer to the Work. Should any part of the
|
||||
License for any reason be judged legally invalid or ineffective under
|
||||
applicable law, such partial invalidity or ineffectiveness shall not
|
||||
invalidate the remainder of the License, and in such case Affirmer hereby
|
||||
affirms that he or she will not (i) exercise any of his or her remaining
|
||||
Copyright and Related Rights in the Work or (ii) assert any associated claims
|
||||
and causes of action with respect to the Work, in either case contrary to
|
||||
Affirmer's express Statement of Purpose.
|
||||
|
||||
4. Limitations and Disclaimers.
|
||||
|
||||
a. No trademark or patent rights held by Affirmer are waived, abandoned,
|
||||
surrendered, licensed or otherwise affected by this document.
|
||||
|
||||
b. Affirmer offers the Work as-is and makes no representations or warranties
|
||||
of any kind concerning the Work, express, implied, statutory or otherwise,
|
||||
including without limitation warranties of title, merchantability, fitness
|
||||
for a particular purpose, non infringement, or the absence of latent or
|
||||
other defects, accuracy, or the present or absence of errors, whether or not
|
||||
discoverable, all to the greatest extent permissible under applicable law.
|
||||
|
||||
c. Affirmer disclaims responsibility for clearing rights of other persons
|
||||
that may apply to the Work or any use thereof, including without limitation
|
||||
any person's Copyright and Related Rights in the Work. Further, Affirmer
|
||||
disclaims responsibility for obtaining any necessary consents, permissions
|
||||
or other rights required for any use of the Work.
|
||||
|
||||
d. Affirmer understands and acknowledges that Creative Commons is not a
|
||||
party to this document and has no duty or obligation with respect to this
|
||||
CC0 or use of the Work.
|
||||
|
||||
For more information, please see
|
||||
<http://creativecommons.org/publicdomain/zero/1.0/>
|
||||
@ -0,0 +1,78 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#include "address.h"
|
||||
#include "params.h"
|
||||
#include "utils.h"
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_addr_to_bytes(
|
||||
unsigned char *bytes, const uint32_t addr[8]) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_ull_to_bytes(
|
||||
bytes + i * 4, 4, addr[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_layer_addr(
|
||||
uint32_t addr[8], uint32_t layer) {
|
||||
addr[0] = layer;
|
||||
}
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_tree_addr(
|
||||
uint32_t addr[8], uint64_t tree) {
|
||||
addr[1] = 0;
|
||||
addr[2] = (uint32_t) (tree >> 32);
|
||||
addr[3] = (uint32_t) tree;
|
||||
}
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_type(
|
||||
uint32_t addr[8], uint32_t type) {
|
||||
addr[4] = type;
|
||||
}
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_copy_subtree_addr(
|
||||
uint32_t out[8], const uint32_t in[8]) {
|
||||
out[0] = in[0];
|
||||
out[1] = in[1];
|
||||
out[2] = in[2];
|
||||
out[3] = in[3];
|
||||
}
|
||||
|
||||
/* These functions are used for OTS addresses. */
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_keypair_addr(
|
||||
uint32_t addr[8], uint32_t keypair) {
|
||||
addr[5] = keypair;
|
||||
}
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_copy_keypair_addr(
|
||||
uint32_t out[8], const uint32_t in[8]) {
|
||||
out[0] = in[0];
|
||||
out[1] = in[1];
|
||||
out[2] = in[2];
|
||||
out[3] = in[3];
|
||||
out[5] = in[5];
|
||||
}
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_chain_addr(
|
||||
uint32_t addr[8], uint32_t chain) {
|
||||
addr[6] = chain;
|
||||
}
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_hash_addr(
|
||||
uint32_t addr[8], uint32_t hash) {
|
||||
addr[7] = hash;
|
||||
}
|
||||
|
||||
/* These functions are used for all hash tree addresses (including FORS). */
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_tree_height(
|
||||
uint32_t addr[8], uint32_t tree_height) {
|
||||
addr[6] = tree_height;
|
||||
}
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_tree_index(
|
||||
uint32_t addr[8], uint32_t tree_index) {
|
||||
addr[7] = tree_index;
|
||||
}
|
||||
@ -0,0 +1,50 @@
|
||||
#ifndef SPX_ADDRESS_H
|
||||
#define SPX_ADDRESS_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define SPX_ADDR_TYPE_WOTS 0
|
||||
#define SPX_ADDR_TYPE_WOTSPK 1
|
||||
#define SPX_ADDR_TYPE_HASHTREE 2
|
||||
#define SPX_ADDR_TYPE_FORSTREE 3
|
||||
#define SPX_ADDR_TYPE_FORSPK 4
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_addr_to_bytes(
|
||||
unsigned char *bytes, const uint32_t addr[8]);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_layer_addr(
|
||||
uint32_t addr[8], uint32_t layer);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_tree_addr(
|
||||
uint32_t addr[8], uint64_t tree);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_type(
|
||||
uint32_t addr[8], uint32_t type);
|
||||
|
||||
/* Copies the layer and tree part of one address into the other */
|
||||
void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_copy_subtree_addr(
|
||||
uint32_t out[8], const uint32_t in[8]);
|
||||
|
||||
/* These functions are used for WOTS and FORS addresses. */
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_keypair_addr(
|
||||
uint32_t addr[8], uint32_t keypair);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_chain_addr(
|
||||
uint32_t addr[8], uint32_t chain);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_hash_addr(
|
||||
uint32_t addr[8], uint32_t hash);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_copy_keypair_addr(
|
||||
uint32_t out[8], const uint32_t in[8]);
|
||||
|
||||
/* These functions are used for all hash tree addresses (including FORS). */
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_tree_height(
|
||||
uint32_t addr[8], uint32_t tree_height);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_tree_index(
|
||||
uint32_t addr[8], uint32_t tree_index);
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,78 @@
|
||||
#ifndef PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_API_H
|
||||
#define PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_API_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_CRYPTO_ALGNAME "SPHINCS+"
|
||||
|
||||
#define PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_CRYPTO_SECRETKEYBYTES 64
|
||||
#define PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_CRYPTO_PUBLICKEYBYTES 32
|
||||
#define PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_CRYPTO_BYTES 8080
|
||||
#define PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_CRYPTO_SEEDBYTES 48
|
||||
|
||||
/*
|
||||
* Returns the length of a secret key, in bytes
|
||||
*/
|
||||
size_t PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_crypto_sign_secretkeybytes(void);
|
||||
|
||||
/*
|
||||
* Returns the length of a public key, in bytes
|
||||
*/
|
||||
size_t PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_crypto_sign_publickeybytes(void);
|
||||
|
||||
/*
|
||||
* Returns the length of a signature, in bytes
|
||||
*/
|
||||
size_t PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_crypto_sign_bytes(void);
|
||||
|
||||
/*
|
||||
* Returns the length of the seed required to generate a key pair, in bytes
|
||||
*/
|
||||
size_t PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_crypto_sign_seedbytes(void);
|
||||
|
||||
/*
|
||||
* Generates a SPHINCS+ key pair given a seed.
|
||||
* Format sk: [SK_SEED || SK_PRF || PUB_SEED || root]
|
||||
* Format pk: [root || PUB_SEED]
|
||||
*/
|
||||
int PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_crypto_sign_seed_keypair(
|
||||
uint8_t *pk, uint8_t *sk, const uint8_t *seed);
|
||||
|
||||
/*
|
||||
* Generates a SPHINCS+ key pair.
|
||||
* Format sk: [SK_SEED || SK_PRF || PUB_SEED || root]
|
||||
* Format pk: [root || PUB_SEED]
|
||||
*/
|
||||
int PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_crypto_sign_keypair(
|
||||
uint8_t *pk, uint8_t *sk);
|
||||
|
||||
/**
|
||||
* Returns an array containing a detached signature.
|
||||
*/
|
||||
int PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_crypto_sign_signature(
|
||||
uint8_t *sig, size_t *siglen,
|
||||
const uint8_t *m, size_t mlen, const uint8_t *sk);
|
||||
|
||||
/**
|
||||
* Verifies a detached signature and message under a given public key.
|
||||
*/
|
||||
int PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_crypto_sign_verify(
|
||||
const uint8_t *sig, size_t siglen,
|
||||
const uint8_t *m, size_t mlen, const uint8_t *pk);
|
||||
|
||||
/**
|
||||
* Returns an array containing the signature followed by the message.
|
||||
*/
|
||||
int PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_crypto_sign(
|
||||
uint8_t *sm, size_t *smlen,
|
||||
const uint8_t *m, size_t mlen, const uint8_t *sk);
|
||||
|
||||
/**
|
||||
* Verifies a given signature-message pair under a given public key.
|
||||
*/
|
||||
int PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_crypto_sign_open(
|
||||
uint8_t *m, size_t *mlen,
|
||||
const uint8_t *sm, size_t smlen, const uint8_t *pk);
|
||||
|
||||
#endif
|
||||
169
src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/fors.c
Normal file
169
src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/fors.c
Normal file
@ -0,0 +1,169 @@
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "address.h"
|
||||
#include "fors.h"
|
||||
#include "hash.h"
|
||||
#include "hash_state.h"
|
||||
#include "thash.h"
|
||||
#include "utils.h"
|
||||
|
||||
static void fors_gen_sk(unsigned char *sk, const unsigned char *sk_seed,
|
||||
uint32_t fors_leaf_addr[8], const hash_state *hash_state_seeded) {
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_prf_addr(
|
||||
sk, sk_seed, fors_leaf_addr, hash_state_seeded);
|
||||
}
|
||||
|
||||
static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk,
|
||||
const unsigned char *pub_seed,
|
||||
uint32_t fors_leaf_addr[8],
|
||||
const hash_state *hash_state_seeded) {
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_thash_1(
|
||||
leaf, sk, pub_seed, fors_leaf_addr, hash_state_seeded);
|
||||
}
|
||||
|
||||
static void fors_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed,
|
||||
const unsigned char *pub_seed,
|
||||
uint32_t addr_idx, const uint32_t fors_tree_addr[8],
|
||||
const hash_state *hash_state_seeded) {
|
||||
uint32_t fors_leaf_addr[8] = {0};
|
||||
|
||||
/* Only copy the parts that must be kept in fors_leaf_addr. */
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_copy_keypair_addr(
|
||||
fors_leaf_addr, fors_tree_addr);
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_type(
|
||||
fors_leaf_addr, SPX_ADDR_TYPE_FORSTREE);
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_tree_index(
|
||||
fors_leaf_addr, addr_idx);
|
||||
|
||||
fors_gen_sk(leaf, sk_seed, fors_leaf_addr, hash_state_seeded);
|
||||
fors_sk_to_leaf(leaf, leaf, pub_seed, fors_leaf_addr, hash_state_seeded);
|
||||
}
|
||||
|
||||
/**
|
||||
* Interprets m as SPX_FORS_HEIGHT-bit unsigned integers.
|
||||
* Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits.
|
||||
* Assumes indices has space for SPX_FORS_TREES integers.
|
||||
*/
|
||||
static void message_to_indices(uint32_t *indices, const unsigned char *m) {
|
||||
unsigned int i, j;
|
||||
unsigned int offset = 0;
|
||||
|
||||
for (i = 0; i < SPX_FORS_TREES; i++) {
|
||||
indices[i] = 0;
|
||||
for (j = 0; j < SPX_FORS_HEIGHT; j++) {
|
||||
indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j;
|
||||
offset++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Signs a message m, deriving the secret key from sk_seed and the FTS address.
|
||||
* Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits.
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_fors_sign(
|
||||
unsigned char *sig, unsigned char *pk,
|
||||
const unsigned char *m,
|
||||
const unsigned char *sk_seed, const unsigned char *pub_seed,
|
||||
const uint32_t fors_addr[8], const hash_state *hash_state_seeded) {
|
||||
uint32_t indices[SPX_FORS_TREES];
|
||||
unsigned char roots[SPX_FORS_TREES * SPX_N];
|
||||
uint32_t fors_tree_addr[8] = {0};
|
||||
uint32_t fors_pk_addr[8] = {0};
|
||||
uint32_t idx_offset;
|
||||
unsigned int i;
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_copy_keypair_addr(
|
||||
fors_tree_addr, fors_addr);
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_copy_keypair_addr(
|
||||
fors_pk_addr, fors_addr);
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_type(
|
||||
fors_tree_addr, SPX_ADDR_TYPE_FORSTREE);
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_type(
|
||||
fors_pk_addr, SPX_ADDR_TYPE_FORSPK);
|
||||
|
||||
message_to_indices(indices, m);
|
||||
|
||||
for (i = 0; i < SPX_FORS_TREES; i++) {
|
||||
idx_offset = i * (1 << SPX_FORS_HEIGHT);
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_tree_height(
|
||||
fors_tree_addr, 0);
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_tree_index(
|
||||
fors_tree_addr, indices[i] + idx_offset);
|
||||
|
||||
/* Include the secret key part that produces the selected leaf node. */
|
||||
fors_gen_sk(sig, sk_seed, fors_tree_addr, hash_state_seeded);
|
||||
sig += SPX_N;
|
||||
|
||||
/* Compute the authentication path for this leaf node. */
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_treehash_FORS_HEIGHT(
|
||||
roots + i * SPX_N, sig, sk_seed, pub_seed,
|
||||
indices[i], idx_offset, fors_gen_leaf, fors_tree_addr,
|
||||
hash_state_seeded);
|
||||
sig += SPX_N * SPX_FORS_HEIGHT;
|
||||
}
|
||||
|
||||
/* Hash horizontally across all tree roots to derive the public key. */
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_thash_FORS_TREES(
|
||||
pk, roots, pub_seed, fors_pk_addr, hash_state_seeded);
|
||||
}
|
||||
|
||||
/**
|
||||
* Derives the FORS public key from a signature.
|
||||
* This can be used for verification by comparing to a known public key, or to
|
||||
* subsequently verify a signature on the derived public key. The latter is the
|
||||
* typical use-case when used as an FTS below an OTS in a hypertree.
|
||||
* Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits.
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_fors_pk_from_sig(
|
||||
unsigned char *pk,
|
||||
const unsigned char *sig, const unsigned char *m,
|
||||
const unsigned char *pub_seed, const uint32_t fors_addr[8],
|
||||
const hash_state *hash_state_seeded) {
|
||||
uint32_t indices[SPX_FORS_TREES];
|
||||
unsigned char roots[SPX_FORS_TREES * SPX_N];
|
||||
unsigned char leaf[SPX_N];
|
||||
uint32_t fors_tree_addr[8] = {0};
|
||||
uint32_t fors_pk_addr[8] = {0};
|
||||
uint32_t idx_offset;
|
||||
unsigned int i;
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_copy_keypair_addr(
|
||||
fors_tree_addr, fors_addr);
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_copy_keypair_addr(
|
||||
fors_pk_addr, fors_addr);
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_type(
|
||||
fors_tree_addr, SPX_ADDR_TYPE_FORSTREE);
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_type(
|
||||
fors_pk_addr, SPX_ADDR_TYPE_FORSPK);
|
||||
|
||||
message_to_indices(indices, m);
|
||||
|
||||
for (i = 0; i < SPX_FORS_TREES; i++) {
|
||||
idx_offset = i * (1 << SPX_FORS_HEIGHT);
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_tree_height(
|
||||
fors_tree_addr, 0);
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_tree_index(
|
||||
fors_tree_addr, indices[i] + idx_offset);
|
||||
|
||||
/* Derive the leaf from the included secret key part. */
|
||||
fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, hash_state_seeded);
|
||||
sig += SPX_N;
|
||||
|
||||
/* Derive the corresponding root node of this tree. */
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_compute_root(
|
||||
roots + i * SPX_N, leaf, indices[i], idx_offset, sig,
|
||||
SPX_FORS_HEIGHT, pub_seed, fors_tree_addr, hash_state_seeded);
|
||||
sig += SPX_N * SPX_FORS_HEIGHT;
|
||||
}
|
||||
|
||||
/* Hash horizontally across all tree roots to derive the public key. */
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_thash_FORS_TREES(
|
||||
pk, roots, pub_seed, fors_pk_addr, hash_state_seeded);
|
||||
}
|
||||
@ -0,0 +1,32 @@
|
||||
#ifndef SPX_FORS_H
|
||||
#define SPX_FORS_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "params.h"
|
||||
#include "hash_state.h"
|
||||
|
||||
/**
|
||||
* Signs a message m, deriving the secret key from sk_seed and the FTS address.
|
||||
* Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits.
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_fors_sign(
|
||||
unsigned char *sig, unsigned char *pk,
|
||||
const unsigned char *m,
|
||||
const unsigned char *sk_seed, const unsigned char *pub_seed,
|
||||
const uint32_t fors_addr[8], const hash_state *hash_state_seeded);
|
||||
|
||||
/**
|
||||
* Derives the FORS public key from a signature.
|
||||
* This can be used for verification by comparing to a known public key, or to
|
||||
* subsequently verify a signature on the derived public key. The latter is the
|
||||
* typical use-case when used as an FTS below an OTS in a hypertree.
|
||||
* Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits.
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_fors_pk_from_sig(
|
||||
unsigned char *pk,
|
||||
const unsigned char *sig, const unsigned char *m,
|
||||
const unsigned char *pub_seed, const uint32_t fors_addr[8],
|
||||
const hash_state *hash_state_seeded);
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,29 @@
|
||||
#ifndef SPX_HASH_H
|
||||
#define SPX_HASH_H
|
||||
|
||||
#include "hash_state.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_initialize_hash_function(
|
||||
hash_state *hash_state_seeded,
|
||||
const unsigned char *pub_seed, const unsigned char *sk_seed);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_prf_addr(
|
||||
unsigned char *out, const unsigned char *key, const uint32_t addr[8],
|
||||
const hash_state *hash_state_seeded);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_gen_message_random(
|
||||
unsigned char *R,
|
||||
const unsigned char *sk_prf, const unsigned char *optrand,
|
||||
const unsigned char *m, size_t mlen,
|
||||
const hash_state *hash_state_seeded);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_hash_message(
|
||||
unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx,
|
||||
const unsigned char *R, const unsigned char *pk,
|
||||
const unsigned char *m, size_t mlen,
|
||||
const hash_state *hash_state_seeded);
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,157 @@
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "address.h"
|
||||
#include "hash.h"
|
||||
#include "params.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include "sha2.h"
|
||||
#include "sha256.h"
|
||||
|
||||
/* For SHA256, there is no immediate reason to initialize at the start,
|
||||
so this function is an empty operation. */
|
||||
void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_initialize_hash_function(
|
||||
hash_state *hash_state_seeded,
|
||||
const unsigned char *pub_seed, const unsigned char *sk_seed) {
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_seed_state(hash_state_seeded, pub_seed);
|
||||
(void)sk_seed; /* Suppress an 'unused parameter' warning. */
|
||||
}
|
||||
|
||||
/*
|
||||
* Computes PRF(key, addr), given a secret key of SPX_N bytes and an address
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_prf_addr(
|
||||
unsigned char *out, const unsigned char *key, const uint32_t addr[8],
|
||||
const hash_state *hash_state_seeded) {
|
||||
unsigned char buf[SPX_N + SPX_SHA256_ADDR_BYTES];
|
||||
unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES];
|
||||
|
||||
memcpy(buf, key, SPX_N);
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_compress_address(buf + SPX_N, addr);
|
||||
|
||||
sha256(outbuf, buf, SPX_N + SPX_SHA256_ADDR_BYTES);
|
||||
memcpy(out, outbuf, SPX_N);
|
||||
|
||||
(void)hash_state_seeded; /* Prevent unused parameter warning. */
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the message-dependent randomness R, using a secret seed as a key
|
||||
* for HMAC, and an optional randomization value prefixed to the message.
|
||||
* This requires m to have at least SPX_SHA256_BLOCK_BYTES + SPX_N space
|
||||
* available in front of the pointer, i.e. before the message to use for the
|
||||
* prefix. This is necessary to prevent having to move the message around (and
|
||||
* allocate memory for it).
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_gen_message_random(
|
||||
unsigned char *R,
|
||||
const unsigned char *sk_prf, const unsigned char *optrand,
|
||||
const unsigned char *m, size_t mlen, const hash_state *hash_state_seeded) {
|
||||
unsigned char buf[SPX_SHA256_BLOCK_BYTES + SPX_SHA256_OUTPUT_BYTES];
|
||||
sha256ctx state;
|
||||
int i;
|
||||
|
||||
/* This implements HMAC-SHA256 */
|
||||
for (i = 0; i < SPX_N; i++) {
|
||||
buf[i] = 0x36 ^ sk_prf[i];
|
||||
}
|
||||
memset(buf + SPX_N, 0x36, SPX_SHA256_BLOCK_BYTES - SPX_N);
|
||||
|
||||
sha256_inc_init(&state);
|
||||
sha256_inc_blocks(&state, buf, 1);
|
||||
|
||||
memcpy(buf, optrand, SPX_N);
|
||||
|
||||
/* If optrand + message cannot fill up an entire block */
|
||||
if (SPX_N + mlen < SPX_SHA256_BLOCK_BYTES) {
|
||||
memcpy(buf + SPX_N, m, mlen);
|
||||
sha256_inc_finalize(buf + SPX_SHA256_BLOCK_BYTES, &state,
|
||||
buf, mlen + SPX_N);
|
||||
}
|
||||
/* Otherwise first fill a block, so that finalize only uses the message */
|
||||
else {
|
||||
memcpy(buf + SPX_N, m, SPX_SHA256_BLOCK_BYTES - SPX_N);
|
||||
sha256_inc_blocks(&state, buf, 1);
|
||||
|
||||
m += SPX_SHA256_BLOCK_BYTES - SPX_N;
|
||||
mlen -= SPX_SHA256_BLOCK_BYTES - SPX_N;
|
||||
sha256_inc_finalize(buf + SPX_SHA256_BLOCK_BYTES, &state, m, mlen);
|
||||
}
|
||||
|
||||
for (i = 0; i < SPX_N; i++) {
|
||||
buf[i] = 0x5c ^ sk_prf[i];
|
||||
}
|
||||
memset(buf + SPX_N, 0x5c, SPX_SHA256_BLOCK_BYTES - SPX_N);
|
||||
|
||||
sha256(buf, buf, SPX_SHA256_BLOCK_BYTES + SPX_SHA256_OUTPUT_BYTES);
|
||||
memcpy(R, buf, SPX_N);
|
||||
|
||||
(void)hash_state_seeded; /* Prevent unused parameter warning. */
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the message hash using R, the public key, and the message.
|
||||
* Outputs the message digest and the index of the leaf. The index is split in
|
||||
* the tree index and the leaf index, for convenient copying to an address.
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_hash_message(
|
||||
unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx,
|
||||
const unsigned char *R, const unsigned char *pk,
|
||||
const unsigned char *m, size_t mlen,
|
||||
const hash_state *hash_state_seeded) {
|
||||
#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1))
|
||||
#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8)
|
||||
#define SPX_LEAF_BITS SPX_TREE_HEIGHT
|
||||
#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8)
|
||||
#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES)
|
||||
|
||||
unsigned char seed[SPX_SHA256_OUTPUT_BYTES + 4];
|
||||
|
||||
/* Round to nearest multiple of SPX_SHA256_BLOCK_BYTES */
|
||||
#define SPX_INBLOCKS (((SPX_N + SPX_PK_BYTES + SPX_SHA256_BLOCK_BYTES - 1) & \
|
||||
-SPX_SHA256_BLOCK_BYTES) / SPX_SHA256_BLOCK_BYTES)
|
||||
unsigned char inbuf[SPX_INBLOCKS * SPX_SHA256_BLOCK_BYTES];
|
||||
|
||||
unsigned char buf[SPX_DGST_BYTES];
|
||||
unsigned char *bufp = buf;
|
||||
sha256ctx state;
|
||||
|
||||
sha256_inc_init(&state);
|
||||
|
||||
memcpy(inbuf, R, SPX_N);
|
||||
memcpy(inbuf + SPX_N, pk, SPX_PK_BYTES);
|
||||
|
||||
/* If R + pk + message cannot fill up an entire block */
|
||||
if (SPX_N + SPX_PK_BYTES + mlen < SPX_INBLOCKS * SPX_SHA256_BLOCK_BYTES) {
|
||||
memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, mlen);
|
||||
sha256_inc_finalize(seed, &state, inbuf, SPX_N + SPX_PK_BYTES + mlen);
|
||||
}
|
||||
/* Otherwise first fill a block, so that finalize only uses the message */
|
||||
else {
|
||||
memcpy(inbuf + SPX_N + SPX_PK_BYTES, m,
|
||||
SPX_INBLOCKS * SPX_SHA256_BLOCK_BYTES - SPX_N - SPX_PK_BYTES);
|
||||
sha256_inc_blocks(&state, inbuf, SPX_INBLOCKS);
|
||||
|
||||
m += SPX_INBLOCKS * SPX_SHA256_BLOCK_BYTES - SPX_N - SPX_PK_BYTES;
|
||||
mlen -= SPX_INBLOCKS * SPX_SHA256_BLOCK_BYTES - SPX_N - SPX_PK_BYTES;
|
||||
sha256_inc_finalize(seed, &state, m, mlen);
|
||||
}
|
||||
|
||||
/* By doing this in two steps, we prevent hashing the message twice;
|
||||
otherwise each iteration in MGF1 would hash the message again. */
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_mgf1(bufp, SPX_DGST_BYTES, seed, SPX_SHA256_OUTPUT_BYTES);
|
||||
|
||||
memcpy(digest, bufp, SPX_FORS_MSG_BYTES);
|
||||
bufp += SPX_FORS_MSG_BYTES;
|
||||
|
||||
*tree = PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_bytes_to_ull(bufp, SPX_TREE_BYTES);
|
||||
*tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS);
|
||||
bufp += SPX_TREE_BYTES;
|
||||
|
||||
*leaf_idx = (uint32_t)PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_bytes_to_ull(
|
||||
bufp, SPX_LEAF_BYTES);
|
||||
*leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS);
|
||||
|
||||
(void)hash_state_seeded; /* Prevent unused parameter warning. */
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
#ifndef SPX_PRIMITIVE_H
|
||||
#define SPX_PRIMITIVE_H
|
||||
|
||||
#include "sha2.h"
|
||||
#define hash_state sha256ctx
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,53 @@
|
||||
#ifndef SPX_PARAMS_H
|
||||
#define SPX_PARAMS_H
|
||||
|
||||
/* Hash output length in bytes. */
|
||||
#define SPX_N 16
|
||||
/* Height of the hypertree. */
|
||||
#define SPX_FULL_HEIGHT 64
|
||||
/* Number of subtree layer. */
|
||||
#define SPX_D 8
|
||||
/* FORS tree dimensions. */
|
||||
#define SPX_FORS_HEIGHT 15
|
||||
#define SPX_FORS_TREES 10
|
||||
/* Winternitz parameter, */
|
||||
#define SPX_WOTS_W 16
|
||||
|
||||
/* The hash function is defined by linking a different hash.c file, as opposed
|
||||
to setting a #define constant. */
|
||||
|
||||
/* For clarity */
|
||||
#define SPX_ADDR_BYTES 32
|
||||
|
||||
/* WOTS parameters. */
|
||||
#define SPX_WOTS_LOGW 4
|
||||
|
||||
#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW)
|
||||
|
||||
/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */
|
||||
#define SPX_WOTS_LEN2 3
|
||||
|
||||
#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2)
|
||||
#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N)
|
||||
#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES
|
||||
|
||||
/* Subtree size. */
|
||||
#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D)
|
||||
|
||||
/* FORS parameters. */
|
||||
#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8)
|
||||
#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N)
|
||||
#define SPX_FORS_PK_BYTES SPX_N
|
||||
|
||||
/* Resulting SPX sizes. */
|
||||
#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\
|
||||
SPX_FULL_HEIGHT * SPX_N)
|
||||
#define SPX_PK_BYTES (2 * SPX_N)
|
||||
#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES)
|
||||
|
||||
/* Optionally, signing can be made non-deterministic using optrand.
|
||||
This can help counter side-channel attacks that would benefit from
|
||||
getting a large number of traces when the signer uses the same nodes. */
|
||||
#define SPX_OPTRAND_BYTES 32
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,71 @@
|
||||
/* Based on the public domain implementation in
|
||||
* crypto_hash/sha512/ref/ from http://bench.cr.yp.to/supercop.html
|
||||
* by D. J. Bernstein */
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "sha2.h"
|
||||
#include "sha256.h"
|
||||
#include "utils.h"
|
||||
|
||||
/*
|
||||
* Compresses an address to a 22-byte sequence.
|
||||
* This reduces the number of required SHA256 compression calls, as the last
|
||||
* block of input is padded with at least 65 bits.
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_compress_address(unsigned char *out, const uint32_t addr[8]) {
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_ull_to_bytes(out, 1, addr[0]); /* drop 3 bytes of the layer field */
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_ull_to_bytes(out + 1, 4, addr[2]); /* drop the highest tree address word */
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_ull_to_bytes(out + 5, 4, addr[3]);
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_ull_to_bytes(out + 9, 1, addr[4]); /* drop 3 bytes of the type field */
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_ull_to_bytes(out + 10, 4, addr[5]);
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_ull_to_bytes(out + 14, 4, addr[6]);
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_ull_to_bytes(out + 18, 4, addr[7]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Requires 'input_plus_four_bytes' to have 'inlen' + 4 bytes, so that the last
|
||||
* four bytes can be used for the counter. Typically 'input' is merely a seed.
|
||||
* Outputs outlen number of bytes
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_mgf1(
|
||||
unsigned char *out, unsigned long outlen,
|
||||
unsigned char *input_plus_four_bytes, unsigned long inlen) {
|
||||
unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES];
|
||||
unsigned long i;
|
||||
|
||||
/* While we can fit in at least another full block of SHA256 output.. */
|
||||
for (i = 0; (i + 1)*SPX_SHA256_OUTPUT_BYTES <= outlen; i++) {
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_ull_to_bytes(input_plus_four_bytes + inlen, 4, i);
|
||||
sha256(out, input_plus_four_bytes, inlen + 4);
|
||||
out += SPX_SHA256_OUTPUT_BYTES;
|
||||
}
|
||||
/* Until we cannot anymore, and we fill the remainder. */
|
||||
if (outlen > i * SPX_SHA256_OUTPUT_BYTES) {
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_ull_to_bytes(input_plus_four_bytes + inlen, 4, i);
|
||||
sha256(outbuf, input_plus_four_bytes, inlen + 4);
|
||||
memcpy(out, outbuf, outlen - i * SPX_SHA256_OUTPUT_BYTES);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Absorb the constant pub_seed using one round of the compression function
|
||||
* This initializes hash_state_seeded, which can then be reused in thash
|
||||
**/
|
||||
void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_seed_state(sha256ctx *hash_state_seeded, const unsigned char *pub_seed) {
|
||||
uint8_t block[SPX_SHA256_BLOCK_BYTES];
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < SPX_N; ++i) {
|
||||
block[i] = pub_seed[i];
|
||||
}
|
||||
for (i = SPX_N; i < SPX_SHA256_BLOCK_BYTES; ++i) {
|
||||
block[i] = 0;
|
||||
}
|
||||
|
||||
sha256_inc_init(hash_state_seeded);
|
||||
sha256_inc_blocks(hash_state_seeded, block, 1);
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
#ifndef SPX_SHA256_H
|
||||
#define SPX_SHA256_H
|
||||
|
||||
#define SPX_SHA256_BLOCK_BYTES 64
|
||||
#define SPX_SHA256_OUTPUT_BYTES 32 /* This does not necessarily equal SPX_N */
|
||||
#define SPX_SHA256_ADDR_BYTES 22
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "sha2.h"
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_compress_address(unsigned char *out, const uint32_t addr[8]);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_mgf1(
|
||||
unsigned char *out, unsigned long outlen,
|
||||
unsigned char *input_plus_four_bytes, unsigned long inlen);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_seed_state(sha256ctx *hash_state_seeded, const unsigned char *pub_seed);
|
||||
|
||||
#endif
|
||||
353
src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/sign.c
Normal file
353
src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/sign.c
Normal file
@ -0,0 +1,353 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "address.h"
|
||||
#include "api.h"
|
||||
#include "fors.h"
|
||||
#include "hash.h"
|
||||
#include "params.h"
|
||||
#include "hash_state.h"
|
||||
#include "randombytes.h"
|
||||
#include "thash.h"
|
||||
#include "utils.h"
|
||||
#include "wots.h"
|
||||
|
||||
/**
|
||||
* Computes the leaf at a given address. First generates the WOTS key pair,
|
||||
* then computes leaf by hashing horizontally.
|
||||
*/
|
||||
static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed,
|
||||
const unsigned char *pub_seed,
|
||||
uint32_t addr_idx, const uint32_t tree_addr[8],
|
||||
const hash_state *hash_state_seeded) {
|
||||
unsigned char pk[SPX_WOTS_BYTES];
|
||||
uint32_t wots_addr[8] = {0};
|
||||
uint32_t wots_pk_addr[8] = {0};
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_type(
|
||||
wots_addr, SPX_ADDR_TYPE_WOTS);
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_type(
|
||||
wots_pk_addr, SPX_ADDR_TYPE_WOTSPK);
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_copy_subtree_addr(
|
||||
wots_addr, tree_addr);
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_keypair_addr(
|
||||
wots_addr, addr_idx);
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_wots_gen_pk(
|
||||
pk, sk_seed, pub_seed, wots_addr, hash_state_seeded);
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_copy_keypair_addr(
|
||||
wots_pk_addr, wots_addr);
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_thash_WOTS_LEN(
|
||||
leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the length of a secret key, in bytes
|
||||
*/
|
||||
size_t PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_crypto_sign_secretkeybytes(void) {
|
||||
return PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_CRYPTO_SECRETKEYBYTES;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the length of a public key, in bytes
|
||||
*/
|
||||
size_t PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_crypto_sign_publickeybytes(void) {
|
||||
return PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_CRYPTO_PUBLICKEYBYTES;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the length of a signature, in bytes
|
||||
*/
|
||||
size_t PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_crypto_sign_bytes(void) {
|
||||
return PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_CRYPTO_BYTES;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the length of the seed required to generate a key pair, in bytes
|
||||
*/
|
||||
size_t PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_crypto_sign_seedbytes(void) {
|
||||
return PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_CRYPTO_SEEDBYTES;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generates an SPX key pair given a seed of length
|
||||
* Format sk: [SK_SEED || SK_PRF || PUB_SEED || root]
|
||||
* Format pk: [PUB_SEED || root]
|
||||
*/
|
||||
int PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_crypto_sign_seed_keypair(
|
||||
uint8_t *pk, uint8_t *sk, const uint8_t *seed) {
|
||||
/* We do not need the auth path in key generation, but it simplifies the
|
||||
code to have just one treehash routine that computes both root and path
|
||||
in one function. */
|
||||
unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N];
|
||||
uint32_t top_tree_addr[8] = {0};
|
||||
hash_state hash_state_seeded;
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_layer_addr(
|
||||
top_tree_addr, SPX_D - 1);
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_type(
|
||||
top_tree_addr, SPX_ADDR_TYPE_HASHTREE);
|
||||
|
||||
/* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */
|
||||
memcpy(sk, seed, PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_CRYPTO_SEEDBYTES);
|
||||
|
||||
memcpy(pk, sk + 2 * SPX_N, SPX_N);
|
||||
|
||||
/* This hook allows the hash function instantiation to do whatever
|
||||
preparation or computation it needs, based on the public seed. */
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_initialize_hash_function(&hash_state_seeded, pk, sk);
|
||||
|
||||
/* Compute root node of the top-most subtree. */
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_treehash_TREE_HEIGHT(
|
||||
sk + 3 * SPX_N, auth_path, sk, sk + 2 * SPX_N, 0, 0,
|
||||
wots_gen_leaf, top_tree_addr, &hash_state_seeded);
|
||||
|
||||
memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generates an SPX key pair.
|
||||
* Format sk: [SK_SEED || SK_PRF || PUB_SEED || root]
|
||||
* Format pk: [PUB_SEED || root]
|
||||
*/
|
||||
int PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_crypto_sign_keypair(
|
||||
uint8_t *pk, uint8_t *sk) {
|
||||
unsigned char seed[PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_CRYPTO_SEEDBYTES];
|
||||
randombytes(seed, PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_CRYPTO_SEEDBYTES);
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_crypto_sign_seed_keypair(
|
||||
pk, sk, seed);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array containing a detached signature.
|
||||
*/
|
||||
int PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_crypto_sign_signature(
|
||||
uint8_t *sig, size_t *siglen,
|
||||
const uint8_t *m, size_t mlen, const uint8_t *sk) {
|
||||
const unsigned char *sk_seed = sk;
|
||||
const unsigned char *sk_prf = sk + SPX_N;
|
||||
const unsigned char *pk = sk + 2 * SPX_N;
|
||||
const unsigned char *pub_seed = pk;
|
||||
|
||||
unsigned char optrand[SPX_N];
|
||||
unsigned char mhash[SPX_FORS_MSG_BYTES];
|
||||
unsigned char root[SPX_N];
|
||||
uint32_t i;
|
||||
uint64_t tree;
|
||||
uint32_t idx_leaf;
|
||||
uint32_t wots_addr[8] = {0};
|
||||
uint32_t tree_addr[8] = {0};
|
||||
|
||||
hash_state hash_state_seeded;
|
||||
|
||||
/* This hook allows the hash function instantiation to do whatever
|
||||
preparation or computation it needs, based on the public seed. */
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_initialize_hash_function(
|
||||
&hash_state_seeded,
|
||||
pub_seed, sk_seed);
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_type(
|
||||
wots_addr, SPX_ADDR_TYPE_WOTS);
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_type(
|
||||
tree_addr, SPX_ADDR_TYPE_HASHTREE);
|
||||
|
||||
/* Optionally, signing can be made non-deterministic using optrand.
|
||||
This can help counter side-channel attacks that would benefit from
|
||||
getting a large number of traces when the signer uses the same nodes. */
|
||||
randombytes(optrand, SPX_N);
|
||||
/* Compute the digest randomization value. */
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_gen_message_random(
|
||||
sig, sk_prf, optrand, m, mlen, &hash_state_seeded);
|
||||
|
||||
/* Derive the message digest and leaf index from R, PK and M. */
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_hash_message(
|
||||
mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded);
|
||||
sig += SPX_N;
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_tree_addr(wots_addr, tree);
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_keypair_addr(
|
||||
wots_addr, idx_leaf);
|
||||
|
||||
/* Sign the message hash using FORS. */
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_fors_sign(
|
||||
sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded);
|
||||
sig += SPX_FORS_BYTES;
|
||||
|
||||
for (i = 0; i < SPX_D; i++) {
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_layer_addr(tree_addr, i);
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_tree_addr(tree_addr, tree);
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_copy_subtree_addr(
|
||||
wots_addr, tree_addr);
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_keypair_addr(
|
||||
wots_addr, idx_leaf);
|
||||
|
||||
/* Compute a WOTS signature. */
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_wots_sign(
|
||||
sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded);
|
||||
sig += SPX_WOTS_BYTES;
|
||||
|
||||
/* Compute the authentication path for the used WOTS leaf. */
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_treehash_TREE_HEIGHT(
|
||||
root, sig, sk_seed, pub_seed, idx_leaf, 0,
|
||||
wots_gen_leaf, tree_addr, &hash_state_seeded);
|
||||
sig += SPX_TREE_HEIGHT * SPX_N;
|
||||
|
||||
/* Update the indices for the next layer. */
|
||||
idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1));
|
||||
tree = tree >> SPX_TREE_HEIGHT;
|
||||
}
|
||||
|
||||
*siglen = SPX_BYTES;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies a detached signature and message under a given public key.
|
||||
*/
|
||||
int PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_crypto_sign_verify(
|
||||
const uint8_t *sig, size_t siglen,
|
||||
const uint8_t *m, size_t mlen, const uint8_t *pk) {
|
||||
const unsigned char *pub_seed = pk;
|
||||
const unsigned char *pub_root = pk + SPX_N;
|
||||
unsigned char mhash[SPX_FORS_MSG_BYTES];
|
||||
unsigned char wots_pk[SPX_WOTS_BYTES];
|
||||
unsigned char root[SPX_N];
|
||||
unsigned char leaf[SPX_N];
|
||||
unsigned int i;
|
||||
uint64_t tree;
|
||||
uint32_t idx_leaf;
|
||||
uint32_t wots_addr[8] = {0};
|
||||
uint32_t tree_addr[8] = {0};
|
||||
uint32_t wots_pk_addr[8] = {0};
|
||||
|
||||
hash_state hash_state_seeded;
|
||||
|
||||
if (siglen != SPX_BYTES) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* This hook allows the hash function instantiation to do whatever
|
||||
preparation or computation it needs, based on the public seed. */
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_initialize_hash_function(
|
||||
&hash_state_seeded,
|
||||
pub_seed, NULL);
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_type(
|
||||
wots_addr, SPX_ADDR_TYPE_WOTS);
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_type(
|
||||
tree_addr, SPX_ADDR_TYPE_HASHTREE);
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_type(
|
||||
wots_pk_addr, SPX_ADDR_TYPE_WOTSPK);
|
||||
|
||||
/* Derive the message digest and leaf index from R || PK || M. */
|
||||
/* The additional SPX_N is a result of the hash domain separator. */
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_hash_message(
|
||||
mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded);
|
||||
sig += SPX_N;
|
||||
|
||||
/* Layer correctly defaults to 0, so no need to set_layer_addr */
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_tree_addr(wots_addr, tree);
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_keypair_addr(
|
||||
wots_addr, idx_leaf);
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_fors_pk_from_sig(
|
||||
root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded);
|
||||
sig += SPX_FORS_BYTES;
|
||||
|
||||
/* For each subtree.. */
|
||||
for (i = 0; i < SPX_D; i++) {
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_layer_addr(tree_addr, i);
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_tree_addr(tree_addr, tree);
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_copy_subtree_addr(
|
||||
wots_addr, tree_addr);
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_keypair_addr(
|
||||
wots_addr, idx_leaf);
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_copy_keypair_addr(
|
||||
wots_pk_addr, wots_addr);
|
||||
|
||||
/* The WOTS public key is only correct if the signature was correct. */
|
||||
/* Initially, root is the FORS pk, but on subsequent iterations it is
|
||||
the root of the subtree below the currently processed subtree. */
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_wots_pk_from_sig(
|
||||
wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded);
|
||||
sig += SPX_WOTS_BYTES;
|
||||
|
||||
/* Compute the leaf node using the WOTS public key. */
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_thash_WOTS_LEN(
|
||||
leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded);
|
||||
|
||||
/* Compute the root node of this subtree. */
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_compute_root(
|
||||
root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT,
|
||||
pub_seed, tree_addr, &hash_state_seeded);
|
||||
sig += SPX_TREE_HEIGHT * SPX_N;
|
||||
|
||||
/* Update the indices for the next layer. */
|
||||
idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1));
|
||||
tree = tree >> SPX_TREE_HEIGHT;
|
||||
}
|
||||
|
||||
/* Check if the root node equals the root node in the public key. */
|
||||
if (memcmp(root, pub_root, SPX_N) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns an array containing the signature followed by the message.
|
||||
*/
|
||||
int PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_crypto_sign(
|
||||
uint8_t *sm, size_t *smlen,
|
||||
const uint8_t *m, size_t mlen, const uint8_t *sk) {
|
||||
size_t siglen;
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_crypto_sign_signature(
|
||||
sm, &siglen, m, mlen, sk);
|
||||
|
||||
memmove(sm + SPX_BYTES, m, mlen);
|
||||
*smlen = siglen + mlen;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies a given signature-message pair under a given public key.
|
||||
*/
|
||||
int PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_crypto_sign_open(
|
||||
uint8_t *m, size_t *mlen,
|
||||
const uint8_t *sm, size_t smlen, const uint8_t *pk) {
|
||||
/* The API caller does not necessarily know what size a signature should be
|
||||
but SPHINCS+ signatures are always exactly SPX_BYTES. */
|
||||
if (smlen < SPX_BYTES) {
|
||||
memset(m, 0, smlen);
|
||||
*mlen = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
*mlen = smlen - SPX_BYTES;
|
||||
|
||||
if (PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_crypto_sign_verify(
|
||||
sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) {
|
||||
memset(m, 0, smlen);
|
||||
*mlen = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* If verification was successful, move the message to the right place. */
|
||||
memmove(m, sm + SPX_BYTES, *mlen);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
#ifndef SPX_THASH_H
|
||||
#define SPX_THASH_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "hash_state.h"
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_thash_1(
|
||||
unsigned char *out, const unsigned char *in,
|
||||
const unsigned char *pub_seed, uint32_t addr[8],
|
||||
const hash_state *hash_state_seeded);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_thash_2(
|
||||
unsigned char *out, const unsigned char *in,
|
||||
const unsigned char *pub_seed, uint32_t addr[8],
|
||||
const hash_state *hash_state_seeded);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_thash_WOTS_LEN(
|
||||
unsigned char *out, const unsigned char *in,
|
||||
const unsigned char *pub_seed, uint32_t addr[8],
|
||||
const hash_state *hash_state_seeded);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_thash_FORS_TREES(
|
||||
unsigned char *out, const unsigned char *in,
|
||||
const unsigned char *pub_seed, uint32_t addr[8],
|
||||
const hash_state *hash_state_seeded);
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,82 @@
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "address.h"
|
||||
#include "params.h"
|
||||
#include "thash.h"
|
||||
|
||||
#include "sha2.h"
|
||||
#include "sha256.h"
|
||||
|
||||
/**
|
||||
* Takes an array of inblocks concatenated arrays of SPX_N bytes.
|
||||
*/
|
||||
static void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_thash(
|
||||
unsigned char *out, unsigned char *buf,
|
||||
const unsigned char *in, unsigned int inblocks,
|
||||
const unsigned char *pub_seed, uint32_t addr[8],
|
||||
const sha256ctx *hash_state_seeded) {
|
||||
|
||||
unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES];
|
||||
unsigned char *bitmask = buf + SPX_N + SPX_SHA256_ADDR_BYTES + 4;
|
||||
sha256ctx sha2_state;
|
||||
unsigned int i;
|
||||
|
||||
memcpy(buf, pub_seed, SPX_N);
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_compress_address(buf + SPX_N, addr);
|
||||
/* MGF1 requires us to have 4 extra bytes in 'buf' */
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_mgf1(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_SHA256_ADDR_BYTES);
|
||||
|
||||
/* Retrieve precomputed state containing pub_seed */
|
||||
sha256_inc_dupe_state(&sha2_state, hash_state_seeded);
|
||||
|
||||
for (i = 0; i < inblocks * SPX_N; i++) {
|
||||
buf[SPX_N + SPX_SHA256_ADDR_BYTES + i] = in[i] ^ bitmask[i];
|
||||
}
|
||||
|
||||
sha256_inc_finalize(outbuf, &sha2_state, buf + SPX_N,
|
||||
SPX_SHA256_ADDR_BYTES + inblocks * SPX_N);
|
||||
memcpy(out, outbuf, SPX_N);
|
||||
}
|
||||
|
||||
/* The wrappers below ensure that we use fixed-size buffers on the stack */
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_thash_1(
|
||||
unsigned char *out, const unsigned char *in,
|
||||
const unsigned char *pub_seed, uint32_t addr[8],
|
||||
const sha256ctx *hash_state_seeded) {
|
||||
|
||||
unsigned char buf[SPX_N + SPX_SHA256_ADDR_BYTES + 4 + 1 * SPX_N];
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_thash(
|
||||
out, buf, in, 1, pub_seed, addr, hash_state_seeded);
|
||||
}
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_thash_2(
|
||||
unsigned char *out, const unsigned char *in,
|
||||
const unsigned char *pub_seed, uint32_t addr[8],
|
||||
const sha256ctx *hash_state_seeded) {
|
||||
|
||||
unsigned char buf[SPX_N + SPX_SHA256_ADDR_BYTES + 4 + 2 * SPX_N];
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_thash(
|
||||
out, buf, in, 2, pub_seed, addr, hash_state_seeded);
|
||||
}
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_thash_WOTS_LEN(
|
||||
unsigned char *out, const unsigned char *in,
|
||||
const unsigned char *pub_seed, uint32_t addr[8],
|
||||
const sha256ctx *hash_state_seeded) {
|
||||
|
||||
unsigned char buf[SPX_N + SPX_SHA256_ADDR_BYTES + 4 + SPX_WOTS_LEN * SPX_N];
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_thash(
|
||||
out, buf, in, SPX_WOTS_LEN, pub_seed, addr, hash_state_seeded);
|
||||
}
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_thash_FORS_TREES(
|
||||
unsigned char *out, const unsigned char *in,
|
||||
const unsigned char *pub_seed, uint32_t addr[8],
|
||||
const sha256ctx *hash_state_seeded) {
|
||||
|
||||
unsigned char buf[SPX_N + SPX_SHA256_ADDR_BYTES + 4 + SPX_FORS_TREES * SPX_N];
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_thash(
|
||||
out, buf, in, SPX_FORS_TREES, pub_seed, addr, hash_state_seeded);
|
||||
}
|
||||
199
src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/utils.c
Normal file
199
src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/utils.c
Normal file
@ -0,0 +1,199 @@
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "address.h"
|
||||
#include "hash.h"
|
||||
#include "params.h"
|
||||
#include "hash_state.h"
|
||||
#include "thash.h"
|
||||
#include "utils.h"
|
||||
|
||||
/**
|
||||
* Converts the value of 'in' to 'outlen' bytes in big-endian byte order.
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_ull_to_bytes(
|
||||
unsigned char *out, size_t outlen, unsigned long long in) {
|
||||
|
||||
/* Iterate over out in decreasing order, for big-endianness. */
|
||||
for (size_t i = outlen; i > 0; i--) {
|
||||
out[i - 1] = in & 0xff;
|
||||
in = in >> 8;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the inlen bytes in 'in' from big-endian byte order to an integer.
|
||||
*/
|
||||
unsigned long long PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_bytes_to_ull(
|
||||
const unsigned char *in, size_t inlen) {
|
||||
unsigned long long retval = 0;
|
||||
|
||||
for (size_t i = 0; i < inlen; i++) {
|
||||
retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i));
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes a root node given a leaf and an auth path.
|
||||
* Expects address to be complete other than the tree_height and tree_index.
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_compute_root(
|
||||
unsigned char *root, const unsigned char *leaf,
|
||||
uint32_t leaf_idx, uint32_t idx_offset,
|
||||
const unsigned char *auth_path, uint32_t tree_height,
|
||||
const unsigned char *pub_seed, uint32_t addr[8],
|
||||
const hash_state *hash_state_seeded) {
|
||||
uint32_t i;
|
||||
unsigned char buffer[2 * SPX_N];
|
||||
|
||||
/* If leaf_idx is odd (last bit = 1), current path element is a right child
|
||||
and auth_path has to go left. Otherwise it is the other way around. */
|
||||
if (leaf_idx & 1) {
|
||||
memcpy(buffer + SPX_N, leaf, SPX_N);
|
||||
memcpy(buffer, auth_path, SPX_N);
|
||||
} else {
|
||||
memcpy(buffer, leaf, SPX_N);
|
||||
memcpy(buffer + SPX_N, auth_path, SPX_N);
|
||||
}
|
||||
auth_path += SPX_N;
|
||||
|
||||
for (i = 0; i < tree_height - 1; i++) {
|
||||
leaf_idx >>= 1;
|
||||
idx_offset >>= 1;
|
||||
/* Set the address of the node we're creating. */
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_tree_height(addr, i + 1);
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_tree_index(
|
||||
addr, leaf_idx + idx_offset);
|
||||
|
||||
/* Pick the right or left neighbor, depending on parity of the node. */
|
||||
if (leaf_idx & 1) {
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_thash_2(
|
||||
buffer + SPX_N, buffer, pub_seed, addr, hash_state_seeded);
|
||||
memcpy(buffer, auth_path, SPX_N);
|
||||
} else {
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_thash_2(
|
||||
buffer, buffer, pub_seed, addr, hash_state_seeded);
|
||||
memcpy(buffer + SPX_N, auth_path, SPX_N);
|
||||
}
|
||||
auth_path += SPX_N;
|
||||
}
|
||||
|
||||
/* The last iteration is exceptional; we do not copy an auth_path node. */
|
||||
leaf_idx >>= 1;
|
||||
idx_offset >>= 1;
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_tree_height(addr, tree_height);
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_tree_index(
|
||||
addr, leaf_idx + idx_offset);
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_thash_2(
|
||||
root, buffer, pub_seed, addr, hash_state_seeded);
|
||||
}
|
||||
|
||||
/**
|
||||
* For a given leaf index, computes the authentication path and the resulting
|
||||
* root node using Merkle's TreeHash algorithm.
|
||||
* Expects the layer and tree parts of the tree_addr to be set, as well as the
|
||||
* tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE).
|
||||
* Applies the offset idx_offset to indices before building addresses, so that
|
||||
* it is possible to continue counting indices across trees.
|
||||
*/
|
||||
static void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_treehash(
|
||||
unsigned char *root, unsigned char *auth_path,
|
||||
unsigned char *stack, unsigned int *heights,
|
||||
const unsigned char *sk_seed, const unsigned char *pub_seed,
|
||||
uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height,
|
||||
void (*gen_leaf)(
|
||||
unsigned char * /* leaf */,
|
||||
const unsigned char * /* sk_seed */,
|
||||
const unsigned char * /* pub_seed */,
|
||||
uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */,
|
||||
const hash_state * /* hash_state_seeded */),
|
||||
uint32_t tree_addr[8],
|
||||
const hash_state *hash_state_seeded) {
|
||||
|
||||
unsigned int offset = 0;
|
||||
uint32_t idx;
|
||||
uint32_t tree_idx;
|
||||
|
||||
for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) {
|
||||
/* Add the next leaf node to the stack. */
|
||||
gen_leaf(stack + offset * SPX_N,
|
||||
sk_seed, pub_seed, idx + idx_offset, tree_addr,
|
||||
hash_state_seeded);
|
||||
offset++;
|
||||
heights[offset - 1] = 0;
|
||||
|
||||
/* If this is a node we need for the auth path.. */
|
||||
if ((leaf_idx ^ 0x1) == idx) {
|
||||
memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N);
|
||||
}
|
||||
|
||||
/* While the top-most nodes are of equal height.. */
|
||||
while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) {
|
||||
/* Compute index of the new node, in the next layer. */
|
||||
tree_idx = (idx >> (heights[offset - 1] + 1));
|
||||
|
||||
/* Set the address of the node we're creating. */
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_tree_height(
|
||||
tree_addr, heights[offset - 1] + 1);
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_tree_index(
|
||||
tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1)));
|
||||
/* Hash the top-most nodes from the stack together. */
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_thash_2(
|
||||
stack + (offset - 2)*SPX_N, stack + (offset - 2)*SPX_N,
|
||||
pub_seed, tree_addr, hash_state_seeded);
|
||||
offset--;
|
||||
/* Note that the top-most node is now one layer higher. */
|
||||
heights[offset - 1]++;
|
||||
|
||||
/* If this is a node we need for the auth path.. */
|
||||
if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) {
|
||||
memcpy(auth_path + heights[offset - 1]*SPX_N,
|
||||
stack + (offset - 1)*SPX_N, SPX_N);
|
||||
}
|
||||
}
|
||||
}
|
||||
memcpy(root, stack, SPX_N);
|
||||
}
|
||||
|
||||
/* The wrappers below ensure that we use fixed-size buffers on the stack */
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_treehash_FORS_HEIGHT(
|
||||
unsigned char *root, unsigned char *auth_path,
|
||||
const unsigned char *sk_seed, const unsigned char *pub_seed,
|
||||
uint32_t leaf_idx, uint32_t idx_offset,
|
||||
void (*gen_leaf)(
|
||||
unsigned char * /* leaf */,
|
||||
const unsigned char * /* sk_seed */,
|
||||
const unsigned char * /* pub_seed */,
|
||||
uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */,
|
||||
const hash_state * /* hash_state_seeded */),
|
||||
uint32_t tree_addr[8], const hash_state *hash_state_seeded) {
|
||||
|
||||
unsigned char stack[(SPX_FORS_HEIGHT + 1)*SPX_N];
|
||||
unsigned int heights[SPX_FORS_HEIGHT + 1];
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_treehash(
|
||||
root, auth_path, stack, heights, sk_seed, pub_seed,
|
||||
leaf_idx, idx_offset, SPX_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded);
|
||||
}
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_treehash_TREE_HEIGHT(
|
||||
unsigned char *root, unsigned char *auth_path,
|
||||
const unsigned char *sk_seed, const unsigned char *pub_seed,
|
||||
uint32_t leaf_idx, uint32_t idx_offset,
|
||||
void (*gen_leaf)(
|
||||
unsigned char * /* leaf */,
|
||||
const unsigned char * /* sk_seed */,
|
||||
const unsigned char * /* pub_seed */,
|
||||
uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */,
|
||||
const hash_state * /* hash_state_seeded */),
|
||||
uint32_t tree_addr[8], const hash_state *hash_state_seeded) {
|
||||
|
||||
unsigned char stack[(SPX_TREE_HEIGHT + 1)*SPX_N];
|
||||
unsigned int heights[SPX_TREE_HEIGHT + 1];
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_treehash(
|
||||
root, auth_path, stack, heights, sk_seed, pub_seed,
|
||||
leaf_idx, idx_offset, SPX_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded);
|
||||
}
|
||||
@ -0,0 +1,64 @@
|
||||
#ifndef SPX_UTILS_H
|
||||
#define SPX_UTILS_H
|
||||
|
||||
#include "params.h"
|
||||
#include "hash_state.h"
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* Converts the value of 'in' to 'outlen' bytes in big-endian byte order.
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_ull_to_bytes(
|
||||
unsigned char *out, size_t outlen, unsigned long long in);
|
||||
|
||||
/**
|
||||
* Converts the inlen bytes in 'in' from big-endian byte order to an integer.
|
||||
*/
|
||||
unsigned long long PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_bytes_to_ull(
|
||||
const unsigned char *in, size_t inlen);
|
||||
|
||||
/**
|
||||
* Computes a root node given a leaf and an auth path.
|
||||
* Expects address to be complete other than the tree_height and tree_index.
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_compute_root(
|
||||
unsigned char *root, const unsigned char *leaf,
|
||||
uint32_t leaf_idx, uint32_t idx_offset,
|
||||
const unsigned char *auth_path, uint32_t tree_height,
|
||||
const unsigned char *pub_seed, uint32_t addr[8],
|
||||
const hash_state *hash_state_seeded);
|
||||
|
||||
/**
|
||||
* For a given leaf index, computes the authentication path and the resulting
|
||||
* root node using Merkle's TreeHash algorithm.
|
||||
* Expects the layer and tree parts of the tree_addr to be set, as well as the
|
||||
* tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE).
|
||||
* Applies the offset idx_offset to indices before building addresses, so that
|
||||
* it is possible to continue counting indices across trees.
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_treehash_FORS_HEIGHT(
|
||||
unsigned char *root, unsigned char *auth_path,
|
||||
const unsigned char *sk_seed, const unsigned char *pub_seed,
|
||||
uint32_t leaf_idx, uint32_t idx_offset,
|
||||
void (*gen_leaf)(
|
||||
unsigned char * /* leaf */,
|
||||
const unsigned char * /* sk_seed */,
|
||||
const unsigned char * /* pub_seed */,
|
||||
uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */,
|
||||
const hash_state * /* hash_state_seeded */),
|
||||
uint32_t tree_addr[8], const hash_state *hash_state_seeded);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_treehash_TREE_HEIGHT(
|
||||
unsigned char *root, unsigned char *auth_path,
|
||||
const unsigned char *sk_seed, const unsigned char *pub_seed,
|
||||
uint32_t leaf_idx, uint32_t idx_offset,
|
||||
void (*gen_leaf)(
|
||||
unsigned char * /* leaf */,
|
||||
const unsigned char * /* sk_seed */,
|
||||
const unsigned char * /* pub_seed */,
|
||||
uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */,
|
||||
const hash_state * /* hash_state_seeded */),
|
||||
uint32_t tree_addr[8], const hash_state *hash_state_seeded);
|
||||
|
||||
#endif
|
||||
167
src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/wots.c
Normal file
167
src/sig/sphincs/pqclean_sphincs-sha256-128s-robust_clean/wots.c
Normal file
@ -0,0 +1,167 @@
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "address.h"
|
||||
#include "hash.h"
|
||||
#include "params.h"
|
||||
#include "hash_state.h"
|
||||
#include "thash.h"
|
||||
#include "utils.h"
|
||||
#include "wots.h"
|
||||
|
||||
// TODO clarify address expectations, and make them more uniform.
|
||||
// TODO i.e. do we expect types to be set already?
|
||||
// TODO and do we expect modifications or copies?
|
||||
|
||||
/**
|
||||
* Computes the starting value for a chain, i.e. the secret key.
|
||||
* Expects the address to be complete up to the chain address.
|
||||
*/
|
||||
static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed,
|
||||
uint32_t wots_addr[8],
|
||||
const hash_state *hash_state_seeded) {
|
||||
/* Make sure that the hash address is actually zeroed. */
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_hash_addr(wots_addr, 0);
|
||||
|
||||
/* Generate sk element. */
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_prf_addr(sk, sk_seed, wots_addr, hash_state_seeded);
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the chaining function.
|
||||
* out and in have to be n-byte arrays.
|
||||
*
|
||||
* Interprets in as start-th value of the chain.
|
||||
* addr has to contain the address of the chain.
|
||||
*/
|
||||
static void gen_chain(unsigned char *out, const unsigned char *in,
|
||||
unsigned int start, unsigned int steps,
|
||||
const unsigned char *pub_seed, uint32_t addr[8],
|
||||
const hash_state *hash_state_seeded) {
|
||||
uint32_t i;
|
||||
|
||||
/* Initialize out with the value at position 'start'. */
|
||||
memcpy(out, in, SPX_N);
|
||||
|
||||
/* Iterate 'steps' calls to the hash function. */
|
||||
for (i = start; i < (start + steps) && i < SPX_WOTS_W; i++) {
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_hash_addr(addr, i);
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_thash_1(
|
||||
out, out, pub_seed, addr, hash_state_seeded);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* base_w algorithm as described in draft.
|
||||
* Interprets an array of bytes as integers in base w.
|
||||
* This only works when log_w is a divisor of 8.
|
||||
*/
|
||||
static void base_w(unsigned int *output, const size_t out_len,
|
||||
const unsigned char *input) {
|
||||
size_t in = 0;
|
||||
size_t out = 0;
|
||||
unsigned char total = 0;
|
||||
unsigned int bits = 0;
|
||||
size_t consumed;
|
||||
|
||||
for (consumed = 0; consumed < out_len; consumed++) {
|
||||
if (bits == 0) {
|
||||
total = input[in];
|
||||
in++;
|
||||
bits += 8;
|
||||
}
|
||||
bits -= SPX_WOTS_LOGW;
|
||||
output[out] = (unsigned int)((total >> bits) & (SPX_WOTS_W - 1));
|
||||
out++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Computes the WOTS+ checksum over a message (in base_w). */
|
||||
static void wots_checksum(unsigned int *csum_base_w,
|
||||
const unsigned int *msg_base_w) {
|
||||
unsigned int csum = 0;
|
||||
unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8];
|
||||
unsigned int i;
|
||||
|
||||
/* Compute checksum. */
|
||||
for (i = 0; i < SPX_WOTS_LEN1; i++) {
|
||||
csum += SPX_WOTS_W - 1 - msg_base_w[i];
|
||||
}
|
||||
|
||||
/* Convert checksum to base_w. */
|
||||
/* Make sure expected empty zero bits are the least significant bits. */
|
||||
csum = csum << (8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8));
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_ull_to_bytes(
|
||||
csum_bytes, sizeof(csum_bytes), csum);
|
||||
base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes);
|
||||
}
|
||||
|
||||
/* Takes a message and derives the matching chain lengths. */
|
||||
static void chain_lengths(unsigned int *lengths, const unsigned char *msg) {
|
||||
base_w(lengths, SPX_WOTS_LEN1, msg);
|
||||
wots_checksum(lengths + SPX_WOTS_LEN1, lengths);
|
||||
}
|
||||
|
||||
/**
|
||||
* WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key
|
||||
* elements and computes the corresponding public key.
|
||||
* It requires the seed pub_seed (used to generate bitmasks and hash keys)
|
||||
* and the address of this WOTS key pair.
|
||||
*
|
||||
* Writes the computed public key to 'pk'.
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_wots_gen_pk(
|
||||
unsigned char *pk, const unsigned char *sk_seed,
|
||||
const unsigned char *pub_seed, uint32_t addr[8],
|
||||
const hash_state *hash_state_seeded) {
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < SPX_WOTS_LEN; i++) {
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_chain_addr(addr, i);
|
||||
wots_gen_sk(pk + i * SPX_N, sk_seed, addr, hash_state_seeded);
|
||||
gen_chain(pk + i * SPX_N, pk + i * SPX_N,
|
||||
0, SPX_WOTS_W - 1, pub_seed, addr, hash_state_seeded);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'.
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_wots_sign(
|
||||
unsigned char *sig, const unsigned char *msg,
|
||||
const unsigned char *sk_seed, const unsigned char *pub_seed,
|
||||
uint32_t addr[8], const hash_state *hash_state_seeded) {
|
||||
unsigned int lengths[SPX_WOTS_LEN];
|
||||
uint32_t i;
|
||||
|
||||
chain_lengths(lengths, msg);
|
||||
|
||||
for (i = 0; i < SPX_WOTS_LEN; i++) {
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_chain_addr(addr, i);
|
||||
wots_gen_sk(sig + i * SPX_N, sk_seed, addr, hash_state_seeded);
|
||||
gen_chain(sig + i * SPX_N, sig + i * SPX_N, 0, lengths[i], pub_seed, addr, hash_state_seeded);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes a WOTS signature and an n-byte message, computes a WOTS public key.
|
||||
*
|
||||
* Writes the computed public key to 'pk'.
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_wots_pk_from_sig(
|
||||
unsigned char *pk,
|
||||
const unsigned char *sig, const unsigned char *msg,
|
||||
const unsigned char *pub_seed, uint32_t addr[8],
|
||||
const hash_state *hash_state_seeded) {
|
||||
unsigned int lengths[SPX_WOTS_LEN];
|
||||
uint32_t i;
|
||||
|
||||
chain_lengths(lengths, msg);
|
||||
|
||||
for (i = 0; i < SPX_WOTS_LEN; i++) {
|
||||
PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_set_chain_addr(addr, i);
|
||||
gen_chain(pk + i * SPX_N, sig + i * SPX_N,
|
||||
lengths[i], SPX_WOTS_W - 1 - lengths[i], pub_seed, addr,
|
||||
hash_state_seeded);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,41 @@
|
||||
#ifndef SPX_WOTS_H
|
||||
#define SPX_WOTS_H
|
||||
|
||||
#include "params.h"
|
||||
#include "hash_state.h"
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* WOTS key generation. Takes a 32 byte seed for the private key, expands it to
|
||||
* a full WOTS private key and computes the corresponding public key.
|
||||
* It requires the seed pub_seed (used to generate bitmasks and hash keys)
|
||||
* and the address of this WOTS key pair.
|
||||
*
|
||||
* Writes the computed public key to 'pk'.
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_wots_gen_pk(
|
||||
unsigned char *pk, const unsigned char *sk_seed,
|
||||
const unsigned char *pub_seed, uint32_t addr[8],
|
||||
const hash_state *hash_state_seeded);
|
||||
|
||||
/**
|
||||
* Takes a n-byte message and the 32-byte seed for the private key to compute a
|
||||
* signature that is placed at 'sig'.
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_wots_sign(
|
||||
unsigned char *sig, const unsigned char *msg,
|
||||
const unsigned char *sk_seed, const unsigned char *pub_seed,
|
||||
uint32_t addr[8], const hash_state *hash_state_seeded);
|
||||
|
||||
/**
|
||||
* Takes a WOTS signature and an n-byte message, computes a WOTS public key.
|
||||
*
|
||||
* Writes the computed public key to 'pk'.
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_wots_pk_from_sig(
|
||||
unsigned char *pk,
|
||||
const unsigned char *sig, const unsigned char *msg,
|
||||
const unsigned char *pub_seed, uint32_t addr[8],
|
||||
const hash_state *hash_state_seeded);
|
||||
|
||||
#endif
|
||||
116
src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/LICENSE
Normal file
116
src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/LICENSE
Normal file
@ -0,0 +1,116 @@
|
||||
CC0 1.0 Universal
|
||||
|
||||
Statement of Purpose
|
||||
|
||||
The laws of most jurisdictions throughout the world automatically confer
|
||||
exclusive Copyright and Related Rights (defined below) upon the creator and
|
||||
subsequent owner(s) (each and all, an "owner") of an original work of
|
||||
authorship and/or a database (each, a "Work").
|
||||
|
||||
Certain owners wish to permanently relinquish those rights to a Work for the
|
||||
purpose of contributing to a commons of creative, cultural and scientific
|
||||
works ("Commons") that the public can reliably and without fear of later
|
||||
claims of infringement build upon, modify, incorporate in other works, reuse
|
||||
and redistribute as freely as possible in any form whatsoever and for any
|
||||
purposes, including without limitation commercial purposes. These owners may
|
||||
contribute to the Commons to promote the ideal of a free culture and the
|
||||
further production of creative, cultural and scientific works, or to gain
|
||||
reputation or greater distribution for their Work in part through the use and
|
||||
efforts of others.
|
||||
|
||||
For these and/or other purposes and motivations, and without any expectation
|
||||
of additional consideration or compensation, the person associating CC0 with a
|
||||
Work (the "Affirmer"), to the extent that he or she is an owner of Copyright
|
||||
and Related Rights in the Work, voluntarily elects to apply CC0 to the Work
|
||||
and publicly distribute the Work under its terms, with knowledge of his or her
|
||||
Copyright and Related Rights in the Work and the meaning and intended legal
|
||||
effect of CC0 on those rights.
|
||||
|
||||
1. Copyright and Related Rights. A Work made available under CC0 may be
|
||||
protected by copyright and related or neighboring rights ("Copyright and
|
||||
Related Rights"). Copyright and Related Rights include, but are not limited
|
||||
to, the following:
|
||||
|
||||
i. the right to reproduce, adapt, distribute, perform, display, communicate,
|
||||
and translate a Work;
|
||||
|
||||
ii. moral rights retained by the original author(s) and/or performer(s);
|
||||
|
||||
iii. publicity and privacy rights pertaining to a person's image or likeness
|
||||
depicted in a Work;
|
||||
|
||||
iv. rights protecting against unfair competition in regards to a Work,
|
||||
subject to the limitations in paragraph 4(a), below;
|
||||
|
||||
v. rights protecting the extraction, dissemination, use and reuse of data in
|
||||
a Work;
|
||||
|
||||
vi. database rights (such as those arising under Directive 96/9/EC of the
|
||||
European Parliament and of the Council of 11 March 1996 on the legal
|
||||
protection of databases, and under any national implementation thereof,
|
||||
including any amended or successor version of such directive); and
|
||||
|
||||
vii. other similar, equivalent or corresponding rights throughout the world
|
||||
based on applicable law or treaty, and any national implementations thereof.
|
||||
|
||||
2. Waiver. To the greatest extent permitted by, but not in contravention of,
|
||||
applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and
|
||||
unconditionally waives, abandons, and surrenders all of Affirmer's Copyright
|
||||
and Related Rights and associated claims and causes of action, whether now
|
||||
known or unknown (including existing as well as future claims and causes of
|
||||
action), in the Work (i) in all territories worldwide, (ii) for the maximum
|
||||
duration provided by applicable law or treaty (including future time
|
||||
extensions), (iii) in any current or future medium and for any number of
|
||||
copies, and (iv) for any purpose whatsoever, including without limitation
|
||||
commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes
|
||||
the Waiver for the benefit of each member of the public at large and to the
|
||||
detriment of Affirmer's heirs and successors, fully intending that such Waiver
|
||||
shall not be subject to revocation, rescission, cancellation, termination, or
|
||||
any other legal or equitable action to disrupt the quiet enjoyment of the Work
|
||||
by the public as contemplated by Affirmer's express Statement of Purpose.
|
||||
|
||||
3. Public License Fallback. Should any part of the Waiver for any reason be
|
||||
judged legally invalid or ineffective under applicable law, then the Waiver
|
||||
shall be preserved to the maximum extent permitted taking into account
|
||||
Affirmer's express Statement of Purpose. In addition, to the extent the Waiver
|
||||
is so judged Affirmer hereby grants to each affected person a royalty-free,
|
||||
non transferable, non sublicensable, non exclusive, irrevocable and
|
||||
unconditional license to exercise Affirmer's Copyright and Related Rights in
|
||||
the Work (i) in all territories worldwide, (ii) for the maximum duration
|
||||
provided by applicable law or treaty (including future time extensions), (iii)
|
||||
in any current or future medium and for any number of copies, and (iv) for any
|
||||
purpose whatsoever, including without limitation commercial, advertising or
|
||||
promotional purposes (the "License"). The License shall be deemed effective as
|
||||
of the date CC0 was applied by Affirmer to the Work. Should any part of the
|
||||
License for any reason be judged legally invalid or ineffective under
|
||||
applicable law, such partial invalidity or ineffectiveness shall not
|
||||
invalidate the remainder of the License, and in such case Affirmer hereby
|
||||
affirms that he or she will not (i) exercise any of his or her remaining
|
||||
Copyright and Related Rights in the Work or (ii) assert any associated claims
|
||||
and causes of action with respect to the Work, in either case contrary to
|
||||
Affirmer's express Statement of Purpose.
|
||||
|
||||
4. Limitations and Disclaimers.
|
||||
|
||||
a. No trademark or patent rights held by Affirmer are waived, abandoned,
|
||||
surrendered, licensed or otherwise affected by this document.
|
||||
|
||||
b. Affirmer offers the Work as-is and makes no representations or warranties
|
||||
of any kind concerning the Work, express, implied, statutory or otherwise,
|
||||
including without limitation warranties of title, merchantability, fitness
|
||||
for a particular purpose, non infringement, or the absence of latent or
|
||||
other defects, accuracy, or the present or absence of errors, whether or not
|
||||
discoverable, all to the greatest extent permissible under applicable law.
|
||||
|
||||
c. Affirmer disclaims responsibility for clearing rights of other persons
|
||||
that may apply to the Work or any use thereof, including without limitation
|
||||
any person's Copyright and Related Rights in the Work. Further, Affirmer
|
||||
disclaims responsibility for obtaining any necessary consents, permissions
|
||||
or other rights required for any use of the Work.
|
||||
|
||||
d. Affirmer understands and acknowledges that Creative Commons is not a
|
||||
party to this document and has no duty or obligation with respect to this
|
||||
CC0 or use of the Work.
|
||||
|
||||
For more information, please see
|
||||
<http://creativecommons.org/publicdomain/zero/1.0/>
|
||||
@ -0,0 +1,78 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#include "address.h"
|
||||
#include "params.h"
|
||||
#include "utils.h"
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_addr_to_bytes(
|
||||
unsigned char *bytes, const uint32_t addr[8]) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_ull_to_bytes(
|
||||
bytes + i * 4, 4, addr[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_layer_addr(
|
||||
uint32_t addr[8], uint32_t layer) {
|
||||
addr[0] = layer;
|
||||
}
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_tree_addr(
|
||||
uint32_t addr[8], uint64_t tree) {
|
||||
addr[1] = 0;
|
||||
addr[2] = (uint32_t) (tree >> 32);
|
||||
addr[3] = (uint32_t) tree;
|
||||
}
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_type(
|
||||
uint32_t addr[8], uint32_t type) {
|
||||
addr[4] = type;
|
||||
}
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_copy_subtree_addr(
|
||||
uint32_t out[8], const uint32_t in[8]) {
|
||||
out[0] = in[0];
|
||||
out[1] = in[1];
|
||||
out[2] = in[2];
|
||||
out[3] = in[3];
|
||||
}
|
||||
|
||||
/* These functions are used for OTS addresses. */
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_keypair_addr(
|
||||
uint32_t addr[8], uint32_t keypair) {
|
||||
addr[5] = keypair;
|
||||
}
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_copy_keypair_addr(
|
||||
uint32_t out[8], const uint32_t in[8]) {
|
||||
out[0] = in[0];
|
||||
out[1] = in[1];
|
||||
out[2] = in[2];
|
||||
out[3] = in[3];
|
||||
out[5] = in[5];
|
||||
}
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_chain_addr(
|
||||
uint32_t addr[8], uint32_t chain) {
|
||||
addr[6] = chain;
|
||||
}
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_hash_addr(
|
||||
uint32_t addr[8], uint32_t hash) {
|
||||
addr[7] = hash;
|
||||
}
|
||||
|
||||
/* These functions are used for all hash tree addresses (including FORS). */
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_tree_height(
|
||||
uint32_t addr[8], uint32_t tree_height) {
|
||||
addr[6] = tree_height;
|
||||
}
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_tree_index(
|
||||
uint32_t addr[8], uint32_t tree_index) {
|
||||
addr[7] = tree_index;
|
||||
}
|
||||
@ -0,0 +1,50 @@
|
||||
#ifndef SPX_ADDRESS_H
|
||||
#define SPX_ADDRESS_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define SPX_ADDR_TYPE_WOTS 0
|
||||
#define SPX_ADDR_TYPE_WOTSPK 1
|
||||
#define SPX_ADDR_TYPE_HASHTREE 2
|
||||
#define SPX_ADDR_TYPE_FORSTREE 3
|
||||
#define SPX_ADDR_TYPE_FORSPK 4
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_addr_to_bytes(
|
||||
unsigned char *bytes, const uint32_t addr[8]);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_layer_addr(
|
||||
uint32_t addr[8], uint32_t layer);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_tree_addr(
|
||||
uint32_t addr[8], uint64_t tree);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_type(
|
||||
uint32_t addr[8], uint32_t type);
|
||||
|
||||
/* Copies the layer and tree part of one address into the other */
|
||||
void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_copy_subtree_addr(
|
||||
uint32_t out[8], const uint32_t in[8]);
|
||||
|
||||
/* These functions are used for WOTS and FORS addresses. */
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_keypair_addr(
|
||||
uint32_t addr[8], uint32_t keypair);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_chain_addr(
|
||||
uint32_t addr[8], uint32_t chain);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_hash_addr(
|
||||
uint32_t addr[8], uint32_t hash);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_copy_keypair_addr(
|
||||
uint32_t out[8], const uint32_t in[8]);
|
||||
|
||||
/* These functions are used for all hash tree addresses (including FORS). */
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_tree_height(
|
||||
uint32_t addr[8], uint32_t tree_height);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_tree_index(
|
||||
uint32_t addr[8], uint32_t tree_index);
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,78 @@
|
||||
#ifndef PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_API_H
|
||||
#define PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_API_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_CRYPTO_ALGNAME "SPHINCS+"
|
||||
|
||||
#define PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_CRYPTO_SECRETKEYBYTES 64
|
||||
#define PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_CRYPTO_PUBLICKEYBYTES 32
|
||||
#define PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_CRYPTO_BYTES 8080
|
||||
#define PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_CRYPTO_SEEDBYTES 48
|
||||
|
||||
/*
|
||||
* Returns the length of a secret key, in bytes
|
||||
*/
|
||||
size_t PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_crypto_sign_secretkeybytes(void);
|
||||
|
||||
/*
|
||||
* Returns the length of a public key, in bytes
|
||||
*/
|
||||
size_t PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_crypto_sign_publickeybytes(void);
|
||||
|
||||
/*
|
||||
* Returns the length of a signature, in bytes
|
||||
*/
|
||||
size_t PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_crypto_sign_bytes(void);
|
||||
|
||||
/*
|
||||
* Returns the length of the seed required to generate a key pair, in bytes
|
||||
*/
|
||||
size_t PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_crypto_sign_seedbytes(void);
|
||||
|
||||
/*
|
||||
* Generates a SPHINCS+ key pair given a seed.
|
||||
* Format sk: [SK_SEED || SK_PRF || PUB_SEED || root]
|
||||
* Format pk: [root || PUB_SEED]
|
||||
*/
|
||||
int PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_crypto_sign_seed_keypair(
|
||||
uint8_t *pk, uint8_t *sk, const uint8_t *seed);
|
||||
|
||||
/*
|
||||
* Generates a SPHINCS+ key pair.
|
||||
* Format sk: [SK_SEED || SK_PRF || PUB_SEED || root]
|
||||
* Format pk: [root || PUB_SEED]
|
||||
*/
|
||||
int PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_crypto_sign_keypair(
|
||||
uint8_t *pk, uint8_t *sk);
|
||||
|
||||
/**
|
||||
* Returns an array containing a detached signature.
|
||||
*/
|
||||
int PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_crypto_sign_signature(
|
||||
uint8_t *sig, size_t *siglen,
|
||||
const uint8_t *m, size_t mlen, const uint8_t *sk);
|
||||
|
||||
/**
|
||||
* Verifies a detached signature and message under a given public key.
|
||||
*/
|
||||
int PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_crypto_sign_verify(
|
||||
const uint8_t *sig, size_t siglen,
|
||||
const uint8_t *m, size_t mlen, const uint8_t *pk);
|
||||
|
||||
/**
|
||||
* Returns an array containing the signature followed by the message.
|
||||
*/
|
||||
int PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_crypto_sign(
|
||||
uint8_t *sm, size_t *smlen,
|
||||
const uint8_t *m, size_t mlen, const uint8_t *sk);
|
||||
|
||||
/**
|
||||
* Verifies a given signature-message pair under a given public key.
|
||||
*/
|
||||
int PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_crypto_sign_open(
|
||||
uint8_t *m, size_t *mlen,
|
||||
const uint8_t *sm, size_t smlen, const uint8_t *pk);
|
||||
|
||||
#endif
|
||||
169
src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/fors.c
Normal file
169
src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/fors.c
Normal file
@ -0,0 +1,169 @@
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "address.h"
|
||||
#include "fors.h"
|
||||
#include "hash.h"
|
||||
#include "hash_state.h"
|
||||
#include "thash.h"
|
||||
#include "utils.h"
|
||||
|
||||
static void fors_gen_sk(unsigned char *sk, const unsigned char *sk_seed,
|
||||
uint32_t fors_leaf_addr[8], const hash_state *hash_state_seeded) {
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_prf_addr(
|
||||
sk, sk_seed, fors_leaf_addr, hash_state_seeded);
|
||||
}
|
||||
|
||||
static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk,
|
||||
const unsigned char *pub_seed,
|
||||
uint32_t fors_leaf_addr[8],
|
||||
const hash_state *hash_state_seeded) {
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_thash_1(
|
||||
leaf, sk, pub_seed, fors_leaf_addr, hash_state_seeded);
|
||||
}
|
||||
|
||||
static void fors_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed,
|
||||
const unsigned char *pub_seed,
|
||||
uint32_t addr_idx, const uint32_t fors_tree_addr[8],
|
||||
const hash_state *hash_state_seeded) {
|
||||
uint32_t fors_leaf_addr[8] = {0};
|
||||
|
||||
/* Only copy the parts that must be kept in fors_leaf_addr. */
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_copy_keypair_addr(
|
||||
fors_leaf_addr, fors_tree_addr);
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_type(
|
||||
fors_leaf_addr, SPX_ADDR_TYPE_FORSTREE);
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_tree_index(
|
||||
fors_leaf_addr, addr_idx);
|
||||
|
||||
fors_gen_sk(leaf, sk_seed, fors_leaf_addr, hash_state_seeded);
|
||||
fors_sk_to_leaf(leaf, leaf, pub_seed, fors_leaf_addr, hash_state_seeded);
|
||||
}
|
||||
|
||||
/**
|
||||
* Interprets m as SPX_FORS_HEIGHT-bit unsigned integers.
|
||||
* Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits.
|
||||
* Assumes indices has space for SPX_FORS_TREES integers.
|
||||
*/
|
||||
static void message_to_indices(uint32_t *indices, const unsigned char *m) {
|
||||
unsigned int i, j;
|
||||
unsigned int offset = 0;
|
||||
|
||||
for (i = 0; i < SPX_FORS_TREES; i++) {
|
||||
indices[i] = 0;
|
||||
for (j = 0; j < SPX_FORS_HEIGHT; j++) {
|
||||
indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j;
|
||||
offset++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Signs a message m, deriving the secret key from sk_seed and the FTS address.
|
||||
* Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits.
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_fors_sign(
|
||||
unsigned char *sig, unsigned char *pk,
|
||||
const unsigned char *m,
|
||||
const unsigned char *sk_seed, const unsigned char *pub_seed,
|
||||
const uint32_t fors_addr[8], const hash_state *hash_state_seeded) {
|
||||
uint32_t indices[SPX_FORS_TREES];
|
||||
unsigned char roots[SPX_FORS_TREES * SPX_N];
|
||||
uint32_t fors_tree_addr[8] = {0};
|
||||
uint32_t fors_pk_addr[8] = {0};
|
||||
uint32_t idx_offset;
|
||||
unsigned int i;
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_copy_keypair_addr(
|
||||
fors_tree_addr, fors_addr);
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_copy_keypair_addr(
|
||||
fors_pk_addr, fors_addr);
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_type(
|
||||
fors_tree_addr, SPX_ADDR_TYPE_FORSTREE);
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_type(
|
||||
fors_pk_addr, SPX_ADDR_TYPE_FORSPK);
|
||||
|
||||
message_to_indices(indices, m);
|
||||
|
||||
for (i = 0; i < SPX_FORS_TREES; i++) {
|
||||
idx_offset = i * (1 << SPX_FORS_HEIGHT);
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_tree_height(
|
||||
fors_tree_addr, 0);
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_tree_index(
|
||||
fors_tree_addr, indices[i] + idx_offset);
|
||||
|
||||
/* Include the secret key part that produces the selected leaf node. */
|
||||
fors_gen_sk(sig, sk_seed, fors_tree_addr, hash_state_seeded);
|
||||
sig += SPX_N;
|
||||
|
||||
/* Compute the authentication path for this leaf node. */
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_treehash_FORS_HEIGHT(
|
||||
roots + i * SPX_N, sig, sk_seed, pub_seed,
|
||||
indices[i], idx_offset, fors_gen_leaf, fors_tree_addr,
|
||||
hash_state_seeded);
|
||||
sig += SPX_N * SPX_FORS_HEIGHT;
|
||||
}
|
||||
|
||||
/* Hash horizontally across all tree roots to derive the public key. */
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_thash_FORS_TREES(
|
||||
pk, roots, pub_seed, fors_pk_addr, hash_state_seeded);
|
||||
}
|
||||
|
||||
/**
|
||||
* Derives the FORS public key from a signature.
|
||||
* This can be used for verification by comparing to a known public key, or to
|
||||
* subsequently verify a signature on the derived public key. The latter is the
|
||||
* typical use-case when used as an FTS below an OTS in a hypertree.
|
||||
* Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits.
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_fors_pk_from_sig(
|
||||
unsigned char *pk,
|
||||
const unsigned char *sig, const unsigned char *m,
|
||||
const unsigned char *pub_seed, const uint32_t fors_addr[8],
|
||||
const hash_state *hash_state_seeded) {
|
||||
uint32_t indices[SPX_FORS_TREES];
|
||||
unsigned char roots[SPX_FORS_TREES * SPX_N];
|
||||
unsigned char leaf[SPX_N];
|
||||
uint32_t fors_tree_addr[8] = {0};
|
||||
uint32_t fors_pk_addr[8] = {0};
|
||||
uint32_t idx_offset;
|
||||
unsigned int i;
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_copy_keypair_addr(
|
||||
fors_tree_addr, fors_addr);
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_copy_keypair_addr(
|
||||
fors_pk_addr, fors_addr);
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_type(
|
||||
fors_tree_addr, SPX_ADDR_TYPE_FORSTREE);
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_type(
|
||||
fors_pk_addr, SPX_ADDR_TYPE_FORSPK);
|
||||
|
||||
message_to_indices(indices, m);
|
||||
|
||||
for (i = 0; i < SPX_FORS_TREES; i++) {
|
||||
idx_offset = i * (1 << SPX_FORS_HEIGHT);
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_tree_height(
|
||||
fors_tree_addr, 0);
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_tree_index(
|
||||
fors_tree_addr, indices[i] + idx_offset);
|
||||
|
||||
/* Derive the leaf from the included secret key part. */
|
||||
fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, hash_state_seeded);
|
||||
sig += SPX_N;
|
||||
|
||||
/* Derive the corresponding root node of this tree. */
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_compute_root(
|
||||
roots + i * SPX_N, leaf, indices[i], idx_offset, sig,
|
||||
SPX_FORS_HEIGHT, pub_seed, fors_tree_addr, hash_state_seeded);
|
||||
sig += SPX_N * SPX_FORS_HEIGHT;
|
||||
}
|
||||
|
||||
/* Hash horizontally across all tree roots to derive the public key. */
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_thash_FORS_TREES(
|
||||
pk, roots, pub_seed, fors_pk_addr, hash_state_seeded);
|
||||
}
|
||||
@ -0,0 +1,32 @@
|
||||
#ifndef SPX_FORS_H
|
||||
#define SPX_FORS_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "params.h"
|
||||
#include "hash_state.h"
|
||||
|
||||
/**
|
||||
* Signs a message m, deriving the secret key from sk_seed and the FTS address.
|
||||
* Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits.
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_fors_sign(
|
||||
unsigned char *sig, unsigned char *pk,
|
||||
const unsigned char *m,
|
||||
const unsigned char *sk_seed, const unsigned char *pub_seed,
|
||||
const uint32_t fors_addr[8], const hash_state *hash_state_seeded);
|
||||
|
||||
/**
|
||||
* Derives the FORS public key from a signature.
|
||||
* This can be used for verification by comparing to a known public key, or to
|
||||
* subsequently verify a signature on the derived public key. The latter is the
|
||||
* typical use-case when used as an FTS below an OTS in a hypertree.
|
||||
* Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits.
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_fors_pk_from_sig(
|
||||
unsigned char *pk,
|
||||
const unsigned char *sig, const unsigned char *m,
|
||||
const unsigned char *pub_seed, const uint32_t fors_addr[8],
|
||||
const hash_state *hash_state_seeded);
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,29 @@
|
||||
#ifndef SPX_HASH_H
|
||||
#define SPX_HASH_H
|
||||
|
||||
#include "hash_state.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_initialize_hash_function(
|
||||
hash_state *hash_state_seeded,
|
||||
const unsigned char *pub_seed, const unsigned char *sk_seed);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_prf_addr(
|
||||
unsigned char *out, const unsigned char *key, const uint32_t addr[8],
|
||||
const hash_state *hash_state_seeded);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_gen_message_random(
|
||||
unsigned char *R,
|
||||
const unsigned char *sk_prf, const unsigned char *optrand,
|
||||
const unsigned char *m, size_t mlen,
|
||||
const hash_state *hash_state_seeded);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_hash_message(
|
||||
unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx,
|
||||
const unsigned char *R, const unsigned char *pk,
|
||||
const unsigned char *m, size_t mlen,
|
||||
const hash_state *hash_state_seeded);
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,157 @@
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "address.h"
|
||||
#include "hash.h"
|
||||
#include "params.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include "sha2.h"
|
||||
#include "sha256.h"
|
||||
|
||||
/* For SHA256, there is no immediate reason to initialize at the start,
|
||||
so this function is an empty operation. */
|
||||
void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_initialize_hash_function(
|
||||
hash_state *hash_state_seeded,
|
||||
const unsigned char *pub_seed, const unsigned char *sk_seed) {
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_seed_state(hash_state_seeded, pub_seed);
|
||||
(void)sk_seed; /* Suppress an 'unused parameter' warning. */
|
||||
}
|
||||
|
||||
/*
|
||||
* Computes PRF(key, addr), given a secret key of SPX_N bytes and an address
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_prf_addr(
|
||||
unsigned char *out, const unsigned char *key, const uint32_t addr[8],
|
||||
const hash_state *hash_state_seeded) {
|
||||
unsigned char buf[SPX_N + SPX_SHA256_ADDR_BYTES];
|
||||
unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES];
|
||||
|
||||
memcpy(buf, key, SPX_N);
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_compress_address(buf + SPX_N, addr);
|
||||
|
||||
sha256(outbuf, buf, SPX_N + SPX_SHA256_ADDR_BYTES);
|
||||
memcpy(out, outbuf, SPX_N);
|
||||
|
||||
(void)hash_state_seeded; /* Prevent unused parameter warning. */
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the message-dependent randomness R, using a secret seed as a key
|
||||
* for HMAC, and an optional randomization value prefixed to the message.
|
||||
* This requires m to have at least SPX_SHA256_BLOCK_BYTES + SPX_N space
|
||||
* available in front of the pointer, i.e. before the message to use for the
|
||||
* prefix. This is necessary to prevent having to move the message around (and
|
||||
* allocate memory for it).
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_gen_message_random(
|
||||
unsigned char *R,
|
||||
const unsigned char *sk_prf, const unsigned char *optrand,
|
||||
const unsigned char *m, size_t mlen, const hash_state *hash_state_seeded) {
|
||||
unsigned char buf[SPX_SHA256_BLOCK_BYTES + SPX_SHA256_OUTPUT_BYTES];
|
||||
sha256ctx state;
|
||||
int i;
|
||||
|
||||
/* This implements HMAC-SHA256 */
|
||||
for (i = 0; i < SPX_N; i++) {
|
||||
buf[i] = 0x36 ^ sk_prf[i];
|
||||
}
|
||||
memset(buf + SPX_N, 0x36, SPX_SHA256_BLOCK_BYTES - SPX_N);
|
||||
|
||||
sha256_inc_init(&state);
|
||||
sha256_inc_blocks(&state, buf, 1);
|
||||
|
||||
memcpy(buf, optrand, SPX_N);
|
||||
|
||||
/* If optrand + message cannot fill up an entire block */
|
||||
if (SPX_N + mlen < SPX_SHA256_BLOCK_BYTES) {
|
||||
memcpy(buf + SPX_N, m, mlen);
|
||||
sha256_inc_finalize(buf + SPX_SHA256_BLOCK_BYTES, &state,
|
||||
buf, mlen + SPX_N);
|
||||
}
|
||||
/* Otherwise first fill a block, so that finalize only uses the message */
|
||||
else {
|
||||
memcpy(buf + SPX_N, m, SPX_SHA256_BLOCK_BYTES - SPX_N);
|
||||
sha256_inc_blocks(&state, buf, 1);
|
||||
|
||||
m += SPX_SHA256_BLOCK_BYTES - SPX_N;
|
||||
mlen -= SPX_SHA256_BLOCK_BYTES - SPX_N;
|
||||
sha256_inc_finalize(buf + SPX_SHA256_BLOCK_BYTES, &state, m, mlen);
|
||||
}
|
||||
|
||||
for (i = 0; i < SPX_N; i++) {
|
||||
buf[i] = 0x5c ^ sk_prf[i];
|
||||
}
|
||||
memset(buf + SPX_N, 0x5c, SPX_SHA256_BLOCK_BYTES - SPX_N);
|
||||
|
||||
sha256(buf, buf, SPX_SHA256_BLOCK_BYTES + SPX_SHA256_OUTPUT_BYTES);
|
||||
memcpy(R, buf, SPX_N);
|
||||
|
||||
(void)hash_state_seeded; /* Prevent unused parameter warning. */
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the message hash using R, the public key, and the message.
|
||||
* Outputs the message digest and the index of the leaf. The index is split in
|
||||
* the tree index and the leaf index, for convenient copying to an address.
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_hash_message(
|
||||
unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx,
|
||||
const unsigned char *R, const unsigned char *pk,
|
||||
const unsigned char *m, size_t mlen,
|
||||
const hash_state *hash_state_seeded) {
|
||||
#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1))
|
||||
#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8)
|
||||
#define SPX_LEAF_BITS SPX_TREE_HEIGHT
|
||||
#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8)
|
||||
#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES)
|
||||
|
||||
unsigned char seed[SPX_SHA256_OUTPUT_BYTES + 4];
|
||||
|
||||
/* Round to nearest multiple of SPX_SHA256_BLOCK_BYTES */
|
||||
#define SPX_INBLOCKS (((SPX_N + SPX_PK_BYTES + SPX_SHA256_BLOCK_BYTES - 1) & \
|
||||
-SPX_SHA256_BLOCK_BYTES) / SPX_SHA256_BLOCK_BYTES)
|
||||
unsigned char inbuf[SPX_INBLOCKS * SPX_SHA256_BLOCK_BYTES];
|
||||
|
||||
unsigned char buf[SPX_DGST_BYTES];
|
||||
unsigned char *bufp = buf;
|
||||
sha256ctx state;
|
||||
|
||||
sha256_inc_init(&state);
|
||||
|
||||
memcpy(inbuf, R, SPX_N);
|
||||
memcpy(inbuf + SPX_N, pk, SPX_PK_BYTES);
|
||||
|
||||
/* If R + pk + message cannot fill up an entire block */
|
||||
if (SPX_N + SPX_PK_BYTES + mlen < SPX_INBLOCKS * SPX_SHA256_BLOCK_BYTES) {
|
||||
memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, mlen);
|
||||
sha256_inc_finalize(seed, &state, inbuf, SPX_N + SPX_PK_BYTES + mlen);
|
||||
}
|
||||
/* Otherwise first fill a block, so that finalize only uses the message */
|
||||
else {
|
||||
memcpy(inbuf + SPX_N + SPX_PK_BYTES, m,
|
||||
SPX_INBLOCKS * SPX_SHA256_BLOCK_BYTES - SPX_N - SPX_PK_BYTES);
|
||||
sha256_inc_blocks(&state, inbuf, SPX_INBLOCKS);
|
||||
|
||||
m += SPX_INBLOCKS * SPX_SHA256_BLOCK_BYTES - SPX_N - SPX_PK_BYTES;
|
||||
mlen -= SPX_INBLOCKS * SPX_SHA256_BLOCK_BYTES - SPX_N - SPX_PK_BYTES;
|
||||
sha256_inc_finalize(seed, &state, m, mlen);
|
||||
}
|
||||
|
||||
/* By doing this in two steps, we prevent hashing the message twice;
|
||||
otherwise each iteration in MGF1 would hash the message again. */
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_mgf1(bufp, SPX_DGST_BYTES, seed, SPX_SHA256_OUTPUT_BYTES);
|
||||
|
||||
memcpy(digest, bufp, SPX_FORS_MSG_BYTES);
|
||||
bufp += SPX_FORS_MSG_BYTES;
|
||||
|
||||
*tree = PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_bytes_to_ull(bufp, SPX_TREE_BYTES);
|
||||
*tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS);
|
||||
bufp += SPX_TREE_BYTES;
|
||||
|
||||
*leaf_idx = (uint32_t)PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_bytes_to_ull(
|
||||
bufp, SPX_LEAF_BYTES);
|
||||
*leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS);
|
||||
|
||||
(void)hash_state_seeded; /* Prevent unused parameter warning. */
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
#ifndef SPX_PRIMITIVE_H
|
||||
#define SPX_PRIMITIVE_H
|
||||
|
||||
#include "sha2.h"
|
||||
#define hash_state sha256ctx
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,53 @@
|
||||
#ifndef SPX_PARAMS_H
|
||||
#define SPX_PARAMS_H
|
||||
|
||||
/* Hash output length in bytes. */
|
||||
#define SPX_N 16
|
||||
/* Height of the hypertree. */
|
||||
#define SPX_FULL_HEIGHT 64
|
||||
/* Number of subtree layer. */
|
||||
#define SPX_D 8
|
||||
/* FORS tree dimensions. */
|
||||
#define SPX_FORS_HEIGHT 15
|
||||
#define SPX_FORS_TREES 10
|
||||
/* Winternitz parameter, */
|
||||
#define SPX_WOTS_W 16
|
||||
|
||||
/* The hash function is defined by linking a different hash.c file, as opposed
|
||||
to setting a #define constant. */
|
||||
|
||||
/* For clarity */
|
||||
#define SPX_ADDR_BYTES 32
|
||||
|
||||
/* WOTS parameters. */
|
||||
#define SPX_WOTS_LOGW 4
|
||||
|
||||
#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW)
|
||||
|
||||
/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */
|
||||
#define SPX_WOTS_LEN2 3
|
||||
|
||||
#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2)
|
||||
#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N)
|
||||
#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES
|
||||
|
||||
/* Subtree size. */
|
||||
#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D)
|
||||
|
||||
/* FORS parameters. */
|
||||
#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8)
|
||||
#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N)
|
||||
#define SPX_FORS_PK_BYTES SPX_N
|
||||
|
||||
/* Resulting SPX sizes. */
|
||||
#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\
|
||||
SPX_FULL_HEIGHT * SPX_N)
|
||||
#define SPX_PK_BYTES (2 * SPX_N)
|
||||
#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES)
|
||||
|
||||
/* Optionally, signing can be made non-deterministic using optrand.
|
||||
This can help counter side-channel attacks that would benefit from
|
||||
getting a large number of traces when the signer uses the same nodes. */
|
||||
#define SPX_OPTRAND_BYTES 32
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,71 @@
|
||||
/* Based on the public domain implementation in
|
||||
* crypto_hash/sha512/ref/ from http://bench.cr.yp.to/supercop.html
|
||||
* by D. J. Bernstein */
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "sha2.h"
|
||||
#include "sha256.h"
|
||||
#include "utils.h"
|
||||
|
||||
/*
|
||||
* Compresses an address to a 22-byte sequence.
|
||||
* This reduces the number of required SHA256 compression calls, as the last
|
||||
* block of input is padded with at least 65 bits.
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_compress_address(unsigned char *out, const uint32_t addr[8]) {
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_ull_to_bytes(out, 1, addr[0]); /* drop 3 bytes of the layer field */
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_ull_to_bytes(out + 1, 4, addr[2]); /* drop the highest tree address word */
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_ull_to_bytes(out + 5, 4, addr[3]);
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_ull_to_bytes(out + 9, 1, addr[4]); /* drop 3 bytes of the type field */
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_ull_to_bytes(out + 10, 4, addr[5]);
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_ull_to_bytes(out + 14, 4, addr[6]);
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_ull_to_bytes(out + 18, 4, addr[7]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Requires 'input_plus_four_bytes' to have 'inlen' + 4 bytes, so that the last
|
||||
* four bytes can be used for the counter. Typically 'input' is merely a seed.
|
||||
* Outputs outlen number of bytes
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_mgf1(
|
||||
unsigned char *out, unsigned long outlen,
|
||||
unsigned char *input_plus_four_bytes, unsigned long inlen) {
|
||||
unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES];
|
||||
unsigned long i;
|
||||
|
||||
/* While we can fit in at least another full block of SHA256 output.. */
|
||||
for (i = 0; (i + 1)*SPX_SHA256_OUTPUT_BYTES <= outlen; i++) {
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_ull_to_bytes(input_plus_four_bytes + inlen, 4, i);
|
||||
sha256(out, input_plus_four_bytes, inlen + 4);
|
||||
out += SPX_SHA256_OUTPUT_BYTES;
|
||||
}
|
||||
/* Until we cannot anymore, and we fill the remainder. */
|
||||
if (outlen > i * SPX_SHA256_OUTPUT_BYTES) {
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_ull_to_bytes(input_plus_four_bytes + inlen, 4, i);
|
||||
sha256(outbuf, input_plus_four_bytes, inlen + 4);
|
||||
memcpy(out, outbuf, outlen - i * SPX_SHA256_OUTPUT_BYTES);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Absorb the constant pub_seed using one round of the compression function
|
||||
* This initializes hash_state_seeded, which can then be reused in thash
|
||||
**/
|
||||
void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_seed_state(sha256ctx *hash_state_seeded, const unsigned char *pub_seed) {
|
||||
uint8_t block[SPX_SHA256_BLOCK_BYTES];
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < SPX_N; ++i) {
|
||||
block[i] = pub_seed[i];
|
||||
}
|
||||
for (i = SPX_N; i < SPX_SHA256_BLOCK_BYTES; ++i) {
|
||||
block[i] = 0;
|
||||
}
|
||||
|
||||
sha256_inc_init(hash_state_seeded);
|
||||
sha256_inc_blocks(hash_state_seeded, block, 1);
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
#ifndef SPX_SHA256_H
|
||||
#define SPX_SHA256_H
|
||||
|
||||
#define SPX_SHA256_BLOCK_BYTES 64
|
||||
#define SPX_SHA256_OUTPUT_BYTES 32 /* This does not necessarily equal SPX_N */
|
||||
#define SPX_SHA256_ADDR_BYTES 22
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "sha2.h"
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_compress_address(unsigned char *out, const uint32_t addr[8]);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_mgf1(
|
||||
unsigned char *out, unsigned long outlen,
|
||||
unsigned char *input_plus_four_bytes, unsigned long inlen);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_seed_state(sha256ctx *hash_state_seeded, const unsigned char *pub_seed);
|
||||
|
||||
#endif
|
||||
353
src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/sign.c
Normal file
353
src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/sign.c
Normal file
@ -0,0 +1,353 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "address.h"
|
||||
#include "api.h"
|
||||
#include "fors.h"
|
||||
#include "hash.h"
|
||||
#include "params.h"
|
||||
#include "hash_state.h"
|
||||
#include "randombytes.h"
|
||||
#include "thash.h"
|
||||
#include "utils.h"
|
||||
#include "wots.h"
|
||||
|
||||
/**
|
||||
* Computes the leaf at a given address. First generates the WOTS key pair,
|
||||
* then computes leaf by hashing horizontally.
|
||||
*/
|
||||
static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed,
|
||||
const unsigned char *pub_seed,
|
||||
uint32_t addr_idx, const uint32_t tree_addr[8],
|
||||
const hash_state *hash_state_seeded) {
|
||||
unsigned char pk[SPX_WOTS_BYTES];
|
||||
uint32_t wots_addr[8] = {0};
|
||||
uint32_t wots_pk_addr[8] = {0};
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_type(
|
||||
wots_addr, SPX_ADDR_TYPE_WOTS);
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_type(
|
||||
wots_pk_addr, SPX_ADDR_TYPE_WOTSPK);
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_copy_subtree_addr(
|
||||
wots_addr, tree_addr);
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_keypair_addr(
|
||||
wots_addr, addr_idx);
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_wots_gen_pk(
|
||||
pk, sk_seed, pub_seed, wots_addr, hash_state_seeded);
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_copy_keypair_addr(
|
||||
wots_pk_addr, wots_addr);
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_thash_WOTS_LEN(
|
||||
leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the length of a secret key, in bytes
|
||||
*/
|
||||
size_t PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_crypto_sign_secretkeybytes(void) {
|
||||
return PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_CRYPTO_SECRETKEYBYTES;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the length of a public key, in bytes
|
||||
*/
|
||||
size_t PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_crypto_sign_publickeybytes(void) {
|
||||
return PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_CRYPTO_PUBLICKEYBYTES;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the length of a signature, in bytes
|
||||
*/
|
||||
size_t PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_crypto_sign_bytes(void) {
|
||||
return PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_CRYPTO_BYTES;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the length of the seed required to generate a key pair, in bytes
|
||||
*/
|
||||
size_t PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_crypto_sign_seedbytes(void) {
|
||||
return PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_CRYPTO_SEEDBYTES;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generates an SPX key pair given a seed of length
|
||||
* Format sk: [SK_SEED || SK_PRF || PUB_SEED || root]
|
||||
* Format pk: [PUB_SEED || root]
|
||||
*/
|
||||
int PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_crypto_sign_seed_keypair(
|
||||
uint8_t *pk, uint8_t *sk, const uint8_t *seed) {
|
||||
/* We do not need the auth path in key generation, but it simplifies the
|
||||
code to have just one treehash routine that computes both root and path
|
||||
in one function. */
|
||||
unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N];
|
||||
uint32_t top_tree_addr[8] = {0};
|
||||
hash_state hash_state_seeded;
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_layer_addr(
|
||||
top_tree_addr, SPX_D - 1);
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_type(
|
||||
top_tree_addr, SPX_ADDR_TYPE_HASHTREE);
|
||||
|
||||
/* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */
|
||||
memcpy(sk, seed, PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_CRYPTO_SEEDBYTES);
|
||||
|
||||
memcpy(pk, sk + 2 * SPX_N, SPX_N);
|
||||
|
||||
/* This hook allows the hash function instantiation to do whatever
|
||||
preparation or computation it needs, based on the public seed. */
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_initialize_hash_function(&hash_state_seeded, pk, sk);
|
||||
|
||||
/* Compute root node of the top-most subtree. */
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_treehash_TREE_HEIGHT(
|
||||
sk + 3 * SPX_N, auth_path, sk, sk + 2 * SPX_N, 0, 0,
|
||||
wots_gen_leaf, top_tree_addr, &hash_state_seeded);
|
||||
|
||||
memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generates an SPX key pair.
|
||||
* Format sk: [SK_SEED || SK_PRF || PUB_SEED || root]
|
||||
* Format pk: [PUB_SEED || root]
|
||||
*/
|
||||
int PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_crypto_sign_keypair(
|
||||
uint8_t *pk, uint8_t *sk) {
|
||||
unsigned char seed[PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_CRYPTO_SEEDBYTES];
|
||||
randombytes(seed, PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_CRYPTO_SEEDBYTES);
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_crypto_sign_seed_keypair(
|
||||
pk, sk, seed);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array containing a detached signature.
|
||||
*/
|
||||
int PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_crypto_sign_signature(
|
||||
uint8_t *sig, size_t *siglen,
|
||||
const uint8_t *m, size_t mlen, const uint8_t *sk) {
|
||||
const unsigned char *sk_seed = sk;
|
||||
const unsigned char *sk_prf = sk + SPX_N;
|
||||
const unsigned char *pk = sk + 2 * SPX_N;
|
||||
const unsigned char *pub_seed = pk;
|
||||
|
||||
unsigned char optrand[SPX_N];
|
||||
unsigned char mhash[SPX_FORS_MSG_BYTES];
|
||||
unsigned char root[SPX_N];
|
||||
uint32_t i;
|
||||
uint64_t tree;
|
||||
uint32_t idx_leaf;
|
||||
uint32_t wots_addr[8] = {0};
|
||||
uint32_t tree_addr[8] = {0};
|
||||
|
||||
hash_state hash_state_seeded;
|
||||
|
||||
/* This hook allows the hash function instantiation to do whatever
|
||||
preparation or computation it needs, based on the public seed. */
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_initialize_hash_function(
|
||||
&hash_state_seeded,
|
||||
pub_seed, sk_seed);
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_type(
|
||||
wots_addr, SPX_ADDR_TYPE_WOTS);
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_type(
|
||||
tree_addr, SPX_ADDR_TYPE_HASHTREE);
|
||||
|
||||
/* Optionally, signing can be made non-deterministic using optrand.
|
||||
This can help counter side-channel attacks that would benefit from
|
||||
getting a large number of traces when the signer uses the same nodes. */
|
||||
randombytes(optrand, SPX_N);
|
||||
/* Compute the digest randomization value. */
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_gen_message_random(
|
||||
sig, sk_prf, optrand, m, mlen, &hash_state_seeded);
|
||||
|
||||
/* Derive the message digest and leaf index from R, PK and M. */
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_hash_message(
|
||||
mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded);
|
||||
sig += SPX_N;
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_tree_addr(wots_addr, tree);
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_keypair_addr(
|
||||
wots_addr, idx_leaf);
|
||||
|
||||
/* Sign the message hash using FORS. */
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_fors_sign(
|
||||
sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded);
|
||||
sig += SPX_FORS_BYTES;
|
||||
|
||||
for (i = 0; i < SPX_D; i++) {
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_layer_addr(tree_addr, i);
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_tree_addr(tree_addr, tree);
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_copy_subtree_addr(
|
||||
wots_addr, tree_addr);
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_keypair_addr(
|
||||
wots_addr, idx_leaf);
|
||||
|
||||
/* Compute a WOTS signature. */
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_wots_sign(
|
||||
sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded);
|
||||
sig += SPX_WOTS_BYTES;
|
||||
|
||||
/* Compute the authentication path for the used WOTS leaf. */
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_treehash_TREE_HEIGHT(
|
||||
root, sig, sk_seed, pub_seed, idx_leaf, 0,
|
||||
wots_gen_leaf, tree_addr, &hash_state_seeded);
|
||||
sig += SPX_TREE_HEIGHT * SPX_N;
|
||||
|
||||
/* Update the indices for the next layer. */
|
||||
idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1));
|
||||
tree = tree >> SPX_TREE_HEIGHT;
|
||||
}
|
||||
|
||||
*siglen = SPX_BYTES;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies a detached signature and message under a given public key.
|
||||
*/
|
||||
int PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_crypto_sign_verify(
|
||||
const uint8_t *sig, size_t siglen,
|
||||
const uint8_t *m, size_t mlen, const uint8_t *pk) {
|
||||
const unsigned char *pub_seed = pk;
|
||||
const unsigned char *pub_root = pk + SPX_N;
|
||||
unsigned char mhash[SPX_FORS_MSG_BYTES];
|
||||
unsigned char wots_pk[SPX_WOTS_BYTES];
|
||||
unsigned char root[SPX_N];
|
||||
unsigned char leaf[SPX_N];
|
||||
unsigned int i;
|
||||
uint64_t tree;
|
||||
uint32_t idx_leaf;
|
||||
uint32_t wots_addr[8] = {0};
|
||||
uint32_t tree_addr[8] = {0};
|
||||
uint32_t wots_pk_addr[8] = {0};
|
||||
|
||||
hash_state hash_state_seeded;
|
||||
|
||||
if (siglen != SPX_BYTES) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* This hook allows the hash function instantiation to do whatever
|
||||
preparation or computation it needs, based on the public seed. */
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_initialize_hash_function(
|
||||
&hash_state_seeded,
|
||||
pub_seed, NULL);
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_type(
|
||||
wots_addr, SPX_ADDR_TYPE_WOTS);
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_type(
|
||||
tree_addr, SPX_ADDR_TYPE_HASHTREE);
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_type(
|
||||
wots_pk_addr, SPX_ADDR_TYPE_WOTSPK);
|
||||
|
||||
/* Derive the message digest and leaf index from R || PK || M. */
|
||||
/* The additional SPX_N is a result of the hash domain separator. */
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_hash_message(
|
||||
mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded);
|
||||
sig += SPX_N;
|
||||
|
||||
/* Layer correctly defaults to 0, so no need to set_layer_addr */
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_tree_addr(wots_addr, tree);
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_keypair_addr(
|
||||
wots_addr, idx_leaf);
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_fors_pk_from_sig(
|
||||
root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded);
|
||||
sig += SPX_FORS_BYTES;
|
||||
|
||||
/* For each subtree.. */
|
||||
for (i = 0; i < SPX_D; i++) {
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_layer_addr(tree_addr, i);
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_tree_addr(tree_addr, tree);
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_copy_subtree_addr(
|
||||
wots_addr, tree_addr);
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_keypair_addr(
|
||||
wots_addr, idx_leaf);
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_copy_keypair_addr(
|
||||
wots_pk_addr, wots_addr);
|
||||
|
||||
/* The WOTS public key is only correct if the signature was correct. */
|
||||
/* Initially, root is the FORS pk, but on subsequent iterations it is
|
||||
the root of the subtree below the currently processed subtree. */
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_wots_pk_from_sig(
|
||||
wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded);
|
||||
sig += SPX_WOTS_BYTES;
|
||||
|
||||
/* Compute the leaf node using the WOTS public key. */
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_thash_WOTS_LEN(
|
||||
leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded);
|
||||
|
||||
/* Compute the root node of this subtree. */
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_compute_root(
|
||||
root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT,
|
||||
pub_seed, tree_addr, &hash_state_seeded);
|
||||
sig += SPX_TREE_HEIGHT * SPX_N;
|
||||
|
||||
/* Update the indices for the next layer. */
|
||||
idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1));
|
||||
tree = tree >> SPX_TREE_HEIGHT;
|
||||
}
|
||||
|
||||
/* Check if the root node equals the root node in the public key. */
|
||||
if (memcmp(root, pub_root, SPX_N) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns an array containing the signature followed by the message.
|
||||
*/
|
||||
int PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_crypto_sign(
|
||||
uint8_t *sm, size_t *smlen,
|
||||
const uint8_t *m, size_t mlen, const uint8_t *sk) {
|
||||
size_t siglen;
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_crypto_sign_signature(
|
||||
sm, &siglen, m, mlen, sk);
|
||||
|
||||
memmove(sm + SPX_BYTES, m, mlen);
|
||||
*smlen = siglen + mlen;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies a given signature-message pair under a given public key.
|
||||
*/
|
||||
int PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_crypto_sign_open(
|
||||
uint8_t *m, size_t *mlen,
|
||||
const uint8_t *sm, size_t smlen, const uint8_t *pk) {
|
||||
/* The API caller does not necessarily know what size a signature should be
|
||||
but SPHINCS+ signatures are always exactly SPX_BYTES. */
|
||||
if (smlen < SPX_BYTES) {
|
||||
memset(m, 0, smlen);
|
||||
*mlen = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
*mlen = smlen - SPX_BYTES;
|
||||
|
||||
if (PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_crypto_sign_verify(
|
||||
sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) {
|
||||
memset(m, 0, smlen);
|
||||
*mlen = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* If verification was successful, move the message to the right place. */
|
||||
memmove(m, sm + SPX_BYTES, *mlen);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
#ifndef SPX_THASH_H
|
||||
#define SPX_THASH_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "hash_state.h"
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_thash_1(
|
||||
unsigned char *out, const unsigned char *in,
|
||||
const unsigned char *pub_seed, uint32_t addr[8],
|
||||
const hash_state *hash_state_seeded);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_thash_2(
|
||||
unsigned char *out, const unsigned char *in,
|
||||
const unsigned char *pub_seed, uint32_t addr[8],
|
||||
const hash_state *hash_state_seeded);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_thash_WOTS_LEN(
|
||||
unsigned char *out, const unsigned char *in,
|
||||
const unsigned char *pub_seed, uint32_t addr[8],
|
||||
const hash_state *hash_state_seeded);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_thash_FORS_TREES(
|
||||
unsigned char *out, const unsigned char *in,
|
||||
const unsigned char *pub_seed, uint32_t addr[8],
|
||||
const hash_state *hash_state_seeded);
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,75 @@
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "address.h"
|
||||
#include "params.h"
|
||||
#include "thash.h"
|
||||
|
||||
#include "sha2.h"
|
||||
#include "sha256.h"
|
||||
|
||||
/**
|
||||
* Takes an array of inblocks concatenated arrays of SPX_N bytes.
|
||||
*/
|
||||
static void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_thash(
|
||||
unsigned char *out, unsigned char *buf,
|
||||
const unsigned char *in, unsigned int inblocks,
|
||||
const unsigned char *pub_seed, uint32_t addr[8],
|
||||
const sha256ctx *hash_state_seeded) {
|
||||
|
||||
unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES];
|
||||
sha256ctx sha2_state;
|
||||
|
||||
(void)pub_seed; /* Suppress an 'unused parameter' warning. */
|
||||
|
||||
/* Retrieve precomputed state containing pub_seed */
|
||||
sha256_inc_dupe_state(&sha2_state, hash_state_seeded);
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_compress_address(buf, addr);
|
||||
memcpy(buf + SPX_SHA256_ADDR_BYTES, in, inblocks * SPX_N);
|
||||
|
||||
sha256_inc_finalize(outbuf, &sha2_state, buf, SPX_SHA256_ADDR_BYTES + inblocks * SPX_N);
|
||||
memcpy(out, outbuf, SPX_N);
|
||||
}
|
||||
|
||||
/* The wrappers below ensure that we use fixed-size buffers on the stack */
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_thash_1(
|
||||
unsigned char *out, const unsigned char *in,
|
||||
const unsigned char *pub_seed, uint32_t addr[8],
|
||||
const sha256ctx *hash_state_seeded) {
|
||||
|
||||
unsigned char buf[SPX_SHA256_ADDR_BYTES + 1 * SPX_N];
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_thash(
|
||||
out, buf, in, 1, pub_seed, addr, hash_state_seeded);
|
||||
}
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_thash_2(
|
||||
unsigned char *out, const unsigned char *in,
|
||||
const unsigned char *pub_seed, uint32_t addr[8],
|
||||
const sha256ctx *hash_state_seeded) {
|
||||
|
||||
unsigned char buf[SPX_SHA256_ADDR_BYTES + 2 * SPX_N];
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_thash(
|
||||
out, buf, in, 2, pub_seed, addr, hash_state_seeded);
|
||||
}
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_thash_WOTS_LEN(
|
||||
unsigned char *out, const unsigned char *in,
|
||||
const unsigned char *pub_seed, uint32_t addr[8],
|
||||
const sha256ctx *hash_state_seeded) {
|
||||
|
||||
unsigned char buf[SPX_SHA256_ADDR_BYTES + SPX_WOTS_LEN * SPX_N];
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_thash(
|
||||
out, buf, in, SPX_WOTS_LEN, pub_seed, addr, hash_state_seeded);
|
||||
}
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_thash_FORS_TREES(
|
||||
unsigned char *out, const unsigned char *in,
|
||||
const unsigned char *pub_seed, uint32_t addr[8],
|
||||
const sha256ctx *hash_state_seeded) {
|
||||
|
||||
unsigned char buf[SPX_SHA256_ADDR_BYTES + SPX_FORS_TREES * SPX_N];
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_thash(
|
||||
out, buf, in, SPX_FORS_TREES, pub_seed, addr, hash_state_seeded);
|
||||
}
|
||||
199
src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/utils.c
Normal file
199
src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/utils.c
Normal file
@ -0,0 +1,199 @@
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "address.h"
|
||||
#include "hash.h"
|
||||
#include "params.h"
|
||||
#include "hash_state.h"
|
||||
#include "thash.h"
|
||||
#include "utils.h"
|
||||
|
||||
/**
|
||||
* Converts the value of 'in' to 'outlen' bytes in big-endian byte order.
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_ull_to_bytes(
|
||||
unsigned char *out, size_t outlen, unsigned long long in) {
|
||||
|
||||
/* Iterate over out in decreasing order, for big-endianness. */
|
||||
for (size_t i = outlen; i > 0; i--) {
|
||||
out[i - 1] = in & 0xff;
|
||||
in = in >> 8;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the inlen bytes in 'in' from big-endian byte order to an integer.
|
||||
*/
|
||||
unsigned long long PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_bytes_to_ull(
|
||||
const unsigned char *in, size_t inlen) {
|
||||
unsigned long long retval = 0;
|
||||
|
||||
for (size_t i = 0; i < inlen; i++) {
|
||||
retval |= ((unsigned long long)in[i]) << (8 * (inlen - 1 - i));
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes a root node given a leaf and an auth path.
|
||||
* Expects address to be complete other than the tree_height and tree_index.
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_compute_root(
|
||||
unsigned char *root, const unsigned char *leaf,
|
||||
uint32_t leaf_idx, uint32_t idx_offset,
|
||||
const unsigned char *auth_path, uint32_t tree_height,
|
||||
const unsigned char *pub_seed, uint32_t addr[8],
|
||||
const hash_state *hash_state_seeded) {
|
||||
uint32_t i;
|
||||
unsigned char buffer[2 * SPX_N];
|
||||
|
||||
/* If leaf_idx is odd (last bit = 1), current path element is a right child
|
||||
and auth_path has to go left. Otherwise it is the other way around. */
|
||||
if (leaf_idx & 1) {
|
||||
memcpy(buffer + SPX_N, leaf, SPX_N);
|
||||
memcpy(buffer, auth_path, SPX_N);
|
||||
} else {
|
||||
memcpy(buffer, leaf, SPX_N);
|
||||
memcpy(buffer + SPX_N, auth_path, SPX_N);
|
||||
}
|
||||
auth_path += SPX_N;
|
||||
|
||||
for (i = 0; i < tree_height - 1; i++) {
|
||||
leaf_idx >>= 1;
|
||||
idx_offset >>= 1;
|
||||
/* Set the address of the node we're creating. */
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_tree_height(addr, i + 1);
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_tree_index(
|
||||
addr, leaf_idx + idx_offset);
|
||||
|
||||
/* Pick the right or left neighbor, depending on parity of the node. */
|
||||
if (leaf_idx & 1) {
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_thash_2(
|
||||
buffer + SPX_N, buffer, pub_seed, addr, hash_state_seeded);
|
||||
memcpy(buffer, auth_path, SPX_N);
|
||||
} else {
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_thash_2(
|
||||
buffer, buffer, pub_seed, addr, hash_state_seeded);
|
||||
memcpy(buffer + SPX_N, auth_path, SPX_N);
|
||||
}
|
||||
auth_path += SPX_N;
|
||||
}
|
||||
|
||||
/* The last iteration is exceptional; we do not copy an auth_path node. */
|
||||
leaf_idx >>= 1;
|
||||
idx_offset >>= 1;
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_tree_height(addr, tree_height);
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_tree_index(
|
||||
addr, leaf_idx + idx_offset);
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_thash_2(
|
||||
root, buffer, pub_seed, addr, hash_state_seeded);
|
||||
}
|
||||
|
||||
/**
|
||||
* For a given leaf index, computes the authentication path and the resulting
|
||||
* root node using Merkle's TreeHash algorithm.
|
||||
* Expects the layer and tree parts of the tree_addr to be set, as well as the
|
||||
* tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE).
|
||||
* Applies the offset idx_offset to indices before building addresses, so that
|
||||
* it is possible to continue counting indices across trees.
|
||||
*/
|
||||
static void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_treehash(
|
||||
unsigned char *root, unsigned char *auth_path,
|
||||
unsigned char *stack, unsigned int *heights,
|
||||
const unsigned char *sk_seed, const unsigned char *pub_seed,
|
||||
uint32_t leaf_idx, uint32_t idx_offset, uint32_t tree_height,
|
||||
void (*gen_leaf)(
|
||||
unsigned char * /* leaf */,
|
||||
const unsigned char * /* sk_seed */,
|
||||
const unsigned char * /* pub_seed */,
|
||||
uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */,
|
||||
const hash_state * /* hash_state_seeded */),
|
||||
uint32_t tree_addr[8],
|
||||
const hash_state *hash_state_seeded) {
|
||||
|
||||
unsigned int offset = 0;
|
||||
uint32_t idx;
|
||||
uint32_t tree_idx;
|
||||
|
||||
for (idx = 0; idx < (uint32_t)(1 << tree_height); idx++) {
|
||||
/* Add the next leaf node to the stack. */
|
||||
gen_leaf(stack + offset * SPX_N,
|
||||
sk_seed, pub_seed, idx + idx_offset, tree_addr,
|
||||
hash_state_seeded);
|
||||
offset++;
|
||||
heights[offset - 1] = 0;
|
||||
|
||||
/* If this is a node we need for the auth path.. */
|
||||
if ((leaf_idx ^ 0x1) == idx) {
|
||||
memcpy(auth_path, stack + (offset - 1)*SPX_N, SPX_N);
|
||||
}
|
||||
|
||||
/* While the top-most nodes are of equal height.. */
|
||||
while (offset >= 2 && heights[offset - 1] == heights[offset - 2]) {
|
||||
/* Compute index of the new node, in the next layer. */
|
||||
tree_idx = (idx >> (heights[offset - 1] + 1));
|
||||
|
||||
/* Set the address of the node we're creating. */
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_tree_height(
|
||||
tree_addr, heights[offset - 1] + 1);
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_tree_index(
|
||||
tree_addr, tree_idx + (idx_offset >> (heights[offset - 1] + 1)));
|
||||
/* Hash the top-most nodes from the stack together. */
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_thash_2(
|
||||
stack + (offset - 2)*SPX_N, stack + (offset - 2)*SPX_N,
|
||||
pub_seed, tree_addr, hash_state_seeded);
|
||||
offset--;
|
||||
/* Note that the top-most node is now one layer higher. */
|
||||
heights[offset - 1]++;
|
||||
|
||||
/* If this is a node we need for the auth path.. */
|
||||
if (((leaf_idx >> heights[offset - 1]) ^ 0x1) == tree_idx) {
|
||||
memcpy(auth_path + heights[offset - 1]*SPX_N,
|
||||
stack + (offset - 1)*SPX_N, SPX_N);
|
||||
}
|
||||
}
|
||||
}
|
||||
memcpy(root, stack, SPX_N);
|
||||
}
|
||||
|
||||
/* The wrappers below ensure that we use fixed-size buffers on the stack */
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_treehash_FORS_HEIGHT(
|
||||
unsigned char *root, unsigned char *auth_path,
|
||||
const unsigned char *sk_seed, const unsigned char *pub_seed,
|
||||
uint32_t leaf_idx, uint32_t idx_offset,
|
||||
void (*gen_leaf)(
|
||||
unsigned char * /* leaf */,
|
||||
const unsigned char * /* sk_seed */,
|
||||
const unsigned char * /* pub_seed */,
|
||||
uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */,
|
||||
const hash_state * /* hash_state_seeded */),
|
||||
uint32_t tree_addr[8], const hash_state *hash_state_seeded) {
|
||||
|
||||
unsigned char stack[(SPX_FORS_HEIGHT + 1)*SPX_N];
|
||||
unsigned int heights[SPX_FORS_HEIGHT + 1];
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_treehash(
|
||||
root, auth_path, stack, heights, sk_seed, pub_seed,
|
||||
leaf_idx, idx_offset, SPX_FORS_HEIGHT, gen_leaf, tree_addr, hash_state_seeded);
|
||||
}
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_treehash_TREE_HEIGHT(
|
||||
unsigned char *root, unsigned char *auth_path,
|
||||
const unsigned char *sk_seed, const unsigned char *pub_seed,
|
||||
uint32_t leaf_idx, uint32_t idx_offset,
|
||||
void (*gen_leaf)(
|
||||
unsigned char * /* leaf */,
|
||||
const unsigned char * /* sk_seed */,
|
||||
const unsigned char * /* pub_seed */,
|
||||
uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */,
|
||||
const hash_state * /* hash_state_seeded */),
|
||||
uint32_t tree_addr[8], const hash_state *hash_state_seeded) {
|
||||
|
||||
unsigned char stack[(SPX_TREE_HEIGHT + 1)*SPX_N];
|
||||
unsigned int heights[SPX_TREE_HEIGHT + 1];
|
||||
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_treehash(
|
||||
root, auth_path, stack, heights, sk_seed, pub_seed,
|
||||
leaf_idx, idx_offset, SPX_TREE_HEIGHT, gen_leaf, tree_addr, hash_state_seeded);
|
||||
}
|
||||
@ -0,0 +1,64 @@
|
||||
#ifndef SPX_UTILS_H
|
||||
#define SPX_UTILS_H
|
||||
|
||||
#include "params.h"
|
||||
#include "hash_state.h"
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* Converts the value of 'in' to 'outlen' bytes in big-endian byte order.
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_ull_to_bytes(
|
||||
unsigned char *out, size_t outlen, unsigned long long in);
|
||||
|
||||
/**
|
||||
* Converts the inlen bytes in 'in' from big-endian byte order to an integer.
|
||||
*/
|
||||
unsigned long long PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_bytes_to_ull(
|
||||
const unsigned char *in, size_t inlen);
|
||||
|
||||
/**
|
||||
* Computes a root node given a leaf and an auth path.
|
||||
* Expects address to be complete other than the tree_height and tree_index.
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_compute_root(
|
||||
unsigned char *root, const unsigned char *leaf,
|
||||
uint32_t leaf_idx, uint32_t idx_offset,
|
||||
const unsigned char *auth_path, uint32_t tree_height,
|
||||
const unsigned char *pub_seed, uint32_t addr[8],
|
||||
const hash_state *hash_state_seeded);
|
||||
|
||||
/**
|
||||
* For a given leaf index, computes the authentication path and the resulting
|
||||
* root node using Merkle's TreeHash algorithm.
|
||||
* Expects the layer and tree parts of the tree_addr to be set, as well as the
|
||||
* tree type (i.e. SPX_ADDR_TYPE_HASHTREE or SPX_ADDR_TYPE_FORSTREE).
|
||||
* Applies the offset idx_offset to indices before building addresses, so that
|
||||
* it is possible to continue counting indices across trees.
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_treehash_FORS_HEIGHT(
|
||||
unsigned char *root, unsigned char *auth_path,
|
||||
const unsigned char *sk_seed, const unsigned char *pub_seed,
|
||||
uint32_t leaf_idx, uint32_t idx_offset,
|
||||
void (*gen_leaf)(
|
||||
unsigned char * /* leaf */,
|
||||
const unsigned char * /* sk_seed */,
|
||||
const unsigned char * /* pub_seed */,
|
||||
uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */,
|
||||
const hash_state * /* hash_state_seeded */),
|
||||
uint32_t tree_addr[8], const hash_state *hash_state_seeded);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_treehash_TREE_HEIGHT(
|
||||
unsigned char *root, unsigned char *auth_path,
|
||||
const unsigned char *sk_seed, const unsigned char *pub_seed,
|
||||
uint32_t leaf_idx, uint32_t idx_offset,
|
||||
void (*gen_leaf)(
|
||||
unsigned char * /* leaf */,
|
||||
const unsigned char * /* sk_seed */,
|
||||
const unsigned char * /* pub_seed */,
|
||||
uint32_t /* addr_idx */, const uint32_t[8] /* tree_addr */,
|
||||
const hash_state * /* hash_state_seeded */),
|
||||
uint32_t tree_addr[8], const hash_state *hash_state_seeded);
|
||||
|
||||
#endif
|
||||
167
src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/wots.c
Normal file
167
src/sig/sphincs/pqclean_sphincs-sha256-128s-simple_clean/wots.c
Normal file
@ -0,0 +1,167 @@
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "address.h"
|
||||
#include "hash.h"
|
||||
#include "params.h"
|
||||
#include "hash_state.h"
|
||||
#include "thash.h"
|
||||
#include "utils.h"
|
||||
#include "wots.h"
|
||||
|
||||
// TODO clarify address expectations, and make them more uniform.
|
||||
// TODO i.e. do we expect types to be set already?
|
||||
// TODO and do we expect modifications or copies?
|
||||
|
||||
/**
|
||||
* Computes the starting value for a chain, i.e. the secret key.
|
||||
* Expects the address to be complete up to the chain address.
|
||||
*/
|
||||
static void wots_gen_sk(unsigned char *sk, const unsigned char *sk_seed,
|
||||
uint32_t wots_addr[8],
|
||||
const hash_state *hash_state_seeded) {
|
||||
/* Make sure that the hash address is actually zeroed. */
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_hash_addr(wots_addr, 0);
|
||||
|
||||
/* Generate sk element. */
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_prf_addr(sk, sk_seed, wots_addr, hash_state_seeded);
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the chaining function.
|
||||
* out and in have to be n-byte arrays.
|
||||
*
|
||||
* Interprets in as start-th value of the chain.
|
||||
* addr has to contain the address of the chain.
|
||||
*/
|
||||
static void gen_chain(unsigned char *out, const unsigned char *in,
|
||||
unsigned int start, unsigned int steps,
|
||||
const unsigned char *pub_seed, uint32_t addr[8],
|
||||
const hash_state *hash_state_seeded) {
|
||||
uint32_t i;
|
||||
|
||||
/* Initialize out with the value at position 'start'. */
|
||||
memcpy(out, in, SPX_N);
|
||||
|
||||
/* Iterate 'steps' calls to the hash function. */
|
||||
for (i = start; i < (start + steps) && i < SPX_WOTS_W; i++) {
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_hash_addr(addr, i);
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_thash_1(
|
||||
out, out, pub_seed, addr, hash_state_seeded);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* base_w algorithm as described in draft.
|
||||
* Interprets an array of bytes as integers in base w.
|
||||
* This only works when log_w is a divisor of 8.
|
||||
*/
|
||||
static void base_w(unsigned int *output, const size_t out_len,
|
||||
const unsigned char *input) {
|
||||
size_t in = 0;
|
||||
size_t out = 0;
|
||||
unsigned char total = 0;
|
||||
unsigned int bits = 0;
|
||||
size_t consumed;
|
||||
|
||||
for (consumed = 0; consumed < out_len; consumed++) {
|
||||
if (bits == 0) {
|
||||
total = input[in];
|
||||
in++;
|
||||
bits += 8;
|
||||
}
|
||||
bits -= SPX_WOTS_LOGW;
|
||||
output[out] = (unsigned int)((total >> bits) & (SPX_WOTS_W - 1));
|
||||
out++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Computes the WOTS+ checksum over a message (in base_w). */
|
||||
static void wots_checksum(unsigned int *csum_base_w,
|
||||
const unsigned int *msg_base_w) {
|
||||
unsigned int csum = 0;
|
||||
unsigned char csum_bytes[(SPX_WOTS_LEN2 * SPX_WOTS_LOGW + 7) / 8];
|
||||
unsigned int i;
|
||||
|
||||
/* Compute checksum. */
|
||||
for (i = 0; i < SPX_WOTS_LEN1; i++) {
|
||||
csum += SPX_WOTS_W - 1 - msg_base_w[i];
|
||||
}
|
||||
|
||||
/* Convert checksum to base_w. */
|
||||
/* Make sure expected empty zero bits are the least significant bits. */
|
||||
csum = csum << (8 - ((SPX_WOTS_LEN2 * SPX_WOTS_LOGW) % 8));
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_ull_to_bytes(
|
||||
csum_bytes, sizeof(csum_bytes), csum);
|
||||
base_w(csum_base_w, SPX_WOTS_LEN2, csum_bytes);
|
||||
}
|
||||
|
||||
/* Takes a message and derives the matching chain lengths. */
|
||||
static void chain_lengths(unsigned int *lengths, const unsigned char *msg) {
|
||||
base_w(lengths, SPX_WOTS_LEN1, msg);
|
||||
wots_checksum(lengths + SPX_WOTS_LEN1, lengths);
|
||||
}
|
||||
|
||||
/**
|
||||
* WOTS key generation. Takes a 32 byte sk_seed, expands it to WOTS private key
|
||||
* elements and computes the corresponding public key.
|
||||
* It requires the seed pub_seed (used to generate bitmasks and hash keys)
|
||||
* and the address of this WOTS key pair.
|
||||
*
|
||||
* Writes the computed public key to 'pk'.
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_wots_gen_pk(
|
||||
unsigned char *pk, const unsigned char *sk_seed,
|
||||
const unsigned char *pub_seed, uint32_t addr[8],
|
||||
const hash_state *hash_state_seeded) {
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < SPX_WOTS_LEN; i++) {
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_chain_addr(addr, i);
|
||||
wots_gen_sk(pk + i * SPX_N, sk_seed, addr, hash_state_seeded);
|
||||
gen_chain(pk + i * SPX_N, pk + i * SPX_N,
|
||||
0, SPX_WOTS_W - 1, pub_seed, addr, hash_state_seeded);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes a n-byte message and the 32-byte sk_see to compute a signature 'sig'.
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_wots_sign(
|
||||
unsigned char *sig, const unsigned char *msg,
|
||||
const unsigned char *sk_seed, const unsigned char *pub_seed,
|
||||
uint32_t addr[8], const hash_state *hash_state_seeded) {
|
||||
unsigned int lengths[SPX_WOTS_LEN];
|
||||
uint32_t i;
|
||||
|
||||
chain_lengths(lengths, msg);
|
||||
|
||||
for (i = 0; i < SPX_WOTS_LEN; i++) {
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_chain_addr(addr, i);
|
||||
wots_gen_sk(sig + i * SPX_N, sk_seed, addr, hash_state_seeded);
|
||||
gen_chain(sig + i * SPX_N, sig + i * SPX_N, 0, lengths[i], pub_seed, addr, hash_state_seeded);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes a WOTS signature and an n-byte message, computes a WOTS public key.
|
||||
*
|
||||
* Writes the computed public key to 'pk'.
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_wots_pk_from_sig(
|
||||
unsigned char *pk,
|
||||
const unsigned char *sig, const unsigned char *msg,
|
||||
const unsigned char *pub_seed, uint32_t addr[8],
|
||||
const hash_state *hash_state_seeded) {
|
||||
unsigned int lengths[SPX_WOTS_LEN];
|
||||
uint32_t i;
|
||||
|
||||
chain_lengths(lengths, msg);
|
||||
|
||||
for (i = 0; i < SPX_WOTS_LEN; i++) {
|
||||
PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_set_chain_addr(addr, i);
|
||||
gen_chain(pk + i * SPX_N, sig + i * SPX_N,
|
||||
lengths[i], SPX_WOTS_W - 1 - lengths[i], pub_seed, addr,
|
||||
hash_state_seeded);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,41 @@
|
||||
#ifndef SPX_WOTS_H
|
||||
#define SPX_WOTS_H
|
||||
|
||||
#include "params.h"
|
||||
#include "hash_state.h"
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* WOTS key generation. Takes a 32 byte seed for the private key, expands it to
|
||||
* a full WOTS private key and computes the corresponding public key.
|
||||
* It requires the seed pub_seed (used to generate bitmasks and hash keys)
|
||||
* and the address of this WOTS key pair.
|
||||
*
|
||||
* Writes the computed public key to 'pk'.
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_wots_gen_pk(
|
||||
unsigned char *pk, const unsigned char *sk_seed,
|
||||
const unsigned char *pub_seed, uint32_t addr[8],
|
||||
const hash_state *hash_state_seeded);
|
||||
|
||||
/**
|
||||
* Takes a n-byte message and the 32-byte seed for the private key to compute a
|
||||
* signature that is placed at 'sig'.
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_wots_sign(
|
||||
unsigned char *sig, const unsigned char *msg,
|
||||
const unsigned char *sk_seed, const unsigned char *pub_seed,
|
||||
uint32_t addr[8], const hash_state *hash_state_seeded);
|
||||
|
||||
/**
|
||||
* Takes a WOTS signature and an n-byte message, computes a WOTS public key.
|
||||
*
|
||||
* Writes the computed public key to 'pk'.
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_wots_pk_from_sig(
|
||||
unsigned char *pk,
|
||||
const unsigned char *sig, const unsigned char *msg,
|
||||
const unsigned char *pub_seed, uint32_t addr[8],
|
||||
const hash_state *hash_state_seeded);
|
||||
|
||||
#endif
|
||||
116
src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/LICENSE
Normal file
116
src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/LICENSE
Normal file
@ -0,0 +1,116 @@
|
||||
CC0 1.0 Universal
|
||||
|
||||
Statement of Purpose
|
||||
|
||||
The laws of most jurisdictions throughout the world automatically confer
|
||||
exclusive Copyright and Related Rights (defined below) upon the creator and
|
||||
subsequent owner(s) (each and all, an "owner") of an original work of
|
||||
authorship and/or a database (each, a "Work").
|
||||
|
||||
Certain owners wish to permanently relinquish those rights to a Work for the
|
||||
purpose of contributing to a commons of creative, cultural and scientific
|
||||
works ("Commons") that the public can reliably and without fear of later
|
||||
claims of infringement build upon, modify, incorporate in other works, reuse
|
||||
and redistribute as freely as possible in any form whatsoever and for any
|
||||
purposes, including without limitation commercial purposes. These owners may
|
||||
contribute to the Commons to promote the ideal of a free culture and the
|
||||
further production of creative, cultural and scientific works, or to gain
|
||||
reputation or greater distribution for their Work in part through the use and
|
||||
efforts of others.
|
||||
|
||||
For these and/or other purposes and motivations, and without any expectation
|
||||
of additional consideration or compensation, the person associating CC0 with a
|
||||
Work (the "Affirmer"), to the extent that he or she is an owner of Copyright
|
||||
and Related Rights in the Work, voluntarily elects to apply CC0 to the Work
|
||||
and publicly distribute the Work under its terms, with knowledge of his or her
|
||||
Copyright and Related Rights in the Work and the meaning and intended legal
|
||||
effect of CC0 on those rights.
|
||||
|
||||
1. Copyright and Related Rights. A Work made available under CC0 may be
|
||||
protected by copyright and related or neighboring rights ("Copyright and
|
||||
Related Rights"). Copyright and Related Rights include, but are not limited
|
||||
to, the following:
|
||||
|
||||
i. the right to reproduce, adapt, distribute, perform, display, communicate,
|
||||
and translate a Work;
|
||||
|
||||
ii. moral rights retained by the original author(s) and/or performer(s);
|
||||
|
||||
iii. publicity and privacy rights pertaining to a person's image or likeness
|
||||
depicted in a Work;
|
||||
|
||||
iv. rights protecting against unfair competition in regards to a Work,
|
||||
subject to the limitations in paragraph 4(a), below;
|
||||
|
||||
v. rights protecting the extraction, dissemination, use and reuse of data in
|
||||
a Work;
|
||||
|
||||
vi. database rights (such as those arising under Directive 96/9/EC of the
|
||||
European Parliament and of the Council of 11 March 1996 on the legal
|
||||
protection of databases, and under any national implementation thereof,
|
||||
including any amended or successor version of such directive); and
|
||||
|
||||
vii. other similar, equivalent or corresponding rights throughout the world
|
||||
based on applicable law or treaty, and any national implementations thereof.
|
||||
|
||||
2. Waiver. To the greatest extent permitted by, but not in contravention of,
|
||||
applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and
|
||||
unconditionally waives, abandons, and surrenders all of Affirmer's Copyright
|
||||
and Related Rights and associated claims and causes of action, whether now
|
||||
known or unknown (including existing as well as future claims and causes of
|
||||
action), in the Work (i) in all territories worldwide, (ii) for the maximum
|
||||
duration provided by applicable law or treaty (including future time
|
||||
extensions), (iii) in any current or future medium and for any number of
|
||||
copies, and (iv) for any purpose whatsoever, including without limitation
|
||||
commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes
|
||||
the Waiver for the benefit of each member of the public at large and to the
|
||||
detriment of Affirmer's heirs and successors, fully intending that such Waiver
|
||||
shall not be subject to revocation, rescission, cancellation, termination, or
|
||||
any other legal or equitable action to disrupt the quiet enjoyment of the Work
|
||||
by the public as contemplated by Affirmer's express Statement of Purpose.
|
||||
|
||||
3. Public License Fallback. Should any part of the Waiver for any reason be
|
||||
judged legally invalid or ineffective under applicable law, then the Waiver
|
||||
shall be preserved to the maximum extent permitted taking into account
|
||||
Affirmer's express Statement of Purpose. In addition, to the extent the Waiver
|
||||
is so judged Affirmer hereby grants to each affected person a royalty-free,
|
||||
non transferable, non sublicensable, non exclusive, irrevocable and
|
||||
unconditional license to exercise Affirmer's Copyright and Related Rights in
|
||||
the Work (i) in all territories worldwide, (ii) for the maximum duration
|
||||
provided by applicable law or treaty (including future time extensions), (iii)
|
||||
in any current or future medium and for any number of copies, and (iv) for any
|
||||
purpose whatsoever, including without limitation commercial, advertising or
|
||||
promotional purposes (the "License"). The License shall be deemed effective as
|
||||
of the date CC0 was applied by Affirmer to the Work. Should any part of the
|
||||
License for any reason be judged legally invalid or ineffective under
|
||||
applicable law, such partial invalidity or ineffectiveness shall not
|
||||
invalidate the remainder of the License, and in such case Affirmer hereby
|
||||
affirms that he or she will not (i) exercise any of his or her remaining
|
||||
Copyright and Related Rights in the Work or (ii) assert any associated claims
|
||||
and causes of action with respect to the Work, in either case contrary to
|
||||
Affirmer's express Statement of Purpose.
|
||||
|
||||
4. Limitations and Disclaimers.
|
||||
|
||||
a. No trademark or patent rights held by Affirmer are waived, abandoned,
|
||||
surrendered, licensed or otherwise affected by this document.
|
||||
|
||||
b. Affirmer offers the Work as-is and makes no representations or warranties
|
||||
of any kind concerning the Work, express, implied, statutory or otherwise,
|
||||
including without limitation warranties of title, merchantability, fitness
|
||||
for a particular purpose, non infringement, or the absence of latent or
|
||||
other defects, accuracy, or the present or absence of errors, whether or not
|
||||
discoverable, all to the greatest extent permissible under applicable law.
|
||||
|
||||
c. Affirmer disclaims responsibility for clearing rights of other persons
|
||||
that may apply to the Work or any use thereof, including without limitation
|
||||
any person's Copyright and Related Rights in the Work. Further, Affirmer
|
||||
disclaims responsibility for obtaining any necessary consents, permissions
|
||||
or other rights required for any use of the Work.
|
||||
|
||||
d. Affirmer understands and acknowledges that Creative Commons is not a
|
||||
party to this document and has no duty or obligation with respect to this
|
||||
CC0 or use of the Work.
|
||||
|
||||
For more information, please see
|
||||
<http://creativecommons.org/publicdomain/zero/1.0/>
|
||||
@ -0,0 +1,78 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#include "address.h"
|
||||
#include "params.h"
|
||||
#include "utils.h"
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_addr_to_bytes(
|
||||
unsigned char *bytes, const uint32_t addr[8]) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_ull_to_bytes(
|
||||
bytes + i * 4, 4, addr[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_layer_addr(
|
||||
uint32_t addr[8], uint32_t layer) {
|
||||
addr[0] = layer;
|
||||
}
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_tree_addr(
|
||||
uint32_t addr[8], uint64_t tree) {
|
||||
addr[1] = 0;
|
||||
addr[2] = (uint32_t) (tree >> 32);
|
||||
addr[3] = (uint32_t) tree;
|
||||
}
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_type(
|
||||
uint32_t addr[8], uint32_t type) {
|
||||
addr[4] = type;
|
||||
}
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_copy_subtree_addr(
|
||||
uint32_t out[8], const uint32_t in[8]) {
|
||||
out[0] = in[0];
|
||||
out[1] = in[1];
|
||||
out[2] = in[2];
|
||||
out[3] = in[3];
|
||||
}
|
||||
|
||||
/* These functions are used for OTS addresses. */
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_keypair_addr(
|
||||
uint32_t addr[8], uint32_t keypair) {
|
||||
addr[5] = keypair;
|
||||
}
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_copy_keypair_addr(
|
||||
uint32_t out[8], const uint32_t in[8]) {
|
||||
out[0] = in[0];
|
||||
out[1] = in[1];
|
||||
out[2] = in[2];
|
||||
out[3] = in[3];
|
||||
out[5] = in[5];
|
||||
}
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_chain_addr(
|
||||
uint32_t addr[8], uint32_t chain) {
|
||||
addr[6] = chain;
|
||||
}
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_hash_addr(
|
||||
uint32_t addr[8], uint32_t hash) {
|
||||
addr[7] = hash;
|
||||
}
|
||||
|
||||
/* These functions are used for all hash tree addresses (including FORS). */
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_tree_height(
|
||||
uint32_t addr[8], uint32_t tree_height) {
|
||||
addr[6] = tree_height;
|
||||
}
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_tree_index(
|
||||
uint32_t addr[8], uint32_t tree_index) {
|
||||
addr[7] = tree_index;
|
||||
}
|
||||
@ -0,0 +1,50 @@
|
||||
#ifndef SPX_ADDRESS_H
|
||||
#define SPX_ADDRESS_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define SPX_ADDR_TYPE_WOTS 0
|
||||
#define SPX_ADDR_TYPE_WOTSPK 1
|
||||
#define SPX_ADDR_TYPE_HASHTREE 2
|
||||
#define SPX_ADDR_TYPE_FORSTREE 3
|
||||
#define SPX_ADDR_TYPE_FORSPK 4
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_addr_to_bytes(
|
||||
unsigned char *bytes, const uint32_t addr[8]);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_layer_addr(
|
||||
uint32_t addr[8], uint32_t layer);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_tree_addr(
|
||||
uint32_t addr[8], uint64_t tree);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_type(
|
||||
uint32_t addr[8], uint32_t type);
|
||||
|
||||
/* Copies the layer and tree part of one address into the other */
|
||||
void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_copy_subtree_addr(
|
||||
uint32_t out[8], const uint32_t in[8]);
|
||||
|
||||
/* These functions are used for WOTS and FORS addresses. */
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_keypair_addr(
|
||||
uint32_t addr[8], uint32_t keypair);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_chain_addr(
|
||||
uint32_t addr[8], uint32_t chain);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_hash_addr(
|
||||
uint32_t addr[8], uint32_t hash);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_copy_keypair_addr(
|
||||
uint32_t out[8], const uint32_t in[8]);
|
||||
|
||||
/* These functions are used for all hash tree addresses (including FORS). */
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_tree_height(
|
||||
uint32_t addr[8], uint32_t tree_height);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_tree_index(
|
||||
uint32_t addr[8], uint32_t tree_index);
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,78 @@
|
||||
#ifndef PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_API_H
|
||||
#define PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_API_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_CRYPTO_ALGNAME "SPHINCS+"
|
||||
|
||||
#define PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_CRYPTO_SECRETKEYBYTES 96
|
||||
#define PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_CRYPTO_PUBLICKEYBYTES 48
|
||||
#define PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_CRYPTO_BYTES 35664
|
||||
#define PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_CRYPTO_SEEDBYTES 72
|
||||
|
||||
/*
|
||||
* Returns the length of a secret key, in bytes
|
||||
*/
|
||||
size_t PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_crypto_sign_secretkeybytes(void);
|
||||
|
||||
/*
|
||||
* Returns the length of a public key, in bytes
|
||||
*/
|
||||
size_t PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_crypto_sign_publickeybytes(void);
|
||||
|
||||
/*
|
||||
* Returns the length of a signature, in bytes
|
||||
*/
|
||||
size_t PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_crypto_sign_bytes(void);
|
||||
|
||||
/*
|
||||
* Returns the length of the seed required to generate a key pair, in bytes
|
||||
*/
|
||||
size_t PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_crypto_sign_seedbytes(void);
|
||||
|
||||
/*
|
||||
* Generates a SPHINCS+ key pair given a seed.
|
||||
* Format sk: [SK_SEED || SK_PRF || PUB_SEED || root]
|
||||
* Format pk: [root || PUB_SEED]
|
||||
*/
|
||||
int PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_crypto_sign_seed_keypair(
|
||||
uint8_t *pk, uint8_t *sk, const uint8_t *seed);
|
||||
|
||||
/*
|
||||
* Generates a SPHINCS+ key pair.
|
||||
* Format sk: [SK_SEED || SK_PRF || PUB_SEED || root]
|
||||
* Format pk: [root || PUB_SEED]
|
||||
*/
|
||||
int PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_crypto_sign_keypair(
|
||||
uint8_t *pk, uint8_t *sk);
|
||||
|
||||
/**
|
||||
* Returns an array containing a detached signature.
|
||||
*/
|
||||
int PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_crypto_sign_signature(
|
||||
uint8_t *sig, size_t *siglen,
|
||||
const uint8_t *m, size_t mlen, const uint8_t *sk);
|
||||
|
||||
/**
|
||||
* Verifies a detached signature and message under a given public key.
|
||||
*/
|
||||
int PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_crypto_sign_verify(
|
||||
const uint8_t *sig, size_t siglen,
|
||||
const uint8_t *m, size_t mlen, const uint8_t *pk);
|
||||
|
||||
/**
|
||||
* Returns an array containing the signature followed by the message.
|
||||
*/
|
||||
int PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_crypto_sign(
|
||||
uint8_t *sm, size_t *smlen,
|
||||
const uint8_t *m, size_t mlen, const uint8_t *sk);
|
||||
|
||||
/**
|
||||
* Verifies a given signature-message pair under a given public key.
|
||||
*/
|
||||
int PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_crypto_sign_open(
|
||||
uint8_t *m, size_t *mlen,
|
||||
const uint8_t *sm, size_t smlen, const uint8_t *pk);
|
||||
|
||||
#endif
|
||||
169
src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/fors.c
Normal file
169
src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/fors.c
Normal file
@ -0,0 +1,169 @@
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "address.h"
|
||||
#include "fors.h"
|
||||
#include "hash.h"
|
||||
#include "hash_state.h"
|
||||
#include "thash.h"
|
||||
#include "utils.h"
|
||||
|
||||
static void fors_gen_sk(unsigned char *sk, const unsigned char *sk_seed,
|
||||
uint32_t fors_leaf_addr[8], const hash_state *hash_state_seeded) {
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_prf_addr(
|
||||
sk, sk_seed, fors_leaf_addr, hash_state_seeded);
|
||||
}
|
||||
|
||||
static void fors_sk_to_leaf(unsigned char *leaf, const unsigned char *sk,
|
||||
const unsigned char *pub_seed,
|
||||
uint32_t fors_leaf_addr[8],
|
||||
const hash_state *hash_state_seeded) {
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_thash_1(
|
||||
leaf, sk, pub_seed, fors_leaf_addr, hash_state_seeded);
|
||||
}
|
||||
|
||||
static void fors_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed,
|
||||
const unsigned char *pub_seed,
|
||||
uint32_t addr_idx, const uint32_t fors_tree_addr[8],
|
||||
const hash_state *hash_state_seeded) {
|
||||
uint32_t fors_leaf_addr[8] = {0};
|
||||
|
||||
/* Only copy the parts that must be kept in fors_leaf_addr. */
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_copy_keypair_addr(
|
||||
fors_leaf_addr, fors_tree_addr);
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_type(
|
||||
fors_leaf_addr, SPX_ADDR_TYPE_FORSTREE);
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_tree_index(
|
||||
fors_leaf_addr, addr_idx);
|
||||
|
||||
fors_gen_sk(leaf, sk_seed, fors_leaf_addr, hash_state_seeded);
|
||||
fors_sk_to_leaf(leaf, leaf, pub_seed, fors_leaf_addr, hash_state_seeded);
|
||||
}
|
||||
|
||||
/**
|
||||
* Interprets m as SPX_FORS_HEIGHT-bit unsigned integers.
|
||||
* Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits.
|
||||
* Assumes indices has space for SPX_FORS_TREES integers.
|
||||
*/
|
||||
static void message_to_indices(uint32_t *indices, const unsigned char *m) {
|
||||
unsigned int i, j;
|
||||
unsigned int offset = 0;
|
||||
|
||||
for (i = 0; i < SPX_FORS_TREES; i++) {
|
||||
indices[i] = 0;
|
||||
for (j = 0; j < SPX_FORS_HEIGHT; j++) {
|
||||
indices[i] ^= (((uint32_t)m[offset >> 3] >> (offset & 0x7)) & 0x1) << j;
|
||||
offset++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Signs a message m, deriving the secret key from sk_seed and the FTS address.
|
||||
* Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits.
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_fors_sign(
|
||||
unsigned char *sig, unsigned char *pk,
|
||||
const unsigned char *m,
|
||||
const unsigned char *sk_seed, const unsigned char *pub_seed,
|
||||
const uint32_t fors_addr[8], const hash_state *hash_state_seeded) {
|
||||
uint32_t indices[SPX_FORS_TREES];
|
||||
unsigned char roots[SPX_FORS_TREES * SPX_N];
|
||||
uint32_t fors_tree_addr[8] = {0};
|
||||
uint32_t fors_pk_addr[8] = {0};
|
||||
uint32_t idx_offset;
|
||||
unsigned int i;
|
||||
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_copy_keypair_addr(
|
||||
fors_tree_addr, fors_addr);
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_copy_keypair_addr(
|
||||
fors_pk_addr, fors_addr);
|
||||
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_type(
|
||||
fors_tree_addr, SPX_ADDR_TYPE_FORSTREE);
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_type(
|
||||
fors_pk_addr, SPX_ADDR_TYPE_FORSPK);
|
||||
|
||||
message_to_indices(indices, m);
|
||||
|
||||
for (i = 0; i < SPX_FORS_TREES; i++) {
|
||||
idx_offset = i * (1 << SPX_FORS_HEIGHT);
|
||||
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_tree_height(
|
||||
fors_tree_addr, 0);
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_tree_index(
|
||||
fors_tree_addr, indices[i] + idx_offset);
|
||||
|
||||
/* Include the secret key part that produces the selected leaf node. */
|
||||
fors_gen_sk(sig, sk_seed, fors_tree_addr, hash_state_seeded);
|
||||
sig += SPX_N;
|
||||
|
||||
/* Compute the authentication path for this leaf node. */
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_treehash_FORS_HEIGHT(
|
||||
roots + i * SPX_N, sig, sk_seed, pub_seed,
|
||||
indices[i], idx_offset, fors_gen_leaf, fors_tree_addr,
|
||||
hash_state_seeded);
|
||||
sig += SPX_N * SPX_FORS_HEIGHT;
|
||||
}
|
||||
|
||||
/* Hash horizontally across all tree roots to derive the public key. */
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_thash_FORS_TREES(
|
||||
pk, roots, pub_seed, fors_pk_addr, hash_state_seeded);
|
||||
}
|
||||
|
||||
/**
|
||||
* Derives the FORS public key from a signature.
|
||||
* This can be used for verification by comparing to a known public key, or to
|
||||
* subsequently verify a signature on the derived public key. The latter is the
|
||||
* typical use-case when used as an FTS below an OTS in a hypertree.
|
||||
* Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits.
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_fors_pk_from_sig(
|
||||
unsigned char *pk,
|
||||
const unsigned char *sig, const unsigned char *m,
|
||||
const unsigned char *pub_seed, const uint32_t fors_addr[8],
|
||||
const hash_state *hash_state_seeded) {
|
||||
uint32_t indices[SPX_FORS_TREES];
|
||||
unsigned char roots[SPX_FORS_TREES * SPX_N];
|
||||
unsigned char leaf[SPX_N];
|
||||
uint32_t fors_tree_addr[8] = {0};
|
||||
uint32_t fors_pk_addr[8] = {0};
|
||||
uint32_t idx_offset;
|
||||
unsigned int i;
|
||||
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_copy_keypair_addr(
|
||||
fors_tree_addr, fors_addr);
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_copy_keypair_addr(
|
||||
fors_pk_addr, fors_addr);
|
||||
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_type(
|
||||
fors_tree_addr, SPX_ADDR_TYPE_FORSTREE);
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_type(
|
||||
fors_pk_addr, SPX_ADDR_TYPE_FORSPK);
|
||||
|
||||
message_to_indices(indices, m);
|
||||
|
||||
for (i = 0; i < SPX_FORS_TREES; i++) {
|
||||
idx_offset = i * (1 << SPX_FORS_HEIGHT);
|
||||
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_tree_height(
|
||||
fors_tree_addr, 0);
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_tree_index(
|
||||
fors_tree_addr, indices[i] + idx_offset);
|
||||
|
||||
/* Derive the leaf from the included secret key part. */
|
||||
fors_sk_to_leaf(leaf, sig, pub_seed, fors_tree_addr, hash_state_seeded);
|
||||
sig += SPX_N;
|
||||
|
||||
/* Derive the corresponding root node of this tree. */
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_compute_root(
|
||||
roots + i * SPX_N, leaf, indices[i], idx_offset, sig,
|
||||
SPX_FORS_HEIGHT, pub_seed, fors_tree_addr, hash_state_seeded);
|
||||
sig += SPX_N * SPX_FORS_HEIGHT;
|
||||
}
|
||||
|
||||
/* Hash horizontally across all tree roots to derive the public key. */
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_thash_FORS_TREES(
|
||||
pk, roots, pub_seed, fors_pk_addr, hash_state_seeded);
|
||||
}
|
||||
@ -0,0 +1,32 @@
|
||||
#ifndef SPX_FORS_H
|
||||
#define SPX_FORS_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "params.h"
|
||||
#include "hash_state.h"
|
||||
|
||||
/**
|
||||
* Signs a message m, deriving the secret key from sk_seed and the FTS address.
|
||||
* Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits.
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_fors_sign(
|
||||
unsigned char *sig, unsigned char *pk,
|
||||
const unsigned char *m,
|
||||
const unsigned char *sk_seed, const unsigned char *pub_seed,
|
||||
const uint32_t fors_addr[8], const hash_state *hash_state_seeded);
|
||||
|
||||
/**
|
||||
* Derives the FORS public key from a signature.
|
||||
* This can be used for verification by comparing to a known public key, or to
|
||||
* subsequently verify a signature on the derived public key. The latter is the
|
||||
* typical use-case when used as an FTS below an OTS in a hypertree.
|
||||
* Assumes m contains at least SPX_FORS_HEIGHT * SPX_FORS_TREES bits.
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_fors_pk_from_sig(
|
||||
unsigned char *pk,
|
||||
const unsigned char *sig, const unsigned char *m,
|
||||
const unsigned char *pub_seed, const uint32_t fors_addr[8],
|
||||
const hash_state *hash_state_seeded);
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,29 @@
|
||||
#ifndef SPX_HASH_H
|
||||
#define SPX_HASH_H
|
||||
|
||||
#include "hash_state.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_initialize_hash_function(
|
||||
hash_state *hash_state_seeded,
|
||||
const unsigned char *pub_seed, const unsigned char *sk_seed);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_prf_addr(
|
||||
unsigned char *out, const unsigned char *key, const uint32_t addr[8],
|
||||
const hash_state *hash_state_seeded);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_gen_message_random(
|
||||
unsigned char *R,
|
||||
const unsigned char *sk_prf, const unsigned char *optrand,
|
||||
const unsigned char *m, size_t mlen,
|
||||
const hash_state *hash_state_seeded);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_hash_message(
|
||||
unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx,
|
||||
const unsigned char *R, const unsigned char *pk,
|
||||
const unsigned char *m, size_t mlen,
|
||||
const hash_state *hash_state_seeded);
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,157 @@
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "address.h"
|
||||
#include "hash.h"
|
||||
#include "params.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include "sha2.h"
|
||||
#include "sha256.h"
|
||||
|
||||
/* For SHA256, there is no immediate reason to initialize at the start,
|
||||
so this function is an empty operation. */
|
||||
void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_initialize_hash_function(
|
||||
hash_state *hash_state_seeded,
|
||||
const unsigned char *pub_seed, const unsigned char *sk_seed) {
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_seed_state(hash_state_seeded, pub_seed);
|
||||
(void)sk_seed; /* Suppress an 'unused parameter' warning. */
|
||||
}
|
||||
|
||||
/*
|
||||
* Computes PRF(key, addr), given a secret key of SPX_N bytes and an address
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_prf_addr(
|
||||
unsigned char *out, const unsigned char *key, const uint32_t addr[8],
|
||||
const hash_state *hash_state_seeded) {
|
||||
unsigned char buf[SPX_N + SPX_SHA256_ADDR_BYTES];
|
||||
unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES];
|
||||
|
||||
memcpy(buf, key, SPX_N);
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_compress_address(buf + SPX_N, addr);
|
||||
|
||||
sha256(outbuf, buf, SPX_N + SPX_SHA256_ADDR_BYTES);
|
||||
memcpy(out, outbuf, SPX_N);
|
||||
|
||||
(void)hash_state_seeded; /* Prevent unused parameter warning. */
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the message-dependent randomness R, using a secret seed as a key
|
||||
* for HMAC, and an optional randomization value prefixed to the message.
|
||||
* This requires m to have at least SPX_SHA256_BLOCK_BYTES + SPX_N space
|
||||
* available in front of the pointer, i.e. before the message to use for the
|
||||
* prefix. This is necessary to prevent having to move the message around (and
|
||||
* allocate memory for it).
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_gen_message_random(
|
||||
unsigned char *R,
|
||||
const unsigned char *sk_prf, const unsigned char *optrand,
|
||||
const unsigned char *m, size_t mlen, const hash_state *hash_state_seeded) {
|
||||
unsigned char buf[SPX_SHA256_BLOCK_BYTES + SPX_SHA256_OUTPUT_BYTES];
|
||||
sha256ctx state;
|
||||
int i;
|
||||
|
||||
/* This implements HMAC-SHA256 */
|
||||
for (i = 0; i < SPX_N; i++) {
|
||||
buf[i] = 0x36 ^ sk_prf[i];
|
||||
}
|
||||
memset(buf + SPX_N, 0x36, SPX_SHA256_BLOCK_BYTES - SPX_N);
|
||||
|
||||
sha256_inc_init(&state);
|
||||
sha256_inc_blocks(&state, buf, 1);
|
||||
|
||||
memcpy(buf, optrand, SPX_N);
|
||||
|
||||
/* If optrand + message cannot fill up an entire block */
|
||||
if (SPX_N + mlen < SPX_SHA256_BLOCK_BYTES) {
|
||||
memcpy(buf + SPX_N, m, mlen);
|
||||
sha256_inc_finalize(buf + SPX_SHA256_BLOCK_BYTES, &state,
|
||||
buf, mlen + SPX_N);
|
||||
}
|
||||
/* Otherwise first fill a block, so that finalize only uses the message */
|
||||
else {
|
||||
memcpy(buf + SPX_N, m, SPX_SHA256_BLOCK_BYTES - SPX_N);
|
||||
sha256_inc_blocks(&state, buf, 1);
|
||||
|
||||
m += SPX_SHA256_BLOCK_BYTES - SPX_N;
|
||||
mlen -= SPX_SHA256_BLOCK_BYTES - SPX_N;
|
||||
sha256_inc_finalize(buf + SPX_SHA256_BLOCK_BYTES, &state, m, mlen);
|
||||
}
|
||||
|
||||
for (i = 0; i < SPX_N; i++) {
|
||||
buf[i] = 0x5c ^ sk_prf[i];
|
||||
}
|
||||
memset(buf + SPX_N, 0x5c, SPX_SHA256_BLOCK_BYTES - SPX_N);
|
||||
|
||||
sha256(buf, buf, SPX_SHA256_BLOCK_BYTES + SPX_SHA256_OUTPUT_BYTES);
|
||||
memcpy(R, buf, SPX_N);
|
||||
|
||||
(void)hash_state_seeded; /* Prevent unused parameter warning. */
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the message hash using R, the public key, and the message.
|
||||
* Outputs the message digest and the index of the leaf. The index is split in
|
||||
* the tree index and the leaf index, for convenient copying to an address.
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_hash_message(
|
||||
unsigned char *digest, uint64_t *tree, uint32_t *leaf_idx,
|
||||
const unsigned char *R, const unsigned char *pk,
|
||||
const unsigned char *m, size_t mlen,
|
||||
const hash_state *hash_state_seeded) {
|
||||
#define SPX_TREE_BITS (SPX_TREE_HEIGHT * (SPX_D - 1))
|
||||
#define SPX_TREE_BYTES ((SPX_TREE_BITS + 7) / 8)
|
||||
#define SPX_LEAF_BITS SPX_TREE_HEIGHT
|
||||
#define SPX_LEAF_BYTES ((SPX_LEAF_BITS + 7) / 8)
|
||||
#define SPX_DGST_BYTES (SPX_FORS_MSG_BYTES + SPX_TREE_BYTES + SPX_LEAF_BYTES)
|
||||
|
||||
unsigned char seed[SPX_SHA256_OUTPUT_BYTES + 4];
|
||||
|
||||
/* Round to nearest multiple of SPX_SHA256_BLOCK_BYTES */
|
||||
#define SPX_INBLOCKS (((SPX_N + SPX_PK_BYTES + SPX_SHA256_BLOCK_BYTES - 1) & \
|
||||
-SPX_SHA256_BLOCK_BYTES) / SPX_SHA256_BLOCK_BYTES)
|
||||
unsigned char inbuf[SPX_INBLOCKS * SPX_SHA256_BLOCK_BYTES];
|
||||
|
||||
unsigned char buf[SPX_DGST_BYTES];
|
||||
unsigned char *bufp = buf;
|
||||
sha256ctx state;
|
||||
|
||||
sha256_inc_init(&state);
|
||||
|
||||
memcpy(inbuf, R, SPX_N);
|
||||
memcpy(inbuf + SPX_N, pk, SPX_PK_BYTES);
|
||||
|
||||
/* If R + pk + message cannot fill up an entire block */
|
||||
if (SPX_N + SPX_PK_BYTES + mlen < SPX_INBLOCKS * SPX_SHA256_BLOCK_BYTES) {
|
||||
memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, mlen);
|
||||
sha256_inc_finalize(seed, &state, inbuf, SPX_N + SPX_PK_BYTES + mlen);
|
||||
}
|
||||
/* Otherwise first fill a block, so that finalize only uses the message */
|
||||
else {
|
||||
memcpy(inbuf + SPX_N + SPX_PK_BYTES, m,
|
||||
SPX_INBLOCKS * SPX_SHA256_BLOCK_BYTES - SPX_N - SPX_PK_BYTES);
|
||||
sha256_inc_blocks(&state, inbuf, SPX_INBLOCKS);
|
||||
|
||||
m += SPX_INBLOCKS * SPX_SHA256_BLOCK_BYTES - SPX_N - SPX_PK_BYTES;
|
||||
mlen -= SPX_INBLOCKS * SPX_SHA256_BLOCK_BYTES - SPX_N - SPX_PK_BYTES;
|
||||
sha256_inc_finalize(seed, &state, m, mlen);
|
||||
}
|
||||
|
||||
/* By doing this in two steps, we prevent hashing the message twice;
|
||||
otherwise each iteration in MGF1 would hash the message again. */
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_mgf1(bufp, SPX_DGST_BYTES, seed, SPX_SHA256_OUTPUT_BYTES);
|
||||
|
||||
memcpy(digest, bufp, SPX_FORS_MSG_BYTES);
|
||||
bufp += SPX_FORS_MSG_BYTES;
|
||||
|
||||
*tree = PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_bytes_to_ull(bufp, SPX_TREE_BYTES);
|
||||
*tree &= (~(uint64_t)0) >> (64 - SPX_TREE_BITS);
|
||||
bufp += SPX_TREE_BYTES;
|
||||
|
||||
*leaf_idx = (uint32_t)PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_bytes_to_ull(
|
||||
bufp, SPX_LEAF_BYTES);
|
||||
*leaf_idx &= (~(uint32_t)0) >> (32 - SPX_LEAF_BITS);
|
||||
|
||||
(void)hash_state_seeded; /* Prevent unused parameter warning. */
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
#ifndef SPX_PRIMITIVE_H
|
||||
#define SPX_PRIMITIVE_H
|
||||
|
||||
#include "sha2.h"
|
||||
#define hash_state sha256ctx
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,53 @@
|
||||
#ifndef SPX_PARAMS_H
|
||||
#define SPX_PARAMS_H
|
||||
|
||||
/* Hash output length in bytes. */
|
||||
#define SPX_N 24
|
||||
/* Height of the hypertree. */
|
||||
#define SPX_FULL_HEIGHT 66
|
||||
/* Number of subtree layer. */
|
||||
#define SPX_D 22
|
||||
/* FORS tree dimensions. */
|
||||
#define SPX_FORS_HEIGHT 8
|
||||
#define SPX_FORS_TREES 33
|
||||
/* Winternitz parameter, */
|
||||
#define SPX_WOTS_W 16
|
||||
|
||||
/* The hash function is defined by linking a different hash.c file, as opposed
|
||||
to setting a #define constant. */
|
||||
|
||||
/* For clarity */
|
||||
#define SPX_ADDR_BYTES 32
|
||||
|
||||
/* WOTS parameters. */
|
||||
#define SPX_WOTS_LOGW 4
|
||||
|
||||
#define SPX_WOTS_LEN1 (8 * SPX_N / SPX_WOTS_LOGW)
|
||||
|
||||
/* SPX_WOTS_LEN2 is floor(log(len_1 * (w - 1)) / log(w)) + 1; we precompute */
|
||||
#define SPX_WOTS_LEN2 3
|
||||
|
||||
#define SPX_WOTS_LEN (SPX_WOTS_LEN1 + SPX_WOTS_LEN2)
|
||||
#define SPX_WOTS_BYTES (SPX_WOTS_LEN * SPX_N)
|
||||
#define SPX_WOTS_PK_BYTES SPX_WOTS_BYTES
|
||||
|
||||
/* Subtree size. */
|
||||
#define SPX_TREE_HEIGHT (SPX_FULL_HEIGHT / SPX_D)
|
||||
|
||||
/* FORS parameters. */
|
||||
#define SPX_FORS_MSG_BYTES ((SPX_FORS_HEIGHT * SPX_FORS_TREES + 7) / 8)
|
||||
#define SPX_FORS_BYTES ((SPX_FORS_HEIGHT + 1) * SPX_FORS_TREES * SPX_N)
|
||||
#define SPX_FORS_PK_BYTES SPX_N
|
||||
|
||||
/* Resulting SPX sizes. */
|
||||
#define SPX_BYTES (SPX_N + SPX_FORS_BYTES + SPX_D * SPX_WOTS_BYTES +\
|
||||
SPX_FULL_HEIGHT * SPX_N)
|
||||
#define SPX_PK_BYTES (2 * SPX_N)
|
||||
#define SPX_SK_BYTES (2 * SPX_N + SPX_PK_BYTES)
|
||||
|
||||
/* Optionally, signing can be made non-deterministic using optrand.
|
||||
This can help counter side-channel attacks that would benefit from
|
||||
getting a large number of traces when the signer uses the same nodes. */
|
||||
#define SPX_OPTRAND_BYTES 32
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,71 @@
|
||||
/* Based on the public domain implementation in
|
||||
* crypto_hash/sha512/ref/ from http://bench.cr.yp.to/supercop.html
|
||||
* by D. J. Bernstein */
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "sha2.h"
|
||||
#include "sha256.h"
|
||||
#include "utils.h"
|
||||
|
||||
/*
|
||||
* Compresses an address to a 22-byte sequence.
|
||||
* This reduces the number of required SHA256 compression calls, as the last
|
||||
* block of input is padded with at least 65 bits.
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_compress_address(unsigned char *out, const uint32_t addr[8]) {
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_ull_to_bytes(out, 1, addr[0]); /* drop 3 bytes of the layer field */
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_ull_to_bytes(out + 1, 4, addr[2]); /* drop the highest tree address word */
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_ull_to_bytes(out + 5, 4, addr[3]);
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_ull_to_bytes(out + 9, 1, addr[4]); /* drop 3 bytes of the type field */
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_ull_to_bytes(out + 10, 4, addr[5]);
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_ull_to_bytes(out + 14, 4, addr[6]);
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_ull_to_bytes(out + 18, 4, addr[7]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Requires 'input_plus_four_bytes' to have 'inlen' + 4 bytes, so that the last
|
||||
* four bytes can be used for the counter. Typically 'input' is merely a seed.
|
||||
* Outputs outlen number of bytes
|
||||
*/
|
||||
void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_mgf1(
|
||||
unsigned char *out, unsigned long outlen,
|
||||
unsigned char *input_plus_four_bytes, unsigned long inlen) {
|
||||
unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES];
|
||||
unsigned long i;
|
||||
|
||||
/* While we can fit in at least another full block of SHA256 output.. */
|
||||
for (i = 0; (i + 1)*SPX_SHA256_OUTPUT_BYTES <= outlen; i++) {
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_ull_to_bytes(input_plus_four_bytes + inlen, 4, i);
|
||||
sha256(out, input_plus_four_bytes, inlen + 4);
|
||||
out += SPX_SHA256_OUTPUT_BYTES;
|
||||
}
|
||||
/* Until we cannot anymore, and we fill the remainder. */
|
||||
if (outlen > i * SPX_SHA256_OUTPUT_BYTES) {
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_ull_to_bytes(input_plus_four_bytes + inlen, 4, i);
|
||||
sha256(outbuf, input_plus_four_bytes, inlen + 4);
|
||||
memcpy(out, outbuf, outlen - i * SPX_SHA256_OUTPUT_BYTES);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Absorb the constant pub_seed using one round of the compression function
|
||||
* This initializes hash_state_seeded, which can then be reused in thash
|
||||
**/
|
||||
void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_seed_state(sha256ctx *hash_state_seeded, const unsigned char *pub_seed) {
|
||||
uint8_t block[SPX_SHA256_BLOCK_BYTES];
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < SPX_N; ++i) {
|
||||
block[i] = pub_seed[i];
|
||||
}
|
||||
for (i = SPX_N; i < SPX_SHA256_BLOCK_BYTES; ++i) {
|
||||
block[i] = 0;
|
||||
}
|
||||
|
||||
sha256_inc_init(hash_state_seeded);
|
||||
sha256_inc_blocks(hash_state_seeded, block, 1);
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
#ifndef SPX_SHA256_H
|
||||
#define SPX_SHA256_H
|
||||
|
||||
#define SPX_SHA256_BLOCK_BYTES 64
|
||||
#define SPX_SHA256_OUTPUT_BYTES 32 /* This does not necessarily equal SPX_N */
|
||||
#define SPX_SHA256_ADDR_BYTES 22
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "sha2.h"
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_compress_address(unsigned char *out, const uint32_t addr[8]);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_mgf1(
|
||||
unsigned char *out, unsigned long outlen,
|
||||
unsigned char *input_plus_four_bytes, unsigned long inlen);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_seed_state(sha256ctx *hash_state_seeded, const unsigned char *pub_seed);
|
||||
|
||||
#endif
|
||||
353
src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/sign.c
Normal file
353
src/sig/sphincs/pqclean_sphincs-sha256-192f-robust_clean/sign.c
Normal file
@ -0,0 +1,353 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "address.h"
|
||||
#include "api.h"
|
||||
#include "fors.h"
|
||||
#include "hash.h"
|
||||
#include "params.h"
|
||||
#include "hash_state.h"
|
||||
#include "randombytes.h"
|
||||
#include "thash.h"
|
||||
#include "utils.h"
|
||||
#include "wots.h"
|
||||
|
||||
/**
|
||||
* Computes the leaf at a given address. First generates the WOTS key pair,
|
||||
* then computes leaf by hashing horizontally.
|
||||
*/
|
||||
static void wots_gen_leaf(unsigned char *leaf, const unsigned char *sk_seed,
|
||||
const unsigned char *pub_seed,
|
||||
uint32_t addr_idx, const uint32_t tree_addr[8],
|
||||
const hash_state *hash_state_seeded) {
|
||||
unsigned char pk[SPX_WOTS_BYTES];
|
||||
uint32_t wots_addr[8] = {0};
|
||||
uint32_t wots_pk_addr[8] = {0};
|
||||
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_type(
|
||||
wots_addr, SPX_ADDR_TYPE_WOTS);
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_type(
|
||||
wots_pk_addr, SPX_ADDR_TYPE_WOTSPK);
|
||||
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_copy_subtree_addr(
|
||||
wots_addr, tree_addr);
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_keypair_addr(
|
||||
wots_addr, addr_idx);
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_wots_gen_pk(
|
||||
pk, sk_seed, pub_seed, wots_addr, hash_state_seeded);
|
||||
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_copy_keypair_addr(
|
||||
wots_pk_addr, wots_addr);
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_thash_WOTS_LEN(
|
||||
leaf, pk, pub_seed, wots_pk_addr, hash_state_seeded);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the length of a secret key, in bytes
|
||||
*/
|
||||
size_t PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_crypto_sign_secretkeybytes(void) {
|
||||
return PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_CRYPTO_SECRETKEYBYTES;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the length of a public key, in bytes
|
||||
*/
|
||||
size_t PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_crypto_sign_publickeybytes(void) {
|
||||
return PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_CRYPTO_PUBLICKEYBYTES;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the length of a signature, in bytes
|
||||
*/
|
||||
size_t PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_crypto_sign_bytes(void) {
|
||||
return PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_CRYPTO_BYTES;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the length of the seed required to generate a key pair, in bytes
|
||||
*/
|
||||
size_t PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_crypto_sign_seedbytes(void) {
|
||||
return PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_CRYPTO_SEEDBYTES;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generates an SPX key pair given a seed of length
|
||||
* Format sk: [SK_SEED || SK_PRF || PUB_SEED || root]
|
||||
* Format pk: [PUB_SEED || root]
|
||||
*/
|
||||
int PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_crypto_sign_seed_keypair(
|
||||
uint8_t *pk, uint8_t *sk, const uint8_t *seed) {
|
||||
/* We do not need the auth path in key generation, but it simplifies the
|
||||
code to have just one treehash routine that computes both root and path
|
||||
in one function. */
|
||||
unsigned char auth_path[SPX_TREE_HEIGHT * SPX_N];
|
||||
uint32_t top_tree_addr[8] = {0};
|
||||
hash_state hash_state_seeded;
|
||||
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_layer_addr(
|
||||
top_tree_addr, SPX_D - 1);
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_type(
|
||||
top_tree_addr, SPX_ADDR_TYPE_HASHTREE);
|
||||
|
||||
/* Initialize SK_SEED, SK_PRF and PUB_SEED from seed. */
|
||||
memcpy(sk, seed, PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_CRYPTO_SEEDBYTES);
|
||||
|
||||
memcpy(pk, sk + 2 * SPX_N, SPX_N);
|
||||
|
||||
/* This hook allows the hash function instantiation to do whatever
|
||||
preparation or computation it needs, based on the public seed. */
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_initialize_hash_function(&hash_state_seeded, pk, sk);
|
||||
|
||||
/* Compute root node of the top-most subtree. */
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_treehash_TREE_HEIGHT(
|
||||
sk + 3 * SPX_N, auth_path, sk, sk + 2 * SPX_N, 0, 0,
|
||||
wots_gen_leaf, top_tree_addr, &hash_state_seeded);
|
||||
|
||||
memcpy(pk + SPX_N, sk + 3 * SPX_N, SPX_N);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generates an SPX key pair.
|
||||
* Format sk: [SK_SEED || SK_PRF || PUB_SEED || root]
|
||||
* Format pk: [PUB_SEED || root]
|
||||
*/
|
||||
int PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_crypto_sign_keypair(
|
||||
uint8_t *pk, uint8_t *sk) {
|
||||
unsigned char seed[PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_CRYPTO_SEEDBYTES];
|
||||
randombytes(seed, PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_CRYPTO_SEEDBYTES);
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_crypto_sign_seed_keypair(
|
||||
pk, sk, seed);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array containing a detached signature.
|
||||
*/
|
||||
int PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_crypto_sign_signature(
|
||||
uint8_t *sig, size_t *siglen,
|
||||
const uint8_t *m, size_t mlen, const uint8_t *sk) {
|
||||
const unsigned char *sk_seed = sk;
|
||||
const unsigned char *sk_prf = sk + SPX_N;
|
||||
const unsigned char *pk = sk + 2 * SPX_N;
|
||||
const unsigned char *pub_seed = pk;
|
||||
|
||||
unsigned char optrand[SPX_N];
|
||||
unsigned char mhash[SPX_FORS_MSG_BYTES];
|
||||
unsigned char root[SPX_N];
|
||||
uint32_t i;
|
||||
uint64_t tree;
|
||||
uint32_t idx_leaf;
|
||||
uint32_t wots_addr[8] = {0};
|
||||
uint32_t tree_addr[8] = {0};
|
||||
|
||||
hash_state hash_state_seeded;
|
||||
|
||||
/* This hook allows the hash function instantiation to do whatever
|
||||
preparation or computation it needs, based on the public seed. */
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_initialize_hash_function(
|
||||
&hash_state_seeded,
|
||||
pub_seed, sk_seed);
|
||||
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_type(
|
||||
wots_addr, SPX_ADDR_TYPE_WOTS);
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_type(
|
||||
tree_addr, SPX_ADDR_TYPE_HASHTREE);
|
||||
|
||||
/* Optionally, signing can be made non-deterministic using optrand.
|
||||
This can help counter side-channel attacks that would benefit from
|
||||
getting a large number of traces when the signer uses the same nodes. */
|
||||
randombytes(optrand, SPX_N);
|
||||
/* Compute the digest randomization value. */
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_gen_message_random(
|
||||
sig, sk_prf, optrand, m, mlen, &hash_state_seeded);
|
||||
|
||||
/* Derive the message digest and leaf index from R, PK and M. */
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_hash_message(
|
||||
mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded);
|
||||
sig += SPX_N;
|
||||
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_tree_addr(wots_addr, tree);
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_keypair_addr(
|
||||
wots_addr, idx_leaf);
|
||||
|
||||
/* Sign the message hash using FORS. */
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_fors_sign(
|
||||
sig, root, mhash, sk_seed, pub_seed, wots_addr, &hash_state_seeded);
|
||||
sig += SPX_FORS_BYTES;
|
||||
|
||||
for (i = 0; i < SPX_D; i++) {
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_layer_addr(tree_addr, i);
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_tree_addr(tree_addr, tree);
|
||||
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_copy_subtree_addr(
|
||||
wots_addr, tree_addr);
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_keypair_addr(
|
||||
wots_addr, idx_leaf);
|
||||
|
||||
/* Compute a WOTS signature. */
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_wots_sign(
|
||||
sig, root, sk_seed, pub_seed, wots_addr, &hash_state_seeded);
|
||||
sig += SPX_WOTS_BYTES;
|
||||
|
||||
/* Compute the authentication path for the used WOTS leaf. */
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_treehash_TREE_HEIGHT(
|
||||
root, sig, sk_seed, pub_seed, idx_leaf, 0,
|
||||
wots_gen_leaf, tree_addr, &hash_state_seeded);
|
||||
sig += SPX_TREE_HEIGHT * SPX_N;
|
||||
|
||||
/* Update the indices for the next layer. */
|
||||
idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1));
|
||||
tree = tree >> SPX_TREE_HEIGHT;
|
||||
}
|
||||
|
||||
*siglen = SPX_BYTES;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies a detached signature and message under a given public key.
|
||||
*/
|
||||
int PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_crypto_sign_verify(
|
||||
const uint8_t *sig, size_t siglen,
|
||||
const uint8_t *m, size_t mlen, const uint8_t *pk) {
|
||||
const unsigned char *pub_seed = pk;
|
||||
const unsigned char *pub_root = pk + SPX_N;
|
||||
unsigned char mhash[SPX_FORS_MSG_BYTES];
|
||||
unsigned char wots_pk[SPX_WOTS_BYTES];
|
||||
unsigned char root[SPX_N];
|
||||
unsigned char leaf[SPX_N];
|
||||
unsigned int i;
|
||||
uint64_t tree;
|
||||
uint32_t idx_leaf;
|
||||
uint32_t wots_addr[8] = {0};
|
||||
uint32_t tree_addr[8] = {0};
|
||||
uint32_t wots_pk_addr[8] = {0};
|
||||
|
||||
hash_state hash_state_seeded;
|
||||
|
||||
if (siglen != SPX_BYTES) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* This hook allows the hash function instantiation to do whatever
|
||||
preparation or computation it needs, based on the public seed. */
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_initialize_hash_function(
|
||||
&hash_state_seeded,
|
||||
pub_seed, NULL);
|
||||
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_type(
|
||||
wots_addr, SPX_ADDR_TYPE_WOTS);
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_type(
|
||||
tree_addr, SPX_ADDR_TYPE_HASHTREE);
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_type(
|
||||
wots_pk_addr, SPX_ADDR_TYPE_WOTSPK);
|
||||
|
||||
/* Derive the message digest and leaf index from R || PK || M. */
|
||||
/* The additional SPX_N is a result of the hash domain separator. */
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_hash_message(
|
||||
mhash, &tree, &idx_leaf, sig, pk, m, mlen, &hash_state_seeded);
|
||||
sig += SPX_N;
|
||||
|
||||
/* Layer correctly defaults to 0, so no need to set_layer_addr */
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_tree_addr(wots_addr, tree);
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_keypair_addr(
|
||||
wots_addr, idx_leaf);
|
||||
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_fors_pk_from_sig(
|
||||
root, sig, mhash, pub_seed, wots_addr, &hash_state_seeded);
|
||||
sig += SPX_FORS_BYTES;
|
||||
|
||||
/* For each subtree.. */
|
||||
for (i = 0; i < SPX_D; i++) {
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_layer_addr(tree_addr, i);
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_tree_addr(tree_addr, tree);
|
||||
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_copy_subtree_addr(
|
||||
wots_addr, tree_addr);
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_set_keypair_addr(
|
||||
wots_addr, idx_leaf);
|
||||
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_copy_keypair_addr(
|
||||
wots_pk_addr, wots_addr);
|
||||
|
||||
/* The WOTS public key is only correct if the signature was correct. */
|
||||
/* Initially, root is the FORS pk, but on subsequent iterations it is
|
||||
the root of the subtree below the currently processed subtree. */
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_wots_pk_from_sig(
|
||||
wots_pk, sig, root, pub_seed, wots_addr, &hash_state_seeded);
|
||||
sig += SPX_WOTS_BYTES;
|
||||
|
||||
/* Compute the leaf node using the WOTS public key. */
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_thash_WOTS_LEN(
|
||||
leaf, wots_pk, pub_seed, wots_pk_addr, &hash_state_seeded);
|
||||
|
||||
/* Compute the root node of this subtree. */
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_compute_root(
|
||||
root, leaf, idx_leaf, 0, sig, SPX_TREE_HEIGHT,
|
||||
pub_seed, tree_addr, &hash_state_seeded);
|
||||
sig += SPX_TREE_HEIGHT * SPX_N;
|
||||
|
||||
/* Update the indices for the next layer. */
|
||||
idx_leaf = (tree & ((1 << SPX_TREE_HEIGHT) - 1));
|
||||
tree = tree >> SPX_TREE_HEIGHT;
|
||||
}
|
||||
|
||||
/* Check if the root node equals the root node in the public key. */
|
||||
if (memcmp(root, pub_root, SPX_N) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns an array containing the signature followed by the message.
|
||||
*/
|
||||
int PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_crypto_sign(
|
||||
uint8_t *sm, size_t *smlen,
|
||||
const uint8_t *m, size_t mlen, const uint8_t *sk) {
|
||||
size_t siglen;
|
||||
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_crypto_sign_signature(
|
||||
sm, &siglen, m, mlen, sk);
|
||||
|
||||
memmove(sm + SPX_BYTES, m, mlen);
|
||||
*smlen = siglen + mlen;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies a given signature-message pair under a given public key.
|
||||
*/
|
||||
int PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_crypto_sign_open(
|
||||
uint8_t *m, size_t *mlen,
|
||||
const uint8_t *sm, size_t smlen, const uint8_t *pk) {
|
||||
/* The API caller does not necessarily know what size a signature should be
|
||||
but SPHINCS+ signatures are always exactly SPX_BYTES. */
|
||||
if (smlen < SPX_BYTES) {
|
||||
memset(m, 0, smlen);
|
||||
*mlen = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
*mlen = smlen - SPX_BYTES;
|
||||
|
||||
if (PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_crypto_sign_verify(
|
||||
sm, SPX_BYTES, sm + SPX_BYTES, *mlen, pk)) {
|
||||
memset(m, 0, smlen);
|
||||
*mlen = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* If verification was successful, move the message to the right place. */
|
||||
memmove(m, sm + SPX_BYTES, *mlen);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
#ifndef SPX_THASH_H
|
||||
#define SPX_THASH_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "hash_state.h"
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_thash_1(
|
||||
unsigned char *out, const unsigned char *in,
|
||||
const unsigned char *pub_seed, uint32_t addr[8],
|
||||
const hash_state *hash_state_seeded);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_thash_2(
|
||||
unsigned char *out, const unsigned char *in,
|
||||
const unsigned char *pub_seed, uint32_t addr[8],
|
||||
const hash_state *hash_state_seeded);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_thash_WOTS_LEN(
|
||||
unsigned char *out, const unsigned char *in,
|
||||
const unsigned char *pub_seed, uint32_t addr[8],
|
||||
const hash_state *hash_state_seeded);
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_thash_FORS_TREES(
|
||||
unsigned char *out, const unsigned char *in,
|
||||
const unsigned char *pub_seed, uint32_t addr[8],
|
||||
const hash_state *hash_state_seeded);
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,82 @@
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "address.h"
|
||||
#include "params.h"
|
||||
#include "thash.h"
|
||||
|
||||
#include "sha2.h"
|
||||
#include "sha256.h"
|
||||
|
||||
/**
|
||||
* Takes an array of inblocks concatenated arrays of SPX_N bytes.
|
||||
*/
|
||||
static void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_thash(
|
||||
unsigned char *out, unsigned char *buf,
|
||||
const unsigned char *in, unsigned int inblocks,
|
||||
const unsigned char *pub_seed, uint32_t addr[8],
|
||||
const sha256ctx *hash_state_seeded) {
|
||||
|
||||
unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES];
|
||||
unsigned char *bitmask = buf + SPX_N + SPX_SHA256_ADDR_BYTES + 4;
|
||||
sha256ctx sha2_state;
|
||||
unsigned int i;
|
||||
|
||||
memcpy(buf, pub_seed, SPX_N);
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_compress_address(buf + SPX_N, addr);
|
||||
/* MGF1 requires us to have 4 extra bytes in 'buf' */
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_mgf1(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_SHA256_ADDR_BYTES);
|
||||
|
||||
/* Retrieve precomputed state containing pub_seed */
|
||||
sha256_inc_dupe_state(&sha2_state, hash_state_seeded);
|
||||
|
||||
for (i = 0; i < inblocks * SPX_N; i++) {
|
||||
buf[SPX_N + SPX_SHA256_ADDR_BYTES + i] = in[i] ^ bitmask[i];
|
||||
}
|
||||
|
||||
sha256_inc_finalize(outbuf, &sha2_state, buf + SPX_N,
|
||||
SPX_SHA256_ADDR_BYTES + inblocks * SPX_N);
|
||||
memcpy(out, outbuf, SPX_N);
|
||||
}
|
||||
|
||||
/* The wrappers below ensure that we use fixed-size buffers on the stack */
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_thash_1(
|
||||
unsigned char *out, const unsigned char *in,
|
||||
const unsigned char *pub_seed, uint32_t addr[8],
|
||||
const sha256ctx *hash_state_seeded) {
|
||||
|
||||
unsigned char buf[SPX_N + SPX_SHA256_ADDR_BYTES + 4 + 1 * SPX_N];
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_thash(
|
||||
out, buf, in, 1, pub_seed, addr, hash_state_seeded);
|
||||
}
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_thash_2(
|
||||
unsigned char *out, const unsigned char *in,
|
||||
const unsigned char *pub_seed, uint32_t addr[8],
|
||||
const sha256ctx *hash_state_seeded) {
|
||||
|
||||
unsigned char buf[SPX_N + SPX_SHA256_ADDR_BYTES + 4 + 2 * SPX_N];
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_thash(
|
||||
out, buf, in, 2, pub_seed, addr, hash_state_seeded);
|
||||
}
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_thash_WOTS_LEN(
|
||||
unsigned char *out, const unsigned char *in,
|
||||
const unsigned char *pub_seed, uint32_t addr[8],
|
||||
const sha256ctx *hash_state_seeded) {
|
||||
|
||||
unsigned char buf[SPX_N + SPX_SHA256_ADDR_BYTES + 4 + SPX_WOTS_LEN * SPX_N];
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_thash(
|
||||
out, buf, in, SPX_WOTS_LEN, pub_seed, addr, hash_state_seeded);
|
||||
}
|
||||
|
||||
void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_thash_FORS_TREES(
|
||||
unsigned char *out, const unsigned char *in,
|
||||
const unsigned char *pub_seed, uint32_t addr[8],
|
||||
const sha256ctx *hash_state_seeded) {
|
||||
|
||||
unsigned char buf[SPX_N + SPX_SHA256_ADDR_BYTES + 4 + SPX_FORS_TREES * SPX_N];
|
||||
PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_thash(
|
||||
out, buf, in, SPX_FORS_TREES, pub_seed, addr, hash_state_seeded);
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user