pq_crypto 0.3.2 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +56 -0
- data/CHANGELOG.md +62 -0
- data/GET_STARTED.md +366 -40
- data/README.md +76 -233
- data/SECURITY.md +107 -82
- data/ext/pqcrypto/extconf.rb +169 -87
- data/ext/pqcrypto/mldsa_api.h +1 -48
- data/ext/pqcrypto/mlkem_api.h +1 -18
- data/ext/pqcrypto/pq_externalmu.c +89 -204
- data/ext/pqcrypto/pqcrypto_native_api.h +129 -0
- data/ext/pqcrypto/pqcrypto_ruby_secure.c +484 -84
- data/ext/pqcrypto/pqcrypto_secure.c +203 -78
- data/ext/pqcrypto/pqcrypto_secure.h +53 -14
- data/ext/pqcrypto/pqcrypto_version.h +7 -0
- data/ext/pqcrypto/randombytes.h +9 -0
- data/ext/pqcrypto/vendor/.vendored +10 -5
- data/ext/pqcrypto/vendor/mldsa-native/BUILDING.md +105 -0
- data/ext/pqcrypto/vendor/mldsa-native/LICENSE +286 -0
- data/ext/pqcrypto/vendor/mldsa-native/META.yml +24 -0
- data/ext/pqcrypto/vendor/mldsa-native/README.md +221 -0
- data/ext/pqcrypto/vendor/mldsa-native/SECURITY.md +8 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/mldsa_native.c +721 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/mldsa_native.h +975 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/mldsa_native_asm.S +724 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/mldsa_native_config.h +723 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/cbmc.h +166 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/common.h +321 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/ct.c +21 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/ct.h +385 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/debug.c +73 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/debug.h +130 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/fips202.c +277 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/fips202.h +244 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/fips202x4.c +182 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/fips202x4.h +117 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/keccakf1600.c +438 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/keccakf1600.h +105 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/auto.h +71 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/fips202_native_aarch64.h +62 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/keccak_f1600_x1_scalar_asm.S +376 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/keccak_f1600_x1_v84a_asm.S +204 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/keccak_f1600_x2_v84a_asm.S +259 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/keccak_f1600_x4_v8a_scalar_hybrid_asm.S +1077 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/keccak_f1600_x4_v8a_v84a_scalar_hybrid_asm.S +987 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/src/keccakf1600_round_constants.c +41 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/x1_scalar.h +26 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/x1_v84a.h +35 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/x2_v84a.h +37 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/x4_v8a_scalar.h +27 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/aarch64/x4_v8a_v84a_scalar.h +36 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/api.h +69 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/armv81m/README.md +10 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/armv81m/mve.h +32 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/armv81m/src/fips202_native_armv81m.h +20 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/armv81m/src/keccak_f1600_x4_mve.S +638 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/armv81m/src/keccak_f1600_x4_mve.c +136 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/armv81m/src/keccakf1600_round_constants.c +52 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/auto.h +29 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/x86_64/src/KeccakP_1600_times4_SIMD256.c +488 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/x86_64/src/KeccakP_1600_times4_SIMD256.h +16 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/fips202/native/x86_64/xkcp.h +31 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/meta.h +247 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/aarch64_zetas.c +231 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/arith_native_aarch64.h +150 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/intt.S +753 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/mld_polyvecl_pointwise_acc_montgomery_l4.S +129 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/mld_polyvecl_pointwise_acc_montgomery_l5.S +145 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/mld_polyvecl_pointwise_acc_montgomery_l7.S +177 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/ntt.S +653 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/pointwise_montgomery.S +79 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/poly_caddq_asm.S +53 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/poly_chknorm_asm.S +55 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/poly_decompose_32_asm.S +85 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/poly_decompose_88_asm.S +85 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/poly_use_hint_32_asm.S +102 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/poly_use_hint_88_asm.S +110 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/polyz_unpack_17_asm.S +72 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/polyz_unpack_19_asm.S +69 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/polyz_unpack_table.c +40 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/rej_uniform_asm.S +189 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/rej_uniform_eta2_asm.S +135 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/rej_uniform_eta4_asm.S +128 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/rej_uniform_eta_table.c +543 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/aarch64/src/rej_uniform_table.c +62 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/api.h +649 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/meta.h +23 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/meta.h +315 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/arith_native_x86_64.h +124 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/consts.c +157 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/consts.h +27 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/intt.S +2311 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/ntt.S +2383 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/nttunpack.S +239 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/pointwise.S +131 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/pointwise_acc_l4.S +139 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/pointwise_acc_l5.S +155 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/pointwise_acc_l7.S +187 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/poly_caddq_avx2.c +61 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/poly_chknorm_avx2.c +52 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/poly_decompose_32_avx2.c +155 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/poly_decompose_88_avx2.c +155 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/poly_use_hint_32_avx2.c +102 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/poly_use_hint_88_avx2.c +104 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/polyz_unpack_17_avx2.c +91 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/polyz_unpack_19_avx2.c +93 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/rej_uniform_avx2.c +126 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/rej_uniform_eta2_avx2.c +155 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/rej_uniform_eta4_avx2.c +139 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/native/x86_64/src/rej_uniform_table.c +160 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/packing.c +293 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/packing.h +224 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/params.h +77 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/poly.c +991 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/poly.h +393 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/poly_kl.c +946 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/poly_kl.h +360 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/polyvec.c +877 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/polyvec.h +725 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/randombytes.h +26 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/reduce.h +139 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/rounding.h +249 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/sign.c +1511 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/sign.h +806 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/symmetric.h +68 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/sys.h +268 -0
- data/ext/pqcrypto/vendor/mldsa-native/mldsa/src/zetas.inc +55 -0
- data/ext/pqcrypto/vendor/mlkem-native/BUILDING.md +104 -0
- data/ext/pqcrypto/vendor/mlkem-native/LICENSE +294 -0
- data/ext/pqcrypto/vendor/mlkem-native/META.yml +30 -0
- data/ext/pqcrypto/vendor/mlkem-native/README.md +223 -0
- data/ext/pqcrypto/vendor/mlkem-native/RELEASE.md +86 -0
- data/ext/pqcrypto/vendor/mlkem-native/SECURITY.md +8 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/README.md +23 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/mlkem_native.c +660 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/mlkem_native.h +538 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/mlkem_native_asm.S +681 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/mlkem_native_config.h +709 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/cbmc.h +174 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/common.h +274 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/compress.c +717 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/compress.h +688 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/debug.c +64 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/debug.h +128 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/fips202.c +251 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/fips202.h +158 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/fips202x4.c +208 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/fips202x4.h +80 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/keccakf1600.c +463 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/keccakf1600.h +98 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/aarch64/auto.h +70 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/aarch64/src/fips202_native_aarch64.h +69 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/aarch64/src/keccak_f1600_x1_scalar_asm.S +375 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/aarch64/src/keccak_f1600_x1_v84a_asm.S +203 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/aarch64/src/keccak_f1600_x2_v84a_asm.S +258 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/aarch64/src/keccak_f1600_x4_v8a_scalar_hybrid_asm.S +1076 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/aarch64/src/keccak_f1600_x4_v8a_v84a_scalar_hybrid_asm.S +986 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/aarch64/src/keccakf1600_round_constants.c +46 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/aarch64/x1_scalar.h +25 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/aarch64/x1_v84a.h +34 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/aarch64/x2_v84a.h +35 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/aarch64/x4_v8a_scalar.h +26 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/aarch64/x4_v8a_v84a_scalar.h +35 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/api.h +117 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/armv81m/README.md +10 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/armv81m/mve.h +79 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/armv81m/src/fips202_native_armv81m.h +35 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/armv81m/src/keccak_f1600_x4_mve.S +667 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/armv81m/src/keccak_f1600_x4_mve.c +40 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/armv81m/src/keccakf1600_round_constants.c +51 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/armv81m/src/state_extract_bytes_x4_mve.S +290 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/armv81m/src/state_xor_bytes_x4_mve.S +314 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/auto.h +28 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/x86_64/keccak_f1600_x4_avx2.h +33 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/x86_64/src/fips202_native_x86_64.h +41 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/x86_64/src/keccak_f1600_x4_avx2.S +451 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/fips202/native/x86_64/src/keccakf1600_constants.c +51 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/indcpa.c +622 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/indcpa.h +156 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/kem.c +446 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/kem.h +326 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/aarch64/README.md +16 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/aarch64/meta.h +122 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/aarch64/src/aarch64_zetas.c +174 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/aarch64/src/arith_native_aarch64.h +177 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/aarch64/src/intt.S +628 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/aarch64/src/ntt.S +562 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/aarch64/src/poly_mulcache_compute_asm.S +127 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/aarch64/src/poly_reduce_asm.S +150 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/aarch64/src/poly_tobytes_asm.S +117 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/aarch64/src/poly_tomont_asm.S +98 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/aarch64/src/polyvec_basemul_acc_montgomery_cached_asm_k2.S +261 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/aarch64/src/polyvec_basemul_acc_montgomery_cached_asm_k3.S +314 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/aarch64/src/polyvec_basemul_acc_montgomery_cached_asm_k4.S +368 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/aarch64/src/rej_uniform_asm.S +226 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/aarch64/src/rej_uniform_table.c +542 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/api.h +637 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/meta.h +25 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/riscv64/README.md +11 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/riscv64/meta.h +128 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/riscv64/src/arith_native_riscv64.h +45 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/riscv64/src/rv64v_debug.c +81 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/riscv64/src/rv64v_debug.h +145 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/riscv64/src/rv64v_izetas.inc +27 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/riscv64/src/rv64v_poly.c +805 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/riscv64/src/rv64v_zetas.inc +27 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/riscv64/src/rv64v_zetas_basemul.inc +39 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/README.md +4 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/meta.h +304 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/arith_native_x86_64.h +309 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/compress_consts.c +94 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/compress_consts.h +45 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/consts.c +102 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/consts.h +25 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/intt.S +719 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/mulcache_compute.S +90 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/ntt.S +639 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/nttfrombytes.S +193 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/ntttobytes.S +181 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/nttunpack.S +174 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/poly_compress_d10.S +382 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/poly_compress_d11.S +448 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/poly_compress_d4.S +163 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/poly_compress_d5.S +220 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/poly_decompress_d10.S +228 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/poly_decompress_d11.S +277 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/poly_decompress_d4.S +180 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/poly_decompress_d5.S +192 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/polyvec_basemul_acc_montgomery_cached_asm_k2.S +502 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/polyvec_basemul_acc_montgomery_cached_asm_k3.S +750 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/polyvec_basemul_acc_montgomery_cached_asm_k4.S +998 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/reduce.S +218 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/rej_uniform_asm.S +103 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/rej_uniform_table.c +544 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/native/x86_64/src/tomont.S +155 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/params.h +76 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/poly.c +572 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/poly.h +317 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/poly_k.c +502 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/poly_k.h +668 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/randombytes.h +60 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/sampling.c +362 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/sampling.h +118 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/symmetric.h +70 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/sys.h +260 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/verify.c +20 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/verify.h +464 -0
- data/ext/pqcrypto/vendor/mlkem-native/mlkem/src/zetas.inc +30 -0
- data/lib/pq_crypto/algorithm_registry.rb +200 -0
- data/lib/pq_crypto/hybrid_kem.rb +1 -12
- data/lib/pq_crypto/kem.rb +104 -13
- data/lib/pq_crypto/pkcs8.rb +387 -0
- data/lib/pq_crypto/serialization.rb +1 -14
- data/lib/pq_crypto/signature.rb +123 -17
- data/lib/pq_crypto/spki.rb +131 -0
- data/lib/pq_crypto/version.rb +1 -1
- data/lib/pq_crypto.rb +79 -20
- data/script/vendor_libs.rb +88 -155
- metadata +241 -73
- data/ext/pqcrypto/vendor/pqclean/common/aes.c +0 -639
- data/ext/pqcrypto/vendor/pqclean/common/aes.h +0 -64
- data/ext/pqcrypto/vendor/pqclean/common/compat.h +0 -73
- data/ext/pqcrypto/vendor/pqclean/common/crypto_declassify.h +0 -7
- data/ext/pqcrypto/vendor/pqclean/common/fips202.c +0 -928
- data/ext/pqcrypto/vendor/pqclean/common/fips202.h +0 -166
- data/ext/pqcrypto/vendor/pqclean/common/keccak2x/feat.S +0 -168
- data/ext/pqcrypto/vendor/pqclean/common/keccak2x/fips202x2.c +0 -684
- data/ext/pqcrypto/vendor/pqclean/common/keccak2x/fips202x2.h +0 -60
- data/ext/pqcrypto/vendor/pqclean/common/keccak4x/KeccakP-1600-times4-SIMD256.c +0 -1028
- data/ext/pqcrypto/vendor/pqclean/common/keccak4x/KeccakP-1600-times4-SnP.h +0 -50
- data/ext/pqcrypto/vendor/pqclean/common/keccak4x/KeccakP-1600-unrolling.macros +0 -198
- data/ext/pqcrypto/vendor/pqclean/common/keccak4x/Makefile +0 -8
- data/ext/pqcrypto/vendor/pqclean/common/keccak4x/Makefile.Microsoft_nmake +0 -8
- data/ext/pqcrypto/vendor/pqclean/common/keccak4x/SIMD256-config.h +0 -3
- data/ext/pqcrypto/vendor/pqclean/common/keccak4x/align.h +0 -34
- data/ext/pqcrypto/vendor/pqclean/common/keccak4x/brg_endian.h +0 -142
- data/ext/pqcrypto/vendor/pqclean/common/nistseedexpander.c +0 -101
- data/ext/pqcrypto/vendor/pqclean/common/nistseedexpander.h +0 -39
- data/ext/pqcrypto/vendor/pqclean/common/randombytes.c +0 -355
- data/ext/pqcrypto/vendor/pqclean/common/randombytes.h +0 -27
- data/ext/pqcrypto/vendor/pqclean/common/sha2.c +0 -769
- data/ext/pqcrypto/vendor/pqclean/common/sha2.h +0 -173
- data/ext/pqcrypto/vendor/pqclean/common/sp800-185.c +0 -156
- data/ext/pqcrypto/vendor/pqclean/common/sp800-185.h +0 -27
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/LICENSE +0 -5
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/Makefile +0 -19
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/Makefile.Microsoft_nmake +0 -23
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/api.h +0 -18
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/cbd.c +0 -83
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/cbd.h +0 -11
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/indcpa.c +0 -327
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/indcpa.h +0 -22
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/kem.c +0 -164
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/kem.h +0 -23
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/ntt.c +0 -146
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/ntt.h +0 -14
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/params.h +0 -36
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/poly.c +0 -299
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/poly.h +0 -37
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/polyvec.c +0 -188
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/polyvec.h +0 -26
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/reduce.c +0 -41
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/reduce.h +0 -13
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/symmetric-shake.c +0 -71
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/symmetric.h +0 -30
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/verify.c +0 -67
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/verify.h +0 -13
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/LICENSE +0 -5
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/Makefile +0 -19
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/Makefile.Microsoft_nmake +0 -23
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/api.h +0 -50
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/ntt.c +0 -98
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/ntt.h +0 -10
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/packing.c +0 -261
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/packing.h +0 -31
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/params.h +0 -44
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/poly.c +0 -799
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/poly.h +0 -52
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/polyvec.c +0 -415
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/polyvec.h +0 -65
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/reduce.c +0 -69
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/reduce.h +0 -17
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/rounding.c +0 -92
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/rounding.h +0 -14
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/sign.c +0 -407
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/sign.h +0 -47
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/symmetric-shake.c +0 -26
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/symmetric.h +0 -34
|
@@ -0,0 +1,1511 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) The mldsa-native project authors
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0 OR ISC OR MIT
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/* References
|
|
7
|
+
* ==========
|
|
8
|
+
*
|
|
9
|
+
* - [FIPS140_3_IG]
|
|
10
|
+
* Implementation Guidance for FIPS 140-3 and the Cryptographic Module
|
|
11
|
+
* Validation Program
|
|
12
|
+
* National Institute of Standards and Technology
|
|
13
|
+
* https://csrc.nist.gov/projects/cryptographic-module-validation-program/fips-140-3-ig-announcements
|
|
14
|
+
*
|
|
15
|
+
* - [FIPS204]
|
|
16
|
+
* FIPS 204 Module-Lattice-Based Digital Signature Standard
|
|
17
|
+
* National Institute of Standards and Technology
|
|
18
|
+
* https://csrc.nist.gov/pubs/fips/204/final
|
|
19
|
+
*
|
|
20
|
+
* - [Round3_Spec]
|
|
21
|
+
* CRYSTALS-Dilithium Algorithm Specifications and Supporting Documentation
|
|
22
|
+
* (Version 3.1)
|
|
23
|
+
* Bai, Ducas, Kiltz, Lepoint, Lyubashevsky, Schwabe, Seiler, Stehlé
|
|
24
|
+
* https://pq-crystals.org/dilithium/data/dilithium-specification-round3-20210208.pdf
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
#include "sign.h"
|
|
28
|
+
|
|
29
|
+
#include "cbmc.h"
|
|
30
|
+
#include "ct.h"
|
|
31
|
+
#include "debug.h"
|
|
32
|
+
#include "packing.h"
|
|
33
|
+
#include "poly.h"
|
|
34
|
+
#include "poly_kl.h"
|
|
35
|
+
#include "polyvec.h"
|
|
36
|
+
#include "randombytes.h"
|
|
37
|
+
#include "symmetric.h"
|
|
38
|
+
|
|
39
|
+
/* Parameter set namespacing
|
|
40
|
+
* This is to facilitate building multiple instances
|
|
41
|
+
* of mldsa-native (e.g. with varying parameter sets)
|
|
42
|
+
* within a single compilation unit. */
|
|
43
|
+
#define mld_check_pct MLD_ADD_PARAM_SET(mld_check_pct) MLD_CONTEXT_PARAMETERS_2
|
|
44
|
+
#define mld_sample_s1_s2 MLD_ADD_PARAM_SET(mld_sample_s1_s2)
|
|
45
|
+
#define mld_validate_hash_length MLD_ADD_PARAM_SET(mld_validate_hash_length)
|
|
46
|
+
#define mld_get_hash_oid MLD_ADD_PARAM_SET(mld_get_hash_oid)
|
|
47
|
+
#define mld_H MLD_ADD_PARAM_SET(mld_H)
|
|
48
|
+
#define mld_compute_pack_z MLD_ADD_PARAM_SET(mld_compute_pack_z)
|
|
49
|
+
#define mld_attempt_signature_generation \
|
|
50
|
+
MLD_ADD_PARAM_SET(mld_attempt_signature_generation) MLD_CONTEXT_PARAMETERS_8
|
|
51
|
+
#define mld_compute_t0_t1_tr_from_sk_components \
|
|
52
|
+
MLD_ADD_PARAM_SET(mld_compute_t0_t1_tr_from_sk_components) \
|
|
53
|
+
MLD_CONTEXT_PARAMETERS_7
|
|
54
|
+
/* End of parameter set namespacing */
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
static int mld_check_pct(uint8_t const pk[MLDSA_CRYPTO_PUBLICKEYBYTES],
|
|
58
|
+
uint8_t const sk[MLDSA_CRYPTO_SECRETKEYBYTES],
|
|
59
|
+
MLD_CONFIG_CONTEXT_PARAMETER_TYPE context)
|
|
60
|
+
__contract__(
|
|
61
|
+
requires(memory_no_alias(pk, MLDSA_CRYPTO_PUBLICKEYBYTES))
|
|
62
|
+
requires(memory_no_alias(sk, MLDSA_CRYPTO_SECRETKEYBYTES))
|
|
63
|
+
ensures(return_value == 0
|
|
64
|
+
|| return_value == MLD_ERR_FAIL
|
|
65
|
+
|| return_value == MLD_ERR_OUT_OF_MEMORY
|
|
66
|
+
|| return_value == MLD_ERR_RNG_FAIL)
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
#if defined(MLD_CONFIG_KEYGEN_PCT)
|
|
70
|
+
/*************************************************
|
|
71
|
+
* @[FIPS140_3_IG]
|
|
72
|
+
* (https://csrc.nist.gov/csrc/media/Projects/cryptographic-module-validation-program/documents/fips%20140-3/FIPS%20140-3%20IG.pdf)
|
|
73
|
+
*
|
|
74
|
+
* TE10.35.02: Pair-wise Consistency Test (PCT) for DSA keypairs
|
|
75
|
+
*
|
|
76
|
+
* Purpose: Validates that a generated public/private key pair can correctly
|
|
77
|
+
* sign and verify data. Test performs signature generation using the private
|
|
78
|
+
* key (sk), followed by signature verification using the public key (pk).
|
|
79
|
+
* Returns 0 if the signature was successfully verified, non-zero if it cannot.
|
|
80
|
+
*
|
|
81
|
+
* Note: @[FIPS204] requires that public/private key pairs are to be used only
|
|
82
|
+
* for the calculation and/of verification of digital signatures.
|
|
83
|
+
**************************************************/
|
|
84
|
+
static int mld_check_pct(uint8_t const pk[MLDSA_CRYPTO_PUBLICKEYBYTES],
|
|
85
|
+
uint8_t const sk[MLDSA_CRYPTO_SECRETKEYBYTES],
|
|
86
|
+
MLD_CONFIG_CONTEXT_PARAMETER_TYPE context)
|
|
87
|
+
{
|
|
88
|
+
MLD_ALIGN uint8_t message[1] = {0};
|
|
89
|
+
size_t siglen;
|
|
90
|
+
int ret;
|
|
91
|
+
MLD_ALLOC(signature, uint8_t, MLDSA_CRYPTO_BYTES, context);
|
|
92
|
+
MLD_ALLOC(pk_test, uint8_t, MLDSA_CRYPTO_PUBLICKEYBYTES, context);
|
|
93
|
+
|
|
94
|
+
if (signature == NULL || pk_test == NULL)
|
|
95
|
+
{
|
|
96
|
+
ret = MLD_ERR_OUT_OF_MEMORY;
|
|
97
|
+
goto cleanup;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/* Copy public key for testing */
|
|
101
|
+
mld_memcpy(pk_test, pk, MLDSA_CRYPTO_PUBLICKEYBYTES);
|
|
102
|
+
|
|
103
|
+
/* Sign a test message using the original secret key */
|
|
104
|
+
ret = mld_sign_signature(signature, &siglen, message, sizeof(message), NULL,
|
|
105
|
+
0, sk, context);
|
|
106
|
+
if (ret != 0)
|
|
107
|
+
{
|
|
108
|
+
goto cleanup;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
#if defined(MLD_CONFIG_KEYGEN_PCT_BREAKAGE_TEST)
|
|
112
|
+
/* Deliberately break public key for testing purposes */
|
|
113
|
+
if (mld_break_pct())
|
|
114
|
+
{
|
|
115
|
+
pk_test[0] = ~pk_test[0];
|
|
116
|
+
}
|
|
117
|
+
#endif /* MLD_CONFIG_KEYGEN_PCT_BREAKAGE_TEST */
|
|
118
|
+
|
|
119
|
+
/* Verify the signature using the (potentially corrupted) public key */
|
|
120
|
+
ret = mld_sign_verify(signature, siglen, message, sizeof(message), NULL, 0,
|
|
121
|
+
pk_test, context);
|
|
122
|
+
|
|
123
|
+
cleanup:
|
|
124
|
+
/* @[FIPS204, Section 3.6.3] Destruction of intermediate values. */
|
|
125
|
+
MLD_FREE(pk_test, uint8_t, MLDSA_CRYPTO_PUBLICKEYBYTES, context);
|
|
126
|
+
MLD_FREE(signature, uint8_t, MLDSA_CRYPTO_BYTES, context);
|
|
127
|
+
|
|
128
|
+
return ret;
|
|
129
|
+
}
|
|
130
|
+
#else /* MLD_CONFIG_KEYGEN_PCT */
|
|
131
|
+
static int mld_check_pct(uint8_t const pk[MLDSA_CRYPTO_PUBLICKEYBYTES],
|
|
132
|
+
uint8_t const sk[MLDSA_CRYPTO_SECRETKEYBYTES],
|
|
133
|
+
MLD_CONFIG_CONTEXT_PARAMETER_TYPE context)
|
|
134
|
+
{
|
|
135
|
+
/* Skip PCT */
|
|
136
|
+
((void)pk);
|
|
137
|
+
((void)sk);
|
|
138
|
+
#if defined(MLD_CONFIG_CONTEXT_PARAMETER)
|
|
139
|
+
((void)context);
|
|
140
|
+
#endif
|
|
141
|
+
return 0;
|
|
142
|
+
}
|
|
143
|
+
#endif /* !MLD_CONFIG_KEYGEN_PCT */
|
|
144
|
+
|
|
145
|
+
static void mld_sample_s1_s2(mld_polyvecl *s1, mld_polyveck *s2,
|
|
146
|
+
const uint8_t seed[MLDSA_CRHBYTES])
|
|
147
|
+
__contract__(
|
|
148
|
+
requires(memory_no_alias(s1, sizeof(mld_polyvecl)))
|
|
149
|
+
requires(memory_no_alias(s2, sizeof(mld_polyveck)))
|
|
150
|
+
requires(memory_no_alias(seed, MLDSA_CRHBYTES))
|
|
151
|
+
assigns(object_whole(s1), object_whole(s2))
|
|
152
|
+
ensures(forall(l0, 0, MLDSA_L, array_abs_bound(s1->vec[l0].coeffs, 0, MLDSA_N, MLDSA_ETA + 1)))
|
|
153
|
+
ensures(forall(k0, 0, MLDSA_K, array_abs_bound(s2->vec[k0].coeffs, 0, MLDSA_N, MLDSA_ETA + 1)))
|
|
154
|
+
)
|
|
155
|
+
{
|
|
156
|
+
/* Sample short vectors s1 and s2 */
|
|
157
|
+
#if defined(MLD_CONFIG_SERIAL_FIPS202_ONLY)
|
|
158
|
+
int i;
|
|
159
|
+
uint16_t nonce = 0;
|
|
160
|
+
/* Safety: The nonces are at most 14 (MLDSA_L + MLDSA_K - 1), and, hence, the
|
|
161
|
+
* casts are safe. */
|
|
162
|
+
for (i = 0; i < MLDSA_L; i++)
|
|
163
|
+
{
|
|
164
|
+
mld_poly_uniform_eta(&s1->vec[i], seed, (uint8_t)(nonce + i));
|
|
165
|
+
}
|
|
166
|
+
for (i = 0; i < MLDSA_K; i++)
|
|
167
|
+
{
|
|
168
|
+
mld_poly_uniform_eta(&s2->vec[i], seed, (uint8_t)(nonce + MLDSA_L + i));
|
|
169
|
+
}
|
|
170
|
+
#else /* MLD_CONFIG_SERIAL_FIPS202_ONLY */
|
|
171
|
+
#if MLD_CONFIG_PARAMETER_SET == 44
|
|
172
|
+
mld_poly_uniform_eta_4x(&s1->vec[0], &s1->vec[1], &s1->vec[2], &s1->vec[3],
|
|
173
|
+
seed, 0, 1, 2, 3);
|
|
174
|
+
mld_poly_uniform_eta_4x(&s2->vec[0], &s2->vec[1], &s2->vec[2], &s2->vec[3],
|
|
175
|
+
seed, 4, 5, 6, 7);
|
|
176
|
+
#elif MLD_CONFIG_PARAMETER_SET == 65
|
|
177
|
+
mld_poly_uniform_eta_4x(&s1->vec[0], &s1->vec[1], &s1->vec[2], &s1->vec[3],
|
|
178
|
+
seed, 0, 1, 2, 3);
|
|
179
|
+
mld_poly_uniform_eta_4x(&s1->vec[4], &s2->vec[0], &s2->vec[1],
|
|
180
|
+
&s2->vec[2] /* irrelevant */, seed, 4, 5, 6,
|
|
181
|
+
0xFF /* irrelevant */);
|
|
182
|
+
mld_poly_uniform_eta_4x(&s2->vec[2], &s2->vec[3], &s2->vec[4], &s2->vec[5],
|
|
183
|
+
seed, 7, 8, 9, 10);
|
|
184
|
+
#elif MLD_CONFIG_PARAMETER_SET == 87
|
|
185
|
+
mld_poly_uniform_eta_4x(&s1->vec[0], &s1->vec[1], &s1->vec[2], &s1->vec[3],
|
|
186
|
+
seed, 0, 1, 2, 3);
|
|
187
|
+
mld_poly_uniform_eta_4x(&s1->vec[4], &s1->vec[5], &s1->vec[6],
|
|
188
|
+
&s2->vec[0] /* irrelevant */, seed, 4, 5, 6,
|
|
189
|
+
0xFF /* irrelevant */);
|
|
190
|
+
mld_poly_uniform_eta_4x(&s2->vec[0], &s2->vec[1], &s2->vec[2], &s2->vec[3],
|
|
191
|
+
seed, 7, 8, 9, 10);
|
|
192
|
+
mld_poly_uniform_eta_4x(&s2->vec[4], &s2->vec[5], &s2->vec[6], &s2->vec[7],
|
|
193
|
+
seed, 11, 12, 13, 14);
|
|
194
|
+
#endif /* MLD_CONFIG_PARAMETER_SET == 87 */
|
|
195
|
+
#endif /* !MLD_CONFIG_SERIAL_FIPS202_ONLY */
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/*************************************************
|
|
199
|
+
* Name: mld_compute_t0_t1_tr_from_sk_components
|
|
200
|
+
*
|
|
201
|
+
* Description: Computes t0, t1, tr, and pk from secret key components
|
|
202
|
+
* rho, s1, s2. This is the shared computation used by
|
|
203
|
+
* both keygen and generating the public key from the
|
|
204
|
+
* secret key.
|
|
205
|
+
*
|
|
206
|
+
* Arguments: - mld_polyveck *t0: output t0
|
|
207
|
+
* - mld_polyveck *t1: output t1
|
|
208
|
+
* - uint8_t tr[MLDSA_TRBYTES]: output tr
|
|
209
|
+
* - uint8_t pk[MLDSA_CRYPTO_PUBLICKEYBYTES]: output public key
|
|
210
|
+
* - const uint8_t rho[MLDSA_SEEDBYTES]: input rho
|
|
211
|
+
* - const mld_polyvecl *s1: input s1
|
|
212
|
+
* - const mld_polyveck *s2: input s2
|
|
213
|
+
**************************************************/
|
|
214
|
+
MLD_MUST_CHECK_RETURN_VALUE
|
|
215
|
+
static int mld_compute_t0_t1_tr_from_sk_components(
|
|
216
|
+
mld_polyveck *t0, mld_polyveck *t1, uint8_t tr[MLDSA_TRBYTES],
|
|
217
|
+
uint8_t pk[MLDSA_CRYPTO_PUBLICKEYBYTES], const uint8_t rho[MLDSA_SEEDBYTES],
|
|
218
|
+
const mld_polyvecl *s1, const mld_polyveck *s2,
|
|
219
|
+
MLD_CONFIG_CONTEXT_PARAMETER_TYPE context)
|
|
220
|
+
__contract__(
|
|
221
|
+
requires(memory_no_alias(t0, sizeof(mld_polyveck)))
|
|
222
|
+
requires(memory_no_alias(t1, sizeof(mld_polyveck)))
|
|
223
|
+
requires(memory_no_alias(tr, MLDSA_TRBYTES))
|
|
224
|
+
requires(memory_no_alias(pk, MLDSA_CRYPTO_PUBLICKEYBYTES))
|
|
225
|
+
requires(memory_no_alias(rho, MLDSA_SEEDBYTES))
|
|
226
|
+
requires(memory_no_alias(s1, sizeof(mld_polyvecl)))
|
|
227
|
+
requires(memory_no_alias(s2, sizeof(mld_polyveck)))
|
|
228
|
+
requires(forall(l0, 0, MLDSA_L, array_bound(s1->vec[l0].coeffs, 0, MLDSA_N, MLD_POLYETA_UNPACK_LOWER_BOUND, MLDSA_ETA + 1)))
|
|
229
|
+
requires(forall(k0, 0, MLDSA_K, array_bound(s2->vec[k0].coeffs, 0, MLDSA_N, MLD_POLYETA_UNPACK_LOWER_BOUND, MLDSA_ETA + 1)))
|
|
230
|
+
assigns(memory_slice(t0, sizeof(mld_polyveck)))
|
|
231
|
+
assigns(memory_slice(t1, sizeof(mld_polyveck)))
|
|
232
|
+
assigns(memory_slice(tr, MLDSA_TRBYTES))
|
|
233
|
+
assigns(memory_slice(pk, MLDSA_CRYPTO_PUBLICKEYBYTES))
|
|
234
|
+
ensures(forall(k1, 0, MLDSA_K, array_bound(t0->vec[k1].coeffs, 0, MLDSA_N, -(1<<(MLDSA_D-1)) + 1, (1<<(MLDSA_D-1)) + 1)))
|
|
235
|
+
ensures(forall(k2, 0, MLDSA_K, array_bound(t1->vec[k2].coeffs, 0, MLDSA_N, 0, 1 << 10)))
|
|
236
|
+
ensures(return_value == 0 || return_value == MLD_ERR_OUT_OF_MEMORY))
|
|
237
|
+
{
|
|
238
|
+
int ret;
|
|
239
|
+
MLD_ALLOC(mat, mld_polymat, 1, context);
|
|
240
|
+
MLD_ALLOC(s1hat, mld_polyvecl, 1, context);
|
|
241
|
+
MLD_ALLOC(t, mld_polyveck, 1, context);
|
|
242
|
+
|
|
243
|
+
if (mat == NULL || s1hat == NULL || t == NULL)
|
|
244
|
+
{
|
|
245
|
+
ret = MLD_ERR_OUT_OF_MEMORY;
|
|
246
|
+
goto cleanup;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/* Expand matrix */
|
|
250
|
+
mld_polyvec_matrix_expand(mat, rho);
|
|
251
|
+
|
|
252
|
+
/* Matrix-vector multiplication */
|
|
253
|
+
*s1hat = *s1;
|
|
254
|
+
mld_polyvecl_ntt(s1hat);
|
|
255
|
+
mld_polyvec_matrix_pointwise_montgomery(t, mat, s1hat);
|
|
256
|
+
mld_polyveck_invntt_tomont(t);
|
|
257
|
+
|
|
258
|
+
/* Add error vector s2 */
|
|
259
|
+
mld_polyveck_add(t, s2);
|
|
260
|
+
|
|
261
|
+
/* Reference: The following reduction is not present in the reference
|
|
262
|
+
* implementation. Omitting this reduction requires the output of
|
|
263
|
+
* the invntt to be small enough such that the addition of s2 does
|
|
264
|
+
* not result in absolute values >= MLDSA_Q. While our C, x86_64,
|
|
265
|
+
* and AArch64 invntt implementations produce small enough
|
|
266
|
+
* values for this to work out, it complicates the bounds
|
|
267
|
+
* reasoning. We instead add an additional reduction, and can
|
|
268
|
+
* consequently, relax the bounds requirements for the invntt.
|
|
269
|
+
*/
|
|
270
|
+
mld_polyveck_reduce(t);
|
|
271
|
+
|
|
272
|
+
/* Decompose to get t1, t0 */
|
|
273
|
+
mld_polyveck_caddq(t);
|
|
274
|
+
mld_polyveck_power2round(t1, t0, t);
|
|
275
|
+
|
|
276
|
+
/* Pack public key and compute tr */
|
|
277
|
+
mld_pack_pk(pk, rho, t1);
|
|
278
|
+
mld_shake256(tr, MLDSA_TRBYTES, pk, MLDSA_CRYPTO_PUBLICKEYBYTES);
|
|
279
|
+
|
|
280
|
+
ret = 0;
|
|
281
|
+
|
|
282
|
+
cleanup:
|
|
283
|
+
/* @[FIPS204, Section 3.6.3] Destruction of intermediate values. */
|
|
284
|
+
MLD_FREE(t, mld_polyveck, 1, context);
|
|
285
|
+
MLD_FREE(s1hat, mld_polyvecl, 1, context);
|
|
286
|
+
MLD_FREE(mat, mld_polymat, 1, context);
|
|
287
|
+
return ret;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
MLD_MUST_CHECK_RETURN_VALUE
|
|
291
|
+
MLD_EXTERNAL_API
|
|
292
|
+
int mld_sign_keypair_internal(uint8_t pk[MLDSA_CRYPTO_PUBLICKEYBYTES],
|
|
293
|
+
uint8_t sk[MLDSA_CRYPTO_SECRETKEYBYTES],
|
|
294
|
+
const uint8_t seed[MLDSA_SEEDBYTES],
|
|
295
|
+
MLD_CONFIG_CONTEXT_PARAMETER_TYPE context)
|
|
296
|
+
{
|
|
297
|
+
int ret;
|
|
298
|
+
const uint8_t *rho, *rhoprime, *key;
|
|
299
|
+
MLD_ALLOC(seedbuf, uint8_t, 2 * MLDSA_SEEDBYTES + MLDSA_CRHBYTES, context);
|
|
300
|
+
MLD_ALLOC(inbuf, uint8_t, MLDSA_SEEDBYTES + 2, context);
|
|
301
|
+
MLD_ALLOC(tr, uint8_t, MLDSA_TRBYTES, context);
|
|
302
|
+
MLD_ALLOC(s1, mld_polyvecl, 1, context);
|
|
303
|
+
MLD_ALLOC(s2, mld_polyveck, 1, context);
|
|
304
|
+
MLD_ALLOC(t1, mld_polyveck, 1, context);
|
|
305
|
+
MLD_ALLOC(t0, mld_polyveck, 1, context);
|
|
306
|
+
|
|
307
|
+
if (seedbuf == NULL || inbuf == NULL || tr == NULL || s1 == NULL ||
|
|
308
|
+
s2 == NULL || t1 == NULL || t0 == NULL)
|
|
309
|
+
{
|
|
310
|
+
ret = MLD_ERR_OUT_OF_MEMORY;
|
|
311
|
+
goto cleanup;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/* Get randomness for rho, rhoprime and key */
|
|
315
|
+
mld_memcpy(inbuf, seed, MLDSA_SEEDBYTES);
|
|
316
|
+
inbuf[MLDSA_SEEDBYTES + 0] = MLDSA_K;
|
|
317
|
+
inbuf[MLDSA_SEEDBYTES + 1] = MLDSA_L;
|
|
318
|
+
mld_shake256(seedbuf, 2 * MLDSA_SEEDBYTES + MLDSA_CRHBYTES, inbuf,
|
|
319
|
+
MLDSA_SEEDBYTES + 2);
|
|
320
|
+
rho = seedbuf;
|
|
321
|
+
rhoprime = rho + MLDSA_SEEDBYTES;
|
|
322
|
+
key = rhoprime + MLDSA_CRHBYTES;
|
|
323
|
+
|
|
324
|
+
/* Constant time: rho is part of the public key and, hence, public. */
|
|
325
|
+
MLD_CT_TESTING_DECLASSIFY(rho, MLDSA_SEEDBYTES);
|
|
326
|
+
|
|
327
|
+
/* Sample s1 and s2 */
|
|
328
|
+
mld_sample_s1_s2(s1, s2, rhoprime);
|
|
329
|
+
|
|
330
|
+
/* Compute t0, t1, tr, and pk from rho, s1, s2 */
|
|
331
|
+
ret = mld_compute_t0_t1_tr_from_sk_components(t0, t1, tr, pk, rho, s1, s2,
|
|
332
|
+
context);
|
|
333
|
+
if (ret != 0)
|
|
334
|
+
{
|
|
335
|
+
goto cleanup;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
/* Pack secret key */
|
|
339
|
+
mld_pack_sk(sk, rho, tr, key, t0, s1, s2);
|
|
340
|
+
|
|
341
|
+
/* Constant time: pk is the public key, inherently public data */
|
|
342
|
+
MLD_CT_TESTING_DECLASSIFY(pk, MLDSA_CRYPTO_PUBLICKEYBYTES);
|
|
343
|
+
|
|
344
|
+
cleanup:
|
|
345
|
+
/* @[FIPS204, Section 3.6.3] Destruction of intermediate values. */
|
|
346
|
+
MLD_FREE(t0, mld_polyveck, 1, context);
|
|
347
|
+
MLD_FREE(t1, mld_polyveck, 1, context);
|
|
348
|
+
MLD_FREE(s2, mld_polyveck, 1, context);
|
|
349
|
+
MLD_FREE(s1, mld_polyvecl, 1, context);
|
|
350
|
+
MLD_FREE(tr, uint8_t, MLDSA_TRBYTES, context);
|
|
351
|
+
MLD_FREE(inbuf, uint8_t, MLDSA_SEEDBYTES + 2, context);
|
|
352
|
+
MLD_FREE(seedbuf, uint8_t, 2 * MLDSA_SEEDBYTES + MLDSA_CRHBYTES, context);
|
|
353
|
+
|
|
354
|
+
if (ret != 0)
|
|
355
|
+
{
|
|
356
|
+
return ret;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
/* Pairwise Consistency Test (PCT) @[FIPS140_3_IG, p.87] */
|
|
360
|
+
/* Do this after freeing all temporaries. */
|
|
361
|
+
return mld_check_pct(pk, sk, context);
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
#if !defined(MLD_CONFIG_NO_RANDOMIZED_API)
|
|
365
|
+
MLD_MUST_CHECK_RETURN_VALUE
|
|
366
|
+
MLD_EXTERNAL_API
|
|
367
|
+
int mld_sign_keypair(uint8_t pk[MLDSA_CRYPTO_PUBLICKEYBYTES],
|
|
368
|
+
uint8_t sk[MLDSA_CRYPTO_SECRETKEYBYTES],
|
|
369
|
+
MLD_CONFIG_CONTEXT_PARAMETER_TYPE context)
|
|
370
|
+
{
|
|
371
|
+
MLD_ALIGN uint8_t seed[MLDSA_SEEDBYTES];
|
|
372
|
+
int ret;
|
|
373
|
+
if (mld_randombytes(seed, MLDSA_SEEDBYTES) != 0)
|
|
374
|
+
{
|
|
375
|
+
ret = MLD_ERR_RNG_FAIL;
|
|
376
|
+
goto cleanup;
|
|
377
|
+
}
|
|
378
|
+
MLD_CT_TESTING_SECRET(seed, sizeof(seed));
|
|
379
|
+
ret = mld_sign_keypair_internal(pk, sk, seed, context);
|
|
380
|
+
|
|
381
|
+
cleanup:
|
|
382
|
+
/* @[FIPS204, Section 3.6.3] Destruction of intermediate values. */
|
|
383
|
+
mld_zeroize(seed, sizeof(seed));
|
|
384
|
+
return ret;
|
|
385
|
+
}
|
|
386
|
+
#endif /* !MLD_CONFIG_NO_RANDOMIZED_API */
|
|
387
|
+
|
|
388
|
+
/*************************************************
|
|
389
|
+
* Name: mld_H
|
|
390
|
+
*
|
|
391
|
+
* Description: Abstracts application of SHAKE256 to
|
|
392
|
+
* one, two or three blocks of data,
|
|
393
|
+
* yielding a user-requested size of
|
|
394
|
+
* output.
|
|
395
|
+
*
|
|
396
|
+
* Arguments: - uint8_t *out: pointer to output
|
|
397
|
+
* - size_t outlen: requested output length in bytes
|
|
398
|
+
* - const uint8_t *in1: pointer to input block 1
|
|
399
|
+
* Must NOT be NULL
|
|
400
|
+
* - size_t in1len: length of input in1 bytes
|
|
401
|
+
* - const uint8_t *in2: pointer to input block 2
|
|
402
|
+
* May be NULL if in2len=0, in which case
|
|
403
|
+
* this block is ignored
|
|
404
|
+
* - size_t in2len: length of input in2 bytes
|
|
405
|
+
* - const uint8_t *in3: pointer to input block 3
|
|
406
|
+
* May be NULL if in3len=0, in which case
|
|
407
|
+
* this block is ignored
|
|
408
|
+
* - size_t in3len: length of input in3 bytes
|
|
409
|
+
**************************************************/
|
|
410
|
+
static void mld_H(uint8_t *out, size_t outlen, const uint8_t *in1,
|
|
411
|
+
size_t in1len, const uint8_t *in2, size_t in2len,
|
|
412
|
+
const uint8_t *in3, size_t in3len)
|
|
413
|
+
__contract__(
|
|
414
|
+
requires(in1len <= MLD_MAX_BUFFER_SIZE)
|
|
415
|
+
requires(in2len <= MLD_MAX_BUFFER_SIZE)
|
|
416
|
+
requires(in3len <= MLD_MAX_BUFFER_SIZE)
|
|
417
|
+
requires(outlen <= 8 * SHAKE256_RATE /* somewhat arbitrary bound */)
|
|
418
|
+
requires(memory_no_alias(in1, in1len))
|
|
419
|
+
requires(in2len == 0 || memory_no_alias(in2, in2len))
|
|
420
|
+
requires(in3len == 0 || memory_no_alias(in3, in3len))
|
|
421
|
+
requires(memory_no_alias(out, outlen))
|
|
422
|
+
assigns(memory_slice(out, outlen))
|
|
423
|
+
)
|
|
424
|
+
{
|
|
425
|
+
mld_shake256ctx state;
|
|
426
|
+
mld_shake256_init(&state);
|
|
427
|
+
mld_shake256_absorb(&state, in1, in1len);
|
|
428
|
+
if (in2len != 0)
|
|
429
|
+
{
|
|
430
|
+
mld_shake256_absorb(&state, in2, in2len);
|
|
431
|
+
}
|
|
432
|
+
if (in3len != 0)
|
|
433
|
+
{
|
|
434
|
+
mld_shake256_absorb(&state, in3, in3len);
|
|
435
|
+
}
|
|
436
|
+
mld_shake256_finalize(&state);
|
|
437
|
+
mld_shake256_squeeze(out, outlen, &state);
|
|
438
|
+
mld_shake256_release(&state);
|
|
439
|
+
|
|
440
|
+
/* @[FIPS204, Section 3.6.3] Destruction of intermediate values. */
|
|
441
|
+
mld_zeroize(&state, sizeof(state));
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
/*************************************************
|
|
445
|
+
* Name: mld_compute_pack_z
|
|
446
|
+
*
|
|
447
|
+
* Description: Computes z = y + s1*c, checks that z has coefficients smaller
|
|
448
|
+
* than MLDSA_GAMMA1 - MLDSA_BETA, and packs z into the
|
|
449
|
+
* signature buffer.
|
|
450
|
+
*
|
|
451
|
+
* Arguments: - uint8_t *sig: output signature
|
|
452
|
+
* - const mld_poly *cp: challenge polynomial
|
|
453
|
+
* - const polyvecl *s1: secret vector s1
|
|
454
|
+
* - const polyvecl *y: masking vector y
|
|
455
|
+
*
|
|
456
|
+
* Returns: - 0: Success (z has coefficients smaller than
|
|
457
|
+
* MLDSA_GAMMA1 - MLDSA_BETA,)
|
|
458
|
+
* - MLD_ERR_FAIL: z rejected (norm check failed)
|
|
459
|
+
* - MLD_ERR_OUT_OF_MEMORY: If MLD_CONFIG_CUSTOM_ALLOC_FREE is
|
|
460
|
+
* used and an allocation via MLD_CUSTOM_ALLOC returned NULL.
|
|
461
|
+
*
|
|
462
|
+
* Reference: This function is inlined into mld_sign_signature in the
|
|
463
|
+
* reference implementation.
|
|
464
|
+
**************************************************/
|
|
465
|
+
MLD_MUST_CHECK_RETURN_VALUE
|
|
466
|
+
static int mld_compute_pack_z(uint8_t sig[MLDSA_CRYPTO_BYTES],
|
|
467
|
+
const mld_poly *cp, const mld_polyvecl *s1,
|
|
468
|
+
const mld_polyvecl *y, mld_poly *z)
|
|
469
|
+
__contract__(
|
|
470
|
+
requires(memory_no_alias(sig, MLDSA_CRYPTO_BYTES))
|
|
471
|
+
requires(memory_no_alias(cp, sizeof(mld_poly)))
|
|
472
|
+
requires(memory_no_alias(s1, sizeof(mld_polyvecl)))
|
|
473
|
+
requires(memory_no_alias(y, sizeof(mld_polyvecl)))
|
|
474
|
+
requires(memory_no_alias(z, sizeof(mld_poly)))
|
|
475
|
+
requires(array_abs_bound(cp->coeffs, 0, MLDSA_N, MLD_NTT_BOUND))
|
|
476
|
+
requires(forall(k0, 0, MLDSA_L,
|
|
477
|
+
array_bound(y->vec[k0].coeffs, 0, MLDSA_N, -(MLDSA_GAMMA1 - 1), MLDSA_GAMMA1 + 1)))
|
|
478
|
+
requires(forall(k1, 0, MLDSA_L, array_abs_bound(s1->vec[k1].coeffs, 0, MLDSA_N, MLD_NTT_BOUND)))
|
|
479
|
+
assigns(memory_slice(sig, MLDSA_CRYPTO_BYTES))
|
|
480
|
+
assigns(memory_slice(z, sizeof(mld_poly)))
|
|
481
|
+
ensures(return_value == 0 || return_value == MLD_ERR_FAIL ||
|
|
482
|
+
return_value == MLD_ERR_OUT_OF_MEMORY)
|
|
483
|
+
)
|
|
484
|
+
{
|
|
485
|
+
unsigned int i;
|
|
486
|
+
uint32_t z_invalid;
|
|
487
|
+
for (i = 0; i < MLDSA_L; i++)
|
|
488
|
+
__loop__(
|
|
489
|
+
assigns(i, memory_slice(z, sizeof(mld_poly)), memory_slice(sig, MLDSA_CRYPTO_BYTES))
|
|
490
|
+
invariant(i <= MLDSA_L)
|
|
491
|
+
decreases(MLDSA_L - i)
|
|
492
|
+
)
|
|
493
|
+
{
|
|
494
|
+
mld_poly_pointwise_montgomery(z, cp, &s1->vec[i]);
|
|
495
|
+
mld_poly_invntt_tomont(z);
|
|
496
|
+
mld_poly_add(z, &y->vec[i]);
|
|
497
|
+
mld_poly_reduce(z);
|
|
498
|
+
|
|
499
|
+
z_invalid = mld_poly_chknorm(z, MLDSA_GAMMA1 - MLDSA_BETA);
|
|
500
|
+
/* Constant time: It is fine (and prohibitively expensive to avoid)
|
|
501
|
+
* to leak the result of the norm check and which polynomial in z caused a
|
|
502
|
+
* rejection. It would even be okay to leak which coefficient led to
|
|
503
|
+
* rejection as the candidate signature will be discarded anyway.
|
|
504
|
+
* See Section 5.5 of @[Round3_Spec]. */
|
|
505
|
+
MLD_CT_TESTING_DECLASSIFY(&z_invalid, sizeof(uint32_t));
|
|
506
|
+
if (z_invalid)
|
|
507
|
+
{
|
|
508
|
+
return MLD_ERR_FAIL; /* reject */
|
|
509
|
+
}
|
|
510
|
+
/* If z is valid, then its coefficients are bounded by
|
|
511
|
+
* MLDSA_GAMMA1 - MLDSA_BETA. This will be needed below
|
|
512
|
+
* to prove the pre-condition of pack_sig_z() */
|
|
513
|
+
mld_assert_abs_bound(z, MLDSA_N, (MLDSA_GAMMA1 - MLDSA_BETA));
|
|
514
|
+
|
|
515
|
+
/* After the norm check, the distribution of each coefficient of z is
|
|
516
|
+
* independent of the secret key and it can, hence, be considered
|
|
517
|
+
* public. It is, hence, okay to immediately pack it into the user-provided
|
|
518
|
+
* signature buffer. */
|
|
519
|
+
mld_pack_sig_z(sig, z, i);
|
|
520
|
+
}
|
|
521
|
+
return 0;
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
/* Reference: The reference implementation does not explicitly check the
|
|
525
|
+
* maximum nonce value, but instead loops indefinitely (even when the nonce
|
|
526
|
+
* would overflow). Internally, sampling of y uses
|
|
527
|
+
* (nonceL), (nonceL+1), ... (nonce*L+L-1).
|
|
528
|
+
* Hence, there are no overflows if nonce < (UINT16_MAX - L)/L.
|
|
529
|
+
* Explicitly checking for this explicitly allows us to prove type-safety.
|
|
530
|
+
* Note that FIPS204 explicitly allows an upper-bound this loop of
|
|
531
|
+
* 814 (< (UINT16_MAX - L)/L) - see @[FIPS204, Appendix C]. */
|
|
532
|
+
#define MLD_NONCE_UB ((UINT16_MAX - MLDSA_L) / MLDSA_L)
|
|
533
|
+
|
|
534
|
+
/*************************************************
|
|
535
|
+
* Name: attempt_signature_generation
|
|
536
|
+
*
|
|
537
|
+
* Description: Attempts to generate a single signature.
|
|
538
|
+
*
|
|
539
|
+
* Arguments: - uint8_t *sig: pointer to output signature
|
|
540
|
+
* - const uint8_t *mu: pointer to message or hash
|
|
541
|
+
* of exactly MLDSA_CRHBYTES bytes
|
|
542
|
+
* - const uint8_t *rhoprime: pointer to randomness seed
|
|
543
|
+
* - uint16_t nonce: current nonce value
|
|
544
|
+
* - const mld_polymat *mat: expanded matrix
|
|
545
|
+
* - const polyvecl *s1: secret vector s1
|
|
546
|
+
* - const polyveck *s2: secret vector s2
|
|
547
|
+
* - const polyveck *t0: vector t0
|
|
548
|
+
*
|
|
549
|
+
* Returns: - 0: Signature generation succeeded
|
|
550
|
+
* - MLD_ERR_FAIL: Signature rejected (norm check failed)
|
|
551
|
+
* - MLD_ERR_OUT_OF_MEMORY: If MLD_CONFIG_CUSTOM_ALLOC_FREE is
|
|
552
|
+
* used and an allocation via MLD_CUSTOM_ALLOC returned NULL.
|
|
553
|
+
*
|
|
554
|
+
* Reference: This code differs from the reference implementation
|
|
555
|
+
* in that it factors out the core signature generation
|
|
556
|
+
* step into a distinct function here in order to improve
|
|
557
|
+
* efficiency of CBMC proof.
|
|
558
|
+
**************************************************/
|
|
559
|
+
MLD_MUST_CHECK_RETURN_VALUE
|
|
560
|
+
static int mld_attempt_signature_generation(
|
|
561
|
+
uint8_t sig[MLDSA_CRYPTO_BYTES], const uint8_t *mu,
|
|
562
|
+
const uint8_t rhoprime[MLDSA_CRHBYTES], uint16_t nonce, mld_polymat *mat,
|
|
563
|
+
const mld_polyvecl *s1, const mld_polyveck *s2, const mld_polyveck *t0,
|
|
564
|
+
MLD_CONFIG_CONTEXT_PARAMETER_TYPE context)
|
|
565
|
+
__contract__(
|
|
566
|
+
requires(memory_no_alias(sig, MLDSA_CRYPTO_BYTES))
|
|
567
|
+
requires(memory_no_alias(mu, MLDSA_CRHBYTES))
|
|
568
|
+
requires(memory_no_alias(rhoprime, MLDSA_CRHBYTES))
|
|
569
|
+
requires(memory_no_alias(mat, sizeof(mld_polymat)))
|
|
570
|
+
requires(memory_no_alias(s1, sizeof(mld_polyvecl)))
|
|
571
|
+
requires(memory_no_alias(s2, sizeof(mld_polyveck)))
|
|
572
|
+
requires(memory_no_alias(t0, sizeof(mld_polyveck)))
|
|
573
|
+
requires(nonce <= MLD_NONCE_UB)
|
|
574
|
+
requires(forall(k1, 0, MLDSA_K, forall(l1, 0, MLDSA_L,
|
|
575
|
+
array_bound(mat->vec[k1].vec[l1].coeffs, 0, MLDSA_N, 0, MLDSA_Q))))
|
|
576
|
+
requires(forall(k2, 0, MLDSA_K, array_abs_bound(t0->vec[k2].coeffs, 0, MLDSA_N, MLD_NTT_BOUND)))
|
|
577
|
+
requires(forall(k3, 0, MLDSA_L, array_abs_bound(s1->vec[k3].coeffs, 0, MLDSA_N, MLD_NTT_BOUND)))
|
|
578
|
+
requires(forall(k4, 0, MLDSA_K, array_abs_bound(s2->vec[k4].coeffs, 0, MLDSA_N, MLD_NTT_BOUND)))
|
|
579
|
+
assigns(memory_slice(sig, MLDSA_CRYPTO_BYTES))
|
|
580
|
+
ensures(return_value == 0 || return_value == MLD_ERR_FAIL ||
|
|
581
|
+
return_value == MLD_ERR_OUT_OF_MEMORY)
|
|
582
|
+
)
|
|
583
|
+
{
|
|
584
|
+
unsigned int n;
|
|
585
|
+
uint32_t w0_invalid, h_invalid;
|
|
586
|
+
int ret;
|
|
587
|
+
/* TODO: Remove the following workaround for
|
|
588
|
+
* https://github.com/diffblue/cbmc/issues/8813 */
|
|
589
|
+
typedef MLD_UNION_OR_STRUCT
|
|
590
|
+
{
|
|
591
|
+
mld_polyvecl y;
|
|
592
|
+
mld_polyveck h;
|
|
593
|
+
}
|
|
594
|
+
yh_u;
|
|
595
|
+
mld_polyvecl *y;
|
|
596
|
+
mld_polyveck *h;
|
|
597
|
+
|
|
598
|
+
/* TODO: Remove the following workaround for
|
|
599
|
+
* https://github.com/diffblue/cbmc/issues/8813 */
|
|
600
|
+
typedef MLD_UNION_OR_STRUCT
|
|
601
|
+
{
|
|
602
|
+
mld_polyveck w1;
|
|
603
|
+
mld_polyvecl tmp;
|
|
604
|
+
}
|
|
605
|
+
w1tmp_u;
|
|
606
|
+
mld_polyveck *w1;
|
|
607
|
+
mld_polyvecl *tmp;
|
|
608
|
+
|
|
609
|
+
MLD_ALLOC(challenge_bytes, uint8_t, MLDSA_CTILDEBYTES, context);
|
|
610
|
+
MLD_ALLOC(yh, yh_u, 1, context);
|
|
611
|
+
MLD_ALLOC(z, mld_poly, 1, context);
|
|
612
|
+
MLD_ALLOC(w1tmp, w1tmp_u, 1, context);
|
|
613
|
+
MLD_ALLOC(w0, mld_polyveck, 1, context);
|
|
614
|
+
MLD_ALLOC(cp, mld_poly, 1, context);
|
|
615
|
+
MLD_ALLOC(t, mld_poly, 1, context);
|
|
616
|
+
|
|
617
|
+
if (challenge_bytes == NULL || yh == NULL || z == NULL || w1tmp == NULL ||
|
|
618
|
+
w0 == NULL || cp == NULL || t == NULL)
|
|
619
|
+
{
|
|
620
|
+
ret = MLD_ERR_OUT_OF_MEMORY;
|
|
621
|
+
goto cleanup;
|
|
622
|
+
}
|
|
623
|
+
y = &yh->y;
|
|
624
|
+
h = &yh->h;
|
|
625
|
+
w1 = &w1tmp->w1;
|
|
626
|
+
tmp = &w1tmp->tmp;
|
|
627
|
+
|
|
628
|
+
/* Sample intermediate vector y */
|
|
629
|
+
mld_polyvecl_uniform_gamma1(y, rhoprime, nonce);
|
|
630
|
+
|
|
631
|
+
/* Matrix-vector multiplication */
|
|
632
|
+
*tmp = *y;
|
|
633
|
+
mld_polyvecl_ntt(tmp);
|
|
634
|
+
mld_polyvec_matrix_pointwise_montgomery(w0, mat, tmp);
|
|
635
|
+
mld_polyveck_invntt_tomont(w0);
|
|
636
|
+
|
|
637
|
+
/* Decompose w and call the random oracle */
|
|
638
|
+
mld_polyveck_caddq(w0);
|
|
639
|
+
mld_polyveck_decompose(w1, w0);
|
|
640
|
+
mld_polyveck_pack_w1(sig, w1);
|
|
641
|
+
|
|
642
|
+
mld_H(challenge_bytes, MLDSA_CTILDEBYTES, mu, MLDSA_CRHBYTES, sig,
|
|
643
|
+
MLDSA_K * MLDSA_POLYW1_PACKEDBYTES, NULL, 0);
|
|
644
|
+
/* Constant time: Leaking challenge_bytes does not reveal any information
|
|
645
|
+
* about the secret key as H() is modelled as random oracle.
|
|
646
|
+
* This also applies to challenges for rejected signatures.
|
|
647
|
+
* See Section 5.5 of @[Round3_Spec]. */
|
|
648
|
+
MLD_CT_TESTING_DECLASSIFY(challenge_bytes, MLDSA_CTILDEBYTES);
|
|
649
|
+
mld_poly_challenge(cp, challenge_bytes);
|
|
650
|
+
mld_poly_ntt(cp);
|
|
651
|
+
|
|
652
|
+
/* Compute z, reject if it reveals secret */
|
|
653
|
+
ret = mld_compute_pack_z(sig, cp, s1, y, t);
|
|
654
|
+
if (ret)
|
|
655
|
+
{
|
|
656
|
+
goto cleanup;
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
/* Check that subtracting cs2 does not change high bits of w and low bits
|
|
660
|
+
* do not reveal secret information */
|
|
661
|
+
mld_polyveck_pointwise_poly_montgomery(h, cp, s2);
|
|
662
|
+
mld_polyveck_invntt_tomont(h);
|
|
663
|
+
mld_polyveck_sub(w0, h);
|
|
664
|
+
mld_polyveck_reduce(w0);
|
|
665
|
+
|
|
666
|
+
w0_invalid = mld_polyveck_chknorm(w0, MLDSA_GAMMA2 - MLDSA_BETA);
|
|
667
|
+
/* Constant time: w0_invalid may be leaked - see comment for z_invalid. */
|
|
668
|
+
MLD_CT_TESTING_DECLASSIFY(&w0_invalid, sizeof(uint32_t));
|
|
669
|
+
if (w0_invalid)
|
|
670
|
+
{
|
|
671
|
+
ret = MLD_ERR_FAIL; /* reject */
|
|
672
|
+
goto cleanup;
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
/* Compute hints for w1 */
|
|
676
|
+
mld_polyveck_pointwise_poly_montgomery(h, cp, t0);
|
|
677
|
+
mld_polyveck_invntt_tomont(h);
|
|
678
|
+
mld_polyveck_reduce(h);
|
|
679
|
+
|
|
680
|
+
h_invalid = mld_polyveck_chknorm(h, MLDSA_GAMMA2);
|
|
681
|
+
/* Constant time: h_invalid may be leaked - see comment for z_invalid. */
|
|
682
|
+
MLD_CT_TESTING_DECLASSIFY(&h_invalid, sizeof(uint32_t));
|
|
683
|
+
if (h_invalid)
|
|
684
|
+
{
|
|
685
|
+
ret = MLD_ERR_FAIL; /* reject */
|
|
686
|
+
goto cleanup;
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
mld_polyveck_add(w0, h);
|
|
690
|
+
|
|
691
|
+
/* Constant time: At this point all norm checks have passed and we, hence,
|
|
692
|
+
* know that the signature does not leak any secret information.
|
|
693
|
+
* Consequently, any value that can be computed from the signature and public
|
|
694
|
+
* key is considered public.
|
|
695
|
+
* w0 and w1 are public as they can be computed from Az - ct = \alpha w1 + w0.
|
|
696
|
+
* h=c*t0 is public as both c and t0 are public.
|
|
697
|
+
* For a more detailed discussion, refer to https://eprint.iacr.org/2022/1406.
|
|
698
|
+
*/
|
|
699
|
+
MLD_CT_TESTING_DECLASSIFY(w0, sizeof(*w0));
|
|
700
|
+
MLD_CT_TESTING_DECLASSIFY(w1, sizeof(*w1));
|
|
701
|
+
n = mld_polyveck_make_hint(h, w0, w1);
|
|
702
|
+
if (n > MLDSA_OMEGA)
|
|
703
|
+
{
|
|
704
|
+
ret = MLD_ERR_FAIL; /* reject */
|
|
705
|
+
goto cleanup;
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
/* All is well - write signature */
|
|
709
|
+
mld_pack_sig_c_h(sig, challenge_bytes, h, n);
|
|
710
|
+
/* Constant time: At this point it is clear that the signature is valid - it
|
|
711
|
+
* can, hence, be considered public. */
|
|
712
|
+
MLD_CT_TESTING_DECLASSIFY(sig, MLDSA_CRYPTO_BYTES);
|
|
713
|
+
ret = 0; /* success */
|
|
714
|
+
|
|
715
|
+
cleanup:
|
|
716
|
+
/* @[FIPS204, Section 3.6.3] Destruction of intermediate values. */
|
|
717
|
+
MLD_FREE(t, mld_poly, 1, context);
|
|
718
|
+
MLD_FREE(cp, mld_poly, 1, context);
|
|
719
|
+
MLD_FREE(w0, mld_polyveck, 1, context);
|
|
720
|
+
MLD_FREE(w1tmp, w1tmp_u, 1, context);
|
|
721
|
+
MLD_FREE(z, mld_poly, 1, context);
|
|
722
|
+
MLD_FREE(yh, yh_u, 1, context);
|
|
723
|
+
MLD_FREE(challenge_bytes, uint8_t, MLDSA_CTILDEBYTES, context);
|
|
724
|
+
|
|
725
|
+
return ret;
|
|
726
|
+
}
|
|
727
|
+
MLD_MUST_CHECK_RETURN_VALUE
|
|
728
|
+
MLD_EXTERNAL_API
|
|
729
|
+
int mld_sign_signature_internal(uint8_t sig[MLDSA_CRYPTO_BYTES], size_t *siglen,
|
|
730
|
+
const uint8_t *m, size_t mlen,
|
|
731
|
+
const uint8_t *pre, size_t prelen,
|
|
732
|
+
const uint8_t rnd[MLDSA_RNDBYTES],
|
|
733
|
+
const uint8_t sk[MLDSA_CRYPTO_SECRETKEYBYTES],
|
|
734
|
+
int externalmu,
|
|
735
|
+
MLD_CONFIG_CONTEXT_PARAMETER_TYPE context)
|
|
736
|
+
{
|
|
737
|
+
int ret;
|
|
738
|
+
uint8_t *rho, *tr, *key, *mu, *rhoprime;
|
|
739
|
+
uint16_t nonce = 0;
|
|
740
|
+
MLD_ALLOC(seedbuf, uint8_t,
|
|
741
|
+
2 * MLDSA_SEEDBYTES + MLDSA_TRBYTES + 2 * MLDSA_CRHBYTES, context);
|
|
742
|
+
MLD_ALLOC(mat, mld_polymat, 1, context);
|
|
743
|
+
MLD_ALLOC(s1, mld_polyvecl, 1, context);
|
|
744
|
+
MLD_ALLOC(t0, mld_polyveck, 1, context);
|
|
745
|
+
MLD_ALLOC(s2, mld_polyveck, 1, context);
|
|
746
|
+
|
|
747
|
+
if (seedbuf == NULL || mat == NULL || s1 == NULL || t0 == NULL || s2 == NULL)
|
|
748
|
+
{
|
|
749
|
+
ret = MLD_ERR_OUT_OF_MEMORY;
|
|
750
|
+
goto cleanup;
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
rho = seedbuf;
|
|
754
|
+
tr = rho + MLDSA_SEEDBYTES;
|
|
755
|
+
key = tr + MLDSA_TRBYTES;
|
|
756
|
+
mu = key + MLDSA_SEEDBYTES;
|
|
757
|
+
rhoprime = mu + MLDSA_CRHBYTES;
|
|
758
|
+
mld_unpack_sk(rho, tr, key, t0, s1, s2, sk);
|
|
759
|
+
|
|
760
|
+
if (!externalmu)
|
|
761
|
+
{
|
|
762
|
+
/* Compute mu = CRH(tr, pre, msg) */
|
|
763
|
+
mld_H(mu, MLDSA_CRHBYTES, tr, MLDSA_TRBYTES, pre, prelen, m, mlen);
|
|
764
|
+
}
|
|
765
|
+
else
|
|
766
|
+
{
|
|
767
|
+
/* mu has been provided directly */
|
|
768
|
+
mld_memcpy(mu, m, MLDSA_CRHBYTES);
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
/* Compute rhoprime = CRH(key, rnd, mu) */
|
|
772
|
+
mld_H(rhoprime, MLDSA_CRHBYTES, key, MLDSA_SEEDBYTES, rnd, MLDSA_RNDBYTES, mu,
|
|
773
|
+
MLDSA_CRHBYTES);
|
|
774
|
+
|
|
775
|
+
/* Constant time: rho is part of the public key and, hence, public. */
|
|
776
|
+
MLD_CT_TESTING_DECLASSIFY(rho, MLDSA_SEEDBYTES);
|
|
777
|
+
/* Expand matrix and transform vectors */
|
|
778
|
+
mld_polyvec_matrix_expand(mat, rho);
|
|
779
|
+
mld_polyvecl_ntt(s1);
|
|
780
|
+
mld_polyveck_ntt(s2);
|
|
781
|
+
mld_polyveck_ntt(t0);
|
|
782
|
+
|
|
783
|
+
/* By default, return failure. Flip to success and write output
|
|
784
|
+
* once signature generation succeeds. */
|
|
785
|
+
ret = MLD_ERR_FAIL;
|
|
786
|
+
|
|
787
|
+
/* Reference: This code is re-structured using a while(1), */
|
|
788
|
+
/* with explicit "continue" statements (rather than "goto") */
|
|
789
|
+
/* to implement rejection of invalid signatures. */
|
|
790
|
+
while (1)
|
|
791
|
+
__loop__(
|
|
792
|
+
assigns(nonce, ret, object_whole(siglen), memory_slice(sig, MLDSA_CRYPTO_BYTES))
|
|
793
|
+
invariant(nonce <= MLD_NONCE_UB)
|
|
794
|
+
|
|
795
|
+
/* t0, s1, s2, and mat are initialized above and are NOT changed by this */
|
|
796
|
+
/* loop. We can therefore re-assert their bounds here as part of the */
|
|
797
|
+
/* loop invariant. This makes proof noticeably faster with CBMC */
|
|
798
|
+
invariant(forall(k1, 0, MLDSA_K, forall(l1, 0, MLDSA_L,
|
|
799
|
+
array_bound(mat->vec[k1].vec[l1].coeffs, 0, MLDSA_N, 0, MLDSA_Q))))
|
|
800
|
+
invariant(forall(k2, 0, MLDSA_K, array_abs_bound(t0->vec[k2].coeffs, 0, MLDSA_N, MLD_NTT_BOUND)))
|
|
801
|
+
invariant(forall(k3, 0, MLDSA_L, array_abs_bound(s1->vec[k3].coeffs, 0, MLDSA_N, MLD_NTT_BOUND)))
|
|
802
|
+
invariant(forall(k4, 0, MLDSA_K, array_abs_bound(s2->vec[k4].coeffs, 0, MLDSA_N, MLD_NTT_BOUND)))
|
|
803
|
+
invariant(ret == MLD_ERR_FAIL)
|
|
804
|
+
decreases(MLD_NONCE_UB - nonce)
|
|
805
|
+
)
|
|
806
|
+
{
|
|
807
|
+
/* Reference: this code explicitly checks for exhaustion of nonce */
|
|
808
|
+
/* values to provide predictable termination and results in that case */
|
|
809
|
+
/* Checking here also means that incrementing nonce below can also */
|
|
810
|
+
/* be proven to be type-safe. */
|
|
811
|
+
if (nonce == MLD_NONCE_UB)
|
|
812
|
+
{
|
|
813
|
+
/* Note that ret == MLD_ERR_FAIL by default, so we
|
|
814
|
+
* don't need to set it here. */
|
|
815
|
+
break;
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
ret = mld_attempt_signature_generation(sig, mu, rhoprime, nonce, mat, s1,
|
|
819
|
+
s2, t0, context);
|
|
820
|
+
nonce++;
|
|
821
|
+
if (ret == 0)
|
|
822
|
+
{
|
|
823
|
+
*siglen = MLDSA_CRYPTO_BYTES;
|
|
824
|
+
break;
|
|
825
|
+
}
|
|
826
|
+
else if (ret != MLD_ERR_FAIL)
|
|
827
|
+
{
|
|
828
|
+
/* For failures such as out-of-memory, propagate and exit immediately. */
|
|
829
|
+
break;
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
/* Otherwise, try again. */
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
cleanup:
|
|
836
|
+
|
|
837
|
+
if (ret != 0)
|
|
838
|
+
{
|
|
839
|
+
/* To be on the safe-side, we zeroize the signature buffer. */
|
|
840
|
+
*siglen = 0;
|
|
841
|
+
mld_memset(sig, 0, MLDSA_CRYPTO_BYTES);
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
/* @[FIPS204, Section 3.6.3] Destruction of intermediate values. */
|
|
845
|
+
MLD_FREE(s2, mld_polyveck, 1, context);
|
|
846
|
+
MLD_FREE(t0, mld_polyveck, 1, context);
|
|
847
|
+
MLD_FREE(s1, mld_polyvecl, 1, context);
|
|
848
|
+
MLD_FREE(mat, mld_polymat, 1, context);
|
|
849
|
+
MLD_FREE(seedbuf, uint8_t,
|
|
850
|
+
2 * MLDSA_SEEDBYTES + MLDSA_TRBYTES + 2 * MLDSA_CRHBYTES, context);
|
|
851
|
+
return ret;
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
#if !defined(MLD_CONFIG_NO_RANDOMIZED_API)
|
|
855
|
+
MLD_MUST_CHECK_RETURN_VALUE
|
|
856
|
+
MLD_EXTERNAL_API
|
|
857
|
+
int mld_sign_signature(uint8_t sig[MLDSA_CRYPTO_BYTES], size_t *siglen,
|
|
858
|
+
const uint8_t *m, size_t mlen, const uint8_t *ctx,
|
|
859
|
+
size_t ctxlen,
|
|
860
|
+
const uint8_t sk[MLDSA_CRYPTO_SECRETKEYBYTES],
|
|
861
|
+
MLD_CONFIG_CONTEXT_PARAMETER_TYPE context)
|
|
862
|
+
{
|
|
863
|
+
size_t pre_len;
|
|
864
|
+
int ret;
|
|
865
|
+
MLD_ALLOC(pre, uint8_t, MLD_DOMAIN_SEPARATION_MAX_BYTES, context);
|
|
866
|
+
MLD_ALLOC(rnd, uint8_t, MLDSA_RNDBYTES, context);
|
|
867
|
+
|
|
868
|
+
if (pre == NULL || rnd == NULL)
|
|
869
|
+
{
|
|
870
|
+
ret = MLD_ERR_OUT_OF_MEMORY;
|
|
871
|
+
goto cleanup;
|
|
872
|
+
}
|
|
873
|
+
|
|
874
|
+
/* Prepare domain separation prefix for pure ML-DSA */
|
|
875
|
+
pre_len = mld_prepare_domain_separation_prefix(pre, NULL, 0, ctx, ctxlen,
|
|
876
|
+
MLD_PREHASH_NONE);
|
|
877
|
+
if (pre_len == 0)
|
|
878
|
+
{
|
|
879
|
+
ret = MLD_ERR_FAIL;
|
|
880
|
+
goto cleanup;
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
/* Randomized variant of ML-DSA. If you need the deterministic variant,
|
|
884
|
+
* call mld_sign_signature_internal directly with all-zero rnd. */
|
|
885
|
+
if (mld_randombytes(rnd, MLDSA_RNDBYTES) != 0)
|
|
886
|
+
{
|
|
887
|
+
ret = MLD_ERR_RNG_FAIL;
|
|
888
|
+
goto cleanup;
|
|
889
|
+
}
|
|
890
|
+
MLD_CT_TESTING_SECRET(rnd, sizeof(rnd));
|
|
891
|
+
|
|
892
|
+
ret = mld_sign_signature_internal(sig, siglen, m, mlen, pre, pre_len, rnd, sk,
|
|
893
|
+
0, context);
|
|
894
|
+
|
|
895
|
+
cleanup:
|
|
896
|
+
if (ret != 0)
|
|
897
|
+
{
|
|
898
|
+
/* To be on the safe-side, make sure *siglen and sig have a well-defined
|
|
899
|
+
* value, even in the case of error.
|
|
900
|
+
*
|
|
901
|
+
* If we come from mld_sign_signature_internal, both are redundant,
|
|
902
|
+
* but the error case should not be the norm, and the added cost of the
|
|
903
|
+
* memset insignificant. */
|
|
904
|
+
*siglen = 0;
|
|
905
|
+
mld_memset(sig, 0, MLDSA_CRYPTO_BYTES);
|
|
906
|
+
}
|
|
907
|
+
|
|
908
|
+
/* @[FIPS204, Section 3.6.3] Destruction of intermediate values. */
|
|
909
|
+
MLD_FREE(rnd, uint8_t, MLDSA_RNDBYTES, context);
|
|
910
|
+
MLD_FREE(pre, uint8_t, MLD_DOMAIN_SEPARATION_MAX_BYTES, context);
|
|
911
|
+
|
|
912
|
+
return ret;
|
|
913
|
+
}
|
|
914
|
+
#endif /* !MLD_CONFIG_NO_RANDOMIZED_API */
|
|
915
|
+
|
|
916
|
+
#if !defined(MLD_CONFIG_NO_RANDOMIZED_API)
|
|
917
|
+
MLD_MUST_CHECK_RETURN_VALUE
|
|
918
|
+
MLD_EXTERNAL_API
|
|
919
|
+
int mld_sign_signature_extmu(uint8_t sig[MLDSA_CRYPTO_BYTES], size_t *siglen,
|
|
920
|
+
const uint8_t mu[MLDSA_CRHBYTES],
|
|
921
|
+
const uint8_t sk[MLDSA_CRYPTO_SECRETKEYBYTES],
|
|
922
|
+
MLD_CONFIG_CONTEXT_PARAMETER_TYPE context)
|
|
923
|
+
{
|
|
924
|
+
MLD_ALIGN uint8_t rnd[MLDSA_RNDBYTES];
|
|
925
|
+
int ret;
|
|
926
|
+
|
|
927
|
+
/* Randomized variant of ML-DSA. If you need the deterministic variant,
|
|
928
|
+
* call mld_sign_signature_internal directly with all-zero rnd. */
|
|
929
|
+
if (mld_randombytes(rnd, MLDSA_RNDBYTES) != 0)
|
|
930
|
+
{
|
|
931
|
+
*siglen = 0;
|
|
932
|
+
ret = MLD_ERR_RNG_FAIL;
|
|
933
|
+
goto cleanup;
|
|
934
|
+
}
|
|
935
|
+
MLD_CT_TESTING_SECRET(rnd, sizeof(rnd));
|
|
936
|
+
|
|
937
|
+
ret = mld_sign_signature_internal(sig, siglen, mu, MLDSA_CRHBYTES, NULL, 0,
|
|
938
|
+
rnd, sk, 1, context);
|
|
939
|
+
|
|
940
|
+
cleanup:
|
|
941
|
+
/* @[FIPS204, Section 3.6.3] Destruction of intermediate values. */
|
|
942
|
+
mld_zeroize(rnd, sizeof(rnd));
|
|
943
|
+
|
|
944
|
+
return ret;
|
|
945
|
+
}
|
|
946
|
+
#endif /* !MLD_CONFIG_NO_RANDOMIZED_API */
|
|
947
|
+
|
|
948
|
+
#if !defined(MLD_CONFIG_NO_RANDOMIZED_API)
|
|
949
|
+
MLD_MUST_CHECK_RETURN_VALUE
|
|
950
|
+
MLD_EXTERNAL_API
|
|
951
|
+
int mld_sign(uint8_t *sm, size_t *smlen, const uint8_t *m, size_t mlen,
|
|
952
|
+
const uint8_t *ctx, size_t ctxlen,
|
|
953
|
+
const uint8_t sk[MLDSA_CRYPTO_SECRETKEYBYTES],
|
|
954
|
+
MLD_CONFIG_CONTEXT_PARAMETER_TYPE context)
|
|
955
|
+
{
|
|
956
|
+
int ret;
|
|
957
|
+
size_t i;
|
|
958
|
+
|
|
959
|
+
for (i = 0; i < mlen; ++i)
|
|
960
|
+
__loop__(
|
|
961
|
+
assigns(i, object_whole(sm))
|
|
962
|
+
invariant(i <= mlen)
|
|
963
|
+
decreases(mlen - i)
|
|
964
|
+
)
|
|
965
|
+
{
|
|
966
|
+
sm[MLDSA_CRYPTO_BYTES + mlen - 1 - i] = m[mlen - 1 - i];
|
|
967
|
+
}
|
|
968
|
+
ret = mld_sign_signature(sm, smlen, sm + MLDSA_CRYPTO_BYTES, mlen, ctx,
|
|
969
|
+
ctxlen, sk, context);
|
|
970
|
+
*smlen += mlen;
|
|
971
|
+
return ret;
|
|
972
|
+
}
|
|
973
|
+
#endif /* !MLD_CONFIG_NO_RANDOMIZED_API */
|
|
974
|
+
|
|
975
|
+
MLD_MUST_CHECK_RETURN_VALUE
|
|
976
|
+
MLD_EXTERNAL_API
|
|
977
|
+
int mld_sign_verify_internal(const uint8_t *sig, size_t siglen,
|
|
978
|
+
const uint8_t *m, size_t mlen, const uint8_t *pre,
|
|
979
|
+
size_t prelen,
|
|
980
|
+
const uint8_t pk[MLDSA_CRYPTO_PUBLICKEYBYTES],
|
|
981
|
+
int externalmu,
|
|
982
|
+
MLD_CONFIG_CONTEXT_PARAMETER_TYPE context)
|
|
983
|
+
{
|
|
984
|
+
int ret, cmp;
|
|
985
|
+
|
|
986
|
+
/* TODO: Remove the following workaround for
|
|
987
|
+
* https://github.com/diffblue/cbmc/issues/8813 */
|
|
988
|
+
typedef MLD_UNION_OR_STRUCT
|
|
989
|
+
{
|
|
990
|
+
mld_polyveck t1;
|
|
991
|
+
mld_polyveck w1;
|
|
992
|
+
}
|
|
993
|
+
t1w1_u;
|
|
994
|
+
mld_polyveck *t1;
|
|
995
|
+
mld_polyveck *w1;
|
|
996
|
+
|
|
997
|
+
MLD_ALLOC(buf, uint8_t, (MLDSA_K * MLDSA_POLYW1_PACKEDBYTES), context);
|
|
998
|
+
MLD_ALLOC(rho, uint8_t, MLDSA_SEEDBYTES, context);
|
|
999
|
+
MLD_ALLOC(mu, uint8_t, MLDSA_CRHBYTES, context);
|
|
1000
|
+
MLD_ALLOC(c, uint8_t, MLDSA_CTILDEBYTES, context);
|
|
1001
|
+
MLD_ALLOC(c2, uint8_t, MLDSA_CTILDEBYTES, context);
|
|
1002
|
+
MLD_ALLOC(cp, mld_poly, 1, context);
|
|
1003
|
+
MLD_ALLOC(mat, mld_polymat, 1, context);
|
|
1004
|
+
MLD_ALLOC(z, mld_polyvecl, 1, context);
|
|
1005
|
+
MLD_ALLOC(t1w1, t1w1_u, 1, context);
|
|
1006
|
+
MLD_ALLOC(tmp, mld_polyveck, 1, context);
|
|
1007
|
+
MLD_ALLOC(h, mld_polyveck, 1, context);
|
|
1008
|
+
|
|
1009
|
+
if (buf == NULL || rho == NULL || mu == NULL || c == NULL || c2 == NULL ||
|
|
1010
|
+
cp == NULL || mat == NULL || z == NULL || t1w1 == NULL || tmp == NULL ||
|
|
1011
|
+
h == NULL)
|
|
1012
|
+
{
|
|
1013
|
+
ret = MLD_ERR_OUT_OF_MEMORY;
|
|
1014
|
+
goto cleanup;
|
|
1015
|
+
}
|
|
1016
|
+
t1 = &t1w1->t1;
|
|
1017
|
+
w1 = &t1w1->w1;
|
|
1018
|
+
|
|
1019
|
+
if (siglen != MLDSA_CRYPTO_BYTES)
|
|
1020
|
+
{
|
|
1021
|
+
ret = MLD_ERR_FAIL;
|
|
1022
|
+
goto cleanup;
|
|
1023
|
+
}
|
|
1024
|
+
|
|
1025
|
+
mld_unpack_pk(rho, t1, pk);
|
|
1026
|
+
|
|
1027
|
+
/* mld_unpack_sig and mld_polyvecl_chknorm signal failure through a
|
|
1028
|
+
* single non-zero error code that's not yet aligned with MLD_ERR_XXX.
|
|
1029
|
+
* Map it to MLD_ERR_FAIL explicitly. */
|
|
1030
|
+
if (mld_unpack_sig(c, z, h, sig))
|
|
1031
|
+
{
|
|
1032
|
+
ret = MLD_ERR_FAIL;
|
|
1033
|
+
goto cleanup;
|
|
1034
|
+
}
|
|
1035
|
+
if (mld_polyvecl_chknorm(z, MLDSA_GAMMA1 - MLDSA_BETA))
|
|
1036
|
+
{
|
|
1037
|
+
ret = MLD_ERR_FAIL;
|
|
1038
|
+
goto cleanup;
|
|
1039
|
+
}
|
|
1040
|
+
|
|
1041
|
+
if (!externalmu)
|
|
1042
|
+
{
|
|
1043
|
+
/* Compute CRH(H(rho, t1), pre, msg) */
|
|
1044
|
+
MLD_ALIGN uint8_t hpk[MLDSA_CRHBYTES];
|
|
1045
|
+
mld_H(hpk, MLDSA_TRBYTES, pk, MLDSA_CRYPTO_PUBLICKEYBYTES, NULL, 0, NULL,
|
|
1046
|
+
0);
|
|
1047
|
+
mld_H(mu, MLDSA_CRHBYTES, hpk, MLDSA_TRBYTES, pre, prelen, m, mlen);
|
|
1048
|
+
|
|
1049
|
+
/* @[FIPS204, Section 3.6.3] Destruction of intermediate values. */
|
|
1050
|
+
mld_zeroize(hpk, sizeof(hpk));
|
|
1051
|
+
}
|
|
1052
|
+
else
|
|
1053
|
+
{
|
|
1054
|
+
/* mu has been provided directly */
|
|
1055
|
+
mld_memcpy(mu, m, MLDSA_CRHBYTES);
|
|
1056
|
+
}
|
|
1057
|
+
|
|
1058
|
+
/* Matrix-vector multiplication; compute Az - c2^dt1 */
|
|
1059
|
+
mld_poly_challenge(cp, c);
|
|
1060
|
+
mld_poly_ntt(cp);
|
|
1061
|
+
mld_polyveck_shiftl(t1);
|
|
1062
|
+
mld_polyveck_ntt(t1);
|
|
1063
|
+
mld_polyveck_pointwise_poly_montgomery(tmp, cp, t1);
|
|
1064
|
+
|
|
1065
|
+
mld_polyvec_matrix_expand(mat, rho);
|
|
1066
|
+
mld_polyvecl_ntt(z);
|
|
1067
|
+
mld_polyvec_matrix_pointwise_montgomery(w1, mat, z);
|
|
1068
|
+
mld_polyveck_sub(w1, tmp);
|
|
1069
|
+
mld_polyveck_reduce(w1);
|
|
1070
|
+
mld_polyveck_invntt_tomont(w1);
|
|
1071
|
+
|
|
1072
|
+
/* Reconstruct w1 */
|
|
1073
|
+
mld_polyveck_caddq(w1);
|
|
1074
|
+
mld_polyveck_use_hint(tmp, w1, h);
|
|
1075
|
+
mld_polyveck_pack_w1(buf, tmp);
|
|
1076
|
+
/* Call random oracle and verify challenge */
|
|
1077
|
+
mld_H(c2, MLDSA_CTILDEBYTES, mu, MLDSA_CRHBYTES, buf,
|
|
1078
|
+
MLDSA_K * MLDSA_POLYW1_PACKEDBYTES, NULL, 0);
|
|
1079
|
+
|
|
1080
|
+
cmp = mld_ct_memcmp(c, c2, MLDSA_CTILDEBYTES);
|
|
1081
|
+
|
|
1082
|
+
/* Declassify the result of the verification. */
|
|
1083
|
+
MLD_CT_TESTING_DECLASSIFY(&cmp, sizeof(cmp));
|
|
1084
|
+
|
|
1085
|
+
ret = cmp == 0 ? 0 : MLD_ERR_FAIL;
|
|
1086
|
+
|
|
1087
|
+
cleanup:
|
|
1088
|
+
/* @[FIPS204, Section 3.6.3] Destruction of intermediate values. */
|
|
1089
|
+
MLD_FREE(h, mld_polyveck, 1, context);
|
|
1090
|
+
MLD_FREE(tmp, mld_polyveck, 1, context);
|
|
1091
|
+
MLD_FREE(t1w1, t1w1_u, 1, context);
|
|
1092
|
+
MLD_FREE(z, mld_polyvecl, 1, context);
|
|
1093
|
+
MLD_FREE(mat, mld_polymat, 1, context);
|
|
1094
|
+
MLD_FREE(cp, mld_poly, 1, context);
|
|
1095
|
+
MLD_FREE(c2, uint8_t, MLDSA_CTILDEBYTES, context);
|
|
1096
|
+
MLD_FREE(c, uint8_t, MLDSA_CTILDEBYTES, context);
|
|
1097
|
+
MLD_FREE(mu, uint8_t, MLDSA_CRHBYTES, context);
|
|
1098
|
+
MLD_FREE(rho, uint8_t, MLDSA_SEEDBYTES, context);
|
|
1099
|
+
MLD_FREE(buf, uint8_t, (MLDSA_K * MLDSA_POLYW1_PACKEDBYTES), context);
|
|
1100
|
+
return ret;
|
|
1101
|
+
}
|
|
1102
|
+
|
|
1103
|
+
MLD_MUST_CHECK_RETURN_VALUE
|
|
1104
|
+
MLD_EXTERNAL_API
|
|
1105
|
+
int mld_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m,
|
|
1106
|
+
size_t mlen, const uint8_t *ctx, size_t ctxlen,
|
|
1107
|
+
const uint8_t pk[MLDSA_CRYPTO_PUBLICKEYBYTES],
|
|
1108
|
+
MLD_CONFIG_CONTEXT_PARAMETER_TYPE context)
|
|
1109
|
+
{
|
|
1110
|
+
MLD_ALIGN uint8_t pre[MLD_DOMAIN_SEPARATION_MAX_BYTES];
|
|
1111
|
+
size_t pre_len;
|
|
1112
|
+
int ret;
|
|
1113
|
+
|
|
1114
|
+
pre_len = mld_prepare_domain_separation_prefix(pre, NULL, 0, ctx, ctxlen,
|
|
1115
|
+
MLD_PREHASH_NONE);
|
|
1116
|
+
if (pre_len == 0)
|
|
1117
|
+
{
|
|
1118
|
+
ret = MLD_ERR_FAIL;
|
|
1119
|
+
goto cleanup;
|
|
1120
|
+
}
|
|
1121
|
+
|
|
1122
|
+
ret = mld_sign_verify_internal(sig, siglen, m, mlen, pre, pre_len, pk, 0,
|
|
1123
|
+
context);
|
|
1124
|
+
|
|
1125
|
+
cleanup:
|
|
1126
|
+
/* @[FIPS204, Section 3.6.3] Destruction of intermediate values. */
|
|
1127
|
+
mld_zeroize(pre, sizeof(pre));
|
|
1128
|
+
|
|
1129
|
+
return ret;
|
|
1130
|
+
}
|
|
1131
|
+
|
|
1132
|
+
MLD_MUST_CHECK_RETURN_VALUE
|
|
1133
|
+
MLD_EXTERNAL_API
|
|
1134
|
+
int mld_sign_verify_extmu(const uint8_t *sig, size_t siglen,
|
|
1135
|
+
const uint8_t mu[MLDSA_CRHBYTES],
|
|
1136
|
+
const uint8_t pk[MLDSA_CRYPTO_PUBLICKEYBYTES],
|
|
1137
|
+
MLD_CONFIG_CONTEXT_PARAMETER_TYPE context)
|
|
1138
|
+
{
|
|
1139
|
+
return mld_sign_verify_internal(sig, siglen, mu, MLDSA_CRHBYTES, NULL, 0, pk,
|
|
1140
|
+
1, context);
|
|
1141
|
+
}
|
|
1142
|
+
|
|
1143
|
+
MLD_MUST_CHECK_RETURN_VALUE
|
|
1144
|
+
MLD_EXTERNAL_API
|
|
1145
|
+
int mld_sign_open(uint8_t *m, size_t *mlen, const uint8_t *sm, size_t smlen,
|
|
1146
|
+
const uint8_t *ctx, size_t ctxlen,
|
|
1147
|
+
const uint8_t pk[MLDSA_CRYPTO_PUBLICKEYBYTES],
|
|
1148
|
+
MLD_CONFIG_CONTEXT_PARAMETER_TYPE context)
|
|
1149
|
+
{
|
|
1150
|
+
int ret;
|
|
1151
|
+
size_t i;
|
|
1152
|
+
|
|
1153
|
+
if (smlen < MLDSA_CRYPTO_BYTES)
|
|
1154
|
+
{
|
|
1155
|
+
ret = MLD_ERR_FAIL;
|
|
1156
|
+
goto cleanup;
|
|
1157
|
+
}
|
|
1158
|
+
|
|
1159
|
+
*mlen = smlen - MLDSA_CRYPTO_BYTES;
|
|
1160
|
+
ret = mld_sign_verify(sm, MLDSA_CRYPTO_BYTES, sm + MLDSA_CRYPTO_BYTES, *mlen,
|
|
1161
|
+
ctx, ctxlen, pk, context);
|
|
1162
|
+
if (ret == 0)
|
|
1163
|
+
{
|
|
1164
|
+
/* All good, copy msg, return 0 */
|
|
1165
|
+
for (i = 0; i < *mlen; ++i)
|
|
1166
|
+
__loop__(
|
|
1167
|
+
assigns(i, memory_slice(m, *mlen))
|
|
1168
|
+
invariant(i <= *mlen)
|
|
1169
|
+
decreases(*mlen - i)
|
|
1170
|
+
)
|
|
1171
|
+
{
|
|
1172
|
+
m[i] = sm[MLDSA_CRYPTO_BYTES + i];
|
|
1173
|
+
}
|
|
1174
|
+
}
|
|
1175
|
+
|
|
1176
|
+
cleanup:
|
|
1177
|
+
|
|
1178
|
+
if (ret != 0)
|
|
1179
|
+
{
|
|
1180
|
+
/* To be on the safe-side, we zeroize the message buffer. */
|
|
1181
|
+
*mlen = 0;
|
|
1182
|
+
mld_memset(m, 0, smlen);
|
|
1183
|
+
}
|
|
1184
|
+
|
|
1185
|
+
return ret;
|
|
1186
|
+
}
|
|
1187
|
+
|
|
1188
|
+
|
|
1189
|
+
MLD_MUST_CHECK_RETURN_VALUE
|
|
1190
|
+
MLD_EXTERNAL_API
|
|
1191
|
+
int mld_sign_signature_pre_hash_internal(
|
|
1192
|
+
uint8_t sig[MLDSA_CRYPTO_BYTES], size_t *siglen, const uint8_t *ph,
|
|
1193
|
+
size_t phlen, const uint8_t *ctx, size_t ctxlen,
|
|
1194
|
+
const uint8_t rnd[MLDSA_RNDBYTES],
|
|
1195
|
+
const uint8_t sk[MLDSA_CRYPTO_SECRETKEYBYTES], int hashalg,
|
|
1196
|
+
MLD_CONFIG_CONTEXT_PARAMETER_TYPE context)
|
|
1197
|
+
{
|
|
1198
|
+
MLD_ALIGN uint8_t pre[MLD_DOMAIN_SEPARATION_MAX_BYTES];
|
|
1199
|
+
size_t pre_len;
|
|
1200
|
+
int ret;
|
|
1201
|
+
|
|
1202
|
+
pre_len = mld_prepare_domain_separation_prefix(pre, ph, phlen, ctx, ctxlen,
|
|
1203
|
+
hashalg);
|
|
1204
|
+
if (pre_len == 0)
|
|
1205
|
+
{
|
|
1206
|
+
ret = MLD_ERR_FAIL;
|
|
1207
|
+
goto cleanup;
|
|
1208
|
+
}
|
|
1209
|
+
|
|
1210
|
+
ret = mld_sign_signature_internal(sig, siglen, pre, pre_len, NULL, 0, rnd, sk,
|
|
1211
|
+
0, context);
|
|
1212
|
+
cleanup:
|
|
1213
|
+
if (ret != 0)
|
|
1214
|
+
{
|
|
1215
|
+
/* To be on the safe-side, make sure *siglen and sig have a well-defined
|
|
1216
|
+
* value, even in the case of error.
|
|
1217
|
+
*
|
|
1218
|
+
* If we come from mld_sign_signature_internal, both are redundant,
|
|
1219
|
+
* but the error case should not be the norm, and the added cost of the
|
|
1220
|
+
* memset insignificant. */
|
|
1221
|
+
*siglen = 0;
|
|
1222
|
+
mld_memset(sig, 0, MLDSA_CRYPTO_BYTES);
|
|
1223
|
+
}
|
|
1224
|
+
|
|
1225
|
+
/* @[FIPS204, Section 3.6.3] Destruction of intermediate values. */
|
|
1226
|
+
mld_zeroize(pre, sizeof(pre));
|
|
1227
|
+
return ret;
|
|
1228
|
+
}
|
|
1229
|
+
|
|
1230
|
+
MLD_MUST_CHECK_RETURN_VALUE
|
|
1231
|
+
MLD_EXTERNAL_API
|
|
1232
|
+
int mld_sign_verify_pre_hash_internal(
|
|
1233
|
+
const uint8_t *sig, size_t siglen, const uint8_t *ph, size_t phlen,
|
|
1234
|
+
const uint8_t *ctx, size_t ctxlen,
|
|
1235
|
+
const uint8_t pk[MLDSA_CRYPTO_PUBLICKEYBYTES], int hashalg,
|
|
1236
|
+
MLD_CONFIG_CONTEXT_PARAMETER_TYPE context)
|
|
1237
|
+
{
|
|
1238
|
+
MLD_ALIGN uint8_t pre[MLD_DOMAIN_SEPARATION_MAX_BYTES];
|
|
1239
|
+
size_t pre_len;
|
|
1240
|
+
int ret;
|
|
1241
|
+
|
|
1242
|
+
pre_len = mld_prepare_domain_separation_prefix(pre, ph, phlen, ctx, ctxlen,
|
|
1243
|
+
hashalg);
|
|
1244
|
+
if (pre_len == 0)
|
|
1245
|
+
{
|
|
1246
|
+
ret = MLD_ERR_FAIL;
|
|
1247
|
+
goto cleanup;
|
|
1248
|
+
}
|
|
1249
|
+
|
|
1250
|
+
ret = mld_sign_verify_internal(sig, siglen, pre, pre_len, NULL, 0, pk, 0,
|
|
1251
|
+
context);
|
|
1252
|
+
|
|
1253
|
+
cleanup:
|
|
1254
|
+
/* @[FIPS204, Section 3.6.3] Destruction of intermediate values. */
|
|
1255
|
+
mld_zeroize(pre, sizeof(pre));
|
|
1256
|
+
return ret;
|
|
1257
|
+
}
|
|
1258
|
+
|
|
1259
|
+
MLD_MUST_CHECK_RETURN_VALUE
|
|
1260
|
+
MLD_EXTERNAL_API
|
|
1261
|
+
int mld_sign_signature_pre_hash_shake256(
|
|
1262
|
+
uint8_t sig[MLDSA_CRYPTO_BYTES], size_t *siglen, const uint8_t *m,
|
|
1263
|
+
size_t mlen, const uint8_t *ctx, size_t ctxlen,
|
|
1264
|
+
const uint8_t rnd[MLDSA_RNDBYTES],
|
|
1265
|
+
const uint8_t sk[MLDSA_CRYPTO_SECRETKEYBYTES],
|
|
1266
|
+
MLD_CONFIG_CONTEXT_PARAMETER_TYPE context)
|
|
1267
|
+
{
|
|
1268
|
+
MLD_ALIGN uint8_t ph[64];
|
|
1269
|
+
int ret;
|
|
1270
|
+
mld_shake256(ph, sizeof(ph), m, mlen);
|
|
1271
|
+
ret = mld_sign_signature_pre_hash_internal(sig, siglen, ph, sizeof(ph), ctx,
|
|
1272
|
+
ctxlen, rnd, sk,
|
|
1273
|
+
MLD_PREHASH_SHAKE_256, context);
|
|
1274
|
+
/* @[FIPS204, Section 3.6.3] Destruction of intermediate values. */
|
|
1275
|
+
mld_zeroize(ph, sizeof(ph));
|
|
1276
|
+
return ret;
|
|
1277
|
+
}
|
|
1278
|
+
|
|
1279
|
+
MLD_MUST_CHECK_RETURN_VALUE
|
|
1280
|
+
MLD_EXTERNAL_API
|
|
1281
|
+
int mld_sign_verify_pre_hash_shake256(
|
|
1282
|
+
const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen,
|
|
1283
|
+
const uint8_t *ctx, size_t ctxlen,
|
|
1284
|
+
const uint8_t pk[MLDSA_CRYPTO_PUBLICKEYBYTES],
|
|
1285
|
+
MLD_CONFIG_CONTEXT_PARAMETER_TYPE context)
|
|
1286
|
+
{
|
|
1287
|
+
MLD_ALIGN uint8_t ph[64];
|
|
1288
|
+
int ret;
|
|
1289
|
+
mld_shake256(ph, sizeof(ph), m, mlen);
|
|
1290
|
+
ret = mld_sign_verify_pre_hash_internal(sig, siglen, ph, sizeof(ph), ctx,
|
|
1291
|
+
ctxlen, pk, MLD_PREHASH_SHAKE_256,
|
|
1292
|
+
context);
|
|
1293
|
+
/* @[FIPS204, Section 3.6.3] Destruction of intermediate values. */
|
|
1294
|
+
mld_zeroize(ph, sizeof(ph));
|
|
1295
|
+
return ret;
|
|
1296
|
+
}
|
|
1297
|
+
|
|
1298
|
+
|
|
1299
|
+
#define MLD_PRE_HASH_OID_LEN 11
|
|
1300
|
+
|
|
1301
|
+
/*************************************************
|
|
1302
|
+
* Name: mld_get_hash_oid
|
|
1303
|
+
*
|
|
1304
|
+
* Description: Returns the OID of a given SHA-2/SHA-3 hash function.
|
|
1305
|
+
*
|
|
1306
|
+
* Arguments: - uint8_t oid[11]: pointer to output oid
|
|
1307
|
+
* - int hashalg: hash algorithm constant (MLD_PREHASH_*)
|
|
1308
|
+
*
|
|
1309
|
+
***************************************************/
|
|
1310
|
+
static void mld_get_hash_oid(uint8_t oid[MLD_PRE_HASH_OID_LEN], int hashalg)
|
|
1311
|
+
{
|
|
1312
|
+
unsigned int i;
|
|
1313
|
+
static const struct
|
|
1314
|
+
{
|
|
1315
|
+
int alg;
|
|
1316
|
+
uint8_t oid[MLD_PRE_HASH_OID_LEN];
|
|
1317
|
+
} oid_map[] = {
|
|
1318
|
+
{MLD_PREHASH_SHA2_224,
|
|
1319
|
+
{0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04}},
|
|
1320
|
+
{MLD_PREHASH_SHA2_256,
|
|
1321
|
+
{0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01}},
|
|
1322
|
+
{MLD_PREHASH_SHA2_384,
|
|
1323
|
+
{0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02}},
|
|
1324
|
+
{MLD_PREHASH_SHA2_512,
|
|
1325
|
+
{0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03}},
|
|
1326
|
+
{MLD_PREHASH_SHA2_512_224,
|
|
1327
|
+
{0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x05}},
|
|
1328
|
+
{MLD_PREHASH_SHA2_512_256,
|
|
1329
|
+
{0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x06}},
|
|
1330
|
+
{MLD_PREHASH_SHA3_224,
|
|
1331
|
+
{0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x07}},
|
|
1332
|
+
{MLD_PREHASH_SHA3_256,
|
|
1333
|
+
{0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x08}},
|
|
1334
|
+
{MLD_PREHASH_SHA3_384,
|
|
1335
|
+
{0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x09}},
|
|
1336
|
+
{MLD_PREHASH_SHA3_512,
|
|
1337
|
+
{0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x0A}},
|
|
1338
|
+
{MLD_PREHASH_SHAKE_128,
|
|
1339
|
+
{0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x0B}},
|
|
1340
|
+
{MLD_PREHASH_SHAKE_256,
|
|
1341
|
+
{0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x0C}}};
|
|
1342
|
+
|
|
1343
|
+
for (i = 0; i < sizeof(oid_map) / sizeof(oid_map[0]); i++)
|
|
1344
|
+
__loop__(
|
|
1345
|
+
invariant(i <= sizeof(oid_map) / sizeof(oid_map[0]))
|
|
1346
|
+
decreases(sizeof(oid_map) / sizeof(oid_map[0]) - i)
|
|
1347
|
+
)
|
|
1348
|
+
{
|
|
1349
|
+
if (oid_map[i].alg == hashalg)
|
|
1350
|
+
{
|
|
1351
|
+
mld_memcpy(oid, oid_map[i].oid, MLD_PRE_HASH_OID_LEN);
|
|
1352
|
+
return;
|
|
1353
|
+
}
|
|
1354
|
+
}
|
|
1355
|
+
}
|
|
1356
|
+
|
|
1357
|
+
static int mld_validate_hash_length(int hashalg, size_t len)
|
|
1358
|
+
{
|
|
1359
|
+
switch (hashalg)
|
|
1360
|
+
{
|
|
1361
|
+
case MLD_PREHASH_SHA2_224:
|
|
1362
|
+
return (len == 224 / 8) ? 0 : -1;
|
|
1363
|
+
case MLD_PREHASH_SHA2_256:
|
|
1364
|
+
return (len == 256 / 8) ? 0 : -1;
|
|
1365
|
+
case MLD_PREHASH_SHA2_384:
|
|
1366
|
+
return (len == 384 / 8) ? 0 : -1;
|
|
1367
|
+
case MLD_PREHASH_SHA2_512:
|
|
1368
|
+
return (len == 512 / 8) ? 0 : -1;
|
|
1369
|
+
case MLD_PREHASH_SHA2_512_224:
|
|
1370
|
+
return (len == 224 / 8) ? 0 : -1;
|
|
1371
|
+
case MLD_PREHASH_SHA2_512_256:
|
|
1372
|
+
return (len == 256 / 8) ? 0 : -1;
|
|
1373
|
+
case MLD_PREHASH_SHA3_224:
|
|
1374
|
+
return (len == 224 / 8) ? 0 : -1;
|
|
1375
|
+
case MLD_PREHASH_SHA3_256:
|
|
1376
|
+
return (len == 256 / 8) ? 0 : -1;
|
|
1377
|
+
case MLD_PREHASH_SHA3_384:
|
|
1378
|
+
return (len == 384 / 8) ? 0 : -1;
|
|
1379
|
+
case MLD_PREHASH_SHA3_512:
|
|
1380
|
+
return (len == 512 / 8) ? 0 : -1;
|
|
1381
|
+
case MLD_PREHASH_SHAKE_128:
|
|
1382
|
+
return (len == 256 / 8) ? 0 : -1;
|
|
1383
|
+
case MLD_PREHASH_SHAKE_256:
|
|
1384
|
+
return (len == 512 / 8) ? 0 : -1;
|
|
1385
|
+
}
|
|
1386
|
+
return -1;
|
|
1387
|
+
}
|
|
1388
|
+
|
|
1389
|
+
size_t mld_prepare_domain_separation_prefix(
|
|
1390
|
+
uint8_t prefix[MLD_DOMAIN_SEPARATION_MAX_BYTES], const uint8_t *ph,
|
|
1391
|
+
size_t phlen, const uint8_t *ctx, size_t ctxlen, int hashalg)
|
|
1392
|
+
{
|
|
1393
|
+
if (ctxlen > 255)
|
|
1394
|
+
{
|
|
1395
|
+
return 0;
|
|
1396
|
+
}
|
|
1397
|
+
|
|
1398
|
+
if (hashalg != MLD_PREHASH_NONE)
|
|
1399
|
+
{
|
|
1400
|
+
if (ph == NULL || mld_validate_hash_length(hashalg, phlen) != 0)
|
|
1401
|
+
{
|
|
1402
|
+
return 0;
|
|
1403
|
+
}
|
|
1404
|
+
}
|
|
1405
|
+
|
|
1406
|
+
/* Common prefix: 0x00/0x01 || ctxlen || ctx */
|
|
1407
|
+
prefix[0] = (hashalg == MLD_PREHASH_NONE) ? 0 : 1;
|
|
1408
|
+
prefix[1] = (uint8_t)ctxlen;
|
|
1409
|
+
if (ctxlen > 0)
|
|
1410
|
+
{
|
|
1411
|
+
mld_memcpy(prefix + 2, ctx, ctxlen);
|
|
1412
|
+
}
|
|
1413
|
+
|
|
1414
|
+
if (hashalg == MLD_PREHASH_NONE)
|
|
1415
|
+
{
|
|
1416
|
+
return 2 + ctxlen;
|
|
1417
|
+
}
|
|
1418
|
+
|
|
1419
|
+
/* HashML-DSA: append oid || ph */
|
|
1420
|
+
mld_get_hash_oid(prefix + 2 + ctxlen, hashalg);
|
|
1421
|
+
mld_memcpy(prefix + 2 + ctxlen + MLD_PRE_HASH_OID_LEN, ph, phlen);
|
|
1422
|
+
return 2 + ctxlen + MLD_PRE_HASH_OID_LEN + phlen;
|
|
1423
|
+
}
|
|
1424
|
+
|
|
1425
|
+
MLD_EXTERNAL_API
|
|
1426
|
+
int mld_sign_pk_from_sk(uint8_t pk[MLDSA_CRYPTO_PUBLICKEYBYTES],
|
|
1427
|
+
const uint8_t sk[MLDSA_CRYPTO_SECRETKEYBYTES],
|
|
1428
|
+
MLD_CONFIG_CONTEXT_PARAMETER_TYPE context)
|
|
1429
|
+
{
|
|
1430
|
+
uint8_t check, cmp0, cmp1, chk1, chk2;
|
|
1431
|
+
int ret;
|
|
1432
|
+
MLD_ALLOC(rho, uint8_t, MLDSA_SEEDBYTES, context);
|
|
1433
|
+
MLD_ALLOC(tr, uint8_t, MLDSA_TRBYTES, context);
|
|
1434
|
+
MLD_ALLOC(tr_computed, uint8_t, MLDSA_TRBYTES, context);
|
|
1435
|
+
MLD_ALLOC(key, uint8_t, MLDSA_SEEDBYTES, context);
|
|
1436
|
+
MLD_ALLOC(s1, mld_polyvecl, 1, context);
|
|
1437
|
+
MLD_ALLOC(s2, mld_polyveck, 1, context);
|
|
1438
|
+
MLD_ALLOC(t0, mld_polyveck, 1, context);
|
|
1439
|
+
MLD_ALLOC(t0_computed, mld_polyveck, 1, context);
|
|
1440
|
+
MLD_ALLOC(t1, mld_polyveck, 1, context);
|
|
1441
|
+
|
|
1442
|
+
if (rho == NULL || tr == NULL || tr_computed == NULL || key == NULL ||
|
|
1443
|
+
s1 == NULL || s2 == NULL || t0 == NULL || t0_computed == NULL ||
|
|
1444
|
+
t1 == NULL)
|
|
1445
|
+
{
|
|
1446
|
+
ret = MLD_ERR_OUT_OF_MEMORY;
|
|
1447
|
+
goto cleanup;
|
|
1448
|
+
}
|
|
1449
|
+
|
|
1450
|
+
/* Unpack secret key */
|
|
1451
|
+
mld_unpack_sk(rho, tr, key, t0, s1, s2, sk);
|
|
1452
|
+
|
|
1453
|
+
/* Validate s1 and s2 coefficients are within [-MLDSA_ETA, MLDSA_ETA] */
|
|
1454
|
+
chk1 = mld_polyvecl_chknorm(s1, MLDSA_ETA + 1) & 0xFF;
|
|
1455
|
+
chk2 = mld_polyveck_chknorm(s2, MLDSA_ETA + 1) & 0xFF;
|
|
1456
|
+
|
|
1457
|
+
/* Recompute t0, t1, tr, and pk from rho, s1, s2 */
|
|
1458
|
+
ret = mld_compute_t0_t1_tr_from_sk_components(t0_computed, t1, tr_computed,
|
|
1459
|
+
pk, rho, s1, s2, context);
|
|
1460
|
+
if (ret != 0)
|
|
1461
|
+
{
|
|
1462
|
+
goto cleanup;
|
|
1463
|
+
}
|
|
1464
|
+
|
|
1465
|
+
/* Validate t0 and tr using constant-time comparisons */
|
|
1466
|
+
cmp0 = mld_ct_memcmp((const uint8_t *)t0, (const uint8_t *)t0_computed,
|
|
1467
|
+
sizeof(mld_polyveck));
|
|
1468
|
+
cmp1 = mld_ct_memcmp((const uint8_t *)tr, (const uint8_t *)tr_computed,
|
|
1469
|
+
MLDSA_TRBYTES);
|
|
1470
|
+
check = mld_value_barrier_u8(cmp0 | cmp1 | chk1 | chk2);
|
|
1471
|
+
|
|
1472
|
+
/* Declassify the final result of the validity check. */
|
|
1473
|
+
MLD_CT_TESTING_DECLASSIFY(&check, sizeof(check));
|
|
1474
|
+
ret = (check != 0) ? MLD_ERR_FAIL : 0;
|
|
1475
|
+
|
|
1476
|
+
cleanup:
|
|
1477
|
+
|
|
1478
|
+
if (ret != 0)
|
|
1479
|
+
{
|
|
1480
|
+
mld_zeroize(pk, MLDSA_CRYPTO_PUBLICKEYBYTES);
|
|
1481
|
+
}
|
|
1482
|
+
|
|
1483
|
+
/* Constant time: pk is either the valid public key or zeroed on error */
|
|
1484
|
+
MLD_CT_TESTING_DECLASSIFY(pk, MLDSA_CRYPTO_PUBLICKEYBYTES);
|
|
1485
|
+
|
|
1486
|
+
/* @[FIPS204, Section 3.6.3] Destruction of intermediate values. */
|
|
1487
|
+
MLD_FREE(t1, mld_polyveck, 1, context);
|
|
1488
|
+
MLD_FREE(t0_computed, mld_polyveck, 1, context);
|
|
1489
|
+
MLD_FREE(t0, mld_polyveck, 1, context);
|
|
1490
|
+
MLD_FREE(s2, mld_polyveck, 1, context);
|
|
1491
|
+
MLD_FREE(s1, mld_polyvecl, 1, context);
|
|
1492
|
+
MLD_FREE(key, uint8_t, MLDSA_SEEDBYTES, context);
|
|
1493
|
+
MLD_FREE(tr_computed, uint8_t, MLDSA_TRBYTES, context);
|
|
1494
|
+
MLD_FREE(tr, uint8_t, MLDSA_TRBYTES, context);
|
|
1495
|
+
MLD_FREE(rho, uint8_t, MLDSA_SEEDBYTES, context);
|
|
1496
|
+
|
|
1497
|
+
return ret;
|
|
1498
|
+
}
|
|
1499
|
+
|
|
1500
|
+
/* To facilitate single-compilation-unit (SCU) builds, undefine all macros.
|
|
1501
|
+
* Don't modify by hand -- this is auto-generated by scripts/autogen. */
|
|
1502
|
+
#undef mld_check_pct
|
|
1503
|
+
#undef mld_sample_s1_s2
|
|
1504
|
+
#undef mld_validate_hash_length
|
|
1505
|
+
#undef mld_get_hash_oid
|
|
1506
|
+
#undef mld_H
|
|
1507
|
+
#undef mld_compute_pack_z
|
|
1508
|
+
#undef mld_attempt_signature_generation
|
|
1509
|
+
#undef mld_compute_t0_t1_tr_from_sk_components
|
|
1510
|
+
#undef MLD_NONCE_UB
|
|
1511
|
+
#undef MLD_PRE_HASH_OID_LEN
|