Skip to content

Commit 8b027f6

Browse files
committed
nimble/ll: Add unit tests for CS DRBG
The BT specification provides sample data that can be used to test the correctness of a CS DRBG implementation.
1 parent ad2879b commit 8b027f6

File tree

4 files changed

+382
-0
lines changed

4 files changed

+382
-0
lines changed

nimble/controller/pkg.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,14 @@ pkg.deps:
4242
- nimble
4343
- nimble/transport
4444

45+
pkg.deps.TEST:
46+
- "@apache-mynewt-core/crypto/mbedtls"
47+
4548
pkg.init:
4649
ble_ll_init:
4750
- $before:ble_transport_hs_init
4851
- $before:ble_transport_ll_init
52+
53+
pkg.cflags.TEST:
54+
- -Irepos/mbedtls/include
55+
- -Irepos/include/mbedtls
Lines changed: 369 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,369 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
#include <stdint.h>
21+
#include <controller/ble_ll_utils.h>
22+
#include <testutil/testutil.h>
23+
#include "ble_ll_cs_drbg_priv.h"
24+
25+
extern uint8_t g_ble_ll_cs_chan_indices[72];
26+
27+
static void
28+
ble_ll_cs_drbg_e_test(void)
29+
{
30+
uint8_t key[16] = {0};
31+
uint8_t data[16] = {0};
32+
uint8_t out[16] = {0};
33+
uint8_t expected_out[16] = {0};
34+
35+
/* Sample data from BT spec Vol 6, Part C, 1.1 Encrypt Command
36+
* Swap because the copy-pasted strings are in leftmost (MSO) to rightmost
37+
* (LSO) orientation.
38+
*/
39+
swap_buf(key, (uint8_t [16]) {
40+
0x4C, 0x68, 0x38, 0x41, 0x39, 0xF5, 0x74, 0xD8,
41+
0x36, 0xBC, 0xF3, 0x4E, 0x9D, 0xFB, 0x01, 0xBF
42+
}, 16);
43+
44+
swap_buf(data, (uint8_t [16]) {
45+
0x02, 0x13, 0x24, 0x35, 0x46, 0x57, 0x68, 0x79,
46+
0xac, 0xbd, 0xce, 0xdf, 0xe0, 0xf1, 0x02, 0x13
47+
}, 16);
48+
49+
swap_buf(expected_out, (uint8_t [16]) {
50+
0x99, 0xad, 0x1b, 0x52, 0x26, 0xa3, 0x7e, 0x3e,
51+
0x05, 0x8e, 0x3b, 0x8e, 0x27, 0xc2, 0xc6, 0x66
52+
}, 16);
53+
54+
ble_ll_cs_drbg_e(key, data, out);
55+
TEST_ASSERT(memcmp(out, expected_out, sizeof(out)) == 0);
56+
}
57+
58+
static void
59+
ble_ll_cs_drbg_f7_test(void)
60+
{
61+
uint8_t v_s[80];
62+
uint8_t k[16];
63+
uint8_t k2[16] = {0};
64+
uint8_t x[16] = {0};
65+
uint8_t expected_k2[16] = {0};
66+
uint8_t expected_x[16] = {0};
67+
68+
/* Sample data from BT spec Vol 6, Part C, 7. Deterministic
69+
* random bit generator sample data.
70+
* Swap because the copy-pasted strings are in leftmost (MSO)
71+
* to rightmost (LSO) orientation.
72+
*/
73+
swap_buf(k, (uint8_t [16]) {
74+
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
75+
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
76+
}, 16);
77+
78+
swap_buf(v_s, (uint8_t [80]) {
79+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
80+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
81+
0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x20,
82+
0xE1, 0x0B, 0xC2, 0x8A, 0x0B, 0xFD, 0xDF, 0xE9,
83+
0x3E, 0x7F, 0x51, 0x86, 0xE0, 0xCA, 0x0B, 0x3B,
84+
0x9F, 0xF4, 0x77, 0xC1, 0x86, 0x73, 0x84, 0x0D,
85+
0xC9, 0x80, 0xDE, 0xDF, 0x98, 0x82, 0xED, 0x44,
86+
0x64, 0xA6, 0x74, 0x96, 0x78, 0x68, 0xF1, 0x43,
87+
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
88+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
89+
}, 80);
90+
91+
swap_buf(expected_k2, (uint8_t [16]) {
92+
0x8B, 0x2B, 0x06, 0xDC, 0x52, 0x2D, 0x3E, 0x0A,
93+
0xF0, 0xA5, 0x0C, 0xAF, 0x48, 0x10, 0xE0, 0x35
94+
}, 16);
95+
96+
TEST_ASSERT(ble_ll_cs_drbg_f7(k, v_s, sizeof(v_s), k2) == 0);
97+
TEST_ASSERT(memcmp(k2, expected_k2, sizeof(k2)) == 0);
98+
99+
v_s[76] = 0x01;
100+
swap_buf(expected_x, (uint8_t [16]) {
101+
0xA3, 0x4F, 0xBE, 0x57, 0xF8, 0xF9, 0x7E, 0x34,
102+
0x9D, 0x15, 0xA3, 0x76, 0x79, 0x60, 0x74, 0x64
103+
}, 16);
104+
105+
TEST_ASSERT(ble_ll_cs_drbg_f7(k, v_s, sizeof(v_s), x) == 0);
106+
TEST_ASSERT(memcmp(x, expected_x, sizeof(x)) == 0);
107+
}
108+
109+
static void
110+
ble_ll_cs_drbg_f8_test(void)
111+
{
112+
uint8_t input_bit_string[40] = {0};
113+
uint8_t expected_sm[32] = {0};
114+
uint8_t sm[32] = {0};
115+
116+
/* Sample data from BT spec Vol 6, Part C, 7. Deterministic
117+
* random bit generator sample data.
118+
* Swap because the copy-pasted strings are in leftmost (MSO)
119+
* to rightmost (LSO) orientation.
120+
*/
121+
122+
/* 320-bit input bit string created from concatenated vectors
123+
* CS_IV || CS_IN || CS_PV
124+
*/
125+
swap_buf(input_bit_string, (uint8_t [40]) {
126+
0xE1, 0x0B, 0xC2, 0x8A, 0x0B, 0xFD, 0xDF, 0xE9,
127+
0x3E, 0x7F, 0x51, 0x86, 0xE0, 0xCA, 0x0B, 0x3B,
128+
0x9F, 0xF4, 0x77, 0xC1, 0x86, 0x73, 0x84, 0x0D,
129+
0xC9, 0x80, 0xDE, 0xDF, 0x98, 0x82, 0xED, 0x44,
130+
0x64, 0xA6, 0x74, 0x96, 0x78, 0x68, 0xF1, 0x43
131+
}, 40);
132+
133+
swap_buf(expected_sm, (uint8_t [32]) {
134+
0xB6, 0x02, 0xB1, 0xB2, 0x8C, 0x6F, 0x0A, 0x3D,
135+
0xDA, 0xE6, 0x37, 0xB4, 0x84, 0x25, 0x08, 0x7D,
136+
0xDC, 0x18, 0x8C, 0x89, 0xA1, 0xB0, 0xCD, 0xFD,
137+
0xA1, 0xE8, 0xFC, 0x66, 0xC9, 0x99, 0x97, 0x50
138+
}, 32);
139+
140+
TEST_ASSERT(ble_ll_cs_drbg_f8(input_bit_string, sm) == 0);
141+
TEST_ASSERT(memcmp(sm, expected_sm, sizeof(sm)) == 0);
142+
}
143+
144+
static void
145+
ble_ll_cs_drbg_f9_test(void)
146+
{
147+
uint8_t sm[32] = {0};
148+
uint8_t k[16] = {0};
149+
uint8_t v[16] = {0};
150+
uint8_t expected_k[16] = {0};
151+
uint8_t expected_v[16] = {0};
152+
153+
/* First call to f9 from instantiation function h9,
154+
* K and V vectors filled with zeros.
155+
*
156+
* Sample data from BT spec Vol 6, Part C, 7. Deterministic
157+
* random bit generator sample data.
158+
* Swap because the copy-pasted strings are in leftmost (MSO)
159+
* to rightmost (LSO) orientation.
160+
*/
161+
162+
swap_buf(sm, (uint8_t [32]) {
163+
0xB6, 0x02, 0xB1, 0xB2, 0x8C, 0x6F, 0x0A, 0x3D,
164+
0xDA, 0xE6, 0x37, 0xB4, 0x84, 0x25, 0x08, 0x7D,
165+
0xDC, 0x18, 0x8C, 0x89, 0xA1, 0xB0, 0xCD, 0xFD,
166+
0xA1, 0xE8, 0xFC, 0x66, 0xC9, 0x99, 0x97, 0x50
167+
}, 32);
168+
169+
swap_buf(expected_k, (uint8_t [16]) {
170+
0xEE, 0xE0, 0x4D, 0x7C, 0x76, 0x11, 0x3A, 0x5C,
171+
0xEC, 0x99, 0x2A, 0xE3, 0x20, 0xC2, 0x4D, 0x27
172+
}, 16);
173+
174+
swap_buf(expected_v, (uint8_t [16]) {
175+
0xDF, 0x90, 0x56, 0x47, 0xC1, 0x06, 0x6E, 0x6F,
176+
0x52, 0xC0, 0x3E, 0xDF, 0xB8, 0x2B, 0x69, 0x28
177+
}, 16);
178+
179+
TEST_ASSERT(ble_ll_cs_drbg_f9(sm, k, v) == 0);
180+
TEST_ASSERT(memcmp(k, expected_k, sizeof(k)) == 0);
181+
TEST_ASSERT(memcmp(v, expected_v, sizeof(v)) == 0);
182+
}
183+
184+
static void
185+
cs_drbg_init(struct ble_ll_cs_drbg_ctx *ctx)
186+
{
187+
memset(ctx, 0, sizeof(*ctx));
188+
189+
/* CS_IV = CS_IV_P || CS_IV_C */
190+
swap_buf(ctx->iv, (uint8_t [16]) {
191+
0xE1, 0x0B, 0xC2, 0x8A, 0x0B, 0xFD, 0xDF, 0xE9,
192+
0x3E, 0x7F, 0x51, 0x86, 0xE0, 0xCA, 0x0B, 0x3B
193+
}, 16);
194+
195+
/* CS_IN = CS_IN_P || CS_IN_C */
196+
swap_buf(ctx->in, (uint8_t [8]) {
197+
0x9F, 0xF4, 0x77, 0xC1, 0x86, 0x73, 0x84, 0x0D
198+
}, 8);
199+
200+
/* CS_PV = CS_PV_P || CS_PV_C */
201+
swap_buf(ctx->pv, (uint8_t [16]) {
202+
0xC9, 0x80, 0xDE, 0xDF, 0x98, 0x82, 0xED, 0x44,
203+
0x64, 0xA6, 0x74, 0x96, 0x78, 0x68, 0xF1, 0x43
204+
}, 16);
205+
206+
ble_ll_cs_drbg_init(ctx);
207+
}
208+
209+
static void
210+
ble_ll_cs_drbg_rand_test(void)
211+
{
212+
struct ble_ll_cs_drbg_ctx ctx;
213+
uint8_t output[20] = {0};
214+
uint8_t expected_output[20] = {0};
215+
216+
/* Test if subsequent drgb generator calls returns expected bit sequences. */
217+
218+
cs_drbg_init(&ctx);
219+
220+
/* First round - request full 128-bit batch */
221+
swap_buf(expected_output, (uint8_t [16]) {
222+
0x79, 0x74, 0x1F, 0xD1, 0x8F, 0x57, 0x7B, 0x45,
223+
0xD0, 0x9A, 0x66, 0x5A, 0x7F, 0x1F, 0x28, 0x58
224+
}, 16);
225+
226+
TEST_ASSERT(ble_ll_cs_drbg_rand(
227+
&ctx, 0x00, BLE_LL_CS_DRBG_HOP_CHAN_NON_MODE0,
228+
output, 16) == 0);
229+
TEST_ASSERT(memcmp(output, expected_output, 16) == 0);
230+
}
231+
232+
static void
233+
ble_ll_cs_drbg_chan_selection_3b_test(void)
234+
{
235+
struct ble_ll_cs_drbg_ctx ctx;
236+
uint8_t filtered_channels[72] = {0};
237+
uint8_t shuffled_channels[72] = {0};
238+
uint8_t expected_shuffled_channels[19] = {0};
239+
240+
cs_drbg_init(&ctx);
241+
242+
memcpy(filtered_channels, (uint8_t [19]) {
243+
2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
244+
13, 14, 15, 16, 17, 18, 19, 20
245+
}, 19);
246+
247+
memcpy(expected_shuffled_channels, (uint8_t [19]) {
248+
11, 7, 14, 18, 9, 19, 10, 8, 5, 2, 4, 15, 16, 13, 12, 6, 17, 20, 3
249+
}, 19);
250+
assert(ble_ll_cs_drbg_shuffle_cr1(&ctx, 0x00, BLE_LL_CS_DRBG_HOP_CHAN_MODE0,
251+
filtered_channels, shuffled_channels, 19) == 0);
252+
assert(memcmp(shuffled_channels, expected_shuffled_channels, 19) == 0);
253+
254+
memcpy(expected_shuffled_channels, (uint8_t [19]) {
255+
6, 12, 5, 10, 3, 2, 18, 17, 16, 8, 11, 7, 19, 4, 13, 20, 9, 15, 14
256+
}, 19);
257+
assert(ble_ll_cs_drbg_shuffle_cr1(&ctx, 0x03, BLE_LL_CS_DRBG_HOP_CHAN_NON_MODE0,
258+
filtered_channels, shuffled_channels, 19) == 0);
259+
assert(memcmp(shuffled_channels, expected_shuffled_channels, 19) == 0);
260+
}
261+
262+
static void
263+
ble_ll_cs_drbg_generate_aa_test(void)
264+
{
265+
struct ble_ll_cs_drbg_ctx ctx;
266+
uint32_t initiator_aa;
267+
uint32_t reflector_aa;
268+
uint32_t expected_initiator_aa;
269+
uint32_t expected_reflector_aa;
270+
271+
cs_drbg_init(&ctx);
272+
273+
/* Step 0 */
274+
assert(ble_ll_cs_drbg_generate_aa(&ctx, 0, &initiator_aa, &reflector_aa) == 0);
275+
expected_initiator_aa = get_be32((uint8_t [4]) {0x6C, 0x37, 0x6A, 0xB8});
276+
expected_reflector_aa = get_be32((uint8_t [4]) {0xF0, 0x79, 0xBC, 0x3A});
277+
assert(initiator_aa == expected_initiator_aa);
278+
assert(reflector_aa == expected_reflector_aa);
279+
280+
/* Step 1 */
281+
assert(ble_ll_cs_drbg_generate_aa(&ctx, 1, &initiator_aa, &reflector_aa) == 0);
282+
expected_initiator_aa = get_be32((uint8_t [4]) {0x01, 0x1C, 0xAE, 0x4E});
283+
expected_reflector_aa = get_be32((uint8_t [4]) {0xD0, 0x6A, 0xCD, 0xDA});
284+
assert(initiator_aa == expected_initiator_aa);
285+
assert(reflector_aa == expected_reflector_aa);
286+
287+
/* Step 2 */
288+
assert(ble_ll_cs_drbg_generate_aa(&ctx, 2, &initiator_aa, &reflector_aa) == 0);
289+
expected_initiator_aa = get_be32((uint8_t [4]) {0x64, 0x06, 0x12, 0x14});
290+
expected_reflector_aa = get_be32((uint8_t [4]) {0x28, 0x94, 0x2F, 0x38});
291+
assert(initiator_aa == expected_initiator_aa);
292+
assert(reflector_aa == expected_reflector_aa);
293+
294+
/* Step 14 */
295+
assert(ble_ll_cs_drbg_generate_aa(&ctx, 14, &initiator_aa, &reflector_aa) == 0);
296+
expected_initiator_aa = get_be32((uint8_t [4]) {0xF7, 0x21, 0x97, 0x86});
297+
expected_reflector_aa = get_be32((uint8_t [4]) {0x57, 0x17, 0x64, 0x70});
298+
assert(initiator_aa == expected_initiator_aa);
299+
assert(reflector_aa == expected_reflector_aa);
300+
}
301+
302+
static void
303+
ble_ll_cs_drbg_rand_marker_position_test(void)
304+
{
305+
uint8_t position1;
306+
uint8_t position2;
307+
struct ble_ll_cs_drbg_ctx ctx;
308+
309+
cs_drbg_init(&ctx);
310+
311+
/* Step 9 */
312+
assert(ble_ll_cs_drbg_rand_marker_position(
313+
&ctx, 9, BLE_LL_CS_RTT_32_BIT_SOUNDING_SEQUENCE,
314+
&position1, &position2) == 0);
315+
assert(position1 == 12 && position2 == 0xFF);
316+
317+
assert(ble_ll_cs_drbg_rand_marker_position(
318+
&ctx, 9, BLE_LL_CS_RTT_32_BIT_SOUNDING_SEQUENCE,
319+
&position1, &position2) == 0);
320+
assert(position1 == 4 && position2 == 0xFF);
321+
322+
/* Step 14 */
323+
assert(ble_ll_cs_drbg_rand_marker_position(
324+
&ctx, 14, BLE_LL_CS_RTT_32_BIT_SOUNDING_SEQUENCE,
325+
&position1, &position2) == 0);
326+
assert(position1 == 8 && position2 == 0xFF);
327+
328+
assert(ble_ll_cs_drbg_rand_marker_position(
329+
&ctx, 14, BLE_LL_CS_RTT_32_BIT_SOUNDING_SEQUENCE,
330+
&position1, &position2) == 0);
331+
assert(position1 == 11 && position2 == 0xFF);
332+
}
333+
334+
static void
335+
ble_ll_cs_drbg_rand_marker_selection_test(void)
336+
{
337+
uint8_t marker_selection;
338+
struct ble_ll_cs_drbg_ctx ctx;
339+
340+
cs_drbg_init(&ctx);
341+
342+
/* Step 9 */
343+
assert(ble_ll_cs_drbg_rand_marker_selection(&ctx, 0x09, &marker_selection) == 0);
344+
assert(marker_selection == 0x00);
345+
346+
assert(ble_ll_cs_drbg_rand_marker_selection(&ctx, 0x09, &marker_selection) == 0);
347+
assert(marker_selection == 0x80);
348+
349+
memset(ctx.t_cache, 0, sizeof(ctx.t_cache));
350+
351+
/* Step 14 */
352+
assert(ble_ll_cs_drbg_rand_marker_selection(&ctx, 14, &marker_selection) == 0);
353+
assert(marker_selection == 0x80);
354+
355+
assert(ble_ll_cs_drbg_rand_marker_selection(&ctx, 14, &marker_selection) == 0);
356+
assert(marker_selection == 0x80);
357+
}
358+
359+
TEST_SUITE(ble_ll_cs_drbg_test_suite) {
360+
ble_ll_cs_drbg_e_test();
361+
ble_ll_cs_drbg_f7_test();
362+
ble_ll_cs_drbg_f8_test();
363+
ble_ll_cs_drbg_f9_test();
364+
ble_ll_cs_drbg_rand_test();
365+
ble_ll_cs_drbg_chan_selection_3b_test();
366+
ble_ll_cs_drbg_generate_aa_test();
367+
ble_ll_cs_drbg_rand_marker_position_test();
368+
ble_ll_cs_drbg_rand_marker_selection_test();
369+
}

0 commit comments

Comments
 (0)