capsules_extra/test/
aes_gcm.rs

1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2022.
4
5//! Test the AES GCM implementation on top of AES hardware.
6
7use core::cell::Cell;
8use kernel::debug;
9use kernel::hil::symmetric_encryption::{GCMClient, AES128GCM, AES128_KEY_SIZE};
10use kernel::utilities::cells::TakeCell;
11use kernel::ErrorCode;
12
13pub struct Test<'a, A: AES128GCM<'a>> {
14    aes_gcm: &'a A,
15
16    buf: TakeCell<'static, [u8]>,
17    current_test: Cell<usize>,
18    encrypting: Cell<bool>,
19
20    // (key, iv, pt, aad, ct, tag)
21    tests: [(
22        &'static [u8],
23        &'static [u8],
24        &'static [u8],
25        &'static [u8],
26        &'static [u8],
27        &'static [u8],
28    ); 2],
29}
30
31impl<'a, A: AES128GCM<'a>> Test<'a, A> {
32    pub fn new(aes_gcm: &'a A, buf: &'static mut [u8]) -> Test<'a, A> {
33        Test {
34            aes_gcm,
35            buf: TakeCell::new(buf),
36            current_test: Cell::new(0),
37            encrypting: Cell::new(true),
38            tests: [
39                (
40                    &KEY_128_TWELVE,
41                    &IV_128_TWELVE,
42                    &[],
43                    &AAD_128_TWELVE,
44                    &[],
45                    &TAG_128_TWELVE,
46                ),
47                (
48                    &KEY_128_THIRTEEN,
49                    &IV_128_THIRTEEN,
50                    &PT_128_THIRTEEN,
51                    &[],
52                    &CT_128_THIRTEEN,
53                    &TAG_128_THIRTEEN,
54                ),
55            ],
56        }
57    }
58
59    pub fn run(&self) {
60        debug!("AES GCM* encryption/decryption tests");
61        self.trigger_test();
62    }
63
64    fn next_test(&self) -> bool {
65        if self.encrypting.get() {
66            self.encrypting.set(false);
67        } else {
68            self.encrypting.set(true);
69            self.current_test.set(self.current_test.get() + 1);
70            if self.current_test.get() >= self.tests.len() {
71                return false;
72            }
73        }
74        true
75    }
76
77    fn trigger_test(&self) {
78        let (key, iv, pt, aad, ct, tag) = self.tests[self.current_test.get()];
79        let (aad_off, pt_off, pt_len) = (0, aad.len(), pt.len());
80        let encrypting = self.encrypting.get();
81
82        let buf = match self.buf.take() {
83            None => panic!("aes_gcm_test failed: buffer is not present in trigger_test."),
84            Some(buf) => buf,
85        };
86
87        if encrypting {
88            buf[aad_off..pt_off].copy_from_slice(aad);
89            buf[pt_off..pt_off + pt_len].copy_from_slice(pt);
90        } else {
91            buf[aad_off..pt_off].copy_from_slice(aad);
92            buf[pt_off..pt_off + pt_len].copy_from_slice(ct);
93            buf[pt_off + pt_len..(pt_off + pt_len + tag.len())].copy_from_slice(tag);
94        }
95
96        if self.aes_gcm.set_key(key) != Ok(()) {
97            panic!("aes_gcm_test failed: cannot set key.");
98        }
99
100        if self.aes_gcm.set_iv(iv) != Ok(()) {
101            panic!("aes_gcm_test failed: cannot set IV.");
102        }
103
104        let _ = self
105            .aes_gcm
106            .crypt(buf, aad_off, pt_off, pt_len, encrypting)
107            .map_err(|(_code, buf)| {
108                self.buf.replace(buf);
109                panic!("Failed to start test.");
110            });
111    }
112
113    fn check_test(&self, tag_is_valid: bool) {
114        let (_key, _iv, pt, aad, ct, tag) = self.tests[self.current_test.get()];
115        let (_aad_off, pt_off, pt_len) = (0, aad.len(), pt.len());
116        let encrypting = self.encrypting.get();
117
118        let buf = match self.buf.take() {
119            None => panic!("aes_gcm_test failed: buffer is not present in check_test."),
120            Some(buf) => buf,
121        };
122
123        if encrypting {
124            let ct_matches = buf[pt_off..(pt_off + pt_len)]
125                .iter()
126                .zip(ct.iter())
127                .all(|(a, b)| *a == *b);
128            let tag_matches = buf[(pt_off + pt_len)..(pt_off + pt_len + tag.len())]
129                .iter()
130                .zip(tag.iter())
131                .all(|(a, b)| *a == *b);
132
133            if ct_matches && tag_matches && tag_is_valid {
134                debug!(
135                    "aes_gcm_test passed: (current_test={}, encrypting={}, tag_is_valid={})",
136                    self.current_test.get(),
137                    self.encrypting.get(),
138                    tag_is_valid
139                );
140            } else {
141                panic!("aes_gcm_test failed: ct_matches={}, tag_matches={}, (current_test={}, encrypting={}, tag_is_valid={}",
142                       ct_matches,
143                       tag_matches,
144                       self.current_test.get(),
145                       self.encrypting.get(),
146                       tag_is_valid);
147            }
148        } else {
149            let pt_matches = buf[pt_off..(pt_off + pt_len)]
150                .iter()
151                .zip(pt.iter())
152                .all(|(a, b)| *a == *b);
153            let tag_matches = buf[(pt_off + pt_len)..(pt_off + pt_len + tag.len())]
154                .iter()
155                .zip(tag.iter())
156                .all(|(a, b)| *a == *b);
157
158            if pt_matches && tag_matches && tag_is_valid {
159                debug!(
160                    "aes_gcm_test passed: (current_test={}, encrypting={}, tag_is_valid={})",
161                    self.current_test.get(),
162                    self.encrypting.get(),
163                    tag_is_valid
164                );
165            } else {
166                panic!("aes_gcm_test failed: pt_matches={}, tag_matches={}, (current_test={}, encrypting={}, tag_is_valid={}",
167                       pt_matches,
168                       tag_matches,
169                       self.current_test.get(),
170                       self.encrypting.get(),
171                       tag_is_valid);
172            }
173        }
174
175        self.buf.replace(buf);
176    }
177}
178
179impl<'a, A: AES128GCM<'a>> GCMClient for Test<'a, A> {
180    fn crypt_done(&self, buf: &'static mut [u8], res: Result<(), ErrorCode>, tag_is_valid: bool) {
181        self.buf.replace(buf);
182        if res != Ok(()) {
183            panic!("aes_gcm_test failed: crypt_done returned {:?}", res);
184        } else {
185            self.check_test(tag_is_valid);
186            if self.next_test() {
187                self.trigger_test()
188            }
189        }
190    }
191}
192
193static KEY_128_TWELVE: [u8; AES128_KEY_SIZE] = [
194    0x26, 0x73, 0x0f, 0x1a, 0xd2, 0x4b, 0x76, 0xd6, 0x6f, 0x7a, 0xb8, 0x45, 0x9d, 0xdc, 0xd1, 0x17,
195];
196
197static IV_128_TWELVE: [u8; 12] = [
198    0x1f, 0xfb, 0x3e, 0x75, 0x71, 0xcb, 0x70, 0x14, 0x5e, 0xa5, 0x16, 0x53,
199];
200
201static AAD_128_TWELVE: [u8; 90] = [
202    0xbf, 0xc3, 0xa8, 0x08, 0xc0, 0x60, 0xcd, 0xfd, 0x2a, 0xb7, 0x69, 0x1b, 0x32, 0x4a, 0xb3, 0x59,
203    0x29, 0xe8, 0x0f, 0x26, 0x2b, 0xf3, 0xb9, 0x4c, 0xc2, 0xf4, 0x5c, 0x62, 0xbb, 0x0f, 0x32, 0xbc,
204    0x4e, 0x4b, 0x96, 0x73, 0x69, 0x11, 0x0a, 0x7b, 0x4c, 0x47, 0x82, 0x7e, 0x93, 0xa9, 0xec, 0xd7,
205    0xfc, 0xda, 0x5e, 0x6a, 0x97, 0x39, 0xa0, 0xd1, 0x78, 0x6d, 0x6d, 0xc7, 0xa4, 0x5c, 0x9c, 0x1e,
206    0x8e, 0xcc, 0x8f, 0x90, 0xdc, 0x70, 0xbc, 0x5a, 0x5a, 0xe1, 0xa0, 0x31, 0x3f, 0xd6, 0xef, 0x87,
207    0xd7, 0xb3, 0x6e, 0x3d, 0x48, 0xc4, 0x44, 0x8f, 0x70, 0x3e,
208];
209
210static TAG_128_TWELVE: [u8; 14] = [
211    0x45, 0xa9, 0xbe, 0x4c, 0x84, 0x9e, 0xcb, 0x25, 0x85, 0x42, 0x1a, 0x1f, 0x08, 0xe6,
212];
213
214static KEY_128_THIRTEEN: [u8; AES128_KEY_SIZE] = [
215    0x8f, 0x85, 0xd3, 0x66, 0x16, 0xa9, 0x5f, 0xc1, 0x05, 0x86, 0xc3, 0x16, 0xb3, 0x05, 0x37, 0x70,
216];
217
218static IV_128_THIRTEEN: [u8; 12] = [
219    0xd3, 0x20, 0xb5, 0x00, 0x26, 0x96, 0x09, 0xac, 0xe1, 0xbe, 0x67, 0xce,
220];
221
222static PT_128_THIRTEEN: [u8; 32] = [
223    0x3a, 0x75, 0x8e, 0xe0, 0x72, 0xfc, 0x70, 0xa6, 0x42, 0x75, 0xb5, 0x6e, 0x72, 0xcb, 0x23, 0xa1,
224    0x59, 0x04, 0x58, 0x9c, 0xef, 0xbe, 0xeb, 0x58, 0x48, 0xec, 0x53, 0xff, 0xc0, 0x6c, 0x7a, 0x5d,
225];
226
227static CT_128_THIRTEEN: [u8; 32] = [
228    0xfb, 0x2f, 0xe3, 0xeb, 0x40, 0xed, 0xfb, 0xd2, 0x2a, 0x51, 0x6b, 0xec, 0x35, 0x9d, 0x4b, 0xb4,
229    0x23, 0x8a, 0x07, 0x00, 0xa4, 0x6f, 0xee, 0x11, 0x36, 0xa0, 0x61, 0x85, 0x40, 0x22, 0x9c, 0x41,
230];
231
232static TAG_128_THIRTEEN: [u8; 16] = [
233    0x42, 0x26, 0x93, 0x16, 0xce, 0xce, 0x7d, 0x88, 0x2c, 0xc6, 0x8c, 0x3e, 0xd9, 0xd2, 0xf0, 0xae,
234];