rtc_dtls/crypto/
mod.rs

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