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`]. 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`]. 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")] 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")] 101 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 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 { 154 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 { 176 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 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 { 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 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 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 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 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 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 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 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 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 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] 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