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