use super::*;
use noxtls_crypto::{
noxtls_ed25519_public_key_from_subject_public_key_info, noxtls_ed25519_verify,
noxtls_mldsa_verify, noxtls_p256_ecdsa_verify_sha256, noxtls_p384_ecdsa_verify_sha384,
noxtls_rsassa_pss_sha256_verify, noxtls_rsassa_pss_sha384_verify, noxtls_rsassa_pss_verify,
MlDsaPublicKey, P256PublicKey, P384PublicKey, RsaPssHashAlgorithm,
};
pub(super) fn noxtls_parse_tls12_signature_fields(
body: &[u8],
offset: usize,
) -> Result<(u16, &[u8])> {
if body.len() < offset + 4 {
return Err(Error::ParseFailure(
"tls12 server key exchange signature header is truncated",
));
}
let signature_scheme = u16::from_be_bytes([body[offset], body[offset + 1]]);
if !noxtls_tls12_signature_scheme_is_modern(signature_scheme) {
return Err(Error::ParseFailure(
"tls12 server key exchange uses unsupported signature scheme",
));
}
let signature_len = u16::from_be_bytes([body[offset + 2], body[offset + 3]]) as usize;
if signature_len == 0 {
return Err(Error::ParseFailure(
"tls12 server key exchange signature must not be empty",
));
}
if body.len() != offset + 4 + signature_len {
return Err(Error::ParseFailure(
"tls12 server key exchange signature length is malformed",
));
}
Ok((signature_scheme, &body[offset + 4..]))
}
#[must_use]
pub(super) fn noxtls_build_tls12_server_key_exchange_signed_input(
client_random: &[u8; 32],
server_random: &[u8; 32],
params: &[u8],
) -> Vec<u8> {
let mut signed_input = Vec::with_capacity(64 + params.len());
signed_input.extend_from_slice(client_random);
signed_input.extend_from_slice(server_random);
signed_input.extend_from_slice(params);
signed_input
}
impl Connection {
pub(super) fn noxtls_verify_tls12_server_key_exchange_signature(
&self,
params: &[u8],
signature_scheme: u16,
signature: &[u8],
) -> Result<()> {
let client_random = self.tls12_client_random.ok_or(Error::StateError(
"tls12 client random must be available before server key exchange verification",
))?;
let server_random = self.tls12_server_random.ok_or(Error::StateError(
"tls12 server random must be available before server key exchange verification",
))?;
let leaf_spki =
self.tls13_server_leaf_public_key_der
.as_deref()
.ok_or(Error::StateError(
"tls12 server certificate public key is unavailable for key exchange verification",
))?;
let signed_input = noxtls_build_tls12_server_key_exchange_signed_input(
&client_random,
&server_random,
params,
);
Self::noxtls_verify_tls12_digitally_signed_signature(
signature_scheme,
signature,
&signed_input,
leaf_spki,
)
}
fn noxtls_verify_tls12_digitally_signed_signature(
signature_scheme: u16,
signature: &[u8],
signed_input: &[u8],
leaf_spki: &[u8],
) -> Result<()> {
match signature_scheme {
TLS13_SIGALG_ECDSA_SECP256R1_SHA256 => {
let public_key = P256PublicKey::from_uncompressed(leaf_spki)?;
let (r, s) = if signature.len() == 64 {
let mut r = [0_u8; 32];
let mut s = [0_u8; 32];
r.copy_from_slice(&signature[..32]);
s.copy_from_slice(&signature[32..]);
(r, s)
} else {
noxtls_parse_ecdsa_signature_der(signature)?
};
noxtls_p256_ecdsa_verify_sha256(&public_key, signed_input, &r, &s).map_err(|_| {
Error::CryptoFailure("tls12 server key exchange signature validation failed")
})
}
TLS13_SIGALG_ECDSA_SECP384R1_SHA384 => {
let public_key = P384PublicKey::from_uncompressed(leaf_spki)
.map_err(|_| Error::ParseFailure("failed to parse p384 server public key"))?;
let (r, s) = noxtls_parse_ecdsa_p384_signature_der(signature)
.map_err(|_| Error::ParseFailure("failed to parse p384 ecdsa signature"))?;
noxtls_p384_ecdsa_verify_sha384(&public_key, signed_input, &r, &s).map_err(|_| {
Error::CryptoFailure("tls12 server key exchange signature validation failed")
})
}
TLS13_SIGALG_RSA_PSS_RSAE_SHA256 | TLS13_SIGALG_RSA_PSS_PSS_SHA256 => {
let public_key = noxtls_parse_rsa_public_key_der(leaf_spki)?;
noxtls_rsassa_pss_sha256_verify(&public_key, signed_input, signature, 32).map_err(
|_| {
Error::CryptoFailure(
"tls12 server key exchange signature validation failed",
)
},
)
}
TLS13_SIGALG_RSA_PSS_RSAE_SHA384 | TLS13_SIGALG_RSA_PSS_PSS_SHA384 => {
let public_key = noxtls_parse_rsa_public_key_der(leaf_spki)?;
noxtls_rsassa_pss_sha384_verify(&public_key, signed_input, signature, 48).map_err(
|_| {
Error::CryptoFailure(
"tls12 server key exchange signature validation failed",
)
},
)
}
TLS13_SIGALG_RSA_PSS_RSAE_SHA512 | TLS13_SIGALG_RSA_PSS_PSS_SHA512 => {
let public_key = noxtls_parse_rsa_public_key_der(leaf_spki)?;
noxtls_rsassa_pss_verify(
&public_key,
signed_input,
signature,
RsaPssHashAlgorithm::Sha512,
RsaPssHashAlgorithm::Sha512,
64,
)
.map_err(|_| {
Error::CryptoFailure("tls12 server key exchange signature validation failed")
})
}
TLS13_SIGALG_ED25519 => {
let public_key = noxtls_ed25519_public_key_from_subject_public_key_info(leaf_spki)?;
noxtls_ed25519_verify(&public_key, signed_input, signature).map_err(|_| {
Error::CryptoFailure("tls12 server key exchange signature validation failed")
})
}
TLS13_SIGALG_MLDSA65 => {
let public_key = MlDsaPublicKey::from_bytes(leaf_spki).map_err(|_| {
Error::ParseFailure("failed to parse mldsa server public key bytes")
})?;
noxtls_mldsa_verify(&public_key, signed_input, signature).map_err(|_| {
Error::CryptoFailure("tls12 server key exchange signature validation failed")
})
}
_ => Err(Error::UnsupportedFeature(
"unsupported tls12 server key exchange signature scheme",
)),
}
}
}