use der::oid::ObjectIdentifier;
use super::{CoverageError, JarError, KeyKind, Scheme, SignatureAlgorithm, SignatureError};
use crate::archive::ZipError;
use crate::types::ApiLevel;
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
pub enum KeyError {
#[error("malformed PEM: {0}")]
Pem(#[from] pem_rfc7468::Error),
#[error("no private key found")]
MissingPrivateKey,
#[error("no certificate found")]
MissingCertificate,
#[error("the private key is encrypted; supply its password")]
PasswordRequired,
#[error("encrypted private keys require the `keystore` feature")]
EncryptionDisabled,
#[error("the password is incorrect")]
WrongPassword,
#[error("PKCS#8 private key: {0}")]
Pkcs8(#[from] pkcs8::Error),
#[error("malformed PKCS#1 RSA private key: {0}")]
Pkcs1(#[from] pkcs1::Error),
#[error("malformed or unsupported EC private key (P-256 and P-384 are supported)")]
InvalidEcKey,
#[error("malformed public key: {0}")]
PublicKey(#[from] spki::Error),
#[error("invalid RSA key: {0}")]
Rsa(#[from] rsa::Error),
#[error("{bits}-bit RSA keys are too weak to sign with; use at least {min} bits")]
RsaKeyTooSmall { bits: u32, min: u32 },
#[error("unsupported key algorithm {oid}")]
UnsupportedAlgorithm { oid: ObjectIdentifier },
#[error("unsupported elliptic curve {oid}")]
UnsupportedCurve { oid: ObjectIdentifier },
#[error("malformed X.509 certificate: {0}")]
Certificate(#[source] der::Error),
#[error("the private key does not match the certificate")]
CertificateMismatch,
#[error("{algorithm} cannot be used with a {key} key")]
AlgorithmMismatch { algorithm: SignatureAlgorithm, key: KeyKind },
#[error("signing failed: {0}")]
Signing(#[source] signature::Error),
#[error("encoding a signature block failed: {0}")]
Encoding(#[source] der::Error),
#[cfg(feature = "keystore")]
#[error("JKS keystore: {0}")]
Jks(#[from] jks::KeyStoreError),
#[cfg(feature = "keystore")]
#[error("PKCS#12 keystore: {0}")]
Pkcs12(#[from] p12_keystore::error::Error),
#[error("the keystore parser rejected malformed input")]
MalformedKeystore,
#[error("the keystore has no entry {alias:?}")]
UnknownAlias { alias: String },
#[error("keystore entry {alias:?} is not a private key")]
NotAPrivateKey { alias: String },
#[error("the keystore has {count} private keys; name one")]
AmbiguousAlias { count: usize },
}
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
pub enum SignError {
#[error(transparent)]
Coverage(#[from] CoverageError),
#[error("APK Signature Scheme v3 supports one signer; {count} were given")]
MultipleV3Signers { count: usize },
#[error("Android {min_sdk} cannot verify JAR signatures made with EC keys (API 18+ required)")]
EcdsaJarRequiresApi18 { min_sdk: ApiLevel },
#[error("the APK has no AndroidManifest.xml; set the minimum SDK explicitly")]
UnknownMinSdk,
#[error(transparent)]
Key(#[from] KeyError),
#[error(transparent)]
Zip(#[from] ZipError),
#[error("signed APK failed its self-check: {0}")]
SelfCheck(#[source] Box<VerifyError>),
}
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
pub enum VerifyError {
#[error("the APK is not signed")]
Unsigned,
#[error(transparent)]
Zip(#[from] ZipError),
#[error("the APK signing block's size fields do not match its length")]
MalformedBlock,
#[error("APK signing block entry at offset {offset:#x} has invalid length {len}")]
InvalidBlockPair { offset: u64, len: u64 },
#[error("malformed {scheme} block near offset {offset:#x}")]
MalformedScheme { scheme: Scheme, offset: u64 },
#[error("{scheme} block has no signers")]
NoSigners { scheme: Scheme },
#[error("{scheme} signer {signer} has no signatures")]
NoSignatures { scheme: Scheme, signer: usize },
#[error("{scheme} signer {signer} uses no supported algorithm (IDs {ids:x?})")]
NoSupportedAlgorithm { scheme: Scheme, signer: usize, ids: Vec<u32> },
#[error("{scheme} signer {signer}: {algorithm} signature: {source}")]
BadSignature { scheme: Scheme, signer: usize, algorithm: SignatureAlgorithm, source: SignatureError },
#[error("{scheme} signer {signer}: digests and signatures name different algorithms")]
AlgorithmListMismatch { scheme: Scheme, signer: usize },
#[error("{scheme} signer {signer} has no certificates")]
NoCertificates { scheme: Scheme, signer: usize },
#[error("{scheme} signer {signer}: public key does not match the certificate")]
PublicKeyMismatch { scheme: Scheme, signer: usize },
#[error("{scheme} signer {signer}: SDK range differs between signed and unsigned data")]
SdkRangeMismatch { scheme: Scheme, signer: usize },
#[error("{scheme} signer {signer}: SDK range {min}..={max} is empty")]
InvalidSdkRange { scheme: Scheme, signer: usize, min: u32, max: u32 },
#[error("{scheme} signers do not cover API level {sdk} exactly once")]
SdkCoverage { scheme: Scheme, sdk: u32 },
#[error("{scheme} signer {signer}: no digest for {algorithm}")]
MissingDigest { scheme: Scheme, signer: usize, algorithm: SignatureAlgorithm },
#[error("{scheme} signer {signer}: the APK's contents do not match the signed digest")]
DigestMismatch { scheme: Scheme, signer: usize },
#[error("{protected_by} declares a {scheme} signature that is missing (stripping attack?)")]
StrippedScheme { scheme: Scheme, protected_by: Scheme },
#[error("{first} and {second} were signed by different signers")]
SignerMismatch { first: Scheme, second: Scheme },
#[error("the APK uses signing key rotation, which this crate cannot verify")]
KeyRotationUnsupported,
#[error("the APK's signatures do not cover the releases it supports: {0}")]
Coverage(#[from] CoverageError),
#[error(transparent)]
Key(#[from] KeyError),
#[error(transparent)]
Jar(#[from] JarError),
}