use crate::der::{self, FromDer};
use crate::error::{DerTypeId, Error};
use crate::verify_cert::Budget;
use pki_types::{AlgorithmIdentifier, SignatureVerificationAlgorithm};
#[cfg(feature = "alloc")]
use alloc::vec::Vec;
#[cfg(feature = "alloc")]
#[derive(Clone, Debug)]
pub(crate) struct OwnedSignedData {
pub(crate) data: Vec<u8>,
pub(crate) algorithm: Vec<u8>,
pub(crate) signature: Vec<u8>,
}
#[cfg(feature = "alloc")]
impl OwnedSignedData {
pub(crate) fn borrow(&self) -> SignedData<'_> {
SignedData {
data: untrusted::Input::from(&self.data),
algorithm: untrusted::Input::from(&self.algorithm),
signature: untrusted::Input::from(&self.signature),
}
}
}
#[derive(Debug)]
pub(crate) struct SignedData<'a> {
pub(crate) data: untrusted::Input<'a>,
pub(crate) algorithm: untrusted::Input<'a>,
pub(crate) signature: untrusted::Input<'a>,
}
impl<'a> SignedData<'a> {
pub(crate) fn from_der(
der: &mut untrusted::Reader<'a>,
size_limit: usize,
) -> Result<(untrusted::Input<'a>, Self), Error> {
let (data, tbs) = der.read_partial(|input| {
der::expect_tag_and_get_value_limited(input, der::Tag::Sequence, size_limit)
})?;
let algorithm = der::expect_tag(der, der::Tag::Sequence)?;
let signature = der::bit_string_with_no_unused_bits(der)?;
Ok((
tbs,
SignedData {
data,
algorithm,
signature,
},
))
}
#[cfg(feature = "alloc")]
pub(crate) fn to_owned(&self) -> OwnedSignedData {
OwnedSignedData {
data: self.data.as_slice_less_safe().to_vec(),
algorithm: self.algorithm.as_slice_less_safe().to_vec(),
signature: self.signature.as_slice_less_safe().to_vec(),
}
}
}
pub(crate) fn verify_signed_data(
supported_algorithms: &[&dyn SignatureVerificationAlgorithm],
spki_value: untrusted::Input,
signed_data: &SignedData,
budget: &mut Budget,
) -> Result<(), Error> {
budget.consume_signature()?;
let mut found_signature_alg_match = false;
for supported_alg in supported_algorithms
.iter()
.filter(|alg| alg.signature_alg_id().as_ref() == signed_data.algorithm.as_slice_less_safe())
{
match verify_signature(
*supported_alg,
spki_value,
signed_data.data,
signed_data.signature,
) {
Err(Error::UnsupportedSignatureAlgorithmForPublicKey) => {
found_signature_alg_match = true;
continue;
}
result => {
return result;
}
}
}
if found_signature_alg_match {
Err(Error::UnsupportedSignatureAlgorithmForPublicKey)
} else {
Err(Error::UnsupportedSignatureAlgorithm)
}
}
pub(crate) fn verify_signature(
signature_alg: &dyn SignatureVerificationAlgorithm,
spki_value: untrusted::Input,
msg: untrusted::Input,
signature: untrusted::Input,
) -> Result<(), Error> {
let spki = der::read_all::<SubjectPublicKeyInfo>(spki_value)?;
if signature_alg.public_key_alg_id().as_ref() != spki.algorithm_id_value.as_slice_less_safe() {
return Err(Error::UnsupportedSignatureAlgorithmForPublicKey);
}
signature_alg
.verify_signature(
spki.key_value.as_slice_less_safe(),
msg.as_slice_less_safe(),
signature.as_slice_less_safe(),
)
.map_err(|_| Error::InvalidSignatureForPublicKey)
}
struct SubjectPublicKeyInfo<'a> {
algorithm_id_value: untrusted::Input<'a>,
key_value: untrusted::Input<'a>,
}
impl<'a> FromDer<'a> for SubjectPublicKeyInfo<'a> {
fn from_der(reader: &mut untrusted::Reader<'a>) -> Result<Self, Error> {
let algorithm_id_value = der::expect_tag(reader, der::Tag::Sequence)?;
let key_value = der::bit_string_with_no_unused_bits(reader)?;
Ok(SubjectPublicKeyInfo {
algorithm_id_value,
key_value,
})
}
const TYPE_ID: DerTypeId = DerTypeId::SubjectPublicKeyInfo;
}
pub mod alg_id {
use super::AlgorithmIdentifier;
pub const ECDSA_P256: AlgorithmIdentifier =
AlgorithmIdentifier::from_slice(include_bytes!("data/alg-ecdsa-p256.der"));
pub const ECDSA_P384: AlgorithmIdentifier =
AlgorithmIdentifier::from_slice(include_bytes!("data/alg-ecdsa-p384.der"));
pub const ECDSA_P521: AlgorithmIdentifier =
AlgorithmIdentifier::from_slice(include_bytes!("data/alg-ecdsa-p521.der"));
pub const ECDSA_SHA256: AlgorithmIdentifier =
AlgorithmIdentifier::from_slice(include_bytes!("data/alg-ecdsa-sha256.der"));
pub const ECDSA_SHA384: AlgorithmIdentifier =
AlgorithmIdentifier::from_slice(include_bytes!("data/alg-ecdsa-sha384.der"));
pub const ECDSA_SHA512: AlgorithmIdentifier =
AlgorithmIdentifier::from_slice(include_bytes!("data/alg-ecdsa-sha512.der"));
pub const RSA_ENCRYPTION: AlgorithmIdentifier =
AlgorithmIdentifier::from_slice(include_bytes!("data/alg-rsa-encryption.der"));
pub const RSA_PKCS1_SHA256: AlgorithmIdentifier =
AlgorithmIdentifier::from_slice(include_bytes!("data/alg-rsa-pkcs1-sha256.der"));
pub const RSA_PKCS1_SHA384: AlgorithmIdentifier =
AlgorithmIdentifier::from_slice(include_bytes!("data/alg-rsa-pkcs1-sha384.der"));
pub const RSA_PKCS1_SHA512: AlgorithmIdentifier =
AlgorithmIdentifier::from_slice(include_bytes!("data/alg-rsa-pkcs1-sha512.der"));
pub const RSA_PSS_SHA256: AlgorithmIdentifier =
AlgorithmIdentifier::from_slice(include_bytes!("data/alg-rsa-pss-sha256.der"));
pub const RSA_PSS_SHA384: AlgorithmIdentifier =
AlgorithmIdentifier::from_slice(include_bytes!("data/alg-rsa-pss-sha384.der"));
pub const RSA_PSS_SHA512: AlgorithmIdentifier =
AlgorithmIdentifier::from_slice(include_bytes!("data/alg-rsa-pss-sha512.der"));
pub const ED25519: AlgorithmIdentifier =
AlgorithmIdentifier::from_slice(include_bytes!("data/alg-ed25519.der"));
}