1use crate::common;
2use crate::common::check_tag_len;
3use crate::{
4 ActiveKeyExchange, AeadAlgorithm, AeadCipher, BlockCipherAlgorithm, CbcAlgorithm, CbcCipher,
5 CryptoAlgorithm, CryptoError, HashAlgorithm, HmacAlgorithm, KeyExchangeAlgorithm, Mac,
6 PublicKey, PublicKeyEncoding, RTCCrypto, RTCCryptoProvider, RTCRandom, SecretVec,
7 SignatureScheme, SigningKey, StreamCipher, StreamCipherAlgorithm, constant_time_eq,
8};
9use ::hmac::Mac as RustCryptoMac;
10use ring::aead;
11use ring::agreement;
12use ring::digest;
13use ring::hmac;
14use ring::rand::SystemRandom;
15use ring::signature::{self, KeyPair};
16use sha1::Sha1;
17use std::sync::Arc;
18
19#[derive(Default)]
21pub struct RingProvider {
22 crypto: RingCrypto,
23 random: RingRandom,
24}
25
26impl RingProvider {
27 #[must_use]
29 pub const fn new() -> Self {
30 Self {
31 crypto: RingCrypto,
32 random: RingRandom,
33 }
34 }
35}
36
37impl RTCCryptoProvider for RingProvider {
38 fn name(&self) -> &'static str {
39 "ring"
40 }
41
42 fn crypto(&self) -> &dyn RTCCrypto {
43 &self.crypto
44 }
45
46 fn random(&self) -> &dyn RTCRandom {
47 &self.random
48 }
49}
50
51#[derive(Default)]
54pub struct RingCrypto;
55
56#[derive(Default)]
58pub struct RingRandom;
59
60impl RTCRandom for RingRandom {
61 fn fill(&self, output: &mut [u8]) -> Result<(), CryptoError> {
62 common::fill_random(output)
63 }
64}
65
66impl RTCCrypto for RingCrypto {
67 fn supports(&self, algorithm: CryptoAlgorithm) -> bool {
68 matches!(
69 algorithm,
70 CryptoAlgorithm::Hash(HashAlgorithm::Md5 | HashAlgorithm::Sha256)
71 | CryptoAlgorithm::Hmac(HmacAlgorithm::Sha1 | HmacAlgorithm::Sha256)
72 | CryptoAlgorithm::Aead(
73 AeadAlgorithm::Aes128Gcm
74 | AeadAlgorithm::Aes256Gcm
75 | AeadAlgorithm::Aes128Ccm
76 | AeadAlgorithm::Aes128Ccm8
77 | AeadAlgorithm::ChaCha20Poly1305,
78 )
79 | CryptoAlgorithm::StreamCipher(
80 StreamCipherAlgorithm::Aes128Ctr | StreamCipherAlgorithm::Aes256Ctr,
81 )
82 | CryptoAlgorithm::BlockCipher(
83 BlockCipherAlgorithm::Aes128 | BlockCipherAlgorithm::Aes256,
84 )
85 | CryptoAlgorithm::Cbc(CbcAlgorithm::Aes256Cbc)
86 | CryptoAlgorithm::KeyExchange(
87 KeyExchangeAlgorithm::P256
88 | KeyExchangeAlgorithm::P384
89 | KeyExchangeAlgorithm::X25519,
90 )
91 | CryptoAlgorithm::Signature(
92 SignatureScheme::Ed25519
93 | SignatureScheme::EcdsaP256Sha256
94 | SignatureScheme::EcdsaP384Sha384
95 | SignatureScheme::RsaPkcs1Sha1
96 | SignatureScheme::RsaPkcs1Sha256
97 | SignatureScheme::RsaPkcs1Sha384
98 | SignatureScheme::RsaPkcs1Sha512,
99 )
100 | CryptoAlgorithm::SigningKeyGeneration(
101 SignatureScheme::Ed25519 | SignatureScheme::EcdsaP256Sha256,
102 )
103 | CryptoAlgorithm::SigningKeyImport(
104 SignatureScheme::Ed25519
105 | SignatureScheme::EcdsaP256Sha256
106 | SignatureScheme::RsaPkcs1Sha256,
107 )
108 )
109 }
110
111 fn hash(&self, algorithm: HashAlgorithm, data: &[u8]) -> Result<Vec<u8>, CryptoError> {
112 match algorithm {
113 HashAlgorithm::Md5 => Ok(common::md5(data)),
114 HashAlgorithm::Sha256 => Ok(digest::digest(&digest::SHA256, data).as_ref().to_vec()),
115 }
116 }
117
118 fn new_hmac(&self, algorithm: HmacAlgorithm, key: &[u8]) -> Result<Box<dyn Mac>, CryptoError> {
119 match algorithm {
120 HmacAlgorithm::Sha1 => Ok(Box::new(RustCryptoHmacSha1::new(key))),
124 HmacAlgorithm::Sha256 => Ok(Box::new(RingHmac {
125 key: hmac::Key::new(hmac_algorithm(algorithm), key),
126 output_len: algorithm.output_len(),
127 })),
128 }
129 }
130
131 fn block_encrypt(
132 &self,
133 algorithm: BlockCipherAlgorithm,
134 key: &[u8],
135 block: &mut [u8],
136 ) -> Result<(), CryptoError> {
137 common::block_encrypt(algorithm, key, block)
138 }
139
140 fn new_stream_cipher(
141 &self,
142 algorithm: StreamCipherAlgorithm,
143 key: &[u8],
144 ) -> Result<Box<dyn StreamCipher>, CryptoError> {
145 common::new_stream_cipher(algorithm, key)
146 }
147
148 fn new_aead(
149 &self,
150 algorithm: AeadAlgorithm,
151 key: &[u8],
152 ) -> Result<Box<dyn AeadCipher>, CryptoError> {
153 match algorithm {
154 AeadAlgorithm::Aes128Ccm | AeadAlgorithm::Aes128Ccm8 => common::new_ccm(algorithm, key),
155 AeadAlgorithm::Aes128Gcm => RingAead::create(&aead::AES_128_GCM, key),
156 AeadAlgorithm::Aes256Gcm => RingAead::create(&aead::AES_256_GCM, key),
157 AeadAlgorithm::ChaCha20Poly1305 => RingAead::create(&aead::CHACHA20_POLY1305, key),
158 }
159 }
160
161 fn new_cbc(
162 &self,
163 algorithm: CbcAlgorithm,
164 key: &[u8],
165 ) -> Result<Box<dyn CbcCipher>, CryptoError> {
166 common::new_cbc(algorithm, key)
167 }
168
169 fn start_key_exchange(
170 &self,
171 algorithm: KeyExchangeAlgorithm,
172 ) -> Result<Box<dyn ActiveKeyExchange>, CryptoError> {
173 RingKeyExchange::start(algorithm)
174 }
175
176 fn generate_signing_key(
177 &self,
178 scheme: SignatureScheme,
179 ) -> Result<Arc<dyn SigningKey>, CryptoError> {
180 RingSigningKey::generate(scheme)
181 }
182
183 fn import_signing_key(
184 &self,
185 scheme: SignatureScheme,
186 pkcs8_der: &[u8],
187 ) -> Result<Arc<dyn SigningKey>, CryptoError> {
188 RingSigningKey::import(scheme, pkcs8_der)
189 }
190
191 fn verify_signature(
192 &self,
193 scheme: SignatureScheme,
194 public_key: PublicKey<'_>,
195 message: &[u8],
196 signature: &[u8],
197 ) -> Result<(), CryptoError> {
198 verify_public_key_encoding(scheme, public_key.encoding)?;
199 signature::UnparsedPublicKey::new(verification_algorithm(scheme), public_key.bytes)
200 .verify(message, signature)
201 .map_err(|_| CryptoError::InvalidSignature)
202 }
203}
204
205struct RingHmac {
210 key: hmac::Key,
211 output_len: usize,
212}
213
214impl Mac for RingHmac {
215 fn output_len(&self) -> usize {
216 self.output_len
217 }
218
219 fn sign(&mut self, input: &[&[u8]], output: &mut [u8]) -> Result<(), CryptoError> {
220 common::check_tag_len(self.output_len, output.len())?;
221 let mut context = hmac::Context::with_key(&self.key);
222 for part in input {
223 context.update(part);
224 }
225 output.copy_from_slice(context.sign().as_ref());
226 Ok(())
227 }
228
229 fn verify(&mut self, input: &[&[u8]], expected: &[u8]) -> Result<(), CryptoError> {
230 common::check_tag_len(self.output_len, expected.len())?;
231 let mut actual = vec![0; self.output_len];
232 self.sign(input, &mut actual)?;
233 if constant_time_eq(&actual, expected) {
234 Ok(())
235 } else {
236 Err(CryptoError::AuthenticationFailed)
237 }
238 }
239}
240
241fn hmac_algorithm(algorithm: HmacAlgorithm) -> hmac::Algorithm {
242 match algorithm {
243 HmacAlgorithm::Sha1 => hmac::HMAC_SHA1_FOR_LEGACY_USE_ONLY,
244 HmacAlgorithm::Sha256 => hmac::HMAC_SHA256,
245 }
246}
247
248struct RingAead {
249 key: aead::LessSafeKey,
250}
251
252impl RingAead {
253 fn create(
254 algorithm: &'static aead::Algorithm,
255 key: &[u8],
256 ) -> Result<Box<dyn AeadCipher>, CryptoError> {
257 common::check_key_len(algorithm.key_len(), key.len())?;
258 let key = aead::UnboundKey::new(algorithm, key)
259 .map(aead::LessSafeKey::new)
260 .map_err(|_| CryptoError::InvalidPrivateKey)?;
261 Ok(Box::new(Self { key }))
262 }
263}
264
265impl AeadCipher for RingAead {
266 fn tag_len(&self) -> usize {
267 16
268 }
269
270 fn seal_in_place(
271 &mut self,
272 nonce: &[u8],
273 aad: &[u8],
274 plaintext_and_ciphertext: &mut [u8],
275 tag_out: &mut [u8],
276 ) -> Result<(), CryptoError> {
277 common::check_nonce_len(12, nonce.len())?;
278 common::check_tag_len(self.tag_len(), tag_out.len())?;
279 let nonce = aead::Nonce::try_assume_unique_for_key(nonce).map_err(|_| {
280 CryptoError::InvalidNonceLength {
281 expected: 12,
282 actual: nonce.len(),
283 }
284 })?;
285 let tag = self
286 .key
287 .seal_in_place_separate_tag(nonce, aead::Aad::from(aad), plaintext_and_ciphertext)
288 .map_err(|_| CryptoError::AuthenticationFailed)?;
289 tag_out.copy_from_slice(tag.as_ref());
290 Ok(())
291 }
292
293 fn open_in_place(
294 &mut self,
295 nonce: &[u8],
296 aad: &[u8],
297 ciphertext_and_plaintext: &mut [u8],
298 tag: &[u8],
299 ) -> Result<(), CryptoError> {
300 common::check_nonce_len(12, nonce.len())?;
301 common::check_tag_len(self.tag_len(), tag.len())?;
302 let nonce = aead::Nonce::try_assume_unique_for_key(nonce).map_err(|_| {
303 CryptoError::InvalidNonceLength {
304 expected: 12,
305 actual: nonce.len(),
306 }
307 })?;
308 let tag = aead::Tag::try_from(tag).map_err(|_| CryptoError::InvalidTagLength {
309 expected: self.tag_len(),
310 actual: tag.len(),
311 })?;
312 self.key
313 .open_in_place_separate_tag(
314 nonce,
315 aead::Aad::from(aad),
316 tag,
317 ciphertext_and_plaintext,
318 0..,
319 )
320 .map(|_| ())
321 .map_err(|_| CryptoError::AuthenticationFailed)
322 }
323}
324
325struct RingKeyExchange {
326 algorithm: KeyExchangeAlgorithm,
327 backend_algorithm: &'static agreement::Algorithm,
328 private_key: agreement::EphemeralPrivateKey,
329 public_key: Vec<u8>,
330}
331
332impl RingKeyExchange {
333 fn start(algorithm: KeyExchangeAlgorithm) -> Result<Box<dyn ActiveKeyExchange>, CryptoError> {
334 let backend_algorithm = agreement_algorithm(algorithm);
335 let private_key =
336 agreement::EphemeralPrivateKey::generate(backend_algorithm, &SystemRandom::new())
337 .map_err(|_| CryptoError::RandomnessFailed)?;
338 let public_key = private_key
339 .compute_public_key()
340 .map_err(|_| CryptoError::Provider("key exchange public-key generation failed".into()))?
341 .as_ref()
342 .to_vec();
343 Ok(Box::new(Self {
344 algorithm,
345 backend_algorithm,
346 private_key,
347 public_key,
348 }))
349 }
350}
351
352impl ActiveKeyExchange for RingKeyExchange {
353 fn algorithm(&self) -> KeyExchangeAlgorithm {
354 self.algorithm
355 }
356
357 fn public_key(&self) -> &[u8] {
358 &self.public_key
359 }
360
361 fn complete(self: Box<Self>, peer_public_key: &[u8]) -> Result<SecretVec, CryptoError> {
362 let peer = agreement::UnparsedPublicKey::new(self.backend_algorithm, peer_public_key);
363 agreement::agree_ephemeral(self.private_key, &peer, |secret| {
364 SecretVec::new(secret.to_vec())
365 })
366 .map_err(|_| CryptoError::InvalidPublicKey)
367 }
368}
369
370enum RingSigningKeyKind {
371 Ed25519(signature::Ed25519KeyPair),
372 EcdsaP256(signature::EcdsaKeyPair),
373 Rsa(signature::RsaKeyPair),
374}
375
376struct RingSigningKey {
377 scheme: SignatureScheme,
378 kind: RingSigningKeyKind,
379 public_key: Vec<u8>,
380 public_key_encoding: PublicKeyEncoding,
381 pkcs8_der: SecretVec,
382}
383
384impl RingSigningKey {
385 fn generate(scheme: SignatureScheme) -> Result<Arc<dyn SigningKey>, CryptoError> {
386 let rng = SystemRandom::new();
387 let pkcs8 = match scheme {
388 SignatureScheme::Ed25519 => signature::Ed25519KeyPair::generate_pkcs8(&rng),
389 SignatureScheme::EcdsaP256Sha256 => signature::EcdsaKeyPair::generate_pkcs8(
390 &signature::ECDSA_P256_SHA256_ASN1_SIGNING,
391 &rng,
392 ),
393 _ => {
394 return Err(CryptoError::UnsupportedAlgorithm(
395 CryptoAlgorithm::SigningKeyGeneration(scheme),
396 ));
397 }
398 }
399 .map_err(|_| CryptoError::RandomnessFailed)?;
400 Self::import(scheme, pkcs8.as_ref())
401 }
402
403 fn import(
404 scheme: SignatureScheme,
405 pkcs8_der: &[u8],
406 ) -> Result<Arc<dyn SigningKey>, CryptoError> {
407 let rng = SystemRandom::new();
408 let (kind, public_key, public_key_encoding) = match scheme {
409 SignatureScheme::Ed25519 => {
410 let key = signature::Ed25519KeyPair::from_pkcs8_maybe_unchecked(pkcs8_der)
411 .map_err(|_| CryptoError::InvalidPrivateKey)?;
412 let public = key.public_key().as_ref().to_vec();
413 (
414 RingSigningKeyKind::Ed25519(key),
415 public,
416 PublicKeyEncoding::Ed25519Raw,
417 )
418 }
419 SignatureScheme::EcdsaP256Sha256 => {
420 let key = signature::EcdsaKeyPair::from_pkcs8(
421 &signature::ECDSA_P256_SHA256_ASN1_SIGNING,
422 pkcs8_der,
423 &rng,
424 )
425 .map_err(|_| CryptoError::InvalidPrivateKey)?;
426 let public = key.public_key().as_ref().to_vec();
427 (
428 RingSigningKeyKind::EcdsaP256(key),
429 public,
430 PublicKeyEncoding::EcUncompressedPoint,
431 )
432 }
433 SignatureScheme::RsaPkcs1Sha256 => {
434 let key = signature::RsaKeyPair::from_pkcs8(pkcs8_der)
435 .map_err(|_| CryptoError::InvalidPrivateKey)?;
436 let public = key.public().as_ref().to_vec();
437 (
438 RingSigningKeyKind::Rsa(key),
439 public,
440 PublicKeyEncoding::RsaPkcs1Der,
441 )
442 }
443 _ => {
444 return Err(CryptoError::UnsupportedAlgorithm(
445 CryptoAlgorithm::SigningKeyImport(scheme),
446 ));
447 }
448 };
449 Ok(Arc::new(Self {
450 scheme,
451 kind,
452 public_key,
453 public_key_encoding,
454 pkcs8_der: SecretVec::new(pkcs8_der.to_vec()),
455 }))
456 }
457}
458
459impl SigningKey for RingSigningKey {
460 fn supports(&self, scheme: SignatureScheme) -> bool {
461 self.scheme == scheme
462 }
463
464 fn public_key(&self) -> PublicKey<'_> {
465 PublicKey {
466 encoding: self.public_key_encoding,
467 bytes: &self.public_key,
468 }
469 }
470
471 fn sign(&self, scheme: SignatureScheme, message: &[u8]) -> Result<Vec<u8>, CryptoError> {
472 if !self.supports(scheme) {
473 return Err(CryptoError::UnsupportedAlgorithm(
474 CryptoAlgorithm::Signature(scheme),
475 ));
476 }
477 match &self.kind {
478 RingSigningKeyKind::Ed25519(key) => Ok(key.sign(message).as_ref().to_vec()),
479 RingSigningKeyKind::EcdsaP256(key) => key
480 .sign(&SystemRandom::new(), message)
481 .map(|signature| signature.as_ref().to_vec())
482 .map_err(|_| CryptoError::Provider("signature generation failed".into())),
483 RingSigningKeyKind::Rsa(key) => {
484 let mut signature = vec![0; key.public().modulus_len()];
485 key.sign(
486 &signature::RSA_PKCS1_SHA256,
487 &SystemRandom::new(),
488 message,
489 &mut signature,
490 )
491 .map_err(|_| CryptoError::Provider("signature generation failed".into()))?;
492 Ok(signature)
493 }
494 }
495 }
496
497 fn to_pkcs8_der(&self) -> Result<Option<SecretVec>, CryptoError> {
498 Ok(Some(self.pkcs8_der.clone()))
499 }
500}
501
502fn agreement_algorithm(algorithm: KeyExchangeAlgorithm) -> &'static agreement::Algorithm {
503 match algorithm {
504 KeyExchangeAlgorithm::P256 => &agreement::ECDH_P256,
505 KeyExchangeAlgorithm::P384 => &agreement::ECDH_P384,
506 KeyExchangeAlgorithm::X25519 => &agreement::X25519,
507 }
508}
509
510fn verification_algorithm(
511 scheme: SignatureScheme,
512) -> &'static dyn signature::VerificationAlgorithm {
513 match scheme {
514 SignatureScheme::Ed25519 => &signature::ED25519,
515 SignatureScheme::EcdsaP256Sha256 => &signature::ECDSA_P256_SHA256_ASN1,
516 SignatureScheme::EcdsaP384Sha384 => &signature::ECDSA_P384_SHA384_ASN1,
517 SignatureScheme::RsaPkcs1Sha1 => &signature::RSA_PKCS1_1024_8192_SHA1_FOR_LEGACY_USE_ONLY,
518 SignatureScheme::RsaPkcs1Sha256 => {
519 &signature::RSA_PKCS1_1024_8192_SHA256_FOR_LEGACY_USE_ONLY
520 }
521 SignatureScheme::RsaPkcs1Sha384 => &signature::RSA_PKCS1_2048_8192_SHA384,
522 SignatureScheme::RsaPkcs1Sha512 => {
523 &signature::RSA_PKCS1_1024_8192_SHA512_FOR_LEGACY_USE_ONLY
524 }
525 }
526}
527
528fn verify_public_key_encoding(
529 scheme: SignatureScheme,
530 encoding: PublicKeyEncoding,
531) -> Result<(), CryptoError> {
532 let valid = matches!(
533 (scheme, encoding),
534 (SignatureScheme::Ed25519, PublicKeyEncoding::Ed25519Raw)
535 | (
536 SignatureScheme::EcdsaP256Sha256 | SignatureScheme::EcdsaP384Sha384,
537 PublicKeyEncoding::EcUncompressedPoint
538 )
539 | (
540 SignatureScheme::RsaPkcs1Sha1
541 | SignatureScheme::RsaPkcs1Sha256
542 | SignatureScheme::RsaPkcs1Sha384
543 | SignatureScheme::RsaPkcs1Sha512,
544 PublicKeyEncoding::RsaPkcs1Der
545 )
546 );
547 if valid {
548 Ok(())
549 } else {
550 Err(CryptoError::InvalidPublicKey)
551 }
552}
553
554type HmacSha1 = ::hmac::Hmac<Sha1>;
555
556pub(crate) struct RustCryptoHmacSha1 {
565 keyed: HmacSha1,
566}
567
568impl RustCryptoHmacSha1 {
569 pub(crate) fn new(key: &[u8]) -> Self {
570 Self {
571 keyed: <HmacSha1 as RustCryptoMac>::new_from_slice(key)
573 .expect("HMAC accepts keys of any length"),
574 }
575 }
576}
577
578impl Mac for RustCryptoHmacSha1 {
579 fn output_len(&self) -> usize {
580 20
581 }
582
583 fn sign(&mut self, input: &[&[u8]], output: &mut [u8]) -> Result<(), CryptoError> {
584 check_tag_len(20, output.len())?;
585 let mut mac = self.keyed.clone();
586 for part in input {
587 mac.update(part);
588 }
589 output.copy_from_slice(&mac.finalize().into_bytes());
590 Ok(())
591 }
592
593 fn verify(&mut self, input: &[&[u8]], expected: &[u8]) -> Result<(), CryptoError> {
594 check_tag_len(20, expected.len())?;
595 let mut actual = [0u8; 20];
596 self.sign(input, &mut actual)?;
597 if crate::constant_time_eq(&actual, expected) {
598 Ok(())
599 } else {
600 Err(CryptoError::AuthenticationFailed)
601 }
602 }
603}