use {
crate::{
rfc5280::{AlgorithmIdentifier, AlgorithmParameter},
X509CertificateError as Error,
},
bcder::{ConstOid, Oid},
ring::{digest, signature},
std::convert::TryFrom,
};
const OID_SHA256: ConstOid = Oid(&[96, 134, 72, 1, 101, 3, 4, 2, 1]);
const OID_SHA512: ConstOid = Oid(&[96, 134, 72, 1, 101, 3, 4, 2, 3]);
const OID_SHA1_RSA: ConstOid = Oid(&[42, 134, 72, 134, 247, 13, 1, 1, 5]);
const OID_SHA256_RSA: ConstOid = Oid(&[42, 134, 72, 134, 247, 13, 1, 1, 11]);
const OID_SHA512_RSA: ConstOid = Oid(&[42, 134, 72, 134, 247, 13, 1, 1, 13]);
const OID_RSAES_PKCS_V15: ConstOid = Oid(&[42, 134, 72, 134, 247, 13, 1, 1, 1]);
const OID_RSA: ConstOid = Oid(&[42, 134, 72, 134, 247, 13, 1, 1, 1]);
pub(crate) const OID_ECDSA_SHA256: ConstOid = Oid(&[42, 134, 72, 206, 61, 4, 3, 2]);
pub(crate) const OID_ECDSA_SHA384: ConstOid = Oid(&[42, 134, 72, 206, 61, 4, 3, 3]);
pub(crate) const OID_EC_PUBLIC_KEY: ConstOid = Oid(&[42, 134, 72, 206, 61, 2, 1]);
const OID_ED25519_KEY_AGREEMENT: ConstOid = Oid(&[43, 101, 110]);
const OID_ED25519_SIGNATURE_ALGORITHM: ConstOid = Oid(&[43, 101, 112]);
pub(crate) const OID_EC_SECP256R1: ConstOid = Oid(&[42, 134, 72, 206, 61, 3, 1, 7]);
pub(crate) const OID_EC_SECP384R1: ConstOid = Oid(&[43, 129, 4, 0, 34]);
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum DigestAlgorithm {
Sha256,
Sha512,
}
impl From<DigestAlgorithm> for Oid {
fn from(alg: DigestAlgorithm) -> Self {
Oid(match alg {
DigestAlgorithm::Sha256 => OID_SHA256.as_ref(),
DigestAlgorithm::Sha512 => OID_SHA512.as_ref(),
}
.into())
}
}
impl TryFrom<&Oid> for DigestAlgorithm {
type Error = Error;
fn try_from(v: &Oid) -> Result<Self, Self::Error> {
if v == &OID_SHA256 {
Ok(Self::Sha256)
} else if v == &OID_SHA512 {
Ok(Self::Sha512)
} else {
Err(Error::UnknownDigestAlgorithm(format!("{}", v)))
}
}
}
impl TryFrom<&AlgorithmIdentifier> for DigestAlgorithm {
type Error = Error;
fn try_from(v: &AlgorithmIdentifier) -> Result<Self, Self::Error> {
Self::try_from(&v.algorithm)
}
}
impl From<DigestAlgorithm> for AlgorithmIdentifier {
fn from(alg: DigestAlgorithm) -> Self {
Self {
algorithm: alg.into(),
parameters: None,
}
}
}
impl From<DigestAlgorithm> for digest::Context {
fn from(alg: DigestAlgorithm) -> Self {
digest::Context::new(match alg {
DigestAlgorithm::Sha256 => &digest::SHA256,
DigestAlgorithm::Sha512 => &digest::SHA512,
})
}
}
impl DigestAlgorithm {
pub fn digester(&self) -> digest::Context {
digest::Context::from(*self)
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum SignatureAlgorithm {
Sha1Rsa,
Sha256Rsa,
Sha512Rsa,
RsaesPkcsV15,
EcdsaSha256,
EcdsaSha384,
Ed25519,
}
impl SignatureAlgorithm {
pub fn resolve_verification_algorithm(
&self,
key_algorithm: KeyAlgorithm,
) -> Result<&'static dyn signature::VerificationAlgorithm, Error> {
match key_algorithm {
KeyAlgorithm::Rsa => match self {
Self::Sha1Rsa => Ok(&signature::RSA_PKCS1_2048_8192_SHA1_FOR_LEGACY_USE_ONLY),
Self::Sha256Rsa => Ok(&signature::RSA_PKCS1_2048_8192_SHA256),
Self::Sha512Rsa => Ok(&signature::RSA_PKCS1_2048_8192_SHA512),
Self::RsaesPkcsV15 => {
Ok(&signature::RSA_PKCS1_1024_8192_SHA256_FOR_LEGACY_USE_ONLY)
}
alg => Err(Error::UnsupportedSignatureVerification(key_algorithm, *alg)),
},
KeyAlgorithm::Ed25519 => match self {
Self::Ed25519 => Ok(&signature::ED25519),
alg => Err(Error::UnsupportedSignatureVerification(key_algorithm, *alg)),
},
KeyAlgorithm::Ecdsa(curve) => match curve {
EcdsaCurve::Secp256r1 => match self {
Self::EcdsaSha256 => Ok(&signature::ECDSA_P256_SHA256_ASN1),
Self::EcdsaSha384 => Ok(&signature::ECDSA_P256_SHA384_ASN1),
alg => Err(Error::UnsupportedSignatureVerification(key_algorithm, *alg)),
},
EcdsaCurve::Secp384r1 => match self {
Self::EcdsaSha256 => Ok(&signature::ECDSA_P384_SHA256_ASN1),
Self::EcdsaSha384 => Ok(&signature::ECDSA_P384_SHA384_ASN1),
alg => Err(Error::UnsupportedSignatureVerification(key_algorithm, *alg)),
},
},
}
}
}
impl From<SignatureAlgorithm> for Oid {
fn from(alg: SignatureAlgorithm) -> Self {
Oid(match alg {
SignatureAlgorithm::Sha1Rsa => OID_SHA1_RSA.as_ref(),
SignatureAlgorithm::Sha256Rsa => OID_SHA256_RSA.as_ref(),
SignatureAlgorithm::Sha512Rsa => OID_SHA512_RSA.as_ref(),
SignatureAlgorithm::RsaesPkcsV15 => OID_RSAES_PKCS_V15.as_ref(),
SignatureAlgorithm::EcdsaSha256 => OID_ECDSA_SHA256.as_ref(),
SignatureAlgorithm::EcdsaSha384 => OID_ECDSA_SHA384.as_ref(),
SignatureAlgorithm::Ed25519 => OID_ED25519_SIGNATURE_ALGORITHM.as_ref(),
}
.into())
}
}
impl TryFrom<&Oid> for SignatureAlgorithm {
type Error = Error;
fn try_from(v: &Oid) -> Result<Self, Self::Error> {
if v == &OID_SHA1_RSA {
Ok(Self::Sha1Rsa)
} else if v == &OID_SHA256_RSA {
Ok(Self::Sha256Rsa)
} else if v == &OID_SHA512_RSA {
Ok(Self::Sha512Rsa)
} else if v == &OID_RSAES_PKCS_V15 {
Ok(Self::RsaesPkcsV15)
} else if v == &OID_ECDSA_SHA256 {
Ok(Self::EcdsaSha256)
} else if v == &OID_ECDSA_SHA384 {
Ok(Self::EcdsaSha384)
} else if v == &OID_ED25519_SIGNATURE_ALGORITHM {
Ok(Self::Ed25519)
} else {
Err(Error::UnknownSignatureAlgorithm(format!("{}", v)))
}
}
}
impl TryFrom<&AlgorithmIdentifier> for SignatureAlgorithm {
type Error = Error;
fn try_from(v: &AlgorithmIdentifier) -> Result<Self, Self::Error> {
Self::try_from(&v.algorithm)
}
}
impl From<SignatureAlgorithm> for AlgorithmIdentifier {
fn from(alg: SignatureAlgorithm) -> Self {
Self {
algorithm: alg.into(),
parameters: None,
}
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum EcdsaCurve {
Secp256r1,
Secp384r1,
}
impl EcdsaCurve {
pub fn all() -> &'static [Self] {
&[Self::Secp256r1, Self::Secp384r1]
}
pub fn as_signature_oid(&self) -> Oid {
Oid(match self {
Self::Secp256r1 => OID_EC_SECP256R1.as_ref().into(),
Self::Secp384r1 => OID_EC_SECP384R1.as_ref().into(),
})
}
}
impl TryFrom<&Oid> for EcdsaCurve {
type Error = Error;
fn try_from(v: &Oid) -> Result<Self, Self::Error> {
if v == &OID_EC_SECP256R1 {
Ok(Self::Secp256r1)
} else if v == &OID_EC_SECP384R1 {
Ok(Self::Secp384r1)
} else {
Err(Error::UnknownEllipticCurve(format!("{}", v)))
}
}
}
impl From<EcdsaCurve> for &'static signature::EcdsaSigningAlgorithm {
fn from(curve: EcdsaCurve) -> Self {
match curve {
EcdsaCurve::Secp256r1 => &signature::ECDSA_P256_SHA256_ASN1_SIGNING,
EcdsaCurve::Secp384r1 => &signature::ECDSA_P384_SHA384_ASN1_SIGNING,
}
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum KeyAlgorithm {
Rsa,
Ecdsa(EcdsaCurve),
Ed25519,
}
impl TryFrom<&Oid> for KeyAlgorithm {
type Error = Error;
fn try_from(v: &Oid) -> Result<Self, Self::Error> {
if v == &OID_RSA {
Ok(Self::Rsa)
} else if v == &OID_EC_PUBLIC_KEY {
Ok(Self::Ecdsa(EcdsaCurve::Secp384r1))
} else if v == &OID_ED25519_KEY_AGREEMENT || v == &OID_ED25519_SIGNATURE_ALGORITHM {
Ok(Self::Ed25519)
} else {
Err(Error::UnknownKeyAlgorithm(format!("{}", v)))
}
}
}
impl From<KeyAlgorithm> for Oid {
fn from(alg: KeyAlgorithm) -> Self {
Oid(match alg {
KeyAlgorithm::Rsa => OID_RSA.as_ref(),
KeyAlgorithm::Ecdsa(_) => OID_EC_PUBLIC_KEY.as_ref(),
KeyAlgorithm::Ed25519 => OID_ED25519_KEY_AGREEMENT.as_ref(),
}
.into())
}
}
impl TryFrom<&AlgorithmIdentifier> for KeyAlgorithm {
type Error = Error;
fn try_from(v: &AlgorithmIdentifier) -> Result<Self, Self::Error> {
let ka = Self::try_from(&v.algorithm)?;
let ka = if let Some(params) = &v.parameters {
match ka {
Self::Ecdsa(_) => {
let curve_oid = params.decode_oid()?;
let curve = EcdsaCurve::try_from(&curve_oid)?;
Ok(Self::Ecdsa(curve))
}
Self::Ed25519 => {
if params.as_slice() == [0x05, 0x00] {
Ok(ka)
} else {
Err(Error::UnhandledKeyAlgorithmParameters("on ED25519"))
}
}
Self::Rsa => {
if params.as_slice() == [0x05, 0x00] {
Ok(ka)
} else {
Err(Error::UnhandledKeyAlgorithmParameters("on RSA"))
}
}
}?
} else {
ka
};
Ok(ka)
}
}
impl From<KeyAlgorithm> for AlgorithmIdentifier {
fn from(alg: KeyAlgorithm) -> Self {
let parameters = match alg {
KeyAlgorithm::Ed25519 => None,
KeyAlgorithm::Rsa => None,
KeyAlgorithm::Ecdsa(curve) => {
Some(AlgorithmParameter::from_oid(curve.as_signature_oid()))
}
};
Self {
algorithm: alg.into(),
parameters,
}
}
}