Merge remote-tracking branch 'upstream-public/pr/1629' into evaluation
diff --git a/library/ccm.c b/library/ccm.c
index cf65209..72b82a0 100644
--- a/library/ccm.c
+++ b/library/ccm.c
@@ -154,7 +154,13 @@
      * 'length' checked later (when writing it to the first block)
      */
     if( tag_len < 4 || tag_len > 16 || tag_len % 2 != 0 )
-        return( MBEDTLS_ERR_CCM_BAD_INPUT );
+    {
+        /*
+         * Loosen the requirements to enable support for CCM* (IEEE 802.15.4)
+         */
+        if( tag_len != 0 )
+            return( MBEDTLS_ERR_CCM_BAD_INPUT );
+    }
 
     /* Also implies q is within bounds */
     if( iv_len < 7 || iv_len > 13 )
@@ -302,7 +308,7 @@
 /*
  * Authenticated encryption
  */
-int mbedtls_ccm_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length,
+int mbedtls_ccm_sfix_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length,
                          const unsigned char *iv, size_t iv_len,
                          const unsigned char *add, size_t add_len,
                          const unsigned char *input, unsigned char *output,
@@ -312,10 +318,41 @@
                             add, add_len, input, output, tag, tag_len ) );
 }
 
+int mbedtls_ccm_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length,
+                         const unsigned char *iv, size_t iv_len,
+                         const unsigned char *add, size_t add_len,
+                         const unsigned char *input, unsigned char *output,
+                         unsigned char *tag, size_t tag_len )
+{
+    if( tag_len == 0 )
+        return( MBEDTLS_ERR_CCM_BAD_INPUT );
+
+    return( mbedtls_ccm_sfix_encrypt_and_tag( ctx, length, iv, iv_len, add,
+                add_len, input, output, tag, tag_len ) );
+}
+
+#define CCM_MAX_IV_LEN 13
+
+int mbedtls_ccm_svar_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length,
+                         size_t iv_len, const unsigned char *add,
+                         size_t add_len, const unsigned char *input,
+                         unsigned char *output, unsigned char *tag,
+                         size_t tag_len, mbedtls_ccm_star_get_nonce_t get_iv,
+                         void *get_iv_ctx )
+{
+    unsigned char iv[CCM_MAX_IV_LEN];
+
+    if( get_iv( get_iv_ctx, tag_len, iv, iv_len ) != 0 )
+        return MBEDTLS_ERR_CCM_BAD_INPUT;
+
+    return( mbedtls_ccm_sfix_encrypt_and_tag( ctx, length, iv, iv_len, add,
+                add_len, input, output, tag, tag_len ) );
+}
+
 /*
  * Authenticated decryption
  */
-int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length,
+int mbedtls_ccm_sfix_auth_decrypt( mbedtls_ccm_context *ctx, size_t length,
                       const unsigned char *iv, size_t iv_len,
                       const unsigned char *add, size_t add_len,
                       const unsigned char *input, unsigned char *output,
@@ -346,6 +383,38 @@
     return( 0 );
 }
 
+int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length,
+                      const unsigned char *iv, size_t iv_len,
+                      const unsigned char *add, size_t add_len,
+                      const unsigned char *input, unsigned char *output,
+                      const unsigned char *tag, size_t tag_len )
+{
+    if( tag_len == 0 )
+        return( MBEDTLS_ERR_CCM_BAD_INPUT );
+
+    return( mbedtls_ccm_sfix_auth_decrypt( ctx, length, iv, iv_len, add,
+                add_len, input, output, tag, tag_len ) );
+}
+
+
+int mbedtls_ccm_svar_auth_decrypt( mbedtls_ccm_context *ctx, size_t length,
+                      const unsigned char *iv, size_t iv_len,
+                      const unsigned char *add, size_t add_len,
+                      const unsigned char *input, unsigned char *output,
+                      size_t* output_len,
+                      mbedtls_ccm_star_get_tag_len_t get_tag_len,
+                      void *get_tlen_ctx )
+{
+    size_t tag_len = 0;
+
+    if( get_tag_len( get_tlen_ctx, &tag_len, iv, iv_len ) != 0 )
+        return( MBEDTLS_ERR_CCM_BAD_INPUT );
+
+    *output_len = length - tag_len;
+
+    return( mbedtls_ccm_sfix_auth_decrypt( ctx, length, iv, iv_len, add,
+                add_len, input, output, input + length, tag_len ) );
+}
 #endif /* !MBEDTLS_CCM_ALT */
 
 #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)