Coverage Report

Created: 2020-05-23 13:54

/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_p256.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_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
2.59k
   {
29
2.59k
   Botan::BigInt xpow3 = x * x * x;
30
2.59k
31
2.59k
   Botan::BigInt g = curve_a * x;
32
2.59k
   g += xpow3;
33
2.59k
   g += curve_b;
34
2.59k
   g = g % curve_p;
35
2.59k
36
2.59k
   Botan::BigInt z = ressol(g, curve_p);
37
2.59k
38
2.59k
   if(z < 0)
39
1.17k
      throw Botan::Exception("Could not perform square root");
40
1.42k
41
1.42k
   if(z.get_bit(0) != yMod2)
42
778
      z = curve_p - z;
43
1.42k
44
1.42k
   return z;
45
1.42k
   }
ecc_p384.cpp:(anonymous namespace)::decompress_point(bool, Botan::BigInt const&, Botan::BigInt const&, Botan::BigInt const&, Botan::BigInt const&)
Line
Count
Source
28
659
   {
29
659
   Botan::BigInt xpow3 = x * x * x;
30
659
31
659
   Botan::BigInt g = curve_a * x;
32
659
   g += xpow3;
33
659
   g += curve_b;
34
659
   g = g % curve_p;
35
659
36
659
   Botan::BigInt z = ressol(g, curve_p);
37
659
38
659
   if(z < 0)
39
278
      throw Botan::Exception("Could not perform square root");
40
381
41
381
   if(z.get_bit(0) != yMod2)
42
135
      z = curve_p - z;
43
381
44
381
   return z;
45
381
   }
ecc_p256.cpp:(anonymous namespace)::decompress_point(bool, Botan::BigInt const&, Botan::BigInt const&, Botan::BigInt const&, Botan::BigInt const&)
Line
Count
Source
28
639
   {
29
639
   Botan::BigInt xpow3 = x * x * x;
30
639
31
639
   Botan::BigInt g = curve_a * x;
32
639
   g += xpow3;
33
639
   g += curve_b;
34
639
   g = g % curve_p;
35
639
36
639
   Botan::BigInt z = ressol(g, curve_p);
37
639
38
639
   if(z < 0)
39
287
      throw Botan::Exception("Could not perform square root");
40
352
41
352
   if(z.get_bit(0) != yMod2)
42
239
      z = curve_p - z;
43
352
44
352
   return z;
45
352
   }
ecc_bp256.cpp:(anonymous namespace)::decompress_point(bool, Botan::BigInt const&, Botan::BigInt const&, Botan::BigInt const&, Botan::BigInt const&)
Line
Count
Source
28
624
   {
29
624
   Botan::BigInt xpow3 = x * x * x;
30
624
31
624
   Botan::BigInt g = curve_a * x;
32
624
   g += xpow3;
33
624
   g += curve_b;
34
624
   g = g % curve_p;
35
624
36
624
   Botan::BigInt z = ressol(g, curve_p);
37
624
38
624
   if(z < 0)
39
343
      throw Botan::Exception("Could not perform square root");
40
281
41
281
   if(z.get_bit(0) != yMod2)
42
155
      z = curve_p - z;
43
281
44
281
   return z;
45
281
   }
ecc_p521.cpp:(anonymous namespace)::decompress_point(bool, Botan::BigInt const&, Botan::BigInt const&, Botan::BigInt const&, Botan::BigInt const&)
Line
Count
Source
28
675
   {
29
675
   Botan::BigInt xpow3 = x * x * x;
30
675
31
675
   Botan::BigInt g = curve_a * x;
32
675
   g += xpow3;
33
675
   g += curve_b;
34
675
   g = g % curve_p;
35
675
36
675
   Botan::BigInt z = ressol(g, curve_p);
37
675
38
675
   if(z < 0)
39
263
      throw Botan::Exception("Could not perform square root");
40
412
41
412
   if(z.get_bit(0) != yMod2)
42
249
      z = curve_p - z;
43
412
44
412
   return z;
45
412
   }
46
47
void check_ecc_math(const Botan::EC_Group& group,
48
                    const uint8_t in[], size_t len)
