Botan 3.7.1
Crypto and TLS for C&
pcurves_sm2p256v1.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 sm2p256v1 {
17
18template <typename Params>
19class Sm2p256v1Rep 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 const int64_t X00 = get_uint32(z.data(), 0);
27 const int64_t X01 = get_uint32(z.data(), 1);
28 const int64_t X02 = get_uint32(z.data(), 2);
29 const int64_t X03 = get_uint32(z.data(), 3);
30 const int64_t X04 = get_uint32(z.data(), 4);
31 const int64_t X05 = get_uint32(z.data(), 5);
32 const int64_t X06 = get_uint32(z.data(), 6);
33 const int64_t X07 = get_uint32(z.data(), 7);
34 const int64_t X08 = get_uint32(z.data(), 8);
35 const int64_t X09 = get_uint32(z.data(), 9);
36 const int64_t X10 = get_uint32(z.data(), 10);
37 const int64_t X11 = get_uint32(z.data(), 11);
38 const int64_t X12 = get_uint32(z.data(), 12);
39 const int64_t X13 = get_uint32(z.data(), 13);
40 const int64_t X14 = get_uint32(z.data(), 14);
41 const int64_t X15 = get_uint32(z.data(), 15);
42
43 const int64_t S0 = X00 + X08 + X09 + X10 + X11 + X12 + 2 * (X13 + X14 + X15);
44 const int64_t S1 = X01 + X09 + X10 + X11 + X12 + X13 + 2 * (X14 + X15);
45 const int64_t S2 = X02 - (X08 + X09 + X13 + X14);
46 const int64_t S3 = X03 + X08 + X11 + X12 + 2 * X13 + X14 + X15;
47 const int64_t S4 = X04 + X09 + X12 + X13 + 2 * X14 + X15;
48 const int64_t S5 = X05 + X10 + X13 + X14 + 2 * X15;
49 const int64_t S6 = X06 + X11 + X14 + X15;
50 const int64_t S7 = X07 + X08 + X09 + X10 + X11 + 2 * (X12 + X13 + X14 + X15) + X15;
51
52 std::array<W, N> r = {};
53
54 SolinasAccum sum(r);
55
56 sum.accum(S0);
57 sum.accum(S1);
58 sum.accum(S2);
59 sum.accum(S3);
60 sum.accum(S4);
61 sum.accum(S5);
62 sum.accum(S6);
63 sum.accum(S7);
64 const auto S = sum.final_carry(0);
65
66 bigint_correct_redc<N>(r, P, sm2_mul_mod_256(S));
67
68 return r;
69 }
70
71 constexpr static std::array<W, N> one() { return std::array<W, N>{1}; }
72
73 constexpr static std::array<W, N> to_rep(const std::array<W, N>& x) { return x; }
74
75 constexpr static std::array<W, N> wide_to_rep(const std::array<W, 2 * N>& x) { return redc(x); }
76
77 constexpr static std::array<W, N> from_rep(const std::array<W, N>& z) { return z; }
78
79 private:
80 // Return (i*P) % 2**256
81 //
82 // Assumes i is small
83 constexpr static std::array<W, N> sm2_mul_mod_256(W i) {
84 static_assert(WordInfo<W>::bits == 32 || WordInfo<W>::bits == 64);
85
86 // For small i, multiples of P have a simple structure so it's faster to
87 // compute the value directly vs a (constant time) table lookup
88
89 auto r = P;
90 if constexpr(WordInfo<W>::bits == 32) {
91 r[7] -= i;
92 r[3] -= i;
93 r[2] += i;
94 r[0] -= i;
95 } else {
96 const uint64_t i32 = static_cast<uint64_t>(i) << 32;
97 r[3] -= i32;
98 r[1] -= i32;
99 r[1] += i;
100 r[0] -= i;
101 }
102 return r;
103 }
104};
105
106// clang-format off
107
108class Params final : public EllipticCurveParameters<
109 "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF",
110 "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC",
111 "28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93",
112 "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123",
113 "32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7",
114 "BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0"> {
115};
116
117// clang-format on
118
119class Curve final : public EllipticCurve<Params, Sm2p256v1Rep> {
120 public:
121 // Return the square of the inverse of x
122 static FieldElement fe_invert2(const FieldElement& x) {
123 // Generated by https://github.com/mmcloughlin/addchain
124 auto z = x.square();
125 auto t0 = x * z;
126 z = t0.square();
127 z *= x;
128 auto t1 = z;
129 t1.square_n(3);
130 t1 *= z;
131 auto t2 = t1.square();
132 z = t2 * x;
133 t2.square_n(5);
134 t1 *= t2;
135 t2 = t1;
136 t2.square_n(12);
137 t1 *= t2;
138 t1.square_n(7);
139 z *= t1;
140 t2 = z;
141 t2.square_n(2);
142 t1 = t2;
143 t1.square_n(29);
144 z *= t1;
145 t1.square_n(2);
146 t2 *= t1;
147 t0 *= t2;
148 t1.square_n(32);
149 t1 *= t0;
150 t1.square_n(64);
151 t0 *= t1;
152 t0.square_n(94);
153 z *= t0;
154 z.square_n(2);
155 return z;
156 }
157};
158
159} // namespace sm2p256v1
160
161} // namespace
162
163std::shared_ptr<const PrimeOrderCurve> PCurveInstance::sm2p256v1() {
165}
166
167} // namespace Botan::PCurve
static std::shared_ptr< const PrimeOrderCurve > sm2p256v1()
Definition pcurves.cpp:89
static std::shared_ptr< const PrimeOrderCurve > instance()
constexpr void accum(int64_t v)
constexpr W final_carry(int64_t C)
int(* final)(unsigned char *, CTX *)
constexpr uint32_t get_uint32(const W xw[], size_t i)
constexpr void bigint_correct_redc(std::array< W, N > &r, const std::array< W, N > &P, const std::array< W, N > &C)
Definition mp_core.h:1108