Botan 3.6.0
Crypto and TLS for C&
Botan::Dilithium_Algos Namespace Reference

Functions

std::pair< DilithiumSeedRho, DilithiumPolyVecdecode_public_key (StrongSpan< const DilithiumSerializedPublicKey > pk, const DilithiumConstants &mode)
 
std::optional< std::tuple< DilithiumCommitmentHash, DilithiumPolyVec, DilithiumPolyVec > > decode_signature (StrongSpan< const DilithiumSerializedSignature > sig, const DilithiumConstants &mode)
 
std::pair< DilithiumPolyVec, DilithiumPolyVecdecompose (const DilithiumPolyVec &vec, const DilithiumConstants &mode)
 
DilithiumSerializedCommitment encode_commitment (const DilithiumPolyVec &w1, const DilithiumConstants &mode)
 
DilithiumSerializedPublicKey encode_public_key (StrongSpan< const DilithiumSeedRho > rho, const DilithiumPolyVec &t1, const DilithiumConstants &mode)
 
DilithiumSerializedSignature encode_signature (StrongSpan< const DilithiumCommitmentHash > c, const DilithiumPolyVec &response, const DilithiumPolyVec &hint, const DilithiumConstants &mode)
 
DilithiumPolyMatNTT expand_A (StrongSpan< const DilithiumSeedRho > rho, const DilithiumConstants &mode)
 
DilithiumInternalKeypair expand_keypair (DilithiumSeedRandomness xi, DilithiumConstants mode)
 
DilithiumPolyVec expand_mask (StrongSpan< const DilithiumSeedRhoPrime > rhoprime, uint16_t nonce, const DilithiumConstants &mode)
 
std::pair< DilithiumPolyVec, DilithiumPolyVecexpand_s (StrongSpan< const DilithiumSeedRhoPrime > rhoprime, const DilithiumConstants &mode)
 
bool infinity_norm_within_bound (const DilithiumPolyVec &vec, size_t bound)
 
DilithiumPolyVec make_hint (const DilithiumPolyVec &z, const DilithiumPolyVec &r, const DilithiumConstants &mode)
 
std::pair< DilithiumPolyVec, DilithiumPolyVecpower2round (const DilithiumPolyVec &vec)
 
DilithiumPoly sample_in_ball (StrongSpan< const DilithiumCommitmentHash > seed, const DilithiumConstants &mode)
 
void use_hint (DilithiumPolyVec &vec, const DilithiumPolyVec &hints, const DilithiumConstants &mode)
 

Function Documentation

◆ decode_public_key()

std::pair< DilithiumSeedRho, DilithiumPolyVec > Botan::Dilithium_Algos::decode_public_key ( StrongSpan< const DilithiumSerializedPublicKey > pk,
const DilithiumConstants & mode )

NIST FIPS 204, Algorithm 23 (pkDecode)

Definition at line 345 of file dilithium_algos.cpp.

346 {
347 if(pk.size() != mode.public_key_bytes()) {
348 throw Decoding_Error("Dilithium: Invalid public key length");
349 }
350
351 BufferSlicer slicer(pk);
352 auto rho = slicer.copy<DilithiumSeedRho>(DilithiumConstants::SEED_RHO_BYTES);
353
354 DilithiumPolyVec t1(mode.k());
355 for(auto& p : t1) {
356 poly_unpack_t1(p, slicer);
357 }
358 BOTAN_ASSERT_NOMSG(slicer.empty());
359
360 return {std::move(rho), std::move(t1)};
361}
#define BOTAN_ASSERT_NOMSG(expr)
Definition assert.h:59
size_t public_key_bytes() const
byte length of the encoded public key
uint8_t k() const
dimensions of the expanded matrix A
decltype(auto) size() const noexcept(noexcept(this->m_span.size()))
constexpr T rho(T x)
Definition rotate.h:51

