@@ -161,6 +161,103 @@ static int test_entropy_source(void * data, uint8_t * output, size_t len, size_t
161
161
return 0 ;
162
162
}
163
163
164
+ struct AesCtrTestEntry
165
+ {
166
+ const uint8_t * key; // /< Key to use for AES-CTR-128 encryption/decryption -- 16 byte length
167
+ const uint8_t * nonce; // /< Nonce to use for AES-CTR-128 encryption/decryption -- 13 byte length
168
+ const uint8_t * plaintext;
169
+ size_t plaintextLen;
170
+ const uint8_t * ciphertext;
171
+ size_t ciphertextLen;
172
+ };
173
+
174
+ /* *
175
+ * Test vectors for AES-CTR-128 encryption/decryption.
176
+ *
177
+ * Sourced from: https://www.ietf.org/rfc/rfc3686.txt (Section 6)
178
+ * Modified to use `IV = flags byte | 13 byte nonce | u16 counter` as defined in NIST SP 800-38A.
179
+ *
180
+ * All AES-CCM test vectors can be used as well, but those are already called to validate underlying AES-CCM functionality.
181
+ */
182
+ const AesCtrTestEntry theAesCtrTestVector[] = {
183
+ {
184
+ .key = (const uint8_t *) " \xae\x68\x52\xf8\x12\x10\x67\xcc\x4b\xf7\xa5\x76\x55\x77\xf3\x9e " ,
185
+ .nonce = (const uint8_t *) " \x00\x00\x00\x30\x00\x00\x00\x00\x00\x00\x00\x00\x00 " ,
186
+ .plaintext = (const uint8_t *) " \x53\x69\x6e\x67\x6c\x65\x20\x62\x6c\x6f\x63\x6b\x20\x6d\x73\x67 " ,
187
+ .plaintextLen = 16 ,
188
+ .ciphertext = (const uint8_t *) " \x0d\x0a\x6b\x6d\xc1\xf6\x9b\x4d\x14\xca\x4c\x15\x42\x22\x42\xc4 " ,
189
+ .ciphertextLen = 16 ,
190
+ },
191
+ {
192
+ .key = (const uint8_t *) " \x7e\x24\x06\x78\x17\xfa\xe0\xd7\x43\xd6\xce\x1f\x32\x53\x91\x63 " ,
193
+ .nonce = (const uint8_t *) " \x00\x6c\xb6\xdb\xc0\x54\x3b\x59\xda\x48\xd9\x0b\x00 " ,
194
+ .plaintext = (const uint8_t *) " \x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f "
195
+ " \x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f " ,
196
+ .plaintextLen = 32 ,
197
+ .ciphertext = (const uint8_t *) " \x4f\x3d\xf9\x49\x15\x88\x4d\xe0\xdc\x0e\x30\x95\x0d\xe7\xa6\xe9 "
198
+ " \x5a\x91\x7e\x1d\x06\x42\x22\xdb\x2f\x6e\xc7\x3d\x99\x4a\xd9\x5f " ,
199
+ .ciphertextLen = 32 ,
200
+ }
201
+ };
202
+
203
+ constexpr size_t kAesCtrTestVectorSize = sizeof (theAesCtrTestVector) / sizeof (theAesCtrTestVector[0 ]);
204
+
205
+ constexpr size_t KEY_LENGTH = Crypto::kAES_CCM128_Key_Length ;
206
+ constexpr size_t NONCE_LENGTH = Crypto::kAES_CCM128_Nonce_Length ;
207
+
208
+ static void TestAES_CTR_128_Encrypt (nlTestSuite * inSuite, const AesCtrTestEntry * vector)
209
+ {
210
+ chip::Platform::ScopedMemoryBuffer<uint8_t > outBuffer;
211
+ outBuffer.Alloc (vector->ciphertextLen );
212
+ NL_TEST_ASSERT (inSuite, outBuffer);
213
+
214
+ CHIP_ERROR err = AES_CTR_crypt (vector->plaintext , vector->plaintextLen , vector->key , KEY_LENGTH, vector->nonce , NONCE_LENGTH,
215
+ outBuffer.Get ());
216
+ NL_TEST_ASSERT (inSuite, err == CHIP_NO_ERROR);
217
+
218
+ bool outputMatches = memcmp (outBuffer.Get (), vector->ciphertext , vector->ciphertextLen ) == 0 ;
219
+ NL_TEST_ASSERT (inSuite, outputMatches);
220
+ if (!outputMatches)
221
+ {
222
+ printf (" \n Test failed due to mismatching ciphertext\n " );
223
+ }
224
+ }
225
+
226
+ static void TestAES_CTR_128_Decrypt (nlTestSuite * inSuite, const AesCtrTestEntry * vector)
227
+ {
228
+ chip::Platform::ScopedMemoryBuffer<uint8_t > outBuffer;
229
+ outBuffer.Alloc (vector->plaintextLen );
230
+ NL_TEST_ASSERT (inSuite, outBuffer);
231
+
232
+ CHIP_ERROR err = AES_CTR_crypt (vector->ciphertext , vector->ciphertextLen , vector->key , KEY_LENGTH, vector->nonce , NONCE_LENGTH,
233
+ outBuffer.Get ());
234
+ NL_TEST_ASSERT (inSuite, err == CHIP_NO_ERROR);
235
+
236
+ bool outputMatches = memcmp (outBuffer.Get (), vector->plaintext , vector->plaintextLen ) == 0 ;
237
+ NL_TEST_ASSERT (inSuite, outputMatches);
238
+ if (!outputMatches)
239
+ {
240
+ printf (" \n Test failed due to mismatching plaintext\n " );
241
+ }
242
+ }
243
+
244
+ static void TestAES_CTR_128CryptTestVectors (nlTestSuite * inSuite, void * inContext)
245
+ {
246
+ HeapChecker heapChecker (inSuite);
247
+ int numOfTestsRan = 0 ;
248
+ for (size_t vectorIndex = 0 ; vectorIndex < kAesCtrTestVectorSize ; vectorIndex++)
249
+ {
250
+ const AesCtrTestEntry * vector = &theAesCtrTestVector[vectorIndex];
251
+ if (vector->plaintextLen > 0 )
252
+ {
253
+ numOfTestsRan++;
254
+ TestAES_CTR_128_Encrypt (inSuite, vector);
255
+ TestAES_CTR_128_Decrypt (inSuite, vector);
256
+ }
257
+ }
258
+ NL_TEST_ASSERT (inSuite, numOfTestsRan > 0 );
259
+ }
260
+
164
261
static void TestAES_CCM_128EncryptTestVectors (nlTestSuite * inSuite, void * inContext)
165
262
{
166
263
HeapChecker heapChecker (inSuite);
@@ -2279,6 +2376,7 @@ static const nlTest sTests[] = {
2279
2376
NL_TEST_DEF (" Test decrypting AES-CCM-128 invalid key" , TestAES_CCM_128DecryptInvalidKey),
2280
2377
NL_TEST_DEF (" Test decrypting AES-CCM-128 invalid nonce" , TestAES_CCM_128DecryptInvalidNonceLen),
2281
2378
NL_TEST_DEF (" Test decrypting AES-CCM-128 Containers" , TestAES_CCM_128Containers),
2379
+ NL_TEST_DEF (" Test encrypt/decrypt AES-CTR-128 test vectors" , TestAES_CTR_128CryptTestVectors),
2282
2380
NL_TEST_DEF (" Test ASN.1 signature conversion routines" , TestAsn1Conversions),
2283
2381
NL_TEST_DEF (" Test Integer to ASN.1 DER conversion" , TestRawIntegerToDerValidCases),
2284
2382
NL_TEST_DEF (" Test Integer to ASN.1 DER conversion error cases" , TestRawIntegerToDerInvalidCases),
0 commit comments