Coverage Report

Created: 2024-11-29 06:10

/src/botan/src/lib/math/pcurves/pcurves_secp224r1/pcurves_secp224r1.cpp
Line
Count
Source
1
/*
2
* (C) 2024 Jack Lloyd
3
*
4
* Botan is released under the Simplified BSD License (see license.txt)
5
*/
6
7
#include <botan/internal/pcurves_instance.h>
8
9
#include <botan/internal/pcurves_solinas.h>
10
#include <botan/internal/pcurves_wrap.h>
11
12
namespace Botan::PCurve {
13
14
namespace {
15
16
namespace secp224r1 {
17
18
template <typename Params>
19
class Secp224r1Rep final {
20
   public:
21
      static constexpr auto P = Params::P;
22
      static constexpr size_t N = Params::N;
23
      typedef typename Params::W W;
24
25
405k
      constexpr static std::array<W, N> redc(const std::array<W, 2 * N>& z) {
26
405k
         const int64_t X00 = get_uint32(z.data(), 0);
27
405k
         const int64_t X01 = get_uint32(z.data(), 1);
28
405k
         const int64_t X02 = get_uint32(z.data(), 2);
29
405k
         const int64_t X03 = get_uint32(z.data(), 3);
30
405k
         const int64_t X04 = get_uint32(z.data(), 4);
31
405k
         const int64_t X05 = get_uint32(z.data(), 5);
32
405k
         const int64_t X06 = get_uint32(z.data(), 6);
33
405k
         const int64_t X07 = get_uint32(z.data(), 7);
34
405k
         const int64_t X08 = get_uint32(z.data(), 8);
35
405k
         const int64_t X09 = get_uint32(z.data(), 9);
36
405k
         const int64_t X10 = get_uint32(z.data(), 10);
37
405k
         const int64_t X11 = get_uint32(z.data(), 11);
38
405k
         const int64_t X12 = get_uint32(z.data(), 12);
39
405k
         const int64_t X13 = get_uint32(z.data(), 13);
40
41
405k
         const int64_t S0 = 0x00000001 + X00 - X07 - X11;
42
405k
         const int64_t S1 = 0x00000000 + X01 - X08 - X12;
43
405k
         const int64_t S2 = 0x00000000 + X02 - X09 - X13;
44
405k
         const int64_t S3 = 0xFFFFFFFF + X03 + X07 + X11 - X10;
45
405k
         const int64_t S4 = 0xFFFFFFFF + X04 + X08 + X12 - X11;
46
405k
         const int64_t S5 = 0xFFFFFFFF + X05 + X09 + X13 - X12;
47
405k
         const int64_t S6 = 0xFFFFFFFF + X06 + X10 - X13;
48
49
405k
         std::array<W, N> r = {};
50
51
405k
         SolinasAccum sum(r);
52
53
405k
         sum.accum(S0);
54
405k
         sum.accum(S1);
55
405k
         sum.accum(S2);
56
405k
         sum.accum(S3);
57
405k
         sum.accum(S4);
58
405k
         sum.accum(S5);
59
405k
         sum.accum(S6);
60
405k
         const auto S = sum.final_carry(0);
61
62
405k
         BOTAN_DEBUG_ASSERT(S <= 2);
63
64
405k
         const auto correction = p224_mul_mod_224(S);
65
405k
         W borrow = bigint_sub2(r.data(), N, correction.data(), N);
66
67
405k
         bigint_cnd_add(borrow, r.data(), N, P.data(), N);
68
69
405k
         return r;
70
405k
      }
71
72
1.59k
      constexpr static std::array<W, N> one() { return std::array<W, N>{1}; }
73
74
46
      constexpr static std::array<W, N> to_rep(const std::array<W, N>& x) { return x; }
75
76
      constexpr static std::array<W, N> wide_to_rep(const std::array<W, 2 * N>& x) { return redc(x); }
77
78
80
      constexpr static std::array<W, N> from_rep(const std::array<W, N>& z) { return z; }
79
80
   private:
81
      // Return (i*P-224) % 2**224
82
      //
83
      // Assumes i is small
84
405k
      constexpr static std::array<W, N> p224_mul_mod_224(W i) {
85
405k
         static_assert(WordInfo<W>::bits == 32 || WordInfo<W>::bits == 64);
86
87
         // For small i, multiples of P-224 have a simple structure so it's faster to
88
         // compute the value directly vs a (constant time) table lookup
89
90
405k
         auto r = P;
91
92
         if constexpr(WordInfo<W>::bits == 32) {
93
            r[3] -= i;
94
            r[0] += i;
95
405k
         } else {
96
405k
            const W i32 = i << 32;
97
405k
            r[1] -= i32;
98
405k
            r[0] += i;
99
405k
         }
100
405k
         return r;
101
405k
      }
102
};
103
104
// clang-format off
105
class Params final : public EllipticCurveParameters<
106
   "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001",
107
   "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE",
108
   "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4",
109
   "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D",
110
   "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21",
111
   "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34"> {
112
};
113
114
// clang-format on
115
116
class Curve final : public EllipticCurve<Params, Secp224r1Rep> {
117
   public:
118
      // Return the square of the inverse of x
119
850
      static FieldElement fe_invert2(const FieldElement& x) {
120
850
         auto z = x.square();
121
850
         z *= x;
122
850
         z = z.square();
123
850
         z *= x;
124
850
         auto t0 = z;
125
850
         t0.square_n(3);
126
850
         t0 *= z;
127
850
         auto t1 = t0;
128
850
         t1.square_n(6);
129
850
         t0 *= t1;
130
850
         t0.square_n(3);
131
850
         z *= t0;
132
850
         t0 = z.square();
133
850
         t0 *= x;
134
850
         t1 = t0;
135
850
         t1.square_n(16);
136
850
         t0 *= t1;
137
850
         t1 = t0;
138
850
         t1.square_n(15);
139
850
         z *= t1;
140
850
         t1 = z;
141
850
         t1.square_n(47);
142
850
         z *= t1;
143
850
         z = z.square();
144
850
         z *= x;
145
850
         t1 = z;
146
850
         t1.square_n(32);
147
850
         t0 *= t1;
148
850
         t0.square_n(96);
149
850
         z *= t0;
150
850
         return z.square();
151
850
      }
152
153
8
      static Scalar scalar_invert(const Scalar& x) {
154
         // Generated using https://github.com/mmcloughlin/addchain
155
8
         auto t6 = x.square();
156
8
         auto z = t6.square();
157
8
         auto t3 = x * z;
158
8
         auto t2 = t3 * t6;
159
8
         auto t8 = t2 * z;
160
8
         auto t7 = t8 * z;
161
8
         auto t5 = t7 * z;
162
8
         auto t0 = t5 * t6;
163
8
         auto t1 = t0 * t6;
164
8
         auto t4 = t1 * z;
165
8
         z = t4 * t6;
166
8
         t6 *= z;
167
8
         auto t10 = t6.square();
168
8
         auto t9 = t10 * x;
169
8
         t10.square_n(5);
170
8
         t9 *= t10;
171
8
         t10.square_n(5);
172
8
         t9 *= t10;
173
8
         t10 = t9;
174
8
         t10.square_n(16);
175
8
         t10 *= t9;
176
8
         auto t11 = t10;
177
8
         t11.square_n(32);
178
8
         t11 *= t10;
179
8
         t11.square_n(32);
180
8
         t10 *= t11;
181
8
         t10.square_n(16);
182
8
         t9 *= t10;
183
8
         t9.square_n(7);
184
8
         t8 *= t9;
185
8
         t8.square_n(4);
186
8
         t8 *= t3;
187
8
         t8.square_n(8);
188
8
         t8 *= t1;
189
8
         t8.square_n(10);
190
8
         t8 *= t1;
191
8
         t8.square_n(7);
192
8
         t7 *= t8;
193
8
         t7.square_n(11);
194
8
         t6 *= t7;
195
8
         t6.square_n(9);
196
8
         t5 *= t6;
197
8
         t5.square_n(5);
198
8
         t4 *= t5;
199
8
         t4.square_n(3);
200
8
         t4 *= t3;
201
8
         t4.square_n(5);
202
8
         t4 *= t3;
203
8
         t4.square_n(5);
204
8
         t3 *= t4;
205
8
         t3.square_n(8);
206
8
         t3 *= t0;
207
8
         t3.square_n(4);
208
8
         t2 *= t3;
209
8
         t2.square_n(8);
210
8
         t1 *= t2;
211
8
         t1.square_n(9);
212
8
         t0 *= t1;
213
8
         t0.square_n(8);
214
8
         z *= t0;
215
8
         z = z.square();
216
8
         z *= x;
217
8
         return z;
218
8
      }
219
};
220
221
}  // namespace secp224r1
222
223
}  // namespace
224
225
110
std::shared_ptr<const PrimeOrderCurve> PCurveInstance::secp224r1() {
226
110
   return PrimeOrderCurveImpl<secp224r1::Curve>::instance();
227
110
}
228
229
}  // namespace Botan::PCurve