//
// This file was automatically generated by witx-codegen - Do not edit manually.
//
// ---------------------- Interface: [wasi_ephemeral_crypto_asymmetric_common] ----------------------
interface wasi-ephemeral-crypto-asymmetric-common {
/// Error codes.
enum crypto-errno {
success,
guest-error,
not-implemented,
unsupported-feature,
prohibited-operation,
unsupported-encoding,
unsupported-algorithm,
unsupported-option,
invalid-key,
invalid-length,
verification-failed,
rng-error,
algorithm-failure,
invalid-signature,
closed,
invalid-handle,
overflow,
internal-error,
too-many-handles,
key-not-supported,
key-required,
invalid-tag,
invalid-operation,
nonce-required,
invalid-nonce,
option-not-set,
not-found,
parameters-missing,
in-progress,
incompatible-keys,
expired,
}
/// Encoding to use for importing or exporting a key pair.
enum keypair-encoding {
raw,
pkcs-8,
pem,
local,
}
/// Encoding to use for importing or exporting a public key.
enum publickey-encoding {
raw,
pkcs-8,
pem,
sec,
local,
}
/// Encoding to use for importing or exporting a secret key.
enum secretkey-encoding {
raw,
pkcs-8,
pem,
sec,
local,
}
/// Encoding to use for importing or exporting a signature.
enum signature-encoding {
raw,
der,
}
/// An algorithm category.
enum algorithm-type {
signatures,
symmetric,
key-exchange,
}
/// Version of a managed key.
///
/// A version can be an arbitrary `u64` integer, with the expection of some reserved values.
type version = u64;
/// Size of a value.
type size = u32;
/// A UNIX timestamp, in seconds since 01/01/1970.
type timestamp = u64;
/// A 64-bit value
type u-64 = u64;
/// Handle for functions returning output whose size may be large or not known in advance.
///
/// An `array_output` object contains a host-allocated byte array.
///
/// A guest can get the size of that array after a function returns in order to then allocate a buffer of the correct size.
/// In addition, the content of such an object can be consumed by a guest in a streaming fashion.
///
/// An `array_output` handle is automatically closed after its full content has been consumed.
type array-output = wasi-handle;
/// A set of options.
///
/// This type is used to set non-default parameters.
///
/// The exact set of allowed options depends on the algorithm being used.
type options = wasi-handle;
/// A handle to the optional secrets management facilities offered by a host.
///
/// This is used to generate, retrieve and invalidate managed keys.
type secrets-manager = wasi-handle;
/// A key pair.
type keypair = wasi-handle;
/// A state to absorb data to be signed.
///
/// After a signature has been computed or verified, the state remains valid for further operations.
///
/// A subsequent signature would sign all the data accumulated since the creation of the state object.
type signature-state = wasi-handle;
/// A signature.
type signature = wasi-handle;
/// A public key, for key exchange and signature verification.
type publickey = wasi-handle;
/// A secret key, for key exchange mechanisms.
type secretkey = wasi-handle;
/// A state to absorb signed data to be verified.
type signature-verification-state = wasi-handle;
/// A state to perform symmetric operations.
///
/// The state is not reset nor invalidated after an option has been performed.
/// Incremental updates and sessions are thus supported.
type symmetric-state = wasi-handle;
/// A symmetric key.
///
/// The key can be imported from raw bytes, or can be a reference to a managed key.
///
/// If it was imported, the host will wipe it from memory as soon as the handle is closed.
type symmetric-key = wasi-handle;
/// An authentication tag.
///
/// This is an object returned by functions computing authentication tags.
///
/// A tag can be compared against another tag (directly supplied as raw bytes) in constant time with the `symmetric_tag_verify()` function.
///
/// This object type can't be directly created from raw bytes. They are only returned by functions computing MACs.
///
/// The host is reponsible for securely wiping them from memory on close.
type symmetric-tag = wasi-handle;
/// Options index, only required by the Interface Types translation layer.
enum opt-options-u {
some,
none,
}
/// An optional options set.
///
/// This union simulates an `Option<Options>` type to make the `options` parameter of some functions optional.
variant opt-options {
some: options,
}
/// Symmetric key index, only required by the Interface Types translation layer.
enum opt-symmetric-key-u {
some,
none,
}
/// An optional symmetric key.
///
/// This union simulates an `Option<SymmetricKey>` type to make the `symmetric_key` parameter of some functions optional.
variant opt-symmetric-key {
some: symmetric-key,
}
// Functions
/// Generate a new key pair.
///
/// Internally, a key pair stores the supplied algorithm and optional parameters.
///
/// Trying to use that key pair with different parameters will throw an `invalid_key` error.
///
/// This function may return `$crypto_errno.unsupported_feature` if key generation is not supported by the host for the chosen algorithm.
///
/// The function may also return `unsupported_algorithm` if the algorithm is not supported by the host.
///
/// Finally, if generating that type of key pair is an expensive operation, the function may return `in_progress`.
/// In that case, the guest should retry with the same parameters until the function completes.
///
/// Example usage:
///
/// ```rust
/// let kp_handle = ctx.keypair_generate(AlgorithmType::Signatures, "RSA_PKCS1_2048_SHA256", None)?;
/// ```
keypair-generate: func(
algorithm-type: algorithm-type,
algorithm: string,
options: opt-options,
) -> result<keypair, crypto-errno>;
/// Import a key pair.
///
/// This function creates a `keypair` object from existing material.
///
/// It may return `unsupported_algorithm` if the encoding scheme is not supported, or `invalid_key` if the key cannot be decoded.
///
/// The function may also return `unsupported_algorithm` if the algorithm is not supported by the host.
///
/// Example usage:
///
/// ```rust
/// let kp_handle = ctx.keypair_import(AlgorithmType::Signatures, "RSA_PKCS1_2048_SHA256", KeypairEncoding::PKCS8)?;
/// ```
keypair-import: func(
algorithm-type: algorithm-type,
algorithm: string,
encoded: list<u8>,
encoding: keypair-encoding,
) -> result<keypair, crypto-errno>;
/// __(optional)__
/// Generate a new managed key pair.
///
/// The key pair is generated and stored by the secrets management facilities.
///
/// It may be used through its identifier, but the host may not allow it to be exported.
///
/// The function returns the `unsupported_feature` error code if secrets management facilities are not supported by the host,
/// or `unsupported_algorithm` if a key cannot be created for the chosen algorithm.
///
/// The function may also return `unsupported_algorithm` if the algorithm is not supported by the host.
///
/// This is also an optional import, meaning that the function may not even exist.
keypair-generate-managed: func(
secrets-manager: secrets-manager,
algorithm-type: algorithm-type,
algorithm: string,
options: opt-options,
) -> result<keypair, crypto-errno>;
/// __(optional)__
/// Store a key pair into the secrets manager.
///
/// On success, the function stores the key pair identifier into `$kp_id`,
/// into which up to `$kp_id_max_len` can be written.
///
/// The function returns `overflow` if the supplied buffer is too small.
keypair-store-managed: func(
secrets-manager: secrets-manager,
kp: keypair,
kp-id: borrow<u8>,
kp-id-max-len: size,
) -> result<_, crypto-errno>;
/// __(optional)__
/// Replace a managed key pair.
///
/// This function crates a new version of a managed key pair, by replacing `$kp_old` with `$kp_new`.
///
/// It does several things:
///
/// - The key identifier for `$kp_new` is set to the one of `$kp_old`.
/// - A new, unique version identifier is assigned to `$kp_new`. This version will be equivalent to using `$version_latest` until the key is replaced.
/// - The `$kp_old` handle is closed.
///
/// Both keys must share the same algorithm and have compatible parameters. If this is not the case, `incompatible_keys` is returned.
///
/// The function may also return the `unsupported_feature` error code if secrets management facilities are not supported by the host,
/// or if keys cannot be rotated.
///
/// Finally, `prohibited_operation` can be returned if `$kp_new` wasn't created by the secrets manager, and the secrets manager prohibits imported keys.
///
/// If the operation succeeded, the new version is returned.
///
/// This is an optional import, meaning that the function may not even exist.
keypair-replace-managed: func(
secrets-manager: secrets-manager,
kp-old: keypair,
kp-new: keypair,
) -> result<version, crypto-errno>;
/// __(optional)__
/// Return the key pair identifier and version of a managed key pair.
///
/// If the key pair is not managed, `unsupported_feature` is returned instead.
///
/// This is an optional import, meaning that the function may not even exist.
keypair-id: func(
kp: keypair,
kp-id: borrow<u8>,
kp-id-max-len: size,
) -> result<tuple<size, version>, crypto-errno>;
/// __(optional)__
/// Return a managed key pair from a key identifier.
///
/// `kp_version` can be set to `version_latest` to retrieve the most recent version of a key pair.
///
/// If no key pair matching the provided information is found, `not_found` is returned instead.
///
/// This is an optional import, meaning that the function may not even exist.
/// ```
keypair-from-id: func(
secrets-manager: secrets-manager,
kp-id: list<u8>,
kp-version: version,
) -> result<keypair, crypto-errno>;
/// Create a key pair from a public key and a secret key.
keypair-from-pk-and-sk: func(
publickey: publickey,
secretkey: secretkey,
) -> result<keypair, crypto-errno>;
/// Export a key pair as the given encoding format.
///
/// May return `prohibited_operation` if this operation is denied or `unsupported_encoding` if the encoding is not supported.
keypair-export: func(
kp: keypair,
encoding: keypair-encoding,
) -> result<array-output, crypto-errno>;
/// Get the public key of a key pair.
keypair-publickey: func(
kp: keypair,
) -> result<publickey, crypto-errno>;
/// Get the secret key of a key pair.
keypair-secretkey: func(
kp: keypair,
) -> result<secretkey, crypto-errno>;
/// Destroy a key pair.
///
/// The host will automatically wipe traces of the secret key from memory.
///
/// If this is a managed key, the key will not be removed from persistent storage, and can be reconstructed later using the key identifier.
keypair-close: func(
kp: keypair,
) -> result<_, crypto-errno>;
/// Import a public key.
///
/// The function may return `unsupported_encoding` if importing from the given format is not implemented or incompatible with the key type.
///
/// It may also return `invalid_key` if the key doesn't appear to match the supplied algorithm.
///
/// Finally, the function may return `unsupported_algorithm` if the algorithm is not supported by the host.
///
/// Example usage:
///
/// ```rust
/// let pk_handle = ctx.publickey_import(AlgorithmType::Signatures, encoded, PublicKeyEncoding::Sec)?;
/// ```
publickey-import: func(
algorithm-type: algorithm-type,
algorithm: string,
encoded: list<u8>,
encoding: publickey-encoding,
) -> result<publickey, crypto-errno>;
/// Export a public key as the given encoding format.
///
/// May return `unsupported_encoding` if the encoding is not supported.
publickey-export: func(
pk: publickey,
encoding: publickey-encoding,
) -> result<array-output, crypto-errno>;
/// Check that a public key is valid and in canonical form.
///
/// This function may perform stricter checks than those made during importation at the expense of additional CPU cycles.
///
/// The function returns `invalid_key` if the public key didn't pass the checks.
publickey-verify: func(
pk: publickey,
) -> result<_, crypto-errno>;
/// Compute the public key for a secret key.
publickey-from-secretkey: func(
sk: secretkey,
) -> result<publickey, crypto-errno>;
/// Destroy a public key.
///
/// Objects are reference counted. It is safe to close an object immediately after the last function needing it is called.
publickey-close: func(
pk: publickey,
) -> result<_, crypto-errno>;
/// Import a secret key.
///
/// The function may return `unsupported_encoding` if importing from the given format is not implemented or incompatible with the key type.
///
/// It may also return `invalid_key` if the key doesn't appear to match the supplied algorithm.
///
/// Finally, the function may return `unsupported_algorithm` if the algorithm is not supported by the host.
///
/// Example usage:
///
/// ```rust
/// let pk_handle = ctx.secretkey_import(AlgorithmType::KX, encoded, SecretKeyEncoding::Raw)?;
/// ```
secretkey-import: func(
algorithm-type: algorithm-type,
algorithm: string,
encoded: list<u8>,
encoding: secretkey-encoding,
) -> result<secretkey, crypto-errno>;
/// Export a secret key as the given encoding format.
///
/// May return `unsupported_encoding` if the encoding is not supported.
secretkey-export: func(
sk: secretkey,
encoding: secretkey-encoding,
) -> result<array-output, crypto-errno>;
/// Destroy a secret key.
///
/// Objects are reference counted. It is safe to close an object immediately after the last function needing it is called.
secretkey-close: func(
sk: secretkey,
) -> result<_, crypto-errno>;
}
// ---------------------- Interface: [wasi_ephemeral_crypto_common] ----------------------
interface wasi-ephemeral-crypto-common {
/// Error codes.
enum crypto-errno {
success,
guest-error,
not-implemented,
unsupported-feature,
prohibited-operation,
unsupported-encoding,
unsupported-algorithm,
unsupported-option,
invalid-key,
invalid-length,
verification-failed,
rng-error,
algorithm-failure,
invalid-signature,
closed,
invalid-handle,
overflow,
internal-error,
too-many-handles,
key-not-supported,
key-required,
invalid-tag,
invalid-operation,
nonce-required,
invalid-nonce,
option-not-set,
not-found,
parameters-missing,
in-progress,
incompatible-keys,
expired,
}
/// Encoding to use for importing or exporting a key pair.
enum keypair-encoding {
raw,
pkcs-8,
pem,
local,
}
/// Encoding to use for importing or exporting a public key.
enum publickey-encoding {
raw,
pkcs-8,
pem,
sec,
local,
}
/// Encoding to use for importing or exporting a secret key.
enum secretkey-encoding {
raw,
pkcs-8,
pem,
sec,
local,
}
/// Encoding to use for importing or exporting a signature.
enum signature-encoding {
raw,
der,
}
/// An algorithm category.
enum algorithm-type {
signatures,
symmetric,
key-exchange,
}
/// Version of a managed key.
///
/// A version can be an arbitrary `u64` integer, with the expection of some reserved values.
type version = u64;
// version-unspecified: version = 0xff00000000000000;
// version-latest: version = 0xff00000000000001;
// version-all: version = 0xff00000000000002;
/// Size of a value.
type size = u32;
/// A UNIX timestamp, in seconds since 01/01/1970.
type timestamp = u64;
/// A 64-bit value
type u-64 = u64;
/// Handle for functions returning output whose size may be large or not known in advance.
///
/// An `array_output` object contains a host-allocated byte array.
///
/// A guest can get the size of that array after a function returns in order to then allocate a buffer of the correct size.
/// In addition, the content of such an object can be consumed by a guest in a streaming fashion.
///
/// An `array_output` handle is automatically closed after its full content has been consumed.
type array-output = wasi-handle;
/// A set of options.
///
/// This type is used to set non-default parameters.
///
/// The exact set of allowed options depends on the algorithm being used.
type options = wasi-handle;
/// A handle to the optional secrets management facilities offered by a host.
///
/// This is used to generate, retrieve and invalidate managed keys.
type secrets-manager = wasi-handle;
/// A key pair.
type keypair = wasi-handle;
/// A state to absorb data to be signed.
///
/// After a signature has been computed or verified, the state remains valid for further operations.
///
/// A subsequent signature would sign all the data accumulated since the creation of the state object.
type signature-state = wasi-handle;
/// A signature.
type signature = wasi-handle;
/// A public key, for key exchange and signature verification.
type publickey = wasi-handle;
/// A secret key, for key exchange mechanisms.
type secretkey = wasi-handle;
/// A state to absorb signed data to be verified.
type signature-verification-state = wasi-handle;
/// A state to perform symmetric operations.
///
/// The state is not reset nor invalidated after an option has been performed.
/// Incremental updates and sessions are thus supported.
type symmetric-state = wasi-handle;
/// A symmetric key.
///
/// The key can be imported from raw bytes, or can be a reference to a managed key.
///
/// If it was imported, the host will wipe it from memory as soon as the handle is closed.
type symmetric-key = wasi-handle;
/// An authentication tag.
///
/// This is an object returned by functions computing authentication tags.
///
/// A tag can be compared against another tag (directly supplied as raw bytes) in constant time with the `symmetric_tag_verify()` function.
///
/// This object type can't be directly created from raw bytes. They are only returned by functions computing MACs.
///
/// The host is reponsible for securely wiping them from memory on close.
type symmetric-tag = wasi-handle;
/// Options index, only required by the Interface Types translation layer.
enum opt-options-u {
some,
none,
}
/// An optional options set.
///
/// This union simulates an `Option<Options>` type to make the `options` parameter of some functions optional.
variant opt-options {
some: options,
}
/// Symmetric key index, only required by the Interface Types translation layer.
enum opt-symmetric-key-u {
some,
none,
}
/// An optional symmetric key.
///
/// This union simulates an `Option<SymmetricKey>` type to make the `symmetric_key` parameter of some functions optional.
variant opt-symmetric-key {
some: symmetric-key,
}
// Functions
/// Create a new object to set non-default options.
///
/// Example usage:
///
/// ```rust
/// let options_handle = options_open(AlgorithmType::Symmetric)?;
/// options_set(options_handle, "context", context)?;
/// options_set_u64(options_handle, "threads", 4)?;
/// let state = symmetric_state_open("BLAKE3", None, Some(options_handle))?;
/// options_close(options_handle)?;
/// ```
options-open: func(
algorithm-type: algorithm-type,
) -> result<options, crypto-errno>;
/// Destroy an options object.
///
/// Objects are reference counted. It is safe to close an object immediately after the last function needing it is called.
options-close: func(
handle: options,
) -> result<_, crypto-errno>;
/// Set or update an option.
///
/// This is used to set algorithm-specific parameters, but also to provide credentials for the secrets management facilities, if required.
///
/// This function may return `unsupported_option` if an option that doesn't exist for any implemented algorithms is specified.
options-set: func(
handle: options,
name: string,
value: list<u8>,
) -> result<_, crypto-errno>;
/// Set or update an integer option.
///
/// This is used to set algorithm-specific parameters.
///
/// This function may return `unsupported_option` if an option that doesn't exist for any implemented algorithms is specified.
options-set-u-64: func(
handle: options,
name: string,
value: u64,
) -> result<_, crypto-errno>;
/// Set or update a guest-allocated memory that the host can use or return data into.
///
/// This is for example used to set the scratch buffer required by memory-hard functions.
///
/// This function may return `unsupported_option` if an option that doesn't exist for any implemented algorithms is specified.
options-set-guest-buffer: func(
handle: options,
name: string,
buffer: borrow<list<u8>>,
) -> result<_, crypto-errno>;
/// Return the length of an `array_output` object.
///
/// This allows a guest to allocate a buffer of the correct size in order to copy the output of a function returning this object type.
array-output-len: func(
array-output: array-output,
) -> result<size, crypto-errno>;
/// Copy the content of an `array_output` object into an application-allocated buffer.
///
/// Multiple calls to that function can be made in order to consume the data in a streaming fashion, if necessary.
///
/// The function returns the number of bytes that were actually copied. `0` means that the end of the stream has been reached. The total size always matches the output of `array_output_len()`.
///
/// The handle is automatically closed after all the data has been consumed.
///
/// Example usage:
///
/// ```rust
/// let len = array_output_len(output_handle)?;
/// let mut out = vec![0u8; len];
/// array_output_pull(output_handle, &mut out)?;
/// ```
array-output-pull: func(
array-output: array-output,
buf: borrow<list<u8>>,
) -> result<size, crypto-errno>;
/// __(optional)__
/// Create a context to use a secrets manager.
///
/// The set of required and supported options is defined by the host.
///
/// The function returns the `unsupported_feature` error code if secrets management facilities are not supported by the host.
/// This is also an optional import, meaning that the function may not even exist.
secrets-manager-open: func(
options: opt-options,
) -> result<secrets-manager, crypto-errno>;
/// __(optional)__
/// Destroy a secrets manager context.
///
/// The function returns the `unsupported_feature` error code if secrets management facilities are not supported by the host.
/// This is also an optional import, meaning that the function may not even exist.
secrets-manager-close: func(
secrets-manager: secrets-manager,
) -> result<_, crypto-errno>;
/// __(optional)__
/// Invalidate a managed key or key pair given an identifier and a version.
///
/// This asks the secrets manager to delete or revoke a stored key, a specific version of a key.
///
/// `key_version` can be set to a version number, to `version.latest` to invalidate the current version, or to `version.all` to invalidate all versions of a key.
///
/// The function returns `unsupported_feature` if this operation is not supported by the host, and `not_found` if the identifier and version don't match any existing key.
///
/// This is an optional import, meaning that the function may not even exist.
secrets-manager-invalidate: func(
secrets-manager: secrets-manager,
key-id: list<u8>,
key-version: version,
) -> result<_, crypto-errno>;
}
// ---------------------- Interface: [wasi_ephemeral_crypto_external_secrets] ----------------------
interface wasi-ephemeral-crypto-external-secrets {
// Functions
/// Store an external secret into the secrets manager.
///
/// `$expiration` is the expiration date of the secret as a UNIX timestamp, in seconds.
/// An expiration date is mandatory.
///
/// On success, the secret identifier is put into `$secret_id` if it fits into `$secret_id_max_len` bytes.
/// If the supplied ouptut buffer is too small, `$overflow` is returned.
///
/// If this function is not supported by the host the `$unsupported_feature` error is returned.
external-secret-store: func(
secrets-manager: secrets-manager,
secret: list<u8>,
expiration: timestamp,
secret-id: borrow<u8>,
secret-id-max-len: size,
) -> result<_, crypto-errno>;
/// Replace a managed external with a new version.
///
/// `$expiration` is the expiration date of the secret as a UNIX timestamp, in seconds.
/// An expiration date is mandatory.
///
/// On success, a new version is created and returned.
///
/// If this function is not supported by the host the `$unsupported_feature` error is returned.
external-secret-replace: func(
secrets-manager: secrets-manager,
secret: list<u8>,
expiration: timestamp,
secret-id: list<u8>,
) -> result<version, crypto-errno>;
/// Get a copy of an external secret given an identifier and version.
///
/// `secret_version` can be set to a version number, or to `version.latest` to retrieve the most recent version of a secret.
///
/// On success, a copy of the secret is returned.
///
/// The function returns `$unsupported_feature` if this operation is not supported by the host, and `not_found` if the identifier and version don't match any existing secret.
external-secret-from-id: func(
secrets-manager: secrets-manager,
secret-id: list<u8>,
secret-version: version,
) -> result<array-output, crypto-errno>;
/// Invalidate an external secret given an identifier and a version.
///
/// This asks the secrets manager to delete or revoke a stored secret, a specific version of a secret.
///
/// `secret_version` can be set to a version number, or to `version.latest` to invalidate the current version, or to `version.all` to invalidate all versions of a secret.
///
/// The function returns `$unsupported_feature` if this operation is not supported by the host, and `not_found` if the identifier and version don't match any existing secret.
external-secret-invalidate: func(
secrets-manager: secrets-manager,
secret-id: list<u8>,
secret-version: version,
) -> result<_, crypto-errno>;
/// Encrypt an external secret.
///
/// Applications don't have access to the encryption key, and the secrets manager is free to choose any suitable algorithm.
///
/// However, the returned ciphertext must include and authenticate both the secret and the expiration date.
///
/// On success, the ciphertext is returned.
external-secret-encapsulate: func(
secrets-manager: secrets-manager,
secret: list<u8>,
expiration: timestamp,
) -> result<array-output, crypto-errno>;
/// Decrypt an external secret previously encrypted by the secrets manager.
///
/// Returns the original secret if the ciphertext is valid.
/// Returns `$expired` if the current date is past the stored expiration date.
/// Returns `$verification_failed` if the ciphertext format is invalid or if its authentication tag couldn't be verified.
external-secret-decapsulate: func(
secrets-manager: secrets-manager,
encrypted-secret: list<u8>,
) -> result<array-output, crypto-errno>;
}
// ---------------------- Interface: [wasi_ephemeral_crypto_kx] ----------------------
interface wasi-ephemeral-crypto-kx {
/// `$kx_keypair` is just an alias for `$keypair`
///
/// However, bindings may want to define a specialized type `kx_keypair` as a super class of `keypair`.
type kx-keypair = wasi-handle;
/// `$kx_publickey` is just an alias for `$publickey`
///
/// However, bindings may want to define a specialized type `kx_publickey` as a super class of `publickey`, with additional methods such as `dh`.
type kx-publickey = wasi-handle;
/// `$kx_secretkey` is just an alias for `$secretkey`
///
/// However, bindings may want to define a specialized type `kx_secretkey` as a super class of `secretkeykey`, with additional methods such as `dh`.
type kx-secretkey = wasi-handle;
// Functions
/// Perform a simple Diffie-Hellman key exchange.
///
/// Both keys must be of the same type, or else the `$crypto_errno.incompatible_keys` error is returned.
/// The algorithm also has to support this kind of key exchange. If this is not the case, the `$crypto_errno.invalid_operation` error is returned.
///
/// Otherwide, a raw shared key is returned, and can be imported as a symmetric key.
/// ```
kx-dh: func(
pk: publickey,
sk: secretkey,
) -> result<array-output, crypto-errno>;
/// Create a shared secret and encrypt it for the given public key.
///
/// This operation is only compatible with specific algorithms.
/// If a selected algorithm doesn't support it, `$crypto_errno.invalid_operation` is returned.
///
/// On success, both the shared secret and its encrypted version are returned.
kx-encapsulate: func(
pk: publickey,
) -> result<tuple<array-output, array-output>, crypto-errno>;
/// Decapsulate an encapsulated secret crated with `kx_encapsulate`
///
/// Return the secret, or `$crypto_errno.verification_failed` on error.
kx-decapsulate: func(
sk: secretkey,
encapsulated-secret: list<u8>,
) -> result<array-output, crypto-errno>;
}
// ---------------------- Interface: [wasi_ephemeral_crypto_signatures] ----------------------
interface wasi-ephemeral-crypto-signatures {
/// `$signature_keypair` is just an alias for `$keypair`
///
/// However, bindings may want to define a specialized type `signature_keypair` as a super class of `keypair`, with additional methods such as `sign`.
type signature-keypair = wasi-handle;
/// `$signature_publickey` is just an alias for `$publickey`
///
/// However, bindings may want to define a specialized type `signature_publickey` as a super class of `publickey`, with additional methods such as `verify`.
type signature-publickey = wasi-handle;
/// `$signature_secretkey` is just an alias for `$secretkey`
///
/// However, bindings may want to define a specialized type `signature_secretkey` as a super class of `secretkey`.
type signature-secretkey = wasi-handle;
// Functions
/// Export a signature.
///
/// This function exports a signature object using the specified encoding.
///
/// May return `unsupported_encoding` if the signature cannot be encoded into the given format.
signature-export: func(
signature: signature,
encoding: signature-encoding,
) -> result<array-output, crypto-errno>;
/// Create a signature object.
///
/// This object can be used along with a public key to verify an existing signature.
///
/// It may return `invalid_signature` if the signature is invalid or incompatible with the specified algorithm, as well as `unsupported_encoding` if the encoding is not compatible with the signature type.
///
/// The function may also return `unsupported_algorithm` if the algorithm is not supported by the host.
///
/// Example usage:
///
/// ```rust
/// let signature_handle = ctx.signature_import("ECDSA_P256_SHA256", SignatureEncoding::DER, encoded)?;
/// ```
signature-import: func(
algorithm: string,
encoded: list<u8>,
encoding: signature-encoding,
) -> result<signature, crypto-errno>;
/// Create a new state to collect data to compute a signature on.
///
/// This function allows data to be signed to be supplied in a streaming fashion.
///
/// The state is not closed and can be used after a signature has been computed, allowing incremental updates by calling `signature_state_update()` again afterwards.
///
/// Example usage - signature creation
///
/// ```rust
/// let kp_handle = ctx.keypair_import(AlgorithmType::Signatures, "Ed25519ph", keypair, KeypairEncoding::Raw)?;
/// let state_handle = ctx.signature_state_open(kp_handle)?;
/// ctx.signature_state_update(state_handle, b"message part 1")?;
/// ctx.signature_state_update(state_handle, b"message part 2")?;
/// let sig_handle = ctx.signature_state_sign(state_handle)?;
/// let raw_sig = ctx.signature_export(sig_handle, SignatureEncoding::Raw)?;
/// ```
signature-state-open: func(
kp: signature-keypair,
) -> result<signature-state, crypto-errno>;
/// Absorb data into the signature state.
///
/// This function may return `unsupported_feature` is the selected algorithm doesn't support incremental updates.
signature-state-update: func(
state: signature-state,
input: list<u8>,
) -> result<_, crypto-errno>;
/// Compute a signature for all the data collected up to that point.
///
/// The function can be called multiple times for incremental signing.
signature-state-sign: func(
state: signature-state,
) -> result<array-output, crypto-errno>;
/// Destroy a signature state.
///
/// Objects are reference counted. It is safe to close an object immediately after the last function needing it is called.
///
/// Note that closing a signature state doesn't close or invalidate the key pair object, that be reused for further signatures.
signature-state-close: func(
state: signature-state,
) -> result<_, crypto-errno>;
/// Create a new state to collect data to verify a signature on.
///
/// This is the verification counterpart of `signature_state`.
///
/// Data can be injected using `signature_verification_state_update()`, and the state is not closed after a verification, allowing incremental verification.
///
/// Example usage - signature verification:
///
/// ```rust
/// let pk_handle = ctx.publickey_import(AlgorithmType::Signatures, "ECDSA_P256_SHA256", encoded_pk, PublicKeyEncoding::Sec)?;
/// let signature_handle = ctx.signature_import(AlgorithmType::Signatures, "ECDSA_P256_SHA256", encoded_sig, SignatureEncoding::Der)?;
/// let state_handle = ctx.signature_verification_state_open(pk_handle)?;
/// ctx.signature_verification_state_update(state_handle, "message")?;
/// ctx.signature_verification_state_verify(signature_handle)?;
/// ```
signature-verification-state-open: func(
kp: signature-publickey,
) -> result<signature-verification-state, crypto-errno>;
/// Absorb data into the signature verification state.
///
/// This function may return `unsupported_feature` is the selected algorithm doesn't support incremental updates.
signature-verification-state-update: func(
state: signature-verification-state,
input: list<u8>,
) -> result<_, crypto-errno>;
/// Check that the given signature is verifies for the data collected up to that point point.
///
/// The state is not closed and can absorb more data to allow for incremental verification.
///
/// The function returns `invalid_signature` if the signature doesn't appear to be valid.
signature-verification-state-verify: func(
state: signature-verification-state,
signature: signature,
) -> result<_, crypto-errno>;
/// Destroy a signature verification state.
///
/// Objects are reference counted. It is safe to close an object immediately after the last function needing it is called.
///
/// Note that closing a signature state doesn't close or invalidate the public key object, that be reused for further verifications.
signature-verification-state-close: func(
state: signature-verification-state,
) -> result<_, crypto-errno>;
/// Destroy a signature.
///
/// Objects are reference counted. It is safe to close an object immediately after the last function needing it is called.
signature-close: func(
signature: signature,
) -> result<_, crypto-errno>;
}
// ---------------------- Interface: [wasi_ephemeral_crypto_signatures_batch] ----------------------
interface wasi-ephemeral-crypto-signatures-batch {
/// The result of a signature sign operation. A pair of the signature and an error code.
signature-sign-result: tuple<array-output, crypto-errno>;
/// A list of signature_sign results.
type signature-results = list<signature-sign-result>;
/// A tuple of a signature verification state and the signature to verify.
///
/// Used for grouping signature verification state to be verified with the signature to verify.
/// Used with batch_signature_state_verify().
signature-verification-input: tuple<signature-verification-state, signature>;
type signature-verification-results = list<crypto-errno>;
// Functions
/// Compute a batch of signatures.
///
/// This is a batch version of the signature_state_sign operation and is an extension of the wasi_emphemeral_crypto_signatures module.
///
/// The batch operation returns an error code of type $crypto_errno that
/// indicates if the batch was processed or if the batch could not be
/// processed.
///
/// Batch processing error codes:
/// - `success`: Batch was processed. The status of each operation is indicated in the results list.
/// - `not_implemented`: Batch functionality is not supported.
/// - `unsupported_feature`: Inconsistent operations within the batch, e.g. not all operations in the batch use the same algorithm.
///
/// If the batch was processed, the result of each operation in the batch
/// is a pair of a $crypto_errno error code and a signature. The error code
/// indicates if that operation succeeded or failed. The signature is only
/// valid if the error code indicates success.
///
/// Example usage:
///
/// ```rust
/// let kp_handle = keypair_import(AlgorithmType::Signatures, "Ed25519", encoded, KeypairEncoding::Raw)?;
///
/// let mut state_handles = Vec::new();
///
/// let state_handle = signature_state_open(kp_handle)?;
/// signature_state_update(state_handle, b"message part 1")?;
/// signature_state_update(state_handle, b"message part 2")?;
/// state_handles.push(state_handle);
///
/// let state_handle = signature_state_open(kp_handle)?;
/// signature_state_update(state_handle, b"message part 1")?;
/// signature_state_update(state_handle, b"message part 2")?;
/// state_handles.push(state_handle);
///
/// let sig_handles = batch_signature_state_sign(state_handles)?;
///
/// let raw_sig1 = signature_export(sig_handle[0], SignatureEncoding::Raw)?;
/// let raw_sig2 = signature_export(sig_handle[1], SignatureEncoding::Raw)?;
/// ```
batch-signature-state-sign: func(
states: list<signature-state>,
) -> result<signature-results, crypto-errno>;
/// Verify a batch of signatures.
///
/// This is a batch version of the signature_state_verify operation and is
/// an extension of the wasi_empemeral_crypto_signatures module.
///
/// The batch operation returns an error code of type $crypto_errno that
/// indicates if the batch was processed (`success`) or if the batch could
/// not be processed.
///
/// Batch processing failure cases are:
/// - `not_implemented`: Batch functionality is not supported.
/// - `unsupported_feature`: Inconsistent operations within the batch, e.g. not all operations in the batch use the same algorithm.
///
/// If the batch was processed, a list of verification results is produced.
/// Each entry in the input list has a corresponding error state returned
/// in the verification results list to indicate if the verification
/// succeeded or encountered and error.
///
/// Example usage:
///
/// ```rust
/// let kp_handle = keypair_import(AlgorithmType::Signatures, "Ed25519", encoded, KeypairEncoding::Raw)?;
///
/// let mut batch = Vec::new();
///
/// let state_handle = signature_verification_state_open(kp_handle)?;
/// signature_verification_state_update(state_handle, b"message part 1")?;
/// signature_verification_state_update(state_handle, b"message part 2")?;
/// state_handles.push((state_handle, signature1));
///
/// let state_handle = signature_state_open(kp_handle)?;
/// signature_state_update(state_handle, b"message part 1")?;
/// signature_state_update(state_handle, b"message part 2")?;
/// state_handles.push((state_handle, signature2));
///
/// let results = batch_signature_state_verify(state_handles)?;
/// ```
batch-signature-state-verify: func(
states: list<signature-verification-input>,
) -> result<signature-verification-results, crypto-errno>;
}
// ---------------------- Interface: [wasi_ephemeral_crypto_symmetric] ----------------------
interface wasi-ephemeral-crypto-symmetric {
// Functions
/// Generate a new symmetric key for a given algorithm.
///
/// `options` can be `None` to use the default parameters, or an algoritm-specific set of parameters to override.
///
/// This function may return `unsupported_feature` if key generation is not supported by the host for the chosen algorithm, or `unsupported_algorithm` if the algorithm is not supported by the host.
symmetric-key-generate: func(
algorithm: string,
options: opt-options,
) -> result<symmetric-key, crypto-errno>;
/// Create a symmetric key from raw material.
///
/// The algorithm is internally stored along with the key, and trying to use the key with an operation expecting a different algorithm will return `invalid_key`.
///
/// The function may also return `unsupported_algorithm` if the algorithm is not supported by the host.
symmetric-key-import: func(
algorithm: string,
raw: list<u8>,
) -> result<symmetric-key, crypto-errno>;
/// Export a symmetric key as raw material.
///
/// This is mainly useful to export a managed key.
///
/// May return `prohibited_operation` if this operation is denied.
symmetric-key-export: func(
symmetric-key: symmetric-key,
) -> result<array-output, crypto-errno>;
/// Destroy a symmetric key.
///
/// Objects are reference counted. It is safe to close an object immediately after the last function needing it is called.
symmetric-key-close: func(
symmetric-key: symmetric-key,
) -> result<_, crypto-errno>;
/// __(optional)__
/// Generate a new managed symmetric key.
///
/// The key is generated and stored by the secrets management facilities.
///
/// It may be used through its identifier, but the host may not allow it to be exported.
///
/// The function returns the `unsupported_feature` error code if secrets management facilities are not supported by the host,
/// or `unsupported_algorithm` if a key cannot be created for the chosen algorithm.
///
/// The function may also return `unsupported_algorithm` if the algorithm is not supported by the host.
///
/// This is also an optional import, meaning that the function may not even exist.
symmetric-key-generate-managed: func(
secrets-manager: secrets-manager,
algorithm: string,
options: opt-options,
) -> result<symmetric-key, crypto-errno>;
/// __(optional)__
/// Store a symmetric key into the secrets manager.
///
/// On success, the function stores the key identifier into `$symmetric_key_id`,
/// into which up to `$symmetric_key_id_max_len` can be written.
///
/// The function returns `overflow` if the supplied buffer is too small.
symmetric-key-store-managed: func(
secrets-manager: secrets-manager,
symmetric-key: symmetric-key,
symmetric-key-id: borrow<u8>,
symmetric-key-id-max-len: size,
) -> result<_, crypto-errno>;
/// __(optional)__
/// Replace a managed symmetric key.
///
/// This function crates a new version of a managed symmetric key, by replacing `$kp_old` with `$kp_new`.
///
/// It does several things:
///
/// - The key identifier for `$symmetric_key_new` is set to the one of `$symmetric_key_old`.
/// - A new, unique version identifier is assigned to `$kp_new`. This version will be equivalent to using `$version_latest` until the key is replaced.
/// - The `$symmetric_key_old` handle is closed.
///
/// Both keys must share the same algorithm and have compatible parameters. If this is not the case, `incompatible_keys` is returned.
///
/// The function may also return the `unsupported_feature` error code if secrets management facilities are not supported by the host,
/// or if keys cannot be rotated.
///
/// Finally, `prohibited_operation` can be returned if `$symmetric_key_new` wasn't created by the secrets manager, and the secrets manager prohibits imported keys.
///
/// If the operation succeeded, the new version is returned.
///
/// This is an optional import, meaning that the function may not even exist.
symmetric-key-replace-managed: func(
secrets-manager: secrets-manager,
symmetric-key-old: symmetric-key,
symmetric-key-new: symmetric-key,
) -> result<version, crypto-errno>;
/// __(optional)__
/// Return the key identifier and version of a managed symmetric key.
///
/// If the key is not managed, `unsupported_feature` is returned instead.
///
/// This is an optional import, meaning that the function may not even exist.
symmetric-key-id: func(
symmetric-key: symmetric-key,
symmetric-key-id: borrow<u8>,
symmetric-key-id-max-len: size,
) -> result<tuple<size, version>, crypto-errno>;
/// __(optional)__
/// Return a managed symmetric key from a key identifier.
///
/// `kp_version` can be set to `version_latest` to retrieve the most recent version of a symmetric key.
///
/// If no key matching the provided information is found, `not_found` is returned instead.
///
/// This is an optional import, meaning that the function may not even exist.
symmetric-key-from-id: func(
secrets-manager: secrets-manager,
symmetric-key-id: list<u8>,
symmetric-key-version: version,
) -> result<symmetric-key, crypto-errno>;
/// Create a new state to aborb and produce data using symmetric operations.
///
/// The state remains valid after every operation in order to support incremental updates.
///
/// The function has two optional parameters: a key and an options set.
///
/// It will fail with a `key_not_supported` error code if a key was provided but the chosen algorithm doesn't natively support keying.
///
/// On the other hand, if a key is required, but was not provided, a `key_required` error will be thrown.
///
/// Some algorithms may require additional parameters. They have to be supplied as an options set:
///
/// ```rust
/// let options_handle = ctx.options_open()?;
/// ctx.options_set("context", b"My application")?;
/// ctx.options_set_u64("fanout", 16)?;
/// let state_handle = ctx.symmetric_state_open("BLAKE2b-512", None, Some(options_handle))?;
/// ```
///
/// If some parameters are mandatory but were not set, the `parameters_missing` error code will be returned.
///
/// A notable exception is the `nonce` parameter, that is common to most AEAD constructions.
///
/// If a nonce is required but was not supplied:
///
/// - If it is safe to do so, the host will automatically generate a nonce. This is true for nonces that are large enough to be randomly generated, or if the host is able to maintain a global counter.
/// - If not, the function will fail and return the dedicated `nonce_required` error code.
///
/// A nonce that was automatically generated can be retrieved after the function returns with `symmetric_state_get(state_handle, "nonce")`.
///
/// **Sample usage patterns:**
///
/// - **Hashing**
///
/// ```rust
/// let mut out = [0u8; 64];
/// let state_handle = ctx.symmetric_state_open("SHAKE-128", None, None)?;
/// ctx.symmetric_state_absorb(state_handle, b"data")?;
/// ctx.symmetric_state_absorb(state_handle, b"more_data")?;
/// ctx.symmetric_state_squeeze(state_handle, &mut out)?;
/// ```
///
/// - **MAC**
///
/// ```rust
/// let mut raw_tag = [0u8; 64];
/// let key_handle = ctx.symmetric_key_import("HMAC/SHA-512", b"key")?;
/// let state_handle = ctx.symmetric_state_open("HMAC/SHA-512", Some(key_handle), None)?;
/// ctx.symmetric_state_absorb(state_handle, b"data")?;
/// ctx.symmetric_state_absorb(state_handle, b"more_data")?;
/// let computed_tag_handle = ctx.symmetric_state_squeeze_tag(state_handle)?;
/// ctx.symmetric_tag_pull(computed_tag_handle, &mut raw_tag)?;
/// ```
///
/// Verification:
///
/// ```rust
/// let state_handle = ctx.symmetric_state_open("HMAC/SHA-512", Some(key_handle), None)?;
/// ctx.symmetric_state_absorb(state_handle, b"data")?;
/// ctx.symmetric_state_absorb(state_handle, b"more_data")?;
/// let computed_tag_handle = ctx.symmetric_state_squeeze_tag(state_handle)?;
/// ctx.symmetric_tag_verify(computed_tag_handle, expected_raw_tag)?;
/// ```
///
/// - **Tuple hashing**
///
/// ```rust
/// let mut out = [0u8; 64];
/// let state_handle = ctx.symmetric_state_open("TupleHashXOF256", None, None)?;
/// ctx.symmetric_state_absorb(state_handle, b"value 1")?;
/// ctx.symmetric_state_absorb(state_handle, b"value 2")?;
/// ctx.symmetric_state_absorb(state_handle, b"value 3")?;
/// ctx.symmetric_state_squeeze(state_handle, &mut out)?;
/// ```
/// Unlike MACs and regular hash functions, inputs are domain separated instead of being concatenated.
///
/// - **Key derivation using extract-and-expand**
///
/// Extract:
///
/// ```rust
/// let mut prk = vec![0u8; 64];
/// let key_handle = ctx.symmetric_key_import("HKDF-EXTRACT/SHA-512", b"key")?;
/// let state_handle = ctx.symmetric_state_open("HKDF-EXTRACT/SHA-512", Some(key_handle), None)?;
/// ctx.symmetric_state_absorb(state_handle, b"salt")?;
/// let prk_handle = ctx.symmetric_state_squeeze_key(state_handle, "HKDF-EXPAND/SHA-512")?;
/// ```
///
/// Expand:
///
/// ```rust
/// let mut subkey = vec![0u8; 32];
/// let state_handle = ctx.symmetric_state_open("HKDF-EXPAND/SHA-512", Some(prk_handle), None)?;
/// ctx.symmetric_state_absorb(state_handle, b"info")?;
/// ctx.symmetric_state_squeeze(state_handle, &mut subkey)?;
/// ```
///
/// - **Key derivation using a XOF**
///
/// ```rust
/// let mut subkey1 = vec![0u8; 32];
/// let mut subkey2 = vec![0u8; 32];
/// let key_handle = ctx.symmetric_key_import("BLAKE3", b"key")?;
/// let state_handle = ctx.symmetric_state_open("BLAKE3", Some(key_handle), None)?;
/// ctx.symmetric_absorb(state_handle, b"context")?;
/// ctx.squeeze(state_handle, &mut subkey1)?;
/// ctx.squeeze(state_handle, &mut subkey2)?;
/// ```
///
/// - **Password hashing**
///
/// ```rust
/// let mut memory = vec![0u8; 1_000_000_000];
/// let options_handle = ctx.symmetric_options_open()?;
/// ctx.symmetric_options_set_guest_buffer(options_handle, "memory", &mut memory)?;
/// ctx.symmetric_options_set_u64(options_handle, "opslimit", 5)?;
/// ctx.symmetric_options_set_u64(options_handle, "parallelism", 8)?;
///
/// let state_handle = ctx.symmetric_state_open("ARGON2-ID-13", None, Some(options))?;
/// ctx.symmtric_state_absorb(state_handle, b"password")?;
///
/// let pw_str_handle = ctx.symmetric_state_squeeze_tag(state_handle)?;
/// let mut pw_str = vec![0u8; ctx.symmetric_tag_len(pw_str_handle)?];
/// ctx.symmetric_tag_pull(pw_str_handle, &mut pw_str)?;
/// ```
///
/// - **AEAD encryption with an explicit nonce**
///
/// ```rust
/// let key_handle = ctx.symmetric_key_generate("AES-256-GCM", None)?;
/// let message = b"test";
///
/// let options_handle = ctx.symmetric_options_open()?;
/// ctx.symmetric_options_set(options_handle, "nonce", nonce)?;
///
/// let state_handle = ctx.symmetric_state_open("AES-256-GCM", Some(key_handle), Some(options_handle))?;
/// let mut ciphertext = vec![0u8; message.len() + ctx.symmetric_state_max_tag_len(state_handle)?];
/// ctx.symmetric_state_absorb(state_handle, "additional data")?;
/// ctx.symmetric_state_encrypt(state_handle, &mut ciphertext, message)?;
/// ```
///
/// - **AEAD encryption with automatic nonce generation**
///
/// ```rust
/// let key_handle = ctx.symmetric_key_generate("AES-256-GCM-SIV", None)?;
/// let message = b"test";
/// let mut nonce = [0u8; 24];
///
/// let state_handle = ctx.symmetric_state_open("AES-256-GCM-SIV", Some(key_handle), None)?;
///
/// let nonce = ctx.symmetric_state_options_get(state_handle, "nonce")?;
///
/// let mut ciphertext = vec![0u8; message.len() + ctx.symmetric_state_max_tag_len(state_handle)?];
/// ctx.symmetric_state_absorb(state_handle, "additional data")?;
/// ctx.symmetric_state_encrypt(state_handle, &mut ciphertext, message)?;
/// ```
///
/// - **Session authenticated modes**
///
/// ```rust
/// let mut out = [0u8; 16];
/// let mut out2 = [0u8; 16];
/// let mut ciphertext = [0u8; 20];
/// let key_handle = ctx.symmetric_key_generate("Xoodyak-128", None)?;
/// let state_handle = ctx.symmetric_state_open("Xoodyak-128", Some(key_handle), None)?;
/// ctx.symmetric_state_absorb(state_handle, b"data")?;
/// ctx.symmetric_state_encrypt(state_handle, &mut ciphertext, b"abcd")?;
/// ctx.symmetric_state_absorb(state_handle, b"more data")?;
/// ctx.symmetric_state_squeeze(state_handle, &mut out)?;
/// ctx.symmetric_state_squeeze(state_handle, &mut out2)?;
/// ctx.symmetric_state_ratchet(state_handle)?;
/// ctx.symmetric_state_absorb(state_handle, b"more data")?;
/// let next_key_handle = ctx.symmetric_state_squeeze_key(state_handle, "Xoodyak-128")?;
/// // ...
/// ```
symmetric-state-open: func(
algorithm: string,
key: opt-symmetric-key,
options: opt-options,
) -> result<symmetric-state, crypto-errno>;
/// Retrieve a parameter from the current state.
///
/// In particular, `symmetric_state_options_get("nonce")` can be used to get a nonce that as automatically generated.
///
/// The function may return `options_not_set` if an option was not set, which is different from an empty value.
///
/// It may also return `unsupported_option` if the option doesn't exist for the chosen algorithm.
symmetric-state-options-get: func(
handle: symmetric-state,
name: string,
value: borrow<u8>,
value-max-len: size,
) -> result<size, crypto-errno>;
/// Retrieve an integer parameter from the current state.
///
/// The function may return `options_not_set` if an option was not set.
///
/// It may also return `unsupported_option` if the option doesn't exist for the chosen algorithm.
symmetric-state-options-get-u-64: func(
handle: symmetric-state,
name: string,
) -> result<u-64, crypto-errno>;
/// Clone a symmetric state.
///
/// The function clones the internal state, assigns a new handle to it and returns the new handle.
symmetric-state-clone: func(
handle: symmetric-state,
) -> result<symmetric-state, crypto-errno>;
/// Destroy a symmetric state.
///
/// Objects are reference counted. It is safe to close an object immediately after the last function needing it is called.
symmetric-state-close: func(
handle: symmetric-state,
) -> result<_, crypto-errno>;
/// Absorb data into the state.
///
/// - **Hash functions:** adds data to be hashed.
/// - **MAC functions:** adds data to be authenticated.
/// - **Tuplehash-like constructions:** adds a new tuple to the state.
/// - **Key derivation functions:** adds to the IKM or to the subkey information.
/// - **AEAD constructions:** adds additional data to be authenticated.
/// - **Stateful hash objects, permutation-based constructions:** absorbs.
///
/// If the chosen algorithm doesn't accept input data, the `invalid_operation` error code is returned.
///
/// If too much data has been fed for the algorithm, `overflow` may be thrown.
symmetric-state-absorb: func(
handle: symmetric-state,
data: list<u8>,
) -> result<_, crypto-errno>;
/// Squeeze bytes from the state.
///
/// - **Hash functions:** this tries to output an `out_len` bytes digest from the absorbed data. The hash function output will be truncated if necessary. If the requested size is too large, the `invalid_len` error code is returned.
/// - **Key derivation functions:** : outputs an arbitrary-long derived key.
/// - **RNGs, DRBGs, stream ciphers:**: outputs arbitrary-long data.
/// - **Stateful hash objects, permutation-based constructions:** squeeze.
///
/// Other kinds of algorithms may return `invalid_operation` instead.
///
/// For password-stretching functions, the function may return `in_progress`.
/// In that case, the guest should retry with the same parameters until the function completes.
symmetric-state-squeeze: func(
handle: symmetric-state,
out: borrow<list<u8>>,
) -> result<_, crypto-errno>;
/// Compute and return a tag for all the data injected into the state so far.
///
/// - **MAC functions**: returns a tag authenticating the absorbed data.
/// - **Tuplehash-like constructions:** returns a tag authenticating all the absorbed tuples.
/// - **Password-hashing functions:** returns a standard string containing all the required parameters for password verification.
///
/// Other kinds of algorithms may return `invalid_operation` instead.
///
/// For password-stretching functions, the function may return `in_progress`.
/// In that case, the guest should retry with the same parameters until the function completes.
symmetric-state-squeeze-tag: func(
handle: symmetric-state,
) -> result<symmetric-tag, crypto-errno>;
/// Use the current state to produce a key for a target algorithm.
///
/// For extract-then-expand constructions, this returns the PRK.
/// For session-base authentication encryption, this returns a key that can be used to resume a session without storing a nonce.
///
/// `invalid_operation` is returned for algorithms not supporting this operation.
symmetric-state-squeeze-key: func(
handle: symmetric-state,
alg-str: string,
) -> result<symmetric-key, crypto-errno>;
/// Return the maximum length of an authentication tag for the current algorithm.
///
/// This allows guests to compute the size required to store a ciphertext along with its authentication tag.
///
/// The returned length may include the encryption mode's padding requirements in addition to the actual tag.
///
/// For an encryption operation, the size of the output buffer should be `input_len + symmetric_state_max_tag_len()`.
///
/// For a decryption operation, the size of the buffer that will store the decrypted data must be `ciphertext_len - symmetric_state_max_tag_len()`.
symmetric-state-max-tag-len: func(
handle: symmetric-state,
) -> result<size, crypto-errno>;
/// Encrypt data with an attached tag.
///
/// - **Stream cipher:** adds the input to the stream cipher output. `out_len` and `data_len` can be equal, as no authentication tags will be added.
/// - **AEAD:** encrypts `data` into `out`, including the authentication tag to the output. Additional data must have been previously absorbed using `symmetric_state_absorb()`. The `symmetric_state_max_tag_len()` function can be used to retrieve the overhead of adding the tag, as well as padding if necessary.
/// - **SHOE, Xoodyak, Strobe:** encrypts data, squeezes a tag and appends it to the output.
///
/// If `out` and `data` are the same address, encryption may happen in-place.
///
/// The function returns the actual size of the ciphertext along with the tag.
///
/// `invalid_operation` is returned for algorithms not supporting encryption.
symmetric-state-encrypt: func(
handle: symmetric-state,
out: borrow<list<u8>>,
data: list<u8>,
) -> result<size, crypto-errno>;
/// Encrypt data, with a detached tag.
///
/// - **Stream cipher:** returns `invalid_operation` since stream ciphers do not include authentication tags.
/// - **AEAD:** encrypts `data` into `out` and returns the tag separately. Additional data must have been previously absorbed using `symmetric_state_absorb()`. The output and input buffers must be of the same length.
/// - **SHOE, Xoodyak, Strobe:** encrypts data and squeezes a tag.
///
/// If `out` and `data` are the same address, encryption may happen in-place.
///
/// The function returns the tag.
///
/// `invalid_operation` is returned for algorithms not supporting encryption.
symmetric-state-encrypt-detached: func(
handle: symmetric-state,
out: borrow<list<u8>>,
data: list<u8>,
) -> result<symmetric-tag, crypto-errno>;
/// - **Stream cipher:** adds the input to the stream cipher output. `out_len` and `data_len` can be equal, as no authentication tags will be added.
/// - **AEAD:** decrypts `data` into `out`. Additional data must have been previously absorbed using `symmetric_state_absorb()`.
/// - **SHOE, Xoodyak, Strobe:** decrypts data, squeezes a tag and verify that it matches the one that was appended to the ciphertext.
///
/// If `out` and `data` are the same address, decryption may happen in-place.
///
/// `out_len` must be exactly `data_len` + `max_tag_len` bytes.
///
/// The function returns the actual size of the decrypted message, which can be smaller than `out_len` for modes that requires padding.
///
/// `invalid_tag` is returned if the tag didn't verify.
///
/// `invalid_operation` is returned for algorithms not supporting encryption.
symmetric-state-decrypt: func(
handle: symmetric-state,
out: borrow<list<u8>>,
data: list<u8>,
) -> result<size, crypto-errno>;
/// - **Stream cipher:** returns `invalid_operation` since stream ciphers do not include authentication tags.
/// - **AEAD:** decrypts `data` into `out`. Additional data must have been previously absorbed using `symmetric_state_absorb()`.
/// - **SHOE, Xoodyak, Strobe:** decrypts data, squeezes a tag and verify that it matches the expected one.
///
/// `raw_tag` is the expected tag, as raw bytes.
///
/// `out` and `data` be must have the same length.
/// If they also share the same address, decryption may happen in-place.
///
/// The function returns the actual size of the decrypted message.
///
/// `invalid_tag` is returned if the tag verification failed.
///
/// `invalid_operation` is returned for algorithms not supporting encryption.
symmetric-state-decrypt-detached: func(
handle: symmetric-state,
out: borrow<list<u8>>,
data: list<u8>,
raw-tag: list<u8>,
) -> result<size, crypto-errno>;
/// Make it impossible to recover the previous state.
///
/// This operation is supported by some systems keeping a rolling state over an entire session, for forward security.
///
/// `invalid_operation` is returned for algorithms not supporting ratcheting.
symmetric-state-ratchet: func(
handle: symmetric-state,
) -> result<_, crypto-errno>;
/// Return the length of an authentication tag.
///
/// This function can be used by a guest to allocate the correct buffer size to copy a computed authentication tag.
symmetric-tag-len: func(
symmetric-tag: symmetric-tag,
) -> result<size, crypto-errno>;
/// Copy an authentication tag into a guest-allocated buffer.
///
/// The handle automatically becomes invalid after this operation. Manually closing it is not required.
///
/// Example usage:
///
/// ```rust
/// let mut raw_tag = [0u8; 16];
/// ctx.symmetric_tag_pull(raw_tag_handle, &mut raw_tag)?;
/// ```
///
/// The function returns `overflow` if the supplied buffer is too small to copy the tag.
///
/// Otherwise, it returns the number of bytes that have been copied.
symmetric-tag-pull: func(
symmetric-tag: symmetric-tag,
buf: borrow<list<u8>>,
) -> result<size, crypto-errno>;
/// Verify that a computed authentication tag matches the expected value, in constant-time.
///
/// The expected tag must be provided as a raw byte string.
///
/// The function returns `invalid_tag` if the tags don't match.
///
/// Example usage:
///
/// ```rust
/// let key_handle = ctx.symmetric_key_import("HMAC/SHA-256", b"key")?;
/// let state_handle = ctx.symmetric_state_open("HMAC/SHA-256", Some(key_handle), None)?;
/// ctx.symmetric_state_absorb(state_handle, b"data")?;
/// let computed_tag_handle = ctx.symmetric_state_squeeze_tag(state_handle)?;
/// ctx.symmetric_tag_verify(computed_tag_handle, expected_raw_tag)?;
/// ```
symmetric-tag-verify: func(
symmetric-tag: symmetric-tag,
expected-raw-tag-ptr: u8,
expected-raw-tag-len: size,
) -> result<_, crypto-errno>;
/// Explicitly destroy an unused authentication tag.
///
/// This is usually not necessary, as `symmetric_tag_pull()` automatically closes a tag after it has been copied.
///
/// Objects are reference counted. It is safe to close an object immediately after the last function needing it is called.
symmetric-tag-close: func(
symmetric-tag: symmetric-tag,
) -> result<_, crypto-errno>;
}
// ---------------------- Interface: [wasi_ephemeral_crypto_symmetric_batch] ----------------------
interface wasi-ephemeral-crypto-symmetric-batch {
/// An output buffer
type output = borrow<list<u8>>;
type output-len = u32;
/// A non-mutable data buffer
type data = list<u8>;
type data-len = u32;
/// An raw tag buffer
type raw-tag = list<u8>;
type raw-tag-len = u32;
/// Tuple representing results and size produced by an encrypt/decrypt operation.
crypt-result: tuple<size, crypto-errno>;
/// A list of results from the individual encrypt/decrypt operations within a batch operation.
type batch-crypt-results = list<crypt-result>;
/// Tuple representing results and size produced by a detached encrypt operation.
encrypt-detached-result: tuple<symmetric-tag, crypto-errno>;
/// A list of results from the individual encrypt/decrypt operations within a batch operation.
type batch-encrypt-detached-results = list<encrypt-detached-result>;
/// A list of results from squeeze operation within a batch operation.
type batch-squeeze-results = list<crypto-errno>;
/// Tuple representing results and tag and error produced by a detached squeeze operation.
squeeze-detached-result: tuple<symmetric-tag, crypto-errno>;
/// A list of results from the individual detached squeeze operations within a batch operation.
type batch-squeeze-detached-results = list<squeeze-detached-result>;
// Functions
/// Batch of operations to squeeze bytes from a batch of states.
///
/// This is a batch version of the $symmetric_state_squeeze operation.
///
/// Each entry in the batch corresponds to an individual squeeze operation.
/// The parameters associated with each operation are grouped into a tuple.
///
/// The batch operation returns an error code of type $crypto_errno that
/// indicates if the batch was processed or if the batch could not be
/// processed.
///
/// Batch processing error codes:
/// - `success`: Batch was processed. The status of each operation is indicated in the results list.
/// - `not_implemented`: Batch functionality is not supported.
/// - `unsupported_feature`: Inconsistent operations within the batch, e.g. not all operations in the batch use the same algorithm.
///
/// If the batch was processed, the result is a list of $crypto_errno error
/// codes that represent the status of the operation in the input list at
/// the same list offset.
///
batch-symmetric-state-squeeze: func(
batch: list<tuple<symmetric-state, data, data-len>>,
) -> result<batch-squeeze-results, crypto-errno>;
/// Batch of operations to compute and return a tag for all the data
/// injected into the state so far.
///
/// This is a batch version of the $symmetric_state_squeeze_tag operation.
///
/// Each entry in the batch corresponds to an individual squeeze_tag
/// operation. The parameters associated with each operation are grouped
/// into a tuple.
///
/// The batch operation returns an error code of type $crypto_errno that
/// indicates if the batch was processed or if the batch could not be
/// processed.
///
/// Batch processing error codes:
/// - `success`: Batch was processed. The status of each operation is indicated in the results list.
/// - `not_implemented`: Batch functionality is not supported.
/// - `unsupported_feature`: Inconsistent operations within the batch, e.g. not all operations in the batch use the same algorithm.
///
/// If the batch was processed, the result is a list of tuples, with each
/// list entry corresponding to the operation in the input list at the same
/// list offset. Each tuple contains a $crypto_errno error code and a tag.
/// The error code represents the status of the operation and the tag is the
/// tag generated from the squeeze operation. The tag is only valid if the
/// tuple's error code is `success`.
///
batch-symmetric-state-squeeze-tag: func(
states: list<symmetric-state>,
) -> result<batch-squeeze-detached-results, crypto-errno>;
/// Perform a batch of symmetric encrypt operations.
///
/// This is a batch version of the symmetric_state_encrypt operation.
///
/// Each entry in the batch corresponds to an individual encrypt operation.
/// The parameters associated with each encrypt operation are grouped into a
/// tuple.
///
/// The batch operation returns an error code of type $crypto_errno that
/// indicates if the batch was processed or if the batch could not be
/// processed.
///
/// Batch processing error codes:
/// - `success`: Batch was processed. The status of each operation is indicated in the results list.
/// - `not_implemented`: Batch functionality is not supported.
/// - `unsupported_feature`: Inconsistent operations within the batch, e.g. not all operations in the batch use the same algorithm.
///
/// If the batch was processed, the result is a list of tuples, with each
/// list entry corresponding to the operation in the input list at the same
/// list offset.
/// Each tuple contains a size and a $crypto_errno error code.
/// The error code represents the status of the operation and the size is
/// the actual size of the ciphertext and the tag in the ouput buffer. The
/// size value is only valid if the tuple's error code is `success`.
///
/// Example usage:
///
/// ```rust
/// let mut batch = Vec::new();
///
/// let state_handle = ctx.symmetric_state_open("AES-256-GCM", Some(key_handle1), Some(options_handle1))?;
/// let mut ciphertext = vec![0u8; message.len() + ctx.symmetric_state_max_tag_len(state_handle)?];
/// batch.push((batch, state_handle, ciphertext, ciphertext.len(), message, message.len()));
///
/// let state_handle = ctx.symmetric_state_open("AES-256-GCM", Some(key_handle2), Some(options_handle2))?;
/// let mut ciphertext = vec![0u8; message2.len() + ctx.symmetric_state_max_tag_len(state_handle)?];
/// batch.push((batch, state_handle, ciphertext, ciphertext.len(), message2, message2.len()));
///
/// let results = ctx.batch_symmetric_state_encrypt(batch)?;
/// ```
batch-symmetric-state-encrypt: func(
batch: list<tuple<symmetric-state, output, output-len, data, data-len>>,
) -> result<batch-crypt-results, crypto-errno>;
/// Perform a batch of symmetric encrypt operations with detached tags.
///
/// This is a batch version of the symmetric_state_encrypt_detached
/// operation.
///
/// Each entry in the batch corresponds to an individual encrypt operation.
/// The parameters associated with each encrypt operation are grouped into a
/// tuple.
///
/// The batch operation returns an error code of type $crypto_errno that
/// indicates if the batch was processed or if the batch could not be
/// processed.
///
/// Batch processing error codes:
/// - `success`: Batch was processed. The status of each operation is indicated in the results list.
/// - `not_implemented`: Batch functionality is not supported.
/// - `unsupported_feature`: Inconsistent operations within the batch, e.g. not all operations in the batch use the same algorithm.
///
/// If the batch was processed, the result is a list of tuples, with each
/// list entry corresponding to the operation in the input list at the same
/// list offset.
/// Each tuple contains a tag and a $crypto_errno error code.
/// The error code represents the status of the operation and the tag is
/// the tag generated by the operation. The tag is only valid if the tuple's
/// error code is `success`.
///
/// Example usage:
///
/// ```rust
/// let mut batch = Vec::new();
///
/// let state_handle = ctx.symmetric_state_open("AES-256-GCM", Some(key_handle1), Some(options_handle1))?;
/// let mut ciphertext = vec![0u8; message.len() + ctx.symmetric_state_max_tag_len(state_handle)?];
/// batch.push((batch, state_handle, ciphertext, ciphertext.len(), message, message.len()));
///
/// let state_handle = ctx.symmetric_state_open("AES-256-GCM", Some(key_handle2), Some(options_handle2))?;
/// let mut ciphertext = vec![0u8; message2.len() + ctx.symmetric_state_max_tag_len(state_handle)?];
/// batch.push((batch, state_handle, ciphertext, ciphertext.len(), message2, message2.len()));
///
/// let results = ctx.batch_symmetric_state_encrypt_detached(batch)?;
/// ```
batch-symmetric-state-encrypt-detached: func(
batch: list<tuple<symmetric-state, output, output-len, data, data-len>>,
) -> result<batch-encrypt-detached-results, crypto-errno>;
/// Perform a batch of symmetric decrypt operations.
///
/// This is a batch version of the symmetric_state_decrypt operation.
///
/// Each entry in the batch corresponds to an individual decrypt operation.
/// The parameters associated with each decrypt operation are grouped into a
/// tuple.
///
/// The batch operation returns an error code of type $crypto_errno that
/// indicates if the batch was processed or if the batch could not be
/// processed.
///
/// Batch processing error codes:
/// - `success`: Batch was processed. The status of each operation is indicated in the results list.
/// - `not_implemented`: Batch functionality is not supported.
/// - `unsupported_feature`: Inconsistent operations within the batch, e.g. not all operations in the batch use the same algorithm.
///
/// If the batch was processed, the result is a list of tuples, with each
/// list entry corresponding to the operation in the input list at the same
/// list offset.
/// Each tuple contains a size and a $crypto_errno error code.
/// The error code represents the status of the operation and the size is
/// the actual size of the decrypted data in the ouput buffer. The size
/// value is only valid if the tuple's error code is `success`.
///
batch-symmetric-state-decrypt: func(
batch: list<tuple<symmetric-state, output, output-len, data, data-len>>,
) -> result<batch-crypt-results, crypto-errno>;
/// Perform a batch of symmetric decrypt operations with detached tags.
///
/// This is a batch version of the symmetric_state_decrypt_detached operation.
///
/// Each entry in the batch corresponds to an individual decrypt operation.
/// The parameters associated with each decrypt operation are grouped into a
/// tuple.
///
/// The batch operation returns an error code of type $crypto_errno that
/// indicates if the batch was processed or if the batch could not be
/// processed.
///
/// Batch processing error codes:
/// - `success`: Batch was processed. The status of each operation is indicated in the results list.
/// - `not_implemented`: Batch functionality is not supported.
/// - `unsupported_feature`: Inconsistent operations within the batch, e.g. not all operations in the batch use the same algorithm.
///
/// If the batch was processed, the result is a list of tuples, with each
/// list entry corresponding to the operation in the input list at the same
/// list offset.
/// Each tuple contains a size and a $crypto_errno error code.
/// The error code represents the status of the operation and the size is
/// the actual size of the decrypted data in the ouput buffer. The size
/// value is only valid if the tuple's error code is `success`.
///
batch-symmetric-state-decrypt-detached: func(
batch: list<tuple<symmetric-state, output, output-len, data, data-len, raw-tag, raw-tag-len>>,
) -> result<batch-crypt-results, crypto-errno>;
}