References BOTAN_ASSERT_NOMSG, Botan::BufferSlicer::copy(), Botan::BufferSlicer::empty(), Botan::DilithiumConstants::k(), Botan::DilithiumConstants::public_key_bytes(), Botan::rho(), Botan::DilithiumConstants::SEED_RHO_BYTES, and Botan::StrongSpan< T >::size().

Referenced by Botan::Dilithium_PublicKeyInternal::decode().

◆ decode_signature()

std::optional< std::tuple< DilithiumCommitmentHash, DilithiumPolyVec, DilithiumPolyVec > > Botan::Dilithium_Algos::decode_signature ( StrongSpan< const DilithiumSerializedSignature > sig,
const DilithiumConstants & mode )

NIST FIPS 204, Algorithm 27 (sigDecode)

Definition at line 493 of file dilithium_algos.cpp.

494 {
495 BufferSlicer slicer(sig);
496 BOTAN_ASSERT_NOMSG(slicer.remaining() == mode.signature_bytes());
497
498 auto commitment_hash = slicer.copy<DilithiumCommitmentHash>(mode.commitment_hash_full_bytes());
499
500 DilithiumPolyVec response(mode.l());
501 for(auto& p : response) {
502 poly_unpack_gamma1(p, slicer, mode);
503 }
504 BOTAN_ASSERT_NOMSG(slicer.remaining() == mode.omega() + mode.k());
505
506 auto hint = hint_unpack(slicer, mode);
507 BOTAN_ASSERT_NOMSG(slicer.empty());
508 if(!hint.has_value()) {
509 return std::nullopt;
510 }
511
512 return std::make_tuple(std::move(commitment_hash), std::move(response), std::move(hint.value()));
513}
size_t commitment_hash_full_bytes() const
length of the entire commitment hash 'c~' in bytes (differs between R3 and ML-DSA)
size_t signature_bytes() const
byte length of the encoded signature
uint8_t l() const
dimensions of the expanded matrix A
DilithiumOmega omega() const
maximal hamming weight of the hint polynomial vector 'h'

References BOTAN_ASSERT_NOMSG, Botan::DilithiumConstants::commitment_hash_full_bytes(), Botan::BufferSlicer::copy(), Botan::BufferSlicer::empty(), Botan::DilithiumConstants::k(), Botan::DilithiumConstants::l(), Botan::DilithiumConstants::omega(), Botan::BufferSlicer::remaining(), and Botan::DilithiumConstants::signature_bytes().

◆ decompose()

std::pair< DilithiumPolyVec, DilithiumPolyVec > Botan::Dilithium_Algos::decompose ( const DilithiumPolyVec & vec,
const DilithiumConstants & mode )

NIST FIPS 204, Algorithm 36 (Decompose) on a polynomial vector

Algorithms 37 (HighBits) and 38 (LowBits) are not implemented explicitly, simply use the first (HighBits) and second (LowBits) element of the result.

Definition at line 819 of file dilithium_algos.cpp.

819 {
821 switch(mode.gamma2()) {
822 case Gamma2::Qminus1DevidedBy32:
823 return decompose_all_coefficents<Gamma2::Qminus1DevidedBy32>(vec);
824 break;
825 case Gamma2::Qminus1DevidedBy88:
826 return decompose_all_coefficents<Gamma2::Qminus1DevidedBy88>(vec);
827 break;
828 }
829
831}
#define BOTAN_ASSERT_UNREACHABLE()
Definition assert.h:137
DilithiumGamma2 gamma2() const
low-order rounding range for decomposing the commitment from polynomial vector 'w'

References BOTAN_ASSERT_UNREACHABLE, and Botan::DilithiumConstants::gamma2().

◆ encode_commitment()

DilithiumSerializedCommitment Botan::Dilithium_Algos::encode_commitment ( const DilithiumPolyVec & w1,
const DilithiumConstants & mode )

NIST FIPS 204, Algorithm 28 (w1Encode)

