xref: /webrtc/dtls/src/crypto/mod.rs (revision 7ceeeeb0)
1 #[cfg(test)]
2 mod crypto_test;
3 
4 pub mod crypto_cbc;
5 pub mod crypto_ccm;
6 pub mod crypto_gcm;
7 pub mod padding;
8 
9 use crate::curve::named_curve::*;
10 use crate::error::*;
11 use crate::record_layer::record_layer_header::*;
12 use crate::signature_hash_algorithm::{HashAlgorithm, SignatureAlgorithm, SignatureHashAlgorithm};
13 
14 use der_parser::{oid, oid::Oid};
15 use rcgen::KeyPair;
16 use ring::rand::SystemRandom;
17 use ring::signature::{EcdsaKeyPair, Ed25519KeyPair, RsaKeyPair};
18 use std::sync::Arc;
19 
20 #[derive(Clone, PartialEq)]
21 pub struct Certificate {
22     pub certificate: Vec<rustls::Certificate>,
23     pub private_key: CryptoPrivateKey,
24 }
25 
26 impl Certificate {
27     pub fn generate_self_signed(subject_alt_names: impl Into<Vec<String>>) -> Result<Self> {
28         let cert = rcgen::generate_simple_self_signed(subject_alt_names)?;
29         let certificate = cert.serialize_der()?;
30         let key_pair = cert.get_key_pair();
31         let serialized_der = key_pair.serialize_der();
32         let private_key = if key_pair.is_compatible(&rcgen::PKCS_ED25519) {
33             CryptoPrivateKey {
34                 kind: CryptoPrivateKeyKind::Ed25519(
35                     Ed25519KeyPair::from_pkcs8(&serialized_der)
36                         .map_err(|e| Error::Other(e.to_string()))?,
37                 ),
38                 serialized_der,
39             }
40         } else if key_pair.is_compatible(&rcgen::PKCS_ECDSA_P256_SHA256) {
41             CryptoPrivateKey {
42                 kind: CryptoPrivateKeyKind::Ecdsa256(
43                     EcdsaKeyPair::from_pkcs8(
44                         &ring::signature::ECDSA_P256_SHA256_ASN1_SIGNING,
45                         &serialized_der,
46                     )
47                     .map_err(|e| Error::Other(e.to_string()))?,
48                 ),
49                 serialized_der,
50             }
51         } else if key_pair.is_compatible(&rcgen::PKCS_RSA_SHA256) {
52             CryptoPrivateKey {
53                 kind: CryptoPrivateKeyKind::Rsa256(
54                     RsaKeyPair::from_pkcs8(&serialized_der)
55                         .map_err(|e| Error::Other(e.to_string()))?,
56                 ),
57                 serialized_der,
58             }
59         } else {
60             return Err(Error::Other("Unsupported key_pair".to_owned()));
61         };
62 
63         Ok(Certificate {
64             certificate: vec![rustls::Certificate(certificate)],
65             private_key,
66         })
67     }
68 
69     pub fn generate_self_signed_with_alg(
70         subject_alt_names: impl Into<Vec<String>>,
71         alg: &'static rcgen::SignatureAlgorithm,
72     ) -> Result<Self> {
73         let mut params = rcgen::CertificateParams::new(subject_alt_names);
74         params.alg = alg;
75         let cert = rcgen::Certificate::from_params(params)?;
76         let certificate = cert.serialize_der()?;
77         let key_pair = cert.get_key_pair();
78         let serialized_der = key_pair.serialize_der();
79         let private_key = if key_pair.is_compatible(&rcgen::PKCS_ED25519) {
80             CryptoPrivateKey {
81                 kind: CryptoPrivateKeyKind::Ed25519(
82                     Ed25519KeyPair::from_pkcs8(&serialized_der)
83                         .map_err(|e| Error::Other(e.to_string()))?,
84                 ),
85                 serialized_der,
86             }
87         } else if key_pair.is_compatible(&rcgen::PKCS_ECDSA_P256_SHA256) {
88             CryptoPrivateKey {
89                 kind: CryptoPrivateKeyKind::Ecdsa256(
90                     EcdsaKeyPair::from_pkcs8(
91                         &ring::signature::ECDSA_P256_SHA256_ASN1_SIGNING,
92                         &serialized_der,
93                     )
94                     .map_err(|e| Error::Other(e.to_string()))?,
95                 ),
96                 serialized_der,
97             }
98         } else if key_pair.is_compatible(&rcgen::PKCS_RSA_SHA256) {
99             CryptoPrivateKey {
100                 kind: CryptoPrivateKeyKind::Rsa256(
101                     RsaKeyPair::from_pkcs8(&serialized_der)
102                         .map_err(|e| Error::Other(e.to_string()))?,
103                 ),
104                 serialized_der,
105             }
106         } else {
107             return Err(Error::Other("Unsupported key_pair".to_owned()));
108         };
109 
110         Ok(Certificate {
111             certificate: vec![rustls::Certificate(certificate)],
112             private_key,
113         })
114     }
115 }
116 
117 pub(crate) fn value_key_message(
118     client_random: &[u8],
119     server_random: &[u8],
120     public_key: &[u8],
121     named_curve: NamedCurve,
122 ) -> Vec<u8> {
123     let mut server_ecdh_params = vec![0u8; 4];
124     server_ecdh_params[0] = 3; // named curve
125     server_ecdh_params[1..3].copy_from_slice(&(named_curve as u16).to_be_bytes());
126     server_ecdh_params[3] = public_key.len() as u8;
127 
128     let mut plaintext = vec![];
129     plaintext.extend_from_slice(client_random);
130     plaintext.extend_from_slice(server_random);
131     plaintext.extend_from_slice(&server_ecdh_params);
132     plaintext.extend_from_slice(public_key);
133 
134     plaintext
135 }
136 
137 pub enum CryptoPrivateKeyKind {
138     Ed25519(Ed25519KeyPair),
139     Ecdsa256(EcdsaKeyPair),
140     Rsa256(RsaKeyPair),
141 }
142 
143 pub struct CryptoPrivateKey {
144     pub kind: CryptoPrivateKeyKind,
145     pub serialized_der: Vec<u8>,
146 }
147 
148 impl PartialEq for CryptoPrivateKey {
149     fn eq(&self, other: &Self) -> bool {
150         if self.serialized_der != other.serialized_der {
151             return false;
152         }
153 
154         matches!(
155             (&self.kind, &other.kind),
156             (
157                 CryptoPrivateKeyKind::Rsa256(_),
158                 CryptoPrivateKeyKind::Rsa256(_)
159             ) | (
160                 CryptoPrivateKeyKind::Ecdsa256(_),
161                 CryptoPrivateKeyKind::Ecdsa256(_)
162             ) | (
163                 CryptoPrivateKeyKind::Ed25519(_),
164                 CryptoPrivateKeyKind::Ed25519(_)
165             )
166         )
167     }
168 }
169 
170 impl Clone for CryptoPrivateKey {
171     fn clone(&self) -> Self {
172         match self.kind {
173             CryptoPrivateKeyKind::Ed25519(_) => CryptoPrivateKey {
174                 kind: CryptoPrivateKeyKind::Ed25519(
175                     Ed25519KeyPair::from_pkcs8(&self.serialized_der).unwrap(),
176                 ),
177                 serialized_der: self.serialized_der.clone(),
178             },
179             CryptoPrivateKeyKind::Ecdsa256(_) => CryptoPrivateKey {
180                 kind: CryptoPrivateKeyKind::Ecdsa256(
181                     EcdsaKeyPair::from_pkcs8(
182                         &ring::signature::ECDSA_P256_SHA256_ASN1_SIGNING,
183                         &self.serialized_der,
184                     )
185                     .unwrap(),
186                 ),
187                 serialized_der: self.serialized_der.clone(),
188             },
189             CryptoPrivateKeyKind::Rsa256(_) => CryptoPrivateKey {
190                 kind: CryptoPrivateKeyKind::Rsa256(
191                     RsaKeyPair::from_pkcs8(&self.serialized_der).unwrap(),
192                 ),
193                 serialized_der: self.serialized_der.clone(),
194             },
195         }
196     }
197 }
198 
199 impl CryptoPrivateKey {
200     pub fn from_key_pair(key_pair: &KeyPair) -> Result<Self> {
201         let serialized_der = key_pair.serialize_der();
202         if key_pair.is_compatible(&rcgen::PKCS_ED25519) {
203             Ok(CryptoPrivateKey {
204                 kind: CryptoPrivateKeyKind::Ed25519(
205                     Ed25519KeyPair::from_pkcs8(&serialized_der)
206                         .map_err(|e| Error::Other(e.to_string()))?,
207                 ),
208                 serialized_der,
209             })
210         } else if key_pair.is_compatible(&rcgen::PKCS_ECDSA_P256_SHA256) {
211             Ok(CryptoPrivateKey {
212                 kind: CryptoPrivateKeyKind::Ecdsa256(
213                     EcdsaKeyPair::from_pkcs8(
214                         &ring::signature::ECDSA_P256_SHA256_ASN1_SIGNING,
215                         &serialized_der,
216                     )
217                     .map_err(|e| Error::Other(e.to_string()))?,
218                 ),
219                 serialized_der,
220             })
221         } else if key_pair.is_compatible(&rcgen::PKCS_RSA_SHA256) {
222             Ok(CryptoPrivateKey {
223                 kind: CryptoPrivateKeyKind::Rsa256(
224                     RsaKeyPair::from_pkcs8(&serialized_der)
225                         .map_err(|e| Error::Other(e.to_string()))?,
226                 ),
227                 serialized_der,
228             })
229         } else {
230             Err(Error::Other("Unsupported key_pair".to_owned()))
231         }
232     }
233 }
234 
235 // If the client provided a "signature_algorithms" extension, then all
236 // certificates provided by the server MUST be signed by a
237 // hash/signature algorithm pair that appears in that extension
238 //
239 // https://tools.ietf.org/html/rfc5246#section-7.4.2
240 pub(crate) fn generate_key_signature(
241     client_random: &[u8],
242     server_random: &[u8],
243     public_key: &[u8],
244     named_curve: NamedCurve,
245     private_key: &CryptoPrivateKey, /*, hash_algorithm: HashAlgorithm*/
246 ) -> Result<Vec<u8>> {
247     let msg = value_key_message(client_random, server_random, public_key, named_curve);
248     let signature = match &private_key.kind {
249         CryptoPrivateKeyKind::Ed25519(kp) => kp.sign(&msg).as_ref().to_vec(),
250         CryptoPrivateKeyKind::Ecdsa256(kp) => {
251             let system_random = SystemRandom::new();
252             kp.sign(&system_random, &msg)
253                 .map_err(|e| Error::Other(e.to_string()))?
254                 .as_ref()
255                 .to_vec()
256         }
257         CryptoPrivateKeyKind::Rsa256(kp) => {
258             let system_random = SystemRandom::new();
259             let mut signature = vec![0; kp.public_modulus_len()];
260             kp.sign(
261                 &ring::signature::RSA_PKCS1_SHA256,
262                 &system_random,
263                 &msg,
264                 &mut signature,
265             )
266             .map_err(|e| Error::Other(e.to_string()))?;
267 
268             signature
269         }
270     };
271 
272     Ok(signature)
273 }
274 
275 // add OID_ED25519 which is not defined in x509_parser
276 pub const OID_ED25519: Oid<'static> = oid!(1.3.101 .112);
277 pub const OID_ECDSA: Oid<'static> = oid!(1.2.840 .10045 .2 .1);
278 
279 fn verify_signature(
280     message: &[u8],
281     hash_algorithm: &SignatureHashAlgorithm,
282     remote_key_signature: &[u8],
283     raw_certificates: &[Vec<u8>],
284 ) -> Result<()> {
285     if raw_certificates.is_empty() {
286         return Err(Error::ErrLengthMismatch);
287     }
288 
289     let (_, certificate) = x509_parser::parse_x509_certificate(&raw_certificates[0])
290         .map_err(|e| Error::Other(e.to_string()))?;
291 
292     let verify_alg: &dyn ring::signature::VerificationAlgorithm = match hash_algorithm.signature {
293         SignatureAlgorithm::Ed25519 => &ring::signature::ED25519,
294         SignatureAlgorithm::Ecdsa if hash_algorithm.hash == HashAlgorithm::Sha256 => {
295             &ring::signature::ECDSA_P256_SHA256_ASN1
296         }
297         SignatureAlgorithm::Ecdsa if hash_algorithm.hash == HashAlgorithm::Sha384 => {
298             &ring::signature::ECDSA_P384_SHA384_ASN1
299         }
300         SignatureAlgorithm::Rsa if hash_algorithm.hash == HashAlgorithm::Sha1 => {
301             &ring::signature::RSA_PKCS1_1024_8192_SHA1_FOR_LEGACY_USE_ONLY
302         }
303         SignatureAlgorithm::Rsa if hash_algorithm.hash == HashAlgorithm::Sha256 => {
304             &ring::signature::RSA_PKCS1_2048_8192_SHA256
305         }
306         SignatureAlgorithm::Rsa if hash_algorithm.hash == HashAlgorithm::Sha384 => {
307             &ring::signature::RSA_PKCS1_2048_8192_SHA384
308         }
309         SignatureAlgorithm::Rsa if hash_algorithm.hash == HashAlgorithm::Sha512 => {
310             &ring::signature::RSA_PKCS1_2048_8192_SHA512
311         }
312         _ => return Err(Error::ErrKeySignatureVerifyUnimplemented),
313     };
314 
315     log::trace!("Picked an algorithm {:?}", verify_alg);
316 
317     let public_key = ring::signature::UnparsedPublicKey::new(
318         verify_alg,
319         certificate
320             .tbs_certificate
321             .subject_pki
322             .subject_public_key
323             .data,
324     );
325 
326     public_key
327         .verify(message, remote_key_signature)
328         .map_err(|e| Error::Other(e.to_string()))?;
329 
330     Ok(())
331 }
332 
333 pub(crate) fn verify_key_signature(
334     message: &[u8],
335     hash_algorithm: &SignatureHashAlgorithm,
336     remote_key_signature: &[u8],
337     raw_certificates: &[Vec<u8>],
338 ) -> Result<()> {
339     verify_signature(
340         message,
341         hash_algorithm,
342         remote_key_signature,
343         raw_certificates,
344     )
345 }
346 
347 // If the server has sent a CertificateRequest message, the client MUST send the Certificate
348 // message.  The ClientKeyExchange message is now sent, and the content
349 // of that message will depend on the public key algorithm selected
350 // between the ClientHello and the ServerHello.  If the client has sent
351 // a certificate with signing ability, a digitally-signed
352 // CertificateVerify message is sent to explicitly verify possession of
353 // the private key in the certificate.
354 // https://tools.ietf.org/html/rfc5246#section-7.3
355 pub(crate) fn generate_certificate_verify(
356     handshake_bodies: &[u8],
357     private_key: &CryptoPrivateKey, /*, hashAlgorithm hashAlgorithm*/
358 ) -> Result<Vec<u8>> {
359     let signature = match &private_key.kind {
360         CryptoPrivateKeyKind::Ed25519(kp) => kp.sign(handshake_bodies).as_ref().to_vec(),
361         CryptoPrivateKeyKind::Ecdsa256(kp) => {
362             let system_random = SystemRandom::new();
363             kp.sign(&system_random, handshake_bodies)
364                 .map_err(|e| Error::Other(e.to_string()))?
365                 .as_ref()
366                 .to_vec()
367         }
368         CryptoPrivateKeyKind::Rsa256(kp) => {
369             let system_random = SystemRandom::new();
370             let mut signature = vec![0; kp.public_modulus_len()];
371             kp.sign(
372                 &ring::signature::RSA_PKCS1_SHA256,
373                 &system_random,
374                 handshake_bodies,
375                 &mut signature,
376             )
377             .map_err(|e| Error::Other(e.to_string()))?;
378 
379             signature
380         }
381     };
382 
383     Ok(signature)
384 }
385 
386 pub(crate) fn verify_certificate_verify(
387     handshake_bodies: &[u8],
388     hash_algorithm: &SignatureHashAlgorithm,
389     remote_key_signature: &[u8],
390     raw_certificates: &[Vec<u8>],
391 ) -> Result<()> {
392     verify_signature(
393         handshake_bodies,
394         hash_algorithm,
395         remote_key_signature,
396         raw_certificates,
397     )
398 }
399 
400 pub(crate) fn load_certs(raw_certificates: &[Vec<u8>]) -> Result<Vec<rustls::Certificate>> {
401     if raw_certificates.is_empty() {
402         return Err(Error::ErrLengthMismatch);
403     }
404 
405     let mut certs = vec![];
406     for raw_cert in raw_certificates {
407         let cert = rustls::Certificate(raw_cert.to_vec());
408         certs.push(cert);
409     }
410 
411     Ok(certs)
412 }
413 
414 pub(crate) fn verify_client_cert(
415     raw_certificates: &[Vec<u8>],
416     cert_verifier: &Arc<dyn rustls::ClientCertVerifier>,
417 ) -> Result<Vec<rustls::Certificate>> {
418     let chains = load_certs(raw_certificates)?;
419 
420     match cert_verifier.verify_client_cert(&chains, None) {
421         Ok(_) => {}
422         Err(err) => return Err(Error::Other(err.to_string())),
423     };
424 
425     Ok(chains)
426 }
427 
428 pub(crate) fn verify_server_cert(
429     raw_certificates: &[Vec<u8>],
430     cert_verifier: &Arc<dyn rustls::ServerCertVerifier>,
431     roots: &rustls::RootCertStore,
432     server_name: &str,
433 ) -> Result<Vec<rustls::Certificate>> {
434     let chains = load_certs(raw_certificates)?;
435     let dns_name = match webpki::DNSNameRef::try_from_ascii_str(server_name) {
436         Ok(dns_name) => dns_name,
437         Err(err) => return Err(Error::Other(err.to_string())),
438     };
439 
440     match cert_verifier.verify_server_cert(roots, &chains, dns_name, &[]) {
441         Ok(_) => {}
442         Err(err) => return Err(Error::Other(err.to_string())),
443     };
444 
445     Ok(chains)
446 }
447 
448 pub(crate) fn generate_aead_additional_data(h: &RecordLayerHeader, payload_len: usize) -> Vec<u8> {
449     let mut additional_data = vec![0u8; 13];
450     // SequenceNumber MUST be set first
451     // we only want uint48, clobbering an extra 2 (using uint64, rust doesn't have uint48)
452     additional_data[..8].copy_from_slice(&h.sequence_number.to_be_bytes());
453     additional_data[..2].copy_from_slice(&h.epoch.to_be_bytes());
454     additional_data[8] = h.content_type as u8;
455     additional_data[9] = h.protocol_version.major;
456     additional_data[10] = h.protocol_version.minor;
457     additional_data[11..].copy_from_slice(&(payload_len as u16).to_be_bytes());
458 
459     additional_data
460 }
461