Coverage Report

Created: 2020-02-14 15:38

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