Definition at line 518 of file dilithium_algos.cpp.

518 {
520 BufferStuffer stuffer(commitment);
521
522 for(const auto& p : w1) {
523 poly_pack_w1(p, stuffer, mode);
524 }
525
526 return commitment;
527}
Helper class to ease in-place marshalling of concatenated fixed-length values.
Definition stl_util.h:142
size_t serialized_commitment_bytes() const
byte length of the packed commitment polynomial vector 'w1'

References Botan::DilithiumConstants::serialized_commitment_bytes().

◆ encode_public_key()

DilithiumSerializedPublicKey Botan::Dilithium_Algos::encode_public_key ( StrongSpan< const DilithiumSeedRho > rho,
const DilithiumPolyVec & t1,
const DilithiumConstants & mode )

NIST FIPS 204, Algorithm 22 (pkEncode)

Definition at line 327 of file dilithium_algos.cpp.

329 {
331 BufferStuffer stuffer(pk);
332
333 stuffer.append(rho);
334 for(const auto& p : t1) {
335 poly_pack_t1(p, stuffer);
336 }
337
338 BOTAN_ASSERT_NOMSG(stuffer.full());
339 return pk;
340}

References Botan::BufferStuffer::append(), BOTAN_ASSERT_NOMSG, Botan::BufferStuffer::full(), Botan::DilithiumConstants::public_key_bytes(), and Botan::rho().

Referenced by Botan::Dilithium_PublicKeyInternal::raw_pk().

◆ encode_signature()

DilithiumSerializedSignature Botan::Dilithium_Algos::encode_signature ( StrongSpan< const DilithiumCommitmentHash > c,
const DilithiumPolyVec & response,
const DilithiumPolyVec & hint,
const DilithiumConstants & mode )

NIST FIPS 204, Algorithm 26 (sigEncode)

Definition at line 474 of file dilithium_algos.cpp.

477 {
479 BufferStuffer stuffer(sig);
480
481 stuffer.append(c);
482 for(const auto& p : response) {
483 poly_pack_gamma1(p, stuffer, mode);
484 }
485 hint_pack(hint, stuffer, mode);
486
487 return sig;
488}

References Botan::BufferStuffer::append(), and Botan::DilithiumConstants::signature_bytes().

◆ expand_A()

DilithiumPolyMatNTT Botan::Dilithium_Algos::expand_A ( StrongSpan< const DilithiumSeedRho > rho,
const DilithiumConstants & mode )

NIST FIPS 204, Algorithm 32 (ExpandA)

Note that the actual concatenation of rho, s and r is done downstream in the sampling function.

Definition at line 695 of file dilithium_algos.cpp.

695 {
696 DilithiumPolyMatNTT A(mode.k(), mode.l());
697 for(uint8_t r = 0; r < mode.k(); ++r) {
698 for(uint8_t s = 0; s < mode.l(); ++s) {
699 sample_ntt_uniform(rho, A[r][s], load_le(std::array{s, r}), mode);
700 }
701 }
702 return A;
703}
constexpr auto load_le(ParamTs &&... params)
Definition loadstor.h:521

References Botan::DilithiumConstants::k(), Botan::DilithiumConstants::l(), Botan::load_le(), and Botan::rho().

Referenced by expand_keypair().

◆ expand_keypair()

DilithiumInternalKeypair Botan::Dilithium_Algos::expand_keypair ( DilithiumSeedRandomness xi,
DilithiumConstants mode )

NIST FIPS 204, Algorithm 6 (ML-DSA.KeyGen_internal)

Lines 5-7 are extracted into a separate function, see above. The key encoding is deferred until the user explicitly invokes the encoding.

Definition at line 665 of file dilithium_algos.cpp.

