xref: /aosp_15_r20/system/security/mls/mls-rs-crypto-boringssl/src/eddsa.rs (revision e1997b9af69e3155ead6e072d106a0077849ffba)
1*e1997b9aSAndroid Build Coastguard Worker // Copyright 2024, The Android Open Source Project
2*e1997b9aSAndroid Build Coastguard Worker //
3*e1997b9aSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*e1997b9aSAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*e1997b9aSAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*e1997b9aSAndroid Build Coastguard Worker //
7*e1997b9aSAndroid Build Coastguard Worker //     http://www.apache.org/licenses/LICENSE-2.0
8*e1997b9aSAndroid Build Coastguard Worker //
9*e1997b9aSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*e1997b9aSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*e1997b9aSAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*e1997b9aSAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*e1997b9aSAndroid Build Coastguard Worker // limitations under the License.
14*e1997b9aSAndroid Build Coastguard Worker 
15*e1997b9aSAndroid Build Coastguard Worker //! Edwards-curve digital signature algorithm.
16*e1997b9aSAndroid Build Coastguard Worker 
17*e1997b9aSAndroid Build Coastguard Worker use bssl_crypto::{ed25519, InvalidSignatureError};
18*e1997b9aSAndroid Build Coastguard Worker use mls_rs_core::crypto::{CipherSuite, SignaturePublicKey, SignatureSecretKey};
19*e1997b9aSAndroid Build Coastguard Worker use mls_rs_crypto_traits::Curve;
20*e1997b9aSAndroid Build Coastguard Worker 
21*e1997b9aSAndroid Build Coastguard Worker use core::array::TryFromSliceError;
22*e1997b9aSAndroid Build Coastguard Worker use thiserror::Error;
23*e1997b9aSAndroid Build Coastguard Worker 
24*e1997b9aSAndroid Build Coastguard Worker /// Errors returned from EdDSA.
25*e1997b9aSAndroid Build Coastguard Worker #[derive(Debug, Error)]
26*e1997b9aSAndroid Build Coastguard Worker pub enum EdDsaError {
27*e1997b9aSAndroid Build Coastguard Worker     /// Error returned when conversion from slice to array fails.
28*e1997b9aSAndroid Build Coastguard Worker     #[error(transparent)]
29*e1997b9aSAndroid Build Coastguard Worker     TryFromSliceError(#[from] TryFromSliceError),
30*e1997b9aSAndroid Build Coastguard Worker     /// Error returned on an invalid signature.
31*e1997b9aSAndroid Build Coastguard Worker     #[error("invalid signature")]
32*e1997b9aSAndroid Build Coastguard Worker     InvalidSig(InvalidSignatureError),
33*e1997b9aSAndroid Build Coastguard Worker     /// Error returned when the private key length is invalid.
34*e1997b9aSAndroid Build Coastguard Worker     #[error("EdDSA private key of invalid length {len}, expected length {expected_len}")]
35*e1997b9aSAndroid Build Coastguard Worker     InvalidPrivKeyLen {
36*e1997b9aSAndroid Build Coastguard Worker         /// Invalid key length.
37*e1997b9aSAndroid Build Coastguard Worker         len: usize,
38*e1997b9aSAndroid Build Coastguard Worker         /// Expected key length.
39*e1997b9aSAndroid Build Coastguard Worker         expected_len: usize,
40*e1997b9aSAndroid Build Coastguard Worker     },
41*e1997b9aSAndroid Build Coastguard Worker     /// Error returned when the public key length is invalid.
42*e1997b9aSAndroid Build Coastguard Worker     #[error("EdDSA public key of invalid length {len}, expected length {expected_len}")]
43*e1997b9aSAndroid Build Coastguard Worker     InvalidPubKeyLen {
44*e1997b9aSAndroid Build Coastguard Worker         /// Invalid key length.
45*e1997b9aSAndroid Build Coastguard Worker         len: usize,
46*e1997b9aSAndroid Build Coastguard Worker         /// Expected key length.
47*e1997b9aSAndroid Build Coastguard Worker         expected_len: usize,
48*e1997b9aSAndroid Build Coastguard Worker     },
49*e1997b9aSAndroid Build Coastguard Worker     /// Error returned when the signature length is invalid.
50*e1997b9aSAndroid Build Coastguard Worker     #[error("EdDSA signature of invalid length {len}, expected length {expected_len}")]
51*e1997b9aSAndroid Build Coastguard Worker     InvalidSigLen {
52*e1997b9aSAndroid Build Coastguard Worker         /// Invalid signature length.
53*e1997b9aSAndroid Build Coastguard Worker         len: usize,
54*e1997b9aSAndroid Build Coastguard Worker         /// Expected signature length.
55*e1997b9aSAndroid Build Coastguard Worker         expected_len: usize,
56*e1997b9aSAndroid Build Coastguard Worker     },
57*e1997b9aSAndroid Build Coastguard Worker     /// Error returned when unsupported cipher suite is requested.
58*e1997b9aSAndroid Build Coastguard Worker     #[error("unsupported cipher suite")]
59*e1997b9aSAndroid Build Coastguard Worker     UnsupportedCipherSuite,
60*e1997b9aSAndroid Build Coastguard Worker }
61*e1997b9aSAndroid Build Coastguard Worker 
62*e1997b9aSAndroid Build Coastguard Worker // Explicitly implemented as InvalidSignatureError's as_dyn_error does not satisfy trait bounds.
63*e1997b9aSAndroid Build Coastguard Worker impl From<InvalidSignatureError> for EdDsaError {
from(e: InvalidSignatureError) -> Self64*e1997b9aSAndroid Build Coastguard Worker     fn from(e: InvalidSignatureError) -> Self {
65*e1997b9aSAndroid Build Coastguard Worker         EdDsaError::InvalidSig(e)
66*e1997b9aSAndroid Build Coastguard Worker     }
67*e1997b9aSAndroid Build Coastguard Worker }
68*e1997b9aSAndroid Build Coastguard Worker 
69*e1997b9aSAndroid Build Coastguard Worker /// EdDSA implementation backed by BoringSSL.
70*e1997b9aSAndroid Build Coastguard Worker #[derive(Clone, Debug, Copy, PartialEq, Eq)]
71*e1997b9aSAndroid Build Coastguard Worker pub struct EdDsa(Curve);
72*e1997b9aSAndroid Build Coastguard Worker 
73*e1997b9aSAndroid Build Coastguard Worker impl EdDsa {
74*e1997b9aSAndroid Build Coastguard Worker     /// Creates a new EdDsa.
new(cipher_suite: CipherSuite) -> Option<Self>75*e1997b9aSAndroid Build Coastguard Worker     pub fn new(cipher_suite: CipherSuite) -> Option<Self> {
76*e1997b9aSAndroid Build Coastguard Worker         Curve::from_ciphersuite(cipher_suite, /*for_sig=*/ true).map(Self)
77*e1997b9aSAndroid Build Coastguard Worker     }
78*e1997b9aSAndroid Build Coastguard Worker 
79*e1997b9aSAndroid Build Coastguard Worker     /// Generates a key pair.
signature_key_generate( &self, ) -> Result<(SignatureSecretKey, SignaturePublicKey), EdDsaError>80*e1997b9aSAndroid Build Coastguard Worker     pub fn signature_key_generate(
81*e1997b9aSAndroid Build Coastguard Worker         &self,
82*e1997b9aSAndroid Build Coastguard Worker     ) -> Result<(SignatureSecretKey, SignaturePublicKey), EdDsaError> {
83*e1997b9aSAndroid Build Coastguard Worker         if self.0 != Curve::Ed25519 {
84*e1997b9aSAndroid Build Coastguard Worker             return Err(EdDsaError::UnsupportedCipherSuite);
85*e1997b9aSAndroid Build Coastguard Worker         }
86*e1997b9aSAndroid Build Coastguard Worker 
87*e1997b9aSAndroid Build Coastguard Worker         let private_key = ed25519::PrivateKey::generate();
88*e1997b9aSAndroid Build Coastguard Worker         let public_key = private_key.to_public();
89*e1997b9aSAndroid Build Coastguard Worker         Ok((private_key.to_seed().to_vec().into(), public_key.as_bytes().to_vec().into()))
90*e1997b9aSAndroid Build Coastguard Worker     }
91*e1997b9aSAndroid Build Coastguard Worker 
92*e1997b9aSAndroid Build Coastguard Worker     /// Derives the public key from the private key.
signature_key_derive_public( &self, secret_key: &SignatureSecretKey, ) -> Result<SignaturePublicKey, EdDsaError>93*e1997b9aSAndroid Build Coastguard Worker     pub fn signature_key_derive_public(
94*e1997b9aSAndroid Build Coastguard Worker         &self,
95*e1997b9aSAndroid Build Coastguard Worker         secret_key: &SignatureSecretKey,
96*e1997b9aSAndroid Build Coastguard Worker     ) -> Result<SignaturePublicKey, EdDsaError> {
97*e1997b9aSAndroid Build Coastguard Worker         if self.0 != Curve::Ed25519 {
98*e1997b9aSAndroid Build Coastguard Worker             return Err(EdDsaError::UnsupportedCipherSuite);
99*e1997b9aSAndroid Build Coastguard Worker         }
100*e1997b9aSAndroid Build Coastguard Worker         if secret_key.len() != ed25519::SEED_LEN {
101*e1997b9aSAndroid Build Coastguard Worker             return Err(EdDsaError::InvalidPrivKeyLen {
102*e1997b9aSAndroid Build Coastguard Worker                 len: secret_key.len(),
103*e1997b9aSAndroid Build Coastguard Worker                 expected_len: ed25519::SEED_LEN,
104*e1997b9aSAndroid Build Coastguard Worker             });
105*e1997b9aSAndroid Build Coastguard Worker         }
106*e1997b9aSAndroid Build Coastguard Worker 
107*e1997b9aSAndroid Build Coastguard Worker         let private_key =
108*e1997b9aSAndroid Build Coastguard Worker             ed25519::PrivateKey::from_seed(secret_key[..ed25519::SEED_LEN].try_into()?);
109*e1997b9aSAndroid Build Coastguard Worker         Ok(private_key.to_public().as_bytes().to_vec().into())
110*e1997b9aSAndroid Build Coastguard Worker     }
111*e1997b9aSAndroid Build Coastguard Worker 
112*e1997b9aSAndroid Build Coastguard Worker     /// Signs `data` using `secret_key`.
sign( &self, secret_key: &SignatureSecretKey, data: &[u8], ) -> Result<Vec<u8>, EdDsaError>113*e1997b9aSAndroid Build Coastguard Worker     pub fn sign(
114*e1997b9aSAndroid Build Coastguard Worker         &self,
115*e1997b9aSAndroid Build Coastguard Worker         secret_key: &SignatureSecretKey,
116*e1997b9aSAndroid Build Coastguard Worker         data: &[u8],
117*e1997b9aSAndroid Build Coastguard Worker     ) -> Result<Vec<u8>, EdDsaError> {
118*e1997b9aSAndroid Build Coastguard Worker         if self.0 != Curve::Ed25519 {
119*e1997b9aSAndroid Build Coastguard Worker             return Err(EdDsaError::UnsupportedCipherSuite);
120*e1997b9aSAndroid Build Coastguard Worker         }
121*e1997b9aSAndroid Build Coastguard Worker         if secret_key.len() != ed25519::SEED_LEN {
122*e1997b9aSAndroid Build Coastguard Worker             return Err(EdDsaError::InvalidPrivKeyLen {
123*e1997b9aSAndroid Build Coastguard Worker                 len: secret_key.len(),
124*e1997b9aSAndroid Build Coastguard Worker                 expected_len: ed25519::SEED_LEN,
125*e1997b9aSAndroid Build Coastguard Worker             });
126*e1997b9aSAndroid Build Coastguard Worker         }
127*e1997b9aSAndroid Build Coastguard Worker 
128*e1997b9aSAndroid Build Coastguard Worker         let private_key =
129*e1997b9aSAndroid Build Coastguard Worker             ed25519::PrivateKey::from_seed(secret_key[..ed25519::SEED_LEN].try_into()?);
130*e1997b9aSAndroid Build Coastguard Worker         Ok(private_key.sign(data).to_vec())
131*e1997b9aSAndroid Build Coastguard Worker     }
132*e1997b9aSAndroid Build Coastguard Worker 
133*e1997b9aSAndroid Build Coastguard Worker     /// Verifies `signature` is a valid signature of `data` using `public_key`.
verify( &self, public_key: &SignaturePublicKey, signature: &[u8], data: &[u8], ) -> Result<(), EdDsaError>134*e1997b9aSAndroid Build Coastguard Worker     pub fn verify(
135*e1997b9aSAndroid Build Coastguard Worker         &self,
136*e1997b9aSAndroid Build Coastguard Worker         public_key: &SignaturePublicKey,
137*e1997b9aSAndroid Build Coastguard Worker         signature: &[u8],
138*e1997b9aSAndroid Build Coastguard Worker         data: &[u8],
139*e1997b9aSAndroid Build Coastguard Worker     ) -> Result<(), EdDsaError> {
140*e1997b9aSAndroid Build Coastguard Worker         if self.0 != Curve::Ed25519 {
141*e1997b9aSAndroid Build Coastguard Worker             return Err(EdDsaError::UnsupportedCipherSuite);
142*e1997b9aSAndroid Build Coastguard Worker         }
143*e1997b9aSAndroid Build Coastguard Worker         if public_key.len() != ed25519::PUBLIC_KEY_LEN {
144*e1997b9aSAndroid Build Coastguard Worker             return Err(EdDsaError::InvalidPubKeyLen {
145*e1997b9aSAndroid Build Coastguard Worker                 len: public_key.len(),
146*e1997b9aSAndroid Build Coastguard Worker                 expected_len: ed25519::PUBLIC_KEY_LEN,
147*e1997b9aSAndroid Build Coastguard Worker             });
148*e1997b9aSAndroid Build Coastguard Worker         }
149*e1997b9aSAndroid Build Coastguard Worker         if signature.len() != ed25519::SIGNATURE_LEN {
150*e1997b9aSAndroid Build Coastguard Worker             return Err(EdDsaError::InvalidSigLen {
151*e1997b9aSAndroid Build Coastguard Worker                 len: signature.len(),
152*e1997b9aSAndroid Build Coastguard Worker                 expected_len: ed25519::SIGNATURE_LEN,
153*e1997b9aSAndroid Build Coastguard Worker             });
154*e1997b9aSAndroid Build Coastguard Worker         }
155*e1997b9aSAndroid Build Coastguard Worker 
156*e1997b9aSAndroid Build Coastguard Worker         let public_key = ed25519::PublicKey::from_bytes(
157*e1997b9aSAndroid Build Coastguard Worker             public_key.as_bytes()[..ed25519::PUBLIC_KEY_LEN].try_into()?,
158*e1997b9aSAndroid Build Coastguard Worker         );
159*e1997b9aSAndroid Build Coastguard Worker         match public_key.verify(data, signature[..ed25519::SIGNATURE_LEN].try_into()?) {
160*e1997b9aSAndroid Build Coastguard Worker             Ok(_) => Ok(()),
161*e1997b9aSAndroid Build Coastguard Worker             Err(e) => Err(EdDsaError::InvalidSig(e)),
162*e1997b9aSAndroid Build Coastguard Worker         }
163*e1997b9aSAndroid Build Coastguard Worker     }
164*e1997b9aSAndroid Build Coastguard Worker }
165*e1997b9aSAndroid Build Coastguard Worker 
166*e1997b9aSAndroid Build Coastguard Worker #[cfg(all(not(mls_build_async), test))]
167*e1997b9aSAndroid Build Coastguard Worker mod test {
168*e1997b9aSAndroid Build Coastguard Worker     use super::{EdDsa, EdDsaError};
169*e1997b9aSAndroid Build Coastguard Worker     use crate::test_helpers::decode_hex;
170*e1997b9aSAndroid Build Coastguard Worker     use assert_matches::assert_matches;
171*e1997b9aSAndroid Build Coastguard Worker     use mls_rs_core::crypto::{CipherSuite, SignaturePublicKey, SignatureSecretKey};
172*e1997b9aSAndroid Build Coastguard Worker 
173*e1997b9aSAndroid Build Coastguard Worker     #[test]
signature_key_generate()174*e1997b9aSAndroid Build Coastguard Worker     fn signature_key_generate() {
175*e1997b9aSAndroid Build Coastguard Worker         let ed25519 = EdDsa::new(CipherSuite::CURVE25519_AES128).unwrap();
176*e1997b9aSAndroid Build Coastguard Worker         assert!(ed25519.signature_key_generate().is_ok());
177*e1997b9aSAndroid Build Coastguard Worker     }
178*e1997b9aSAndroid Build Coastguard Worker 
179*e1997b9aSAndroid Build Coastguard Worker     #[test]
signature_key_derive_public()180*e1997b9aSAndroid Build Coastguard Worker     fn signature_key_derive_public() {
181*e1997b9aSAndroid Build Coastguard Worker         // Test 1 from https://www.rfc-editor.org/rfc/rfc8032#section-7.1
182*e1997b9aSAndroid Build Coastguard Worker         let private_key = SignatureSecretKey::from(
183*e1997b9aSAndroid Build Coastguard Worker             decode_hex::<32>("9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60")
184*e1997b9aSAndroid Build Coastguard Worker                 .to_vec(),
185*e1997b9aSAndroid Build Coastguard Worker         );
186*e1997b9aSAndroid Build Coastguard Worker         let expected_public_key = SignaturePublicKey::from(
187*e1997b9aSAndroid Build Coastguard Worker             decode_hex::<32>("d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a")
188*e1997b9aSAndroid Build Coastguard Worker                 .to_vec(),
189*e1997b9aSAndroid Build Coastguard Worker         );
190*e1997b9aSAndroid Build Coastguard Worker 
191*e1997b9aSAndroid Build Coastguard Worker         let ed25519 = EdDsa::new(CipherSuite::CURVE25519_CHACHA).unwrap();
192*e1997b9aSAndroid Build Coastguard Worker         assert_eq!(ed25519.signature_key_derive_public(&private_key).unwrap(), expected_public_key);
193*e1997b9aSAndroid Build Coastguard Worker     }
194*e1997b9aSAndroid Build Coastguard Worker 
195*e1997b9aSAndroid Build Coastguard Worker     #[test]
signature_key_derive_public_invalid_key()196*e1997b9aSAndroid Build Coastguard Worker     fn signature_key_derive_public_invalid_key() {
197*e1997b9aSAndroid Build Coastguard Worker         let private_key_short =
198*e1997b9aSAndroid Build Coastguard Worker             SignatureSecretKey::from(decode_hex::<16>("9d61b19deffd5a60ba844af492ec2cc4").to_vec());
199*e1997b9aSAndroid Build Coastguard Worker 
200*e1997b9aSAndroid Build Coastguard Worker         let ed25519 = EdDsa::new(CipherSuite::CURVE25519_CHACHA).unwrap();
201*e1997b9aSAndroid Build Coastguard Worker         assert_matches!(
202*e1997b9aSAndroid Build Coastguard Worker             ed25519.signature_key_derive_public(&private_key_short),
203*e1997b9aSAndroid Build Coastguard Worker             Err(EdDsaError::InvalidPrivKeyLen { .. })
204*e1997b9aSAndroid Build Coastguard Worker         );
205*e1997b9aSAndroid Build Coastguard Worker     }
206*e1997b9aSAndroid Build Coastguard Worker 
207*e1997b9aSAndroid Build Coastguard Worker     #[test]
sign_verify()208*e1997b9aSAndroid Build Coastguard Worker     fn sign_verify() {
209*e1997b9aSAndroid Build Coastguard Worker         // Test 3 from https://www.rfc-editor.org/rfc/rfc8032#section-7.1
210*e1997b9aSAndroid Build Coastguard Worker         let private_key = SignatureSecretKey::from(
211*e1997b9aSAndroid Build Coastguard Worker             decode_hex::<32>("c5aa8df43f9f837bedb7442f31dcb7b166d38535076f094b85ce3a2e0b4458f7")
212*e1997b9aSAndroid Build Coastguard Worker                 .to_vec(),
213*e1997b9aSAndroid Build Coastguard Worker         );
214*e1997b9aSAndroid Build Coastguard Worker         let data: [u8; 2] = decode_hex("af82");
215*e1997b9aSAndroid Build Coastguard Worker         let expected_sig = decode_hex::<64>("6291d657deec24024827e69c3abe01a30ce548a284743a445e3680d7db5ac3ac18ff9b538d16f290ae67f760984dc6594a7c15e9716ed28dc027beceea1ec40a").to_vec();
216*e1997b9aSAndroid Build Coastguard Worker 
217*e1997b9aSAndroid Build Coastguard Worker         let ed25519 = EdDsa::new(CipherSuite::CURVE25519_AES128).unwrap();
218*e1997b9aSAndroid Build Coastguard Worker         let sig = ed25519.sign(&private_key, &data).unwrap();
219*e1997b9aSAndroid Build Coastguard Worker         assert_eq!(sig, expected_sig);
220*e1997b9aSAndroid Build Coastguard Worker 
221*e1997b9aSAndroid Build Coastguard Worker         let public_key = ed25519.signature_key_derive_public(&private_key).unwrap();
222*e1997b9aSAndroid Build Coastguard Worker         assert!(ed25519.verify(&public_key, &sig, &data).is_ok());
223*e1997b9aSAndroid Build Coastguard Worker     }
224*e1997b9aSAndroid Build Coastguard Worker 
225*e1997b9aSAndroid Build Coastguard Worker     #[test]
sign_invalid_key()226*e1997b9aSAndroid Build Coastguard Worker     fn sign_invalid_key() {
227*e1997b9aSAndroid Build Coastguard Worker         let private_key_short =
228*e1997b9aSAndroid Build Coastguard Worker             SignatureSecretKey::from(decode_hex::<16>("c5aa8df43f9f837bedb7442f31dcb7b1").to_vec());
229*e1997b9aSAndroid Build Coastguard Worker 
230*e1997b9aSAndroid Build Coastguard Worker         let ed25519 = EdDsa::new(CipherSuite::CURVE25519_AES128).unwrap();
231*e1997b9aSAndroid Build Coastguard Worker         assert_matches!(
232*e1997b9aSAndroid Build Coastguard Worker             ed25519.sign(&private_key_short, &decode_hex::<2>("af82")),
233*e1997b9aSAndroid Build Coastguard Worker             Err(EdDsaError::InvalidPrivKeyLen { .. })
234*e1997b9aSAndroid Build Coastguard Worker         );
235*e1997b9aSAndroid Build Coastguard Worker     }
236*e1997b9aSAndroid Build Coastguard Worker 
237*e1997b9aSAndroid Build Coastguard Worker     #[test]
verify_invalid_key()238*e1997b9aSAndroid Build Coastguard Worker     fn verify_invalid_key() {
239*e1997b9aSAndroid Build Coastguard Worker         let public_key_short =
240*e1997b9aSAndroid Build Coastguard Worker             SignaturePublicKey::from(decode_hex::<16>("fc51cd8e6218a1a38da47ed00230f058").to_vec());
241*e1997b9aSAndroid Build Coastguard Worker         let sig = decode_hex::<64>("6291d657deec24024827e69c3abe01a30ce548a284743a445e3680d7db5ac3ac18ff9b538d16f290ae67f760984dc6594a7c15e9716ed28dc027beceea1ec40a").to_vec();
242*e1997b9aSAndroid Build Coastguard Worker         let data: [u8; 2] = decode_hex("af82");
243*e1997b9aSAndroid Build Coastguard Worker 
244*e1997b9aSAndroid Build Coastguard Worker         let ed25519 = EdDsa::new(CipherSuite::CURVE25519_AES128).unwrap();
245*e1997b9aSAndroid Build Coastguard Worker         assert_matches!(
246*e1997b9aSAndroid Build Coastguard Worker             ed25519.verify(&public_key_short, &sig, &data),
247*e1997b9aSAndroid Build Coastguard Worker             Err(EdDsaError::InvalidPubKeyLen { .. })
248*e1997b9aSAndroid Build Coastguard Worker         );
249*e1997b9aSAndroid Build Coastguard Worker     }
250*e1997b9aSAndroid Build Coastguard Worker 
251*e1997b9aSAndroid Build Coastguard Worker     #[test]
verify_invalid_sig()252*e1997b9aSAndroid Build Coastguard Worker     fn verify_invalid_sig() {
253*e1997b9aSAndroid Build Coastguard Worker         let public_key = SignaturePublicKey::from(
254*e1997b9aSAndroid Build Coastguard Worker             decode_hex::<32>("fc51cd8e6218a1a38da47ed00230f0580816ed13ba3303ac5deb911548908025")
255*e1997b9aSAndroid Build Coastguard Worker                 .to_vec(),
256*e1997b9aSAndroid Build Coastguard Worker         );
257*e1997b9aSAndroid Build Coastguard Worker         let sig_short =
258*e1997b9aSAndroid Build Coastguard Worker             decode_hex::<32>("6291d657deec24024827e69c3abe01a30ce548a284743a445e3680d7db5ac3ac")
259*e1997b9aSAndroid Build Coastguard Worker                 .to_vec();
260*e1997b9aSAndroid Build Coastguard Worker         let data: [u8; 2] = decode_hex("af82");
261*e1997b9aSAndroid Build Coastguard Worker 
262*e1997b9aSAndroid Build Coastguard Worker         let ed25519 = EdDsa::new(CipherSuite::CURVE25519_AES128).unwrap();
263*e1997b9aSAndroid Build Coastguard Worker         assert_matches!(
264*e1997b9aSAndroid Build Coastguard Worker             ed25519.verify(&public_key, &sig_short, &data),
265*e1997b9aSAndroid Build Coastguard Worker             Err(EdDsaError::InvalidSigLen { .. })
266*e1997b9aSAndroid Build Coastguard Worker         );
267*e1997b9aSAndroid Build Coastguard Worker     }
268*e1997b9aSAndroid Build Coastguard Worker 
269*e1997b9aSAndroid Build Coastguard Worker     #[test]
unsupported_cipher_suites()270*e1997b9aSAndroid Build Coastguard Worker     fn unsupported_cipher_suites() {
271*e1997b9aSAndroid Build Coastguard Worker         for suite in vec![
272*e1997b9aSAndroid Build Coastguard Worker             CipherSuite::P256_AES128,
273*e1997b9aSAndroid Build Coastguard Worker             CipherSuite::P384_AES256,
274*e1997b9aSAndroid Build Coastguard Worker             CipherSuite::P521_AES256,
275*e1997b9aSAndroid Build Coastguard Worker             CipherSuite::CURVE448_CHACHA,
276*e1997b9aSAndroid Build Coastguard Worker             CipherSuite::CURVE448_AES256,
277*e1997b9aSAndroid Build Coastguard Worker         ] {
278*e1997b9aSAndroid Build Coastguard Worker             assert_matches!(
279*e1997b9aSAndroid Build Coastguard Worker                 EdDsa::new(suite).unwrap().signature_key_generate(),
280*e1997b9aSAndroid Build Coastguard Worker                 Err(EdDsaError::UnsupportedCipherSuite)
281*e1997b9aSAndroid Build Coastguard Worker             );
282*e1997b9aSAndroid Build Coastguard Worker         }
283*e1997b9aSAndroid Build Coastguard Worker     }
284*e1997b9aSAndroid Build Coastguard Worker }
285