Coverage Report

Created: 2021-02-21 07:20

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