49
2.59k
   {
50
2.59k
   // These depend only on the group, which is also static
51
2.59k
   static const Botan::PointGFp base_point = group.get_base_point();
52
2.59k
53
2.59k
   // This is shared across runs to reduce overhead
54
2.59k
   static std::vector<Botan::BigInt> ws(Botan::PointGFp::WORKSPACE_SIZE);
55
2.59k
56
2.59k
   const size_t hlen = len / 2;
57
2.59k
   const Botan::BigInt a = Botan::BigInt::decode(in, hlen);
58
2.59k
   const Botan::BigInt b = Botan::BigInt::decode(in + hlen, len - hlen);
59
2.59k
   const Botan::BigInt c = a + b;
60
2.59k
61
2.59k
   const Botan::PointGFp P1 = base_point * a;
62
2.59k
   const Botan::PointGFp Q1 = base_point * b;
63
2.59k
   const Botan::PointGFp R1 = base_point * c;
64
2.59k
65
2.59k
   const Botan::PointGFp S1 = P1 + Q1;
66
2.59k
   const Botan::PointGFp T1 = Q1 + P1;
67
2.59k
68
2.59k
   FUZZER_ASSERT_EQUAL(S1, R1);
69
2.59k
   FUZZER_ASSERT_EQUAL(T1, R1);
70
2.59k
71
2.59k
   const Botan::PointGFp P2 = group.blinded_base_point_multiply(a, fuzzer_rng(), ws);
72
2.59k
   const Botan::PointGFp Q2 = group.blinded_base_point_multiply(b, fuzzer_rng(), ws);
73
2.59k
   const Botan::PointGFp R2 = group.blinded_base_point_multiply(c, fuzzer_rng(), ws);
74
2.59k
   const Botan::PointGFp S2 = P2 + Q2;
75
2.59k
   const Botan::PointGFp T2 = Q2 + P2;
76
2.59k
77
2.59k
   FUZZER_ASSERT_EQUAL(S2, R2);
78
2.59k
   FUZZER_ASSERT_EQUAL(T2, R2);
79
2.59k
80
2.59k
   const Botan::PointGFp P3 = group.blinded_var_point_multiply(base_point, a, fuzzer_rng(), ws);
81
2.59k
   const Botan::PointGFp Q3 = group.blinded_var_point_multiply(base_point, b, fuzzer_rng(), ws);
82
2.59k
   const Botan::PointGFp R3 = group.blinded_var_point_multiply(base_point, c, fuzzer_rng(), ws);
83
2.59k
   const Botan::PointGFp S3 = P3 + Q3;
84
2.59k
   const Botan::PointGFp T3 = Q3 + P3;
85
2.59k
86
2.59k
   FUZZER_ASSERT_EQUAL(S3, R3);
87
2.59k
   FUZZER_ASSERT_EQUAL(T3, R3);
88
2.59k
89
2.59k
   FUZZER_ASSERT_EQUAL(S1, S2);
90
2.59k
   FUZZER_ASSERT_EQUAL(S1, S3);
91
2.59k
92
2.59k
   try
93
2.59k
      {
94
2.59k
      const auto yp = decompress_point(true, a, group.get_p(), group.get_a(), group.get_b());
95
2.59k
      const auto pt_p = group.blinded_var_point_multiply(group.point(a, yp), b, fuzzer_rng(), ws);
96
2.59k
97
2.59k
      const auto yn = -yp;
98
2.59k
      const auto pt_n = group.blinded_var_point_multiply(group.point(a, yn), b, fuzzer_rng(), ws);
99
2.59k
100
2.59k
      FUZZER_ASSERT_EQUAL(pt_p, -pt_n);
101
2.59k
      }
102
2.59k
   catch(...) {}
103
2.59k
   }
