diff --git a/include/psa/crypto.h b/include/psa/crypto.h
index 998b092b9a..d02f3ff847 100755
--- a/include/psa/crypto.h
+++ b/include/psa/crypto.h
@@ -54,43 +54,206 @@ typedef enum {
     /** The action was completed successfully. */
     PSA_SUCCESS = 0,
     /** The requested operation or a parameter is not supported
-        by this implementation. */
+     * by this implementation.
+     *
+     * Implementations should return this error code when an enumeration
+     * parameter such as a key type, algorithm, etc. is not recognized.
+     * If a combination of parameters is recognized and identified as
+     * not valid, return #PSA_ERROR_INVALID_ARGUMENT instead. */
     PSA_ERROR_NOT_SUPPORTED,
-    /** The requested action is denied by a policy. */
+    /** The requested action is denied by a policy.
+     *
+     * Implementations should return this error code when the parameters
+     * are recognized as valid and supported, and a policy explicitly
+     * denies the requested operation.
+     *
+     * If a subset of the parameters of a function call identify a
+     * forbidden operation, and another subset of the parameters are
+     * not valid or not supported, it is unspecified whether the function
+     * returns #PSA_ERROR_NOT_PERMITTED, #PSA_ERROR_NOT_SUPPORTED or
+     * #PSA_ERROR_INVALID_ARGUMENT. */
     PSA_ERROR_NOT_PERMITTED,
-    /** An output buffer is too small. */
+    /** An output buffer is too small.
+     *
+     * Applications can call the `PSA_xxx_SIZE` macro listed in the function
+     * description to determine a sufficient buffer size.
+     *
+     * Implementations should preferably return this error code only
+     * in cases when performing the operation with a larger output
+     * buffer would succeed. However implementations may return this
+     * error if a function has invalid or unsupported parameters in addition
+     * to the parameters that determine the necessary output buffer size. */
     PSA_ERROR_BUFFER_TOO_SMALL,
     /** A slot is occupied, but must be empty to carry out the
-        requested action. */
+     * requested action.
+     *
+     * If the slot number is invalid (i.e. the requested action could
+     * not be performed even after erasing the slot's content),
+     * implementations shall return #PSA_ERROR_INVALID_ARGUMENT instead. */
     PSA_ERROR_OCCUPIED_SLOT,
     /** A slot is empty, but must be occupied to carry out the
-        requested action. */
+     * requested action.
+     *
+     * If the slot number is invalid (i.e. the requested action could
+     * not be performed even after creating appropriate content in the slot),
+     * implementations shall return #PSA_ERROR_INVALID_ARGUMENT instead. */
     PSA_ERROR_EMPTY_SLOT,
-    /** The requested action cannot be performed in the current state. */
+    /** The requested action cannot be performed in the current state.
+     *
+     * Multipart operations return this error when one of the
+     * functions is called out of sequence. Refer to the function
+     * descriptions for permitted sequencing of functions.
+     *
+     * Implementations shall not return this error code to indicate
+     * that a key slot is occupied when it needs to be free or vice versa,
+     * but shall return #PSA_ERROR_OCCUPIED_SLOT or #PSA_ERROR_EMPTY_SLOT
+     * as applicable. */
     PSA_ERROR_BAD_STATE,
-    /** The parameters passed to the function are invalid. */
+    /** The parameters passed to the function are invalid.
+     *
+     * Implementations may return this error any time a parameter or
+     * combination of parameters are recognized as invalid.
+     *
+     * Implementations shall not return this error code to indicate
+     * that a key slot is occupied when it needs to be free or vice versa,
+     * but shall return #PSA_ERROR_OCCUPIED_SLOT or #PSA_ERROR_EMPTY_SLOT
+     * as applicable. */
     PSA_ERROR_INVALID_ARGUMENT,
-    /** There is not enough runtime memory. */
+    /** There is not enough runtime memory.
+     *
+     * If the action is carried out across multiple security realms, this
+     * error can refer to available memory in any of the security realms. */
     PSA_ERROR_INSUFFICIENT_MEMORY,
-    /** There is not enough persistent storage. */
+    /** There is not enough persistent storage.
+     *
+     * Functions that modify the key storage return this error code if
+     * there is insufficient storage space on the host media. In addition,
+     * many functions that do not otherwise access storage may return this
+     * error code if the implementation requires a mandatory log entry for
+     * the requested action and the log storage space is full. */
     PSA_ERROR_INSUFFICIENT_STORAGE,
-    /** There was a communication failure inside the implementation. */
+    /** There was a communication failure inside the implementation.
+     *
+     * This can indicate a communication failure between the application
+     * and an external cryptoprocessor or between the cryptoprocessor and
+     * an external volatile or persistent memory. A communication failure
+     * may be transient or permanent depending on the cause.
+     *
+     * \warning If a function returns this error, it is undetermined
+     * whether the requested action has completed or not. Implementations
+     * should return #PSA_SUCCESS on successful completion whenver
+     * possible, however functions may return #PSA_ERROR_COMMUNICATION_FAILURE
+     * if the requested action was completed successfully in an external
+     * cryptoprocessor but there was a breakdown of communication before
+     * the cryptoprocessor could report the status to the application.
+     */
     PSA_ERROR_COMMUNICATION_FAILURE,
-    /** There was a storage failure that may have led to data loss. */
+    /** There was a storage failure that may have led to data loss.
+     *
+     * This error indicates that some persistent storage is corrupted.
+     * It should not be used for a corruption of volatile memory
+     * (use #PSA_ERROR_TAMPERING_DETECTED), for a communication error
+     * between the cryptoprocessor and its external storage (use
+     * #PSA_ERROR_COMMUNICATION_FAILURE), or when the storage is
+     * in a valid state but is full (use #PSA_ERROR_INSUFFICIENT_STORAGE).
+     *
+     * Note that a storage failure does not indicate that any data that was
+     * previously read is invalid. However this previously read data may no
+     * longer be readable from storage.
+     *
+     * When a storage failure occurs, it is no longer possible to ensure
+     * the global integrity of the keystore. Depending on the global
+     * integrity guarantees offered by the implementation, access to other
+     * data may or may not fail even if the data is still readable but
+     * its integrity canont be guaranteed.
+     *
+     * Implementations should only use this error code to report a
+     * permanent storage corruption. However application writers should
+     * keep in mind that transient errors while reading the storage may be
+     * reported using this error code. */
     PSA_ERROR_STORAGE_FAILURE,
-    /** A hardware failure was detected. */
+    /** A hardware failure was detected.
+     *
+     * A hardware failure may be transient or permanent depending on the
+     * cause. */
     PSA_ERROR_HARDWARE_FAILURE,
-    /** A tampering attempt was detected. */
+    /** A tampering attempt was detected.
+     *
+     * If an application receives this error code, there is no guarantee
+     * that previously accessed or computed data was correct and remains
+     * confidential. Applications should not perform any security function
+     * and should enter a safe failure state.
+     *
+     * Implementations may return this error code if they detect an invalid
+     * state that cannot happen during normal operation and that indicates
+     * that the implementation's security guarantees no longer hold. Depending
+     * on the implementation architecture and on its security and safety goals,
+     * the implementation may forcibly terminate the application.
+     *
+     * This error code is intended as a last resort when a security breach
+     * is detected and it is unsure whether the keystore data is still
+     * protected. Implementations shall only return this error code
+     * to report an alarm from a tampering detector, to indicate that
+     * the confidentiality of stored data can no longer be guaranteed,
+     * or to indicate that the integrity of previously returned data is now
+     * considered compromised. Implementations shall not use this error code
+     * to indicate a hardware failure that merely makes it impossible to
+     * perform the requested operation (use #PSA_ERROR_COMMUNICATION_FAILURE,
+     * #PSA_ERROR_STORAGE_FAILURE, #PSA_ERROR_HARDWARE_FAILURE,
+     * #PSA_ERROR_INSUFFICIENT_ENTROPY or other applicable error code
+     * instead).
+     *
+     * This error indicates an attack against the application. Implementations
+     * shall not return this error code as a consequence of the behavior of
+     * the application itself. */
     PSA_ERROR_TAMPERING_DETECTED,
     /** There is not enough entropy to generate random data needed
-        for the requested action. */
+     * for the requested action.
+     *
+     * This error indicates a failure of a hardware random generator.
+     * Application writers should note that this error can be returned not
+     * only by functions whose purpose is to generate random data, such
+     * as key, IV or nonce generation, but also by functions that execute
+     * an algorithm with a randomized result, as well as functions that
+     * use randomization of intermediate computations as a countermeasure
+     * to certain attacks.
+     *
+     * Implementations should avoid returning this error after psa_crypto_init()
+     * has succeeded. Implementations should generate sufficient
+     * entropy during initialization and subsequently use a cryptographically
+     * secure pseudorandom generator (PRNG). However implementations may return
+     * this error at any time if a policy requires the PRNG to be reseeded
+     * during normal operation. */
     PSA_ERROR_INSUFFICIENT_ENTROPY,
-    /** The signature, MAC or hash is incorrect. */
+    /** The signature, MAC or hash is incorrect.
+     *
+     * Verification functions return this error if the verification
+     * calculations completed successfully, and the value to be verified
+     * was determined to be incorrect.
+     *
+     * If the value to verify has an invalid size, implementations may return
+     * either #PSA_ERROR_INVALID_ARGUMENT or #PSA_ERROR_INVALID_SIGNATURE. */
     PSA_ERROR_INVALID_SIGNATURE,
-    /** The decrypted padding is incorrect. */
+    /** The decrypted padding is incorrect.
+     *
+     * \warning In some protocols, when decrypting data, it is essential that
+     * the behavior of the application does not depend on whether the padding
+     * is correct, down to precise timing. Applications should prefer
+     * protocols that use authenticated encryption rather than plain
+     * encryption. If the application must perform a decryption of
+     * unauthenticated data, the application writer should take care not
+     * to reveal whether the padding is invalid.
+     *
+     * Implementations should strive to make valid and invalid padding
+     * as close as possible to indistinguishable to an external observer.
+     * In particular, the timing of a decryption operation should not
+     * depend on the validity of the padding. */
     PSA_ERROR_INVALID_PADDING,
     /** An error occurred that does not correspond to any defined
-        failure cause. */
+     * failure cause.
+     *
+     * Implementations may use this error code if none of the other standard
+     * error codes are applicable. */
     PSA_ERROR_UNKNOWN_ERROR,
 } psa_status_t;
 
@@ -141,15 +304,47 @@ 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)
 
