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, 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 = "chacha")]
266 KeyAlg::Chacha20(Chacha20Types::C20P) => {
267 Chacha20Key::<C20P>::generate(rng).map(R::alloc_key)
268 }
269 #[cfg(feature = "chacha")]
270 KeyAlg::Chacha20(Chacha20Types::XC20P) => {
271 Chacha20Key::<XC20P>::generate(rng).map(R::alloc_key)
272 }
273 #[cfg(feature = "ed25519")]
274 KeyAlg::Ed25519 => Ed25519KeyPair::generate(rng).map(R::alloc_key),
275 #[cfg(feature = "ed25519")]
276 KeyAlg::X25519 => X25519KeyPair::generate(rng).map(R::alloc_key),
277 #[cfg(feature = "k256")]
278 KeyAlg::EcCurve(EcCurves::Secp256k1) => K256KeyPair::generate(rng).map(R::alloc_key),
279 #[cfg(feature = "p256")]
280 KeyAlg::EcCurve(EcCurves::Secp256r1) => P256KeyPair::generate(rng).map(R::alloc_key),
281 #[cfg(feature = "p384")]
282 KeyAlg::EcCurve(EcCurves::Secp384r1) => P384KeyPair::generate(rng).map(R::alloc_key),
283 #[allow(unreachable_patterns)]
284 _ => Err(err_msg!(
285 Unsupported,
286 "Unsupported algorithm for key generation with rng"
287 )),
288 }
289}
290
291#[inline]
292fn generate_any_for_hardware<R: AllocKey>(alg: KeyAlg) -> Result<R, Error> {
293 match alg {
294 #[cfg(feature = "p256_hardware")]
295 KeyAlg::EcCurve(EcCurves::Secp256r1) => P256HardwareKeyPair::generate(
296 uuid::Uuid::new_v4()
297 .hyphenated()
298 .encode_lower(&mut uuid::Uuid::encode_buffer()),
299 )
300 .map(R::alloc_key),
301 _ => Err(err_msg!(
302 Unsupported,
303 "Unsupported algorithm for key generation with id"
304 )),
305 }
306}
307
308#[inline]
309fn get_any_with_id<R: AllocKey>(alg: KeyAlg, _id: &str) -> Result<R, Error> {
310 let key = match alg {
311 #[cfg(feature = "p256_hardware")]
312 KeyAlg::EcCurve(EcCurves::Secp256r1) => P256HardwareKeyPair::from_id(_id).map(R::alloc_key),
313 _ => Err(err_msg!(
314 Unsupported,
315 "Unsupported algorithm for key retrieval by id"
316 )),
317 }?;
318
319 Ok(key)
320}
321
322#[inline]
323fn from_public_bytes_any<R: AllocKey>(alg: KeyAlg, public: &[u8]) -> Result<R, Error> {
324 match alg {
325 #[cfg(feature = "bls")]
326 KeyAlg::Bls12_381(BlsCurves::G1) => {
327 BlsKeyPair::<G1>::from_public_bytes(public).map(R::alloc_key)
328 }
329 #[cfg(feature = "bls")]
330 KeyAlg::Bls12_381(BlsCurves::G2) => {
331 BlsKeyPair::<G2>::from_public_bytes(public).map(R::alloc_key)
332 }
333 #[cfg(feature = "ed25519")]
334 KeyAlg::Ed25519 => Ed25519KeyPair::from_public_bytes(public).map(R::alloc_key),
335 #[cfg(feature = "ed25519")]
336 KeyAlg::X25519 => X25519KeyPair::from_public_bytes(public).map(R::alloc_key),
337 #[cfg(feature = "k256")]
338 KeyAlg::EcCurve(EcCurves::Secp256k1) => {
339 K256KeyPair::from_public_bytes(public).map(R::alloc_key)
340 }
341 #[cfg(feature = "p256")]
342 KeyAlg::EcCurve(EcCurves::Secp256r1) => {
343 P256KeyPair::from_public_bytes(public).map(R::alloc_key)
344 }
345 #[cfg(feature = "p384")]
346 KeyAlg::EcCurve(EcCurves::Secp384r1) => {
347 P384KeyPair::from_public_bytes(public).map(R::alloc_key)
348 }
349 #[allow(unreachable_patterns)]
350 _ => Err(err_msg!(
351 Unsupported,
352 "Unsupported algorithm for public key import"
353 )),
354 }
355}
356
357#[inline]
358fn from_secret_bytes_any<R: AllocKey>(alg: KeyAlg, secret: &[u8]) -> Result<R, Error> {
359 match alg {
360 #[cfg(feature = "aes")]
361 KeyAlg::Aes(AesTypes::A128Gcm) => {
362 AesKey::<A128Gcm>::from_secret_bytes(secret).map(R::alloc_key)
363 }
364 #[cfg(feature = "aes")]
365 KeyAlg::Aes(AesTypes::A256Gcm) => {
366 AesKey::<A256Gcm>::from_secret_bytes(secret).map(R::alloc_key)
367 }
368 #[cfg(feature = "aes")]
369 KeyAlg::Aes(AesTypes::A128CbcHs256) => {
370 AesKey::<A128CbcHs256>::from_secret_bytes(secret).map(R::alloc_key)
371 }
372 #[cfg(feature = "aes")]
373 KeyAlg::Aes(AesTypes::A256CbcHs512) => {
374 AesKey::<A256CbcHs512>::from_secret_bytes(secret).map(R::alloc_key)
375 }
376 #[cfg(feature = "aes")]
377 KeyAlg::Aes(AesTypes::A128Kw) => {
378 AesKey::<A128Kw>::from_secret_bytes(secret).map(R::alloc_key)
379 }
380 #[cfg(feature = "aes")]
381 KeyAlg::Aes(AesTypes::A256Kw) => {
382 AesKey::<A256Kw>::from_secret_bytes(secret).map(R::alloc_key)
383 }
384 #[cfg(feature = "bls")]
385 KeyAlg::Bls12_381(BlsCurves::G1) => {
386 BlsKeyPair::<G1>::from_secret_bytes(secret).map(R::alloc_key)
387 }
388 #[cfg(feature = "bls")]
389 KeyAlg::Bls12_381(BlsCurves::G2) => {
390 BlsKeyPair::<G2>::from_secret_bytes(secret).map(R::alloc_key)
391 }
392 #[cfg(feature = "chacha")]
393 KeyAlg::Chacha20(Chacha20Types::C20P) => {
394 Chacha20Key::<C20P>::from_secret_bytes(secret).map(R::alloc_key)
395 }
396 #[cfg(feature = "chacha")]
397 KeyAlg::Chacha20(Chacha20Types::XC20P) => {
398 Chacha20Key::<XC20P>::from_secret_bytes(secret).map(R::alloc_key)
399 }
400 #[cfg(feature = "ed25519")]
401 KeyAlg::Ed25519 => Ed25519KeyPair::from_secret_bytes(secret).map(R::alloc_key),
402 #[cfg(feature = "ed25519")]
403 KeyAlg::X25519 => X25519KeyPair::from_secret_bytes(secret).map(R::alloc_key),
404 #[cfg(feature = "k256")]
405 KeyAlg::EcCurve(EcCurves::Secp256k1) => {
406 K256KeyPair::from_secret_bytes(secret).map(R::alloc_key)
407 }
408 #[cfg(feature = "p256")]
409 KeyAlg::EcCurve(EcCurves::Secp256r1) => {
410 P256KeyPair::from_secret_bytes(secret).map(R::alloc_key)
411 }
412 #[cfg(feature = "p384")]
413 KeyAlg::EcCurve(EcCurves::Secp384r1) => {
414 P384KeyPair::from_secret_bytes(secret).map(R::alloc_key)
415 }
416 #[allow(unreachable_patterns)]
417 _ => Err(err_msg!(
418 Unsupported,
419 "Unsupported algorithm for secret key import"
420 )),
421 }
422}
423
424#[cfg(any(feature = "aes", feature = "chacha"))]
425#[inline]
426fn from_key_exchange_any<R, Sk, Pk>(alg: KeyAlg, secret: &Sk, public: &Pk) -> Result<R, Error>
427where
428 R: AllocKey,
429 Sk: KeyExchange<Pk> + ?Sized,
430 Pk: ?Sized,
431{
432 match alg {
433 #[cfg(feature = "aes")]
434 KeyAlg::Aes(AesTypes::A128Gcm) => {
435 AesKey::<A128Gcm>::from_key_exchange(secret, public).map(R::alloc_key)
436 }
437 #[cfg(feature = "aes")]
438 KeyAlg::Aes(AesTypes::A256Gcm) => {
439 AesKey::<A256Gcm>::from_key_exchange(secret, public).map(R::alloc_key)
440 }
441 #[cfg(feature = "aes")]
442 KeyAlg::Aes(AesTypes::A128CbcHs256) => {
443 AesKey::<A128CbcHs256>::from_key_exchange(secret, public).map(R::alloc_key)
444 }
445 #[cfg(feature = "aes")]
446 KeyAlg::Aes(AesTypes::A256CbcHs512) => {
447 AesKey::<A256CbcHs512>::from_key_exchange(secret, public).map(R::alloc_key)
448 }
449 #[cfg(feature = "aes")]
450 KeyAlg::Aes(AesTypes::A128Kw) => {
451 AesKey::<A128Kw>::from_key_exchange(secret, public).map(R::alloc_key)
452 }
453 #[cfg(feature = "aes")]
454 KeyAlg::Aes(AesTypes::A256Kw) => {
455 AesKey::<A256Kw>::from_key_exchange(secret, public).map(R::alloc_key)
456 }
457 #[cfg(feature = "chacha")]
458 KeyAlg::Chacha20(Chacha20Types::C20P) => {
459 Chacha20Key::<C20P>::from_key_exchange(secret, public).map(R::alloc_key)
460 }
461 #[cfg(feature = "chacha")]
462 KeyAlg::Chacha20(Chacha20Types::XC20P) => {
463 Chacha20Key::<XC20P>::from_key_exchange(secret, public).map(R::alloc_key)
464 }
465 #[allow(unreachable_patterns)]
466 _ => Err(err_msg!(
467 Unsupported,
468 "Unsupported algorithm for key exchange"
469 )),
470 }
471}
472
473#[cfg(not(any(feature = "aes", feature = "chacha")))]
474#[inline]
475fn from_key_exchange_any<R, Sk: ?Sized, Pk: ?Sized>(
476 _alg: KeyAlg,
477 _secret: &Sk,
478 _public: &Pk,
479) -> Result<R, Error> {
480 return Err(err_msg!(
481 Unsupported,
482 "Unsupported algorithm for key exchange"
483 ));
484}
485
486#[cfg(any(feature = "aes", feature = "chacha"))]
487#[inline]
488fn from_key_derivation_any<R: AllocKey>(
489 alg: KeyAlg,
490 derive: impl KeyDerivation,
491) -> Result<R, Error> {
492 match alg {
493 #[cfg(feature = "aes")]
494 KeyAlg::Aes(AesTypes::A128Gcm) => {
495 AesKey::<A128Gcm>::from_key_derivation(derive).map(R::alloc_key)
496 }
497 #[cfg(feature = "aes")]
498 KeyAlg::Aes(AesTypes::A256Gcm) => {
499 AesKey::<A256Gcm>::from_key_derivation(derive).map(R::alloc_key)
500 }
501 #[cfg(feature = "aes")]
502 KeyAlg::Aes(AesTypes::A128CbcHs256) => {
503 AesKey::<A128CbcHs256>::from_key_derivation(derive).map(R::alloc_key)
504 }
505 #[cfg(feature = "aes")]
506 KeyAlg::Aes(AesTypes::A256CbcHs512) => {
507 AesKey::<A256CbcHs512>::from_key_derivation(derive).map(R::alloc_key)
508 }
509 #[cfg(feature = "aes")]
510 KeyAlg::Aes(AesTypes::A128Kw) => {
511 AesKey::<A128Kw>::from_key_derivation(derive).map(R::alloc_key)
512 }
513 #[cfg(feature = "aes")]
514 KeyAlg::Aes(AesTypes::A256Kw) => {
515 AesKey::<A256Kw>::from_key_derivation(derive).map(R::alloc_key)
516 }
517 #[cfg(feature = "chacha")]
518 KeyAlg::Chacha20(Chacha20Types::C20P) => {
519 Chacha20Key::<C20P>::from_key_derivation(derive).map(R::alloc_key)
520 }
521 #[cfg(feature = "chacha")]
522 KeyAlg::Chacha20(Chacha20Types::XC20P) => {
523 Chacha20Key::<XC20P>::from_key_derivation(derive).map(R::alloc_key)
524 }
525 #[allow(unreachable_patterns)]
526 _ => Err(err_msg!(
527 Unsupported,
528 "Unsupported algorithm for key derivation"
529 )),
530 }
531}
532
533#[cfg(not(any(feature = "aes", feature = "chacha")))]
534fn from_key_derivation_any<R: AllocKey>(
535 _alg: KeyAlg,
536 _derive: impl KeyDerivation,
537) -> Result<R, Error> {
538 return Err(err_msg!(
539 Unsupported,
540 "Unsupported algorithm for key derivation"
541 ));
542}
543
544#[inline]
545fn convert_key_any<R: AllocKey>(key: &AnyKey, alg: KeyAlg) -> Result<R, Error> {
546 match (key.algorithm(), alg) {
547 #[cfg(feature = "bls")]
548 (KeyAlg::Bls12_381(BlsCurves::G1), KeyAlg::Bls12_381(BlsCurves::G2)) => Ok(R::alloc_key(
549 BlsKeyPair::<G2>::try_from(key.assume::<BlsKeyPair<G1>>())?,
550 )),
551 #[cfg(feature = "bls")]
552 (KeyAlg::Bls12_381(BlsCurves::G2), KeyAlg::Bls12_381(BlsCurves::G1)) => Ok(R::alloc_key(
553 BlsKeyPair::<G1>::try_from(key.assume::<BlsKeyPair<G2>>())?,
554 )),
555 #[cfg(feature = "ed25519")]
556 (KeyAlg::Ed25519, KeyAlg::X25519) => Ok(<X25519KeyPair as TryFrom<_>>::try_from(
557 key.assume::<Ed25519KeyPair>(),
558 )
559 .map(R::alloc_key)?),
560 #[allow(unreachable_patterns)]
561 _ => Err(err_msg!(
562 Unsupported,
563 "Unsupported key conversion operation"
564 )),
565 }
566}
567
568#[inline]
569fn get_key_id_any(key: &AnyKey) -> Result<SecretBytes, Error> {
570 match key.algorithm() {
571 #[cfg(feature = "p256_hardware")]
572 KeyAlg::EcCurve(EcCurves::Secp256r1) => {
573 Ok(key.assume::<P256HardwareKeyPair>().key_id.clone())
574 }
575 #[allow(unreachable_patterns)]
576 _ => Err(err_msg!(Unsupported, "Unsupported get key id operation")),
577 }
578}
579
580impl FromJwk for Box<AnyKey> {
581 fn from_jwk_parts(jwk: JwkParts<'_>) -> Result<Self, Error> {
582 from_jwk_any(jwk)
583 }
584}
585
586impl FromJwk for Arc<AnyKey> {
587 fn from_jwk_parts(jwk: JwkParts<'_>) -> Result<Self, Error> {
588 from_jwk_any(jwk)
589 }
590}
591
592#[inline]
593fn from_jwk_any<R: AllocKey>(jwk: JwkParts<'_>) -> Result<R, Error> {
594 match (jwk.kty, jwk.crv.as_ref(), jwk.alg.as_ref()) {
595 #[cfg(feature = "aes")]
596 ("oct", _, A128Gcm::JWK_ALG) => AesKey::<A128Gcm>::from_jwk_parts(jwk).map(R::alloc_key),
597 #[cfg(feature = "aes")]
598 ("oct", _, A256Gcm::JWK_ALG) => AesKey::<A256Gcm>::from_jwk_parts(jwk).map(R::alloc_key),
599 #[cfg(feature = "aes")]
600 ("oct", _, A128CbcHs256::JWK_ALG) => {
601 AesKey::<A128CbcHs256>::from_jwk_parts(jwk).map(R::alloc_key)
602 }
603 #[cfg(feature = "aes")]
604 ("oct", _, A256CbcHs512::JWK_ALG) => {
605 AesKey::<A256CbcHs512>::from_jwk_parts(jwk).map(R::alloc_key)
606 }
607 #[cfg(feature = "aes")]
608 ("oct", _, A128Kw::JWK_ALG) => AesKey::<A128Kw>::from_jwk_parts(jwk).map(R::alloc_key),
609 #[cfg(feature = "aes")]
610 ("oct", _, A256Kw::JWK_ALG) => AesKey::<A256Kw>::from_jwk_parts(jwk).map(R::alloc_key),
611 #[cfg(feature = "bls")]
612 ("EC", G1::JWK_CURVE, _) => BlsKeyPair::<G1>::from_jwk_parts(jwk).map(R::alloc_key),
613 #[cfg(feature = "bls")]
614 ("EC", G2::JWK_CURVE, _) => BlsKeyPair::<G2>::from_jwk_parts(jwk).map(R::alloc_key),
615 #[cfg(feature = "bls")]
616 ("OKP", G1::JWK_CURVE_OKP, _) => BlsKeyPair::<G1>::from_jwk_parts(jwk).map(R::alloc_key),
617 #[cfg(feature = "bls")]
618 ("OKP", G2::JWK_CURVE_OKP, _) => BlsKeyPair::<G2>::from_jwk_parts(jwk).map(R::alloc_key),
619 #[cfg(feature = "chacha")]
620 ("oct", _, C20P::JWK_ALG) => Chacha20Key::<C20P>::from_jwk_parts(jwk).map(R::alloc_key),
621 #[cfg(feature = "chacha")]
622 ("oct", _, XC20P::JWK_ALG) => Chacha20Key::<XC20P>::from_jwk_parts(jwk).map(R::alloc_key),
623 #[cfg(feature = "ed25519")]
624 ("OKP", ed25519::JWK_CURVE, _) => Ed25519KeyPair::from_jwk_parts(jwk).map(R::alloc_key),
625 #[cfg(feature = "ed25519")]
626 ("OKP", x25519::JWK_CURVE, _) => X25519KeyPair::from_jwk_parts(jwk).map(R::alloc_key),
627 #[cfg(feature = "k256")]
628 ("EC", k256::JWK_CURVE, _) => K256KeyPair::from_jwk_parts(jwk).map(R::alloc_key),
629 #[cfg(feature = "p256")]
630 ("EC", p256::JWK_CURVE, _) => P256KeyPair::from_jwk_parts(jwk).map(R::alloc_key),
631 #[cfg(feature = "p384")]
632 ("EC", p384::JWK_CURVE, _) => P384KeyPair::from_jwk_parts(jwk).map(R::alloc_key),
633 _ => Err(err_msg!(Unsupported, "Unsupported JWK for key import")),
634 }
635}
636
637macro_rules! match_key_alg {
638 ($slf:expr, $ty:ty, $($kty:ident),+ $(,$errmsg:literal)?) => {{
639 fn matcher(key: &AnyKey) -> Result<$ty, Error> {
640 #[allow(unused_variables)]
641 let alg = key.algorithm();
642 match_key_alg!(@ $($kty)+ ; key, alg);
643 return Err(err_msg!(Unsupported $(,$errmsg)?))
644 }
645 matcher($slf)
646 }};
647 (@ ; $key:ident, $alg:ident) => {()};
648 (@ Aes $($rest:ident)*; $key:ident, $alg:ident) => {{
649 #[cfg(feature = "aes")]
650 if $alg == KeyAlg::Aes(AesTypes::A128Gcm) {
651 return Ok($key.assume::<AesKey<A128Gcm>>());
652 }
653 #[cfg(feature = "aes")]
654 if $alg == KeyAlg::Aes(AesTypes::A256Gcm) {
655 return Ok($key.assume::<AesKey<A256Gcm>>());
656 }
657 #[cfg(feature = "aes")]
658 if $alg == KeyAlg::Aes(AesTypes::A128CbcHs256) {
659 return Ok($key.assume::<AesKey<A128CbcHs256>>());
660 }
661 #[cfg(feature = "aes")]
662 if $alg == KeyAlg::Aes(AesTypes::A256CbcHs512) {
663 return Ok($key.assume::<AesKey<A256CbcHs512>>());
664 }
665 #[cfg(feature = "aes")]
666 if $alg == KeyAlg::Aes(AesTypes::A128Kw) {
667 return Ok($key.assume::<AesKey<A128Kw>>());
668 }
669 #[cfg(feature = "aes")]
670 if $alg == KeyAlg::Aes(AesTypes::A256Kw) {
671 return Ok($key.assume::<AesKey<A256Kw>>());
672 }
673 match_key_alg!(@ $($rest)*; $key, $alg)
674 }};
675 (@ Bls $($rest:ident)*; $key:ident, $alg:ident) => {{
676 #[cfg(feature = "bls")]
677 if $alg == KeyAlg::Bls12_381(BlsCurves::G1) {
678 return Ok($key.assume::<BlsKeyPair<G1>>());
679 }
680 #[cfg(feature = "bls")]
681 if $alg == KeyAlg::Bls12_381(BlsCurves::G2) {
682 return Ok($key.assume::<BlsKeyPair<G2>>());
683 }
684 match_key_alg!(@ $($rest)*; $key, $alg)
685 }};
686 (@ Chacha $($rest:ident)*; $key:ident, $alg:ident) => {{
687 #[cfg(feature = "chacha")]
688 if $alg == KeyAlg::Chacha20(Chacha20Types::C20P) {
689 return Ok($key.assume::<Chacha20Key<C20P>>());
690 }
691 #[cfg(feature = "chacha")]
692 if $alg == KeyAlg::Chacha20(Chacha20Types::XC20P) {
693 return Ok($key.assume::<Chacha20Key<XC20P>>());
694 }
695 match_key_alg!(@ $($rest)*; $key, $alg)
696 }};
697 (@ Ed25519 $($rest:ident)*; $key:ident, $alg:ident) => {{
698 #[cfg(feature = "ed25519")]
699 if $alg == KeyAlg::Ed25519 {
700 return Ok($key.assume::<Ed25519KeyPair>())
701 }
702 match_key_alg!(@ $($rest)*; $key, $alg)
703 }};
704 (@ X25519 $($rest:ident)*; $key:ident, $alg:ident) => {{
705 #[cfg(feature = "ed25519")]
706 if $alg == KeyAlg::X25519 {
707 return Ok($key.assume::<X25519KeyPair>())
708 }
709 match_key_alg!(@ $($rest)*; $key, $alg)
710 }};
711 (@ K256 $($rest:ident)*; $key:ident, $alg:ident) => {{
712 #[cfg(feature = "k256")]
713 if $alg == KeyAlg::EcCurve(EcCurves::Secp256k1) {
714 return Ok($key.assume::<K256KeyPair>())
715 }
716 match_key_alg!(@ $($rest)*; $key, $alg)
717 }};
718 (@ P256 $($rest:ident)*; $key:ident, $alg:ident) => {{
719 #[cfg(feature = "p256")]
720 if $alg == KeyAlg::EcCurve(EcCurves::Secp256r1) && $key.backend() == KeyBackend::Software {
721 return Ok($key.assume::<P256KeyPair>())
722 }
723 match_key_alg!(@ $($rest)*; $key, $alg)
724 }};
725 (@ P256Hardware $($rest:ident)*; $key:ident, $alg:ident) => {{
726 #[cfg(feature = "p256_hardware")]
727 if $alg == KeyAlg::EcCurve(EcCurves::Secp256r1) && $key.backend() == KeyBackend::SecureElement {
728 return Ok($key.assume::<P256HardwareKeyPair>())
729 }
730 match_key_alg!(@ $($rest)*; $key, $alg)
731 }};
732 (@ P384 $($rest:ident)*; $key:ident, $alg:ident) => {{
733 #[cfg(feature = "p384")]
734 if $alg == KeyAlg::EcCurve(EcCurves::Secp384r1) {
735 return Ok($key.assume::<P384KeyPair>())
736 }
737 match_key_alg!(@ $($rest)*; $key, $alg)
738 }};
739}
740
741impl AnyKey {
742 fn key_as_aead(&self) -> Result<&dyn KeyAeadInPlace, Error> {
743 match_key_alg! {
744 self,
745 &dyn KeyAeadInPlace,
746 Aes,
747 Chacha,
748 "AEAD is not supported for this key type"
749 }
750 }
751
752 fn key_to_secret(&self) -> Result<&dyn ToSecretBytes, Error> {
753 match_key_alg! {
754 self,
755 &dyn ToSecretBytes,
756 Aes,
757 Bls,
758 Chacha,
759 Ed25519,
760 K256,
761 P256,
762 P384,
763 X25519,
764 "Secret key export is not supported for this key type"
765 }
766 }
767
768 fn key_to_public(&self) -> Result<&dyn ToPublicBytes, Error> {
769 match_key_alg! {
770 self,
771 &dyn ToPublicBytes,
772 Bls,
773 Ed25519,
774 K256,
775 P256,
776 P256Hardware,
777 P384,
778 X25519,
779 "Public key export is not supported for this key type"
780 }
781 }
782}
783
784impl ToPublicBytes for AnyKey {
785 fn public_bytes_length(&self) -> Result<usize, Error> {
786 self.key_to_public()?.public_bytes_length()
787 }
788
789 fn write_public_bytes(&self, out: &mut dyn WriteBuffer) -> Result<(), Error> {
790 self.key_to_public()?.write_public_bytes(out)
791 }
792}
793
794impl ToSecretBytes for AnyKey {
795 fn secret_bytes_length(&self) -> Result<usize, Error> {
796 self.key_to_secret()?.secret_bytes_length()
797 }
798
799 fn write_secret_bytes(&self, out: &mut dyn WriteBuffer) -> Result<(), Error> {
800 self.key_to_secret()?.write_secret_bytes(out)
801 }
802}
803
804impl KeyExchange for AnyKey {
805 fn write_key_exchange(&self, other: &AnyKey, out: &mut dyn WriteBuffer) -> Result<(), Error> {
806 if self.key_type_id() != other.key_type_id() {
807 return Err(err_msg!(Unsupported, "Unsupported key exchange"));
808 }
809 match self.algorithm() {
810 #[cfg(feature = "ed25519")]
811 KeyAlg::X25519 => Ok(self
812 .assume::<X25519KeyPair>()
813 .write_key_exchange(other.assume::<X25519KeyPair>(), out)?),
814 #[cfg(feature = "k256")]
815 KeyAlg::EcCurve(EcCurves::Secp256k1) => Ok(self
816 .assume::<K256KeyPair>()
817 .write_key_exchange(other.assume::<K256KeyPair>(), out)?),
818 #[cfg(feature = "p256")]
819 KeyAlg::EcCurve(EcCurves::Secp256r1) => Ok(self
820 .assume::<P256KeyPair>()
821 .write_key_exchange(other.assume::<P256KeyPair>(), out)?),
822 #[cfg(feature = "p384")]
823 KeyAlg::EcCurve(EcCurves::Secp384r1) => Ok(self
824 .assume::<P384KeyPair>()
825 .write_key_exchange(other.assume::<P384KeyPair>(), out)?),
826 #[allow(unreachable_patterns)]
827 _ => {
828 let _ = out;
829 Err(err_msg!(Unsupported, "Unsupported key exchange"))
830 }
831 }
832 }
833}
834
835impl KeyAeadInPlace for AnyKey {
836 fn encrypt_in_place(
837 &self,
838 buffer: &mut dyn ResizeBuffer,
839 nonce: &[u8],
840 aad: &[u8],
841 ) -> Result<usize, Error> {
842 self.key_as_aead()?.encrypt_in_place(buffer, nonce, aad)
843 }
844
845 fn decrypt_in_place(
846 &self,
847 buffer: &mut dyn ResizeBuffer,
848 nonce: &[u8],
849 aad: &[u8],
850 ) -> Result<(), Error> {
851 self.key_as_aead()?.decrypt_in_place(buffer, nonce, aad)
852 }
853
854 fn aead_params(&self) -> KeyAeadParams {
855 if let Ok(key) = self.key_as_aead() {
856 key.aead_params()
857 } else {
858 KeyAeadParams::default()
859 }
860 }
861
862 fn aead_padding(&self, msg_len: usize) -> usize {
863 if let Ok(key) = self.key_as_aead() {
864 key.aead_padding(msg_len)
865 } else {
866 0
867 }
868 }
869}
870
871impl ToJwk for AnyKey {
872 fn encode_jwk(&self, enc: &mut dyn JwkEncoder) -> Result<(), Error> {
873 let key = match_key_alg! {
874 self,
875 &dyn ToJwk,
876 Aes,
877 Bls,
878 Chacha,
879 Ed25519,
880 K256,
881 P256,
882 P256Hardware,
883 P384,
884 X25519,
885 "JWK export is not supported for this key type"
886 }?;
887 key.encode_jwk(enc)
888 }
889}
890
891impl KeySign for AnyKey {
892 fn write_signature(
893 &self,
894 message: &[u8],
895 sig_type: Option<SignatureType>,
896 out: &mut dyn WriteBuffer,
897 ) -> Result<(), Error> {
898 let key = match_key_alg! {
899 self,
900 &dyn KeySign,
901 Ed25519,
902 K256,
903 P256,
904 P256Hardware,
905 P384,
906 "Signing is not supported for this key type"
907 }?;
908 key.write_signature(message, sig_type, out)
909 }
910}
911
912impl KeySigVerify for AnyKey {
913 fn verify_signature(
914 &self,
915 message: &[u8],
916 signature: &[u8],
917 sig_type: Option<SignatureType>,
918 ) -> Result<bool, Error> {
919 let key = match_key_alg! {
920 self,
921 &dyn KeySigVerify,
922 Ed25519,
923 K256,
924 P256,
925 P256Hardware,
926 P384,
927 "Signature verification is not supported for this key type"
928 }?;
929 key.verify_signature(message, signature, sig_type)
930 }
931}
932
933trait AllocKey {
935 fn alloc_key<K: AnyKeyAlg + Send + Sync + RefUnwindSafe + UnwindSafe>(key: K) -> Self;
936}
937
938impl AllocKey for Arc<AnyKey> {
939 #[inline(always)]
940 fn alloc_key<K: AnyKeyAlg + Send + Sync + RefUnwindSafe + UnwindSafe>(key: K) -> Self {
941 Self::from_key(key)
942 }
943}
944
945impl AllocKey for Box<AnyKey> {
946 #[inline(always)]
947 fn alloc_key<K: AnyKeyAlg + Send + Sync + RefUnwindSafe + UnwindSafe>(key: K) -> Self {
948 Self::from_key(key)
949 }
950}
951
952pub trait AnyKeyAlg: HasKeyAlg + HasKeyBackend + 'static {
953 fn as_any(&self) -> &dyn Any;
954}
955
956impl<K: HasKeyAlg + HasKeyBackend + Sized + 'static> AnyKeyAlg for K {
958 fn as_any(&self) -> &dyn Any {
959 self
960 }
961}
962
963#[cfg(test)]
964mod tests {
965 #[allow(unused_imports)]
966 use super::*;
967
968 #[cfg(feature = "ed25519")]
971 #[test]
972 fn ed25519_as_any() {
973 let key = Box::<AnyKey>::random(KeyAlg::Ed25519).unwrap();
974 assert_eq!(key.algorithm(), KeyAlg::Ed25519);
975 assert_eq!(key.key_type_id(), TypeId::of::<Ed25519KeyPair>());
976 let _ = key.to_jwk_public(None).unwrap();
977 }
978
979 #[cfg(feature = "aes")]
980 #[test]
981 fn key_exchange_any() {
982 let alice = Box::<AnyKey>::random(KeyAlg::X25519).unwrap();
983 let bob = Box::<AnyKey>::random(KeyAlg::X25519).unwrap();
984 let exch_a = alice.key_exchange_bytes(&bob).unwrap();
985 let exch_b = bob.key_exchange_bytes(&alice).unwrap();
986 assert_eq!(exch_a, exch_b);
987
988 let _aes_key =
989 Box::<AnyKey>::from_key_exchange(KeyAlg::Aes(AesTypes::A256Gcm), &*alice, &*bob)
990 .unwrap();
991 }
992
993 #[cfg(feature = "chacha")]
994 #[test]
995 fn key_encrypt_any() {
996 use crate::buffer::SecretBytes;
997 let message = b"test message";
998 let mut data = SecretBytes::from(&message[..]);
999
1000 let key = Box::<AnyKey>::random(KeyAlg::Chacha20(Chacha20Types::XC20P)).unwrap();
1001 let nonce = [0u8; 24]; key.encrypt_in_place(&mut data, &nonce, &[]).unwrap();
1003 assert_ne!(data, &message[..]);
1004 key.decrypt_in_place(&mut data, &nonce, &[]).unwrap();
1005 assert_eq!(data, &message[..]);
1006 }
1007}