use super::{
ATTESTATION_PATH_SEGMENT, DERIVATION_NAMESPACE, ROLE_ATTESTATION_KEY_ID_V1, ROOT_PATH_SEGMENT,
SHARD_PATH_SEGMENT, delegated::canonical::public_key_hash,
};
use crate::{
InternalError,
cdk::types::Principal,
dto::auth::{AttestationKey, AttestationKeyStatus},
ops::{
auth::AuthValidationError,
config::ConfigOps,
ic::ecdsa::EcdsaOps,
storage::{auth::AuthStateOps, state::subnet::SubnetStateOps},
},
};
use std::cmp::Reverse;
pub(super) fn attestation_keys_sorted(key_name: &str) -> Vec<AttestationKey> {
let mut keys = AuthStateOps::attestation_keys(key_name);
keys.sort_by_key(|entry| {
let status_rank = match entry.status {
AttestationKeyStatus::Current => 0u8,
AttestationKeyStatus::Previous => 1u8,
};
(status_rank, Reverse(entry.key_id))
});
keys
}
pub(super) fn delegated_tokens_key_name() -> Result<String, InternalError> {
let cfg = ConfigOps::delegated_tokens_config()?;
if cfg.ecdsa_key_name.trim().is_empty() {
return Err(AuthValidationError::EcdsaKeyNameMissing.into());
}
Ok(cfg.ecdsa_key_name)
}
pub(super) fn attestation_key_name() -> Result<String, InternalError> {
let cfg = ConfigOps::role_attestation_config()?;
if cfg.ecdsa_key_name.trim().is_empty() {
return Err(AuthValidationError::AttestationKeyNameMissing.into());
}
Ok(cfg.ecdsa_key_name)
}
pub(super) fn root_derivation_path() -> Vec<Vec<u8>> {
vec![DERIVATION_NAMESPACE.to_vec(), ROOT_PATH_SEGMENT.to_vec()]
}
pub(super) fn shard_derivation_path(shard_pid: Principal) -> Vec<Vec<u8>> {
vec![
DERIVATION_NAMESPACE.to_vec(),
SHARD_PATH_SEGMENT.to_vec(),
shard_pid.as_slice().to_vec(),
]
}
pub(super) fn attestation_derivation_path() -> Vec<Vec<u8>> {
vec![
DERIVATION_NAMESPACE.to_vec(),
ATTESTATION_PATH_SEGMENT.to_vec(),
ROOT_PATH_SEGMENT.to_vec(),
]
}
pub(super) async fn ensure_attestation_key_cached(
key_name: &str,
root_pid: Principal,
now_secs: u64,
) -> Result<(), InternalError> {
if AuthStateOps::attestation_public_key_sec1(ROLE_ATTESTATION_KEY_ID_V1, key_name).is_some() {
return Ok(());
}
let public_key =
EcdsaOps::public_key_sec1(key_name, attestation_derivation_path(), root_pid).await?;
AuthStateOps::upsert_attestation_key(AttestationKey {
key_id: ROLE_ATTESTATION_KEY_ID_V1,
key_hash: public_key_hash(&public_key),
key_name: key_name.to_string(),
public_key,
status: AttestationKeyStatus::Current,
valid_from: Some(now_secs),
valid_until: None,
});
Ok(())
}
pub(super) async fn ensure_root_public_key_published(
key_name: &str,
root_pid: Principal,
) -> Result<(), InternalError> {
if SubnetStateOps::delegated_root_public_key(key_name).is_none() {
let root_pk = EcdsaOps::public_key_sec1(key_name, root_derivation_path(), root_pid).await?;
SubnetStateOps::set_delegated_root_public_key(key_name.to_string(), root_pk);
}
Ok(())
}