pub trait KeyTransportBackend: Backend {
// Required methods
fn wrap(
&mut self,
key_id: &KeyId,
wrapping_key_id: &KeyId,
scheme: WrapScheme,
) -> Result<WrappedKey, BackendError>;
fn unwrap(
&mut self,
wrapped: &WrappedKey,
unwrapping_key_id: &KeyId,
label: &str,
policy: KeyPolicy,
expected: Option<KeyAlgorithm>,
) -> Result<KeyMetadata, BackendError>;
fn generate_data_key(
&mut self,
kek: &KeyId,
algorithm: KeyAlgorithm,
) -> Result<DataKey, BackendError>;
fn open_data_key(
&mut self,
kek: &KeyId,
wrapped: &[u8],
protection: KeyProtection,
) -> Result<Zeroizing<Vec<u8>>, BackendError>;
// Provided method
fn wrap_to_public(
&mut self,
key_id: &KeyId,
recipient_pub_key: &PublicKeyDer,
scheme: WrapScheme,
) -> Result<WrappedKey, BackendError> { ... }
}Expand description
Key transport (wrapping) operations.
Every method returns a WrappedKey carrying the scheme it was asked for
and a WrapDescription of what it did, so
the caller records an observation rather than a request.
Required Methods§
Sourcefn wrap(
&mut self,
key_id: &KeyId,
wrapping_key_id: &KeyId,
scheme: WrapScheme,
) -> Result<WrappedKey, BackendError>
fn wrap( &mut self, key_id: &KeyId, wrapping_key_id: &KeyId, scheme: WrapScheme, ) -> Result<WrappedKey, BackendError>
Wrap key_id using wrapping_key_id under scheme.
Sourcefn unwrap(
&mut self,
wrapped: &WrappedKey,
unwrapping_key_id: &KeyId,
label: &str,
policy: KeyPolicy,
expected: Option<KeyAlgorithm>,
) -> Result<KeyMetadata, BackendError>
fn unwrap( &mut self, wrapped: &WrappedKey, unwrapping_key_id: &KeyId, label: &str, policy: KeyPolicy, expected: Option<KeyAlgorithm>, ) -> Result<KeyMetadata, BackendError>
Unwrap wrapped using unwrapping_key_id, importing the result with
label under policy.
The policy is the receiving ceremony’s, not the origin’s: nothing travels with a wrapped key that says what it may do, so the step that imports it declares that, exactly as the step that generated it did.
expected is that same declaration one level down, because nothing
travels with a wrapped key saying what it is either. Recovered bytes
are a private key or a bare secret depending on what was wrapped, and
the two are told apart by what the receiving ceremony says it is
restoring rather than by what the bytes happen to parse as. None is a
ceremony that declared nothing, which an implementation may serve only
where the recovered form is unambiguous. A declaration that disagrees
with what came out is a failure, not something to reconcile.
Sourcefn generate_data_key(
&mut self,
kek: &KeyId,
algorithm: KeyAlgorithm,
) -> Result<DataKey, BackendError>
fn generate_data_key( &mut self, kek: &KeyId, algorithm: KeyAlgorithm, ) -> Result<DataKey, BackendError>
Produce a fresh content-encryption key protected by kek.
Two copies of one key come back: the plaintext, for the caller to
encrypt content with and then drop, and a copy only kek opens, which
the container carries to the recipient.
Content does not appear here. No key-protection device Rite talks to is a cipher you hand a file to: a cloud KMS caps a direct encrypt at a few kilobytes, a TPM takes a kilobyte per call over a slow bus, and a smart card is slower still. Every one of them offers this operation instead, so a backend implements what it can actually do and the content pipeline stays in one place above it.
algorithm must be a symmetric one, since a data key is a secret the
caller encrypts with directly. It is the length request AWS KMS spells
KeySpec: AES_256 | AES_128.
The result carries a KeyProtection because the caller has to declare
the key-encryption algorithm in the container it assembles, and only the
backend knows which one it used.
§Not yet a parameter
An encryption context, which AWS calls EncryptionContext and Azure
calls aad, binds a data key to the purpose it was issued for: the same
value must be supplied to open it again, or the open fails. AWS
recommends it on every call. It is absent here because supplying it would
oblige the ceremony to store it somewhere a later run can read it back,
and CMS has no slot for it that the tag covers except authAttrs, which
is deferred. Adding it is the next widening this pair needs, and it wants
the transcript question answered first.
Sourcefn open_data_key(
&mut self,
kek: &KeyId,
wrapped: &[u8],
protection: KeyProtection,
) -> Result<Zeroizing<Vec<u8>>, BackendError>
fn open_data_key( &mut self, kek: &KeyId, wrapped: &[u8], protection: KeyProtection, ) -> Result<Zeroizing<Vec<u8>>, BackendError>
Recover a data key from the protected copy a container carries.
The counterpart of generate_data_key, and
the half of the pair almost every backend implements: protecting a data
key needs only a public key or a shared secret, while opening one always
needs the device that holds the other half.
protection says how wrapped was protected, taken from the container
rather than assumed, because the bytes say nothing about themselves and
the backend may implement several. An implementation that was not asked
which one to use could only guess, and a wrong guess on key material is
silent. A backend refuses a protection it does not implement rather than
decrypting under an assumption.
Provided Methods§
Sourcefn wrap_to_public(
&mut self,
key_id: &KeyId,
recipient_pub_key: &PublicKeyDer,
scheme: WrapScheme,
) -> Result<WrappedKey, BackendError>
fn wrap_to_public( &mut self, key_id: &KeyId, recipient_pub_key: &PublicKeyDer, scheme: WrapScheme, ) -> Result<WrappedKey, BackendError>
Wrap key_id to an external recipient’s public key.
Default implementation returns UnsupportedOperation.
Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".