Botan 3.6.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 const auto correction = sm2_mul_mod_256(S);
67 W borrow = bigint_sub2(r.data(), N, correction.data(), N);
68
69 bigint_cnd_add(borrow, r.data(), N, P.data(), N);
70
71 return r;
72 }
73
74 constexpr static std::array<W, N> one() { return std::array<W, N>{1}; }
75
76 constexpr static std::array<W, N> to_rep(const std::array<W, N>& x) { return x; }
77
78 constexpr static std::array<W, N> wide_to_rep(const std::array<W, 2 * N>& x) { return redc(x); }
79
80 constexpr static std::array<W, N> from_rep(const std::array<W, N>& z) { return z; }
81
82 private:
83 // Return (i*P) % 2**256
84 //
85 // Assumes i is small
86 constexpr static std::array<W, N> sm2_mul_mod_256(W i) {
87 static_assert(WordInfo<W>::bits == 32 || WordInfo<W>::bits == 64);
88
89 // For small i, multiples of P have a simple structure so it's faster to
90 // compute the value directly vs a (constant time) table lookup
91
92 auto r = P;
93 if constexpr(WordInfo<W>::bits == 32) {
94 r[7] -= i;
95 r[3] -= i;
96 r[2] += i;
97 r[0] -= i;
98 } else {
99 const uint64_t i32 = static_cast<uint64_t>(i) << 32;
100 r[3] -= i32;
101 r[1] -= i32;
102 r[1] += i;
103 r[0] -= i;
104 }
105 return r;
106 }
107};
108
109// clang-format off
110
111class Params final : public EllipticCurveParameters<
112 "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF",
113 "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC",
114 "28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93",
115 "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123",
116 "32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7",
117 "BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0"> {
118};
119
120// clang-format on
121
122class Curve final : public EllipticCurve<Params, Sm2p256v1Rep> {
123 public:
124 // Return the square of the inverse of x
125 static FieldElement fe_invert2(const FieldElement& x) {
126 // Generated by https://github.com/mmcloughlin/addchain
127 auto z = x.square();
128 auto t0 = x * z;
129 z = t0.square();
130 z *= x;
131 auto t1 = z;
132 t1.square_n(3);
133 t1 *= z;
134 auto t2 = t1.square();
135 z = t2 * x;
136 t2.square_n(5);
137 t1 *= t2;
138 t2 = t1;
139 t2.square_n(12);
140 t1 *= t2;
141 t1.square_n(7);
142 z *= t1;
143 t2 = z;
144 t2.square_n(2);
145 t1 = t2;
146 t1.square_n(29);
147 z *= t1;
148 t1.square_n(2);
149 t2 *= t1;
150 t0 *= t2;
151 t1.square_n(32);
152 t1 *= t0;
153 t1.square_n(64);
154 t0 *= t1;
155 t0.square_n(94);
156 z *= t0;
157 z.square_n(2);
158 return z;
159 }
160};
161
162} // namespace sm2p256v1
163
164} // namespace
165
166std::shared_ptr<const PrimeOrderCurve> PCurveInstance::sm2p256v1() {
168}
169
170} // 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 W bigint_cnd_add(W cnd, W x[], size_t x_size, const W y[], size_t y_size)
Definition mp_core.h:42
constexpr auto bigint_sub2(W x[], size_t x_size, const W y[], size_t y_size) -> W
Definition mp_core.h:291