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#[derive(Clone, PartialEq, Debug)]
30pub struct Certificate {
31 pub certificate: Vec<CertificateDer<'static>>,
33 pub private_key: CryptoPrivateKey,
35}
36
37impl Certificate {
38 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 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 #[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 #[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; 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#[derive(Debug)]
143pub enum CryptoPrivateKeyKind {
144 Ed25519(Ed25519KeyPair),
145 Ecdsa256(EcdsaKeyPair),
146 Rsa256(ring::rsa::KeyPair),
147}
148
149#[derive(Debug)]
151pub struct CryptoPrivateKey {
152 pub kind: CryptoPrivateKeyKind,
154 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
255pub(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, ) -> 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
295pub 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
378pub(crate) fn generate_certificate_verify(
387 handshake_bodies: &[u8],
388 private_key: &CryptoPrivateKey, ) -> 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 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}