cipher_auth_xxcrypt(): fix some null pointer handling

Make sure that if a buffer is allowed to be empty, a null pointer is
accepted if the buffer length is 0. This was already the case for most
but not all arguments to mbedtls_cipher_auth_{en,de}crypt{,_ext}.

Make sure to pass NULL for an empty buffer in the tests.

Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
diff --git a/library/cipher.c b/library/cipher.c
index 44cba34..cf45446 100644
--- a/library/cipher.c
+++ b/library/cipher.c
@@ -1313,7 +1313,7 @@
 
         /* PSA Crypto API always writes the authentication tag
          * at the end of the encrypted message. */
-        if( tag != output + ilen )
+        if( output == NULL || tag != output + ilen )
             return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
 
         status = psa_aead_encrypt( cipher_psa->slot,
@@ -1393,7 +1393,7 @@
 
         /* PSA Crypto API always writes the authentication tag
          * at the end of the encrypted message. */
-        if( tag != input + ilen )
+        if( input == NULL || tag != input + ilen )
             return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
 
         status = psa_aead_decrypt( cipher_psa->slot,
@@ -1481,10 +1481,10 @@
                          unsigned char *tag, size_t tag_len )
 {
     CIPHER_VALIDATE_RET( ctx != NULL );
-    CIPHER_VALIDATE_RET( iv != NULL );
+    CIPHER_VALIDATE_RET( iv_len == 0 || iv != NULL );
     CIPHER_VALIDATE_RET( ad_len == 0 || ad != NULL );
     CIPHER_VALIDATE_RET( ilen == 0 || input != NULL );
-    CIPHER_VALIDATE_RET( output != NULL );
+    CIPHER_VALIDATE_RET( ilen == 0 || output != NULL );
     CIPHER_VALIDATE_RET( olen != NULL );
     CIPHER_VALIDATE_RET( tag_len == 0 || tag != NULL );
 
@@ -1515,10 +1515,10 @@
                          const unsigned char *tag, size_t tag_len )
 {
     CIPHER_VALIDATE_RET( ctx != NULL );
-    CIPHER_VALIDATE_RET( iv != NULL );
+    CIPHER_VALIDATE_RET( iv_len == 0 || iv != NULL );
     CIPHER_VALIDATE_RET( ad_len == 0 || ad != NULL );
     CIPHER_VALIDATE_RET( ilen == 0 || input != NULL );
-    CIPHER_VALIDATE_RET( output != NULL );
+    CIPHER_VALIDATE_RET( ilen == 0 || output != NULL );
     CIPHER_VALIDATE_RET( olen != NULL );
     CIPHER_VALIDATE_RET( tag_len == 0 || tag != NULL );
 
@@ -1552,7 +1552,7 @@
                          size_t *olen, size_t tag_len )
 {
     CIPHER_VALIDATE_RET( ctx != NULL );
-    CIPHER_VALIDATE_RET( iv != NULL );
+    CIPHER_VALIDATE_RET( iv_len == 0 || iv != NULL );
     CIPHER_VALIDATE_RET( ad_len == 0 || ad != NULL );
     CIPHER_VALIDATE_RET( ilen == 0 || input != NULL );
     CIPHER_VALIDATE_RET( output != NULL );
@@ -1601,7 +1601,7 @@
                          size_t *olen, size_t tag_len )
 {
     CIPHER_VALIDATE_RET( ctx != NULL );
-    CIPHER_VALIDATE_RET( iv != NULL );
+    CIPHER_VALIDATE_RET( iv_len == 0 || iv != NULL );
     CIPHER_VALIDATE_RET( ad_len == 0 || ad != NULL );
     CIPHER_VALIDATE_RET( ilen == 0 || input != NULL );
     CIPHER_VALIDATE_RET( output_len == 0 || output != NULL );
diff --git a/tests/suites/test_suite_cipher.function b/tests/suites/test_suite_cipher.function
index 47a763c..ffe3284 100644
--- a/tests/suites/test_suite_cipher.function
+++ b/tests/suites/test_suite_cipher.function
@@ -1155,6 +1155,16 @@
     unsigned char *tag_buf = NULL;
 #endif /* !MBEDTLS_DEPRECATED_WARNING && !MBEDTLS_DEPRECATED_REMOVED */
 
+    /* Null pointers are documented as valid for inputs of length 0.
+     * The test framework passes non-null pointers, so set them to NULL.
+     * key, cipher and tag can't be empty. */
+    if( iv->len == 0 )
+        iv->x = NULL;
+    if( ad->len == 0 )
+        ad->x = NULL;
+    if( clear->len == 0 )
+        clear->x = NULL;
+
     mbedtls_cipher_init( &ctx );
 
     /* Initialize PSA Crypto */
@@ -1345,8 +1355,7 @@
      * Authenticate and decrypt, and check result
      */
 
-    /* We can't pass a NULL output buffer to this function */
-    ASSERT_ALLOC( decrypt_buf, cipher->len ? cipher->len : 1 );
+    ASSERT_ALLOC( decrypt_buf, cipher->len );
     outlen = 0;
     ret = mbedtls_cipher_auth_decrypt( &ctx, iv->x, iv->len, ad->x, ad->len,
                                tmp_cipher, cipher->len, decrypt_buf, &outlen,
@@ -1397,8 +1406,7 @@
         else
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
         {
-            /* can't pass a NULL output buffer to this function */
-            ASSERT_ALLOC( encrypt_buf, cipher->len ? cipher->len : 1 );
+            ASSERT_ALLOC( encrypt_buf, cipher->len );
             ASSERT_ALLOC( tag_buf, tag->len );
             tmp_cipher = encrypt_buf;
             tmp_tag = tag_buf;
@@ -1421,7 +1429,8 @@
             TEST_ASSERT( ret == 0 );
 
             TEST_ASSERT( outlen == cipher->len );
-            TEST_ASSERT( memcmp( tmp_cipher, cipher->x, cipher->len ) == 0 );
+            if( cipher->len != 0 )
+                TEST_ASSERT( memcmp( tmp_cipher, cipher->x, cipher->len ) == 0 );
             TEST_ASSERT( memcmp( tmp_tag, tag->x, tag->len ) == 0 );
         }
     }