Skip to main content

KeyTransportBackend

Trait KeyTransportBackend 

Source
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§

Source

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.

Source

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.

Source

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.

Source

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§

Source

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".

Implementors§