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#[derive(Clone, PartialEq, Debug)]
31pub struct Certificate {
32 pub certificate: Vec<CertificateDer<'static>>,
34 pub private_key: CryptoPrivateKey,
36}
37
38impl Certificate {
39 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 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 #[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 #[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; 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#[derive(Debug)]
144pub enum CryptoPrivateKeyKind {
145 Ed25519(Ed25519KeyPair),
146 Ecdsa256(EcdsaKeyPair),
147 Rsa256(ring::rsa::KeyPair),
148}
149
150#[derive(Debug)]
152pub struct CryptoPrivateKey {
153 pub kind: CryptoPrivateKeyKind,
155 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
256pub(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, ) -> 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
296pub 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
379pub(crate) fn generate_certificate_verify(
388 handshake_bodies: &[u8],
389 private_key: &CryptoPrivateKey, ) -> 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 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}