665 {
666 const auto& sympriv = mode.symmetric_primitives();
667 CT::poison(xi);
668
669 auto [rho, rhoprime, K] = sympriv.H(xi);
670 CT::unpoison(rho); // rho is public (seed for the public matrix A)
671
672 const auto A = Dilithium_Algos::expand_A(rho, mode);
673 auto [s1, s2] = Dilithium_Algos::expand_s(rhoprime, mode);
674 auto [t1, t0] = Dilithium_Algos::compute_t1_and_t0(A, s1, s2);
675
676 CT::unpoison(t1); // part of the public key
677
679 std::make_shared<Dilithium_PublicKeyInternal>(mode, std::move(rho), std::move(t1)),
680 std::make_shared<Dilithium_PrivateKeyInternal>(
681 std::move(mode), std::move(xi), std::move(K), std::move(s1), std::move(s2), std::move(t0)),
682 };
683
684 CT::unpoison(*keypair.second);
685
686 return keypair;
687};
Dilithium_Symmetric_Primitives_Base & symmetric_primitives() const
std::pair< std::shared_ptr< Dilithium_PublicKeyInternal >, std::shared_ptr< Dilithium_PrivateKeyInternal > > DilithiumInternalKeypair
Internal representation of a Dilithium key pair.

References expand_A(), expand_s(), Botan::CT::poison(), Botan::rho(), Botan::DilithiumConstants::symmetric_primitives(), and Botan::CT::unpoison().

Referenced by Botan::ML_DSA_Expanding_Keypair_Codec::decode_keypair(), and Botan::Dilithium_PrivateKey::Dilithium_PrivateKey().

◆ expand_mask()

DilithiumPolyVec Botan::Dilithium_Algos::expand_mask ( StrongSpan< const DilithiumSeedRhoPrime > rhoprime,
uint16_t nonce,
const DilithiumConstants & mode )

NIST FIPS 204, Algorithm 34 (ExpandMask)

Definition at line 728 of file dilithium_algos.cpp.

730 {
731 DilithiumPolyVec s(mode.l());
732 for(auto& p : s) {
733 auto& xof = mode.symmetric_primitives().H(rhoprime, nonce++);
734 poly_unpack_gamma1(p, xof, mode);
735 }
736 return s;
737}
DilithiumHashedPublicKey H(StrongSpan< const DilithiumSerializedPublicKey > pk) const

References Botan::Dilithium_Symmetric_Primitives_Base::H(), Botan::DilithiumConstants::l(), and Botan::DilithiumConstants::symmetric_primitives().

◆ expand_s()

std::pair< DilithiumPolyVec, DilithiumPolyVec > Botan::Dilithium_Algos::expand_s ( StrongSpan< const DilithiumSeedRhoPrime > rhoprime,
const DilithiumConstants & mode )

NIST FIPS 204, Algorithm 33 (ExpandS)

Definition at line 708 of file dilithium_algos.cpp.

709 {
710 auto result = std::make_pair(DilithiumPolyVec(mode.l()), DilithiumPolyVec(mode.k()));
711 auto& [s1, s2] = result;
712
713 uint16_t nonce = 0;
714 for(auto& p : s1) {
715 sample_uniform_eta(rhoprime, p, nonce++, mode);
716 }
717
718 for(auto& p : s2) {
719 sample_uniform_eta(rhoprime, p, nonce++, mode);
720 }
721
722 return result;
723}

References Botan::DilithiumConstants::k(), and Botan::DilithiumConstants::l().

Referenced by expand_keypair().

◆ infinity_norm_within_bound()

bool Botan::Dilithium_Algos::infinity_norm_within_bound ( const DilithiumPolyVec & vec,
size_t bound )

Definition at line 936 of file dilithium_algos.cpp.

936 {
937 BOTAN_DEBUG_ASSERT(bound <= (DilithiumConstants::Q - 1) / 8);
938
939 // It is ok to leak which coefficient violates the bound as the probability
940 // for each coefficient is independent of secret data but we must not leak
941 // the sign of the centralized representative.
942 for(const auto& p : vec) {
943 for(auto c : p) {
944 const auto abs_c = c - is_negative_mask(c).if_set_return(2 * c);
945 if(CT::driveby_unpoison(abs_c >= bound)) {
946 return false;
947 }
948 }
949 }
950
951 return true;
952}
#define BOTAN_DEBUG_ASSERT(expr)
Definition assert.h:98

