use super::AlgorithmIdentifier;
use crate::{Error, ErrorCode, Result};
use structured_asn1::memory::Work;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ParameterSet {
MlDsa44,
MlDsa65,
MlDsa87,
}
impl ParameterSet {
#[must_use]
pub const fn public_key_len(self) -> usize {
match self {
Self::MlDsa44 => 1312,
Self::MlDsa65 => 1952,
Self::MlDsa87 => 2592,
}
}
#[must_use]
pub const fn signature_len(self) -> usize {
match self {
Self::MlDsa44 => 2420,
Self::MlDsa65 => 3309,
Self::MlDsa87 => 4627,
}
}
}
pub fn resolve<W: Work>(
identifier: AlgorithmIdentifier<'_>,
execution: &W,
) -> Result<Option<ParameterSet>> {
let bytes = identifier.algorithm().as_bytes();
identifier
.query_in(execution)
.charge_work(bytes.len() as u64 + 1)
.map_err(|reason| Error::resource(reason, identifier.field, identifier.offset()))?;
let value = from_octets(bytes);
if value.is_some() {
require_absent(identifier)?;
}
Ok(value)
}
pub(super) fn from_octets(bytes: &[u8]) -> Option<ParameterSet> {
match bytes {
[0x60, 0x86, 0x48, 1, 0x65, 3, 4, 3, last] => from_arc(*last),
_ => None,
}
}
pub(super) fn from_arc(last: u8) -> Option<ParameterSet> {
match last {
17 => Some(ParameterSet::MlDsa44),
18 => Some(ParameterSet::MlDsa65),
19 => Some(ParameterSet::MlDsa87),
_ => None,
}
}
pub(super) fn require_absent(identifier: AlgorithmIdentifier<'_>) -> Result<()> {
if let Some(parameters) = identifier.parameters_nested() {
return Err(Error::new(
ErrorCode::MalformedValue,
identifier.field,
parameters.offset(),
));
}
Ok(())
}