#[non_exhaustive]pub enum Error {
Show 16 variants
DevicePublicKeyInvalid {
reason: &'static str,
},
DeviceSignatureInvalid {
reason: &'static str,
},
UnsupportedPlatform {
platform: &'static str,
},
HardwareUnavailable {
reason: String,
},
Hardware {
operation: &'static str,
code: i32,
},
KeyNotFound {
label: String,
},
Jni {
operation: &'static str,
detail: String,
},
KeyAlreadyExists {
label: String,
},
InvalidDigestLength {
expected: usize,
actual: usize,
},
InvalidKeyLabel {
reason: &'static str,
},
InvalidPublicKey {
reason: &'static str,
},
InvalidSignatureLength {
expected: usize,
actual: usize,
},
InvalidWrappedKey {
reason: &'static str,
code: i32,
},
InvalidMasterKey {
reason: &'static str,
},
KeyNotExportable {
reason: &'static str,
},
RandomnessUnavailable,
}Expand description
Failures that can arise from device identity handling and the platform key store.
Variants (Non-exhaustive)§
This enum is marked as non-exhaustive
DevicePublicKeyInvalid
The device public key is not a valid P-256 SEC1 uncompressed point.
Public keys arrive as external input (QR codes, the network), so this is a normal rejection path rather than an internal inconsistency.
DeviceSignatureInvalid
The device signature is malformed, or verification failed.
§Why the two cases are merged
The caller’s response is identical (reject this authentication), and distinguishing them would give an attacker a small oracle: the difference between “malformed” and “did not verify” could be probed.
Fields
UnsupportedPlatform
This platform has no backend implementation yet.
Do not treat it as a signal that falling back to a software key is allowed automatically. Whether software keys are acceptable is a security policy decision that requires explicit user consent; a silent fallback would leave the user believing the key is hardware-protected.
This machine has no usable hardware key store (an implementation exists, but it is unavailable in this environment).
§It is a different thing from Error::UnsupportedPlatform
Here a different environment would work (a virtual machine without a TPM, a TPM disabled by group policy, a key store held exclusively by another process); there a different platform is required. Merging them would make the UI give the same advice for “change machine” and “change device”, which are two different user actions.
Hardware
A platform API returned a failure.
Fields
KeyNotFound
The referenced key does not exist.
Jni
The platform reported a failure in its own words.
§Why this is separate from Error::Hardware
Android reports failures as Java exceptions rather than as numeric codes: the class and the message are the whole diagnosis, and there is no code to format. Collapsing the two would either invent a code that means nothing or throw the message away — and the message is what tells a user apart “this device has no secure hardware” from “this key was refused”.
The detail is the platform’s own text, naming an operation and an exception. The platform does not put key material in it.
Fields
KeyAlreadyExists
A key already exists under this label.
§Why this is a separate variant
crate::keystore::DeviceKeyStore::open_or_create has to distinguish it from other
failures: for that method “already exists” is the desired outcome (the key can simply
be opened), while a hardware fault is not. Folding it into Error::Hardware would
leave that distinction to a comparison of native error codes, which are an
implementation detail.
Relatedly, create never overwrites an existing key: overwriting would replace the
device identity that other devices use to recognise this one.
InvalidDigestLength
The digest length passed in does not meet the requirement of the curve.
ECDSA accepts truncated digests, but the truncation rule is fixed per curve and is handled inside the implementation. Accepting a digest of the wrong length would only let the signing and verification sides disagree about how far to truncate, and such a disagreement shows up as “signatures randomly fail to verify”.
InvalidKeyLabel
The key label is invalid.
The label becomes an entry name in the system-wide key namespace, so it is
validated against a whitelist. The most direct hazard is NUL truncation: if \0 were
allowed, "a\0b" and "a" would be the same name to a C string, and two different
labels would map to one device identity.
Fields
InvalidPublicKey
The public key returned by hardware is not a valid P-256 public key.
Separate from Error::DevicePublicKeyInvalid: that one means “a public key received
from a peer is invalid” (a normal rejection path), while this one means “the public
key we just read back from our own hardware is invalid” — an internal inconsistency
pointing at the platform backend or the parsing logic, not a user error.
The two are handled quite differently: the first only requires rejecting this connection, the second has to surface an error a developer can see.
InvalidSignatureLength
The signature length returned by hardware is wrong.
As above, this is an internal inconsistency rather than a user error.
InvalidWrappedKey
The wrapped master key could not be turned back into a master key.
§This is not a hardware fault
The bytes are damaged, or they were produced by a different key-encryption key (a restored file, a key store that was re-created, a different device). Retrying and changing machine do not help, so the variant is deliberately not classified as environmental: what the caller has to offer the user is a recovery path, not a different computer.
code is the platform’s own numeric code where it has one, and 0 where it does not
(the in-memory backend). The code is kept for diagnostics for the same reason
Error::Hardware keeps it: a native code is the only handle available for looking
a failure up in vendor documentation.
Fields
InvalidMasterKey
The platform key store returned something that is not master key material.
An internal inconsistency rather than a user error: the store was asked for the material it holds, and what came back has the wrong shape. Reported instead of being truncated or padded, because a master key of the wrong length would fail later in a place that no longer points here.
KeyNotExportable
The platform key store holds the entry but will not return its material.
This is the failure mode of the direct form — “the store holds the material and hands it back” — on a platform whose key store protects a key by never letting its material out. The entry is unusable for that form, and the honest answer is this error rather than a store that silently keeps something the caller can never read again. The wrapped form exists for exactly this situation.
The OS random source is unavailable.
Can only occur with the mock backend; real backends leave randomness to the hardware,
which generates keys inside the TPM / Secure Enclave.
Implementations§
Source§impl Error
impl Error
Sourcepub const fn is_missing_hardware(&self) -> bool
pub const fn is_missing_hardware(&self) -> bool
Whether this error means “no hardware protection is available on this machine”.
The UI can use it to decide whether to tell the user that the device identity key will
be stored in software. It does not mean that falling back automatically is allowed;
see Error::UnsupportedPlatform.
Sourcepub const fn is_environmental(&self) -> bool
pub const fn is_environmental(&self) -> bool
Whether this error means “a different machine or platform would solve it”.
It differs from Error::is_missing_hardware, which answers “is there hardware
protection”: this one answers “would retrying help”. A platform API failure
(Error::Hardware) belongs here, and it is not missing hardware — the key store
may be perfectly fine and only this call failed.
Trait Implementations§
Source§impl Error for Error
impl Error for Error
1.30.0 · Source§fn source(&self) -> Option<&(dyn Error + 'static)>
fn source(&self) -> Option<&(dyn Error + 'static)>
1.0.0 · Source§fn description(&self) -> &str
fn description(&self) -> &str
use the Display impl or to_string()