/src/botan/src/lib/pubkey/ec_group/ec_apoint.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * (C) 2024 Jack Lloyd |
3 | | * |
4 | | * Botan is released under the Simplified BSD License (see license.txt) |
5 | | */ |
6 | | |
7 | | #include <botan/ec_apoint.h> |
8 | | |
9 | | #include <botan/ec_group.h> |
10 | | #include <botan/ec_scalar.h> |
11 | | #include <botan/internal/ec_inner_data.h> |
12 | | |
13 | | namespace Botan { |
14 | | |
15 | 34.6k | EC_AffinePoint::EC_AffinePoint(std::unique_ptr<EC_AffinePoint_Data> point) : m_point(std::move(point)) { |
16 | 34.6k | BOTAN_ASSERT_NONNULL(m_point); |
17 | 34.6k | } |
18 | | |
19 | 0 | EC_AffinePoint::EC_AffinePoint(const EC_AffinePoint& other) : m_point(other.inner().clone()) {} |
20 | | |
21 | 24.8k | EC_AffinePoint::EC_AffinePoint(EC_AffinePoint&& other) noexcept : m_point(std::move(other.m_point)) {} |
22 | | |
23 | 0 | EC_AffinePoint& EC_AffinePoint::operator=(const EC_AffinePoint& other) { |
24 | 0 | if(this != &other) { |
25 | 0 | m_point = other.inner().clone(); |
26 | 0 | } |
27 | 0 | return (*this); |
28 | 0 | } |
29 | | |
30 | 0 | EC_AffinePoint& EC_AffinePoint::operator=(EC_AffinePoint&& other) noexcept { |
31 | 0 | m_point.swap(other.m_point); |
32 | 0 | return (*this); |
33 | 0 | } |
34 | | |
35 | 16.2k | EC_AffinePoint::EC_AffinePoint(const EC_Group& group, std::span<const uint8_t> bytes) { |
36 | 16.2k | m_point = group._data()->point_deserialize(bytes); |
37 | 16.2k | if(!m_point) { |
38 | 3.35k | throw Decoding_Error("Failed to deserialize elliptic curve point"); |
39 | 3.35k | } |
40 | 16.2k | } |
41 | | |
42 | | EC_AffinePoint::EC_AffinePoint(const EC_Group& group, const EC_Point& pt) : |
43 | 11.7k | EC_AffinePoint(group, pt.encode(EC_Point_Format::Uncompressed)) {} |
44 | | |
45 | 0 | EC_AffinePoint EC_AffinePoint::identity(const EC_Group& group) { |
46 | 0 | const uint8_t id_encoding[1] = {0}; |
47 | 0 | return EC_AffinePoint(group, id_encoding); |
48 | 0 | } |
49 | | |
50 | 0 | EC_AffinePoint EC_AffinePoint::generator(const EC_Group& group) { |
51 | 0 | return EC_AffinePoint(group, group.get_base_point()); |
52 | 0 | } |
53 | | |
54 | 3.72k | std::optional<EC_AffinePoint> EC_AffinePoint::from_bigint_xy(const EC_Group& group, const BigInt& x, const BigInt& y) { |
55 | 3.72k | if(x.is_negative() || x >= group.get_p()) { |
56 | 0 | return {}; |
57 | 0 | } |
58 | 3.72k | if(y.is_negative() || y >= group.get_p()) { |
59 | 1.86k | return {}; |
60 | 1.86k | } |
61 | | |
62 | 1.86k | const size_t fe_bytes = group.get_p_bytes(); |
63 | 1.86k | std::vector<uint8_t> sec1(1 + 2 * fe_bytes); |
64 | 1.86k | sec1[0] = 0x04; |
65 | 1.86k | x.serialize_to(std::span{sec1}.subspan(1, fe_bytes)); |
66 | 1.86k | y.serialize_to(std::span{sec1}.last(fe_bytes)); |
67 | | |
68 | 1.86k | return EC_AffinePoint::deserialize(group, sec1); |
69 | 3.72k | } |
70 | | |
71 | 173 | size_t EC_AffinePoint::field_element_bytes() const { |
72 | 173 | return inner().field_element_bytes(); |
73 | 173 | } |
74 | | |
75 | 173 | bool EC_AffinePoint::is_identity() const { |
76 | 173 | return inner().is_identity(); |
77 | 173 | } |
78 | | |
79 | | EC_AffinePoint EC_AffinePoint::hash_to_curve_ro(const EC_Group& group, |
80 | | std::string_view hash_fn, |
81 | | std::span<const uint8_t> input, |
82 | 0 | std::span<const uint8_t> domain_sep) { |
83 | 0 | auto pt = group._data()->point_hash_to_curve_ro(hash_fn, input, domain_sep); |
84 | 0 | return EC_AffinePoint(std::move(pt)); |
85 | 0 | } |
86 | | |
87 | | EC_AffinePoint EC_AffinePoint::hash_to_curve_nu(const EC_Group& group, |
88 | | std::string_view hash_fn, |
89 | | std::span<const uint8_t> input, |
90 | 0 | std::span<const uint8_t> domain_sep) { |
91 | 0 | auto pt = group._data()->point_hash_to_curve_nu(hash_fn, input, domain_sep); |
92 | 0 | return EC_AffinePoint(std::move(pt)); |
93 | 0 | } |
94 | | |
95 | 72.3k | EC_AffinePoint::~EC_AffinePoint() = default; |
96 | | |
97 | 2.03k | std::optional<EC_AffinePoint> EC_AffinePoint::deserialize(const EC_Group& group, std::span<const uint8_t> bytes) { |
98 | 2.03k | if(auto pt = group._data()->point_deserialize(bytes)) { |
99 | 2.03k | return EC_AffinePoint(std::move(pt)); |
100 | 2.03k | } else { |
101 | 0 | return {}; |
102 | 0 | } |
103 | 2.03k | } |
104 | | |
105 | 20.9k | EC_AffinePoint EC_AffinePoint::g_mul(const EC_Scalar& scalar, RandomNumberGenerator& rng, std::vector<BigInt>& ws) { |
106 | 20.9k | auto pt = scalar._inner().group()->point_g_mul(scalar.inner(), rng, ws); |
107 | 20.9k | return EC_AffinePoint(std::move(pt)); |
108 | 20.9k | } |
109 | | |
110 | 11.7k | EC_AffinePoint EC_AffinePoint::mul(const EC_Scalar& scalar, RandomNumberGenerator& rng, std::vector<BigInt>& ws) const { |
111 | 11.7k | return EC_AffinePoint(inner().mul(scalar._inner(), rng, ws)); |
112 | 11.7k | } |
113 | | |
114 | | std::optional<EC_AffinePoint> EC_AffinePoint::mul_px_qy(const EC_AffinePoint& p, |
115 | | const EC_Scalar& x, |
116 | | const EC_AffinePoint& q, |
117 | | const EC_Scalar& y, |
118 | 0 | RandomNumberGenerator& rng) { |
119 | 0 | auto pt = p._inner().group()->mul_px_qy(p._inner(), x._inner(), q._inner(), y._inner(), rng); |
120 | 0 | if(pt) { |
121 | 0 | return EC_AffinePoint(std::move(pt)); |
122 | 0 | } else { |
123 | 0 | return {}; |
124 | 0 | } |
125 | 0 | } |
126 | | |
127 | 0 | EC_AffinePoint EC_AffinePoint::add(const EC_AffinePoint& q) const { |
128 | 0 | auto pt = _inner().group()->affine_add(_inner(), q._inner()); |
129 | 0 | return EC_AffinePoint(std::move(pt)); |
130 | 0 | } |
131 | | |
132 | 0 | EC_AffinePoint EC_AffinePoint::negate() const { |
133 | 0 | auto pt = this->_inner().group()->affine_neg(this->_inner()); |
134 | 0 | return EC_AffinePoint(std::move(pt)); |
135 | 0 | } |
136 | | |
137 | 173 | void EC_AffinePoint::serialize_x_to(std::span<uint8_t> bytes) const { |
138 | 173 | BOTAN_STATE_CHECK(!this->is_identity()); |
139 | 173 | m_point->serialize_x_to(bytes); |
140 | 173 | } |
141 | | |
142 | 0 | void EC_AffinePoint::serialize_y_to(std::span<uint8_t> bytes) const { |
143 | 0 | BOTAN_STATE_CHECK(!this->is_identity()); |
144 | 0 | m_point->serialize_y_to(bytes); |
145 | 0 | } |
146 | | |
147 | 0 | void EC_AffinePoint::serialize_xy_to(std::span<uint8_t> bytes) const { |
148 | 0 | BOTAN_STATE_CHECK(!this->is_identity()); |
149 | 0 | m_point->serialize_xy_to(bytes); |
150 | 0 | } |
151 | | |
152 | 0 | void EC_AffinePoint::serialize_compressed_to(std::span<uint8_t> bytes) const { |
153 | 0 | BOTAN_STATE_CHECK(!this->is_identity()); |
154 | 0 | m_point->serialize_compressed_to(bytes); |
155 | 0 | } |
156 | | |
157 | 0 | void EC_AffinePoint::serialize_uncompressed_to(std::span<uint8_t> bytes) const { |
158 | 0 | BOTAN_STATE_CHECK(!this->is_identity()); |
159 | 0 | m_point->serialize_uncompressed_to(bytes); |
160 | 0 | } |
161 | | |
162 | 35.6k | EC_Point EC_AffinePoint::to_legacy_point() const { |
163 | 35.6k | return m_point->to_legacy_point(); |
164 | 35.6k | } |
165 | | |
166 | 0 | EC_AffinePoint EC_AffinePoint::_from_inner(std::unique_ptr<EC_AffinePoint_Data> inner) { |
167 | 0 | return EC_AffinePoint(std::move(inner)); |
168 | 0 | } |
169 | | |
170 | 773 | const std::shared_ptr<const EC_Group_Data>& EC_AffinePoint::_group() const { |
171 | 773 | return inner().group(); |
172 | 773 | } |
173 | | |
174 | | } // namespace Botan |