ecc_p384.cpp:(anonymous namespace)::check_ecc_math(Botan::EC_Group const&, unsigned char const*, unsigned long)
Line
Count
Source
49
659
   {
50
659
   // These depend only on the group, which is also static
51
659
   static const Botan::PointGFp base_point = group.get_base_point();
52
659
53
659
   // This is shared across runs to reduce overhead
54
659
   static std::vector<Botan::BigInt> ws(Botan::PointGFp::WORKSPACE_SIZE);
55
659
56
659
   const size_t hlen = len / 2;
57
659
   const Botan::BigInt a = Botan::BigInt::decode(in, hlen);
58
659
   const Botan::BigInt b = Botan::BigInt::decode(in + hlen, len - hlen);
59
659
   const Botan::BigInt c = a + b;
60
659
61
659
   const Botan::PointGFp P1 = base_point * a;
62
659
   const Botan::PointGFp Q1 = base_point * b;
63
659
   const Botan::PointGFp R1 = base_point * c;
64
659
65
659
   const Botan::PointGFp S1 = P1 + Q1;
66
659
   const Botan::PointGFp T1 = Q1 + P1;
67
659
68
659
   FUZZER_ASSERT_EQUAL(S1, R1);
69
659
   FUZZER_ASSERT_EQUAL(T1, R1);
70
659
71
659
   const Botan::PointGFp P2 = group.blinded_base_point_multiply(a, fuzzer_rng(), ws);
72
659
   const Botan::PointGFp Q2 = group.blinded_base_point_multiply(b, fuzzer_rng(), ws);
73
659
   const Botan::PointGFp R2 = group.blinded_base_point_multiply(c, fuzzer_rng(), ws);
74
659
   const Botan::PointGFp S2 = P2 + Q2;
75
659
   const Botan::PointGFp T2 = Q2 + P2;
76
659
77
659
   FUZZER_ASSERT_EQUAL(S2, R2);
78
659
   FUZZER_ASSERT_EQUAL(T2, R2);
79
659
80
659
   const Botan::PointGFp P3 = group.blinded_var_point_multiply(base_point, a, fuzzer_rng(), ws);
81
659
   const Botan::PointGFp Q3 = group.blinded_var_point_multiply(base_point, b, fuzzer_rng(), ws);
82
659
   const Botan::PointGFp R3 = group.blinded_var_point_multiply(base_point, c, fuzzer_rng(), ws);
83
659
   const Botan::PointGFp S3 = P3 + Q3;
84
659
   const Botan::PointGFp T3 = Q3 + P3;
85
659
86
659
   FUZZER_ASSERT_EQUAL(S3, R3);
87
659
   FUZZER_ASSERT_EQUAL(T3, R3);
88
659
89
659
   FUZZER_ASSERT_EQUAL(S1, S2);
90
659
   FUZZER_ASSERT_EQUAL(S1, S3);
91
659
92
659
   try
93
659
      {
94
659
      const auto yp = decompress_point(true, a, group.get_p(), group.get_a(), group.get_b());
95
659
      const auto pt_p = group.blinded_var_point_multiply(group.point(a, yp), b, fuzzer_rng(), ws);
96
659
97
659
      const auto yn = -yp;
98
659
      const auto pt_n = group.blinded_var_point_multiply(group.point(a, yn), b, fuzzer_rng(), ws);
99
659
100
659
      FUZZER_ASSERT_EQUAL(pt_p, -pt_n);
101
659
      }
102
659
   catch(...) {}
103
659
   }
ecc_p256.cpp:(anonymous namespace)::check_ecc_math(Botan::EC_Group const&, unsigned char const*, unsigned long)
Line
Count
Source
49
639
   {
50
639
   // These depend only on the group, which is also static
51
639
   static const Botan::PointGFp base_point = group.get_base_point();
52
639
53
639
   // This is shared across runs to reduce overhead
54
639
   static std::vector<Botan::BigInt> ws(Botan::PointGFp::WORKSPACE_SIZE);
55
639
56
639
   const size_t hlen = len / 2;
57
639
   const Botan::BigInt a = Botan::BigInt::decode(in, hlen);
58
639
   const Botan::BigInt b = Botan::BigInt::decode(in + hlen, len - hlen);
59
639
   const Botan::BigInt c = a + b;
60
639
61
639
   const Botan::PointGFp P1 = base_point * a;
62
639
   const Botan::PointGFp Q1 = base_point * b;
63
639
   const Botan::PointGFp R1 = base_point * c;
64
639
65
639
   const Botan::PointGFp S1 = P1 + Q1;
66
639
   const Botan::PointGFp T1 = Q1 + P1;
67
639
68
639
   FUZZER_ASSERT_EQUAL(S1, R1);
69
639
   FUZZER_ASSERT_EQUAL(T1, R1);
70
639
71
639
   const Botan::PointGFp P2 = group.blinded_base_point_multiply(a, fuzzer_rng(), ws);
72
639
   const Botan::PointGFp Q2 = group.blinded_base_point_multiply(b, fuzzer_rng(), ws);
73
639
   const Botan::PointGFp R2 = group.blinded_base_point_multiply(c, fuzzer_rng(), ws);
74
639
   const Botan::PointGFp S2 = P2 + Q2;
75
639
   const Botan::PointGFp T2 = Q2 + P2;
76
639
77
639
   FUZZER_ASSERT_EQUAL(S2, R2);
78
639
   FUZZER_ASSERT_EQUAL(T2, R2);
79
639
80
639
   const Botan::PointGFp P3 = group.blinded_var_point_multiply(base_point, a, fuzzer_rng(), ws);
81
639
   const Botan::PointGFp Q3 = group.blinded_var_point_multiply(base_point, b, fuzzer_rng(), ws);
82
639
   const Botan::PointGFp R3 = group.blinded_var_point_multiply(base_point, c, fuzzer_rng(), ws);
83
639
   const Botan::PointGFp S3 = P3 + Q3;
84
639
   const Botan::PointGFp T3 = Q3 + P3;
85
639
86
639
   FUZZER_ASSERT_EQUAL(S3, R3);
87
639
   FUZZER_ASSERT_EQUAL(T3, R3);
88
639
89
639
   FUZZER_ASSERT_EQUAL(S1, S2);
90
639
   FUZZER_ASSERT_EQUAL(S1, S3);
91
639
92
639
   try
93
639
      {
94
639
      const auto yp = decompress_point(true, a, group.get_p(), group.get_a(), group.get_b());
95
639
      const auto pt_p = group.blinded_var_point_multiply(group.point(a, yp), b, fuzzer_rng(), ws);
96
639
97
639
      const auto yn = -yp;
98
639
      const auto pt_n = group.blinded_var_point_multiply(group.point(a, yn), b, fuzzer_rng(), ws);
99
639
100
639
      FUZZER_ASSERT_EQUAL(pt_p, -pt_n);
101
639
      }
102
639
   catch(...) {}
103
639
   }
