### 8.2 Working with MAC algorithms ¶

To use most of these function it is necessary to create a context; this is done using:

Function: `gcry_error_t` gcry_mac_open `(gcry_mac_hd_t *hd, int algo, unsigned int flags, gcry_ctx_t ctx)` ¶

  Create a MAC object for algorithm algo. flags may be given as a bitwise OR of constants described below. hd is guaranteed to either receive a valid handle or `NULL`. ctx is context object to associate MAC object with. ctx maybe set to `NULL`.

  For a list of supported algorithms, see Available MAC algorithms.

  The flags allowed for mode are:

  `GCRY_MAC_FLAG_SECURE`

    Allocate all buffers and the resulting MAC in "secure memory". Use this if the MAC data is highly confidential.

In order to use a handle for performing MAC algorithm operations, a ‘key’ has to be set first:

Function: `gcry_error_t` gcry_mac_setkey `(gcry_mac_hd_t h, const void *key, size_t keylen)` ¶

  Set the MAC key to the value of key of length keylen bytes. With HMAC algorithms, there is no restriction on the length of the key. With CMAC algorithms, the length of the key is restricted to those supported by the underlying block cipher.

GMAC algorithms and Poly1305-with-cipher algorithms need initialization vector to be set, which can be performed with function:

Function: `gcry_error_t` gcry_mac_setiv `(gcry_mac_hd_t h, const void *iv, size_t ivlen)` ¶

  Set the IV to the value of iv of length ivlen bytes.

After you are done with the MAC calculation, you should release the resources by using:

Function: `void` gcry_mac_close `(gcry_mac_hd_t h)` ¶

  Release all resources of MAC context h. h should not be used after a call to this function. A `NULL` passed as h is ignored. The function also clears all sensitive information associated with this handle.

Often you have to do several MAC operations using the same algorithm. To avoid the overhead of creating and releasing context, a reset function is provided:

Function: `gcry_error_t` gcry_mac_reset `(gcry_mac_hd_t h)` ¶

  Reset the current context to its initial state. This is effectively identical to a close followed by an open and setting same key.

  Note that gcry_mac_reset is implemented as a macro.

Now that we have prepared everything to calculate MAC, it is time to see how it is actually done.

Function: `gcry_error_t` gcry_mac_write `(gcry_mac_hd_t h, const void *buffer, size_t length)` ¶

  Pass length bytes of the data in buffer to the MAC object with handle h to update the MAC values. If this function is used after the context has been finalized, it will keep on pushing the data through the algorithm specific transform function and thereby change the context; however the results are not meaningful and this feature is only available to mitigate timing attacks.

The way to read out the calculated MAC is by using the function:

Function: `gcry_error_t` gcry_mac_read `(gcry_mac_hd_t h, void *buffer, size_t *length)` ¶

  `gcry_mac_read` returns the MAC after finalizing the calculation. Function copies the resulting MAC value to buffer of the length length. If length is larger than length of resulting MAC value, then length of MAC is returned through length.

To compare existing MAC value with recalculated MAC, one is to use the function:

Function: `gcry_error_t` gcry_mac_verify `(gcry_mac_hd_t h, void *buffer, size_t length)` ¶

  `gcry_mac_verify` finalizes MAC calculation and compares result with length bytes of data in buffer. Error code `GPG_ERR_CHECKSUM` is returned if the MAC value in the buffer buffer does not match the MAC calculated in object h.

In some situations it might be hard to remember the algorithm used for the MAC calculation. The following function might be used to get that information:

Function: `int` gcry_mac_get_algo `(gcry_mac_hd_t h)` ¶

  Retrieve the algorithm used with the handle h.

MAC algorithms are identified by internal algorithm numbers (see `gcry_mac_open` for a list). However, in most applications they are used by names, so two functions are available to map between string representations and MAC algorithm identifiers.

Function: `const char *` gcry_mac_algo_name `(int algo)` ¶

  Map the MAC algorithm id algo to a string representation of the algorithm name. For unknown algorithms this function returns the string `"?"`. This function should not be used to test for the availability of an algorithm.

Function: `int` gcry_mac_map_name `(const char *name)` ¶

  Map the algorithm with name to a MAC algorithm identifier. Returns 0 if the algorithm name is not known. This function should not be used to test for the availability of an algorithm.

To test whether an algorithm is actually available for use, the following macro should be used:

Function: `gcry_error_t` gcry_mac_test_algo `(int algo)` ¶

  The macro returns 0 if the MAC algorithm algo is available for use.

If the length of a message digest is not known, it can be retrieved using the following function:

Function: `unsigned int` gcry_mac_get_algo_maclen `(int algo)` ¶

  Retrieve the length in bytes of the MAC yielded by algorithm algo. This is often used prior to `gcry_mac_read` to allocate sufficient memory for the MAC value. On error `0` is returned.

Function: `unsigned int` gcry_mac_get_algo_keylen `(algo)` ¶

  This function returns length of the key for MAC algorithm algo. If the algorithm supports multiple key lengths, the default supported key length is returned. On error `0` is returned. The key length is returned as number of octets.