Add a CCM AEAD for Matter, the IoT standard.

Change-Id: I8b1e4652d8d1445a6665af88d158e006ff3fdb20
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/53185
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: Adam Langley <agl@google.com>
diff --git a/crypto/cipher_extra/aead_test.cc b/crypto/cipher_extra/aead_test.cc
index 6c6210d..506db26 100644
--- a/crypto/cipher_extra/aead_test.cc
+++ b/crypto/cipher_extra/aead_test.cc
@@ -154,6 +154,9 @@
 
     {"AES_128_CCM_BLUETOOTH_8", EVP_aead_aes_128_ccm_bluetooth_8,
      "aes_128_ccm_bluetooth_8_tests.txt", 0},
+
+    {"AES_128_CCM_Matter", EVP_aead_aes_128_ccm_matter,
+     "aes_128_ccm_matter_tests.txt", 0},
 };
 
 class PerAEADTest : public testing::TestWithParam<KnownAEAD> {
diff --git a/crypto/cipher_extra/test/aes_128_ccm_matter_tests.txt b/crypto/cipher_extra/test/aes_128_ccm_matter_tests.txt
new file mode 100644
index 0000000..7cff4fb
--- /dev/null
+++ b/crypto/cipher_extra/test/aes_128_ccm_matter_tests.txt
@@ -0,0 +1,92 @@
+# These test vectors were derived from those found in
+# the Bluetooth Mesh Profile Specification v1.0. That document doesn't use
+# 16-byte tags, so the tags have been updated here. Note that the first four or
+# eight bytes of the tag is not equal to the tag from those vectors because CCM
+# authenticates the expected tag length.
+
+KEY: 0953fa93e7caac9638f58820220a398e
+NONCE: 00800000011201000012345678
+IN: fffd034b50057e400000010000
+AD:
+CT: b5e5bfdacbaf6cb7fb6bff871f
+TAG: b0d6dd827d35bf372fa6425dcd17d356
+
+# Section 8.3.2
+KEY: 0953fa93e7caac9638f58820220a398e
+NONCE: 00800148202345000012345678
+IN: 120104320308ba072f
+AD:
+CT: 79d7dbc0c9b4d43eeb
+TAG: 281508e50d58dbbd27c39597800f4733
+
+# Section 8.3.3.
+KEY: 0953fa93e7caac9638f58820220a398e
+NONCE: 00802b38322fe3000012345678
+IN: 120104fa0205a6000a
+AD:
+CT: 53273086b8c5ee00bd
+TAG: d52b87a8ce6290a772d472b8c62bdc13
+
+# Section 8.3.4.
+KEY: be635105434859f484fc798e043ce40e
+NONCE: 00800000021201000012345678
+IN: 23450100
+AD:
+CT: b0e5d0ad
+TAG: 6078e0ddbb7cd43faea57c7051e5b4ae
+
+# Section 8.3.5.
+KEY: be635105434859f484fc798e043ce40e
+NONCE: 00800148342345000012345678
+IN: 120102001234567800
+AD:
+CT: 5c39da1792b1fee9ec
+TAG: a9233958aced64f2343b9d610e876440
+
+# Section 8.3.7.
+KEY: 0953fa93e7caac9638f58820220a398e
+NONCE: 008b0148352345000012345678
+IN: 000300a6ac00000002
+AD:
+CT: 0d0d730f94d7f3509d
+TAG: dda1694adb791652fb6ae04682f19b29
+
+# Section 8.3.9.
+KEY: 0953fa93e7caac9638f58820220a398e
+NONCE: 008b0148362345000012345678
+IN: 000300a6ac00000003
+AD:
+CT: d85d806bbed248614f
+TAG: ef7f4d55e47d21522ebe3d5bc735a5c5
+
+# Section 8.3.10.
+KEY: be635105434859f484fc798e043ce40e
+NONCE: 00800000031201000012345678
+IN: 23450101
+AD:
+CT: 7777ed35
+TAG: 35d84e18784c4bf3cb1b4c191dc555cc
+
+# Section 8.3.12.
+KEY: be635105434859f484fc798e043ce40e
+NONCE: 00800000041201000012345678
+IN: 23450101
+AD:
+CT: ae214660
+TAG: d146b28beafe7f984f9430502d07aafe
+
+# Section 8.3.14.
+KEY: be635105434859f484fc798e043ce40e
+NONCE: 00800000051201000012345678
+IN: 23450100
+AD:
+CT: 7d3ae62a
+TAG: 52ee03ab84e1a33365e8a61275665f71
+
+# Section 8.3.24.
+KEY: 63964771734fbd76e3b40519d1d94a48
+NONCE: 010007080d1234973612345677
+IN: ea0a00576f726c64
+AD: f4a002c7fb1e4ca0a469a021de0db875
+CT: de1547118463123e
+TAG: 14604c1ddb4f5987064b1736f3923962
diff --git a/crypto/fipsmodule/cipher/e_aesccm.c b/crypto/fipsmodule/cipher/e_aesccm.c
index c9d52e0..cd61701 100644
--- a/crypto/fipsmodule/cipher/e_aesccm.c
+++ b/crypto/fipsmodule/cipher/e_aesccm.c
@@ -432,3 +432,22 @@
   out->seal_scatter = aead_aes_ccm_seal_scatter;
   out->open_gather = aead_aes_ccm_open_gather;
 }
+
+static int aead_aes_ccm_matter_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
+                                    size_t key_len, size_t tag_len) {
+  return aead_aes_ccm_init(ctx, key, key_len, tag_len, 16, 2);
+}
+
+DEFINE_METHOD_FUNCTION(EVP_AEAD, EVP_aead_aes_128_ccm_matter) {
+  memset(out, 0, sizeof(EVP_AEAD));
+
+  out->key_len = 16;
+  out->nonce_len = 13;
+  out->overhead = 16;
+  out->max_tag_len = 16;
+
+  out->init = aead_aes_ccm_matter_init;
+  out->cleanup = aead_aes_ccm_cleanup;
+  out->seal_scatter = aead_aes_ccm_seal_scatter;
+  out->open_gather = aead_aes_ccm_open_gather;
+}
diff --git a/include/openssl/aead.h b/include/openssl/aead.h
index 5486b4b..131cfec 100644
--- a/include/openssl/aead.h
+++ b/include/openssl/aead.h
@@ -180,6 +180,10 @@
 // v1.0.
 OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_128_ccm_bluetooth_8(void);
 
+// EVP_aead_aes_128_ccm_matter is AES-128-CCM with M=16 and L=2 (16-byte tags
+// and 13-byte nonces), as used in the Matter specification.
+OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_128_ccm_matter(void);
+
 // EVP_has_aes_hardware returns one if we enable hardware support for fast and
 // constant-time AES-GCM.
 OPENSSL_EXPORT int EVP_has_aes_hardware(void);
diff --git a/sources.cmake b/sources.cmake
index 4cbc4c5..b3355a7 100644
--- a/sources.cmake
+++ b/sources.cmake
@@ -11,6 +11,7 @@
   crypto/cipher_extra/test/aes_128_cbc_sha1_tls_tests.txt
   crypto/cipher_extra/test/aes_128_ccm_bluetooth_tests.txt
   crypto/cipher_extra/test/aes_128_ccm_bluetooth_8_tests.txt
+  crypto/cipher_extra/test/aes_128_ccm_matter_tests.txt
   crypto/cipher_extra/test/aes_128_ctr_hmac_sha256.txt
   crypto/cipher_extra/test/aes_128_gcm_randnonce_tests.txt
   crypto/cipher_extra/test/aes_128_gcm_siv_tests.txt