From dcd149432700c971d2709eb1533f4b5896d448c9 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Thu, 12 Jul 2018 00:30:52 +0200 Subject: [PATCH] Doc: write documentation for many macros and functions As of this commit, all #identifier links in the documentation are resolved. --- include/psa/crypto.h | 437 +++++++++++++++++++++++++++++++++++++ include/psa/crypto_sizes.h | 54 ++++- 2 files changed, 490 insertions(+), 1 deletion(-) diff --git a/include/psa/crypto.h b/include/psa/crypto.h index fb7edf83c3..34ab8e1121 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -339,11 +339,13 @@ typedef uint32_t psa_key_type_t; #define PSA_KEY_TYPE_VENDOR_FLAG ((psa_key_type_t)0x80000000) #define PSA_KEY_TYPE_CATEGORY_MASK ((psa_key_type_t)0x7e000000) + /** Raw data. * * A "key" of this type cannot be used for any cryptographic operation. * Applications may use this type to store arbitrary data in the keystore. */ #define PSA_KEY_TYPE_RAW_DATA ((psa_key_type_t)0x02000000) + #define PSA_KEY_TYPE_CATEGORY_SYMMETRIC ((psa_key_type_t)0x04000000) #define PSA_KEY_TYPE_CATEGORY_ASYMMETRIC ((psa_key_type_t)0x06000000) #define PSA_KEY_TYPE_PAIR_FLAG ((psa_key_type_t)0x01000000) @@ -357,12 +359,14 @@ typedef uint32_t psa_key_type_t; * This size can be calculated with #PSA_HASH_SIZE(`alg`) where * `alg` is the HMAC algorithm or the underlying hash algorithm. */ #define PSA_KEY_TYPE_HMAC ((psa_key_type_t)0x02000001) + /** Key for an cipher, AEAD or MAC algorithm based on the AES block cipher. * * The size of the key can be 16 bytes (AES-128), 24 bytes (AES-192) or * 32 bytes (AES-256). */ #define PSA_KEY_TYPE_AES ((psa_key_type_t)0x04000001) + /** Key for a cipher or MAC algorithm based on DES or 3DES (Triple-DES). * * The size of the key can be 8 bytes (single DES), 16 bytes (2-key 3DES) or @@ -373,9 +377,11 @@ typedef uint32_t psa_key_type_t; * is weak and deprecated and should only be used in legacy protocols. */ #define PSA_KEY_TYPE_DES ((psa_key_type_t)0x04000002) + /** Key for an cipher, AEAD or MAC algorithm based on the * Camellia block cipher. */ #define PSA_KEY_TYPE_CAMELLIA ((psa_key_type_t)0x04000003) + /** Key for the RC4 stream cipher. * * Note that RC4 is weak and deprecated and should only be used in @@ -386,15 +392,19 @@ typedef uint32_t psa_key_type_t; #define PSA_KEY_TYPE_RSA_PUBLIC_KEY ((psa_key_type_t)0x06010000) /** RSA key pair (private and public key). */ #define PSA_KEY_TYPE_RSA_KEYPAIR ((psa_key_type_t)0x07010000) + /** DSA public key. */ #define PSA_KEY_TYPE_DSA_PUBLIC_KEY ((psa_key_type_t)0x06020000) /** DSA key pair (private and public key). */ #define PSA_KEY_TYPE_DSA_KEYPAIR ((psa_key_type_t)0x07020000) + #define PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE ((psa_key_type_t)0x06030000) #define PSA_KEY_TYPE_ECC_KEYPAIR_BASE ((psa_key_type_t)0x07030000) #define PSA_KEY_TYPE_ECC_CURVE_MASK ((psa_key_type_t)0x0000ffff) +/** Elliptic curve key pair. */ #define PSA_KEY_TYPE_ECC_KEYPAIR(curve) \ (PSA_KEY_TYPE_ECC_KEYPAIR_BASE | (curve)) +/** Elliptic curve public key. */ #define PSA_KEY_TYPE_ECC_PUBLIC_KEY(curve) \ (PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE | (curve)) @@ -526,6 +536,7 @@ typedef uint32_t psa_algorithm_t; #define PSA_ALG_IS_VENDOR_DEFINED(alg) \ (((alg) & PSA_ALG_VENDOR_FLAG) != 0) + /** Whether the specified algorithm is a hash algorithm. * * \param alg An algorithm identifier (value of type #psa_algorithm_t). @@ -536,18 +547,82 @@ typedef uint32_t psa_algorithm_t; */ #define PSA_ALG_IS_HASH(alg) \ (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_HASH) + +/** Whether the specified algorithm is a MAC algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \c alg is a MAC algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \c alg is not a supported + * algorithm identifier. + */ #define PSA_ALG_IS_MAC(alg) \ (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_MAC) + +/** Whether the specified algorithm is a symmetric cipher algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \c alg is a symmetric cipher algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \c alg is not a supported + * algorithm identifier. + */ #define PSA_ALG_IS_CIPHER(alg) \ (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_CIPHER) + +/** Whether the specified algorithm is an authenticated encryption + * with associated data (AEAD) algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \c alg is an AEAD algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \c alg is not a supported + * algorithm identifier. + */ #define PSA_ALG_IS_AEAD(alg) \ (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_AEAD) + +/** Whether the specified algorithm is a public-key signature algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \c alg is a public-key signature algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \c alg is not a supported + * algorithm identifier. + */ #define PSA_ALG_IS_SIGN(alg) \ (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_SIGN) + +/** Whether the specified algorithm is a public-key encryption algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \c alg is a public-key encryption algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \c alg is not a supported + * algorithm identifier. + */ #define PSA_ALG_IS_ASYMMETRIC_ENCRYPTION(alg) \ (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_ASYMMETRIC_ENCRYPTION) + +/** Whether the specified algorithm is a key agreement algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \c alg is a key agreement algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \c alg is not a supported + * algorithm identifier. + */ #define PSA_ALG_IS_KEY_AGREEMENT(alg) \ (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_KEY_AGREEMENT) + +/** Whether the specified algorithm is a key derivation algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \c alg is a key derivation algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \c alg is not a supported + * algorithm identifier. + */ #define PSA_ALG_IS_KEY_DERIVATION(alg) \ (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_KEY_DERIVATION) @@ -583,15 +658,35 @@ typedef uint32_t psa_algorithm_t; */ #define PSA_ALG_HMAC(hash_alg) \ (PSA_ALG_HMAC_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) + #define PSA_ALG_HMAC_HASH(hmac_alg) \ (PSA_ALG_CATEGORY_HASH | ((hmac_alg) & PSA_ALG_HASH_MASK)) + +/** Whether the specified algorithm is an HMAC algorithm. + * + * HMAC is a family of MAC algorithms that are based on a hash function. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \c alg is an HMAC algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \c alg is not a supported + * algorithm identifier. + */ #define PSA_ALG_IS_HMAC(alg) \ (((alg) & (PSA_ALG_CATEGORY_MASK | PSA_ALG_MAC_SUBCATEGORY_MASK)) == \ PSA_ALG_HMAC_BASE) + #define PSA_ALG_CIPHER_MAC_BASE ((psa_algorithm_t)0x02c00000) #define PSA_ALG_CBC_MAC ((psa_algorithm_t)0x02c00001) #define PSA_ALG_CMAC ((psa_algorithm_t)0x02c00002) #define PSA_ALG_GMAC ((psa_algorithm_t)0x02c00003) + +/** Whether the specified algorithm is a MAC algorithm based on a block cipher. + * + * \return 1 if \c alg is a MAC algorithm based on a block cipher, 0 otherwise. + * This macro may return either 0 or 1 if \c alg is not a supported + * algorithm identifier. + */ #define PSA_ALG_IS_CIPHER_MAC(alg) \ (((alg) & (PSA_ALG_CATEGORY_MASK | PSA_ALG_MAC_SUBCATEGORY_MASK)) == \ PSA_ALG_CIPHER_MAC_BASE) @@ -600,21 +695,71 @@ typedef uint32_t psa_algorithm_t; #define PSA_ALG_BLOCK_CIPHER_BASE ((psa_algorithm_t)0x04000000) #define PSA_ALG_BLOCK_CIPHER_MODE_MASK ((psa_algorithm_t)0x000000ff) #define PSA_ALG_BLOCK_CIPHER_PADDING_MASK ((psa_algorithm_t)0x003f0000) + +/** Use a block cipher mode without padding. + * + * This padding mode may only be used with messages whose lengths are a + * whole number of blocks for the chosen block cipher. + */ #define PSA_ALG_BLOCK_CIPHER_PAD_NONE ((psa_algorithm_t)0x00000000) #define PSA_ALG_BLOCK_CIPHER_PAD_PKCS7 ((psa_algorithm_t)0x00010000) + +/** Whether the specified algorithm is a block cipher. + * + * A block cipher is a symmetric cipher that encrypts or decrypts messages + * by chopping them into fixed-size blocks. Processing a message requires + * applying a _padding mode_ to transform the message into one whose + * length is a whole number of blocks. To construct an algorithm + * identifier for a block cipher, apply a bitwise-or between the block + * cipher mode and the padding mode. For example, CBC with PKCS#7 padding + * is `PSA_ALG_CBC_BASE | PSA_ALG_BLOCK_CIPHER_PAD_PKCS7`. + * + * The transformation applied to each block is determined by the key type. + * For example, to use AES-128-CBC-PKCS7, use the algorithm above with + * a key of type #PSA_KEY_TYPE_AES and a length of 128 bits (16 bytes). + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \c alg is a block cipher algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \c alg is not a supported + * algorithm identifier or if it is not a symmetric cipher algorithm. + */ #define PSA_ALG_IS_BLOCK_CIPHER(alg) \ (((alg) & (PSA_ALG_CATEGORY_MASK | PSA_ALG_CIPHER_SUBCATEGORY_MASK)) == \ PSA_ALG_BLOCK_CIPHER_BASE) +/** The CBC block cipher mode. + */ #define PSA_ALG_CBC_BASE ((psa_algorithm_t)0x04000001) #define PSA_ALG_CFB_BASE ((psa_algorithm_t)0x04000002) #define PSA_ALG_OFB_BASE ((psa_algorithm_t)0x04000003) #define PSA_ALG_XTS_BASE ((psa_algorithm_t)0x04000004) #define PSA_ALG_STREAM_CIPHER_BASE ((psa_algorithm_t)0x04800000) +/** The CTR stream cipher mode. + * + * CTR is a stream cipher which is built from a block cipher. The + * underlying block cipher is determined by the key type. For example, + * to use AES-128-CTR, use this algorithm with + * a key of type #PSA_KEY_TYPE_AES and a length of 128 bits (16 bytes). + */ #define PSA_ALG_CTR ((psa_algorithm_t)0x04800001) +/** The ARC4 stream cipher algorithm. + */ #define PSA_ALG_ARC4 ((psa_algorithm_t)0x04800002) +/** Whether the specified algorithm is a stream cipher. + * + * A stream cipher is a symmetric cipher that encrypts or decrypts messages + * by applying a bitwise-xor with a stream of bytes that is generated + * from a key. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \c alg is a stream cipher algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \c alg is not a supported + * algorithm identifier or if it is not a symmetric cipher algorithm. + */ #define PSA_ALG_IS_STREAM_CIPHER(alg) \ (((alg) & (PSA_ALG_CATEGORY_MASK | PSA_ALG_CIPHER_SUBCATEGORY_MASK)) == \ PSA_ALG_STREAM_CIPHER_BASE) @@ -647,6 +792,7 @@ typedef uint32_t psa_algorithm_t; #define PSA_ALG_RSA_PKCS1V15_SIGN_RAW PSA_ALG_RSA_PKCS1V15_SIGN_BASE #define PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) \ (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_RSA_PKCS1V15_SIGN_BASE) + #define PSA_ALG_RSA_PSS_BASE ((psa_algorithm_t)0x10030000) /** RSA PSS signature with hashing. * @@ -777,8 +923,25 @@ typedef uint32_t psa_algorithm_t; ((alg) & PSA_ALG_HASH_MASK) | PSA_ALG_CATEGORY_HASH : \ 0) +/** RSA PKCS#1 v1.5 encryption. + */ #define PSA_ALG_RSA_PKCS1V15_CRYPT ((psa_algorithm_t)0x12020000) + #define PSA_ALG_RSA_OAEP_BASE ((psa_algorithm_t)0x12030000) +/** RSA OAEP encryption. + * + * This is the encryption scheme defined by RFC 8017 + * (PKCS#1: RSA Cryptography Specifications) under the name + * RSAES-OAEP, with the message generation function MGF1. + * + * \param hash_alg The hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true) to use + * for MGF1. + * + * \return The corresponding RSA OAEP signature algorithm. + * \return Unspecified if \p alg is not a supported + * hash algorithm. + */ #define PSA_ALG_RSA_OAEP(hash_alg) \ (PSA_ALG_RSA_OAEP_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) #define PSA_ALG_IS_RSA_OAEP(alg) \ @@ -979,24 +1142,42 @@ typedef uint32_t psa_key_usage_t; #define PSA_KEY_USAGE_EXPORT ((psa_key_usage_t)0x00000001) /** Whether the key may be used to encrypt a message. + * + * This flag allows the key to be used for a symmetric encryption operation, + * for an AEAD encryption-and-authentication operation, + * or for an asymmetric encryption operation, + * if otherwise permitted by the key's type and policy. * * For a key pair, this concerns the public key. */ #define PSA_KEY_USAGE_ENCRYPT ((psa_key_usage_t)0x00000100) /** Whether the key may be used to decrypt a message. + * + * This flag allows the key to be used for a symmetric decryption operation, + * for an AEAD decryption-and-verification operation, + * or for an asymmetric decryption operation, + * if otherwise permitted by the key's type and policy. * * For a key pair, this concerns the private key. */ #define PSA_KEY_USAGE_DECRYPT ((psa_key_usage_t)0x00000200) /** Whether the key may be used to sign a message. + * + * This flag allows the key to be used for a MAC calculation operation + * or for an asymmetric signature operation, + * if otherwise permitted by the key's type and policy. * * For a key pair, this concerns the private key. */ #define PSA_KEY_USAGE_SIGN ((psa_key_usage_t)0x00000400) /** Whether the key may be used to verify a message signature. + * + * This flag allows the key to be used for a MAC verification operation + * or for an asymmetric signature verification operation, + * if otherwise permitted by by the key's type and policy. * * For a key pair, this concerns the public key. */ @@ -1023,8 +1204,10 @@ void psa_key_policy_set_usage(psa_key_policy_t *policy, psa_key_usage_t usage, psa_algorithm_t alg); +/** \brief Retrieve the usage field of a policy structure. */ psa_key_usage_t psa_key_policy_get_usage(psa_key_policy_t *policy); +/** \brief Retrieve the algorithm field of a policy structure. */ psa_algorithm_t psa_key_policy_get_algorithm(psa_key_policy_t *policy); /** \brief Set the usage policy on a key slot. @@ -1431,19 +1614,131 @@ psa_status_t psa_mac_verify_setup(psa_mac_operation_t *operation, psa_key_slot_t key, psa_algorithm_t alg); +/** Add a message fragment to a multipart MAC operation. + * + * The application must call psa_mac_sign_setup() or psa_mac_verify_setup() + * before calling this function. + * + * If this function returns an error status, the operation becomes inactive. + * + * \param operation Active MAC operation. + * \param input Buffer containing the message fragment to add to + * the MAC calculation. + * \param input_length Size of the \c input buffer in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (not started, or already completed). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_TAMPERING_DETECTED + */ psa_status_t psa_mac_update(psa_mac_operation_t *operation, const uint8_t *input, size_t input_length); +/** Finish the calculation of the MAC of a message. + * + * The application must call psa_mac_sign_setup() before calling this function. + * This function calculates the MAC of the message formed by concatenating + * the inputs passed to preceding calls to psa_mac_update(). + * + * When this function returns, the operation becomes inactive. + * + * \warning Applications should not call this function if they expect + * a specific value for the MAC. Call psa_mac_verify_finish() instead. + * Beware that comparing integrity or authenticity data such as + * MAC values with a function such as \c memcmp is risky + * because the time taken by the comparison may leak information + * about the MAC value which could allow an attacker to guess + * a valid MAC and thereby bypass security controls. + * + * \param operation Active MAC operation. + * \param mac Buffer where the MAC value is to be written. + * \param mac_size Size of the \p mac buffer in bytes. + * \param mac_length On success, the number of bytes + * that make up the MAC value. This is always + * #PSA_MAC_FINAL_SIZE(\c key_type, \c key_bits, \p alg) + * where \c key_type and \c key_bits are the type and + * bit-size respectively of \c key and `alg` is the + * MAC algorithm that is calculated. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (not started, or already completed). + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \c mac buffer is too small. You can determine a + * sufficient buffer size by calling PSA_MAC_FINAL_SIZE(). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_TAMPERING_DETECTED + */ psa_status_t psa_mac_sign_finish(psa_mac_operation_t *operation, uint8_t *mac, size_t mac_size, size_t *mac_length); +/** Finish the calculation of the MAC of a message and compare it with + * an expected value. + * + * The application must call psa_mac_verify_setup() before calling this function. + * This function calculates the MAC of the message formed by concatenating + * the inputs passed to preceding calls to psa_mac_update(). It then + * compares the calculated MAC with the expected MAC passed as a + * parameter to this function. + * + * When this function returns, the operation becomes inactive. + * + * \note Implementations shall make the best effort to ensure that the + * comparison between the actual MAC and the expected MAC is performed + * in constant time. + * + * \param operation Active MAC operation. + * \param mac Buffer containing the expected MAC value. + * \param mac_length Size of the \c mac buffer in bytes. + * + * \retval #PSA_SUCCESS + * The expected MAC is identical to the actual MAC of the message. + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The MAC of the message was calculated successfully, but it + * differs from the expected MAC. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (not started, or already completed). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_TAMPERING_DETECTED + */ psa_status_t psa_mac_verify_finish(psa_mac_operation_t *operation, const uint8_t *mac, size_t mac_length); +/** Abort a MAC operation. + * + * This function may be called at any time after psa_mac_sign_setup() + * or psa_mac_verify_setup(). + * Aborting an operation frees all associated resources except for the + * \c operation structure itself. + * + * Implementation should strive to be robust and handle inactive MAC + * operations safely (do nothing and return #PSA_ERROR_BAD_STATE). However, + * application writers should beware that uninitialized memory may happen + * to be indistinguishable from an active MAC operation, and the behavior + * of psa_mac_abort() is undefined in this case. + * + * \param operation Active MAC operation. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_BAD_STATE + * \c operation is not an active MAC operation. + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_TAMPERING_DETECTED + */ psa_status_t psa_mac_abort(psa_mac_operation_t *operation); /**@}*/ @@ -1556,15 +1851,104 @@ psa_status_t psa_cipher_decrypt_setup(psa_cipher_operation_t *operation, psa_key_slot_t key, psa_algorithm_t alg); +/** Generate an IV for a symmetric encryption operation. + * + * This function generates a random IV (initialization vector), nonce + * or initial counter value for the encryption operation as appropriate + * for the chosen algorithm, key type and key size. + * + * The application must call psa_cipher_encrypt_setup() before + * calling this function. + * + * If this function returns an error status, the operation becomes inactive. + * + * \param operation Active cipher operation. + * \param iv Buffer where the generated IV is to be written. + * \param iv_size Size of the \c iv buffer in bytes. + * \param iv_length On success, the number of bytes of the generated IV. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (not started, or IV already set). + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \c output buffer is too small. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_TAMPERING_DETECTED + */ psa_status_t psa_cipher_generate_iv(psa_cipher_operation_t *operation, unsigned char *iv, size_t iv_size, size_t *iv_length); +/** Set the IV for a symmetric encryption or decryption operation. + * + * This function sets the random IV (initialization vector), nonce + * or initial counter value for the encryption or decryption operation. + * + * The application must call psa_cipher_encrypt_setup() before + * calling this function. + * + * If this function returns an error status, the operation becomes inactive. + * + * \note When encrypting, applications should use psa_cipher_generate_iv() + * instead of this function, unless implementing a protocol that requires + * a non-random IV. + * + * \param operation Active cipher operation. + * \param iv Buffer containing the IV to use. + * \param iv_length Size of the IV in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (not started, or IV already set). + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The size of the \c iv is not acceptable for the chosen algorithm, + * or the chosen algorithm does not use an IV. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_TAMPERING_DETECTED + */ psa_status_t psa_cipher_set_iv(psa_cipher_operation_t *operation, const unsigned char *iv, size_t iv_length); +/** Encrypt or decrypt a message fragment in an active cipher operation. + * + * The application must call psa_cipher_encrypt_setup() or + * psa_cipher_decrypt_setup() before calling this function. The choice + * of setup function determines whether this function encrypts or + * decrypts its input. After calling a setup function, if the chosen + * algorithm requires an IV, the application must call + * psa_cipher_generate_iv() or psa_cipher_set_iv(). + * + * If this function returns an error status, the operation becomes inactive. + * + * \param operation Active cipher operation. + * \param input Buffer containing the message fragment to + * encrypt or decrypt. + * \param input_length Size of the \c input buffer in bytes. + * \param output Buffer where the output is to be written. + * \param output_size Size of the \c output buffer in bytes. + * \param output_length On success, the number of bytes + * that make up the returned output. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (not started, IV required but + * not set, or already completed). + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p output buffer is too small. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_TAMPERING_DETECTED + */ psa_status_t psa_cipher_update(psa_cipher_operation_t *operation, const uint8_t *input, size_t input_length, @@ -1572,11 +1956,64 @@ psa_status_t psa_cipher_update(psa_cipher_operation_t *operation, size_t output_size, size_t *output_length); +/** Finish encrypting or decrypting a message in a cipher operation. + * + * The application must call psa_cipher_encrypt_setup() or + * psa_cipher_decrypt_setup() before calling this function. The choice + * of setup function determines whether this function encrypts or + * decrypts its input. + * + * This function finishes the encryption or decryption of the message + * formed by concatenating the inputs passed to preceding calls to + * psa_cipher_update(). + * + * When this function returns, the operation becomes inactive. + * + * \param operation Active cipher operation. + * \param output Buffer where the output is to be written. + * \param output_size Size of the \c output buffer in bytes. + * \param output_length On success, the number of bytes + * that make up the returned output. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (not started, IV required but + * not set, or already completed). + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p output buffer is too small. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_TAMPERING_DETECTED + */ psa_status_t psa_cipher_finish(psa_cipher_operation_t *operation, uint8_t *output, size_t output_size, size_t *output_length); +/** Abort a cipher operation. + * + * This function may be called at any time after + * psa_cipher_encrypt_setup() or psa_cipher_decrypt_setup(). + * Aborting an operation frees all associated resources except for the + * \c operation structure itself. + * + * Implementation should strive to be robust and handle inactive cipher + * operations safely (do nothing and return #PSA_ERROR_BAD_STATE). However, + * application writers should beware that uninitialized memory may happen + * to be indistinguishable from an active cipher operation, and the behavior + * of psa_cipher_abort() is undefined in this case. + * + * \param operation Active cipher operation. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_BAD_STATE + * \c operation is not an active cipher operation. + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_TAMPERING_DETECTED + */ psa_status_t psa_cipher_abort(psa_cipher_operation_t *operation); /**@}*/ diff --git a/include/psa/crypto_sizes.h b/include/psa/crypto_sizes.h index 574d3e55c8..ab5b17e194 100644 --- a/include/psa/crypto_sizes.h +++ b/include/psa/crypto_sizes.h @@ -237,17 +237,69 @@ * sensible size or 0. * If the parameters are not valid, the * return value is unspecified. - * */ #define PSA_ASYMMETRIC_SIGN_OUTPUT_SIZE(key_type, key_bits, alg) \ (PSA_KEY_TYPE_IS_RSA(key_type) ? ((void)alg, PSA_BITS_TO_BYTES(key_bits)) : \ PSA_KEY_TYPE_IS_ECC(key_type) ? PSA_ECDSA_SIGNATURE_SIZE(key_bits) : \ ((void)alg, 0)) +/** Safe output buffer size for psa_asymmetric_encrypt(). + * + * This macro returns a safe buffer size for a ciphertext produced using + * a key of the specified type and size, with the specified algorithm. + * Note that the actual size of the ciphertext may be smaller, depending + * on the algorithm. + * + * \warning This function may call its arguments multiple times or + * zero times, so you should not pass arguments that contain + * side effects. + * + * \param key_type An asymmetric key type (this may indifferently be a + * key pair type or a public key type). + * \param key_bits The size of the key in bits. + * \param alg The signature algorithm. + * + * \return If the parameters are valid and supported, return + * a buffer size in bytes that guarantees that + * psa_asymmetric_encrypt() will not fail with + * #PSA_ERROR_BUFFER_TOO_SMALL. + * If the parameters are a valid combination that is not supported + * by the implementation, this macro either shall return either a + * sensible size or 0. + * If the parameters are not valid, the + * return value is unspecified. + */ #define PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE(key_type, key_bits, alg) \ (PSA_KEY_TYPE_IS_RSA(key_type) ? \ ((void)alg, PSA_BITS_TO_BYTES(key_bits)) : \ 0) + +/** Safe output buffer size for psa_asymmetric_decrypt(). + * + * This macro returns a safe buffer size for a ciphertext produced using + * a key of the specified type and size, with the specified algorithm. + * Note that the actual size of the ciphertext may be smaller, depending + * on the algorithm. + * + * \warning This function may call its arguments multiple times or + * zero times, so you should not pass arguments that contain + * side effects. + * + * \param key_type An asymmetric key type (this may indifferently be a + * key pair type or a public key type). + * \param key_bits The size of the key in bits. + * \param alg The signature algorithm. + * + * \return If the parameters are valid and supported, return + * a buffer size in bytes that guarantees that + * psa_asymmetric_decrypt() will not fail with + * #PSA_ERROR_BUFFER_TOO_SMALL. + * If the parameters are a valid combination that is not supported + * by the implementation, this macro either shall return either a + * sensible size or 0. + * If the parameters are not valid, the + * return value is unspecified. + */ #define PSA_ASYMMETRIC_DECRYPT_OUTPUT_SIZE(key_type, key_bits, alg) \ (PSA_KEY_TYPE_IS_RSA(key_type) ? \ PSA_BITS_TO_BYTES(key_bits) - PSA_RSA_MINIMUM_PADDING_SIZE(alg) : \