diff --git a/integration_tests/tests/self_test.rs b/integration_tests/tests/self_test.rs index 99cc024..3767999 100644 --- a/integration_tests/tests/self_test.rs +++ b/integration_tests/tests/self_test.rs @@ -4,7 +4,6 @@ use simple_https_client::tls13client; use simple_https_server::tls13server; #[test] -#[should_panic] fn test_sha256_chacha20_poly1305_rsa_pss_rsa_sha256_x25519() { self_test_algorithm(simple_https_client::SHA256_Chacha20Poly1305_RsaPssRsaSha256_X25519); } @@ -17,7 +16,6 @@ fn test_sha256_chacha20_poly1305_ecdsa_secp256r1_sha256_p256() { self_test_algorithm(simple_https_client::SHA256_Chacha20Poly1305_EcdsaSecp256r1Sha256_P256); } #[test] -#[should_panic] fn test_sha256_chacha20_poly1305_rsa_pss_rsa_sha256_p256() { self_test_algorithm(simple_https_client::SHA256_Chacha20Poly1305_RsaPssRsaSha256_P256); } @@ -34,14 +32,12 @@ fn test_sha256_aes128_gcm_ecdsa_secp256r1_sha256_x25519() { } } #[test] -#[should_panic] fn test_sha256_aes128_gcm_rsa_pss_rsa_sha256_p256() { if libcrux_platform::aes_ni_support() { self_test_algorithm(simple_https_client::SHA256_Aes128Gcm_RsaPssRsaSha256_P256); } } #[test] -#[should_panic] fn test_sha256_aes128_gcm_rsa_pss_rsa_sha256_x25519() { if libcrux_platform::aes_ni_support() { self_test_algorithm(simple_https_client::SHA256_Aes128Gcm_RsaPssRsaSha256_X25519); @@ -60,14 +56,12 @@ fn test_sha384_aes256_gcm_ecdsa_secp256r1_sha256_x25519() { } } #[test] -#[should_panic] fn test_sha384_aes256_gcm_rsa_pss_rsa_sha256_p256() { if libcrux_platform::aes_ni_support() { self_test_algorithm(simple_https_client::SHA384_Aes256Gcm_RsaPssRsaSha256_P256); } } #[test] -#[should_panic] fn test_sha384_aes256_gcm_rsa_pss_rsa_sha256_x25519() { if libcrux_platform::aes_ni_support() { self_test_algorithm(simple_https_client::SHA384_Aes256Gcm_RsaPssRsaSha256_X25519); diff --git a/src/tls13crypto.rs b/src/tls13crypto.rs index a476def..ce2228b 100644 --- a/src/tls13crypto.rs +++ b/src/tls13crypto.rs @@ -5,7 +5,8 @@ use libcrux::{ }; use crate::{ - eq, tlserr, Bytes, Declassify, TLSError, CRYPTO_ERROR, INVALID_SIGNATURE, UNSUPPORTED_ALGORITHM, + eq, tls13cert, tlserr, Bytes, Declassify, TLSError, CRYPTO_ERROR, INVALID_SIGNATURE, + UNSUPPORTED_ALGORITHM, }; pub type Random = Bytes; //was [U8;32] @@ -226,7 +227,9 @@ pub enum SignatureScheme { pub fn to_libcrux_sig_alg(a: &SignatureScheme) -> Result { match a { - SignatureScheme::RsaPssRsaSha256 => tlserr(UNSUPPORTED_ALGORITHM), + SignatureScheme::RsaPssRsaSha256 => Ok(signature::Algorithm::RsaPss( + signature::DigestAlgorithm::Sha256, + )), SignatureScheme::ED25519 => Ok(signature::Algorithm::Ed25519), SignatureScheme::EcdsaSecp256r1Sha256 => Ok(signature::Algorithm::EcDsaP256( signature::DigestAlgorithm::Sha256, @@ -237,15 +240,48 @@ pub fn to_libcrux_sig_alg(a: &SignatureScheme) -> Result Result { - let sig = signature::sign( - to_libcrux_sig_alg(alg)?, - &input.declassify(), - &sk.declassify(), - &mut rand::thread_rng(), - ); + let sig = match alg { + SignatureScheme::EcdsaSecp256r1Sha256 | SignatureScheme::ED25519 => signature::sign( + to_libcrux_sig_alg(alg)?, + &input.declassify(), + &sk.declassify(), + &mut rand::thread_rng(), + ), + SignatureScheme::RsaPssRsaSha256 => { + // salt must be same length as digest ouput length + let mut salt = [0u8; 32]; + use rand::RngCore; + rand::thread_rng().fill_bytes(&mut salt); + let (cert_scheme, cert_slice) = tls13cert::verification_key_from_cert(cert)?; + if !matches!(cert_scheme, SignatureScheme::RsaPssRsaSha256) { + return tlserr(CRYPTO_ERROR); // XXX: Right error type? + } + let (pk_modulus, pk_exponent) = tls13cert::rsa_public_key(cert, cert_slice)?; + + if !valid_rsa_exponent(pk_exponent.declassify()) { + return tlserr(UNSUPPORTED_ALGORITHM); + } + + let key_size = supported_rsa_key_size(&pk_modulus)?; + + let pk = RsaPssPublicKey::new(key_size, &pk_modulus.declassify()[1..]) + .map_err(|_| CRYPTO_ERROR)?; + + let sk = signature::rsa_pss::RsaPssPrivateKey::new(&pk, &sk.declassify()) + .map_err(|_| CRYPTO_ERROR)?; + + sk.sign( + signature::DigestAlgorithm::Sha256, + &salt, + &input.declassify(), + ) + .map(signature::Signature::RsaPss) + } + }; match sig { Ok(signature::Signature::Ed25519(sig)) => Ok(sig.as_bytes().into()), Ok(signature::Signature::EcDsaP256(sig)) => { @@ -292,21 +328,12 @@ pub fn verify( } } (SignatureScheme::RsaPssRsaSha256, PublicVerificationKey::Rsa((n, e))) => { - let e = e.declassify(); - if !(e.len() == 3 && e[0] == 0x1 && e[1] == 0x0 && e[2] == 0x1) { - // libcrux only supports `e = 3` + if !valid_rsa_exponent(e.declassify()) { tlserr(UNSUPPORTED_ALGORITHM) } else { - let key_size = match n.len() { - // The format includes an extra 0-byte in front to disambiguate from negative numbers - 257 => RsaPssKeySize::N2048, - 385 => RsaPssKeySize::N3072, - 513 => RsaPssKeySize::N4096, - 769 => RsaPssKeySize::N6144, - 1025 => RsaPssKeySize::N8192, - _ => return tlserr(UNSUPPORTED_ALGORITHM), - }; - let pk = RsaPssPublicKey::new(key_size, &n.declassify()[1..]).unwrap(); + let key_size = supported_rsa_key_size(n)?; + let pk = RsaPssPublicKey::new(key_size, &n.declassify()[1..]) + .map_err(|_| CRYPTO_ERROR)?; let res = pk.verify( signature::DigestAlgorithm::Sha256, &sig.declassify().into(), @@ -323,6 +350,27 @@ pub fn verify( } } +/// Determine if given modulus conforms to one of the key sizes supported by +/// `libcrux`. +fn supported_rsa_key_size(n: &Bytes) -> Result { + let key_size = match n.len() { + // The format includes an extra 0-byte in front to disambiguate from negative numbers + 257 => RsaPssKeySize::N2048, + 385 => RsaPssKeySize::N3072, + 513 => RsaPssKeySize::N4096, + 769 => RsaPssKeySize::N6144, + 1025 => RsaPssKeySize::N8192, + _ => return tlserr(UNSUPPORTED_ALGORITHM), + }; + Ok(key_size) +} + +/// Determine if given public exponent is supported by `libcrux`, i.e. whether +/// `e == 0x010001`. +fn valid_rsa_exponent(e: Vec) -> bool { + e.len() == 3 && e[0] == 0x1 && e[1] == 0x0 && e[2] == 0x1 +} + #[derive(Clone, Copy, PartialEq, Debug)] pub enum KemScheme { X25519, diff --git a/src/tls13formats.rs b/src/tls13formats.rs index 3c9c2b5..638cbe8 100644 --- a/src/tls13formats.rs +++ b/src/tls13formats.rs @@ -906,13 +906,19 @@ fn parse_ecdsa_signature(sig: Bytes) -> Result { } } pub fn certificate_verify(algs: &Algorithms, cv: &Bytes) -> Result { - if cv.len() != 64 { - tlserr(parse_failed()) - } else { - let sv = ecdsa_signature(cv)?; - let sig = signature_algorithm(algs)?.concat(&lbytes2(&sv)?); - Ok(handshake_message(HandshakeType::CertificateVerify, &sig)?) - } + let sv = match algs.2 { + SignatureScheme::RsaPssRsaSha256 => cv.clone(), + SignatureScheme::EcdsaSecp256r1Sha256 | SignatureScheme::ED25519 => { + if cv.len() != 64 { + return tlserr(parse_failed()); + } else { + ecdsa_signature(cv)? + } + } + }; + + let sig = signature_algorithm(algs)?.concat(&lbytes2(&sv)?); + handshake_message(HandshakeType::CertificateVerify, &sig) } pub fn parse_certificate_verify(algs: &Algorithms, cv: &HandshakeData) -> Result { diff --git a/src/tls13handshake.rs b/src/tls13handshake.rs index 0052ba9..51f3b78 100644 --- a/src/tls13handshake.rs +++ b/src/tls13handshake.rs @@ -493,7 +493,7 @@ fn get_server_signature( let tx = transcript_add1(tx, &sc); let th = get_transcript_hash(&tx)?; let sigval = Bytes::from_slice(&PREFIX_SERVER_SIGNATURE).concat(&th); - let sig = sign(&sig_alg(&algs), &sigk, &sigval, ent)?; + let sig = sign(&sig_alg(&algs), &sigk, &cert, &sigval, ent)?; let scv = certificate_verify(&algs, &sig)?; let tx = transcript_add1(tx, &scv); Ok((