webrtc_dtls/crypto/
mod.rs

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