use bcder::{decode, encode};
use bcder::{ConstOid, Oid, Tag};
use bcder::decode::DecodeError;
use bcder::encode::PrimitiveContent;
use bytes::Bytes;
use crate::oid;
use super::keys::PublicKeyFormat;
use super::signer::SigningAlgorithm;
pub trait SignatureAlgorithm: Sized {
type Encoder: encode::Values;
fn signing_algorithm(&self) -> SigningAlgorithm;
fn public_key_format(&self) -> PublicKeyFormat {
self.signing_algorithm().public_key_format()
}
fn x509_take_from<S: decode::Source>(
cons: &mut decode::Constructed<S>
) -> Result<Self, DecodeError<S::Error>>;
fn x509_encode(&self) -> Self::Encoder;
}
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct RpkiSignatureAlgorithm {
has_parameter: bool
}
impl RpkiSignatureAlgorithm {
fn x509_from_constructed<S: decode::Source>(
cons: &mut decode::Constructed<S>
) -> Result<Self, DecodeError<S::Error>> {
oid::SHA256_WITH_RSA_ENCRYPTION.skip_if(cons)?;
let has_parameter = cons.take_opt_primitive_if(
Tag::NULL, |_| Ok(())
)?.is_some();
Ok(RpkiSignatureAlgorithm { has_parameter })
}
pub fn cms_take_from<S: decode::Source>(
cons: &mut decode::Constructed<S>
) -> Result<Self, DecodeError<S::Error>> {
cons.take_sequence(Self::cms_from_constructed)
}
fn cms_from_constructed<S: decode::Source>(
cons: &mut decode::Constructed<S>
) -> Result<Self, DecodeError<S::Error>> {
let oid = Oid::take_from(cons)?;
if
oid != oid::RSA_ENCRYPTION
&& oid != oid::SHA256_WITH_RSA_ENCRYPTION
{
return Err(cons.content_err("invalid signature algorithm"))
}
let has_parameter = cons.take_opt_primitive_if(
Tag::NULL, |_| Ok(())
)?.is_some();
Ok(RpkiSignatureAlgorithm { has_parameter })
}
pub fn x509_encode(self) -> impl encode::Values {
encode::sequence((
oid::SHA256_WITH_RSA_ENCRYPTION.encode(),
().encode(),
))
}
pub fn cms_encode(self) -> impl encode::Values {
encode::sequence((
oid::RSA_ENCRYPTION.encode(),
().encode(),
))
}
}
impl Default for RpkiSignatureAlgorithm {
fn default() -> Self {
RpkiSignatureAlgorithm { has_parameter: true }
}
}
impl SignatureAlgorithm for RpkiSignatureAlgorithm {
type Encoder = encode::Constructed<(
encode::Primitive<ConstOid>, encode::Primitive<()>
)>;
fn signing_algorithm(&self) -> SigningAlgorithm {
SigningAlgorithm::RsaSha256
}
fn x509_take_from<S: decode::Source>(
cons: &mut decode::Constructed<S>
) -> Result<Self, DecodeError<S::Error>> {
cons.take_sequence(Self::x509_from_constructed)
}
fn x509_encode(&self) -> Self::Encoder {
encode::Constructed::new(
Tag::SEQUENCE,
(oid::SHA256_WITH_RSA_ENCRYPTION.encode(), ().encode())
)
}
}
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
pub struct BgpsecSignatureAlgorithm(());
impl BgpsecSignatureAlgorithm {
fn x509_from_constructed<S: decode::Source>(
cons: &mut decode::Constructed<S>
) -> Result<Self, DecodeError<S::Error>> {
oid::ECDSA_WITH_SHA256.skip_if(cons)?;
Ok(BgpsecSignatureAlgorithm(()))
}
}
impl SignatureAlgorithm for BgpsecSignatureAlgorithm {
type Encoder = encode::Constructed<encode::Primitive<ConstOid>>;
fn signing_algorithm(&self) -> SigningAlgorithm {
SigningAlgorithm::EcdsaP256Sha256
}
fn x509_take_from<S: decode::Source>(
cons: &mut decode::Constructed<S>
) -> Result<Self, DecodeError<S::Error>> {
cons.take_sequence(Self::x509_from_constructed)
}
fn x509_encode(&self) -> Self::Encoder {
encode::Constructed::new(
Tag::SEQUENCE,
oid::ECDSA_WITH_SHA256.encode()
)
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Signature<Alg> {
algorithm: Alg,
value: Bytes
}
pub type RpkiSignature = Signature<RpkiSignatureAlgorithm>;
impl<Alg> Signature<Alg> {
pub fn new(algorithm: Alg, value: Bytes) -> Self {
Signature { algorithm, value }
}
pub fn algorithm(&self) -> &Alg {
&self.algorithm
}
pub fn value(&self) -> &Bytes {
&self.value
}
pub fn unwrap(self) -> (Alg, Bytes) {
(self.algorithm, self.value)
}
}