Coverage Report

Created: 2025-12-05 06:47

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/Botan-3.4.0/build/include/internal/botan/internal/donna128.h
Line
Count
Source
1
/*
2
* A minimal 128-bit integer type for curve25519-donna
3
* (C) 2014 Jack Lloyd
4
*
5
* Botan is released under the Simplified BSD License (see license.txt)
6
*/
7
8
#ifndef BOTAN_CURVE25519_DONNA128_H_
9
#define BOTAN_CURVE25519_DONNA128_H_
10
11
#include <botan/internal/mul128.h>
12
#include <type_traits>
13
14
namespace Botan {
15
16
class donna128 final {
17
   public:
18
0
      constexpr donna128(uint64_t ll = 0, uint64_t hh = 0) {
19
0
         l = ll;
20
0
         h = hh;
21
0
      }
22
23
      donna128(const donna128&) = default;
24
      donna128& operator=(const donna128&) = default;
25
26
      template <typename T>
27
0
      constexpr friend donna128 operator>>(const donna128& x, T shift) {
28
0
         donna128 z = x;
29
0
30
0
         if(shift > 64) {
31
0
            z.l = z.h >> (shift - 64);
32
0
            z.h = 0;
33
0
         } else if(shift == 64) {
34
0
            z.l = z.h;
35
0
            z.h = 0;
36
0
         } else if(shift > 0) {
37
0
            const uint64_t carry = z.h << static_cast<size_t>(64 - shift);
38
0
            z.h >>= shift;
39
0
            z.l >>= shift;
40
0
            z.l |= carry;
41
0
         }
42
0
43
0
         return z;
44
0
      }
45
46
      template <typename T>
47
0
      constexpr friend donna128 operator<<(const donna128& x, T shift) {
48
0
         donna128 z = x;
49
0
         if(shift > 64) {
50
0
            z.h = z.l << (shift - 64);
51
0
            z.l = 0;
52
0
         } else if(shift == 64) {
53
0
            z.h = z.l;
54
0
            z.l = 0;
55
0
         } else if(shift > 0) {
56
0
            const uint64_t carry = z.l >> static_cast<size_t>(64 - shift);
57
0
            z.l = (z.l << shift);
58
0
            z.h = (z.h << shift) | carry;
59
0
         }
60
0
61
0
         return z;
62
0
      }
63
64
0
      constexpr friend uint64_t operator&(const donna128& x, uint64_t mask) { return x.l & mask; }
65
66
0
      constexpr uint64_t operator&=(uint64_t mask) {
67
0
         h = 0;
68
0
         l &= mask;
69
0
         return l;
70
0
      }
71
72
0
      constexpr donna128& operator+=(const donna128& x) {
73
0
         l += x.l;
74
0
         h += x.h;
75
0
76
0
         const uint64_t carry = (l < x.l);
77
0
         h += carry;
78
0
         return *this;
79
0
      }
80
81
0
      constexpr donna128& operator+=(uint64_t x) {
82
0
         l += x;
83
0
         const uint64_t carry = (l < x);
84
0
         h += carry;
85
0
         return *this;
86
0
      }
87
88
0
      constexpr uint64_t lo() const { return l; }
89
90
0
      constexpr uint64_t hi() const { return h; }
91
92
0
      constexpr operator uint64_t() const { return l; }
93
94
   private:
95
      uint64_t h = 0, l = 0;
96
};
97
98
template <std::unsigned_integral T>
99
constexpr inline donna128 operator*(const donna128& x, T y) {
100
   BOTAN_ARG_CHECK(x.hi() == 0, "High 64 bits of donna128 set to zero during multiply");
101
102
   uint64_t lo = 0, hi = 0;
103
   mul64x64_128(x.lo(), static_cast<uint64_t>(y), &lo, &hi);
104
   return donna128(lo, hi);
105
}
106
107
template <std::unsigned_integral T>
108
constexpr inline donna128 operator*(T y, const donna128& x) {
109
   return x * y;
110
}
111
112
0
constexpr inline donna128 operator+(const donna128& x, const donna128& y) {
113
0
   donna128 z = x;
114
0
   z += y;
115
0
   return z;
116
0
}
117
118
0
constexpr inline donna128 operator+(const donna128& x, uint64_t y) {
119
0
   donna128 z = x;
120
0
   z += y;
121
0
   return z;
122
0
}
123
124
0
constexpr inline donna128 operator|(const donna128& x, const donna128& y) {
125
0
   return donna128(x.lo() | y.lo(), x.hi() | y.hi());
126
0
}
127
128
0
constexpr inline donna128 operator|(const donna128& x, uint64_t y) {
129
0
   return donna128(x.lo() | y, x.hi());
130
0
}
131
132
0
constexpr inline uint64_t carry_shift(const donna128& a, size_t shift) {
133
0
   return (a >> shift).lo();
134
0
}
135
136
0
constexpr inline uint64_t combine_lower(const donna128& a, size_t s1, const donna128& b, size_t s2) {
137
0
   donna128 z = (a >> s1) | (b << s2);
138
0
   return z.lo();
139
0
}
140
141
#if defined(BOTAN_TARGET_HAS_NATIVE_UINT128)
142
0
inline uint64_t carry_shift(const uint128_t a, size_t shift) {
143
0
   return static_cast<uint64_t>(a >> shift);
144
0
}
145
146
0
inline uint64_t combine_lower(const uint128_t a, size_t s1, const uint128_t b, size_t s2) {
147
0
   return static_cast<uint64_t>((a >> s1) | (b << s2));
148
0
}
149
#endif
150
151
}  // namespace Botan
152
153
#endif