DuckDetector flagged two issues: 1. Oversized challenge accepted — 256-byte attestation challenge should return INVALID_INPUT_LENGTH (-21) like real KeyMint. Added early check in handleGenerateKey before any path decision. 2. Issuer/subject chain mismatch — rcgen's HashMap loses DN attribute ordering and converts PrintableString to UTF8String, producing different DER bytes. Replaced rcgen with manual DER assembly that injects raw keybox issuer_dn_der bytes directly. Verified on device: TX_ID 315 rejects 256-byte challenge, TX_ID 501 generates valid 4-cert chain with correct issuer linkage.
76 lines
2.5 KiB
Rust
76 lines
2.5 KiB
Rust
use std::fmt;
|
|
|
|
#[derive(Debug)]
|
|
pub enum CertGenError {
|
|
Jni(String),
|
|
NullParam(&'static str),
|
|
UnsupportedAlgorithm(i32),
|
|
UnsupportedEcCurve(i32),
|
|
KeyGenFailed(String),
|
|
CertBuildFailed(String),
|
|
KeyboxParseFailed(String),
|
|
AttestationBuildFailed(String),
|
|
DerError(der::Error),
|
|
EmptyKeyboxChain,
|
|
ChallengeTooLong(usize),
|
|
InvalidParameter(String),
|
|
SigningFailed(String),
|
|
SerializationFailed(String),
|
|
}
|
|
|
|
impl fmt::Display for CertGenError {
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
match self {
|
|
Self::Jni(msg) => write!(f, "JNI error: {}", msg),
|
|
Self::NullParam(name) => write!(f, "null required parameter: {}", name),
|
|
Self::UnsupportedAlgorithm(v) => write!(f, "unsupported algorithm: {}", v),
|
|
Self::UnsupportedEcCurve(v) => write!(f, "unsupported EC curve: {}", v),
|
|
Self::KeyGenFailed(msg) => write!(f, "key generation failed: {}", msg),
|
|
Self::CertBuildFailed(msg) => write!(f, "certificate build failed: {}", msg),
|
|
Self::KeyboxParseFailed(msg) => write!(f, "keybox parse failed: {}", msg),
|
|
Self::AttestationBuildFailed(msg) => write!(f, "attestation build failed: {}", msg),
|
|
Self::DerError(e) => write!(f, "DER error: {}", e),
|
|
Self::EmptyKeyboxChain => write!(f, "keybox certificate chain is empty"),
|
|
Self::ChallengeTooLong(len) => write!(f, "attestation challenge too long: {} bytes (max 128)", len),
|
|
Self::InvalidParameter(msg) => write!(f, "invalid parameter: {}", msg),
|
|
Self::SigningFailed(msg) => write!(f, "signing failed: {}", msg),
|
|
Self::SerializationFailed(msg) => write!(f, "serialization failed: {}", msg),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl std::error::Error for CertGenError {}
|
|
|
|
impl From<jni::errors::Error> for CertGenError {
|
|
fn from(e: jni::errors::Error) -> Self {
|
|
Self::Jni(e.to_string())
|
|
}
|
|
}
|
|
|
|
impl From<der::Error> for CertGenError {
|
|
fn from(e: der::Error) -> Self {
|
|
Self::DerError(e)
|
|
}
|
|
}
|
|
|
|
impl From<ring::error::Unspecified> for CertGenError {
|
|
fn from(e: ring::error::Unspecified) -> Self {
|
|
Self::KeyGenFailed(e.to_string())
|
|
}
|
|
}
|
|
|
|
impl From<ring::error::KeyRejected> for CertGenError {
|
|
fn from(e: ring::error::KeyRejected) -> Self {
|
|
Self::KeyGenFailed(e.to_string())
|
|
}
|
|
}
|
|
|
|
impl From<rsa::Error> for CertGenError {
|
|
fn from(e: rsa::Error) -> Self {
|
|
Self::KeyGenFailed(e.to_string())
|
|
}
|
|
}
|
|
|
|
|
|
pub type Result<T> = std::result::Result<T, CertGenError>;
|