Coverage Report

Created: 2026-02-07 07:14

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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