From 49dd8d8cec020c0dfd1af14dda1c6ebf6ed484ef Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Mon, 6 May 2019 15:16:19 +0200 Subject: [PATCH] Add size macros for multipart AEAD New macros PSA_AEAD_UPDATE_OUTPUT_SIZE, PSA_AEAD_FINISH_OUTPUT_SIZE and PSA_AEAD_VERIFY_OUTPUT_SIZE to determine the output buffer sizes for psa_aead_update(), psa_aead_finish() and psa_aead_verify(). --- include/psa/crypto.h | 28 ++++++++++++++++ include/psa/crypto_sizes.h | 65 ++++++++++++++++++++++++++++++++++---- 2 files changed, 87 insertions(+), 6 deletions(-) diff --git a/include/psa/crypto.h b/include/psa/crypto.h index 374f985c6..a0961c74a 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -2501,6 +2501,10 @@ psa_status_t psa_aead_update_ad(psa_aead_operation_t *operation, * \param input_length Size of the \p input buffer in bytes. * \param[out] output Buffer where the output is to be written. * \param output_size Size of the \p output buffer in bytes. + * This must be at least + * #PSA_AEAD_UPDATE_OUTPUT_SIZE(\c alg, + * \p input_length) where \c alg is the + * algorithm that is being calculated. * \param[out] output_length On success, the number of bytes * that make up the returned output. * @@ -2511,6 +2515,9 @@ psa_status_t psa_aead_update_ad(psa_aead_operation_t *operation, * or already completed). * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p output buffer is too small. + * You can determine a sufficient buffer size by calling + * #PSA_AEAD_UPDATE_OUTPUT_SIZE(\c alg, \p input_length) + * where \c alg is the algorithm that is being calculated. * \retval #PSA_ERROR_INVALID_ARGUMENT * The total length of input to psa_aead_update_ad() so far is * less than the additional data length that was previously @@ -2554,11 +2561,18 @@ psa_status_t psa_aead_update(psa_aead_operation_t *operation, * \param[out] ciphertext Buffer where the last part of the ciphertext * is to be written. * \param ciphertext_size Size of the \p ciphertext buffer in bytes. + * This must be at least + * #PSA_AEAD_FINISH_OUTPUT_SIZE(\c alg) where + * \c alg is the algorithm that is being + * calculated. * \param[out] ciphertext_length On success, the number of bytes of * returned ciphertext. * \param[out] tag Buffer where the authentication tag is * to be written. * \param tag_size Size of the \p tag buffer in bytes. + * This must be at least + * #PSA_AEAD_TAG_LENGTH(\c alg) where \c alg is + * the algorithm that is being calculated. * \param[out] tag_length On success, the number of bytes * that make up the returned tag. * @@ -2569,6 +2583,11 @@ psa_status_t psa_aead_update(psa_aead_operation_t *operation, * decryption, or already completed). * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p ciphertext or \p tag buffer is too small. + * You can determine a sufficient buffer size for \p ciphertext by + * calling #PSA_AEAD_FINISH_OUTPUT_SIZE(\c alg) + * where \c alg is the algorithm that is being calculated. + * You can determine a sufficient buffer size for \p tag by + * calling #PSA_AEAD_TAG_LENGTH(\c alg). * \retval #PSA_ERROR_INVALID_ARGUMENT * The total length of input to psa_aead_update_ad() so far is * less than the additional data length that was previously @@ -2608,6 +2627,10 @@ psa_status_t psa_aead_finish(psa_aead_operation_t *operation, * that could not be processed until the end * of the input. * \param plaintext_size Size of the \p plaintext buffer in bytes. + * This must be at least + * #PSA_AEAD_VERIFY_OUTPUT_SIZE(\c alg) where + * \c alg is the algorithm that is being + * calculated. * \param[out] plaintext_length On success, the number of bytes of * returned plaintext. * \param[in] tag Buffer containing the authentication tag. @@ -2618,6 +2641,11 @@ psa_status_t psa_aead_finish(psa_aead_operation_t *operation, * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (not set up, nonce not set, * encryption, or already completed). + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p plaintext buffer is too small. + * You can determine a sufficient buffer size for \p plaintext by + * calling #PSA_AEAD_VERIFY_OUTPUT_SIZE(\c alg) + * where \c alg is the algorithm that is being calculated. * \retval #PSA_ERROR_INVALID_ARGUMENT * The total length of input to psa_aead_update_ad() so far is * less than the additional data length that was previously diff --git a/include/psa/crypto_sizes.h b/include/psa/crypto_sizes.h index 439f20de6..353792791 100644 --- a/include/psa/crypto_sizes.h +++ b/include/psa/crypto_sizes.h @@ -292,26 +292,79 @@ (plaintext_length) - PSA_AEAD_TAG_LENGTH(alg) : \ 0) -/** The maximum size of the output of psa_aead_finish(), in bytes. +/** A sufficient output buffer size for psa_aead_update(). + * + * If the size of the output buffer is at least this large, it is + * guaranteed that psa_aead_finish() will not fail due to an + * insufficient buffer size. The actual size of the output may be smaller + * in any given call. + * + * \param alg An AEAD algorithm + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * \param input_length Size of the input in bytes. + * + * \return A sufficient output buffer size for the specified + * algorithm. + * If the AEAD algorithm is not recognized, return 0. + * An implementation may return either 0 or a + * correct size for an AEAD algorithm that it + * recognizes, but does not support. + */ +/* For all the AEAD modes defined in this specification, it is possible + * to emit output without delay. However, hardware may not always be + * capable of this. So for modes based on a block cipher, allow the + * implementation to delay the output until it has a full block. */ +#define PSA_AEAD_UPDATE_OUTPUT_SIZE(alg, input_length) \ + (PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER(alg) ? \ + ((plaintext_length) + PSA_MAX_BLOCK_CIPHER_BLOCK_SIZE - 1) / PSA_MAX_BLOCK_CIPHER_BLOCK_SIZE : \ + (plaintext_length)) + +/** A sufficient ciphertext buffer size for psa_aead_finish(). * * If the size of the ciphertext buffer is at least this large, it is * guaranteed that psa_aead_finish() will not fail due to an - * insufficient buffer size. Depending on the algorithm, the actual size of - * the ciphertext may be smaller. + * insufficient ciphertext buffer size. The actual size of the output may + * be smaller in any given call. * * \param alg An AEAD algorithm * (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_AEAD(\p alg) is true). * - * \return The maximum trailing ciphertext size for the + * \return A sufficient ciphertext buffer size for the * specified algorithm. * If the AEAD algorithm is not recognized, return 0. * An implementation may return either 0 or a * correct size for an AEAD algorithm that it * recognizes, but does not support. */ -#define PSA_AEAD_FINISH_OUTPUT_SIZE(alg) \ - ((size_t)0) +#define PSA_AEAD_FINISH_OUTPUT_SIZE(alg) \ + (PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER(alg) ? \ + PSA_MAX_BLOCK_CIPHER_BLOCK_SIZE : \ + 0) + +/** A sufficient plaintext buffer size for psa_aead_verify(). + * + * If the size of the plaintext buffer is at least this large, it is + * guaranteed that psa_aead_verify() will not fail due to an + * insufficient plaintext buffer size. The actual size of the output may + * be smaller in any given call. + * + * \param alg An AEAD algorithm + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * + * \return A sufficient plaintext buffer size for the + * specified algorithm. + * If the AEAD algorithm is not recognized, return 0. + * An implementation may return either 0 or a + * correct size for an AEAD algorithm that it + * recognizes, but does not support. + */ +#define PSA_AEAD_VERIFY_OUTPUT_SIZE(alg) \ + (PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER(alg) ? \ + PSA_MAX_BLOCK_CIPHER_BLOCK_SIZE : \ + 0) #define PSA_RSA_MINIMUM_PADDING_SIZE(alg) \ (PSA_ALG_IS_RSA_OAEP(alg) ? \