• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

randombit / botan / 12256396908

10 Dec 2024 12:45PM UTC coverage: 91.251% (+0.2%) from 91.076%
12256396908

Pull #4309

github

web-flow
Merge 733a9052d into 4725c2d79
Pull Request #4309: Add Entropy Source and DRNG Manager (ESDM) RNG support

93431 of 102389 relevant lines covered (91.25%)

11600314.44 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

93.29
/src/tests/test_ecc_pointmul.cpp
1
/*
2
* (C) 2014,2015,2019 Jack Lloyd
3
*
4
* Botan is released under the Simplified BSD License (see license.txt)
5
*/
6

7
#include "tests.h"
8

9
#if defined(BOTAN_HAS_ECC_GROUP)
10
   #include <botan/bigint.h>
11
   #include <botan/ec_group.h>
12
   #include <botan/internal/fmt.h>
13
#endif
14

15
namespace Botan_Tests {
16

17
namespace {
18

19
#if defined(BOTAN_HAS_ECC_GROUP)
20

21
class ECC_Basepoint_Mul_Tests final : public Text_Based_Test {
×
22
   public:
23
      ECC_Basepoint_Mul_Tests() : Text_Based_Test("pubkey/ecc_base_point_mul.vec", "k,P") {}
2✔
24

25
      Test::Result run_one_test(const std::string& group_id, const VarMap& vars) override {
533✔
26
         Test::Result result("ECC base point multiply " + group_id);
533✔
27

28
         const auto k_bytes = vars.get_req_bin("k");
533✔
29
         const auto P_bytes = vars.get_req_bin("P");
533✔
30

31
         const auto group = Botan::EC_Group::from_name(group_id);
533✔
32

33
         const Botan::BigInt k(k_bytes);
533✔
34
         const auto pt = group.OS2ECP(P_bytes);
533✔
35

36
         const Botan::EC_Point& base_point = group.get_base_point();
533✔
37

38
         const Botan::EC_Point p1 = base_point * k;
533✔
39
         result.test_eq("mul with *", p1, pt);
533✔
40

41
         std::vector<Botan::BigInt> ws;
533✔
42
         const Botan::EC_Point p2 = group.blinded_base_point_multiply(k, this->rng(), ws);
533✔
43
         result.test_eq("blinded_base_point_multiply", p2, pt);
533✔
44

45
         const Botan::EC_Point p3 = group.blinded_var_point_multiply(base_point, k, this->rng(), ws);
533✔
46
         result.test_eq("blinded_var_point_multiply", p3, pt);
533✔
47

48
         const auto scalar = Botan::EC_Scalar::from_bigint(group, k);
533✔
49
         const auto apg = Botan::EC_AffinePoint::g_mul(scalar, this->rng(), ws);
533✔
50
         result.test_eq("AffinePoint::g_mul", apg.serialize_uncompressed(), P_bytes);
1,066✔
51

52
         const auto ag = Botan::EC_AffinePoint(group, base_point);
533✔
53
         const auto ap = ag.mul(scalar, this->rng(), ws);
533✔
54
         result.test_eq("AffinePoint::mul", ap.to_legacy_point(), pt);
1,066✔
55

56
         return result;
1,066✔
57
      }
2,132✔
58
};
59

60
BOTAN_REGISTER_TEST("pubkey", "ecc_basemul", ECC_Basepoint_Mul_Tests);
61

62
class ECC_Varpoint_Mul_Tests final : public Text_Based_Test {
×
63
   public:
64
      ECC_Varpoint_Mul_Tests() : Text_Based_Test("pubkey/ecc_var_point_mul.vec", "P,k,Z") {}
2✔
65

66
      Test::Result run_one_test(const std::string& group_id, const VarMap& vars) override {
829✔
67
         Test::Result result("ECC var point multiply " + group_id);
829✔
68

69
         const auto p = vars.get_req_bin("P");
829✔
70
         const Botan::BigInt k = vars.get_req_bn("k");
829✔
71
         const auto z = vars.get_req_bin("Z");
829✔
72

73
         const auto group = Botan::EC_Group::from_name(group_id);
829✔
74

75
         const Botan::EC_Point pt = group.OS2ECP(p);
829✔
76

77
         result.confirm("Input point is on the curve", pt.on_the_curve());
1,658✔
78

79
         const Botan::EC_Point p1 = pt * k;
829✔
80
         result.test_eq("p * k", p1.encode(Botan::EC_Point::Compressed), z);
1,658✔
81

82
         result.confirm("Output point is on the curve", p1.on_the_curve());
1,658✔
83

84
         std::vector<Botan::BigInt> ws;
829✔
85
         const Botan::EC_Point p2 = group.blinded_var_point_multiply(pt, k, this->rng(), ws);
829✔
86
         result.test_eq("p * k (blinded)", p2.encode(Botan::EC_Point::Compressed), z);
1,658✔
87

88
         const auto s_k = Botan::EC_Scalar::from_bigint(group, k);
829✔
89
         const auto apt = Botan::EC_AffinePoint::deserialize(group, p).value();
1,658✔
90
         const auto apt_k = apt.mul(s_k, this->rng(), ws);
829✔
91
         result.test_eq("p * k (AffinePoint)", apt_k.serialize_compressed(), z);
1,658✔
92

93
         const auto apt_k_neg = apt.negate().mul(s_k.negate(), this->rng(), ws);
829✔
94
         result.test_eq("-p * -k (AffinePoint)", apt_k_neg.serialize_compressed(), z);
1,658✔
95

96
         const auto neg_apt_neg_k = apt.mul(s_k.negate(), this->rng(), ws).negate();
829✔
97
         result.test_eq("-(p * -k) (AffinePoint)", neg_apt_neg_k.serialize_compressed(), z);
1,658✔
98

99
         return result;
1,658✔
100
      }
3,316✔
101
};
102

103
BOTAN_REGISTER_TEST("pubkey", "ecc_varmul", ECC_Varpoint_Mul_Tests);
104

105
class ECC_Mul2_Tests final : public Text_Based_Test {
×
106
   public:
107
      ECC_Mul2_Tests() : Text_Based_Test("pubkey/ecc_var_point_mul2.vec", "P,x,Q,y,Z") {}
2✔
108

109
      Test::Result run_one_test(const std::string& group_id, const VarMap& vars) override {
819✔
110
         Test::Result result("ECC mul2 " + group_id);
819✔
111

112
         const auto Z_bytes = vars.get_req_bin("Z");
819✔
113

114
         const auto check_px_qy = [&](const char* what,
4,095✔
115
                                      const Botan::EC_AffinePoint& p,
116
                                      const Botan::EC_Scalar& x,
117
                                      const Botan::EC_AffinePoint& q,
118
                                      const Botan::EC_Scalar& y,
119
                                      bool with_final_negation = false) {
120
            if(const auto z = Botan::EC_AffinePoint::mul_px_qy(p, x, q, y, rng())) {
3,276✔
121
               if(with_final_negation) {
3,276✔
122
                  result.test_eq(what, z->negate().serialize_compressed(), Z_bytes);
4,914✔
123
               } else {
124
                  result.test_eq(what, z->serialize_compressed(), Z_bytes);
4,914✔
125
               }
126
            } else {
127
               result.test_failure("EC_AffinePoint::mul_px_qy failed to produce a result");
×
128
            }
×
129

130
            // Now check the same using naive multiply and add:
131
            std::vector<BigInt> ws;
3,276✔
132
            auto z = p.mul(x, rng(), ws).add(q.mul(y, rng(), ws));
3,276✔
133
            if(with_final_negation) {
3,276✔
134
               z = z.negate();
1,638✔
135
            }
136
            result.test_eq("p*x + q*y naive", z.serialize_compressed(), Z_bytes);
6,552✔
137
         };
3,276✔
138

139
         const auto group = Botan::EC_Group::from_name(group_id);
819✔
140

141
         const auto p = Botan::EC_AffinePoint::deserialize(group, vars.get_req_bin("P")).value();
3,276✔
142
         const auto q = Botan::EC_AffinePoint::deserialize(group, vars.get_req_bin("Q")).value();
3,276✔
143
         const auto x = Botan::EC_Scalar::from_bigint(group, vars.get_req_bn("x"));
1,638✔
144
         const auto y = Botan::EC_Scalar::from_bigint(group, vars.get_req_bn("y"));
1,638✔
145

146
         const auto np = p.negate();
819✔
147
         const auto nq = q.negate();
819✔
148
         const auto nx = x.negate();
819✔
149
         const auto ny = y.negate();
819✔
150

151
         check_px_qy("p*x + q*y", p, x, q, y);
819✔
152
         check_px_qy("-p*-x + -q*-y", np, nx, nq, ny);
819✔
153
         check_px_qy("-(p*-x + q*-y)", p, nx, q, ny, true);
819✔
154
         check_px_qy("-(-p*x + -q*y)", np, x, nq, y, true);
819✔
155

156
         return result;
1,638✔
157
      }
1,638✔
158
};
159

160
BOTAN_REGISTER_TEST("pubkey", "ecc_mul2", ECC_Mul2_Tests);
161

162
class ECC_Mul2_Inf_Tests final : public Test {
×
163
   public:
164
      std::vector<Test::Result> run() override {
1✔
165
         std::vector<Test::Result> results;
1✔
166

167
         for(const auto& group_id : Botan::EC_Group::known_named_groups()) {
29✔
168
            Test::Result result("ECC mul2 inf " + group_id);
28✔
169

170
            const auto check_px_qy = [&](const char* what,
224✔
171
                                         const Botan::EC_AffinePoint& p,
172
                                         const Botan::EC_Scalar& x,
173
                                         const Botan::EC_AffinePoint& q,
174
                                         const Botan::EC_Scalar& y) {
175
               if(const auto z = Botan::EC_AffinePoint::mul_px_qy(p, x, q, y, rng())) {
196✔
176
                  result.test_failure(Botan::fmt("EC_AffinePoint::mul_px_qy {} unexpectedly produced a result", what));
×
177
               } else {
178
                  result.test_success(Botan::fmt("EC_AffinePoint::mul_px_qy {} returned nullopt as expected", what));
392✔
179
               }
196✔
180
            };
196✔
181

182
            const auto group = Botan::EC_Group::from_name(group_id);
28✔
183

184
            const auto g = Botan::EC_AffinePoint::generator(group);
28✔
185

186
            // Choose some other random point z
187
            std::vector<Botan::BigInt> ws;
28✔
188
            const auto z = g.mul(Botan::EC_Scalar::random(group, rng()), rng(), ws);
28✔
189

190
            const auto r = Botan::EC_Scalar::random(group, rng());
28✔
191
            const auto neg_r = r.negate();
28✔
192
            const auto neg_r2 = neg_r + neg_r;
28✔
193

194
            const auto zero = r - r;
28✔
195
            result.confirm("Computed EC_Scalar is zero", zero.is_zero());
56✔
196

197
            const auto g2 = g.add(g);
28✔
198

199
            const auto id = Botan::EC_AffinePoint::identity(group);
28✔
200

201
            check_px_qy("0*g + r*id", g, zero, id, r);
28✔
202
            check_px_qy("0*id + r*id", id, zero, id, r);
28✔
203
            check_px_qy("0*g + 0*z", g, zero, z, zero);
28✔
204
            check_px_qy("r*g + -r*g", g, r, g, neg_r);
28✔
205
            check_px_qy("-r*g + r*g", g, neg_r, g, r);
28✔
206
            check_px_qy("r*g + r*-g", g, r, g.negate(), r);
28✔
207
            check_px_qy("r*g2 + -r2*g", g2, r, g, neg_r2);
28✔
208

209
            results.push_back(result);
28✔
210
         }
28✔
211

212
         return results;
1✔
213
      }
×
214
};
215

216
BOTAN_REGISTER_TEST("pubkey", "ecc_mul2_inf", ECC_Mul2_Inf_Tests);
217

218
class ECC_Addition_Tests final : public Test {
×
219
   public:
220
      std::vector<Test::Result> run() override {
1✔
221
         std::vector<Test::Result> results;
1✔
222

223
         for(const auto& group_id : Botan::EC_Group::known_named_groups()) {
29✔
224
            Test::Result result("ECC addition " + group_id);
28✔
225

226
            const auto group = Botan::EC_Group::from_name(group_id);
28✔
227

228
            const auto g = Botan::EC_AffinePoint::generator(group);
28✔
229
            result.test_eq("g is not the identity element", g.is_identity(), false);
28✔
230

231
            // Choose some other random point z
232
            std::vector<Botan::BigInt> ws;
28✔
233
            const auto z = g.mul(Botan::EC_Scalar::random(group, rng()), rng(), ws);
28✔
234
            result.test_eq("z is not the identity element", z.is_identity(), false);
28✔
235

236
            const auto id = Botan::EC_AffinePoint::identity(group);
28✔
237
            result.test_eq("id is the identity element", id.is_identity(), true);
28✔
238

239
            const auto g_bytes = g.serialize_uncompressed();
28✔
240

241
            auto check_expr_is_g = [&](const char* msg, const Botan::EC_AffinePoint& pt) {
308✔
242
               result.test_eq(Botan::fmt("{} is g", msg), pt.serialize_uncompressed(), g_bytes);
560✔
243
            };
280✔
244

245
            const auto nz = z.negate();
28✔
246

247
            check_expr_is_g("g + id", g.add(id));
28✔
248
            check_expr_is_g("id + g", id.add(g));
28✔
249
            check_expr_is_g("g + id", g.add(id));
28✔
250
            check_expr_is_g("g + -id", g.add(id.negate()));
28✔
251
            check_expr_is_g("g + g + -g", g.add(g).add(g.negate()));
28✔
252
            check_expr_is_g("-id + g", id.negate().add(g));
28✔
253
            check_expr_is_g("z + g - z", z.add(g).add(nz));
28✔
254
            check_expr_is_g("z - z + g", z.add(nz).add(g));
28✔
255
            check_expr_is_g("z + z + g - z - z", z.add(z).add(g).add(nz).add(nz));
28✔
256
            check_expr_is_g("z + id + g + z - z - z", z.add(id).add(g).add(z).add(nz).add(nz));
28✔
257

258
            results.push_back(result);
28✔
259
         }
56✔
260

261
         return results;
1✔
262
      }
×
263
};
264

265
BOTAN_REGISTER_TEST("pubkey", "ecc_addition", ECC_Addition_Tests);
266

267
#endif
268

269
}  // namespace
270

271
}  // namespace Botan_Tests
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc