/src/rnp/src/lib/crypto/dilithium_exdsa_composite.cpp
Line | Count | Source |
1 | | /* |
2 | | * Copyright (c) 2023, [MTG AG](https://www.mtg.de). |
3 | | * All rights reserved. |
4 | | * |
5 | | * Redistribution and use in source and binary forms, with or without modification, |
6 | | * are permitted provided that the following conditions are met: |
7 | | * |
8 | | * 1. Redistributions of source code must retain the above copyright notice, |
9 | | * this list of conditions and the following disclaimer. |
10 | | * |
11 | | * 2. Redistributions in binary form must reproduce the above copyright notice, |
12 | | * this list of conditions and the following disclaimer in the documentation |
13 | | * and/or other materials provided with the distribution. |
14 | | * |
15 | | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
16 | | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
17 | | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
18 | | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE |
19 | | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
20 | | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
21 | | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
22 | | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
23 | | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
24 | | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
25 | | */ |
26 | | |
27 | | #include "dilithium_exdsa_composite.h" |
28 | | #include "types.h" |
29 | | #include "logging.h" |
30 | | |
31 | | pgp_dilithium_exdsa_composite_key_t::~pgp_dilithium_exdsa_composite_key_t() |
32 | 42.7k | { |
33 | 42.7k | } |
34 | | |
35 | | void |
36 | | pgp_dilithium_exdsa_composite_key_t::initialized_or_throw() const |
37 | 4.67k | { |
38 | 4.67k | if (!is_initialized()) { |
39 | 0 | RNP_LOG("Trying to use uninitialized mldsa-ecdsa/eddsa key"); |
40 | 0 | throw rnp::rnp_exception(RNP_ERROR_BAD_STATE); |
41 | 0 | } |
42 | 4.67k | } |
43 | | |
44 | | rnp_result_t |
45 | | pgp_dilithium_exdsa_composite_key_t::gen_keypair(rnp::RNG * rng, |
46 | | pgp_dilithium_exdsa_key_t *key, |
47 | | pgp_pubkey_alg_t alg) |
48 | 0 | { |
49 | 0 | rnp_result_t res; |
50 | 0 | pgp_curve_t curve = pk_alg_to_curve_id(alg); |
51 | 0 | dilithium_parameter_e dilithium_id = pk_alg_to_dilithium_id(alg); |
52 | |
|
53 | 0 | exdsa_key_t exdsa_key_pair; |
54 | |
|
55 | 0 | res = ec_key_t::generate_exdsa_key_pair(rng, &exdsa_key_pair, curve); |
56 | 0 | if (res != RNP_SUCCESS) { |
57 | 0 | RNP_LOG("generating mldsa exdsa composite key failed when generating exdsa key"); |
58 | 0 | return res; |
59 | 0 | } |
60 | | |
61 | 0 | auto dilithium_key_pair = dilithium_generate_keypair(rng, dilithium_id); |
62 | |
|
63 | 0 | key->priv = pgp_dilithium_exdsa_composite_private_key_t( |
64 | 0 | exdsa_key_pair.priv.get_encoded(), dilithium_key_pair.second.get_encoded(), alg); |
65 | 0 | key->pub = pgp_dilithium_exdsa_composite_public_key_t( |
66 | 0 | exdsa_key_pair.pub.get_encoded(), dilithium_key_pair.first.get_encoded(), alg); |
67 | |
|
68 | 0 | return RNP_SUCCESS; |
69 | 0 | } |
70 | | |
71 | | size_t |
72 | | pgp_dilithium_exdsa_composite_key_t::exdsa_curve_privkey_size(pgp_curve_t curve) |
73 | 158 | { |
74 | 158 | switch (curve) { |
75 | 17 | case PGP_CURVE_ED25519: |
76 | 17 | return 32; |
77 | | /* TODO */ |
78 | | // case PGP_CURVE_ED448: |
79 | | // return 56; |
80 | 10 | case PGP_CURVE_NIST_P_256: |
81 | 10 | return 32; |
82 | 42 | case PGP_CURVE_NIST_P_384: |
83 | 42 | return 48; |
84 | 16 | case PGP_CURVE_BP256: |
85 | 16 | return 32; |
86 | 73 | case PGP_CURVE_BP384: |
87 | 73 | return 48; |
88 | 0 | default: |
89 | 0 | RNP_LOG("invalid curve given"); |
90 | 0 | throw rnp::rnp_exception(RNP_ERROR_BAD_PARAMETERS); |
91 | 158 | } |
92 | 158 | } |
93 | | |
94 | | size_t |
95 | | pgp_dilithium_exdsa_composite_key_t::exdsa_curve_pubkey_size(pgp_curve_t curve) |
96 | 28.9k | { |
97 | 28.9k | switch (curve) { |
98 | 15.4k | case PGP_CURVE_ED25519: |
99 | 15.4k | return 32; |
100 | | /* TODO */ |
101 | | // case PGP_CURVE_ED448: |
102 | | // return 56; |
103 | 5.82k | case PGP_CURVE_NIST_P_256: |
104 | 5.82k | return 65; |
105 | 1.84k | case PGP_CURVE_NIST_P_384: |
106 | 1.84k | return 97; |
107 | 3.17k | case PGP_CURVE_BP256: |
108 | 3.17k | return 65; |
109 | 2.61k | case PGP_CURVE_BP384: |
110 | 2.61k | return 97; |
111 | 0 | default: |
112 | 0 | RNP_LOG("invalid curve given"); |
113 | 0 | throw rnp::rnp_exception(RNP_ERROR_BAD_PARAMETERS); |
114 | 28.9k | } |
115 | 28.9k | } |
116 | | |
117 | | size_t |
118 | | pgp_dilithium_exdsa_composite_key_t::exdsa_curve_signature_size(pgp_curve_t curve) |
119 | 5.86k | { |
120 | 5.86k | switch (curve) { |
121 | 856 | case PGP_CURVE_ED25519: |
122 | 856 | return 64; |
123 | | /* TODO */ |
124 | | // case PGP_CURVE_ED448: |
125 | | // return 114; |
126 | 1.01k | case PGP_CURVE_NIST_P_256: |
127 | 1.01k | return 64; |
128 | 1.25k | case PGP_CURVE_NIST_P_384: |
129 | 1.25k | return 96; |
130 | 1.39k | case PGP_CURVE_BP256: |
131 | 1.39k | return 64; |
132 | 1.33k | case PGP_CURVE_BP384: |
133 | 1.33k | return 96; |
134 | 0 | default: |
135 | 0 | RNP_LOG("invalid curve given"); |
136 | 0 | throw rnp::rnp_exception(RNP_ERROR_BAD_PARAMETERS); |
137 | 5.86k | } |
138 | 5.86k | } |
139 | | |
140 | | dilithium_parameter_e |
141 | | pgp_dilithium_exdsa_composite_key_t::pk_alg_to_dilithium_id(pgp_pubkey_alg_t pk_alg) |
142 | 34.9k | { |
143 | 34.9k | switch (pk_alg) { |
144 | 16.3k | case PGP_PKA_DILITHIUM3_ED25519: |
145 | 16.3k | FALLTHROUGH_STATEMENT; |
146 | 23.1k | case PGP_PKA_DILITHIUM3_P256: |
147 | 23.1k | FALLTHROUGH_STATEMENT; |
148 | 27.7k | case PGP_PKA_DILITHIUM3_BP256: |
149 | 27.7k | return dilithium_L3; |
150 | 4.02k | case PGP_PKA_DILITHIUM5_BP384: |
151 | 4.02k | FALLTHROUGH_STATEMENT; |
152 | 7.16k | case PGP_PKA_DILITHIUM5_P384: |
153 | 7.16k | return dilithium_L5; |
154 | 0 | default: |
155 | 0 | RNP_LOG("invalid PK alg given"); |
156 | 0 | throw rnp::rnp_exception(RNP_ERROR_BAD_PARAMETERS); |
157 | 34.9k | } |
158 | 34.9k | } |
159 | | |
160 | | pgp_curve_t |
161 | | pgp_dilithium_exdsa_composite_key_t::pk_alg_to_curve_id(pgp_pubkey_alg_t pk_alg) |
162 | 44.1k | { |
163 | 44.1k | switch (pk_alg) { |
164 | 21.3k | case PGP_PKA_DILITHIUM3_ED25519: |
165 | 21.3k | return PGP_CURVE_ED25519; |
166 | 8.68k | case PGP_PKA_DILITHIUM3_P256: |
167 | 8.68k | return PGP_CURVE_NIST_P_256; |
168 | 5.58k | case PGP_PKA_DILITHIUM3_BP256: |
169 | 5.58k | return PGP_CURVE_BP256; |
170 | 4.85k | case PGP_PKA_DILITHIUM5_BP384: |
171 | 4.85k | return PGP_CURVE_BP384; |
172 | 3.63k | case PGP_PKA_DILITHIUM5_P384: |
173 | 3.63k | return PGP_CURVE_NIST_P_384; |
174 | | /*case PGP_PKA_DILITHIUM5_ED448: |
175 | | throw rnp::rnp_exception(RNP_ERROR_NOT_IMPLEMENTED);*/ |
176 | 0 | default: |
177 | 0 | RNP_LOG("invalid PK alg given"); |
178 | 0 | throw rnp::rnp_exception(RNP_ERROR_BAD_PARAMETERS); |
179 | 44.1k | } |
180 | 44.1k | } |
181 | | |
182 | | pgp_dilithium_exdsa_composite_public_key_t::pgp_dilithium_exdsa_composite_public_key_t( |
183 | | const uint8_t *key_encoded, size_t key_encoded_len, pgp_pubkey_alg_t pk_alg) |
184 | 0 | : pk_alg_(pk_alg) |
185 | 0 | { |
186 | 0 | parse_component_keys(std::vector<uint8_t>(key_encoded, key_encoded + key_encoded_len)); |
187 | 0 | } |
188 | | |
189 | | pgp_dilithium_exdsa_composite_public_key_t::pgp_dilithium_exdsa_composite_public_key_t( |
190 | | std::vector<uint8_t> const &key_encoded, pgp_pubkey_alg_t pk_alg) |
191 | 9.14k | : pk_alg_(pk_alg) |
192 | 9.14k | { |
193 | 9.14k | parse_component_keys(key_encoded); |
194 | 9.14k | } |
195 | | |
196 | | pgp_dilithium_exdsa_composite_public_key_t::pgp_dilithium_exdsa_composite_public_key_t( |
197 | | std::vector<uint8_t> const &exdsa_key_encoded, |
198 | | std::vector<uint8_t> const &dilithium_key_encoded, |
199 | | pgp_pubkey_alg_t pk_alg) |
200 | 0 | : pk_alg_(pk_alg), dilithium_key_(dilithium_key_encoded, pk_alg_to_dilithium_id(pk_alg)), |
201 | 0 | exdsa_key_(exdsa_key_encoded, pk_alg_to_curve_id(pk_alg)) |
202 | 0 | { |
203 | 0 | if (exdsa_curve_pubkey_size(pk_alg_to_curve_id(pk_alg)) != exdsa_key_encoded.size() || |
204 | 0 | dilithium_pubkey_size(pk_alg_to_dilithium_id(pk_alg)) != |
205 | 0 | dilithium_key_encoded.size()) { |
206 | 0 | RNP_LOG("exdsa or mldsa key length mismatch"); |
207 | 0 | throw rnp::rnp_exception(RNP_ERROR_BAD_PARAMETERS); |
208 | 0 | } |
209 | 0 | is_initialized_ = true; |
210 | 0 | } |
211 | | |
212 | | pgp_dilithium_exdsa_composite_private_key_t::pgp_dilithium_exdsa_composite_private_key_t( |
213 | | const uint8_t *key_encoded, size_t key_encoded_len, pgp_pubkey_alg_t pk_alg) |
214 | 46 | : pk_alg_(pk_alg) |
215 | 46 | { |
216 | 46 | parse_component_keys(std::vector<uint8_t>(key_encoded, key_encoded + key_encoded_len)); |
217 | 46 | } |
218 | | |
219 | | pgp_dilithium_exdsa_composite_private_key_t::pgp_dilithium_exdsa_composite_private_key_t( |
220 | | std::vector<uint8_t> const &key_encoded, pgp_pubkey_alg_t pk_alg) |
221 | 0 | : pk_alg_(pk_alg) |
222 | 0 | { |
223 | 0 | parse_component_keys(key_encoded); |
224 | 0 | } |
225 | | |
226 | | /* copy assignment operator is used on key materials struct and thus needs to be defined for |
227 | | * this class as well */ |
228 | | pgp_dilithium_exdsa_composite_private_key_t & |
229 | | pgp_dilithium_exdsa_composite_private_key_t::operator=( |
230 | | const pgp_dilithium_exdsa_composite_private_key_t &other) |
231 | 5.92k | { |
232 | 5.92k | pgp_dilithium_exdsa_composite_key_t::operator=(other); |
233 | 5.92k | pk_alg_ = other.pk_alg_; |
234 | 5.92k | if (other.is_initialized() && other.dilithium_key_) { |
235 | 46 | dilithium_key_ = |
236 | 46 | std::make_unique<pgp_dilithium_private_key_t>(pgp_dilithium_private_key_t( |
237 | 46 | other.dilithium_key_->get_encoded(), other.dilithium_key_->param())); |
238 | 46 | } |
239 | 5.92k | if (other.is_initialized() && other.exdsa_key_) { |
240 | 46 | exdsa_key_ = std::make_unique<exdsa_private_key_t>( |
241 | 46 | exdsa_private_key_t(other.exdsa_key_->get_encoded(), other.exdsa_key_->get_curve())); |
242 | 46 | } |
243 | | |
244 | 5.92k | return *this; |
245 | 5.92k | } |
246 | | |
247 | | pgp_dilithium_exdsa_composite_private_key_t::pgp_dilithium_exdsa_composite_private_key_t( |
248 | | const pgp_dilithium_exdsa_composite_private_key_t &other) |
249 | 5.87k | { |
250 | 5.87k | *this = other; |
251 | 5.87k | } |
252 | | |
253 | | pgp_dilithium_exdsa_composite_private_key_t::pgp_dilithium_exdsa_composite_private_key_t( |
254 | | std::vector<uint8_t> const &exdsa_key_encoded, |
255 | | std::vector<uint8_t> const &dilithium_key_encoded, |
256 | | pgp_pubkey_alg_t pk_alg) |
257 | 0 | : pk_alg_(pk_alg) |
258 | 0 | { |
259 | 0 | if (exdsa_curve_privkey_size(pk_alg_to_curve_id(pk_alg)) != exdsa_key_encoded.size() || |
260 | 0 | dilithium_privkey_size(pk_alg_to_dilithium_id(pk_alg)) != |
261 | 0 | dilithium_key_encoded.size()) { |
262 | 0 | RNP_LOG("exdsa or mldsa key length mismatch"); |
263 | 0 | throw rnp::rnp_exception(RNP_ERROR_BAD_PARAMETERS); |
264 | 0 | } |
265 | | |
266 | 0 | dilithium_key_ = std::make_unique<pgp_dilithium_private_key_t>( |
267 | 0 | pgp_dilithium_private_key_t(dilithium_key_encoded, pk_alg_to_dilithium_id(pk_alg))); |
268 | 0 | exdsa_key_ = std::make_unique<exdsa_private_key_t>( |
269 | 0 | exdsa_private_key_t(exdsa_key_encoded, pk_alg_to_curve_id(pk_alg))); |
270 | 0 | is_initialized_ = true; |
271 | 0 | } |
272 | | |
273 | | size_t |
274 | | pgp_dilithium_exdsa_composite_private_key_t::encoded_size(pgp_pubkey_alg_t pk_alg) |
275 | 112 | { |
276 | 112 | dilithium_parameter_e dilithium_param = pk_alg_to_dilithium_id(pk_alg); |
277 | 112 | pgp_curve_t curve = pk_alg_to_curve_id(pk_alg); |
278 | 112 | return exdsa_curve_privkey_size(curve) + dilithium_privkey_size(dilithium_param); |
279 | 112 | } |
280 | | |
281 | | void |
282 | | pgp_dilithium_exdsa_composite_private_key_t::parse_component_keys( |
283 | | std::vector<uint8_t> key_encoded) |
284 | 46 | { |
285 | 46 | if (key_encoded.size() != encoded_size(pk_alg_)) { |
286 | 0 | RNP_LOG("ML-DSA composite key format invalid: length mismatch"); |
287 | 0 | throw rnp::rnp_exception(RNP_ERROR_BAD_PARAMETERS); |
288 | 0 | } |
289 | | |
290 | 46 | dilithium_parameter_e dilithium_param = pk_alg_to_dilithium_id(pk_alg_); |
291 | 46 | pgp_curve_t curve = pk_alg_to_curve_id(pk_alg_); |
292 | 46 | size_t split_at = exdsa_curve_privkey_size(pk_alg_to_curve_id(pk_alg_)); |
293 | | |
294 | 46 | dilithium_key_ = std::make_unique<pgp_dilithium_private_key_t>(pgp_dilithium_private_key_t( |
295 | 46 | key_encoded.data() + split_at, key_encoded.size() - split_at, dilithium_param)); |
296 | 46 | exdsa_key_ = std::make_unique<exdsa_private_key_t>( |
297 | 46 | exdsa_private_key_t(key_encoded.data(), split_at, curve)); |
298 | | |
299 | 46 | is_initialized_ = true; |
300 | 46 | } |
301 | | |
302 | | std::vector<uint8_t> |
303 | | pgp_dilithium_exdsa_composite_private_key_t::get_encoded() const |
304 | 0 | { |
305 | 0 | initialized_or_throw(); |
306 | 0 | std::vector<uint8_t> result; |
307 | 0 | std::vector<uint8_t> exdsa_key_encoded = exdsa_key_->get_encoded(); |
308 | 0 | std::vector<uint8_t> dilithium_key_encoded = dilithium_key_->get_encoded(); |
309 | |
|
310 | 0 | result.insert(result.end(), std::begin(exdsa_key_encoded), std::end(exdsa_key_encoded)); |
311 | 0 | result.insert( |
312 | 0 | result.end(), std::begin(dilithium_key_encoded), std::end(dilithium_key_encoded)); |
313 | 0 | return result; |
314 | 0 | }; |
315 | | |
316 | | rnp_result_t |
317 | | pgp_dilithium_exdsa_composite_private_key_t::sign(rnp::RNG * rng, |
318 | | pgp_dilithium_exdsa_signature_t *sig, |
319 | | pgp_hash_alg_t hash_alg, |
320 | | const uint8_t * msg, |
321 | | size_t msg_len) const |
322 | 0 | { |
323 | 0 | initialized_or_throw(); |
324 | 0 | std::vector<uint8_t> dilithium_sig; |
325 | 0 | std::vector<uint8_t> exdsa_sig; |
326 | 0 | rnp_result_t ret; |
327 | |
|
328 | 0 | try { |
329 | 0 | dilithium_sig = dilithium_key_->sign(rng, msg, msg_len); |
330 | 0 | } catch (const std::exception &e) { |
331 | 0 | RNP_LOG("%s", e.what()); |
332 | 0 | return RNP_ERROR_SIGNING_FAILED; |
333 | 0 | } |
334 | 0 | ret = exdsa_key_->sign(rng, exdsa_sig, msg, msg_len, hash_alg); |
335 | 0 | if (ret != RNP_SUCCESS) { |
336 | 0 | RNP_LOG("exdsa sign failed"); |
337 | 0 | return RNP_ERROR_SIGNING_FAILED; |
338 | 0 | } |
339 | | |
340 | 0 | sig->sig.assign(exdsa_sig.data(), exdsa_sig.data() + exdsa_sig.size()); |
341 | 0 | sig->sig.insert(sig->sig.end(), dilithium_sig.begin(), dilithium_sig.end()); |
342 | |
|
343 | 0 | return RNP_SUCCESS; |
344 | 0 | } |
345 | | |
346 | | void |
347 | | pgp_dilithium_exdsa_composite_private_key_t::secure_clear() |
348 | 890 | { |
349 | | // private key buffer is stored in a secure_vector and will be securely erased by the |
350 | | // destructor. |
351 | 890 | dilithium_key_.reset(); |
352 | 890 | exdsa_key_.reset(); |
353 | 890 | is_initialized_ = false; |
354 | 890 | } |
355 | | |
356 | | size_t |
357 | | pgp_dilithium_exdsa_composite_public_key_t::encoded_size(pgp_pubkey_alg_t pk_alg) |
358 | 19.7k | { |
359 | 19.7k | dilithium_parameter_e dilithium_param = pk_alg_to_dilithium_id(pk_alg); |
360 | 19.7k | pgp_curve_t curve = pk_alg_to_curve_id(pk_alg); |
361 | 19.7k | return exdsa_curve_pubkey_size(curve) + dilithium_pubkey_size(dilithium_param); |
362 | 19.7k | } |
363 | | |
364 | | void |
365 | | pgp_dilithium_exdsa_composite_public_key_t::parse_component_keys( |
366 | | std::vector<uint8_t> key_encoded) |
367 | 9.14k | { |
368 | 9.14k | if (key_encoded.size() != encoded_size(pk_alg_)) { |
369 | 0 | RNP_LOG("ML-DSA composite key format invalid: length mismatch"); |
370 | 0 | throw rnp::rnp_exception(RNP_ERROR_BAD_PARAMETERS); |
371 | 0 | } |
372 | | |
373 | 9.14k | dilithium_parameter_e dilithium_param = pk_alg_to_dilithium_id(pk_alg_); |
374 | 9.14k | pgp_curve_t curve = pk_alg_to_curve_id(pk_alg_); |
375 | 9.14k | size_t split_at = exdsa_curve_pubkey_size(pk_alg_to_curve_id(pk_alg_)); |
376 | | |
377 | 9.14k | dilithium_key_ = pgp_dilithium_public_key_t( |
378 | 9.14k | key_encoded.data() + split_at, key_encoded.size() - split_at, dilithium_param); |
379 | 9.14k | exdsa_key_ = exdsa_public_key_t(key_encoded.data(), split_at, curve); |
380 | | |
381 | 9.14k | is_initialized_ = true; |
382 | 9.14k | } |
383 | | |
384 | | std::vector<uint8_t> |
385 | | pgp_dilithium_exdsa_composite_public_key_t::get_encoded() const |
386 | 4.67k | { |
387 | 4.67k | initialized_or_throw(); |
388 | 4.67k | std::vector<uint8_t> result; |
389 | 4.67k | std::vector<uint8_t> exdsa_key_encoded = exdsa_key_.get_encoded(); |
390 | 4.67k | std::vector<uint8_t> dilithium_key_encoded = dilithium_key_.get_encoded(); |
391 | | |
392 | 4.67k | result.insert(result.end(), std::begin(exdsa_key_encoded), std::end(exdsa_key_encoded)); |
393 | 4.67k | result.insert( |
394 | 4.67k | result.end(), std::begin(dilithium_key_encoded), std::end(dilithium_key_encoded)); |
395 | 4.67k | return result; |
396 | 4.67k | }; |
397 | | |
398 | | rnp_result_t |
399 | | pgp_dilithium_exdsa_composite_public_key_t::verify(const pgp_dilithium_exdsa_signature_t *sig, |
400 | | pgp_hash_alg_t hash_alg, |
401 | | const uint8_t *hash, |
402 | | size_t hash_len) const |
403 | 0 | { |
404 | 0 | initialized_or_throw(); |
405 | 0 | std::vector<uint8_t> dilithium_sig; |
406 | 0 | std::vector<uint8_t> exdsa_sig; |
407 | |
|
408 | 0 | if (sig->sig.size() != sig->composite_signature_size(pk_alg_)) { |
409 | 0 | RNP_LOG("invalid signature size for mldsa exdsa composite algorithm %d", pk_alg_); |
410 | 0 | return RNP_ERROR_VERIFICATION_FAILED; |
411 | 0 | } |
412 | | |
413 | 0 | size_t split_at = exdsa_curve_signature_size(pk_alg_to_curve_id(pk_alg_)); |
414 | 0 | exdsa_sig = std::vector<uint8_t>(sig->sig.data(), sig->sig.data() + split_at); |
415 | 0 | dilithium_sig = |
416 | 0 | std::vector<uint8_t>(sig->sig.data() + split_at, sig->sig.data() + sig->sig.size()); |
417 | |
|
418 | 0 | if (exdsa_key_.verify(exdsa_sig, hash, hash_len, hash_alg) != RNP_SUCCESS || |
419 | 0 | !dilithium_key_.verify_signature( |
420 | 0 | hash, hash_len, dilithium_sig.data(), dilithium_sig.size())) { |
421 | 0 | RNP_LOG("could not verify composite signature"); |
422 | 0 | return RNP_ERROR_VERIFICATION_FAILED; |
423 | 0 | } |
424 | | |
425 | 0 | return RNP_SUCCESS; |
426 | 0 | } |
427 | | |
428 | | bool |
429 | | pgp_dilithium_exdsa_composite_public_key_t::is_valid(rnp::RNG *rng) const |
430 | 0 | { |
431 | 0 | if (!is_initialized()) { |
432 | 0 | return false; |
433 | 0 | } |
434 | 0 | return (exdsa_key_.is_valid(rng) && dilithium_key_.is_valid(rng)); |
435 | 0 | } |
436 | | |
437 | | bool |
438 | | pgp_dilithium_exdsa_composite_private_key_t::is_valid(rnp::RNG *rng) const |
439 | 0 | { |
440 | 0 | if (!is_initialized()) { |
441 | 0 | return false; |
442 | 0 | } |
443 | 0 | return (exdsa_key_->is_valid(rng) && dilithium_key_->is_valid(rng)); |
444 | 0 | } |
445 | | |
446 | | rnp_result_t |
447 | | dilithium_exdsa_validate_key(rnp::RNG *rng, const pgp_dilithium_exdsa_key_t *key, bool secret) |
448 | 0 | { |
449 | 0 | bool valid; |
450 | |
|
451 | 0 | valid = key->pub.is_valid(rng); |
452 | 0 | if (secret) { |
453 | 0 | valid = valid && key->priv.is_valid(rng); |
454 | 0 | } |
455 | 0 | if (!valid) { |
456 | 0 | return RNP_ERROR_GENERIC; |
457 | 0 | } |
458 | | |
459 | 0 | return RNP_SUCCESS; |
460 | 0 | } |