/src/botan/src/lib/pubkey/rfc6979/rfc6979.cpp
Line | Count | Source |
1 | | /* |
2 | | * RFC 6979 Deterministic Nonce Generator |
3 | | * (C) 2014,2015,2024 Jack Lloyd |
4 | | * |
5 | | * Botan is released under the Simplified BSD License (see license.txt) |
6 | | */ |
7 | | |
8 | | #include <botan/internal/rfc6979.h> |
9 | | |
10 | | #include <botan/assert.h> |
11 | | #include <botan/hmac_drbg.h> |
12 | | #include <botan/mac.h> |
13 | | #include <botan/internal/fmt.h> |
14 | | |
15 | | namespace Botan { |
16 | | |
17 | 0 | RFC6979_Nonce_Generator::RFC6979_Nonce_Generator(RFC6979_Nonce_Generator&& other) noexcept = default; |
18 | 0 | RFC6979_Nonce_Generator& RFC6979_Nonce_Generator::operator=(RFC6979_Nonce_Generator&& other) noexcept = default; |
19 | | |
20 | 367 | RFC6979_Nonce_Generator::~RFC6979_Nonce_Generator() = default; |
21 | | |
22 | | RFC6979_Nonce_Generator::RFC6979_Nonce_Generator(std::string_view hash, size_t order_bits, const BigInt& x) : |
23 | 0 | m_qlen(order_bits), m_rlen((m_qlen + 7) / 8), m_rng_in(m_rlen * 2), m_rng_out(m_rlen) { |
24 | 0 | m_hmac_drbg = std::make_unique<HMAC_DRBG>(MessageAuthenticationCode::create_or_throw(fmt("HMAC({})", hash))); |
25 | |
|
26 | 0 | x.serialize_to(std::span{m_rng_in}.first(m_rlen)); |
27 | 0 | } |
28 | | |
29 | 0 | BigInt RFC6979_Nonce_Generator::nonce_for(const BigInt& order, const BigInt& m) { |
30 | 0 | BOTAN_DEBUG_ASSERT(order.bits() == m_qlen); |
31 | |
|
32 | 0 | m.serialize_to(std::span{m_rng_in}.last(m_rlen)); |
33 | |
|
34 | 0 | m_hmac_drbg->initialize_with(m_rng_in); |
35 | |
|
36 | 0 | const size_t shift = 8 * m_rlen - m_qlen; |
37 | 0 | BOTAN_ASSERT_NOMSG(shift < 8); |
38 | |
|
39 | 0 | BigInt k; |
40 | |
|
41 | 0 | for(;;) { |
42 | 0 | m_hmac_drbg->randomize(m_rng_out); |
43 | 0 | k._assign_from_bytes(m_rng_out); |
44 | |
|
45 | 0 | if(shift > 0) { |
46 | 0 | k >>= shift; |
47 | 0 | } |
48 | |
|
49 | 0 | if(k > 0 && k < order) { |
50 | 0 | break; |
51 | 0 | } |
52 | 0 | } |
53 | |
|
54 | 0 | return k; |
55 | 0 | } |
56 | | |
57 | | #if defined(BOTAN_HAS_ECC_GROUP) |
58 | | RFC6979_Nonce_Generator::RFC6979_Nonce_Generator(std::string_view hash, size_t order_bits, const EC_Scalar& scalar) : |
59 | 367 | m_qlen(order_bits), m_rlen((m_qlen + 7) / 8), m_rng_in(m_rlen * 2), m_rng_out(m_rlen) { |
60 | 367 | m_hmac_drbg = std::make_unique<HMAC_DRBG>(MessageAuthenticationCode::create_or_throw(fmt("HMAC({})", hash))); |
61 | | |
62 | 367 | scalar.serialize_to(std::span{m_rng_in}.first(m_rlen)); |
63 | 367 | } |
64 | | |
65 | 367 | EC_Scalar RFC6979_Nonce_Generator::nonce_for(const EC_Group& group, const EC_Scalar& m) { |
66 | 367 | m.serialize_to(std::span{m_rng_in}.last(m_rlen)); |
67 | | |
68 | 367 | m_hmac_drbg->initialize_with(m_rng_in); |
69 | | |
70 | 367 | const size_t shift = 8 * m_rlen - m_qlen; |
71 | 367 | BOTAN_ASSERT_NOMSG(shift < 8); |
72 | | |
73 | 367 | for(;;) { |
74 | 367 | m_hmac_drbg->randomize(m_rng_out); |
75 | | |
76 | 367 | if(shift > 0) { |
77 | 0 | uint8_t carry = 0; |
78 | 0 | for(uint8_t& b : m_rng_out) { |
79 | 0 | const uint8_t w = b; |
80 | 0 | b = (w >> shift) | carry; |
81 | 0 | carry = w << (8 - shift); |
82 | 0 | } |
83 | 0 | } |
84 | | |
85 | 367 | if(auto k = EC_Scalar::deserialize(group, m_rng_out)) { |
86 | 367 | return *k; |
87 | 367 | } |
88 | 367 | } |
89 | 367 | } |
90 | | #endif |
91 | | |
92 | | } // namespace Botan |