Coverage Report

Created: 2020-08-01 06:18

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