1use alloc::{boxed::Box, sync::Arc};
2use core::{
3 any::{Any, TypeId},
4 fmt::Debug,
5 panic::{RefUnwindSafe, UnwindSafe},
6};
7
8#[cfg(feature = "aes")]
9use super::{
10 aes::{A128CbcHs256, A128Gcm, A128Kw, A256CbcHs512, A256Gcm, A256Kw, AesKey, AesType},
11 AesTypes,
12};
13
14#[cfg(feature = "bls")]
15use super::{
16 bls::{BlsKeyPair, BlsPublicKeyType, G1, G1G2, G2},
17 BlsCurves,
18};
19
20#[cfg(feature = "chacha")]
21use super::{
22 chacha20::{Chacha20Key, Chacha20Type, C20P, XC20P},
23 Chacha20Types,
24};
25
26#[cfg(feature = "ed25519")]
27use super::ed25519::{self, Ed25519KeyPair};
28#[cfg(feature = "ed25519")]
29use super::x25519::{self, X25519KeyPair};
30
31#[cfg(feature = "k256")]
32use super::k256::{self, K256KeyPair};
33
34#[cfg(feature = "p256")]
35use super::p256::{self, P256KeyPair};
36
37#[cfg(feature = "p384")]
38use super::p384::{self, P384KeyPair};
39
40#[cfg(feature = "p256_hardware")]
41use super::p256_hardware::P256HardwareKeyPair;
42
43use super::{HasKeyAlg, HasKeyBackend, KeyAlg};
44use crate::{
45 backend::KeyBackend,
46 buffer::{ResizeBuffer, SecretBytes, WriteBuffer},
47 encrypt::{KeyAeadInPlace, KeyAeadParams},
48 error::Error,
49 jwk::{FromJwk, JwkEncoder, JwkParts, ToJwk},
50 kdf::{KeyDerivation, KeyExchange},
51 random::KeyMaterial,
52 repr::{KeyGen, KeyPublicBytes, KeySecretBytes, ToPublicBytes, ToSecretBytes},
53 sign::{KeySigVerify, KeySign, SignatureType},
54};
55
56#[cfg(any(
57 feature = "k256",
58 feature = "p256",
59 feature = "p384",
60 feature = "p256_hardware"
61))]
62use super::EcCurves;
63
64#[cfg(any(feature = "aes", feature = "chacha"))]
65use crate::kdf::{FromKeyDerivation, FromKeyExchange};
66
67#[derive(Debug)]
68pub struct KeyT<T: AnyKeyAlg + Send + Sync + RefUnwindSafe + UnwindSafe + ?Sized>(T);
69
70pub type AnyKey = KeyT<dyn AnyKeyAlg + Send + Sync + RefUnwindSafe + UnwindSafe>;
72
73impl AnyKey {
74 pub fn algorithm(&self) -> KeyAlg {
75 self.0.algorithm()
76 }
77
78 pub fn backend(&self) -> KeyBackend {
79 self.0.key_backend()
80 }
81
82 fn assume<K: AnyKeyAlg>(&self) -> &K {
83 self.downcast_ref().expect("Error assuming key type")
84 }
85
86 #[inline]
87 pub fn downcast_ref<K: AnyKeyAlg>(&self) -> Option<&K> {
88 self.0.as_any().downcast_ref()
89 }
90
91 #[inline]
92 pub fn key_type_id(&self) -> TypeId {
93 self.0.as_any().type_id()
94 }
95
96 #[inline]
97 pub fn key_id(&self) -> Result<SecretBytes, Error> {
98 get_key_id_any(self)
99 }
100}
101
102pub trait AnyKeyCreate: Sized {
104 fn generate_with_rng(alg: KeyAlg, rng: impl KeyMaterial) -> Result<Self, Error>;
106
107 fn generate_for_hardware(alg: KeyAlg) -> Result<Self, Error>;
109
110 fn get_with_id(alg: KeyAlg, id: &str) -> Result<Self, Error>;
112
113 #[cfg(feature = "getrandom")]
115 fn random(alg: KeyAlg) -> Result<Self, Error> {
116 Self::generate_with_rng(alg, crate::random::default_rng())
117 }
118
119 fn random_det(alg: KeyAlg, seed: &[u8]) -> Result<Self, Error> {
121 Self::generate_with_rng(alg, crate::random::RandomDet::new(seed))
122 }
123
124 fn from_public_bytes(alg: KeyAlg, public: &[u8]) -> Result<Self, Error>;
126
127 fn from_secret_bytes(alg: KeyAlg, secret: &[u8]) -> Result<Self, Error>;
129
130 fn from_key<K: HasKeyAlg + HasKeyBackend + Send + Sync + RefUnwindSafe + UnwindSafe + 'static>(
132 key: K,
133 ) -> Self;
134
135 fn from_key_exchange<Sk, Pk>(alg: KeyAlg, secret: &Sk, public: &Pk) -> Result<Self, Error>
137 where
138 Sk: KeyExchange<Pk> + ?Sized,
139 Pk: ?Sized;
140
141 fn from_key_derivation(alg: KeyAlg, derive: impl KeyDerivation) -> Result<Self, Error>;
143
144 fn convert_key(&self, alg: KeyAlg) -> Result<Self, Error>;
146}
147
148impl AnyKeyCreate for Box<AnyKey> {
149 fn generate_with_rng(alg: KeyAlg, rng: impl KeyMaterial) -> Result<Self, Error> {
150 generate_any_with_rng(alg, rng)
151 }
152
153 fn generate_for_hardware(alg: KeyAlg) -> Result<Self, Error> {
154 generate_any_for_hardware(alg)
155 }
156
157 fn get_with_id(alg: KeyAlg, id: &str) -> Result<Self, Error> {
158 get_any_with_id(alg, id)
159 }
160
161 fn from_public_bytes(alg: KeyAlg, public: &[u8]) -> Result<Self, Error> {
162 from_public_bytes_any(alg, public)
163 }
164
165 fn from_secret_bytes(alg: KeyAlg, secret: &[u8]) -> Result<Self, Error> {
166 from_secret_bytes_any(alg, secret)
167 }
168
169 #[inline(always)]
170 fn from_key<
171 K: HasKeyAlg + HasKeyBackend + Send + Sync + RefUnwindSafe + UnwindSafe + 'static,
172 >(
173 key: K,
174 ) -> Self {
175 Box::new(KeyT(key))
176 }
177
178 fn from_key_exchange<Sk, Pk>(alg: KeyAlg, secret: &Sk, public: &Pk) -> Result<Self, Error>
179 where
180 Sk: KeyExchange<Pk> + ?Sized,
181 Pk: ?Sized,
182 {
183 from_key_exchange_any(alg, secret, public)
184 }
185
186 fn from_key_derivation(alg: KeyAlg, derive: impl KeyDerivation) -> Result<Self, Error> {
187 from_key_derivation_any(alg, derive)
188 }
189
190 fn convert_key(&self, alg: KeyAlg) -> Result<Self, Error> {
191 convert_key_any(self, alg)
192 }
193}
194
195impl AnyKeyCreate for Arc<AnyKey> {
196 fn generate_with_rng(alg: KeyAlg, rng: impl KeyMaterial) -> Result<Self, Error> {
197 generate_any_with_rng(alg, rng)
198 }
199
200 fn generate_for_hardware(alg: KeyAlg) -> Result<Self, Error> {
201 generate_any_for_hardware(alg)
202 }
203
204 fn get_with_id(alg: KeyAlg, id: &str) -> Result<Self, Error> {
205 get_any_with_id(alg, id)
206 }
207
208 fn from_public_bytes(alg: KeyAlg, public: &[u8]) -> Result<Self, Error> {
209 from_public_bytes_any(alg, public)
210 }
211
212 fn from_secret_bytes(alg: KeyAlg, secret: &[u8]) -> Result<Self, Error> {
213 from_secret_bytes_any(alg, secret)
214 }
215
216 #[inline(always)]
217 fn from_key<
218 K: HasKeyAlg + HasKeyBackend + Send + Sync + RefUnwindSafe + UnwindSafe + 'static,
219 >(
220 key: K,
221 ) -> Self {
222 Arc::new(KeyT(key))
223 }
224
225 fn from_key_exchange<Sk, Pk>(alg: KeyAlg, secret: &Sk, public: &Pk) -> Result<Self, Error>
226 where
227 Sk: KeyExchange<Pk> + ?Sized,
228 Pk: ?Sized,
229 {
230 from_key_exchange_any(alg, secret, public)
231 }
232
233 fn from_key_derivation(alg: KeyAlg, derive: impl KeyDerivation) -> Result<Self, Error> {
234 from_key_derivation_any(alg, derive)
235 }
236
237 fn convert_key(&self, alg: KeyAlg) -> Result<Self, Error> {
238 convert_key_any(self, alg)
239 }
240}
241
242#[inline]
243fn generate_any_with_rng<R: AllocKey>(alg: KeyAlg, rng: impl KeyMaterial) -> Result<R, Error> {
244 match alg {
245 #[cfg(feature = "aes")]
246 KeyAlg::Aes(AesTypes::A128Gcm) => AesKey::<A128Gcm>::generate(rng).map(R::alloc_key),
247 #[cfg(feature = "aes")]
248 KeyAlg::Aes(AesTypes::A256Gcm) => AesKey::<A256Gcm>::generate(rng).map(R::alloc_key),
249 #[cfg(feature = "aes")]
250 KeyAlg::Aes(AesTypes::A128CbcHs256) => {
251 AesKey::<A128CbcHs256>::generate(rng).map(R::alloc_key)
252 }
253 #[cfg(feature = "aes")]
254 KeyAlg::Aes(AesTypes::A256CbcHs512) => {
255 AesKey::<A256CbcHs512>::generate(rng).map(R::alloc_key)
256 }
257 #[cfg(feature = "aes")]
258 KeyAlg::Aes(AesTypes::A128Kw) => AesKey::<A128Kw>::generate(rng).map(R::alloc_key),
259 #[cfg(feature = "aes")]
260 KeyAlg::Aes(AesTypes::A256Kw) => AesKey::<A256Kw>::generate(rng).map(R::alloc_key),
261 #[cfg(feature = "bls")]
262 KeyAlg::Bls12_381(BlsCurves::G1) => BlsKeyPair::<G1>::generate(rng).map(R::alloc_key),
263 #[cfg(feature = "bls")]
264 KeyAlg::Bls12_381(BlsCurves::G2) => BlsKeyPair::<G2>::generate(rng).map(R::alloc_key),
265 #[cfg(feature = "bls")]
266 KeyAlg::Bls12_381(BlsCurves::G1G2) => BlsKeyPair::<G1G2>::generate(rng).map(R::alloc_key),
267 #[cfg(feature = "chacha")]
268 KeyAlg::Chacha20(Chacha20Types::C20P) => {
269 Chacha20Key::<C20P>::generate(rng).map(R::alloc_key)
270 }
271 #[cfg(feature = "chacha")]
272 KeyAlg::Chacha20(Chacha20Types::XC20P) => {
273 Chacha20Key::<XC20P>::generate(rng).map(R::alloc_key)
274 }
275 #[cfg(feature = "ed25519")]
276 KeyAlg::Ed25519 => Ed25519KeyPair::generate(rng).map(R::alloc_key),
277 #[cfg(feature = "ed25519")]
278 KeyAlg::X25519 => X25519KeyPair::generate(rng).map(R::alloc_key),
279 #[cfg(feature = "k256")]
280 KeyAlg::EcCurve(EcCurves::Secp256k1) => K256KeyPair::generate(rng).map(R::alloc_key),
281 #[cfg(feature = "p256")]
282 KeyAlg::EcCurve(EcCurves::Secp256r1) => P256KeyPair::generate(rng).map(R::alloc_key),
283 #[cfg(feature = "p384")]
284 KeyAlg::EcCurve(EcCurves::Secp384r1) => P384KeyPair::generate(rng).map(R::alloc_key),
285 #[allow(unreachable_patterns)]
286 _ => Err(err_msg!(
287 Unsupported,
288 "Unsupported algorithm for key generation with rng"
289 )),
290 }
291}
292
293#[inline]
294fn generate_any_for_hardware<R: AllocKey>(alg: KeyAlg) -> Result<R, Error> {
295 match alg {
296 #[cfg(feature = "p256_hardware")]
297 KeyAlg::EcCurve(EcCurves::Secp256r1) => P256HardwareKeyPair::generate(
298 uuid::Uuid::new_v4()
299 .hyphenated()
300 .encode_lower(&mut uuid::Uuid::encode_buffer()),
301 )
302 .map(R::alloc_key),
303 _ => Err(err_msg!(
304 Unsupported,
305 "Unsupported algorithm for key generation with id"
306 )),
307 }
308}
309
310#[inline]
311fn get_any_with_id<R: AllocKey>(alg: KeyAlg, _id: &str) -> Result<R, Error> {
312 let key = match alg {
313 #[cfg(feature = "p256_hardware")]
314 KeyAlg::EcCurve(EcCurves::Secp256r1) => P256HardwareKeyPair::from_id(_id).map(R::alloc_key),
315 _ => Err(err_msg!(
316 Unsupported,
317 "Unsupported algorithm for key retrieval by id"
318 )),
319 }?;
320
321 Ok(key)
322}
323
324#[inline]
325fn from_public_bytes_any<R: AllocKey>(alg: KeyAlg, public: &[u8]) -> Result<R, Error> {
326 match alg {
327 #[cfg(feature = "bls")]
328 KeyAlg::Bls12_381(BlsCurves::G1) => {
329 BlsKeyPair::<G1>::from_public_bytes(public).map(R::alloc_key)
330 }
331 #[cfg(feature = "bls")]
332 KeyAlg::Bls12_381(BlsCurves::G2) => {
333 BlsKeyPair::<G2>::from_public_bytes(public).map(R::alloc_key)
334 }
335 #[cfg(feature = "bls")]
336 KeyAlg::Bls12_381(BlsCurves::G1G2) => {
337 BlsKeyPair::<G1G2>::from_public_bytes(public).map(R::alloc_key)
338 }
339 #[cfg(feature = "ed25519")]
340 KeyAlg::Ed25519 => Ed25519KeyPair::from_public_bytes(public).map(R::alloc_key),
341 #[cfg(feature = "ed25519")]
342 KeyAlg::X25519 => X25519KeyPair::from_public_bytes(public).map(R::alloc_key),
343 #[cfg(feature = "k256")]
344 KeyAlg::EcCurve(EcCurves::Secp256k1) => {
345 K256KeyPair::from_public_bytes(public).map(R::alloc_key)
346 }
347 #[cfg(feature = "p256")]
348 KeyAlg::EcCurve(EcCurves::Secp256r1) => {
349 P256KeyPair::from_public_bytes(public).map(R::alloc_key)
350 }
351 #[cfg(feature = "p384")]
352 KeyAlg::EcCurve(EcCurves::Secp384r1) => {
353 P384KeyPair::from_public_bytes(public).map(R::alloc_key)
354 }
355 #[allow(unreachable_patterns)]
356 _ => Err(err_msg!(
357 Unsupported,
358 "Unsupported algorithm for public key import"
359 )),
360 }
361}
362
363#[inline]
364fn from_secret_bytes_any<R: AllocKey>(alg: KeyAlg, secret: &[u8]) -> Result<R, Error> {
365 match alg {
366 #[cfg(feature = "aes")]
367 KeyAlg::Aes(AesTypes::A128Gcm) => {
368 AesKey::<A128Gcm>::from_secret_bytes(secret).map(R::alloc_key)
369 }
370 #[cfg(feature = "aes")]
371 KeyAlg::Aes(AesTypes::A256Gcm) => {
372 AesKey::<A256Gcm>::from_secret_bytes(secret).map(R::alloc_key)
373 }
374 #[cfg(feature = "aes")]
375 KeyAlg::Aes(AesTypes::A128CbcHs256) => {
376 AesKey::<A128CbcHs256>::from_secret_bytes(secret).map(R::alloc_key)
377 }
378 #[cfg(feature = "aes")]
379 KeyAlg::Aes(AesTypes::A256CbcHs512) => {
380 AesKey::<A256CbcHs512>::from_secret_bytes(secret).map(R::alloc_key)
381 }
382 #[cfg(feature = "aes")]
383 KeyAlg::Aes(AesTypes::A128Kw) => {
384 AesKey::<A128Kw>::from_secret_bytes(secret).map(R::alloc_key)
385 }
386 #[cfg(feature = "aes")]
387 KeyAlg::Aes(AesTypes::A256Kw) => {
388 AesKey::<A256Kw>::from_secret_bytes(secret).map(R::alloc_key)
389 }
390 #[cfg(feature = "bls")]
391 KeyAlg::Bls12_381(BlsCurves::G1) => {
392 BlsKeyPair::<G1>::from_secret_bytes(secret).map(R::alloc_key)
393 }
394 #[cfg(feature = "bls")]
395 KeyAlg::Bls12_381(BlsCurves::G2) => {
396 BlsKeyPair::<G2>::from_secret_bytes(secret).map(R::alloc_key)
397 }
398 #[cfg(feature = "bls")]
399 KeyAlg::Bls12_381(BlsCurves::G1G2) => {
400 BlsKeyPair::<G1G2>::from_secret_bytes(secret).map(R::alloc_key)
401 }
402 #[cfg(feature = "chacha")]
403 KeyAlg::Chacha20(Chacha20Types::C20P) => {
404 Chacha20Key::<C20P>::from_secret_bytes(secret).map(R::alloc_key)
405 }
406 #[cfg(feature = "chacha")]
407 KeyAlg::Chacha20(Chacha20Types::XC20P) => {
408 Chacha20Key::<XC20P>::from_secret_bytes(secret).map(R::alloc_key)
409 }
410 #[cfg(feature = "ed25519")]
411 KeyAlg::Ed25519 => Ed25519KeyPair::from_secret_bytes(secret).map(R::alloc_key),
412 #[cfg(feature = "ed25519")]
413 KeyAlg::X25519 => X25519KeyPair::from_secret_bytes(secret).map(R::alloc_key),
414 #[cfg(feature = "k256")]
415 KeyAlg::EcCurve(EcCurves::Secp256k1) => {
416 K256KeyPair::from_secret_bytes(secret).map(R::alloc_key)
417 }
418 #[cfg(feature = "p256")]
419 KeyAlg::EcCurve(EcCurves::Secp256r1) => {
420 P256KeyPair::from_secret_bytes(secret).map(R::alloc_key)
421 }
422 #[cfg(feature = "p384")]
423 KeyAlg::EcCurve(EcCurves::Secp384r1) => {
424 P384KeyPair::from_secret_bytes(secret).map(R::alloc_key)
425 }
426 #[allow(unreachable_patterns)]
427 _ => Err(err_msg!(
428 Unsupported,
429 "Unsupported algorithm for secret key import"
430 )),
431 }
432}
433
434#[cfg(any(feature = "aes", feature = "chacha"))]
435#[inline]
436fn from_key_exchange_any<R, Sk, Pk>(alg: KeyAlg, secret: &Sk, public: &Pk) -> Result<R, Error>
437where
438 R: AllocKey,
439 Sk: KeyExchange<Pk> + ?Sized,
440 Pk: ?Sized,
441{
442 match alg {
443 #[cfg(feature = "aes")]
444 KeyAlg::Aes(AesTypes::A128Gcm) => {
445 AesKey::<A128Gcm>::from_key_exchange(secret, public).map(R::alloc_key)
446 }
447 #[cfg(feature = "aes")]
448 KeyAlg::Aes(AesTypes::A256Gcm) => {
449 AesKey::<A256Gcm>::from_key_exchange(secret, public).map(R::alloc_key)
450 }
451 #[cfg(feature = "aes")]
452 KeyAlg::Aes(AesTypes::A128CbcHs256) => {
453 AesKey::<A128CbcHs256>::from_key_exchange(secret, public).map(R::alloc_key)
454 }
455 #[cfg(feature = "aes")]
456 KeyAlg::Aes(AesTypes::A256CbcHs512) => {
457 AesKey::<A256CbcHs512>::from_key_exchange(secret, public).map(R::alloc_key)
458 }
459 #[cfg(feature = "aes")]
460 KeyAlg::Aes(AesTypes::A128Kw) => {
461 AesKey::<A128Kw>::from_key_exchange(secret, public).map(R::alloc_key)
462 }
463 #[cfg(feature = "aes")]
464 KeyAlg::Aes(AesTypes::A256Kw) => {
465 AesKey::<A256Kw>::from_key_exchange(secret, public).map(R::alloc_key)
466 }
467 #[cfg(feature = "chacha")]
468 KeyAlg::Chacha20(Chacha20Types::C20P) => {
469 Chacha20Key::<C20P>::from_key_exchange(secret, public).map(R::alloc_key)
470 }
471 #[cfg(feature = "chacha")]
472 KeyAlg::Chacha20(Chacha20Types::XC20P) => {
473 Chacha20Key::<XC20P>::from_key_exchange(secret, public).map(R::alloc_key)
474 }
475 #[allow(unreachable_patterns)]
476 _ => Err(err_msg!(
477 Unsupported,
478 "Unsupported algorithm for key exchange"
479 )),
480 }
481}
482
483#[cfg(not(any(feature = "aes", feature = "chacha")))]
484#[inline]
485fn from_key_exchange_any<R, Sk: ?Sized, Pk: ?Sized>(
486 _alg: KeyAlg,
487 _secret: &Sk,
488 _public: &Pk,
489) -> Result<R, Error> {
490 return Err(err_msg!(
491 Unsupported,
492 "Unsupported algorithm for key exchange"
493 ));
494}
495
496#[cfg(any(feature = "aes", feature = "chacha"))]
497#[inline]
498fn from_key_derivation_any<R: AllocKey>(
499 alg: KeyAlg,
500 derive: impl KeyDerivation,
501) -> Result<R, Error> {
502 match alg {
503 #[cfg(feature = "aes")]
504 KeyAlg::Aes(AesTypes::A128Gcm) => {
505 AesKey::<A128Gcm>::from_key_derivation(derive).map(R::alloc_key)
506 }
507 #[cfg(feature = "aes")]
508 KeyAlg::Aes(AesTypes::A256Gcm) => {
509 AesKey::<A256Gcm>::from_key_derivation(derive).map(R::alloc_key)
510 }
511 #[cfg(feature = "aes")]
512 KeyAlg::Aes(AesTypes::A128CbcHs256) => {
513 AesKey::<A128CbcHs256>::from_key_derivation(derive).map(R::alloc_key)
514 }
515 #[cfg(feature = "aes")]
516 KeyAlg::Aes(AesTypes::A256CbcHs512) => {
517 AesKey::<A256CbcHs512>::from_key_derivation(derive).map(R::alloc_key)
518 }
519 #[cfg(feature = "aes")]
520 KeyAlg::Aes(AesTypes::A128Kw) => {
521 AesKey::<A128Kw>::from_key_derivation(derive).map(R::alloc_key)
522 }
523 #[cfg(feature = "aes")]
524 KeyAlg::Aes(AesTypes::A256Kw) => {
525 AesKey::<A256Kw>::from_key_derivation(derive).map(R::alloc_key)
526 }
527 #[cfg(feature = "chacha")]
528 KeyAlg::Chacha20(Chacha20Types::C20P) => {
529 Chacha20Key::<C20P>::from_key_derivation(derive).map(R::alloc_key)
530 }
531 #[cfg(feature = "chacha")]
532 KeyAlg::Chacha20(Chacha20Types::XC20P) => {
533 Chacha20Key::<XC20P>::from_key_derivation(derive).map(R::alloc_key)
534 }
535 #[allow(unreachable_patterns)]
536 _ => Err(err_msg!(
537 Unsupported,
538 "Unsupported algorithm for key derivation"
539 )),
540 }
541}
542
543#[cfg(not(any(feature = "aes", feature = "chacha")))]
544fn from_key_derivation_any<R: AllocKey>(
545 _alg: KeyAlg,
546 _derive: impl KeyDerivation,
547) -> Result<R, Error> {
548 return Err(err_msg!(
549 Unsupported,
550 "Unsupported algorithm for key derivation"
551 ));
552}
553
554#[inline]
555fn convert_key_any<R: AllocKey>(key: &AnyKey, alg: KeyAlg) -> Result<R, Error> {
556 match (key.algorithm(), alg) {
557 #[cfg(feature = "bls")]
558 (KeyAlg::Bls12_381(BlsCurves::G1G2), KeyAlg::Bls12_381(BlsCurves::G1)) => Ok(R::alloc_key(
559 BlsKeyPair::<G1>::from(key.assume::<BlsKeyPair<G1G2>>()),
560 )),
561 #[cfg(feature = "bls")]
562 (KeyAlg::Bls12_381(BlsCurves::G1G2), KeyAlg::Bls12_381(BlsCurves::G2)) => Ok(R::alloc_key(
563 BlsKeyPair::<G2>::from(key.assume::<BlsKeyPair<G1G2>>()),
564 )),
565 #[cfg(feature = "ed25519")]
566 (KeyAlg::Ed25519, KeyAlg::X25519) => Ok(<X25519KeyPair as TryFrom<_>>::try_from(
567 key.assume::<Ed25519KeyPair>(),
568 )
569 .map(R::alloc_key)?),
570 #[allow(unreachable_patterns)]
571 _ => Err(err_msg!(
572 Unsupported,
573 "Unsupported key conversion operation"
574 )),
575 }
576}
577
578#[inline]
579fn get_key_id_any(key: &AnyKey) -> Result<SecretBytes, Error> {
580 match key.algorithm() {
581 #[cfg(feature = "p256_hardware")]
582 KeyAlg::EcCurve(EcCurves::Secp256r1) => {
583 Ok(key.assume::<P256HardwareKeyPair>().key_id.clone())
584 }
585 #[allow(unreachable_patterns)]
586 _ => Err(err_msg!(Unsupported, "Unsupported get key id operation")),
587 }
588}
589
590impl FromJwk for Box<AnyKey> {
591 fn from_jwk_parts(jwk: JwkParts<'_>) -> Result<Self, Error> {
592 from_jwk_any(jwk)
593 }
594}
595
596impl FromJwk for Arc<AnyKey> {
597 fn from_jwk_parts(jwk: JwkParts<'_>) -> Result<Self, Error> {
598 from_jwk_any(jwk)
599 }
600}
601
602#[inline]
603fn from_jwk_any<R: AllocKey>(jwk: JwkParts<'_>) -> Result<R, Error> {
604 match (jwk.kty, jwk.crv.as_ref(), jwk.alg.as_ref()) {
605 #[cfg(feature = "aes")]
606 ("oct", _, A128Gcm::JWK_ALG) => AesKey::<A128Gcm>::from_jwk_parts(jwk).map(R::alloc_key),
607 #[cfg(feature = "aes")]
608 ("oct", _, A256Gcm::JWK_ALG) => AesKey::<A256Gcm>::from_jwk_parts(jwk).map(R::alloc_key),
609 #[cfg(feature = "aes")]
610 ("oct", _, A128CbcHs256::JWK_ALG) => {
611 AesKey::<A128CbcHs256>::from_jwk_parts(jwk).map(R::alloc_key)
612 }
613 #[cfg(feature = "aes")]
614 ("oct", _, A256CbcHs512::JWK_ALG) => {
615 AesKey::<A256CbcHs512>::from_jwk_parts(jwk).map(R::alloc_key)
616 }
617 #[cfg(feature = "aes")]
618 ("oct", _, A128Kw::JWK_ALG) => AesKey::<A128Kw>::from_jwk_parts(jwk).map(R::alloc_key),
619 #[cfg(feature = "aes")]
620 ("oct", _, A256Kw::JWK_ALG) => AesKey::<A256Kw>::from_jwk_parts(jwk).map(R::alloc_key),
621 #[cfg(feature = "bls")]
622 ("OKP" | "EC", G1::JWK_CURVE, _) => BlsKeyPair::<G1>::from_jwk_parts(jwk).map(R::alloc_key),
623 #[cfg(feature = "bls")]
624 ("OKP" | "EC", G2::JWK_CURVE, _) => BlsKeyPair::<G2>::from_jwk_parts(jwk).map(R::alloc_key),
625 #[cfg(feature = "bls")]
626 ("OKP" | "EC", G1G2::JWK_CURVE, _) => {
627 BlsKeyPair::<G1G2>::from_jwk_parts(jwk).map(R::alloc_key)
628 }
629 #[cfg(feature = "chacha")]
630 ("oct", _, C20P::JWK_ALG) => Chacha20Key::<C20P>::from_jwk_parts(jwk).map(R::alloc_key),
631 #[cfg(feature = "chacha")]
632 ("oct", _, XC20P::JWK_ALG) => Chacha20Key::<XC20P>::from_jwk_parts(jwk).map(R::alloc_key),
633 #[cfg(feature = "ed25519")]
634 ("OKP", ed25519::JWK_CURVE, _) => Ed25519KeyPair::from_jwk_parts(jwk).map(R::alloc_key),
635 #[cfg(feature = "ed25519")]
636 ("OKP", x25519::JWK_CURVE, _) => X25519KeyPair::from_jwk_parts(jwk).map(R::alloc_key),
637 #[cfg(feature = "k256")]
638 ("EC", k256::JWK_CURVE, _) => K256KeyPair::from_jwk_parts(jwk).map(R::alloc_key),
639 #[cfg(feature = "p256")]
640 ("EC", p256::JWK_CURVE, _) => P256KeyPair::from_jwk_parts(jwk).map(R::alloc_key),
641 #[cfg(feature = "p384")]
642 ("EC", p384::JWK_CURVE, _) => P384KeyPair::from_jwk_parts(jwk).map(R::alloc_key),
643 _ => Err(err_msg!(Unsupported, "Unsupported JWK for key import")),
644 }
645}
646
647macro_rules! match_key_alg {
648 ($slf:expr, $ty:ty, $($kty:ident),+ $(,$errmsg:literal)?) => {{
649 fn matcher(key: &AnyKey) -> Result<$ty, Error> {
650 #[allow(unused_variables)]
651 let alg = key.algorithm();
652 match_key_alg!(@ $($kty)+ ; key, alg);
653 return Err(err_msg!(Unsupported $(,$errmsg)?))
654 }
655 matcher($slf)
656 }};
657 (@ ; $key:ident, $alg:ident) => {()};
658 (@ Aes $($rest:ident)*; $key:ident, $alg:ident) => {{
659 #[cfg(feature = "aes")]
660 if $alg == KeyAlg::Aes(AesTypes::A128Gcm) {
661 return Ok($key.assume::<AesKey<A128Gcm>>());
662 }
663 #[cfg(feature = "aes")]
664 if $alg == KeyAlg::Aes(AesTypes::A256Gcm) {
665 return Ok($key.assume::<AesKey<A256Gcm>>());
666 }
667 #[cfg(feature = "aes")]
668 if $alg == KeyAlg::Aes(AesTypes::A128CbcHs256) {
669 return Ok($key.assume::<AesKey<A128CbcHs256>>());
670 }
671 #[cfg(feature = "aes")]
672 if $alg == KeyAlg::Aes(AesTypes::A256CbcHs512) {
673 return Ok($key.assume::<AesKey<A256CbcHs512>>());
674 }
675 #[cfg(feature = "aes")]
676 if $alg == KeyAlg::Aes(AesTypes::A128Kw) {
677 return Ok($key.assume::<AesKey<A128Kw>>());
678 }
679 #[cfg(feature = "aes")]
680 if $alg == KeyAlg::Aes(AesTypes::A256Kw) {
681 return Ok($key.assume::<AesKey<A256Kw>>());
682 }
683 match_key_alg!(@ $($rest)*; $key, $alg)
684 }};
685 (@ Bls $($rest:ident)*; $key:ident, $alg:ident) => {{
686 #[cfg(feature = "bls")]
687 if $alg == KeyAlg::Bls12_381(BlsCurves::G1) {
688 return Ok($key.assume::<BlsKeyPair<G1>>());
689 }
690 #[cfg(feature = "bls")]
691 if $alg == KeyAlg::Bls12_381(BlsCurves::G2) {
692 return Ok($key.assume::<BlsKeyPair<G2>>());
693 }
694 #[cfg(feature = "bls")]
695 if $alg == KeyAlg::Bls12_381(BlsCurves::G1G2) {
696 return Ok($key.assume::<BlsKeyPair<G1G2>>());
697 }
698 match_key_alg!(@ $($rest)*; $key, $alg)
699 }};
700 (@ Chacha $($rest:ident)*; $key:ident, $alg:ident) => {{
701 #[cfg(feature = "chacha")]
702 if $alg == KeyAlg::Chacha20(Chacha20Types::C20P) {
703 return Ok($key.assume::<Chacha20Key<C20P>>());
704 }
705 #[cfg(feature = "chacha")]
706 if $alg == KeyAlg::Chacha20(Chacha20Types::XC20P) {
707 return Ok($key.assume::<Chacha20Key<XC20P>>());
708 }
709 match_key_alg!(@ $($rest)*; $key, $alg)
710 }};
711 (@ Ed25519 $($rest:ident)*; $key:ident, $alg:ident) => {{
712 #[cfg(feature = "ed25519")]
713 if $alg == KeyAlg::Ed25519 {
714 return Ok($key.assume::<Ed25519KeyPair>())
715 }
716 match_key_alg!(@ $($rest)*; $key, $alg)
717 }};
718 (@ X25519 $($rest:ident)*; $key:ident, $alg:ident) => {{
719 #[cfg(feature = "ed25519")]
720 if $alg == KeyAlg::X25519 {
721 return Ok($key.assume::<X25519KeyPair>())
722 }
723 match_key_alg!(@ $($rest)*; $key, $alg)
724 }};
725 (@ K256 $($rest:ident)*; $key:ident, $alg:ident) => {{
726 #[cfg(feature = "k256")]
727 if $alg == KeyAlg::EcCurve(EcCurves::Secp256k1) {
728 return Ok($key.assume::<K256KeyPair>())
729 }
730 match_key_alg!(@ $($rest)*; $key, $alg)
731 }};
732 (@ P256 $($rest:ident)*; $key:ident, $alg:ident) => {{
733 #[cfg(feature = "p256")]
734 if $alg == KeyAlg::EcCurve(EcCurves::Secp256r1) && $key.backend() == KeyBackend::Software {
735 return Ok($key.assume::<P256KeyPair>())
736 }
737 match_key_alg!(@ $($rest)*; $key, $alg)
738 }};
739 (@ P256Hardware $($rest:ident)*; $key:ident, $alg:ident) => {{
740 #[cfg(feature = "p256_hardware")]
741 if $alg == KeyAlg::EcCurve(EcCurves::Secp256r1) && $key.backend() == KeyBackend::SecureElement {
742 return Ok($key.assume::<P256HardwareKeyPair>())
743 }
744 match_key_alg!(@ $($rest)*; $key, $alg)
745 }};
746 (@ P384 $($rest:ident)*; $key:ident, $alg:ident) => {{
747 #[cfg(feature = "p384")]
748 if $alg == KeyAlg::EcCurve(EcCurves::Secp384r1) {
749 return Ok($key.assume::<P384KeyPair>())
750 }
751 match_key_alg!(@ $($rest)*; $key, $alg)
752 }};
753}
754
755impl AnyKey {
756 fn key_as_aead(&self) -> Result<&dyn KeyAeadInPlace, Error> {
757 match_key_alg! {
758 self,
759 &dyn KeyAeadInPlace,
760 Aes,
761 Chacha,
762 "AEAD is not supported for this key type"
763 }
764 }
765
766 fn key_to_secret(&self) -> Result<&dyn ToSecretBytes, Error> {
767 match_key_alg! {
768 self,
769 &dyn ToSecretBytes,
770 Aes,
771 Bls,
772 Chacha,
773 Ed25519,
774 K256,
775 P256,
776 P384,
777 X25519,
778 "Secret key export is not supported for this key type"
779 }
780 }
781
782 fn key_to_public(&self) -> Result<&dyn ToPublicBytes, Error> {
783 match_key_alg! {
784 self,
785 &dyn ToPublicBytes,
786 Bls,
787 Ed25519,
788 K256,
789 P256,
790 P256Hardware,
791 P384,
792 X25519,
793 "Public key export is not supported for this key type"
794 }
795 }
796}
797
798impl ToPublicBytes for AnyKey {
799 fn public_bytes_length(&self) -> Result<usize, Error> {
800 self.key_to_public()?.public_bytes_length()
801 }
802
803 fn write_public_bytes(&self, out: &mut dyn WriteBuffer) -> Result<(), Error> {
804 self.key_to_public()?.write_public_bytes(out)
805 }
806}
807
808impl ToSecretBytes for AnyKey {
809 fn secret_bytes_length(&self) -> Result<usize, Error> {
810 self.key_to_secret()?.secret_bytes_length()
811 }
812
813 fn write_secret_bytes(&self, out: &mut dyn WriteBuffer) -> Result<(), Error> {
814 self.key_to_secret()?.write_secret_bytes(out)
815 }
816}
817
818impl KeyExchange for AnyKey {
819 fn write_key_exchange(&self, other: &AnyKey, out: &mut dyn WriteBuffer) -> Result<(), Error> {
820 if self.key_type_id() != other.key_type_id() {
821 return Err(err_msg!(Unsupported, "Unsupported key exchange"));
822 }
823 match self.algorithm() {
824 #[cfg(feature = "ed25519")]
825 KeyAlg::X25519 => Ok(self
826 .assume::<X25519KeyPair>()
827 .write_key_exchange(other.assume::<X25519KeyPair>(), out)?),
828 #[cfg(feature = "k256")]
829 KeyAlg::EcCurve(EcCurves::Secp256k1) => Ok(self
830 .assume::<K256KeyPair>()
831 .write_key_exchange(other.assume::<K256KeyPair>(), out)?),
832 #[cfg(feature = "p256")]
833 KeyAlg::EcCurve(EcCurves::Secp256r1) => Ok(self
834 .assume::<P256KeyPair>()
835 .write_key_exchange(other.assume::<P256KeyPair>(), out)?),
836 #[cfg(feature = "p384")]
837 KeyAlg::EcCurve(EcCurves::Secp384r1) => Ok(self
838 .assume::<P384KeyPair>()
839 .write_key_exchange(other.assume::<P384KeyPair>(), out)?),
840 #[allow(unreachable_patterns)]
841 _ => {
842 let _ = out;
843 Err(err_msg!(Unsupported, "Unsupported key exchange"))
844 }
845 }
846 }
847}
848
849impl KeyAeadInPlace for AnyKey {
850 fn encrypt_in_place(
851 &self,
852 buffer: &mut dyn ResizeBuffer,
853 nonce: &[u8],
854 aad: &[u8],
855 ) -> Result<usize, Error> {
856 self.key_as_aead()?.encrypt_in_place(buffer, nonce, aad)
857 }
858
859 fn decrypt_in_place(
860 &self,
861 buffer: &mut dyn ResizeBuffer,
862 nonce: &[u8],
863 aad: &[u8],
864 ) -> Result<(), Error> {
865 self.key_as_aead()?.decrypt_in_place(buffer, nonce, aad)
866 }
867
868 fn aead_params(&self) -> KeyAeadParams {
869 if let Ok(key) = self.key_as_aead() {
870 key.aead_params()
871 } else {
872 KeyAeadParams::default()
873 }
874 }
875
876 fn aead_padding(&self, msg_len: usize) -> usize {
877 if let Ok(key) = self.key_as_aead() {
878 key.aead_padding(msg_len)
879 } else {
880 0
881 }
882 }
883}
884
885impl ToJwk for AnyKey {
886 fn encode_jwk(&self, enc: &mut dyn JwkEncoder) -> Result<(), Error> {
887 let key = match_key_alg! {
888 self,
889 &dyn ToJwk,
890 Aes,
891 Bls,
892 Chacha,
893 Ed25519,
894 K256,
895 P256,
896 P256Hardware,
897 P384,
898 X25519,
899 "JWK export is not supported for this key type"
900 }?;
901 key.encode_jwk(enc)
902 }
903}
904
905impl KeySign for AnyKey {
906 fn write_signature(
907 &self,
908 message: &[u8],
909 sig_type: Option<SignatureType>,
910 out: &mut dyn WriteBuffer,
911 ) -> Result<(), Error> {
912 let key = match_key_alg! {
913 self,
914 &dyn KeySign,
915 Ed25519,
916 K256,
917 P256,
918 P256Hardware,
919 P384,
920 "Signing is not supported for this key type"
921 }?;
922 key.write_signature(message, sig_type, out)
923 }
924}
925
926impl KeySigVerify for AnyKey {
927 fn verify_signature(
928 &self,
929 message: &[u8],
930 signature: &[u8],
931 sig_type: Option<SignatureType>,
932 ) -> Result<bool, Error> {
933 let key = match_key_alg! {
934 self,
935 &dyn KeySigVerify,
936 Ed25519,
937 K256,
938 P256,
939 P256Hardware,
940 P384,
941 "Signature verification is not supported for this key type"
942 }?;
943 key.verify_signature(message, signature, sig_type)
944 }
945}
946
947trait AllocKey {
949 fn alloc_key<K: AnyKeyAlg + Send + Sync + RefUnwindSafe + UnwindSafe>(key: K) -> Self;
950}
951
952impl AllocKey for Arc<AnyKey> {
953 #[inline(always)]
954 fn alloc_key<K: AnyKeyAlg + Send + Sync + RefUnwindSafe + UnwindSafe>(key: K) -> Self {
955 Self::from_key(key)
956 }
957}
958
959impl AllocKey for Box<AnyKey> {
960 #[inline(always)]
961 fn alloc_key<K: AnyKeyAlg + Send + Sync + RefUnwindSafe + UnwindSafe>(key: K) -> Self {
962 Self::from_key(key)
963 }
964}
965
966pub trait AnyKeyAlg: HasKeyAlg + HasKeyBackend + 'static {
967 fn as_any(&self) -> &dyn Any;
968}
969
970impl<K: HasKeyAlg + HasKeyBackend + Sized + 'static> AnyKeyAlg for K {
972 fn as_any(&self) -> &dyn Any {
973 self
974 }
975}
976
977#[cfg(test)]
978mod tests {
979 #[allow(unused_imports)]
980 use super::*;
981
982 #[cfg(feature = "ed25519")]
985 #[test]
986 fn ed25519_as_any() {
987 let key = Box::<AnyKey>::random(KeyAlg::Ed25519).unwrap();
988 assert_eq!(key.algorithm(), KeyAlg::Ed25519);
989 assert_eq!(key.key_type_id(), TypeId::of::<Ed25519KeyPair>());
990 let _ = key.to_jwk_public(None).unwrap();
991 }
992
993 #[cfg(feature = "aes")]
994 #[test]
995 fn key_exchange_any() {
996 let alice = Box::<AnyKey>::random(KeyAlg::X25519).unwrap();
997 let bob = Box::<AnyKey>::random(KeyAlg::X25519).unwrap();
998 let exch_a = alice.key_exchange_bytes(&bob).unwrap();
999 let exch_b = bob.key_exchange_bytes(&alice).unwrap();
1000 assert_eq!(exch_a, exch_b);
1001
1002 let _aes_key =
1003 Box::<AnyKey>::from_key_exchange(KeyAlg::Aes(AesTypes::A256Gcm), &*alice, &*bob)
1004 .unwrap();
1005 }
1006
1007 #[cfg(feature = "chacha")]
1008 #[test]
1009 fn key_encrypt_any() {
1010 use crate::buffer::SecretBytes;
1011 let message = b"test message";
1012 let mut data = SecretBytes::from(&message[..]);
1013
1014 let key = Box::<AnyKey>::random(KeyAlg::Chacha20(Chacha20Types::XC20P)).unwrap();
1015 let nonce = [0u8; 24]; key.encrypt_in_place(&mut data, &nonce, &[]).unwrap();
1017 assert_ne!(data, &message[..]);
1018 key.decrypt_in_place(&mut data, &nonce, &[]).unwrap();
1019 assert_eq!(data, &message[..]);
1020 }
1021}