Coverage Report

Created: 2021-05-04 09:02

/src/botan/src/fuzzer/ecc_helper.h
Line
Count
Source (jump to first uncovered line)
1
/*
2
* (C) 2015,2016 Jack Lloyd
3
*
4
* Botan is released under the Simplified BSD License (see license.txt)
5
*/
6
7
#ifndef ECC_HELPERS_H_
8
#define ECC_HELPERS_H_
9
10
#include "fuzzers.h"
11
#include <botan/ec_group.h>
12
#include <botan/reducer.h>
13
#include <botan/numthry.h>
14
15
namespace {
16
17
inline std::ostream& operator<<(std::ostream& o, const Botan::PointGFp& point)
18
0
   {
19
0
   o << point.get_affine_x() << "," << point.get_affine_y();
20
0
   return o;
21
0
   }
Unexecuted instantiation: ecc_p384.cpp:(anonymous namespace)::operator<<(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, Botan::PointGFp const&)
Unexecuted instantiation: ecc_bp256.cpp:(anonymous namespace)::operator<<(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, Botan::PointGFp const&)
Unexecuted instantiation: ecc_p256.cpp:(anonymous namespace)::operator<<(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, Botan::PointGFp const&)
Unexecuted instantiation: ecc_p521.cpp:(anonymous namespace)::operator<<(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, Botan::PointGFp const&)
22
23
Botan::BigInt decompress_point(bool yMod2,
24
                               const Botan::BigInt& x,
25
                               const Botan::BigInt& curve_p,
26
                               const Botan::BigInt& curve_a,
27
                               const Botan::BigInt& curve_b)
28
3.51k
   {
29
3.51k
   Botan::BigInt xpow3 = x * x * x;
30
31
3.51k
   Botan::BigInt g = curve_a * x;
32
3.51k
   g += xpow3;
33
3.51k
   g += curve_b;
34
3.51k
   g = g % curve_p;
35
36
3.51k
   Botan::BigInt z = ressol(g, curve_p);
37
38
3.51k
   if(z < 0)
39
1.57k
      throw Botan::Exception("Could not perform square root");
40
41
1.94k
   if(z.get_bit(0) != yMod2)
42
1.04k
      z = curve_p - z;
43
44
1.94k
   return z;
45
1.94k
   }
ecc_p384.cpp:(anonymous namespace)::decompress_point(bool, Botan::BigInt const&, Botan::BigInt const&, Botan::BigInt const&, Botan::BigInt const&)
Line
Count
Source
28
894
   {
29
894
   Botan::BigInt xpow3 = x * x * x;
30
31
894
   Botan::BigInt g = curve_a * x;
32
894
   g += xpow3;
33
894
   g += curve_b;
34
894
   g = g % curve_p;
35
36
894
   Botan::BigInt z = ressol(g, curve_p);
37
38
894
   if(z < 0)
39
372
      throw Botan::Exception("Could not perform square root");
40
41
522
   if(z.get_bit(0) != yMod2)
42
168
      z = curve_p - z;
43
44
522
   return z;
45
522
   }
ecc_bp256.cpp:(anonymous namespace)::decompress_point(bool, Botan::BigInt const&, Botan::BigInt const&, Botan::BigInt const&, Botan::BigInt const&)
Line
Count
Source
28
846
   {
29
846
   Botan::BigInt xpow3 = x * x * x;
30
31
846
   Botan::BigInt g = curve_a * x;
32
846
   g += xpow3;
33
846
   g += curve_b;
34
846
   g = g % curve_p;
35
36
846
   Botan::BigInt z = ressol(g, curve_p);
37
38
846
   if(z < 0)
39
475
      throw Botan::Exception("Could not perform square root");
40
41
371
   if(z.get_bit(0) != yMod2)
42
186
      z = curve_p - z;
43
44
371
   return z;
45
371
   }
ecc_p256.cpp:(anonymous namespace)::decompress_point(bool, Botan::BigInt const&, Botan::BigInt const&, Botan::BigInt const&, Botan::BigInt const&)
Line
Count
Source
28
875
   {
29
875
   Botan::BigInt xpow3 = x * x * x;
30
31
875
   Botan::BigInt g = curve_a * x;
32
875
   g += xpow3;
33
875
   g += curve_b;
34
875
   g = g % curve_p;
35
36
875
   Botan::BigInt z = ressol(g, curve_p);
37
38
875
   if(z < 0)
39
389
      throw Botan::Exception("Could not perform square root");
40
41
486
   if(z.get_bit(0) != yMod2)
42
310
      z = curve_p - z;
43
44
486
   return z;
45
486
   }
ecc_p521.cpp:(anonymous namespace)::decompress_point(bool, Botan::BigInt const&, Botan::BigInt const&, Botan::BigInt const&, Botan::BigInt const&)
Line
Count
Source
28
903
   {
29
903
   Botan::BigInt xpow3 = x * x * x;
30
31
903
   Botan::BigInt g = curve_a * x;
32
903
   g += xpow3;
33
903
   g += curve_b;
34
903
   g = g % curve_p;
35
36
903
   Botan::BigInt z = ressol(g, curve_p);
37
38
903
   if(z < 0)
39
342
      throw Botan::Exception("Could not perform square root");
40
41
561
   if(z.get_bit(0) != yMod2)
42
382
      z = curve_p - z;
43
44
561
   return z;
45
561
   }
46
47
void check_ecc_math(const Botan::EC_Group& group,
48
                    const uint8_t in[], size_t len)
49
3.51k
   {
50
   // These depend only on the group, which is also static
51
3.51k
   static const Botan::PointGFp base_point = group.get_base_point();
52
53
   // This is shared across runs to reduce overhead
54
3.51k
   static std::vector<Botan::BigInt> ws(Botan::PointGFp::WORKSPACE_SIZE);
55
56
3.51k
   const size_t hlen = len / 2;
57
3.51k
   const Botan::BigInt a = Botan::BigInt::decode(in, hlen);
58
3.51k
   const Botan::BigInt b = Botan::BigInt::decode(in + hlen, len - hlen);
59
3.51k
   const Botan::BigInt c = a + b;
60
61
3.51k
   const Botan::PointGFp P1 = base_point * a;
62
3.51k
   const Botan::PointGFp Q1 = base_point * b;
63
3.51k
   const Botan::PointGFp R1 = base_point * c;
64
65
3.51k
   const Botan::PointGFp S1 = P1 + Q1;
66
3.51k
   const Botan::PointGFp T1 = Q1 + P1;
67
68
3.51k
   FUZZER_ASSERT_EQUAL(S1, R1);
69
3.51k
   FUZZER_ASSERT_EQUAL(T1, R1);
70
71
3.51k
   const Botan::PointGFp P2 = group.blinded_base_point_multiply(a, fuzzer_rng(), ws);
72
3.51k
   const Botan::PointGFp Q2 = group.blinded_base_point_multiply(b, fuzzer_rng(), ws);
73
3.51k
   const Botan::PointGFp R2 = group.blinded_base_point_multiply(c, fuzzer_rng(), ws);
74
3.51k
   const Botan::PointGFp S2 = P2 + Q2;
75
3.51k
   const Botan::PointGFp T2 = Q2 + P2;
76
77
3.51k
   FUZZER_ASSERT_EQUAL(S2, R2);
78
3.51k
   FUZZER_ASSERT_EQUAL(T2, R2);
79
80
3.51k
   const Botan::PointGFp P3 = group.blinded_var_point_multiply(base_point, a, fuzzer_rng(), ws);
81
3.51k
   const Botan::PointGFp Q3 = group.blinded_var_point_multiply(base_point, b, fuzzer_rng(), ws);
82
3.51k
   const Botan::PointGFp R3 = group.blinded_var_point_multiply(base_point, c, fuzzer_rng(), ws);
83
3.51k
   const Botan::PointGFp S3 = P3 + Q3;
84
3.51k
   const Botan::PointGFp T3 = Q3 + P3;
85
86
3.51k
   FUZZER_ASSERT_EQUAL(S3, R3);
87
3.51k
   FUZZER_ASSERT_EQUAL(T3, R3);
88
89
3.51k
   FUZZER_ASSERT_EQUAL(S1, S2);
90
3.51k
   FUZZER_ASSERT_EQUAL(S1, S3);
91
92
3.51k
   try
93
3.51k
      {
94
3.51k
      const auto yp = decompress_point(true, a, group.get_p(), group.get_a(), group.get_b());
95
3.51k
      const auto pt_p = group.blinded_var_point_multiply(group.point(a, yp), b, fuzzer_rng(), ws);
96
97
3.51k
      const auto yn = -yp;
98
3.51k
      const auto pt_n = group.blinded_var_point_multiply(group.point(a, yn), b, fuzzer_rng(), ws);
99
100
3.51k
      FUZZER_ASSERT_EQUAL(pt_p, -pt_n);
101
3.51k
      }
102
3.51k
   catch(...) {}
103
3.51k
   }
ecc_p384.cpp:(anonymous namespace)::check_ecc_math(Botan::EC_Group const&, unsigned char const*, unsigned long)
Line
Count
Source
49
894
   {
50
   // These depend only on the group, which is also static
51
894
   static const Botan::PointGFp base_point = group.get_base_point();
52
53
   // This is shared across runs to reduce overhead
54
894
   static std::vector<Botan::BigInt> ws(Botan::PointGFp::WORKSPACE_SIZE);
55
56
894
   const size_t hlen = len / 2;
57
894
   const Botan::BigInt a = Botan::BigInt::decode(in, hlen);
58
894
   const Botan::BigInt b = Botan::BigInt::decode(in + hlen, len - hlen);
59
894
   const Botan::BigInt c = a + b;
60
61
894
   const Botan::PointGFp P1 = base_point * a;
62
894
   const Botan::PointGFp Q1 = base_point * b;
63
894
   const Botan::PointGFp R1 = base_point * c;
64
65
894
   const Botan::PointGFp S1 = P1 + Q1;
66
894
   const Botan::PointGFp T1 = Q1 + P1;
67
68
894
   FUZZER_ASSERT_EQUAL(S1, R1);
69
894
   FUZZER_ASSERT_EQUAL(T1, R1);
70
71
894
   const Botan::PointGFp P2 = group.blinded_base_point_multiply(a, fuzzer_rng(), ws);
72
894
   const Botan::PointGFp Q2 = group.blinded_base_point_multiply(b, fuzzer_rng(), ws);
73
894
   const Botan::PointGFp R2 = group.blinded_base_point_multiply(c, fuzzer_rng(), ws);
74
894
   const Botan::PointGFp S2 = P2 + Q2;
75
894
   const Botan::PointGFp T2 = Q2 + P2;
76
77
894
   FUZZER_ASSERT_EQUAL(S2, R2);
78
894
   FUZZER_ASSERT_EQUAL(T2, R2);
79
80
894
   const Botan::PointGFp P3 = group.blinded_var_point_multiply(base_point, a, fuzzer_rng(), ws);
81
894
   const Botan::PointGFp Q3 = group.blinded_var_point_multiply(base_point, b, fuzzer_rng(), ws);
82
894
   const Botan::PointGFp R3 = group.blinded_var_point_multiply(base_point, c, fuzzer_rng(), ws);
83
894
   const Botan::PointGFp S3 = P3 + Q3;
84
894
   const Botan::PointGFp T3 = Q3 + P3;
85
86
894
   FUZZER_ASSERT_EQUAL(S3, R3);
87
894
   FUZZER_ASSERT_EQUAL(T3, R3);
88
89
894
   FUZZER_ASSERT_EQUAL(S1, S2);
90
894
   FUZZER_ASSERT_EQUAL(S1, S3);
91
92
894
   try
93
894
      {
94
894
      const auto yp = decompress_point(true, a, group.get_p(), group.get_a(), group.get_b());
95
894
      const auto pt_p = group.blinded_var_point_multiply(group.point(a, yp), b, fuzzer_rng(), ws);
96
97
894
      const auto yn = -yp;
98
894
      const auto pt_n = group.blinded_var_point_multiply(group.point(a, yn), b, fuzzer_rng(), ws);
99
100
894
      FUZZER_ASSERT_EQUAL(pt_p, -pt_n);
101
894
      }
102
894
   catch(...) {}
103
894
   }
ecc_bp256.cpp:(anonymous namespace)::check_ecc_math(Botan::EC_Group const&, unsigned char const*, unsigned long)
Line
Count
Source
49
846
   {
50
   // These depend only on the group, which is also static
51
846
   static const Botan::PointGFp base_point = group.get_base_point();
52
53
   // This is shared across runs to reduce overhead
54
846
   static std::vector<Botan::BigInt> ws(Botan::PointGFp::WORKSPACE_SIZE);
55
56
846
   const size_t hlen = len / 2;
57
846
   const Botan::BigInt a = Botan::BigInt::decode(in, hlen);
58
846
   const Botan::BigInt b = Botan::BigInt::decode(in + hlen, len - hlen);
59
846
   const Botan::BigInt c = a + b;
60
61
846
   const Botan::PointGFp P1 = base_point * a;
62
846
   const Botan::PointGFp Q1 = base_point * b;
63
846
   const Botan::PointGFp R1 = base_point * c;
64
65
846
   const Botan::PointGFp S1 = P1 + Q1;
66
846
   const Botan::PointGFp T1 = Q1 + P1;
67
68
846
   FUZZER_ASSERT_EQUAL(S1, R1);
69
846
   FUZZER_ASSERT_EQUAL(T1, R1);
70
71
846
   const Botan::PointGFp P2 = group.blinded_base_point_multiply(a, fuzzer_rng(), ws);
72
846
   const Botan::PointGFp Q2 = group.blinded_base_point_multiply(b, fuzzer_rng(), ws);
73
846
   const Botan::PointGFp R2 = group.blinded_base_point_multiply(c, fuzzer_rng(), ws);
74
846
   const Botan::PointGFp S2 = P2 + Q2;
75
846
   const Botan::PointGFp T2 = Q2 + P2;
76
77
846
   FUZZER_ASSERT_EQUAL(S2, R2);
78
846
   FUZZER_ASSERT_EQUAL(T2, R2);
79
80
846
   const Botan::PointGFp P3 = group.blinded_var_point_multiply(base_point, a, fuzzer_rng(), ws);
81
846
   const Botan::PointGFp Q3 = group.blinded_var_point_multiply(base_point, b, fuzzer_rng(), ws);
82
846
   const Botan::PointGFp R3 = group.blinded_var_point_multiply(base_point, c, fuzzer_rng(), ws);
83
846
   const Botan::PointGFp S3 = P3 + Q3;
84
846
   const Botan::PointGFp T3 = Q3 + P3;
85
86
846
   FUZZER_ASSERT_EQUAL(S3, R3);
87
846
   FUZZER_ASSERT_EQUAL(T3, R3);
88
89
846
   FUZZER_ASSERT_EQUAL(S1, S2);
90
846
   FUZZER_ASSERT_EQUAL(S1, S3);
91
92
846
   try
93
846
      {
94
846
      const auto yp = decompress_point(true, a, group.get_p(), group.get_a(), group.get_b());
95
846
      const auto pt_p = group.blinded_var_point_multiply(group.point(a, yp), b, fuzzer_rng(), ws);
96
97
846
      const auto yn = -yp;
98
846
      const auto pt_n = group.blinded_var_point_multiply(group.point(a, yn), b, fuzzer_rng(), ws);
99
100
846
      FUZZER_ASSERT_EQUAL(pt_p, -pt_n);
101
846
      }
102
846
   catch(...) {}
103
846
   }
ecc_p256.cpp:(anonymous namespace)::check_ecc_math(Botan::EC_Group const&, unsigned char const*, unsigned long)
Line
Count
Source
49
875
   {
50
   // These depend only on the group, which is also static
51
875
   static const Botan::PointGFp base_point = group.get_base_point();
52
53
   // This is shared across runs to reduce overhead
54
875
   static std::vector<Botan::BigInt> ws(Botan::PointGFp::WORKSPACE_SIZE);
55
56
875
   const size_t hlen = len / 2;
57
875
   const Botan::BigInt a = Botan::BigInt::decode(in, hlen);
58
875
   const Botan::BigInt b = Botan::BigInt::decode(in + hlen, len - hlen);
59
875
   const Botan::BigInt c = a + b;
60
61
875
   const Botan::PointGFp P1 = base_point * a;
62
875
   const Botan::PointGFp Q1 = base_point * b;
63
875
   const Botan::PointGFp R1 = base_point * c;
64
65
875
   const Botan::PointGFp S1 = P1 + Q1;
66
875
   const Botan::PointGFp T1 = Q1 + P1;
67
68
875
   FUZZER_ASSERT_EQUAL(S1, R1);
69
875
   FUZZER_ASSERT_EQUAL(T1, R1);
70
71
875
   const Botan::PointGFp P2 = group.blinded_base_point_multiply(a, fuzzer_rng(), ws);
72
875
   const Botan::PointGFp Q2 = group.blinded_base_point_multiply(b, fuzzer_rng(), ws);
73
875
   const Botan::PointGFp R2 = group.blinded_base_point_multiply(c, fuzzer_rng(), ws);
74
875
   const Botan::PointGFp S2 = P2 + Q2;
75
875
   const Botan::PointGFp T2 = Q2 + P2;
76
77
875
   FUZZER_ASSERT_EQUAL(S2, R2);
78
875
   FUZZER_ASSERT_EQUAL(T2, R2);
79
80
875
   const Botan::PointGFp P3 = group.blinded_var_point_multiply(base_point, a, fuzzer_rng(), ws);
81
875
   const Botan::PointGFp Q3 = group.blinded_var_point_multiply(base_point, b, fuzzer_rng(), ws);
82
875
   const Botan::PointGFp R3 = group.blinded_var_point_multiply(base_point, c, fuzzer_rng(), ws);
83
875
   const Botan::PointGFp S3 = P3 + Q3;
84
875
   const Botan::PointGFp T3 = Q3 + P3;
85
86
875
   FUZZER_ASSERT_EQUAL(S3, R3);
87
875
   FUZZER_ASSERT_EQUAL(T3, R3);
88
89
875
   FUZZER_ASSERT_EQUAL(S1, S2);
90
875
   FUZZER_ASSERT_EQUAL(S1, S3);
91
92
875
   try
93
875
      {
94
875
      const auto yp = decompress_point(true, a, group.get_p(), group.get_a(), group.get_b());
95
875
      const auto pt_p = group.blinded_var_point_multiply(group.point(a, yp), b, fuzzer_rng(), ws);
96
97
875
      const auto yn = -yp;
98
875
      const auto pt_n = group.blinded_var_point_multiply(group.point(a, yn), b, fuzzer_rng(), ws);
99
100
875
      FUZZER_ASSERT_EQUAL(pt_p, -pt_n);
101
875
      }
102
875
   catch(...) {}
103
875
   }
ecc_p521.cpp:(anonymous namespace)::check_ecc_math(Botan::EC_Group const&, unsigned char const*, unsigned long)
Line
Count
Source
49
903
   {
50
   // These depend only on the group, which is also static
51
903
   static const Botan::PointGFp base_point = group.get_base_point();
52
53
   // This is shared across runs to reduce overhead
54
903
   static std::vector<Botan::BigInt> ws(Botan::PointGFp::WORKSPACE_SIZE);
55
56
903
   const size_t hlen = len / 2;
57
903
   const Botan::BigInt a = Botan::BigInt::decode(in, hlen);
58
903
   const Botan::BigInt b = Botan::BigInt::decode(in + hlen, len - hlen);
59
903
   const Botan::BigInt c = a + b;
60
61
903
   const Botan::PointGFp P1 = base_point * a;
62
903
   const Botan::PointGFp Q1 = base_point * b;
63
903
   const Botan::PointGFp R1 = base_point * c;
64
65
903
   const Botan::PointGFp S1 = P1 + Q1;
66
903
   const Botan::PointGFp T1 = Q1 + P1;
67
68
903
   FUZZER_ASSERT_EQUAL(S1, R1);
69
903
   FUZZER_ASSERT_EQUAL(T1, R1);
70
71
903
   const Botan::PointGFp P2 = group.blinded_base_point_multiply(a, fuzzer_rng(), ws);
72
903
   const Botan::PointGFp Q2 = group.blinded_base_point_multiply(b, fuzzer_rng(), ws);
73
903
   const Botan::PointGFp R2 = group.blinded_base_point_multiply(c, fuzzer_rng(), ws);
74
903
   const Botan::PointGFp S2 = P2 + Q2;
75
903
   const Botan::PointGFp T2 = Q2 + P2;
76
77
903
   FUZZER_ASSERT_EQUAL(S2, R2);
78
903
   FUZZER_ASSERT_EQUAL(T2, R2);
79
80
903
   const Botan::PointGFp P3 = group.blinded_var_point_multiply(base_point, a, fuzzer_rng(), ws);
81
903
   const Botan::PointGFp Q3 = group.blinded_var_point_multiply(base_point, b, fuzzer_rng(), ws);
82
903
   const Botan::PointGFp R3 = group.blinded_var_point_multiply(base_point, c, fuzzer_rng(), ws);
83
903
   const Botan::PointGFp S3 = P3 + Q3;
84
903
   const Botan::PointGFp T3 = Q3 + P3;
85
86
903
   FUZZER_ASSERT_EQUAL(S3, R3);
87
903
   FUZZER_ASSERT_EQUAL(T3, R3);
88
89
903
   FUZZER_ASSERT_EQUAL(S1, S2);
90
903
   FUZZER_ASSERT_EQUAL(S1, S3);
91
92
903
   try
93
903
      {
94
903
      const auto yp = decompress_point(true, a, group.get_p(), group.get_a(), group.get_b());
95
903
      const auto pt_p = group.blinded_var_point_multiply(group.point(a, yp), b, fuzzer_rng(), ws);
96
97
903
      const auto yn = -yp;
98
903
      const auto pt_n = group.blinded_var_point_multiply(group.point(a, yn), b, fuzzer_rng(), ws);
99
100
903
      FUZZER_ASSERT_EQUAL(pt_p, -pt_n);
101
903
      }
102
903
   catch(...) {}
103
903
   }
104
105
}
106
107
#endif