ecc_bp256.cpp:(anonymous namespace)::check_ecc_math(Botan::EC_Group const&, unsigned char const*, unsigned long)
Line
Count
Source
49
624
   {
50
624
   // These depend only on the group, which is also static
51
624
   static const Botan::PointGFp base_point = group.get_base_point();
52
624
53
624
   // This is shared across runs to reduce overhead
54
624
   static std::vector<Botan::BigInt> ws(Botan::PointGFp::WORKSPACE_SIZE);
55
624
56
624
   const size_t hlen = len / 2;
57
624
   const Botan::BigInt a = Botan::BigInt::decode(in, hlen);
58
624
   const Botan::BigInt b = Botan::BigInt::decode(in + hlen, len - hlen);
59
624
   const Botan::BigInt c = a + b;
60
624
61
624
   const Botan::PointGFp P1 = base_point * a;
62
624
   const Botan::PointGFp Q1 = base_point * b;
63
624
   const Botan::PointGFp R1 = base_point * c;
64
624
65
624
   const Botan::PointGFp S1 = P1 + Q1;
66
624
   const Botan::PointGFp T1 = Q1 + P1;
67
624
68
624
   FUZZER_ASSERT_EQUAL(S1, R1);
69
624
   FUZZER_ASSERT_EQUAL(T1, R1);
70
624
71
624
   const Botan::PointGFp P2 = group.blinded_base_point_multiply(a, fuzzer_rng(), ws);
72
624
   const Botan::PointGFp Q2 = group.blinded_base_point_multiply(b, fuzzer_rng(), ws);
73
624
   const Botan::PointGFp R2 = group.blinded_base_point_multiply(c, fuzzer_rng(), ws);
74
624
   const Botan::PointGFp S2 = P2 + Q2;
75
624
   const Botan::PointGFp T2 = Q2 + P2;
76
624
77
624
   FUZZER_ASSERT_EQUAL(S2, R2);
78
624
   FUZZER_ASSERT_EQUAL(T2, R2);
79
624
80
624
   const Botan::PointGFp P3 = group.blinded_var_point_multiply(base_point, a, fuzzer_rng(), ws);
81
624
   const Botan::PointGFp Q3 = group.blinded_var_point_multiply(base_point, b, fuzzer_rng(), ws);
82
624
   const Botan::PointGFp R3 = group.blinded_var_point_multiply(base_point, c, fuzzer_rng(), ws);
83
624
   const Botan::PointGFp S3 = P3 + Q3;
84
624
   const Botan::PointGFp T3 = Q3 + P3;
85
624
86
624
   FUZZER_ASSERT_EQUAL(S3, R3);
87
624
   FUZZER_ASSERT_EQUAL(T3, R3);
88
624
89
624
   FUZZER_ASSERT_EQUAL(S1, S2);
90
624
   FUZZER_ASSERT_EQUAL(S1, S3);
91
624
92
624
   try
93
624
      {
94
624
      const auto yp = decompress_point(true, a, group.get_p(), group.get_a(), group.get_b());
95
624
      const auto pt_p = group.blinded_var_point_multiply(group.point(a, yp), b, fuzzer_rng(), ws);
96
624
97
624
      const auto yn = -yp;
98
624
      const auto pt_n = group.blinded_var_point_multiply(group.point(a, yn), b, fuzzer_rng(), ws);
99
624
100
624
      FUZZER_ASSERT_EQUAL(pt_p, -pt_n);
101
624
      }
102
624
   catch(...) {}
103
624
   }
