use rama_core::error::BoxErrorExt as _;
use std::ops::Deref;
use aws_lc_rs::{
hmac,
hmac::{HMAC_SHA256, HMAC_SHA384, HMAC_SHA512},
signature::{
ECDSA_P256_SHA256_FIXED_SIGNING, ECDSA_P384_SHA384_FIXED_SIGNING,
ECDSA_P521_SHA512_FIXED_SIGNING, EcdsaSigningAlgorithm, EcdsaVerificationAlgorithm,
RSA_PKCS1_2048_8192_SHA256, RSA_PKCS1_2048_8192_SHA384, RSA_PKCS1_2048_8192_SHA512,
RSA_PKCS1_SHA256, RSA_PKCS1_SHA384, RSA_PKCS1_SHA512, RSA_PSS_2048_8192_SHA256,
RSA_PSS_2048_8192_SHA384, RSA_PSS_2048_8192_SHA512, RSA_PSS_SHA256, RSA_PSS_SHA384,
RSA_PSS_SHA512, RsaEncoding, VerificationAlgorithm,
},
};
use rama_core::error::BoxError;
use serde::{Deserialize, Serialize};
use crate::jose::JWKEllipticCurves;
#[derive(Debug, Serialize, Deserialize, Copy, Clone, PartialEq, Eq)]
#[serde(rename_all = "UPPERCASE")]
pub enum JWA {
HS256,
HS384,
HS512,
RS256,
RS384,
RS512,
ES256,
ES384,
ES512,
PS256,
PS384,
PS512,
}
impl From<JWKEllipticCurves> for JWA {
fn from(value: JWKEllipticCurves) -> Self {
match value {
JWKEllipticCurves::P256 => Self::ES256,
JWKEllipticCurves::P384 => Self::ES384,
JWKEllipticCurves::P521 => Self::ES512,
}
}
}
impl TryFrom<JWA> for JWKEllipticCurves {
type Error = BoxError;
fn try_from(value: JWA) -> Result<Self, Self::Error> {
match value {
JWA::ES256 => Ok(Self::P256),
JWA::ES384 => Ok(Self::P384),
JWA::ES512 => Ok(Self::P521),
JWA::HS256 | JWA::HS384 | JWA::HS512 => Err(BoxError::from_static_str(
"Hmac cannot be converted to elliptic curve",
)),
JWA::RS256 | JWA::RS384 | JWA::RS512 | JWA::PS256 | JWA::PS384 | JWA::PS512 => Err(
BoxError::from_static_str("RSA cannot be converted to elliptic curve"),
),
}
}
}
impl TryFrom<JWA> for &'static EcdsaSigningAlgorithm {
type Error = BoxError;
fn try_from(value: JWA) -> Result<Self, Self::Error> {
match value {
JWA::ES256 => Ok(&ECDSA_P256_SHA256_FIXED_SIGNING),
JWA::ES384 => Ok(&ECDSA_P384_SHA384_FIXED_SIGNING),
JWA::ES512 => Ok(&ECDSA_P521_SHA512_FIXED_SIGNING),
JWA::HS256 | JWA::HS384 | JWA::HS512 => Err(BoxError::from_static_str(
"Hmac cannot be converted to elliptic curve",
)),
JWA::RS256 | JWA::RS384 | JWA::RS512 | JWA::PS256 | JWA::PS384 | JWA::PS512 => Err(
BoxError::from_static_str("RSA cannot be converted to elliptic curve"),
),
}
}
}
impl TryFrom<JWA> for &'static EcdsaVerificationAlgorithm {
type Error = BoxError;
fn try_from(value: JWA) -> Result<Self, Self::Error> {
let signing_algo: &'static EcdsaSigningAlgorithm = value.try_into()?;
Ok(signing_algo.deref())
}
}
impl TryFrom<&'static EcdsaSigningAlgorithm> for JWA {
type Error = BoxError;
fn try_from(value: &'static EcdsaSigningAlgorithm) -> Result<Self, Self::Error> {
match value {
alg if *alg == ECDSA_P256_SHA256_FIXED_SIGNING => Ok(Self::ES256),
alg if *alg == ECDSA_P384_SHA384_FIXED_SIGNING => Ok(Self::ES384),
alg if *alg == ECDSA_P521_SHA512_FIXED_SIGNING => Ok(Self::ES512),
_ => Err(BoxError::from_static_str("cannot convert to jwa")),
}
}
}
impl TryFrom<JWA> for &'static hmac::Algorithm {
type Error = BoxError;
fn try_from(value: JWA) -> Result<Self, Self::Error> {
match value {
JWA::HS256 => Ok(&HMAC_SHA256),
JWA::HS384 => Ok(&HMAC_SHA384),
JWA::HS512 => Ok(&HMAC_SHA512),
_ => Err(BoxError::from_static_str(
"Non-Hmac algorithm cannot be converted to hmac types",
)),
}
}
}
impl TryFrom<JWA> for &'static dyn RsaEncoding {
type Error = BoxError;
fn try_from(value: JWA) -> Result<Self, Self::Error> {
match value {
JWA::RS256 => Ok(&RSA_PKCS1_SHA256),
JWA::RS384 => Ok(&RSA_PKCS1_SHA384),
JWA::RS512 => Ok(&RSA_PKCS1_SHA512),
JWA::PS256 => Ok(&RSA_PSS_SHA256),
JWA::PS384 => Ok(&RSA_PSS_SHA384),
JWA::PS512 => Ok(&RSA_PSS_SHA512),
_ => Err(BoxError::from_static_str(
"Non-RSA algorithm cannot be converted to rsa types",
)),
}
}
}
impl TryFrom<JWA> for &'static dyn VerificationAlgorithm {
type Error = BoxError;
fn try_from(value: JWA) -> Result<Self, Self::Error> {
match value {
JWA::RS256 => Ok(&RSA_PKCS1_2048_8192_SHA256),
JWA::RS384 => Ok(&RSA_PKCS1_2048_8192_SHA384),
JWA::RS512 => Ok(&RSA_PKCS1_2048_8192_SHA512),
JWA::PS256 => Ok(&RSA_PSS_2048_8192_SHA256),
JWA::PS384 => Ok(&RSA_PSS_2048_8192_SHA384),
JWA::PS512 => Ok(&RSA_PSS_2048_8192_SHA512),
JWA::ES256 | JWA::ES384 | JWA::ES512 => {
let signing_algo: &'static EcdsaSigningAlgorithm = value.try_into()?;
Ok(signing_algo.deref())
}
_ => Err(BoxError::from_static_str(
"Verification algorithm is not supported",
)),
}
}
}