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