ecc_p521.cpp:(anonymous namespace)::check_ecc_math(Botan::EC_Group const&, unsigned char const*, unsigned long)
Line
Count
Source
49
675
   {
50
675
   // These depend only on the group, which is also static
51
675
   static const Botan::PointGFp base_point = group.get_base_point();
52
675
53
675
   // This is shared across runs to reduce overhead
54
675
   static std::vector<Botan::BigInt> ws(Botan::PointGFp::WORKSPACE_SIZE);
55
675
56
675
   const size_t hlen = len / 2;
57
675
   const Botan::BigInt a = Botan::BigInt::decode(in, hlen);
58
675
   const Botan::BigInt b = Botan::BigInt::decode(in + hlen, len - hlen);
59
675
   const Botan::BigInt c = a + b;
60
675
61
675
   const Botan::PointGFp P1 = base_point * a;
62
675
   const Botan::PointGFp Q1 = base_point * b;
63
675
   const Botan::PointGFp R1 = base_point * c;
64
675
65
675
   const Botan::PointGFp S1 = P1 + Q1;
66
675
   const Botan::PointGFp T1 = Q1 + P1;
67
675
68
675
   FUZZER_ASSERT_EQUAL(S1, R1);
69
675
   FUZZER_ASSERT_EQUAL(T1, R1);
70
675
71
675
   const Botan::PointGFp P2 = group.blinded_base_point_multiply(a, fuzzer_rng(), ws);
72
675
   const Botan::PointGFp Q2 = group.blinded_base_point_multiply(b, fuzzer_rng(), ws);
73
675
   const Botan::PointGFp R2 = group.blinded_base_point_multiply(c, fuzzer_rng(), ws);
74
675
   const Botan::PointGFp S2 = P2 + Q2;
75
675
   const Botan::PointGFp T2 = Q2 + P2;
76
675
77
675
   FUZZER_ASSERT_EQUAL(S2, R2);
78
675
   FUZZER_ASSERT_EQUAL(T2, R2);
79
675
80
675
   const Botan::PointGFp P3 = group.blinded_var_point_multiply(base_point, a, fuzzer_rng(), ws);
81
675
   const Botan::PointGFp Q3 = group.blinded_var_point_multiply(base_point, b, fuzzer_rng(), ws);
82
675
   const Botan::PointGFp R3 = group.blinded_var_point_multiply(base_point, c, fuzzer_rng(), ws);
83
675
   const Botan::PointGFp S3 = P3 + Q3;
84
675
   const Botan::PointGFp T3 = Q3 + P3;
85
675
86
675
   FUZZER_ASSERT_EQUAL(S3, R3);
87
675
   FUZZER_ASSERT_EQUAL(T3, R3);
88
675
89
675
   FUZZER_ASSERT_EQUAL(S1, S2);
90
675
   FUZZER_ASSERT_EQUAL(S1, S3);
91
675
92
675
   try
93
675
      {
94
675
      const auto yp = decompress_point(true, a, group.get_p(), group.get_a(), group.get_b());
95
675
      const auto pt_p = group.blinded_var_point_multiply(group.point(a, yp), b, fuzzer_rng(), ws);
96
675
97
675
      const auto yn = -yp;
98
675
      const auto pt_n = group.blinded_var_point_multiply(group.point(a, yn), b, fuzzer_rng(), ws);
99
675
100
675
      FUZZER_ASSERT_EQUAL(pt_p, -pt_n);
101
675
      }
102
675
   catch(...) {}
103
675
   }
104
105
}
106
107
#endif