+/** HMAC key.
+ *
+ * The key policy determines which underlying hash algorithm the key can be
+ * used for.
+ *
+ * HMAC keys should generally have the same size as the underlying hash.
+ * 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
+ * 24 bytes (3-key 3DES).
+ *
+ * Note that single DES and 2-key 3DES are weak and strongly
+ * deprecated and should only be used to decrypt legacy data. 3-key 3DES
+ * 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
+ * legacy protocols. */
 #define PSA_KEY_TYPE_ARC4                       ((psa_key_type_t)0x04000004)
 
 /** RSA public key. */
@@ -207,8 +402,14 @@ typedef uint32_t psa_key_type_t;
  * \param type  A cipher key type (value of type #psa_key_type_t).
  *
  * \return      The block size for a block cipher, or 1 for a stream cipher.
- *              The return value is undefined if \c type does not identify
- *              a cipher algorithm.
+ *              The return value is undefined if \c type is not a supported
+ *              cipher key type.
+ *
+ * \note It is possible to build stream cipher algorithms on top of a block
+ *       cipher, for example CTR mode (#PSA_ALG_CTR).
+ *       This macro only takes the key type into account, so it cannot be
+ *       used to determine the size of the data that #psa_cipher_update()
+ *       might buffer for future processing in general.
  *
  * \note This macro returns a compile-time constant if its argument is one.
  *
@@ -289,7 +490,17 @@ typedef uint32_t psa_algorithm_t;
 
 #define PSA_ALG_MAC_SUBCATEGORY_MASK            ((psa_algorithm_t)0x00c00000)
 #define PSA_ALG_HMAC_BASE                       ((psa_algorithm_t)0x02800000)
-#define PSA_ALG_HMAC(hash_alg)                  \
+/** Macro to build an HMAC algorithm.
+ *
+ * For example, `PSA_ALG_HMAC(PSA_ALG_SHA256)` is HMAC-SHA-256.
+ *
+ * \param alg   A hash algorithm (\c PSA_ALG_XXX value such that
+ *              #PSA_ALG_IS_HASH(alg) is true).
+ *
+ * \return      The corresponding HMAC algorithm.
+ * \return      Unspecified if \p alg is not a hash algorithm.
+ */
+#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))
@@ -368,13 +579,15 @@ typedef uint32_t psa_algorithm_t;
  * \retval PSA_SUCCESS
  *         Success.
  * \retval PSA_ERROR_NOT_SUPPORTED
- *         The key type or key size is not supported.
+ *         The key type or key size is not supported, either by the
+ *         implementation in general or in this particular slot.
  * \retval PSA_ERROR_INVALID_ARGUMENT
  *         The key slot is invalid,
  *         or the key data is not correctly formatted.
  * \retval PSA_ERROR_OCCUPIED_SLOT
-           There is already a key in the specified slot.
+ *         There is already a key in the specified slot.
  * \retval PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval PSA_ERROR_INSUFFICIENT_STORAGE
  * \retval PSA_ERROR_COMMUNICATION_FAILURE
  * \retval PSA_ERROR_HARDWARE_FAILURE
  * \retval PSA_ERROR_TAMPERING_DETECTED
@@ -385,13 +598,37 @@ psa_status_t psa_import_key(psa_key_slot_t key,
                             size_t data_length);
 
 /**
- * \brief Destroy a key.
+ * \brief Destroy a key and restore the slot to its default state.
+ *
+ * This function destroys the content of the key slot from both volatile
+ * memory and, if applicable, non-volatile storage. Implementations shall
+ * make a best effort to ensure that any previous content of the slot is
+ * unrecoverable.
+ *
+ * This function also erases any metadata such as policies. It returns the
+ * specified slot to its default state.
+ *
+ * \param key           The key slot to erase.
  *
  * \retval PSA_SUCCESS
- * \retval PSA_ERROR_EMPTY_SLOT
+ *         The slot's content, if any, has been erased.
+ * \retval PSA_ERROR_NOT_PERMITTED
+ *         The slot holds content and cannot be erased because it is
+ *         read-only, either due to a policy or due to physical restrictions.
+ * \retval PSA_ERROR_INVALID_ARGUMENT
+ *         The specified slot number does not designate a valid slot.
  * \retval PSA_ERROR_COMMUNICATION_FAILURE
- * \retval PSA_ERROR_HARDWARE_FAILURE
+ *         There was an failure in communication with the cryptoprocessor.
+ *         The key material may still be present in the cryptoprocessor.
+ * \retval PSA_ERROR_STORAGE_FAILURE
+ *         The storage is corrupted. Implementations shall make a best effort
+ *         to erase key material even in this stage, however applications
+ *         should be aware that it may be impossible to guarantee that the
+ *         key material is not recoverable in such cases.
  * \retval PSA_ERROR_TAMPERING_DETECTED
+ *         An unexpected condition which is not a storage corruption or
+ *         a communication failure occurred. The cryptoprocessor may have
+ *         been compromised.
  */
 psa_status_t psa_destroy_key(psa_key_slot_t key);
 
@@ -668,30 +905,32 @@ typedef struct psa_hash_operation_s psa_hash_operation_t;
  * This is also the hash size that psa_hash_verify() expects.
  *
  * \param alg   A hash algorithm (\c PSA_ALG_XXX value such that
- *              #PSA_ALG_IS_HASH(alg) is true).
+ *              #PSA_ALG_IS_HASH(alg) is true), or an HMAC algorithm
+ *              (`PSA_ALG_HMAC(hash_alg)` where `hash_alg` is a
+ *              hash algorithm).
  *
  * \return The hash size for the specified hash algorithm.
  *         If the hash algorithm is not recognized, return 0.
  *         An implementation may return either 0 or the correct size
  *         for a hash algorithm that it recognizes, but does not support.
  */
-#define PSA_HASH_FINAL_SIZE(alg)                \
-    (                                           \
-        (alg) == PSA_ALG_MD2 ? 16 :             \
-        (alg) == PSA_ALG_MD4 ? 16 :             \
-        (alg) == PSA_ALG_MD5 ? 16 :             \
-        (alg) == PSA_ALG_RIPEMD160 ? 20 :       \
-        (alg) == PSA_ALG_SHA_1 ? 20 :           \
-        (alg) == PSA_ALG_SHA_224 ? 28 :         \
-        (alg) == PSA_ALG_SHA_256 ? 32 :         \
-        (alg) == PSA_ALG_SHA_384 ? 48 :         \
-        (alg) == PSA_ALG_SHA_512 ? 64 :         \
-        (alg) == PSA_ALG_SHA_512_224 ? 28 :     \
-        (alg) == PSA_ALG_SHA_512_256 ? 32 :     \
-        (alg) == PSA_ALG_SHA3_224 ? 28 :        \
-        (alg) == PSA_ALG_SHA3_256 ? 32 :        \
-        (alg) == PSA_ALG_SHA3_384 ? 48 :        \
-        (alg) == PSA_ALG_SHA3_512 ? 64 :        \
+#define PSA_HASH_SIZE(alg)                                            \
+    (                                                                 \
+        PSA_ALG_RSA_GET_HASH(alg) == PSA_ALG_MD2 ? 16 :               \
+        PSA_ALG_RSA_GET_HASH(alg) == PSA_ALG_MD4 ? 16 :               \
+        PSA_ALG_RSA_GET_HASH(alg) == PSA_ALG_MD5 ? 16 :               \
+        PSA_ALG_RSA_GET_HASH(alg) == PSA_ALG_RIPEMD160 ? 20 :         \
+        PSA_ALG_RSA_GET_HASH(alg) == PSA_ALG_SHA_1 ? 20 :             \
+        PSA_ALG_RSA_GET_HASH(alg) == PSA_ALG_SHA_224 ? 28 :           \
+        PSA_ALG_RSA_GET_HASH(alg) == PSA_ALG_SHA_256 ? 32 :           \
+        PSA_ALG_RSA_GET_HASH(alg) == PSA_ALG_SHA_384 ? 48 :           \
+        PSA_ALG_RSA_GET_HASH(alg) == PSA_ALG_SHA_512 ? 64 :           \
+        PSA_ALG_RSA_GET_HASH(alg) == PSA_ALG_SHA_512_224 ? 28 :       \
+        PSA_ALG_RSA_GET_HASH(alg) == PSA_ALG_SHA_512_256 ? 32 :       \
+        PSA_ALG_RSA_GET_HASH(alg) == PSA_ALG_SHA3_224 ? 28 :          \
+        PSA_ALG_RSA_GET_HASH(alg) == PSA_ALG_SHA3_256 ? 32 :          \
+        PSA_ALG_RSA_GET_HASH(alg) == PSA_ALG_SHA3_384 ? 48 :          \
+        PSA_ALG_RSA_GET_HASH(alg) == PSA_ALG_SHA3_512 ? 64 :          \
         0)
 
 /** Start a multipart hash operation.
@@ -776,7 +1015,7 @@ psa_status_t psa_hash_update(psa_hash_operation_t *operation,
  * \param hash_size     Size of the \c hash buffer in bytes.
  * \param hash_length   On success, the number of bytes
  *                      that make up the hash value. This is always
- *                      #PSA_HASH_FINAL_SIZE(alg) where \c alg is the
+ *                      #PSA_HASH_SIZE(alg) where \c alg is the
  *                      hash algorithm that is calculated.
  *
  * \retval PSA_SUCCESS
@@ -785,7 +1024,7 @@ psa_status_t psa_hash_update(psa_hash_operation_t *operation,
  *         The operation state is not valid (not started, or already completed).
  * \retval PSA_ERROR_BUFFER_TOO_SMALL
  *         The size of the \c hash buffer is too small. You can determine a
- *         sufficient buffer size by calling #PSA_HASH_FINAL_SIZE(alg)
+ *         sufficient buffer size by calling #PSA_HASH_SIZE(alg)
  *         where \c alg is the hash algorithm that is calculated.
  * \retval PSA_ERROR_INSUFFICIENT_MEMORY
  * \retval PSA_ERROR_COMMUNICATION_FAILURE
@@ -881,7 +1120,7 @@ typedef struct psa_mac_operation_s psa_mac_operation_t;
  *         for a MAC algorithm that it recognizes, but does not support.
  */
 #define PSA_MAC_FINAL_SIZE(key_type, key_bits, alg)                     \
-    (PSA_ALG_IS_HMAC(alg) ? PSA_HASH_FINAL_SIZE(PSA_ALG_HMAC_HASH(alg)) : \
+    (PSA_ALG_IS_HMAC(alg) ? PSA_HASH_SIZE(PSA_ALG_HMAC_HASH(alg)) : \
      PSA_ALG_IS_BLOCK_CIPHER_MAC(alg) ? PSA_BLOCK_CIPHER_BLOCK_SIZE(key_type) : \
      0)
 
diff --git a/library/psa_crypto.c b/library/psa_crypto.c
index e4f2a8722a..18126f638d 100755
--- a/library/psa_crypto.c
+++ b/library/psa_crypto.c
@@ -388,9 +388,11 @@ psa_status_t psa_destroy_key(psa_key_slot_t key)
         return( PSA_ERROR_INVALID_ARGUMENT );
     slot = &global_data.key_slots[key];
     if( slot->type == PSA_KEY_TYPE_NONE )
-        return( PSA_ERROR_EMPTY_SLOT );
-
-    if( PSA_KEY_TYPE_IS_RAW_BYTES( slot->type ) )
+    {
+        /* No key material to clean, but do zeroize the slot below to wipe
+         * metadata such as policies. */
+    }
+    else if( PSA_KEY_TYPE_IS_RAW_BYTES( slot->type ) )
     {
         mbedtls_free( slot->data.raw.data );
     }
@@ -816,7 +818,7 @@ psa_status_t psa_hash_finish( psa_hash_operation_t *operation,
                               size_t *hash_length )
 {
     int ret;
-    size_t actual_hash_length = PSA_HASH_FINAL_SIZE( operation->alg );
+    size_t actual_hash_length = PSA_HASH_SIZE( operation->alg );
 
     /* Fill the output buffer with something that isn't a valid hash
      * (barring an attack on the hash and deliberately-crafted input),