Botan 3.11.0
Crypto and TLS for C&
pcurves_secp192r1.cpp
Go to the documentation of this file.
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
12namespace Botan::PCurve {
13
14namespace {
15
16namespace secp192r1 {
17
18template <typename Params>
19class Secp192r1Rep 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 constexpr static std::array<W, N> redc(const std::array<W, 2 * N>& z) {
26 if constexpr(std::same_as<W, uint64_t> && WordInfo<W>::dword_is_native) {
27 using dword = typename WordInfo<W>::dword;
28
29 const dword S01 = dword(z[0]) + z[3] + z[5];
30 const dword S23 = dword(z[1]) + z[3] + z[4] + z[5];
31 const dword S45 = dword(z[2]) + z[4] + z[5];
32
33 std::array<W, N> r = {};
34
35 dword S = S01;
36 r[0] = static_cast<uint64_t>(S);
37 S >>= 64;
38
39 S += S23;
40 r[1] = static_cast<uint64_t>(S);
41 S >>= 64;
42
43 S += S45;
44 r[2] = static_cast<uint64_t>(S);
45 S >>= 64;
46
47 BOTAN_DEBUG_ASSERT(S <= 3);
48
49 solinas_correct_redc<N>(r, P, p192_mul_mod_192(static_cast<W>(S)));
50
51 return r;
52 }
53
54 const int64_t X00 = get_uint32(z.data(), 0);
55 const int64_t X01 = get_uint32(z.data(), 1);
56 const int64_t X02 = get_uint32(z.data(), 2);
57 const int64_t X03 = get_uint32(z.data(), 3);
58 const int64_t X04 = get_uint32(z.data(), 4);
59 const int64_t X05 = get_uint32(z.data(), 5);
60 const int64_t X06 = get_uint32(z.data(), 6);
61 const int64_t X07 = get_uint32(z.data(), 7);
62 const int64_t X08 = get_uint32(z.data(), 8);
63 const int64_t X09 = get_uint32(z.data(), 9);
64 const int64_t X10 = get_uint32(z.data(), 10);
65 const int64_t X11 = get_uint32(z.data(), 11);
66
67 const int64_t S0 = X00 + X06 + X10;
68 const int64_t S1 = X01 + X07 + X11;
69 const int64_t S2 = X02 + X06 + X08 + X10;
70 const int64_t S3 = X03 + X07 + X09 + X11;
71 const int64_t S4 = X04 + X08 + X10;
72 const int64_t S5 = X05 + X09 + X11;
73
74 std::array<W, N> r = {};
75
76 SolinasAccum sum(r);
77
78 sum.accum(S0);
79 sum.accum(S1);
80 sum.accum(S2);
81 sum.accum(S3);
82 sum.accum(S4);
83 sum.accum(S5);
84 const auto S = sum.final_carry(0);
85
86 BOTAN_DEBUG_ASSERT(S <= 3);
87
88 solinas_correct_redc<N>(r, P, p192_mul_mod_192(S));
89
90 return r;
91 }
92
93 constexpr static std::array<W, N> one() { return std::array<W, N>{1}; }
94
95 constexpr static std::array<W, N> to_rep(const std::array<W, N>& x) { return x; }
96
97 constexpr static std::array<W, N> wide_to_rep(const std::array<W, 2 * N>& x) { return redc(x); }
98
99 constexpr static std::array<W, N> from_rep(const std::array<W, N>& z) { return z; }
100
101 private:
102 // Return (i*P-192) % 2**192
103 //
104 // Assumes i is small
105 constexpr static std::array<W, N> p192_mul_mod_192(W i) {
106 static_assert(WordInfo<W>::bits == 32 || WordInfo<W>::bits == 64);
107
108 // For small i, multiples of P-192 have a simple structure so it's faster to
109 // compute the value directly vs a (constant time) table lookup
110
111 auto r = P;
112
113 if constexpr(WordInfo<W>::bits == 32) {
114 r[2] -= i;
115 r[0] -= i;
116 } else {
117 r[1] -= i;
118 r[0] -= i;
119 }
120 return r;
121 }
122};
123
124// clang-format off
125
126class Params final : public EllipticCurveParameters<
127 "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF",
128 "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC",
129 "64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1",
130 "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831",
131 "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012",
132 "07192B95FFC8DA78631011ED6B24CDD573F977A11E794811"> {
133};
134
135// clang-format on
136
137class Curve final : public EllipticCurve<Params, Secp192r1Rep> {
138 public:
139 // Return the square of the inverse of x
140 static constexpr FieldElement fe_invert2(const FieldElement& x) {
141 // Generated using https://github.com/mmcloughlin/addchain
142 auto z = x.square();
143 z *= x;
144 auto t0 = z.square();
145 t0 *= x;
146 auto t2 = t0.square();
147 auto t1 = t2.square();
148 auto t3 = t1;
149 t3.square_n(3);
150 t1 *= t3;
151 t3 = t1;
152 t3.square_n(2);
153 t2 *= t3;
154 t2.square_n(7);
155 t1 *= t2;
156 t2 = t1;
157 t2.square_n(15);
158 t1 *= t2;
159 t2 = t1;
160 t2.square_n(30);
161 t1 *= t2;
162 z *= t1;
163 t1 = z;
164 t1.square_n(3);
165 t2 = t1;
166 t2.square_n(62);
167 t1 *= t2;
168 t0 *= t1;
169 t0.square_n(63);
170 z *= t0;
171 z.square_n(2);
172 return z;
173 }
174};
175
176} // namespace secp192r1
177
178} // namespace
179
180std::shared_ptr<const PrimeOrderCurve> PCurveInstance::secp192r1() {
182}
183
184} // namespace Botan::PCurve
#define BOTAN_DEBUG_ASSERT(expr)
Definition assert.h:129
static std::shared_ptr< const PrimeOrderCurve > instance()
constexpr void accum(int64_t v)
constexpr W final_carry(int64_t C)
constexpr uint32_t get_uint32(const W xw[], size_t i)
constexpr void solinas_correct_redc(std::array< W, N > &r, const std::array< W, N > &P, const std::array< W, N > &C)