use alloc::string::ToString;
pub mod extension_module;
use crate::ieee1609dot2::{
Certificate, CertificateId, HashedData, Ieee1609Dot2Content, Ieee1609Dot2Data, RecipientInfo,
SignerIdentifier,
};
use rasn::prelude::*;
pub const ETSI_TS103097_MODULE_OID: &Oid = Oid::const_new(&[0, 4, 0, 5, 5, 103_097, 1, 3, 1]);
#[derive(Debug, Clone, AsnType, Encode, Decode, PartialEq, Eq)]
#[rasn(delegate)]
pub struct EtsiTs103097Certificate(Certificate);
impl core::ops::Deref for EtsiTs103097Certificate {
type Target = Certificate;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl TryFrom<Certificate> for EtsiTs103097Certificate {
type Error = rasn::error::InnerSubtypeConstraintError;
fn try_from(cert: Certificate) -> Result<Self, Self::Error> {
let etsi_cert = EtsiTs103097Certificate(cert);
etsi_cert.validate_components()
}
}
impl InnerSubtypeConstraint for EtsiTs103097Certificate {
fn validate_and_decode_containing(
self,
_: Option<rasn::Codec>,
) -> Result<Self, rasn::error::InnerSubtypeConstraintError> {
let tbs = &self.0.to_be_signed;
let id = &tbs.id;
if !matches!(id, CertificateId::Name(_) | CertificateId::None(_)) {
return Err(
rasn::error::InnerSubtypeConstraintError::InvalidComponentValue {
component_path: "EtsiTs103097Certificate.toBeSignedCertificate.certificateId",
component_name: "CertificateId",
details: "Only CertificateId::Name or CertificateId::None is permitted"
.to_string(),
},
);
}
if tbs.cert_request_permissions.is_some() {
return Err(
rasn::error::InnerSubtypeConstraintError::UnexpectedComponentPresent {
component_path: "EtsiTs103097Certificate.toBeSignedCertificate",
component_name: "certRequestPermissions",
},
);
}
if tbs.can_request_rollover.is_some() {
return Err(
rasn::error::InnerSubtypeConstraintError::UnexpectedComponentPresent {
component_path: "EtsiTs103097Certificate.toBeSignedCertificate",
component_name: "canRequestRollover",
},
);
}
Ok(self)
}
}
#[derive(Debug, Clone, AsnType, Encode, Decode, PartialEq, Eq)]
#[rasn(delegate)]
pub struct EtsiTs103097Data(Ieee1609Dot2Data);
impl core::ops::Deref for EtsiTs103097Data {
type Target = Ieee1609Dot2Data;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl TryFrom<Ieee1609Dot2Data> for EtsiTs103097Data {
type Error = rasn::error::InnerSubtypeConstraintError;
fn try_from(data: Ieee1609Dot2Data) -> Result<Self, Self::Error> {
let etsi_data = EtsiTs103097Data(data);
etsi_data.validate_components()
}
}
impl InnerSubtypeConstraint for EtsiTs103097Data {
fn validate_and_decode_containing(
self,
_: Option<rasn::Codec>,
) -> Result<Self, rasn::error::InnerSubtypeConstraintError> {
match &self.0.content {
Ieee1609Dot2Content::SignedData(signed_data) => {
let tbs_data = &signed_data.tbs_data;
let header_info = &tbs_data.header_info;
if header_info.generation_time.is_none() {
return Err(
rasn::error::InnerSubtypeConstraintError::MissingRequiredComponent {
component_path: "EtsiTs103097Data.content.signedData.tbsData.headerInfo",
components: &["generationTime"],
},
);
}
if header_info.p2pcd_learning_request.is_some() {
return Err(
rasn::error::InnerSubtypeConstraintError::UnexpectedComponentPresent {
component_path: "EtsiTs103097Data.content.signedData.tbsData.headerInfo",
component_name: "p2pcdLearningRequest",
},
);
}
if header_info.missing_crl_identifier.is_some() {
return Err(
rasn::error::InnerSubtypeConstraintError::UnexpectedComponentPresent {
component_path: "EtsiTs103097Data.content.signedData.tbsData.headerInfo",
component_name: "missingCrlIdentifier",
},
);
}
let signer = &signed_data.signer;
match signer {
SignerIdentifier::Certificate(cert) => {
if cert.len() != 1 {
return Err(
rasn::error::InnerSubtypeConstraintError::InvalidComponentSize {
component_path: "EtsiTs103097Data.content.signedData.signer",
component_name: "certificate",
details: "Exactly one certificate is required".to_string(),
},
);
}
}
_ => {
return Err(
rasn::error::InnerSubtypeConstraintError::InvalidComponentValue {
component_path: "EtsiTs103097Data.content.signedData.signer",
component_name: "signer",
details: "Only Certificate variant is allowed".to_string(),
},
);
}
}
}
Ieee1609Dot2Content::EncryptedData(encrypted_data) => {
let recipients = &encrypted_data.recipients;
for (index, recipient) in recipients.iter().enumerate() {
if matches!(
recipient,
RecipientInfo::PskRecipInfo(_)
| RecipientInfo::SymmRecipInfo(_)
| RecipientInfo::RekRecipInfo(_)
) {
return Err(
rasn::error::InnerSubtypeConstraintError::InvalidComponentValue {
component_path: "EtsiTs103097Data.content.encryptedData.recipients",
component_name: "RecipientInfo",
details: alloc::format!(
"PskRecipInfo, SymmRecipInfo or RekRecipInfo is not allowed, occured in index {index}"
),
},
);
}
}
}
_ => {
return Err(
rasn::error::InnerSubtypeConstraintError::MissingRequiredComponent {
component_path: "EtsiTs103097Data.content",
components: &["signedData", "encryptedData"],
},
);
}
};
Ok(self)
}
}
#[derive(Debug, Clone, Encode, Decode, AsnType, PartialEq, Eq)]
#[rasn(delegate)]
pub struct EtsiTs103097DataUnsecured<T: rasn::Decode>(
EtsiTs103097Data,
core::marker::PhantomData<T>,
);
impl<T: rasn::Decode> core::ops::Deref for EtsiTs103097DataUnsecured<T> {
type Target = EtsiTs103097Data;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T: rasn::Decode> TryFrom<EtsiTs103097Data> for EtsiTs103097DataUnsecured<T> {
type Error = rasn::error::InnerSubtypeConstraintError;
fn try_from(data: EtsiTs103097Data) -> Result<Self, Self::Error> {
let etsi_data = EtsiTs103097DataUnsecured(data, core::marker::PhantomData);
etsi_data.validate_components()
}
}
impl<T: rasn::Decode> InnerSubtypeConstraint for EtsiTs103097DataUnsecured<T> {
fn validate_and_decode_containing(
self,
decode_containing_with: Option<rasn::Codec>,
) -> Result<Self, rasn::error::InnerSubtypeConstraintError> {
match &self.0.content {
Ieee1609Dot2Content::UnsecuredData(unsecured) => {
if let Some(codec) = decode_containing_with {
let decoded = codec.decode_from_binary::<T>(unsecured);
match decoded {
Ok(_) => Ok(self),
Err(err) => Err(
rasn::error::InnerSubtypeConstraintError::InvalidInnerContaining {
expected: "Ieee1609Dot2Content::UnsecuredData::T",
err,
},
),
}
} else {
Ok(self)
}
}
_ => Err(
rasn::error::InnerSubtypeConstraintError::InvalidComponentValue {
component_path: "EtsiTs103097DataUnsecured.content",
component_name: "unsecuredData",
details: "Only UnsecuredData is allowed".to_string(),
},
),
}
}
}
#[derive(Debug, Clone, AsnType, Encode, Decode, PartialEq, Eq)]
#[rasn(delegate)]
pub struct EtsiTs103097DataSigned<T: rasn::Decode>(EtsiTs103097Data, core::marker::PhantomData<T>);
impl<T: rasn::Decode> core::ops::Deref for EtsiTs103097DataSigned<T> {
type Target = EtsiTs103097Data;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T: rasn::Decode> TryFrom<EtsiTs103097Data> for EtsiTs103097DataSigned<T> {
type Error = rasn::error::InnerSubtypeConstraintError;
fn try_from(data: EtsiTs103097Data) -> Result<Self, Self::Error> {
let etsi_data = EtsiTs103097DataSigned(data, core::marker::PhantomData);
etsi_data.validate_components()
}
}
impl<T: rasn::Decode> InnerSubtypeConstraint for EtsiTs103097DataSigned<T> {
fn validate_and_decode_containing(
self,
decode_containing_with: Option<rasn::Codec>,
) -> Result<Self, rasn::error::InnerSubtypeConstraintError> {
match &self.0.content {
Ieee1609Dot2Content::SignedData(signed_data) => {
let tbs_payload = &signed_data.tbs_data.payload.data;
match tbs_payload {
Some(data) => match &data.content {
Ieee1609Dot2Content::UnsecuredData(unsecured) => {
if let Some(codec) = decode_containing_with {
let decoded = codec.decode_from_binary::<T>(unsecured);
match decoded {
Ok(_) => Ok(self),
Err(err) => Err(
rasn::error::InnerSubtypeConstraintError::InvalidInnerContaining {
expected: "Ieee1609Dot2Content::UnsecuredData::T",
err
}
),
}
} else {
Ok(self)
}
}
_ => Err(
rasn::error::InnerSubtypeConstraintError::InvalidComponentVariant {
component_path: "EtsiTs103097Data.content.signedData.tbsData.payload.data.content",
component_type: "Ieee1609Dot2Content",
details: "Only UnsecuredData is allowed".to_string(),
},
),
},
_ => Err(
rasn::error::InnerSubtypeConstraintError::MissingRequiredComponent {
component_path: "EtsiTs103097DataSigned.content.signedData.tbsData.payload",
components: &["Data payload field must be present."],
},
),
}
}
_ => Err(
rasn::error::InnerSubtypeConstraintError::InvalidComponentVariant {
component_path: "EtsiTs103097DataSigned.content",
component_type: "Ieee1609Dot2Content",
details: "Only SignedData is allowed".to_string(),
},
),
}
}
}
#[derive(Debug, Clone, AsnType, Encode, Decode, PartialEq, Eq)]
#[rasn(delegate)]
pub struct EtsiTs103097DataSignedExternalPayload<T: rasn::Decode>(
EtsiTs103097Data,
core::marker::PhantomData<T>,
);
impl<T: rasn::Decode> core::ops::Deref for EtsiTs103097DataSignedExternalPayload<T> {
type Target = EtsiTs103097Data;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T: rasn::Decode> TryFrom<EtsiTs103097Data> for EtsiTs103097DataSignedExternalPayload<T> {
type Error = rasn::error::InnerSubtypeConstraintError;
fn try_from(data: EtsiTs103097Data) -> Result<Self, Self::Error> {
let etsi_data = EtsiTs103097DataSignedExternalPayload(data, core::marker::PhantomData);
etsi_data.validate_components()
}
}
impl<T: rasn::Decode> InnerSubtypeConstraint for EtsiTs103097DataSignedExternalPayload<T> {
fn validate_and_decode_containing(
self,
_: Option<rasn::Codec>,
) -> Result<Self, rasn::error::InnerSubtypeConstraintError> {
match &self.0.content {
Ieee1609Dot2Content::SignedData(signed_data) => {
let tbs_payload = &signed_data.tbs_data.payload;
match &tbs_payload.ext_data_hash {
Some(ext_hash) => {
if !matches!(ext_hash, HashedData::Sha256HashedData(..)) {
return Err(
rasn::error::InnerSubtypeConstraintError::InvalidComponentVariant {
component_path: "EtsiTs103097DataSignedExternalPayload.content.signedData.tbsData.payload.extDataHash",
component_type: "HashedData",
details: "Only SHA-256 hashed data is allowed".to_string(),
},
);
}
Ok(self)
}
None => Err(
rasn::error::InnerSubtypeConstraintError::MissingRequiredComponent {
component_path: "EtsiTs103097DataSignedExternalPayload.content.signedData.tbsData.payload",
components: &["extDataHash"],
},
),
}
}
_ => Err(
rasn::error::InnerSubtypeConstraintError::InvalidComponentVariant {
component_path: "EtsiTs103097DataSignedExternalPayload.content",
component_type: "Ieee1609Dot2Content",
details: "Only SignedData is allowed".to_string(),
},
),
}
}
}
#[derive(Debug, Clone, AsnType, Encode, Decode, PartialEq, Eq)]
#[rasn(delegate)]
pub struct EtsiTs103097DataEncrypted<T: rasn::Decode>(
EtsiTs103097Data,
core::marker::PhantomData<T>,
);
impl<T: rasn::Decode> core::ops::Deref for EtsiTs103097DataEncrypted<T> {
type Target = EtsiTs103097Data;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T: rasn::Decode> TryFrom<EtsiTs103097Data> for EtsiTs103097DataEncrypted<T> {
type Error = rasn::error::InnerSubtypeConstraintError;
fn try_from(data: EtsiTs103097Data) -> Result<Self, Self::Error> {
let etsi_data = EtsiTs103097DataEncrypted(data, core::marker::PhantomData);
etsi_data.validate_components()
}
}
impl<T: rasn::Decode> InnerSubtypeConstraint for EtsiTs103097DataEncrypted<T> {
fn validate_and_decode_containing(
self,
decode_containing_with: Option<rasn::Codec>,
) -> Result<Self, rasn::error::InnerSubtypeConstraintError> {
match &self.0.content {
Ieee1609Dot2Content::EncryptedData(encrypted_data) => {
match &encrypted_data.ciphertext {
crate::ieee1609dot2::SymmetricCiphertext::Aes128ccm(ciphertext) => {
if let Some(codec) = decode_containing_with {
if codec
.decode_from_binary::<T>(&ciphertext.ccm_ciphertext)
.is_ok()
{
return Ok(self);
} else {
return Err(
rasn::error::InnerSubtypeConstraintError::InvalidComponentValue {
component_path:
"EtsiTs103097DataEncrypted.content.encryptedData.ciphertext",
component_name: "ccmCiphertext",
details: "Failed to decode ccmCiphertext as the specified type"
.to_string(),
},
);
}
}
Ok(self)
}
_ => Err(
rasn::error::InnerSubtypeConstraintError::InvalidComponentVariant {
component_path: "EtsiTs103097DataEncrypted.content.encryptedData.ciphertext",
component_type: "SymmetricCiphertext",
details: "Only aes128ccm is allowed".to_string(),
},
),
}
}
_ => Err(
rasn::error::InnerSubtypeConstraintError::InvalidComponentVariant {
component_path: "EtsiTs103097DataEncrypted.content",
component_type: "Ieee1609Dot2Content",
details: "Only EncryptedData is allowed".to_string(),
},
),
}
}
}
#[derive(Debug, Clone, AsnType, Encode, Decode, PartialEq, Eq)]
#[rasn(delegate)]
pub struct EtsiTs103097DataSignedAndEncrypted<T: rasn::Decode>(
EtsiTs103097DataEncrypted<EtsiTs103097DataSigned<T>>,
);
impl<T: rasn::Decode> core::ops::Deref for EtsiTs103097DataSignedAndEncrypted<T> {
type Target = EtsiTs103097DataEncrypted<EtsiTs103097DataSigned<T>>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T: rasn::Decode> TryFrom<EtsiTs103097DataEncrypted<EtsiTs103097DataSigned<T>>>
for EtsiTs103097DataSignedAndEncrypted<T>
{
type Error = rasn::error::InnerSubtypeConstraintError;
fn try_from(
data: EtsiTs103097DataEncrypted<EtsiTs103097DataSigned<T>>,
) -> Result<Self, Self::Error> {
let etsi_data = EtsiTs103097DataSignedAndEncrypted(data);
etsi_data.validate_components()
}
}
impl<T: rasn::Decode> InnerSubtypeConstraint for EtsiTs103097DataSignedAndEncrypted<T> {
fn validate_and_decode_containing(
self,
codec: Option<rasn::Codec>,
) -> Result<Self, rasn::error::InnerSubtypeConstraintError> {
Ok(Self(self.0.validate_and_decode_containing(codec)?))
}
}
#[derive(Debug, Clone, AsnType, Encode, Decode, PartialEq, Eq)]
#[rasn(delegate)]
pub struct EtsiTs103097DataEncryptedUnicast<T: rasn::Decode>(
EtsiTs103097DataEncrypted<EtsiTs103097DataUnsecured<T>>,
);
impl<T: rasn::Decode> core::ops::Deref for EtsiTs103097DataEncryptedUnicast<T> {
type Target = EtsiTs103097DataEncrypted<EtsiTs103097DataUnsecured<T>>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T: rasn::Decode> TryFrom<EtsiTs103097DataEncrypted<EtsiTs103097DataUnsecured<T>>>
for EtsiTs103097DataEncryptedUnicast<T>
{
type Error = rasn::error::InnerSubtypeConstraintError;
fn try_from(
data: EtsiTs103097DataEncrypted<EtsiTs103097DataUnsecured<T>>,
) -> Result<Self, Self::Error> {
let etsi_data = EtsiTs103097DataEncryptedUnicast(data);
etsi_data.validate_components()
}
}
impl<T: rasn::Decode> InnerSubtypeConstraint for EtsiTs103097DataEncryptedUnicast<T> {
fn validate_and_decode_containing(
self,
codec: Option<rasn::Codec>,
) -> Result<Self, rasn::error::InnerSubtypeConstraintError> {
let encrypted = self.0.validate_and_decode_containing(codec)?;
match &encrypted.0.content {
Ieee1609Dot2Content::EncryptedData(encrypted_data) => {
if encrypted_data.recipients.len() != 1 {
return Err(
rasn::error::InnerSubtypeConstraintError::InvalidComponentSize {
component_path: "EtsiTs103097DataEncryptedUnicast.content.encryptedData",
component_name: "recipients",
details: "Exactly one recipient is required".to_string(),
},
);
}
Ok(Self(encrypted))
}
_ => Err(
rasn::error::InnerSubtypeConstraintError::InvalidComponentVariant {
component_path: "EtsiTs103097DataEncryptedUnicast.content",
component_type: "Ieee1609Dot2Content",
details: "Only EncryptedData is allowed".to_string(),
},
),
}
}
}
#[derive(Debug, Clone, AsnType, Encode, Decode, PartialEq, Eq)]
#[rasn(delegate)]
pub struct EtsiTs103097DataSignedAndEncryptedUnicast<T: rasn::Decode>(
EtsiTs103097DataEncrypted<EtsiTs103097DataSigned<T>>,
);
impl<T: rasn::Decode> core::ops::Deref for EtsiTs103097DataSignedAndEncryptedUnicast<T> {
type Target = EtsiTs103097DataEncrypted<EtsiTs103097DataSigned<T>>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T: rasn::Decode> TryFrom<EtsiTs103097DataEncrypted<EtsiTs103097DataSigned<T>>>
for EtsiTs103097DataSignedAndEncryptedUnicast<T>
{
type Error = rasn::error::InnerSubtypeConstraintError;
fn try_from(
data: EtsiTs103097DataEncrypted<EtsiTs103097DataSigned<T>>,
) -> Result<Self, Self::Error> {
let etsi_data = EtsiTs103097DataSignedAndEncryptedUnicast(data);
etsi_data.validate_components()
}
}
impl<T: rasn::Decode> InnerSubtypeConstraint for EtsiTs103097DataSignedAndEncryptedUnicast<T> {
fn validate_and_decode_containing(
self,
codec: Option<rasn::Codec>,
) -> Result<Self, rasn::error::InnerSubtypeConstraintError> {
let encrypted = self.0.validate_and_decode_containing(codec)?;
match &encrypted.0.content {
Ieee1609Dot2Content::EncryptedData(encrypted_data) => {
if encrypted_data.recipients.len() != 1 {
return Err(
rasn::error::InnerSubtypeConstraintError::InvalidComponentSize {
component_path: "EtsiTs103097DataSignedAndEncryptedUnicast.content.encryptedData",
component_name: "recipients",
details: "Exactly one recipient is required".to_string(),
},
);
}
Ok(Self(encrypted))
}
_ => Err(
rasn::error::InnerSubtypeConstraintError::InvalidComponentVariant {
component_path: "EtsiTs103097DataSignedAndEncryptedUnicast.content",
component_type: "Ieee1609Dot2Content",
details: "Only EncryptedData is allowed".to_string(),
},
),
}
}
}