/src/botan/src/lib/pubkey/ec_group/ec_scalar.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_scalar.h> |
8 | | |
9 | | #include <botan/ec_group.h> |
10 | | #include <botan/internal/ec_inner_data.h> |
11 | | |
12 | | namespace Botan { |
13 | | |
14 | 0 | EC_Scalar EC_Scalar::_from_inner(std::unique_ptr<EC_Scalar_Data> inner) { |
15 | 0 | return EC_Scalar(std::move(inner)); |
16 | 0 | } |
17 | | |
18 | 35.8k | EC_Scalar::EC_Scalar(std::unique_ptr<EC_Scalar_Data> scalar) : m_scalar(std::move(scalar)) { |
19 | 35.8k | BOTAN_ASSERT_NONNULL(m_scalar); |
20 | 35.8k | } |
21 | | |
22 | 1.26k | EC_Scalar::EC_Scalar(const EC_Scalar& other) : m_scalar(other.inner().clone()) {} |
23 | | |
24 | 24.6k | EC_Scalar::EC_Scalar(EC_Scalar&& other) noexcept : m_scalar(std::move(other.m_scalar)) {} |
25 | | |
26 | 0 | EC_Scalar& EC_Scalar::operator=(const EC_Scalar& other) { |
27 | 0 | if(this != &other) { |
28 | 0 | this->assign(other); |
29 | 0 | } |
30 | 0 | return (*this); |
31 | 0 | } |
32 | | |
33 | 0 | EC_Scalar& EC_Scalar::operator=(EC_Scalar&& other) noexcept { |
34 | 0 | BOTAN_ARG_CHECK(_inner().group() == other._inner().group(), "Curve mismatch"); |
35 | 0 | std::swap(m_scalar, other.m_scalar); |
36 | 0 | return (*this); |
37 | 0 | } |
38 | | |
39 | 62.1k | EC_Scalar::~EC_Scalar() = default; |
40 | | |
41 | 0 | size_t EC_Scalar::bytes() const { |
42 | 0 | return m_scalar->bytes(); |
43 | 0 | } |
44 | | |
45 | 347 | EC_Scalar EC_Scalar::from_bytes_with_trunc(const EC_Group& group, std::span<const uint8_t> bytes) { |
46 | 347 | return EC_Scalar(group._data()->scalar_from_bytes_with_trunc(bytes)); |
47 | 347 | } |
48 | | |
49 | 201 | EC_Scalar EC_Scalar::from_bytes_mod_order(const EC_Group& group, std::span<const uint8_t> bytes) { |
50 | 201 | if(auto s = group._data()->scalar_from_bytes_mod_order(bytes)) { |
51 | 200 | return EC_Scalar(std::move(s)); |
52 | 200 | } else { |
53 | 1 | throw Decoding_Error("EC_Scalar::from_bytes_mod_order input invalid"); |
54 | 1 | } |
55 | 201 | } |
56 | | |
57 | 11.0k | EC_Scalar EC_Scalar::random(const EC_Group& group, RandomNumberGenerator& rng) { |
58 | 11.0k | return EC_Scalar(group._data()->scalar_random(rng)); |
59 | 11.0k | } |
60 | | |
61 | 0 | EC_Scalar EC_Scalar::one(const EC_Group& group) { |
62 | 0 | return EC_Scalar(group._data()->scalar_one()); |
63 | 0 | } |
64 | | |
65 | 21.2k | EC_Scalar EC_Scalar::from_bigint(const EC_Group& group, const BigInt& bn) { |
66 | 21.2k | if(auto data = group._data()->scalar_from_bigint(bn)) { |
67 | 21.2k | return EC_Scalar(std::move(data)); |
68 | 21.2k | } else { |
69 | 0 | throw Invalid_Argument("EC_Scalar::from_bigint input out of range"); |
70 | 0 | } |
71 | 21.2k | } |
72 | | |
73 | 11.4k | BigInt EC_Scalar::to_bigint() const { |
74 | 11.4k | secure_vector<uint8_t> bytes(m_scalar->bytes()); |
75 | 11.4k | m_scalar->serialize_to(bytes); |
76 | 11.4k | return BigInt::from_bytes(bytes); |
77 | 11.4k | } |
78 | | |
79 | 0 | EC_Scalar EC_Scalar::gk_x_mod_order(const EC_Scalar& scalar, RandomNumberGenerator& rng, std::vector<BigInt>& ws) { |
80 | 0 | const auto& group = scalar._inner().group(); |
81 | 0 | return EC_Scalar(group->gk_x_mod_order(scalar.inner(), rng, ws)); |
82 | 0 | } |
83 | | |
84 | 0 | void EC_Scalar::serialize_to(std::span<uint8_t> bytes) const { |
85 | 0 | inner().serialize_to(bytes); |
86 | 0 | } |
87 | | |
88 | 0 | void EC_Scalar::serialize_pair_to(std::span<uint8_t> bytes, const EC_Scalar& r, const EC_Scalar& s) { |
89 | 0 | BOTAN_ARG_CHECK(r._inner().group() == s._inner().group(), "Curve mismatch"); |
90 | 0 | const size_t scalar_bytes = r.bytes(); |
91 | 0 | BOTAN_ARG_CHECK(bytes.size() == 2 * scalar_bytes, "Invalid output length"); |
92 | 0 | r.serialize_to(bytes.first(scalar_bytes)); |
93 | 0 | s.serialize_to(bytes.last(scalar_bytes)); |
94 | 0 | } |
95 | | |
96 | | std::optional<std::pair<EC_Scalar, EC_Scalar>> EC_Scalar::deserialize_pair(const EC_Group& group, |
97 | 759 | std::span<const uint8_t> bytes) { |
98 | 759 | if(bytes.size() % 2 != 0) { |
99 | 1 | return {}; |
100 | 1 | } |
101 | | |
102 | 758 | const size_t half = bytes.size() / 2; |
103 | | |
104 | 758 | auto r = EC_Scalar::deserialize(group, bytes.first(half)); |
105 | 758 | auto s = EC_Scalar::deserialize(group, bytes.last(half)); |
106 | | |
107 | 758 | if(r && s) { |
108 | 548 | return std::make_pair(r.value(), s.value()); |
109 | 548 | } else { |
110 | 210 | return {}; |
111 | 210 | } |
112 | 758 | } |
113 | | |
114 | 1.51k | std::optional<EC_Scalar> EC_Scalar::deserialize(const EC_Group& group, std::span<const uint8_t> bytes) { |
115 | 1.51k | if(auto v = group._data()->scalar_deserialize(bytes)) { |
116 | 1.13k | return EC_Scalar(std::move(v)); |
117 | 1.13k | } else { |
118 | 386 | return {}; |
119 | 386 | } |
120 | 1.51k | } |
121 | | |
122 | 509 | EC_Scalar::EC_Scalar(const EC_Group& group, std::span<const uint8_t> bytes) { |
123 | 509 | m_scalar = group._data()->scalar_deserialize(bytes); |
124 | 509 | if(!m_scalar) { |
125 | 105 | throw Decoding_Error("EC_Scalar::from_bytes is not a valid scalar value"); |
126 | 105 | } |
127 | 509 | } |
128 | | |
129 | 1.29k | bool EC_Scalar::is_zero() const { |
130 | 1.29k | return inner().is_zero(); |
131 | 1.29k | } |
132 | | |
133 | 547 | EC_Scalar EC_Scalar::invert() const { |
134 | 547 | return EC_Scalar(inner().invert()); |
135 | 547 | } |
136 | | |
137 | 200 | EC_Scalar EC_Scalar::negate() const { |
138 | 200 | return EC_Scalar(inner().negate()); |
139 | 200 | } |
140 | | |
141 | 0 | void EC_Scalar::square_self() { |
142 | 0 | m_scalar->square_self(); |
143 | 0 | } |
144 | | |
145 | 0 | EC_Scalar EC_Scalar::add(const EC_Scalar& x) const { |
146 | 0 | return EC_Scalar(inner().add(x.inner())); |
147 | 0 | } |
148 | | |
149 | 0 | EC_Scalar EC_Scalar::sub(const EC_Scalar& x) const { |
150 | 0 | return EC_Scalar(inner().sub(x.inner())); |
151 | 0 | } |
152 | | |
153 | 1.09k | EC_Scalar EC_Scalar::mul(const EC_Scalar& x) const { |
154 | 1.09k | return EC_Scalar(inner().mul(x.inner())); |
155 | 1.09k | } |
156 | | |
157 | 0 | void EC_Scalar::assign(const EC_Scalar& x) { |
158 | 0 | m_scalar->assign(x.inner()); |
159 | 0 | } |
160 | | |
161 | 0 | bool EC_Scalar::is_eq(const EC_Scalar& x) const { |
162 | 0 | return inner().is_eq(x.inner()); |
163 | 0 | } |
164 | | |
165 | | } // namespace Botan |