References BOTAN_DEBUG_ASSERT, Botan::CT::driveby_unpoison(), and Botan::DilithiumConstants::Q.

◆ make_hint()

DilithiumPolyVec Botan::Dilithium_Algos::make_hint ( const DilithiumPolyVec & z,
const DilithiumPolyVec & r,
const DilithiumConstants & mode )

NIST FIPS 204, Algorithm 39 (MakeHint)

MakeHint is specified per value in FIPS 204. This implements the algorithm for the entire polynomial vector. The specified algorithm is equivalent to the inner lambda.

TODO: This is taken from the reference implementation. We should implement it as specified in the spec, and see if that has any performance impact.

Definition at line 843 of file dilithium_algos.cpp.

843 {
844 BOTAN_DEBUG_ASSERT(z.size() == r.size());
845
846 auto make_hint = [gamma2 = uint32_t(mode.gamma2()),
847 q_gamma2 = static_cast<uint32_t>(DilithiumConstants::Q) - uint32_t(mode.gamma2())](
848 int32_t c0, int32_t c1) -> CT::Choice {
849 BOTAN_DEBUG_ASSERT(c0 >= 0);
850 BOTAN_DEBUG_ASSERT(c1 >= 0);
851
852 const uint32_t pc0 = static_cast<uint32_t>(c0);
853 const uint32_t pc1 = static_cast<uint32_t>(c1);
854
855 return (CT::Mask<uint32_t>::is_gt(pc0, gamma2) & CT::Mask<uint32_t>::is_lte(pc0, q_gamma2) &
857 .as_choice();
858 };
859
860 DilithiumPolyVec hint(r.size());
861
862 for(size_t i = 0; i < r.size(); ++i) {
863 for(size_t j = 0; j < r[i].size(); ++j) {
864 hint[i][j] = make_hint(z[i][j], r[i][j]).as_bool();
865 }
866 }
867
868 BOTAN_DEBUG_ASSERT(hint.ct_validate_value_range(0, 1));
869
870 return hint;
871}
DilithiumPolyVec make_hint(const DilithiumPolyVec &z, const DilithiumPolyVec &r, const DilithiumConstants &mode)

References BOTAN_DEBUG_ASSERT, Botan::CRYSTALS::PolynomialVector< Trait, D >::ct_validate_value_range(), Botan::DilithiumConstants::gamma2(), make_hint(), Botan::DilithiumConstants::Q, and Botan::CRYSTALS::PolynomialVector< Trait, D >::size().

Referenced by make_hint().

◆ power2round()

std::pair< DilithiumPolyVec, DilithiumPolyVec > Botan::Dilithium_Algos::power2round ( const DilithiumPolyVec & vec)

NIST FIPS 204, Algorithm 35 (Power2Round)

In contrast to the spec, this function takes a polynomial vector and performs the power2round operation on each coefficient in the vector. The actual Algorithm 35 as specified is actually just the inner lambda.

Definition at line 746 of file dilithium_algos.cpp.

746 {
747 // This procedure is taken verbatim from Dilithium's reference implementation.
748 auto power2round = [d = DilithiumConstants::D](int32_t r) -> std::pair<int32_t, int32_t> {
749 const int32_t r1 = (r + (1 << (d - 1)) - 1) >> d;
750 const int32_t r0 = r - (r1 << d);
751 return {r1, r0};
752 };
753
754 auto result = std::make_pair(DilithiumPolyVec(vec.size()), DilithiumPolyVec(vec.size()));
755
756 for(size_t i = 0; i < vec.size(); ++i) {
757 for(size_t j = 0; j < vec[i].size(); ++j) {
758 std::tie(result.first[i][j], result.second[i][j]) = power2round(vec[i][j]);
759 }
760 }
761
762 return result;
763}
std::pair< DilithiumPolyVec, DilithiumPolyVec > power2round(const DilithiumPolyVec &vec)

References Botan::DilithiumConstants::D, power2round(), and Botan::CRYSTALS::PolynomialVector< Trait, D >::size().

Referenced by power2round().

◆ sample_in_ball()

DilithiumPoly Botan::Dilithium_Algos::sample_in_ball ( StrongSpan< const DilithiumCommitmentHash > seed,
const DilithiumConstants & mode )

NIST FIPS 204, Algorithm 29 (SampleInBall)

Definition at line 532 of file dilithium_algos.cpp.

532 {
533 // This generator resembles the while loop in the spec.
534 auto& xof = mode.symmetric_primitives().H(seed);
536
538 uint64_t signs = load_le(bounded_xof.next<8>());
539 for(size_t i = c.size() - mode.tau(); i < c.size(); ++i) {
540 const auto j = bounded_xof.next_byte([i](uint8_t byte) { return byte <= i; });
541 c[i] = c[j];
542 c[j] = 1 - 2 * (signs & 1);
543 signs >>= 1;
544 }
545
548
549 return c;
550}
constexpr size_t hamming_weight() const noexcept
Definition pqcrystals.h:292
constexpr size_t size() const
Definition pqcrystals.h:274
constexpr bool ct_validate_value_range(T min, T max) const noexcept
Definition pqcrystals.h:287
DilithiumTau tau() const
hamming weight of the polynomial 'c' sampled from the commitment's hash

References BOTAN_DEBUG_ASSERT, Botan::CRYSTALS::Polynomial< Trait, D >::ct_validate_value_range(), Botan::Dilithium_Symmetric_Primitives_Base::H(), Botan::CRYSTALS::Polynomial< Trait, D >::hamming_weight(), Botan::load_le(), Botan::CRYSTALS::Polynomial< Trait, D >::size(), Botan::DilithiumConstants::symmetric_primitives(), and Botan::DilithiumConstants::tau().

◆ use_hint()

void Botan::Dilithium_Algos::use_hint ( DilithiumPolyVec & vec,
const DilithiumPolyVec & hints,
const DilithiumConstants & mode )

NIST FIPS 204, Algorithm 40 (UseHint)

UseHint is specified per value in FIPS 204. This implements the algorithm for the entire polynomial vector. The specified algorithm is equivalent to the inner lambdas of 'use_hint_with_coefficients'.

Definition at line 918 of file dilithium_algos.cpp.

918 {
919 BOTAN_DEBUG_ASSERT(hints.size() == vec.size());
921 BOTAN_DEBUG_ASSERT(vec.ct_validate_value_range(0, DilithiumConstants::Q - 1));
922
924 switch(mode.gamma2()) {
925 case Gamma2::Qminus1DevidedBy32:
926 use_hint_on_coefficients<Gamma2::Qminus1DevidedBy32>(hints, vec);
927 break;
928 case Gamma2::Qminus1DevidedBy88:
929 use_hint_on_coefficients<Gamma2::Qminus1DevidedBy88>(hints, vec);
930 break;
931 }
932
933 BOTAN_DEBUG_ASSERT(vec.ct_validate_value_range(0, (DilithiumConstants::Q - 1) / (2 * mode.gamma2())));
934}
constexpr bool ct_validate_value_range(T min, T max) const noexcept
Definition pqcrystals.h:436

References BOTAN_DEBUG_ASSERT, Botan::CRYSTALS::PolynomialVector< Trait, D >::ct_validate_value_range(), Botan::DilithiumConstants::gamma2(), Botan::DilithiumConstants::Q, and Botan::CRYSTALS::PolynomialVector< Trait, D >::size().