1 /*
2  * Copyright 2018 Oticon A/S
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 #include <stdlib.h>
7 #include <stdio.h>
8 #include <stdint.h>
9 #include <string.h>
10 #include "blecrypt.h"
11 
print_bytes(const void * data,int data_len)12 static void print_bytes(const void *data, int data_len)
13 {
14     char s[3*data_len + 1];
15     memset(s, 0, 3*data_len + 1);
16     const uint8_t *ip = data;
17     char *op = s;
18     if (data_len > 0)
19     {
20         op += sprintf(op, "%02x", *ip++);
21         while (--data_len > 0)
22         {
23             op += sprintf(op, " %02x", *ip++);
24         }
25     }
26     printf("    %s\n", s);
27 }
28 
29 // Calculates session key for encryption/decryption (wrapper for blecrypt_aes_128 function).
30 // Call this once when BLE link is going to be encrypted.
blecrypt_session_key_calc(const uint8_t * skd,const uint8_t * ltk,uint8_t * sk)31 void blecrypt_session_key_calc(
32     // Inputs
33     const uint8_t *skd,                             // Session key diversifier (SKD_LEN bytes, little-endian)
34     const uint8_t *ltk,                             // Long (or short) term key (KEY_LEN bytes, little-endian)
35     // Outputs (the pointers themselves are inputs and must point to large enough areas)
36     uint8_t *sk)                                    // Session key (KEY_LEN bytes, BIG-ENDIAN)
37 {
38     uint8_t skd_be[KEY_LEN];
39     uint8_t ltk_be[KEY_LEN];
40 
41     // Flip key and plaintext data to big-endian
42     blecrypt_reverse_byte_order(skd, skd_be, KEY_LEN);
43     blecrypt_reverse_byte_order(ltk, ltk_be, KEY_LEN);
44 
45     // Calculate session key by encrypting SKD with LTK
46     blecrypt_aes_128(ltk_be, skd_be, sk);
47 }
48 
49 
50 // Tests session key calculation by calculating session key and checking result against reference.
test_session_key_calc(const uint8_t * skd,const uint8_t * ltk,const uint8_t * expected_sk,uint8_t * sk)51 static void test_session_key_calc(
52     // Inputs
53     const uint8_t *skd,
54     const uint8_t *ltk,
55     const uint8_t *expected_sk, // little-endian here
56     // Outputs (the pointers themselves are inputs and must point to large enough areas)
57     uint8_t *sk) // session key is big-endian for OpenSSL
58 {
59     uint8_t sk_le[KEY_LEN];
60 
61     // Calculate session key
62     blecrypt_session_key_calc(skd, ltk, sk);
63 
64     // Check results (session key needs to be flipped to little-endian for comparison)
65     blecrypt_reverse_byte_order(sk, sk_le, KEY_LEN);
66     if (memcmp(sk_le, expected_sk, KEY_LEN) != 0)
67     {
68         printf("FAILED: Session key doesn't match reference.\n");
69         exit(1);
70     }
71     printf("PASSED: Verified session key.\n");
72     print_bytes(sk_le, KEY_LEN);
73 }
74 
75 // Calculates CCM nonce for packet.
nonce_calc(const uint8_t * iv,uint64_t packet_counter,blecrypt_packet_direction_t packet_direction,uint8_t * ccm_nonce)76 static void nonce_calc(
77     // Inputs
78     const uint8_t *iv,                              // Initialization vector (IV_LEN bytes, little-endian)
79     uint64_t packet_counter,                        // 39-bit packet count (in given direction, excl. retransmissions and empty packets) since start of encryption
80     blecrypt_packet_direction_t packet_direction,   // Direction of packet
81     // Outputs (the pointers themselves are inputs and must point to large enough areas)
82     uint8_t *ccm_nonce)                             // Resulting nonce (NONCE_LEN bytes, little-endian)
83 {
84     int i;
85     // Copy 39-bit packet counter into first 5 bytes of nonce and set 40th bit depending on packet
86     // direction
87     for (i = 0; i < NONCE_LEN - IV_LEN - 1; i++)
88     {
89         ccm_nonce[i] = packet_counter & 0xFF;
90         packet_counter >>= 8;
91     }
92     ccm_nonce[i] = (packet_counter & 0x7F) | (packet_direction == MASTER_TO_SLAVE_DIRECTION ? 0x80 : 0);
93     // Copy initialization vector into remaining 8 bytes of nonce
94     memcpy(&ccm_nonce[NONCE_LEN - IV_LEN], iv, IV_LEN);
95 }
96 
97 
98 // Tests encryption by encrypting 1 packet and checking result against reference.
test_packet_encryption(const uint8_t * unencrypted_packet_payload,const uint8_t * expected_encrypted_packet,blecrypt_packet_direction_t packet_direction,uint64_t packet_counter,const uint8_t * iv,const uint8_t * sk)99 static void test_packet_encryption(
100     // Inputs
101     const uint8_t *unencrypted_packet_payload,
102     const uint8_t *expected_encrypted_packet,
103     blecrypt_packet_direction_t packet_direction,
104     uint64_t packet_counter,
105     const uint8_t *iv,
106     const uint8_t *sk) // session key is big-endian for OpenSSL
107 {
108     // Set up variables
109     uint8_t packet_1st_header_byte = expected_encrypted_packet[0];
110     int packet_payload_and_mic_len = expected_encrypted_packet[1];
111     const uint8_t *expected_encrypted_packet_payload_and_mic = &expected_encrypted_packet[2];
112     int packet_payload_len = packet_payload_and_mic_len - MIC_LEN;
113     uint8_t encrypted_packet_payload_and_mic[255 /*packet_payload_and_mic_len*/]; // Local buffer for encryption output
114 
115     uint8_t ccm_nonce[NONCE_LEN];
116     // Calculate nonce
117     nonce_calc(iv, packet_counter, packet_direction, ccm_nonce);
118 
119     // Encrypt
120     blecrypt_packet_encrypt(
121         packet_1st_header_byte, packet_payload_len, unencrypted_packet_payload, sk, ccm_nonce,
122         encrypted_packet_payload_and_mic);
123 
124     // Check results
125     if (memcmp(encrypted_packet_payload_and_mic, expected_encrypted_packet_payload_and_mic, packet_payload_and_mic_len) != 0)
126     {
127         printf("FAILED: Encrypted packet doesn't match reference.\n");
128         exit(1);
129     }
130     printf("PASSED: Verified encrypted packet payload and MIC.\n");
131     print_bytes(encrypted_packet_payload_and_mic, packet_payload_and_mic_len);
132 }
133 
134 // Tests decryption by decrypting 1 packet and checking result against reference.
test_packet_decryption(const uint8_t * encrypted_packet,const uint8_t * expected_decrypted_packet_payload,blecrypt_packet_direction_t packet_direction,uint64_t packet_counter,const uint8_t * iv,const uint8_t * sk,int no_mic)135 static void test_packet_decryption(
136     // Inputs
137     const uint8_t *encrypted_packet,
138     const uint8_t *expected_decrypted_packet_payload,
139     blecrypt_packet_direction_t packet_direction,
140     uint64_t packet_counter,
141     const uint8_t *iv,
142     const uint8_t *sk, // session key is big-endian for OpenSSL
143     int no_mic)
144 {
145     // Set up variables
146     uint8_t packet_1st_header_byte = encrypted_packet[0];
147     int packet_payload_len = encrypted_packet[1] - (no_mic ? 0 : MIC_LEN);
148     const uint8_t *encrypted_packet_payload_and_mic = &encrypted_packet[2];
149     uint8_t decrypted_packet_payload[251 /*packet_payload_len*/]; // Local buffer for decryption output
150     int mic_ok;
151 
152     uint8_t ccm_nonce[NONCE_LEN];
153     // Calculate nonce
154     nonce_calc(iv, packet_counter, packet_direction, ccm_nonce);
155 
156     // Decrypt
157     mic_ok = blecrypt_packet_decrypt(
158         packet_1st_header_byte, packet_payload_len, encrypted_packet_payload_and_mic, sk, ccm_nonce,
159         no_mic,
160         decrypted_packet_payload);
161 
162     // Check results
163     if (!mic_ok)
164     {
165         printf("FAILED: MIC verification failed.\n");
166         exit(1);
167     }
168     if (memcmp(decrypted_packet_payload, expected_decrypted_packet_payload, packet_payload_len) != 0)
169     {
170         printf("FAILED: Decrypted packet doesn't match reference.\n");
171         exit(1);
172     }
173     if (no_mic)
174     {
175         printf("PASSED: Verified decrypted packet payload (MIC not present).\n");
176     }
177     else
178     {
179         printf("PASSED: Verified MIC and decrypted packet payload.\n");
180     }
181     print_bytes(decrypted_packet_payload, packet_payload_len);
182 }
183 
184 ///////////////////////////////////////////////////////////////////////////////
185 // BLE sample data from BT Core v4.2 vol 6 part C section 1
186 ///////////////////////////////////////////////////////////////////////////////
187 
188 // LTK (16 bytes little-endian) - slave's long term key
189 static const uint8_t ref_ltk[KEY_LEN] = {
190     0xbf, 0x01, 0xfb, 0x9d, 0x4e, 0xf3, 0xbc, 0x36, 0xd8, 0x74, 0xf5, 0x39, 0x41, 0x38, 0x68, 0x4c
191 };
192 
193 // SKDm (8 bytes little-endian) - master's part of session key diversifier
194 static const uint8_t ref_skd_m[SKD_LEN/2] = {
195     0x13, 0x02, 0xf1, 0xe0, 0xdf, 0xce, 0xbd, 0xac
196 };
197 
198 // IVm (4 bytes little-endian) - master's part of initialization vector
199 static const uint8_t ref_iv_m[IV_LEN/2] = {
200     0x24, 0xab, 0xdc, 0xba
201 };
202 
203 // SKDs (8 bytes little-endian) - slave's part of session key diversifier
204 static const uint8_t ref_skd_s[SKD_LEN/2] = {
205     0x79, 0x68, 0x57, 0x46, 0x35, 0x24, 0x13, 0x02
206 };
207 
208 // IVs (4 bytes little-endian) - slave's part of initialization vector
209 static const uint8_t ref_iv_s[IV_LEN/2] = {
210     0xbe, 0xba, 0xaf, 0xde
211 };
212 
213 // SK (16 bytes little-endian) - session key (this is the CCM key used to encrypt BLE packets)
214 static const uint8_t ref_sk[KEY_LEN] = {
215     0x66, 0xc6, 0xc2, 0x27, 0x8e, 0x3b, 0x8e, 0x05, 0x3e, 0x7e, 0xa3, 0x26, 0x52, 0x1b, 0xad, 0x99
216 };
217 
218 // Packets
219 
220 // LL_START_ENC_RSP1 (master -> slave)
221 static const uint8_t packet0_encrypted[] = {
222     0x0F, 0x05, 0x9f, 0xcd, 0xa7, 0xf4, 0x48
223 };
224 static const uint8_t packet0_payload_unencrypted[] = {
225     0x06
226 };
227 
228 // LL_START_ENC_RSP2 (slave -> master)
229 static const uint8_t packet1_encrypted[] = {
230     0x07, 0x05, 0xa3, 0x4c, 0x13, 0xa4, 0x15
231 };
232 static const uint8_t packet1_payload_unencrypted[] = {
233     0x06
234 };
235 
236 // LL_DATA1 (master -> slave)
237 static const uint8_t packet2_encrypted[] = {
238     0x0e, 0x1f, 0x7a, 0x70, 0xd6, 0x64, 0x15, 0x22, 0x6d, 0xf2, 0x6b, 0x17, 0x83, 0x9a, 0x06, 0x04, 0x05, 0x59, 0x6b, 0xd6, 0x56, 0x4f, 0x79, 0x6b, 0x5b, 0x9c, 0xe6, 0xff, 0x32, 0xf7, 0x5a, 0x6d, 0x33
239 };
240 static const uint8_t packet2_payload_unencrypted[] = {
241     0x17, 0x00, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30
242 };
243 
244 // LL_DATA2 (slave -> master)
245 static const uint8_t packet3_encrypted[] = {
246     0x06, 0x1f, 0xf3, 0x88, 0x81, 0xe7, 0xbd, 0x94, 0xc9, 0xc3, 0x69, 0xb9, 0xa6, 0x68, 0x46, 0xdd, 0x47, 0x86, 0xaa, 0x8c, 0x39, 0xce, 0x54, 0x0d, 0x0d, 0xae, 0x3a, 0xdc, 0xdf, 0x89, 0xb9, 0x60, 0x88
247 };
248 static const uint8_t packet3_payload_unencrypted[] = {
249     0x17, 0x00, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x30, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51
250 };
251 
252 ///////////////////////////////////////////////////////////////////////////////
253 // End of BLE sample data
254 ///////////////////////////////////////////////////////////////////////////////
255 
256 ///////////////////////////////////////////////////////////////////////////////
257 // MIC-less test data (copy of BLE sample data with MIC removed)
258 ///////////////////////////////////////////////////////////////////////////////
259 
260 // LL_DATA1 (master -> slave) with no MIC
261 static const uint8_t packet2_encrypted_no_mic[] = {
262     0x0e, 0x1b, 0x7a, 0x70, 0xd6, 0x64, 0x15, 0x22, 0x6d, 0xf2, 0x6b, 0x17, 0x83, 0x9a, 0x06, 0x04, 0x05, 0x59, 0x6b, 0xd6, 0x56, 0x4f, 0x79, 0x6b, 0x5b, 0x9c, 0xe6, 0xff, 0x32
263 };
264 
265 ///////////////////////////////////////////////////////////////////////////////
266 // End of MIC-less test data
267 ///////////////////////////////////////////////////////////////////////////////
268 
269 
270 // Values of MIC presence flag for decryption
271 #define HAS_MIC     0
272 #define HAS_NO_MIC  1
273 
main(int argc,char * argv[])274 int main(int argc, char *argv[])
275 {
276     // In reality both the master and slave devices have copies of both the master and slave packet
277     // counters, but the counter values should always be the same in both devices (as soon as
278     // transmissions have been acknowledged), so for this test bench we need only 1 copy of the 2
279     // counters
280     uint64_t master_packet_counter = 0;
281     uint64_t slave_packet_counter = 0;
282 
283     // SKD - session key diversifier
284     uint8_t skd[SKD_LEN];
285     // IV - initialization vector
286     uint8_t iv[IV_LEN];
287     // SK - session key (this is the CCM key used to encrypt BLE packets)
288     uint8_t sk[KEY_LEN]; // sk is big-endian for OpenSSL
289 
290     // Calculate SKD by concatenating SKDm and SKDs (master and slave contributions)
291     memcpy(skd, ref_skd_m, SKD_LEN/2);
292     memcpy(skd + SKD_LEN/2, ref_skd_s, SKD_LEN/2);
293 
294     // Calculate IV by concatenating IVm and IVs (master and slave contributions)
295     memcpy(iv, ref_iv_m, IV_LEN/2);
296     memcpy(iv + IV_LEN/2, ref_iv_s, IV_LEN/2);
297 
298     // Calculate session key, and check results
299     test_session_key_calc(skd, ref_ltk, ref_sk, sk);
300 
301     // Encrypt and decrypt packets, and check results
302     test_packet_encryption(packet0_payload_unencrypted, packet0_encrypted, MASTER_TO_SLAVE_DIRECTION, master_packet_counter, iv, sk);
303     test_packet_decryption(packet0_encrypted, packet0_payload_unencrypted, MASTER_TO_SLAVE_DIRECTION, master_packet_counter, iv, sk, HAS_MIC);
304     master_packet_counter++;
305     test_packet_encryption(packet1_payload_unencrypted, packet1_encrypted, SLAVE_TO_MASTER_DIRECTION, slave_packet_counter, iv, sk);
306     test_packet_decryption(packet1_encrypted, packet1_payload_unencrypted, SLAVE_TO_MASTER_DIRECTION, slave_packet_counter, iv, sk, HAS_MIC);
307     slave_packet_counter++;
308     test_packet_encryption(packet2_payload_unencrypted, packet2_encrypted, MASTER_TO_SLAVE_DIRECTION, master_packet_counter, iv, sk);
309     test_packet_decryption(packet2_encrypted, packet2_payload_unencrypted, MASTER_TO_SLAVE_DIRECTION, master_packet_counter, iv, sk, HAS_MIC);
310     // Non-standard MIC-less encryption mode
311     test_packet_decryption(packet2_encrypted_no_mic, packet2_payload_unencrypted, MASTER_TO_SLAVE_DIRECTION, master_packet_counter, iv, sk, HAS_NO_MIC);
312     master_packet_counter++;
313     test_packet_encryption(packet3_payload_unencrypted, packet3_encrypted, SLAVE_TO_MASTER_DIRECTION, slave_packet_counter, iv, sk);
314     test_packet_decryption(packet3_encrypted, packet3_payload_unencrypted, SLAVE_TO_MASTER_DIRECTION, slave_packet_counter, iv, sk, HAS_MIC);
315     slave_packet_counter++;
316 
317     printf("All tests PASSED!\n");
318     return 0;
319 }
320