Skip to main content

spideroak_crypto/
rust.rs

1//! [RustCrypto] cryptography.
2//!
3//! [RustCrypto]: https://github.com/RustCrypto
4
5use core::{borrow::Borrow, fmt, result::Result};
6
7use aes_gcm::{
8    aead::{AeadInPlace, KeyInit, KeySizeUser},
9    A_MAX, C_MAX, P_MAX,
10};
11use crypto_common::BlockSizeUser;
12use ecdsa::{
13    der,
14    signature::{Signer as Signer_, Verifier},
15};
16use elliptic_curve::{
17    ecdh,
18    scalar::NonZeroScalar,
19    sec1::{EncodedPoint, FromEncodedPoint, ToEncodedPoint},
20    CurveArithmetic, FieldBytesSize,
21};
22use rand_core::{impls, CryptoRng, RngCore};
23use sha2::digest::OutputSizeUser;
24use subtle::{Choice, ConstantTimeEq};
25use typenum::{Unsigned, U12, U16};
26
27use crate::{
28    aead::{
29        check_open_in_place_params, check_seal_in_place_params, Aead, AeadKey, IndCca2, Lifetime,
30        OpenError, SealError,
31    },
32    block::BlockSize,
33    csprng::{Csprng, Random},
34    ec::{Curve, Secp256r1, Secp384r1},
35    hash::{Digest, Hash},
36    hex::{Hex, ToHex},
37    hkdf::hkdf_impl,
38    hmac::hmac_impl,
39    hpke::{AeadId, HpkeAead, KdfId, KemId},
40    import::{try_from_slice, ExportError, Import, ImportError},
41    kem::{dhkem_impl, DecapKey, Ecdh, EcdhError, EncapKey},
42    keys::{PublicKey, SecretKey, SecretKeyBytes},
43    oid::{
44        consts::{
45            AES_256_GCM, ECDSA_WITH_SHA2_256, ECDSA_WITH_SHA2_384, HKDF_WITH_SHA2_256,
46            HKDF_WITH_SHA2_384, HKDF_WITH_SHA2_512, HMAC_WITH_SHA2_256, HMAC_WITH_SHA2_384,
47            HMAC_WITH_SHA2_512, HMAC_WITH_SHA2_512_256, SECP256R1, SECP384R1, SHA2_256, SHA2_384,
48            SHA2_512, SHA2_512_256,
49        },
50        Identified, Oid,
51    },
52    signer::{Signature, Signer, SignerError, SigningKey, VerifyingKey},
53    zeroize::{is_zeroize_on_drop, Zeroize, ZeroizeOnDrop},
54};
55
56/// AES-256-GCM.
57#[cfg_attr(feature = "clone-aead", derive(Clone))]
58pub struct Aes256Gcm(aes_gcm::Aes256Gcm);
59
60impl Aead for Aes256Gcm {
61    // Assumes a random nonce.
62    const LIFETIME: Lifetime = Lifetime::Messages(u32::MAX as u64);
63
64    type KeySize = <aes_gcm::Aes256Gcm as KeySizeUser>::KeySize;
65    type NonceSize = U12;
66    type Overhead = U16; // tag only
67
68    const MAX_PLAINTEXT_SIZE: u64 = P_MAX;
69    const MAX_ADDITIONAL_DATA_SIZE: u64 = A_MAX;
70    const MAX_CIPHERTEXT_SIZE: u64 = C_MAX;
71
72    type Key = AeadKey<Self::KeySize>;
73
74    #[inline]
75    fn new(key: &Self::Key) -> Self {
76        let key: &[u8; 32] = key.as_array();
77        Self(aes_gcm::Aes256Gcm::new(key.into()))
78    }
79
80    fn seal_in_place(
81        &self,
82        nonce: &[u8],
83        data: &mut [u8],
84        tag: &mut [u8],
85        additional_data: &[u8],
86    ) -> Result<(), SealError> {
87        check_seal_in_place_params::<Self>(nonce, data, tag, additional_data)?;
88
89        let got_tag = self
90            .0
91            .encrypt_in_place_detached(
92                // From<&[T]> for GenericArray<T, _> panics on incorrect length
93                #[allow(clippy::unnecessary_fallible_conversions)]
94                nonce
95                    .try_into()
96                    .map_err(|_| SealError::InvalidNonceSize(InvalidNonceSize))?,
97                additional_data,
98                data,
99            )
100            .map_err(|_| SealError::Encryption)?;
101        tag.copy_from_slice(&got_tag[..]);
102
103        Ok(())
104    }
105
106    fn open_in_place(
107        &self,
108        nonce: &[u8],
109        data: &mut [u8],
110        tag: &[u8],
111        additional_data: &[u8],
112    ) -> Result<(), OpenError> {
113        check_open_in_place_params::<Self>(nonce, data, tag, additional_data)?;
114
115        self.0
116            .decrypt_in_place_detached(
117                // From<&[T]> for GenericArray<T, _> panics on incorrect length
118                #[allow(clippy::unnecessary_fallible_conversions)]
119                nonce
120                    .try_into()
121                    .map_err(|_| OpenError::InvalidNonceSize(InvalidNonceSize))?,
122                additional_data,
123                data,
124                // From<&[T]> for GenericArray<T, _> panics on incorrect length
125                #[allow(clippy::unnecessary_fallible_conversions)]
126                tag.try_into().map_err(|_| OpenError::InvalidOverheadSize)?,
127            )
128            .map_err(|_| OpenError::Authentication)
129    }
130}
131
132impl IndCca2 for Aes256Gcm {}
133
134impl Identified for Aes256Gcm {
135    const OID: &'static Oid = AES_256_GCM;
136}
137
138impl HpkeAead for Aes256Gcm {
139    const ID: AeadId = AeadId::Aes256Gcm;
140}
141
142impl fmt::Debug for Aes256Gcm {
143    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
144        f.debug_struct("Aes256Gcm").finish_non_exhaustive()
145    }
146}
147
148#[cfg(feature = "committing-aead")]
149mod committing {
150    use aes::cipher::{BlockEncrypt, BlockSizeUser, KeyInit};
151    use generic_array::GenericArray;
152    use typenum::{Unsigned, U32};
153
154    use super::{Aes256Gcm, Sha256};
155    use crate::{
156        aead::{AeadKey, BlockCipher},
157        oid::consts::{HTE_AES_256_GCM, UTC_AES_256_GCM},
158    };
159
160    /// AES-256.
161    #[doc(hidden)]
162    #[derive(Debug)]
163    pub struct Aes256(aes::Aes256);
164
165    impl BlockCipher for Aes256 {
166        type BlockSize = <aes::Aes256 as BlockSizeUser>::BlockSize;
167        const BLOCK_SIZE: usize = Self::BlockSize::USIZE;
168        type Key = AeadKey<U32>;
169
170        fn new(key: &Self::Key) -> Self {
171            let key: &[u8; 32] = key.as_array();
172            let cipher = <aes::Aes256 as KeyInit>::new(key.into());
173            Self(cipher)
174        }
175
176        fn encrypt_block(&self, block: &mut GenericArray<u8, Self::BlockSize>) {
177            // Mismatched GenericArray versions, yay.
178            let block: &mut [u8; 16] = block.as_mut();
179            self.0.encrypt_block(block.into())
180        }
181    }
182
183    crate::aead::utc_aead!(
184        Cmt1Aes256Gcm,
185        Aes256Gcm,
186        Aes256,
187        "CMT-1 AES-256-GCM.",
188        UTC_AES_256_GCM,
189    );
190    crate::aead::hte_aead!(
191        Cmt4Aes256Gcm,
192        Cmt1Aes256Gcm,
193        Sha256,
194        "CMT-4 AES-256-GCM.",
195        HTE_AES_256_GCM,
196    );
197}
198#[cfg(feature = "committing-aead")]
199#[cfg_attr(docsrs, doc(cfg(feature = "committing-aead")))]
200pub use committing::*;
201
202use crate::aead::InvalidNonceSize;
203
204macro_rules! curve_impl {
205    (
206        $name:ident,
207        $doc:expr,
208        $oid:expr,
209        $inner:ty,
210        $point:ident,
211        $curve:ident $(,)?
212    ) => {
213        #[doc = concat!($doc, ".")]
214        pub use $inner as $name;
215
216        impl Curve for $inner {
217            type ScalarSize = <$curve as Curve>::ScalarSize;
218            type CompressedSize = <$curve as Curve>::CompressedSize;
219            type UncompressedSize = <$curve as Curve>::UncompressedSize;
220        }
221
222        impl Identified for $inner {
223            const OID: &'static Oid = $oid;
224        }
225
226        #[doc = concat!("An encoded ", $doc, "point.")]
227        #[derive(Copy, Clone, Debug)]
228        pub struct $point(EncodedPoint<$inner>);
229
230        impl Borrow<[u8]> for $point {
231            fn borrow(&self) -> &[u8] {
232                self.0.as_bytes()
233            }
234        }
235
236        impl<'a> Import<&'a [u8]> for $point {
237            fn import(data: &'a [u8]) -> Result<Self, ImportError> {
238                let point = EncodedPoint::<$inner>::from_bytes(data)
239                    .map_err(|_| ImportError::InvalidSyntax)?;
240                Ok(Self(point))
241            }
242        }
243
244        impl ToHex for &$point {
245            type Output = EncodedPoint<$inner>;
246
247            fn to_hex(self) -> Hex<Self::Output> {
248                Hex::new(self.0)
249            }
250        }
251    };
252}
253curve_impl!(
254    P256,
255    "NIST-P256",
256    SECP256R1,
257    p256::NistP256,
258    P256Point,
259    Secp256r1
260);
261curve_impl!(
262    P384,
263    "NIST-P256",
264    SECP384R1,
265    p384::NistP384,
266    P384Point,
267    Secp384r1
268);
269
270/// An ECDH shared secret.
271pub struct SharedSecret<C>(ecdh::SharedSecret<C>)
272where
273    C: CurveArithmetic;
274
275impl<C> Borrow<[u8]> for SharedSecret<C>
276where
277    C: CurveArithmetic,
278{
279    fn borrow(&self) -> &[u8] {
280        self.0.raw_secret_bytes().as_slice()
281    }
282}
283
284impl<C> fmt::Debug for SharedSecret<C>
285where
286    C: CurveArithmetic,
287{
288    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
289        f.debug_struct("SharedSecret").finish_non_exhaustive()
290    }
291}
292
293impl<C> ZeroizeOnDrop for SharedSecret<C> where C: CurveArithmetic {}
294impl<C> Drop for SharedSecret<C>
295where
296    C: CurveArithmetic,
297{
298    fn drop(&mut self) {
299        is_zeroize_on_drop(&self.0);
300    }
301}
302
303macro_rules! ecdh_impl {
304    (
305        $curve:ident,
306        $doc:expr,
307        $sk:ident,
308        $pk:ident,
309        $point:ident $(,)?
310    ) => {
311        #[doc = concat!($doc, " ECDH private key.")]
312        #[derive(Clone)]
313        pub struct $sk(NonZeroScalar<$curve>);
314
315        impl DecapKey for $sk {
316            type EncapKey = $pk;
317
318            #[inline]
319            fn public(&self) -> Result<$pk, $crate::signer::PkError> {
320                Ok($pk(elliptic_curve::PublicKey::from_secret_scalar(&self.0)))
321            }
322        }
323
324        impl SecretKey for $sk {
325            type Size = FieldBytesSize<$curve>;
326
327            #[inline]
328            fn try_export_secret(&self) -> Result<SecretKeyBytes<Self::Size>, ExportError> {
329                // Mismatched GenericArray versions, yay.
330                let secret: [u8; FieldBytesSize::<$curve>::USIZE] = self.0.to_bytes().into();
331                Ok(SecretKeyBytes::new(secret.into()))
332            }
333        }
334
335        impl Random for $sk {
336            #[inline]
337            fn random<R: Csprng>(rng: R) -> Self {
338                let sk = NonZeroScalar::random(&mut RngWrapper(rng));
339                Self(sk)
340            }
341        }
342
343        impl fmt::Debug for $sk {
344            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
345                f.debug_struct(stringify!($sk)).finish_non_exhaustive()
346            }
347        }
348
349        impl ConstantTimeEq for $sk {
350            fn ct_eq(&self, other: &Self) -> Choice {
351                self.0.ct_eq(&other.0)
352            }
353        }
354
355        impl<'a> Import<&'a [u8]> for $sk {
356            fn import(data: &'a [u8]) -> Result<Self, ImportError> {
357                let bytes = *try_from_slice(data)?;
358                let sk = Option::from(NonZeroScalar::from_repr(bytes.into()))
359                    .ok_or(ImportError::InvalidSyntax)?;
360                Ok(Self(sk))
361            }
362        }
363
364        impl ZeroizeOnDrop for $sk {}
365        impl Drop for $sk {
366            fn drop(&mut self) {
367                self.0.zeroize();
368            }
369        }
370
371        #[doc = concat!($doc, " ECDH public key.")]
372        #[derive(Clone, Eq, PartialEq)]
373        pub struct $pk(elliptic_curve::PublicKey<$curve>);
374
375        impl EncapKey for $pk {}
376
377        impl PublicKey for $pk {
378            type Data = $point;
379
380            fn export(&self) -> Self::Data {
381                $point(self.0.to_encoded_point(false))
382            }
383        }
384
385        impl fmt::Debug for $pk {
386            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
387                f.debug_tuple(stringify!($pk))
388                    .field(&self.export().to_hex())
389                    .finish()
390            }
391        }
392
393        impl<'a> Import<&'a [u8]> for $pk {
394            fn import(data: &'a [u8]) -> Result<Self, ImportError> {
395                let point = EncodedPoint::<$curve>::from_bytes(data)
396                    .map_err(|_| ImportError::InvalidSyntax)?;
397                let pk = Option::from(elliptic_curve::PublicKey::from_encoded_point(&point))
398                    .ok_or(ImportError::InvalidSyntax)?;
399                Ok(Self(pk))
400            }
401        }
402
403        impl Ecdh for $curve {
404            const SCALAR_SIZE: usize = <$curve as Curve>::ScalarSize::USIZE;
405
406            type PrivateKey = $sk;
407            type PublicKey = $pk;
408            type SharedSecret = SharedSecret<$curve>;
409
410            fn ecdh(
411                local: &Self::PrivateKey,
412                remote: &Self::PublicKey,
413            ) -> Result<Self::SharedSecret, EcdhError> {
414                let secret = ecdh::diffie_hellman(&local.0, remote.0.as_affine());
415                Ok(SharedSecret(secret))
416            }
417        }
418    };
419}
420ecdh_impl!(P256, "P-256", P256PrivateKey, P256PublicKey, P256Point);
421ecdh_impl!(P384, "P-384", P384PrivateKey, P384PublicKey, P384Point);
422// RustCrypto hasn't really implemented P-521.
423
424dhkem_impl!(
425    DhKemP256HkdfSha256,
426    "DHKEM(P256, HKDF-SHA256)",
427    KemId::DhKemP256HkdfSha256,
428    P256,
429    HkdfSha256,
430    P256PrivateKey,
431    P256PublicKey,
432);
433
434/// An ASN.1 DER encoded ECDSA signature.
435#[derive(Clone, Debug)]
436pub struct SigBytes<T>(T);
437
438impl<T> Borrow<[u8]> for SigBytes<T>
439where
440    T: AsRef<[u8]>,
441{
442    fn borrow(&self) -> &[u8] {
443        self.0.as_ref()
444    }
445}
446
447macro_rules! ecdsa_impl {
448    (
449        $curve:ident,
450        $doc:expr,
451        $sk:ident,
452        $pk:ident,
453        $sig:ident,
454        $point:ident,
455        $sig_oid:expr $(,)?
456    ) => {
457        #[doc = concat!($doc, " ECDSA private key.")]
458        #[derive(Clone)]
459        pub struct $sk(ecdsa::SigningKey<$curve>);
460
461        impl SigningKey<$curve> for $sk {
462            fn sign(&self, msg: &[u8]) -> Result<$sig, SignerError> {
463                let sig = self.0.sign(msg);
464                Ok($sig(sig))
465            }
466
467            #[inline]
468            fn public(&self) -> Result<$pk, $crate::signer::PkError> {
469                Ok($pk(ecdsa::VerifyingKey::from(&self.0)))
470            }
471        }
472
473        impl SecretKey for $sk {
474            type Size = FieldBytesSize<$curve>;
475
476            #[inline]
477            fn try_export_secret(&self) -> Result<SecretKeyBytes<Self::Size>, ExportError> {
478                // Mismatched GenericArray versions, yay.
479                let secret: [u8; FieldBytesSize::<$curve>::USIZE] = self.0.to_bytes().into();
480                Ok(SecretKeyBytes::new(secret.into()))
481            }
482        }
483
484        impl Random for $sk {
485            #[inline]
486            fn random<R: Csprng>(rng: R) -> Self {
487                let sk = ecdsa::SigningKey::random(&mut RngWrapper(rng));
488                Self(sk)
489            }
490        }
491
492        impl fmt::Debug for $sk {
493            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
494                f.debug_struct(stringify!($sk)).finish_non_exhaustive()
495            }
496        }
497
498        impl ConstantTimeEq for $sk {
499            fn ct_eq(&self, other: &Self) -> Choice {
500                self.0.ct_eq(&other.0)
501            }
502        }
503
504        impl<'a> Import<&'a [u8]> for $sk {
505            fn import(data: &'a [u8]) -> Result<Self, ImportError> {
506                let sk =
507                    ecdsa::SigningKey::from_slice(data).map_err(|_| ImportError::InvalidSyntax)?;
508                Ok(Self(sk))
509            }
510        }
511
512        impl ZeroizeOnDrop for $sk {}
513        impl Drop for $sk {
514            #[inline]
515            fn drop(&mut self) {
516                is_zeroize_on_drop(&self.0);
517            }
518        }
519
520        #[doc = concat!($doc, " ECDSA public key.")]
521        #[derive(Clone, Eq, PartialEq)]
522        pub struct $pk(ecdsa::VerifyingKey<$curve>);
523
524        impl VerifyingKey<$curve> for $pk {
525            fn verify(&self, msg: &[u8], sig: &$sig) -> Result<(), SignerError> {
526                self.0
527                    .verify(msg, &sig.0)
528                    .map_err(|_| SignerError::Verification)
529            }
530        }
531
532        impl PublicKey for $pk {
533            type Data = $point;
534
535            fn export(&self) -> Self::Data {
536                $point(self.0.to_encoded_point(false))
537            }
538        }
539
540        impl fmt::Debug for $pk {
541            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
542                f.debug_struct(stringify!($pk))
543                    .field("point", &self.export().to_hex())
544                    .finish()
545            }
546        }
547
548        impl<'a> Import<&'a [u8]> for $pk {
549            fn import(data: &'a [u8]) -> Result<Self, ImportError> {
550                let point = EncodedPoint::<$curve>::from_bytes(data)
551                    .map_err(|_| ImportError::InvalidSyntax)?;
552                let pk = ecdsa::VerifyingKey::from_encoded_point(&point)
553                    .map_err(|_| ImportError::InvalidSyntax)?;
554                Ok(Self(pk))
555            }
556        }
557
558        #[doc = concat!($doc, " ECDSA signature.")]
559        #[derive(Clone, Debug)]
560        pub struct $sig(ecdsa::Signature<$curve>);
561
562        impl Signature<$curve> for $sig {
563            type Data = SigBytes<der::Signature<$curve>>;
564
565            fn export(&self) -> Self::Data {
566                SigBytes(self.0.to_der())
567            }
568        }
569
570        impl Identified for $sig {
571            const OID: &'static Oid = $sig_oid;
572        }
573
574        impl<'a> Import<&'a [u8]> for $sig {
575            fn import(data: &'a [u8]) -> Result<Self, ImportError> {
576                let sig =
577                    ecdsa::Signature::from_der(data).map_err(|_| ImportError::InvalidSyntax)?;
578                Ok(Self(sig))
579            }
580        }
581
582        impl Signer for $curve {
583            type SigningKey = $sk;
584            type VerifyingKey = $pk;
585            type Signature = $sig;
586        }
587    };
588}
589ecdsa_impl!(
590    P256,
591    "P-256 with SHA2-256",
592    P256SigningKey,
593    P256VerifyingKey,
594    P256Signature,
595    P256Point,
596    ECDSA_WITH_SHA2_256,
597);
598ecdsa_impl!(
599    P384,
600    "P-384 with SHA2-384",
601    P384SigningKey,
602    P384VerifyingKey,
603    P384Signature,
604    P384Point,
605    ECDSA_WITH_SHA2_384,
606);
607
608macro_rules! hash_impl {
609    (
610        $name:ident,
611        $doc:expr,
612        $oid:expr $(,)?
613    ) => {
614        #[doc = concat!($doc, ".")]
615        #[derive(Clone, Debug, Default)]
616        pub struct $name(sha2::$name);
617
618        impl Hash for $name {
619            type DigestSize = <sha2::$name as OutputSizeUser>::OutputSize;
620            const DIGEST_SIZE: usize =
621                <<sha2::$name as OutputSizeUser>::OutputSize as Unsigned>::USIZE;
622
623            #[inline]
624            fn new() -> Self {
625                Self(<sha2::$name as sha2::Digest>::new())
626            }
627
628            #[inline]
629            fn update(&mut self, data: &[u8]) {
630                sha2::Digest::update(&mut self.0, data)
631            }
632
633            #[inline]
634            fn digest(self) -> Digest<Self::DigestSize> {
635                Digest::from_array(sha2::Digest::finalize(self.0).into())
636            }
637
638            #[inline]
639            fn hash(data: &[u8]) -> Digest<Self::DigestSize> {
640                Digest::from_array(<sha2::$name as sha2::Digest>::digest(data).into())
641            }
642        }
643
644        impl BlockSize for $name {
645            type BlockSize = <sha2::$name as BlockSizeUser>::BlockSize;
646        }
647
648        impl Identified for $name {
649            const OID: &'static Oid = $oid;
650        }
651    };
652}
653hash_impl!(Sha256, "SHA2-256", SHA2_256);
654hash_impl!(Sha384, "SHA2-384", SHA2_384);
655hash_impl!(Sha512, "SHA2-512", SHA2_512);
656hash_impl!(Sha512_256, "SHA2-512-256", SHA2_512_256);
657
658hkdf_impl!(
659    HkdfSha256,
660    "HKDF-SHA2-256",
661    Sha256,
662    oid = HKDF_WITH_SHA2_256,
663    kdf_id = KdfId::HkdfSha256,
664);
665hkdf_impl!(
666    HkdfSha384,
667    "HKDF-SHA2-384",
668    Sha384,
669    oid = HKDF_WITH_SHA2_384,
670    kdf_id = KdfId::HkdfSha384,
671);
672hkdf_impl!(
673    HkdfSha512,
674    "HKDF-SHA2-512",
675    Sha512,
676    oid = HKDF_WITH_SHA2_512,
677    kdf_id = KdfId::HkdfSha512,
678);
679
680hmac_impl!(HmacSha256, "HMAC-SHA2-256", Sha256, HMAC_WITH_SHA2_256);
681hmac_impl!(HmacSha384, "HMAC-SHA2-384", Sha384, HMAC_WITH_SHA2_384);
682hmac_impl!(HmacSha512, "HMAC-SHA2-512", Sha512, HMAC_WITH_SHA2_512);
683hmac_impl!(
684    HmacSha512_512,
685    "HMAC-SHA2-512_512",
686    Sha512,
687    HMAC_WITH_SHA2_512_256,
688);
689
690/// Translates [`Csprng`] to [`RngCore`].
691struct RngWrapper<R>(R);
692
693impl<R> CryptoRng for RngWrapper<R> {}
694
695impl<R: Csprng> RngCore for RngWrapper<R> {
696    fn next_u32(&mut self) -> u32 {
697        impls::next_u32_via_fill(self)
698    }
699
700    fn next_u64(&mut self) -> u64 {
701        impls::next_u64_via_fill(self)
702    }
703
704    fn fill_bytes(&mut self, dst: &mut [u8]) {
705        self.0.fill_bytes(dst)
706    }
707
708    fn try_fill_bytes(&mut self, dst: &mut [u8]) -> Result<(), rand_core::Error> {
709        self.fill_bytes(dst);
710        Ok(())
711    }
712}
713
714#[cfg(test)]
715mod tests {
716    use super::*;
717
718    mod aead_tests {
719        use super::*;
720        use crate::test_util::test_aead;
721
722        test_aead!(aes256gcm, Aes256Gcm, AeadTest::AesGcm);
723
724        #[cfg(feature = "committing-aead")]
725        mod committing {
726            use super::*;
727
728            test_aead!(cmd1_aead_aes256_gcm, Cmt1Aes256Gcm);
729            test_aead!(cmd4_aead_aes256_gcm, Cmt4Aes256Gcm);
730        }
731    }
732
733    mod ecdh_tests {
734        use super::*;
735        use crate::test_util::vectors::{test_ecdh, EcdhTest};
736
737        #[test]
738        fn test_ecdh_p256() {
739            test_ecdh::<P256>(EcdhTest::EcdhSecp256r1Ecpoint);
740        }
741
742        #[test]
743        fn test_ecdh_p384() {
744            test_ecdh::<P384>(EcdhTest::EcdhSecp384r1Ecpoint);
745        }
746    }
747
748    mod ecdsa_tests {
749        use super::*;
750        use crate::test_util::test_signer;
751
752        test_signer!(p256, P256, EcdsaTest::EcdsaSecp256r1Sha256);
753        test_signer!(p384, P384, EcdsaTest::EcdsaSecp384r1Sha384);
754    }
755
756    mod hkdf_tests {
757        use super::*;
758        use crate::test_util::test_kdf;
759
760        test_kdf!(test_hkdf_sha256, HkdfSha256, HkdfTest::HkdfSha256);
761        test_kdf!(test_hkdf_sha384, HkdfSha384, HkdfTest::HkdfSha384);
762        test_kdf!(test_hkdf_sha512, HkdfSha512, HkdfTest::HkdfSha512);
763    }
764
765    mod hmac_tests {
766        use super::*;
767        use crate::test_util::test_mac;
768
769        test_mac!(test_hmac_sha256, HmacSha256, MacTest::HmacSha256);
770        test_mac!(test_hmac_sha384, HmacSha384, MacTest::HmacSha384);
771        test_mac!(test_hmac_sha512, HmacSha512, MacTest::HmacSha512);
772    }
773
774    mod hpke_tests {
775        use super::*;
776        use crate::test_util::test_hpke;
777
778        test_hpke!(
779            sha256,
780            DhKemP256HkdfSha256,
781            HkdfSha256,
782            Aes256Gcm,
783            HpkeTest::HpkeDhKemP256HkdfSha256HkdfSha256Aes256Gcm,
784        );
785        test_hpke!(
786            sha512,
787            DhKemP256HkdfSha256,
788            HkdfSha512,
789            Aes256Gcm,
790            HpkeTest::HpkeDhKemP256HkdfSha256HkdfSha512Aes256Gcm,
791        );
792    }
793}