Coverage Report

Created: 2020-03-26 13:53

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