History

lib/crypto: tests: Add KUnit test suite for AES-CCM

Add a KUnit test suite for the AES-CCM library API. It consists of: - All the shared test cases from aead-test-template.h. These include extensive consistency tests, a "Monte-Carlo test", and a benchmark. - Tests against hardcoded AES-CCM test vectors from external sources. - Tests for CCM-specific message length validation. To generate the expected aes_ccm_monte_carlo_checksum[] value, add a script gen-aead-testvecs.py which computes it using python-cryptography.

Eric Biggers committed 3 months ago

Commit 2aeef501 parent 9396dc95 files · +427 −0Browse files

Unified · Split

5 files
  1. lib/crypto/.kunitconfig +1 −0
  2. lib/crypto/tests/Kconfig +9 −0
  3. lib/crypto/tests/Makefile +1 −0
  4. lib/crypto/tests/aes_ccm_kunit.c +356 −0
  5. scripts/crypto/gen-aead-testvecs.py +60 −0
lib/crypto/.kunitconfig+1−0
@@ -3,6 +3,7 @@ CONFIG_KUNIT=y · 2 unmodified lines
3CONFIG_CRYPTO_LIB_ENABLE_ALL_FOR_KUNIT=y3CONFIG_CRYPTO_LIB_ENABLE_ALL_FOR_KUNIT=y
4 4
5CONFIG_CRYPTO_LIB_AES_CBC_MACS_KUNIT_TEST=y5CONFIG_CRYPTO_LIB_AES_CBC_MACS_KUNIT_TEST=y
6CONFIG_CRYPTO_LIB_AES_CCM_KUNIT_TEST=y
6CONFIG_CRYPTO_LIB_BLAKE2B_KUNIT_TEST=y7CONFIG_CRYPTO_LIB_BLAKE2B_KUNIT_TEST=y
7CONFIG_CRYPTO_LIB_BLAKE2S_KUNIT_TEST=y8CONFIG_CRYPTO_LIB_BLAKE2S_KUNIT_TEST=y
8CONFIG_CRYPTO_LIB_CHACHA20POLY1305_KUNIT_TEST=y9CONFIG_CRYPTO_LIB_CHACHA20POLY1305_KUNIT_TEST=y
lib/crypto/tests/Kconfig+9−0
@@ -9,6 +9,15 @@ config CRYPTO_LIB_AES_CBC_MACS_KUNIT_TEST · 8 unmodified lines
9 KUnit tests for the AES-CMAC, AES-XCBC-MAC, and AES-CBC-MAC message9 KUnit tests for the AES-CMAC, AES-XCBC-MAC, and AES-CBC-MAC message
10 authentication codes.10 authentication codes.
11 11
12config CRYPTO_LIB_AES_CCM_KUNIT_TEST
13 tristate "KUnit tests for AES-CCM" if !KUNIT_ALL_TESTS
14 depends on KUNIT && CRYPTO_LIB_AES_CCM
15 default KUNIT_ALL_TESTS
16 select CRYPTO_LIB_BENCHMARK_VISIBLE
17 # This test uses BLAKE2s, but that's always built-in.
18 help
19 KUnit tests for the AES-CCM authenticated encryption algorithm.
20
12config CRYPTO_LIB_BLAKE2B_KUNIT_TEST21config CRYPTO_LIB_BLAKE2B_KUNIT_TEST
13 tristate "KUnit tests for BLAKE2b" if !KUNIT_ALL_TESTS22 tristate "KUnit tests for BLAKE2b" if !KUNIT_ALL_TESTS
14 depends on KUNIT && CRYPTO_LIB_BLAKE2B23 depends on KUNIT && CRYPTO_LIB_BLAKE2B
lib/crypto/tests/Makefile+1−0
@@ -1,6 +1,7 @@
1# SPDX-License-Identifier: GPL-2.0-or-later1# SPDX-License-Identifier: GPL-2.0-or-later
2 2
3obj-$(CONFIG_CRYPTO_LIB_AES_CBC_MACS_KUNIT_TEST) += aes_cbc_macs_kunit.o3obj-$(CONFIG_CRYPTO_LIB_AES_CBC_MACS_KUNIT_TEST) += aes_cbc_macs_kunit.o
4obj-$(CONFIG_CRYPTO_LIB_AES_CCM_KUNIT_TEST) += aes_ccm_kunit.o
4obj-$(CONFIG_CRYPTO_LIB_BLAKE2B_KUNIT_TEST) += blake2b_kunit.o5obj-$(CONFIG_CRYPTO_LIB_BLAKE2B_KUNIT_TEST) += blake2b_kunit.o
5obj-$(CONFIG_CRYPTO_LIB_BLAKE2S_KUNIT_TEST) += blake2s_kunit.o6obj-$(CONFIG_CRYPTO_LIB_BLAKE2S_KUNIT_TEST) += blake2s_kunit.o
6obj-$(CONFIG_CRYPTO_LIB_CHACHA20POLY1305_KUNIT_TEST) += chacha20poly1305_kunit.o7obj-$(CONFIG_CRYPTO_LIB_CHACHA20POLY1305_KUNIT_TEST) += chacha20poly1305_kunit.o
lib/crypto/tests/aes_ccm_kunit.c+356−0
@@ -0,0 +1,356 @@
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * KUnit test suite for AES-CCM
4 *
5 * Copyright 2026 Google LLC
6 */
7#include <crypto/aes-ccm.h>
8#include <crypto/blake2s.h>
9#include "test-utils.h"
10
11/* AES-CCM test vectors from external sources */
12static const struct aes_ccm_testvec {
13 const char *name;
14 const char *key;
15 size_t key_len;
16 const char *nonce;
17 size_t nonce_len;
18 const char *ad;
19 size_t ad_len;
20 const char *ptext;
21 const char *ctext;
22 size_t data_len;
23 const char *tag;
24 size_t tag_len;
25} aes_ccm_testvecs[] = {
26 {
27 .name = "RFC 3610 Packet Vector #1",
28 .key = "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7"
29 "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf",
30 .key_len = 16,
31 .nonce = "\x00\x00\x00\x03\x02\x01\x00\xa0"
32 "\xa1\xa2\xa3\xa4\xa5",
33 .nonce_len = 13,
34 .ad = "\x00\x01\x02\x03\x04\x05\x06\x07",
35 .ad_len = 8,
36 .ptext = "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
37 "\x10\x11\x12\x13\x14\x15\x16\x17"
38 "\x18\x19\x1a\x1b\x1c\x1d\x1e",
39 .ctext = "\x58\x8c\x97\x9a\x61\xc6\x63\xd2"
40 "\xf0\x66\xd0\xc2\xc0\xf9\x89\x80"
41 "\x6d\x5f\x6b\x61\xda\xc3\x84",
42 .data_len = 23,
43 .tag = "\x17\xe8\xd1\x2c\xfd\xf9\x26\xe0",
44 .tag_len = 8,
45 },
46 {
47 .name = "RFC 3610 Packet Vector #5",
48 .key = "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7"
49 "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf",
50 .key_len = 16,
51 .nonce = "\x00\x00\x00\x07\x06\x05\x04\xa0"
52 "\xa1\xa2\xa3\xa4\xa5",
53 .nonce_len = 13,
54 .ad = "\x00\x01\x02\x03\x04\x05\x06\x07"
55 "\x08\x09\x0a\x0b",
56 .ad_len = 12,
57 .ptext = "\x0c\x0d\x0e\x0f\x10\x11\x12\x13"
58 "\x14\x15\x16\x17\x18\x19\x1a\x1b"
59 "\x1c\x1d\x1e\x1f",
60 .ctext = "\xdc\xf1\xfb\x7b\x5d\x9e\x23\xfb"
61 "\x9d\x4e\x13\x12\x53\x65\x8a\xd8"
62 "\x6e\xbd\xca\x3e",
63 .data_len = 20,
64 .tag = "\x51\xe8\x3f\x07\x7d\x9c\x2d\x93",
65 .tag_len = 8,
66 },
67 {
68 .name = "RFC 3610 Packet Vector #9",
69 .key = "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7"
70 "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf",
71 .key_len = 16,
72 .nonce = "\x00\x00\x00\x0b\x0a\x09\x08\xa0"
73 "\xa1\xa2\xa3\xa4\xa5",
74 .nonce_len = 13,
75 .ad = "\x00\x01\x02\x03\x04\x05\x06\x07",
76 .ad_len = 8,
77 .ptext = "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
78 "\x10\x11\x12\x13\x14\x15\x16\x17"
79 "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
80 "\x20",
81 .ctext = "\x82\x53\x1a\x60\xcc\x24\x94\x5a"
82 "\x4b\x82\x79\x18\x1a\xb5\xc8\x4d"
83 "\xf2\x1c\xe7\xf9\xb7\x3f\x42\xe1"
84 "\x97",
85 .data_len = 25,
86 .tag = "\xea\x9c\x07\xe5\x6b\x5e\xb1\x7e"
87 "\x5f\x4e",
88 .tag_len = 10,
89 },
90 {
91 .name = "NIST SP 800-38C Example 1",
92 .key = "\x40\x41\x42\x43\x44\x45\x46\x47"
93 "\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f",
94 .key_len = 16,
95 .nonce = "\x10\x11\x12\x13\x14\x15\x16",
96 .nonce_len = 7,
97 .ad = "\x00\x01\x02\x03\x04\x05\x06\x07",
98 .ad_len = 8,
99 .ptext = "\x20\x21\x22\x23",
100 .ctext = "\x71\x62\x01\x5b",
101 .data_len = 4,
102 .tag = "\x4d\xac\x25\x5d",
103 .tag_len = 4,
104 },
105 {
106 .name = "NIST SP 800-38C Example 2",
107 .key = "\x40\x41\x42\x43\x44\x45\x46\x47"
108 "\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f",
109 .key_len = 16,
110 .nonce = "\x10\x11\x12\x13\x14\x15\x16\x17",
111 .nonce_len = 8,
112 .ad = "\x00\x01\x02\x03\x04\x05\x06\x07"
113 "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
114 .ad_len = 16,
115 .ptext = "\x20\x21\x22\x23\x24\x25\x26\x27"
116 "\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f",
117 .ctext = "\xd2\xa1\xf0\xe0\x51\xea\x5f\x62"
118 "\x08\x1a\x77\x92\x07\x3d\x59\x3d",
119 .data_len = 16,
120 .tag = "\x1f\xc6\x4f\xbf\xac\xcd",
121 .tag_len = 6,
122 },
123 {
124 .name = "NIST SP 800-38C Example 3",
125 .key = "\x40\x41\x42\x43\x44\x45\x46\x47"
126 "\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f",
127 .key_len = 16,
128 .nonce = "\x10\x11\x12\x13\x14\x15\x16\x17"
129 "\x18\x19\x1a\x1b",
130 .nonce_len = 12,
131 .ad = "\x00\x01\x02\x03\x04\x05\x06\x07"
132 "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
133 "\x10\x11\x12\x13",
134 .ad_len = 20,
135 .ptext = "\x20\x21\x22\x23\x24\x25\x26\x27"
136 "\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f"
137 "\x30\x31\x32\x33\x34\x35\x36\x37",
138 .ctext = "\xe3\xb2\x01\xa9\xf5\xb7\x1a\x7a"
139 "\x9b\x1c\xea\xec\xcd\x97\xe7\x0b"
140 "\x61\x76\xaa\xd9\xa4\x42\x8a\xa5",
141 .data_len = 24,
142 .tag = "\x48\x43\x92\xfb\xc1\xb0\x99\x51",
143 .tag_len = 8,
144 },
145};
146
147static void test_aes_ccm_one_test_vector(struct kunit *test,
148 const struct aes_ccm_testvec *tv)
149{
150 u8 *ctext = alloc_buf(test, tv->data_len);
151 u8 *decrypted = alloc_buf(test, tv->data_len);
152 u8 *tag = alloc_buf(test, tv->tag_len);
153 struct aes_ccm_key key;
154 int err;
155
156 err = aes_ccm_preparekey(&key, tv->key, tv->key_len, tv->tag_len);
157 KUNIT_ASSERT_EQ_MSG(test, 0, err, "Failed to prepare key for %s",
158 tv->name);
159
160 err = aes_ccm_encrypt(ctext, tv->ptext, tv->data_len, tag, tv->ad,
161 tv->ad_len, tv->nonce, tv->nonce_len, &key);
162 KUNIT_ASSERT_EQ_MSG(test, 0, err, "Encryption failed for %s", tv->name);
163 KUNIT_ASSERT_MEMEQ_MSG(test, tv->ctext, ctext, tv->data_len,
164 "Wrong ciphertext for %s", tv->name);
165 KUNIT_ASSERT_MEMEQ_MSG(test, tag, tv->tag, tv->tag_len,
166 "Wrong tag for %s", tv->name);
167
168 err = aes_ccm_decrypt(decrypted, ctext, tv->data_len, tag, tv->ad,
169 tv->ad_len, tv->nonce, tv->nonce_len, &key);
170 KUNIT_ASSERT_EQ_MSG(test, 0, err, "Decryption failed for %s", tv->name);
171 KUNIT_ASSERT_MEMEQ_MSG(test, tv->ptext, decrypted, tv->data_len,
172 "Wrong plaintext for %s", tv->name);
173}
174
175static void test_aes_ccm_test_vectors(struct kunit *test)
176{
177 for (size_t i = 0; i < ARRAY_SIZE(aes_ccm_testvecs); i++)
178 test_aes_ccm_one_test_vector(test, &aes_ccm_testvecs[i]);
179}
180
181/*
182 * Test NIST SP 800-38C Example 4, which uses a deterministically-generated
183 * 65536-byte associated data string.
184 */
185static void test_aes_ccm_nist_sp800_38c_example4(struct kunit *test)
186{
187 struct aes_ccm_testvec tv = {
188 .name = "NIST SP 800-38C Example 4",
189 .key_len = 16,
190 .nonce_len = 13,
191 .ad_len = 65536,
192 .ctext = "\x69\x91\x5d\xad\x1e\x84\xc6\x37"
193 "\x6a\x68\xc2\x96\x7e\x4d\xab\x61"
194 "\x5a\xe0\xfd\x1f\xae\xc4\x4c\xc4"
195 "\x84\x82\x85\x29\x46\x3c\xcf\x72",
196 .data_len = 32,
197 .tag = "\xb4\xac\x6b\xec\x93\xe8\x59\x8e"
198 "\x7f\x0d\xad\xbc\xea\x5b",
199 .tag_len = 14,
200 };
201 u8 *key, *nonce, *ad, *ptext;
202
203 key = alloc_buf(test, tv.key_len);
204 for (size_t i = 0; i < tv.key_len; i++)
205 key[i] = 0x40 + i;
206
207 nonce = alloc_guarded_buf(test, tv.nonce_len);
208 for (size_t i = 0; i < tv.nonce_len; i++)
209 nonce[i] = 0x10 + i;
210
211 ad = alloc_guarded_buf(test, tv.ad_len);
212 for (size_t i = 0; i < tv.ad_len; i++)
213 ad[i] = (u8)i;
214
215 ptext = alloc_guarded_buf(test, tv.data_len);
216 for (size_t i = 0; i < tv.data_len; i++)
217 ptext[i] = 0x20 + i;
218
219 tv.key = key;
220 tv.nonce = nonce;
221 tv.ad = ad;
222 tv.ptext = ptext;
223
224 test_aes_ccm_one_test_vector(test, &tv);
225}
226
227static const size_t aes_ccm_valid_key_lens[] = { 16, 24, 32 };
228#define AEAD_MAX_KEY_LEN 32
229#define AEAD_VALID_KEY_LENS aes_ccm_valid_key_lens
230
231static const size_t aes_ccm_valid_nonce_lens[] = { 7, 8, 9, 10, 11, 12, 13 };
232#define AEAD_MAX_NONCE_LEN 13
233#define AEAD_VALID_NONCE_LENS aes_ccm_valid_nonce_lens
234
235static const size_t aes_ccm_valid_tag_lens[] = { 4, 6, 8, 10, 12, 14, 16 };
236#define AEAD_MAX_TAG_LEN 16
237#define AEAD_VALID_TAG_LENS aes_ccm_valid_tag_lens
238
239#define AEAD_KEY aes_ccm_key
240#define AEAD_CTX aes_ccm_ctx
241#define AEAD_PREPAREKEY aes_ccm_preparekey
242#define AEAD_ENCRYPT aes_ccm_encrypt
243#define AEAD_DECRYPT aes_ccm_decrypt
244
245#define AEAD_INIT aes_ccm_init
246#define AEAD_AUTH_UPDATE aes_ccm_auth_update
247#define AEAD_ENCRYPT_UPDATE aes_ccm_encrypt_update
248#define AEAD_DECRYPT_UPDATE aes_ccm_decrypt_update
249#define AEAD_ENCRYPT_FINAL aes_ccm_encrypt_final
250#define AEAD_DECRYPT_FINAL aes_ccm_decrypt_final
251
252/* This value was generated by gen-aead-testvecs.py. */
253static const u8 aes_ccm_monte_carlo_checksum[BLAKE2S_HASH_SIZE] = {
254 0x70, 0x1c, 0xde, 0xa4, 0xe2, 0x03, 0x50, 0xb2, 0xf5, 0x9e, 0x61,
255 0x66, 0xe4, 0xe5, 0x13, 0x1a, 0x00, 0x95, 0x34, 0x03, 0xb7, 0x61,
256 0x2c, 0xdb, 0xc3, 0x15, 0x36, 0x84, 0x93, 0x7f, 0xb4, 0x5b,
257};
258#define AEAD_MONTE_CARLO_CHECKSUM aes_ccm_monte_carlo_checksum
259
260#include "aead-test-template.h"
261
262/*
263 * Test that for each AES-CCM nonce length, the message length is validated
264 * against the correct corresponding maximum message length.
265 */
266static void test_aes_ccm_data_len_too_large(struct kunit *test)
267{
268 static const struct {
269 size_t nonce_len;
270 u64 max_data_len;
271 } lens[] = {
272 /* clang-format off */
273 { 7, 0xffffffffffffffff }, /* U64_MAX */
274 { 8, 0xffffffffffffff },
275 { 9, 0xffffffffffff },
276 { 10, 0xffffffffff },
277 { 11, 0xffffffff },
278 { 12, 0xffffff },
279 { 13, 0xffff },
280 /* clang-format on */
281 };
282 u8 nonce[13] = {};
283 u8 raw_key[AES_KEYSIZE_256] = {};
284 int err;
285 struct aes_ccm_key *key = alloc_buf(test, sizeof(*key));
286 struct aes_ccm_ctx ctx;
287
288 err = aes_ccm_preparekey(key, raw_key, sizeof(raw_key), 16);
289 KUNIT_ASSERT_EQ(test, 0, err);
290
291 for (size_t i = 0; i < ARRAY_SIZE(lens); i++) {
292 size_t nonce_len = lens[i].nonce_len;
293 u64 max_data_len = lens[i].max_data_len;
294
295 /* data_len <= max_data_len should be accepted. */
296 err = aes_ccm_init(&ctx, 0, 0, nonce, nonce_len, key);
297 KUNIT_ASSERT_EQ_MSG(
298 test, 0, err,
299 "data_len=0 wasn't accepted with nonce_len=%zu",
300 nonce_len);
301 err = aes_ccm_init(&ctx, max_data_len, 0, nonce, nonce_len,
302 key);
303 KUNIT_ASSERT_EQ_MSG(
304 test, 0, err,
305 "data_len=%llu wasn't accepted with nonce_len=%zu",
306 max_data_len, nonce_len);
307
308 /* data_len > max_data_len should be rejected. */
309 if (max_data_len == U64_MAX)
310 continue;
311 err = aes_ccm_init(&ctx, max_data_len + 1, 0, nonce, nonce_len,
312 key);
313 KUNIT_ASSERT_EQ_MSG(
314 test, -EOVERFLOW, err,
315 "data_len=%llu wasn't rejected with -EOVERFLOW with nonce_len=%zu (aes_ccm_init)",
316 max_data_len + 1, nonce_len);
317 if (max_data_len + 1 <= SIZE_MAX) {
318 err = aes_ccm_encrypt(NULL, NULL, max_data_len + 1,
319 NULL, NULL, 0, nonce, nonce_len,
320 key);
321 KUNIT_ASSERT_EQ_MSG(
322 test, -EOVERFLOW, err,
323 "data_len=%llu wasn't rejected with -EOVERFLOW with nonce_len=%zu (aes_ccm_encrypt)",
324 max_data_len + 1, nonce_len);
325 err = aes_ccm_decrypt(NULL, NULL, max_data_len + 1,
326 NULL, NULL, 0, nonce, nonce_len,
327 key);
328 KUNIT_ASSERT_EQ_MSG(
329 test, -EOVERFLOW, err,
330 "data_len=%llu wasn't rejected with -EOVERFLOW with nonce_len=%zu (aes_ccm_decrypt)",
331 max_data_len + 1, nonce_len);
332 }
333 err = aes_ccm_init(&ctx, U64_MAX, 0, nonce, nonce_len, key);
334 KUNIT_ASSERT_EQ_MSG(
335 test, -EOVERFLOW, err,
336 "data_len=U64_MAX wasn't rejected with -EOVERFLOW with nonce_len=%zu (aes_ccm_init)",
337 nonce_len);
338 }
339}
340
341static struct kunit_case aes_ccm_test_cases[] = {
342 KUNIT_CASE(test_aes_ccm_test_vectors),
343 KUNIT_CASE(test_aes_ccm_nist_sp800_38c_example4),
344 KUNIT_CASE(test_aes_ccm_data_len_too_large),
345 AEAD_KUNIT_CASES,
346 {},
347};
348
349static struct kunit_suite aes_ccm_test_suite = {
350 .name = "aes_ccm",
351 .test_cases = aes_ccm_test_cases,
352};
353kunit_test_suite(aes_ccm_test_suite);
354
355MODULE_DESCRIPTION("KUnit tests and benchmark for AES-CCM");
356MODULE_LICENSE("GPL");
scripts/crypto/gen-aead-testvecs.py+60−0
@@ -0,0 +1,60 @@
1#!/usr/bin/env python3
2# SPDX-License-Identifier: GPL-2.0-or-later
3#
4# Script that generates known-good data used in the AEAD tests.
5#
6# Requires that python-cryptography be installed.
7#
8# Copyright 2026 Google LLC
9
10import hashlib
11import sys
12import cryptography.hazmat.primitives.ciphers.aead
13
14
15# Deterministically generate 'length' random bytes.
16def rand_bytes(length):
17 seed = length
18 out = []
19 for _ in range(length):
20 seed = (seed * 25214903917 + 11) % 2**48
21 out.append((seed >> 16) % 256)
22 return bytes(out)
23
24
25# Deterministically generate many different AEAD inputs using exactly the same
26# method that the test uses; encrypt them using an independent implementation of
27# the algorithm; compute the checksum of all the resulting (ciphertext, authtag)
28# pairs concatenated to each other; and print the checksum as a C struct.
29def gen_monte_carlo_checksum(alg):
30 blake2s = hashlib.blake2s()
31 for data_len in range(1025):
32 ad_len = data_len % 293
33 pt = rand_bytes(data_len)
34 ad = rand_bytes(ad_len)
35 if alg == "aes-ccm":
36 key_len = [16, 24, 32][data_len % 3]
37 key = rand_bytes(key_len)
38 nonce = rand_bytes([7, 8, 9, 10, 11, 12, 13][data_len % 7])
39 tag_len = [4, 6, 8, 10, 12, 14, 16][data_len % 7]
40 ccm = cryptography.hazmat.primitives.ciphers.aead.AESCCM(
41 key, tag_length=tag_len
42 )
43 ct_and_tag = ccm.encrypt(nonce, pt, ad)
44
45 blake2s.update(ct_and_tag)
46
47 name = f"{alg.replace('-', '_')}_monte_carlo_checksum"
48 value = blake2s.digest()
49 print(f"static const u8 {name}[BLAKE2S_HASH_SIZE] = {{")
50 for i in range(0, len(value), 11):
51 line = "\t" + "".join(f"0x{b:02x}, " for b in value[i : i + 11])
52 print(f"{line.rstrip()}")
53 print("};")
54
55
56if len(sys.argv) != 2 or sys.argv[1] not in ("aes-ccm"):
57 sys.stderr.write("Usage: gen-aead-testvecs.py [aes-ccm]\n")
58 sys.exit(1)
59
60gen_monte_carlo_checksum(sys.argv[1])