# Module: wasi_ephemeral_crypto_symmetric ## Table of contents ### Types list: [**[All](#types)**] - [_[`crypto_errno`](#crypto_errno)_] - [_[`keypair_encoding`](#keypair_encoding)_] - [_[`publickey_encoding`](#publickey_encoding)_] - [_[`secretkey_encoding`](#secretkey_encoding)_] - [_[`signature_encoding`](#signature_encoding)_] - [_[`algorithm_type`](#algorithm_type)_] - [_[`version`](#version)_] - [_[`size`](#size)_] - [_[`timestamp`](#timestamp)_] - [_[`u64`](#u64)_] - [_[`array_output`](#array_output)_] - [_[`options`](#options)_] - [_[`secrets_manager`](#secrets_manager)_] - [_[`keypair`](#keypair)_] - [_[`signature_state`](#signature_state)_] - [_[`signature`](#signature)_] - [_[`publickey`](#publickey)_] - [_[`secretkey`](#secretkey)_] - [_[`signature_verification_state`](#signature_verification_state)_] - [_[`symmetric_state`](#symmetric_state)_] - [_[`symmetric_key`](#symmetric_key)_] - [_[`symmetric_tag`](#symmetric_tag)_] - [_[`opt_options_u`](#opt_options_u)_] - [_[`opt_options`](#opt_options)_] - [_[`opt_symmetric_key_u`](#opt_symmetric_key_u)_] - [_[`opt_symmetric_key`](#opt_symmetric_key)_] ### Functions list: [**[All](#functions)**] - [[`symmetric_key_generate()`](#symmetric_key_generate)] - [[`symmetric_key_import()`](#symmetric_key_import)] - [[`symmetric_key_export()`](#symmetric_key_export)] - [[`symmetric_key_close()`](#symmetric_key_close)] - [[`symmetric_key_generate_managed()`](#symmetric_key_generate_managed)] - [[`symmetric_key_store_managed()`](#symmetric_key_store_managed)] - [[`symmetric_key_replace_managed()`](#symmetric_key_replace_managed)] - [[`symmetric_key_id()`](#symmetric_key_id)] - [[`symmetric_key_from_id()`](#symmetric_key_from_id)] - [[`symmetric_state_open()`](#symmetric_state_open)] - [[`symmetric_state_options_get()`](#symmetric_state_options_get)] - [[`symmetric_state_options_get_u64()`](#symmetric_state_options_get_u64)] - [[`symmetric_state_close()`](#symmetric_state_close)] - [[`symmetric_state_absorb()`](#symmetric_state_absorb)] - [[`symmetric_state_squeeze()`](#symmetric_state_squeeze)] - [[`symmetric_state_squeeze_tag()`](#symmetric_state_squeeze_tag)] - [[`symmetric_state_squeeze_key()`](#symmetric_state_squeeze_key)] - [[`symmetric_state_max_tag_len()`](#symmetric_state_max_tag_len)] - [[`symmetric_state_encrypt()`](#symmetric_state_encrypt)] - [[`symmetric_state_encrypt_detached()`](#symmetric_state_encrypt_detached)] - [[`symmetric_state_decrypt()`](#symmetric_state_decrypt)] - [[`symmetric_state_decrypt_detached()`](#symmetric_state_decrypt_detached)] - [[`symmetric_state_ratchet()`](#symmetric_state_ratchet)] - [[`symmetric_tag_len()`](#symmetric_tag_len)] - [[`symmetric_tag_pull()`](#symmetric_tag_pull)] - [[`symmetric_tag_verify()`](#symmetric_tag_verify)] - [[`symmetric_tag_close()`](#symmetric_tag_close)] ## Types ### _[`crypto_errno`](#crypto_errno)_ Enumeration with tag type: `u16`, and the following members: * **`success`**: _[`crypto_errno`](#crypto_errno)_ * **`guest_error`**: _[`crypto_errno`](#crypto_errno)_ * **`not_implemented`**: _[`crypto_errno`](#crypto_errno)_ * **`unsupported_feature`**: _[`crypto_errno`](#crypto_errno)_ * **`prohibited_operation`**: _[`crypto_errno`](#crypto_errno)_ * **`unsupported_encoding`**: _[`crypto_errno`](#crypto_errno)_ * **`unsupported_algorithm`**: _[`crypto_errno`](#crypto_errno)_ * **`unsupported_option`**: _[`crypto_errno`](#crypto_errno)_ * **`invalid_key`**: _[`crypto_errno`](#crypto_errno)_ * **`invalid_length`**: _[`crypto_errno`](#crypto_errno)_ * **`verification_failed`**: _[`crypto_errno`](#crypto_errno)_ * **`rng_error`**: _[`crypto_errno`](#crypto_errno)_ * **`algorithm_failure`**: _[`crypto_errno`](#crypto_errno)_ * **`invalid_signature`**: _[`crypto_errno`](#crypto_errno)_ * **`closed`**: _[`crypto_errno`](#crypto_errno)_ * **`invalid_handle`**: _[`crypto_errno`](#crypto_errno)_ * **`overflow`**: _[`crypto_errno`](#crypto_errno)_ * **`internal_error`**: _[`crypto_errno`](#crypto_errno)_ * **`too_many_handles`**: _[`crypto_errno`](#crypto_errno)_ * **`key_not_supported`**: _[`crypto_errno`](#crypto_errno)_ * **`key_required`**: _[`crypto_errno`](#crypto_errno)_ * **`invalid_tag`**: _[`crypto_errno`](#crypto_errno)_ * **`invalid_operation`**: _[`crypto_errno`](#crypto_errno)_ * **`nonce_required`**: _[`crypto_errno`](#crypto_errno)_ * **`invalid_nonce`**: _[`crypto_errno`](#crypto_errno)_ * **`option_not_set`**: _[`crypto_errno`](#crypto_errno)_ * **`not_found`**: _[`crypto_errno`](#crypto_errno)_ * **`parameters_missing`**: _[`crypto_errno`](#crypto_errno)_ * **`in_progress`**: _[`crypto_errno`](#crypto_errno)_ * **`incompatible_keys`**: _[`crypto_errno`](#crypto_errno)_ * **`expired`**: _[`crypto_errno`](#crypto_errno)_ > Error codes. --- ### _[`keypair_encoding`](#keypair_encoding)_ Enumeration with tag type: `u16`, and the following members: * **`raw`**: _[`keypair_encoding`](#keypair_encoding)_ * **`pkcs8`**: _[`keypair_encoding`](#keypair_encoding)_ * **`pem`**: _[`keypair_encoding`](#keypair_encoding)_ * **`local`**: _[`keypair_encoding`](#keypair_encoding)_ > Encoding to use for importing or exporting a key pair. --- ### _[`publickey_encoding`](#publickey_encoding)_ Enumeration with tag type: `u16`, and the following members: * **`raw`**: _[`publickey_encoding`](#publickey_encoding)_ * **`pkcs8`**: _[`publickey_encoding`](#publickey_encoding)_ * **`pem`**: _[`publickey_encoding`](#publickey_encoding)_ * **`sec`**: _[`publickey_encoding`](#publickey_encoding)_ * **`compressed_sec`**: _[`publickey_encoding`](#publickey_encoding)_ * **`local`**: _[`publickey_encoding`](#publickey_encoding)_ > Encoding to use for importing or exporting a public key. --- ### _[`secretkey_encoding`](#secretkey_encoding)_ Enumeration with tag type: `u16`, and the following members: * **`raw`**: _[`secretkey_encoding`](#secretkey_encoding)_ * **`pkcs8`**: _[`secretkey_encoding`](#secretkey_encoding)_ * **`pem`**: _[`secretkey_encoding`](#secretkey_encoding)_ * **`sec`**: _[`secretkey_encoding`](#secretkey_encoding)_ * **`compressed_sec`**: _[`secretkey_encoding`](#secretkey_encoding)_ * **`local`**: _[`secretkey_encoding`](#secretkey_encoding)_ > Encoding to use for importing or exporting a secret key. --- ### _[`signature_encoding`](#signature_encoding)_ Enumeration with tag type: `u16`, and the following members: * **`raw`**: _[`signature_encoding`](#signature_encoding)_ * **`der`**: _[`signature_encoding`](#signature_encoding)_ > Encoding to use for importing or exporting a signature. --- ### _[`algorithm_type`](#algorithm_type)_ Enumeration with tag type: `u16`, and the following members: * **`signatures`**: _[`algorithm_type`](#algorithm_type)_ * **`symmetric`**: _[`algorithm_type`](#algorithm_type)_ * **`key_exchange`**: _[`algorithm_type`](#algorithm_type)_ > An algorithm category. --- ### _[`version`](#version)_ Alias for `u64`. > Version of a managed key. > > A version can be an arbitrary `u64` integer, with the expection of some reserved values. --- ### _[`size`](#size)_ Alias for `usize`. > Size of a value. --- ### _[`timestamp`](#timestamp)_ Alias for `u64`. > A UNIX timestamp, in seconds since 01/01/1970. --- ### _[`u64`](#u64)_ Alias for `u64`. > A 64-bit value --- ### _[`array_output`](#array_output)_ Alias for `handle`. > 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. --- ### _[`options`](#options)_ Alias for `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. --- ### _[`secrets_manager`](#secrets_manager)_ Alias for `handle`. > A handle to the optional secrets management facilities offered by a host. > > This is used to generate, retrieve and invalidate managed keys. --- ### _[`keypair`](#keypair)_ Alias for `handle`. > A key pair. --- ### _[`signature_state`](#signature_state)_ Alias for `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. --- ### _[`signature`](#signature)_ Alias for `handle`. > A signature. --- ### _[`publickey`](#publickey)_ Alias for `handle`. > A public key, for key exchange and signature verification. --- ### _[`secretkey`](#secretkey)_ Alias for `handle`. > A secret key, for key exchange mechanisms. --- ### _[`signature_verification_state`](#signature_verification_state)_ Alias for `handle`. > A state to absorb signed data to be verified. --- ### _[`symmetric_state`](#symmetric_state)_ Alias for `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. --- ### _[`symmetric_key`](#symmetric_key)_ Alias for `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. --- ### _[`symmetric_tag`](#symmetric_tag)_ Alias for `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. --- ### _[`opt_options_u`](#opt_options_u)_ Enumeration with tag type: `u8`, and the following members: * **`some`**: _[`opt_options_u`](#opt_options_u)_ * **`none`**: _[`opt_options_u`](#opt_options_u)_ > Options index, only required by the Interface Types translation layer. --- ### _[`opt_options`](#opt_options)_ Tagged union with tag type: `u8` and the following possibilities: * **`some`**: _[`options`](#options)_ * **`none`**: _(empty)_ > An optional options set. > > This union simulates an `Option\` type to make the `options` parameter of some functions optional. --- ### _[`opt_symmetric_key_u`](#opt_symmetric_key_u)_ Enumeration with tag type: `u8`, and the following members: * **`some`**: _[`opt_symmetric_key_u`](#opt_symmetric_key_u)_ * **`none`**: _[`opt_symmetric_key_u`](#opt_symmetric_key_u)_ > Symmetric key index, only required by the Interface Types translation layer. --- ### _[`opt_symmetric_key`](#opt_symmetric_key)_ Tagged union with tag type: `u8` and the following possibilities: * **`some`**: _[`symmetric_key`](#symmetric_key)_ * **`none`**: _(empty)_ > An optional symmetric key. > > This union simulates an `Option\` type to make the `symmetric_key` parameter of some functions optional. --- ## Functions ### [`symmetric_key_generate()`](#symmetric_key_generate) Returned error type: _[`crypto_errno`](#crypto_errno)_ #### Input: * **`algorithm`**: `string` * **`options`**: _[`opt_options`](#opt_options)_ #### Output: * _[`symmetric_key`](#symmetric_key)_ mutable pointer > 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_import()`](#symmetric_key_import) Returned error type: _[`crypto_errno`](#crypto_errno)_ #### Input: * **`algorithm`**: `string` * **`raw`**: `u8` pointer * **`raw_len`**: _[`size`](#size)_ #### Output: * _[`symmetric_key`](#symmetric_key)_ mutable pointer > 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_export()`](#symmetric_key_export) Returned error type: _[`crypto_errno`](#crypto_errno)_ #### Input: * **`symmetric_key`**: _[`symmetric_key`](#symmetric_key)_ #### Output: * _[`array_output`](#array_output)_ mutable pointer > 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_close()`](#symmetric_key_close) Returned error type: _[`crypto_errno`](#crypto_errno)_ #### Input: * **`symmetric_key`**: _[`symmetric_key`](#symmetric_key)_ This function has no output. > 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_generate_managed()`](#symmetric_key_generate_managed) Returned error type: _[`crypto_errno`](#crypto_errno)_ #### Input: * **`secrets_manager`**: _[`secrets_manager`](#secrets_manager)_ * **`algorithm`**: `string` * **`options`**: _[`opt_options`](#opt_options)_ #### Output: * _[`symmetric_key`](#symmetric_key)_ mutable pointer > __(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_store_managed()`](#symmetric_key_store_managed) Returned error type: _[`crypto_errno`](#crypto_errno)_ #### Input: * **`secrets_manager`**: _[`secrets_manager`](#secrets_manager)_ * **`symmetric_key`**: _[`symmetric_key`](#symmetric_key)_ * **`symmetric_key_id`**: `u8` mutable pointer * **`symmetric_key_id_max_len`**: _[`size`](#size)_ This function has no output. > __(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_replace_managed()`](#symmetric_key_replace_managed) Returned error type: _[`crypto_errno`](#crypto_errno)_ #### Input: * **`secrets_manager`**: _[`secrets_manager`](#secrets_manager)_ * **`symmetric_key_old`**: _[`symmetric_key`](#symmetric_key)_ * **`symmetric_key_new`**: _[`symmetric_key`](#symmetric_key)_ #### Output: * _[`version`](#version)_ mutable pointer > __(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_id()`](#symmetric_key_id) Returned error type: _[`crypto_errno`](#crypto_errno)_ #### Input: * **`symmetric_key`**: _[`symmetric_key`](#symmetric_key)_ * **`symmetric_key_id`**: `u8` mutable pointer * **`symmetric_key_id_max_len`**: _[`size`](#size)_ #### Output: * _[`size`](#size)_ mutable pointer * _[`version`](#version)_ mutable pointer > __(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_from_id()`](#symmetric_key_from_id) Returned error type: _[`crypto_errno`](#crypto_errno)_ #### Input: * **`secrets_manager`**: _[`secrets_manager`](#secrets_manager)_ * **`symmetric_key_id`**: `u8` pointer * **`symmetric_key_id_len`**: _[`size`](#size)_ * **`symmetric_key_version`**: _[`version`](#version)_ #### Output: * _[`symmetric_key`](#symmetric_key)_ mutable pointer > __(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_state_open()`](#symmetric_state_open) Returned error type: _[`crypto_errno`](#crypto_errno)_ #### Input: * **`algorithm`**: `string` * **`key`**: _[`opt_symmetric_key`](#opt_symmetric_key)_ * **`options`**: _[`opt_options`](#opt_options)_ #### Output: * _[`symmetric_state`](#symmetric_state)_ mutable pointer > 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_handle = ctx.symmetric_state_options_get(state_handle, "nonce")?; > ctx.array_output_pull(nonce_handle, &mut 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_options_get()`](#symmetric_state_options_get) Returned error type: _[`crypto_errno`](#crypto_errno)_ #### Input: * **`handle`**: _[`symmetric_state`](#symmetric_state)_ * **`name`**: `string` * **`value`**: `u8` mutable pointer * **`value_max_len`**: _[`size`](#size)_ #### Output: * _[`size`](#size)_ mutable pointer > 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_u64()`](#symmetric_state_options_get_u64) Returned error type: _[`crypto_errno`](#crypto_errno)_ #### Input: * **`handle`**: _[`symmetric_state`](#symmetric_state)_ * **`name`**: `string` #### Output: * _[`u64`](#u64)_ mutable pointer > Retrieve an integer 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. > > It may also return `unsupported_option` if the option doesn't exist for the chosen algorithm. --- ### [`symmetric_state_close()`](#symmetric_state_close) Returned error type: _[`crypto_errno`](#crypto_errno)_ #### Input: * **`handle`**: _[`symmetric_state`](#symmetric_state)_ This function has no output. > 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_absorb()`](#symmetric_state_absorb) Returned error type: _[`crypto_errno`](#crypto_errno)_ #### Input: * **`handle`**: _[`symmetric_state`](#symmetric_state)_ * **`data`**: `u8` pointer * **`data_len`**: _[`size`](#size)_ This function has no output. > 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_squeeze()`](#symmetric_state_squeeze) Returned error type: _[`crypto_errno`](#crypto_errno)_ #### Input: * **`handle`**: _[`symmetric_state`](#symmetric_state)_ * **`out`**: `u8` mutable pointer * **`out_len`**: _[`size`](#size)_ This function has no output. > 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_tag()`](#symmetric_state_squeeze_tag) Returned error type: _[`crypto_errno`](#crypto_errno)_ #### Input: * **`handle`**: _[`symmetric_state`](#symmetric_state)_ #### Output: * _[`symmetric_tag`](#symmetric_tag)_ mutable pointer > 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_key()`](#symmetric_state_squeeze_key) Returned error type: _[`crypto_errno`](#crypto_errno)_ #### Input: * **`handle`**: _[`symmetric_state`](#symmetric_state)_ * **`alg_str`**: `string` #### Output: * _[`symmetric_key`](#symmetric_key)_ mutable pointer > 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_max_tag_len()`](#symmetric_state_max_tag_len) Returned error type: _[`crypto_errno`](#crypto_errno)_ #### Input: * **`handle`**: _[`symmetric_state`](#symmetric_state)_ #### Output: * _[`size`](#size)_ mutable pointer > 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_encrypt()`](#symmetric_state_encrypt) Returned error type: _[`crypto_errno`](#crypto_errno)_ #### Input: * **`handle`**: _[`symmetric_state`](#symmetric_state)_ * **`out`**: `u8` mutable pointer * **`out_len`**: _[`size`](#size)_ * **`data`**: `u8` pointer * **`data_len`**: _[`size`](#size)_ #### Output: * _[`size`](#size)_ mutable pointer > 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_detached()`](#symmetric_state_encrypt_detached) Returned error type: _[`crypto_errno`](#crypto_errno)_ #### Input: * **`handle`**: _[`symmetric_state`](#symmetric_state)_ * **`out`**: `u8` mutable pointer * **`out_len`**: _[`size`](#size)_ * **`data`**: `u8` pointer * **`data_len`**: _[`size`](#size)_ #### Output: * _[`symmetric_tag`](#symmetric_tag)_ mutable pointer > 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_decrypt()`](#symmetric_state_decrypt) Returned error type: _[`crypto_errno`](#crypto_errno)_ #### Input: * **`handle`**: _[`symmetric_state`](#symmetric_state)_ * **`out`**: `u8` mutable pointer * **`out_len`**: _[`size`](#size)_ * **`data`**: `u8` pointer * **`data_len`**: _[`size`](#size)_ #### Output: * _[`size`](#size)_ mutable pointer > - **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_detached()`](#symmetric_state_decrypt_detached) Returned error type: _[`crypto_errno`](#crypto_errno)_ #### Input: * **`handle`**: _[`symmetric_state`](#symmetric_state)_ * **`out`**: `u8` mutable pointer * **`out_len`**: _[`size`](#size)_ * **`data`**: `u8` pointer * **`data_len`**: _[`size`](#size)_ * **`raw_tag`**: `u8` pointer * **`raw_tag_len`**: _[`size`](#size)_ #### Output: * _[`size`](#size)_ mutable pointer > - **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_ratchet()`](#symmetric_state_ratchet) Returned error type: _[`crypto_errno`](#crypto_errno)_ #### Input: * **`handle`**: _[`symmetric_state`](#symmetric_state)_ This function has no output. > 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_tag_len()`](#symmetric_tag_len) Returned error type: _[`crypto_errno`](#crypto_errno)_ #### Input: * **`symmetric_tag`**: _[`symmetric_tag`](#symmetric_tag)_ #### Output: * _[`size`](#size)_ mutable pointer > 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_pull()`](#symmetric_tag_pull) Returned error type: _[`crypto_errno`](#crypto_errno)_ #### Input: * **`symmetric_tag`**: _[`symmetric_tag`](#symmetric_tag)_ * **`buf`**: `u8` mutable pointer * **`buf_len`**: _[`size`](#size)_ #### Output: * _[`size`](#size)_ mutable pointer > 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_verify()`](#symmetric_tag_verify) Returned error type: _[`crypto_errno`](#crypto_errno)_ #### Input: * **`symmetric_tag`**: _[`symmetric_tag`](#symmetric_tag)_ * **`expected_raw_tag_ptr`**: `u8` pointer * **`expected_raw_tag_len`**: _[`size`](#size)_ This function has no output. > 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_close()`](#symmetric_tag_close) Returned error type: _[`crypto_errno`](#crypto_errno)_ #### Input: * **`symmetric_tag`**: _[`symmetric_tag`](#symmetric_tag)_ This function has no output. > 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. ---