1 /**
2 * Copyright (c) 2018 Oticon A/S
3 * Copyright (c) 2023 Nordic Semiconductor ASA
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19
20 #include <stdbool.h>
21 #include <dlfcn.h>
22 #include <string.h>
23 #include "bs_types.h"
24 #include "bs_tracing.h"
25 #include "bs_cmd_line.h"
26 #include "bs_dynargs.h"
27 #include "nsi_tasks.h"
28
29 static bool latest_ccm_if = true;
30
31 static bool Real_encryption_enabled = false;
32 static void *LibCryptoHandle = NULL;
33 //Note that if this library IF is changed, this function prototypes need to be updated:
34 //IF to the libCryptoBLE:
35 typedef enum { SLAVE_TO_MASTER_DIRECTION, MASTER_TO_SLAVE_DIRECTION } blecrypt_packet_direction_t;
36
37 typedef void (*blecrypt_packet_encrypt_f)(
38 // Inputs
39 uint8_t packet_1st_header_byte,
40 uint8_t packet_payload_len,
41 const uint8_t *packet_payload,
42 const uint8_t *sk,
43 const uint8_t *nonce,
44 uint8_t *encrypted_packet_payload_and_mic);
45
46 typedef int (*blecrypt_packet_decrypt_f)(
47 uint8_t packet_1st_header_byte,
48 uint8_t packet_payload_len,
49 const uint8_t *packet_payload_and_mic,
50 const uint8_t *sk,
51 const uint8_t *nonce,
52 int no_mic,
53 uint8_t *decrypted_packet_payload);
54
55 typedef void (*blecrypt_packet_encrypt_v3_f)(
56 uint8_t *adata,
57 int alen,
58 int mlen,
59 int maclen,
60 int noncelen,
61 const uint8_t *mdata,
62 const uint8_t *sk,
63 const uint8_t *ccm_nonce,
64 uint8_t *encrypted_packet_payload_and_mac
65 );
66
67 typedef int (*blecrypt_packet_decrypt_v3_f)(
68 uint8_t *adata,
69 int alen,
70 int mlen,
71 int maclen,
72 int noncelen,
73 const uint8_t *mdata_and_mac,
74 const uint8_t *sk,
75 const uint8_t *ccm_nonce,
76 int no_mac,
77 uint8_t *decrypted_packet_payload
78 );
79
80 typedef void (*blecrypt_aes_128_f)(
81 // Inputs
82 const uint8_t *key_be, // Key (KEY_LEN bytes, big-endian)
83 const uint8_t *plaintext_data_be, // Plaintext data (KEY_LEN bytes, big-endian)
84 // Outputs (the pointers themselves are inputs and must point to large enough areas)
85 uint8_t *encrypted_data_be); // Plaintext data (KEY_LEN bytes, big-endian)
86
87 typedef void (*blecrypt_aes_ecb_f)(
88 // Inputs
89 const uint8_t *key_be, // Key (KEY_LEN bytes, big-endian)
90 size_t key_size, // Key size in bits
91 const uint8_t *plaintext_data_be, // Plaintext data (128bits/16Bytes, big-endian)
92 // Outputs (the pointers themselves are inputs and must point to large enough areas)
93 uint8_t *encrypted_data_be); // Plaintext data (KEY_LEN bytes, big-endian)
94
95 static blecrypt_packet_encrypt_f blecrypt_packet_encrypt;
96 static blecrypt_packet_encrypt_v3_f blecrypt_packet_encrypt_v3;
97 static blecrypt_packet_decrypt_f blecrypt_packet_decrypt;
98 static blecrypt_packet_decrypt_v3_f blecrypt_packet_decrypt_v3;
99 static blecrypt_aes_128_f blecrypt_aes_128;
100 static blecrypt_aes_ecb_f blecrypt_aes_ecb;
101
102 static bool BLECrypt_if_args_useRealAES;
103
BLECrypt_if_register_cmd_args(void)104 static void BLECrypt_if_register_cmd_args(void) {
105 static bs_args_struct_t args_struct_toadd[] = {
106 {
107 .option = "RealEncryption",
108 .name = "realAES",
109 .type = 'b',
110 .dest = (void*)&BLECrypt_if_args_useRealAES,
111 .descript = "(0)/1 Use the real AES encryption for the LL or just send everything in "
112 "plain text (default) (requires the ext_libCryptov1 component)"
113 },
114 ARG_TABLE_ENDMARKER
115 };
116
117 bs_add_extra_dynargs(args_struct_toadd);
118 }
119
120 NSI_TASK(BLECrypt_if_register_cmd_args, PRE_BOOT_1, 90);
121
BLECrypt_if_enable_real_encryption(void)122 static void BLECrypt_if_enable_real_encryption(void) {
123 if ( BLECrypt_if_args_useRealAES ) { //if the user tried to enable it
124 //Attempt to load libCrypto
125 char lib_name[128];
126 char *error;
127 snprintf(lib_name,128,"../lib/libCryptov1.so"); //Relative to the working directory which is expected to be the bin folder
128 LibCryptoHandle = dlopen(lib_name, RTLD_NOW);
129 if (!LibCryptoHandle) { //Not found
130 snprintf(lib_name,128,"libCryptov1.so"); //Let's see if the user set LD_LIBRARY_PATH
131 LibCryptoHandle = dlopen(lib_name, RTLD_NOW);
132 if (!LibCryptoHandle) {
133 bs_trace_warning_line("%s\n",dlerror());
134 bs_trace_warning_line("Could not find the libCrypto library neither in ../lib or in LD_LIBRARY_PATH, is it compiled? => disabling real encryption\n");
135 Real_encryption_enabled = false;
136 return;
137 } else {
138 bs_trace_info_line(3, "This executable assumes the working directory is BabbleSim's bin/ folder, but it is not. libCrypto was found anyhow\n");
139 }
140 }
141 if ((error = dlerror()) != NULL) {
142 bs_trace_error_line("%s\n",error);
143 }
144
145 *(void **) (&blecrypt_packet_encrypt) = dlsym(LibCryptoHandle, "blecrypt_packet_encrypt");
146 if ((error = dlerror()) != NULL) {
147 bs_trace_error_line("%s\n",error);
148 }
149 *(void **) (&blecrypt_packet_decrypt) = dlsym(LibCryptoHandle, "blecrypt_packet_decrypt");
150 if ((error = dlerror()) != NULL) {
151 bs_trace_error_line("%s\n",error);
152 }
153 *(void **) (&blecrypt_aes_128) = dlsym(LibCryptoHandle, "blecrypt_aes_128");
154 if ((error = dlerror()) != NULL) {
155 bs_trace_error_line("%s\n",error);
156 }
157 *(void **) (&blecrypt_aes_ecb) = dlsym(LibCryptoHandle, "blecrypt_aes_ecb");
158 if ((error = dlerror()) != NULL) {
159 //bs_trace_warning_line("Too old libCrypto library please update. 54L CRACEN CM AES model will just pass thru (%s)\n",error);
160 }
161 *(void **) (&blecrypt_packet_encrypt_v3) = dlsym(LibCryptoHandle, "blecrypt_packet_encrypt_v3");
162 if ((error = dlerror()) != NULL) {
163 bs_trace_warning_line("%s\n",error);
164 latest_ccm_if = false;
165 bs_trace_info_line(2, "Falling back to old libCrypto IF. 802.15.4 encryption will not work properly for 54 devices. "
166 "Please update your bsim installation\n",error);
167 }
168 *(void **) (&blecrypt_packet_decrypt_v3) = dlsym(LibCryptoHandle, "blecrypt_packet_decrypt_v3");
169 if ((error = dlerror()) != NULL) {
170 bs_trace_warning_line("%s\n",error);
171 }
172 Real_encryption_enabled = true;
173 } else {
174 Real_encryption_enabled = false;
175 }
176 }
177
178 NSI_TASK(BLECrypt_if_enable_real_encryption, HW_INIT, 100);
179
BLECrypt_if_free(void)180 static void BLECrypt_if_free(void){
181 if ( LibCryptoHandle != NULL ){
182 //#define DONTCLOSELIBRARIES
183 #ifndef DONTCLOSELIBRARIES /*To be able to profile time spent in libraries in callgrind*/
184 dlclose(LibCryptoHandle);
185 LibCryptoHandle = NULL;
186 #endif
187 }
188 }
189
190 NSI_TASK(BLECrypt_if_free, ON_EXIT_POST, 100);
191
BLECrypt_if_encrypt_packet(uint8_t packet_first_header_byte,const uint8_t * unecrypted_payload,uint8_t * encrypted_payload,int length,bool generate_mic,const uint8_t * sk,const uint8_t * nonce)192 void BLECrypt_if_encrypt_packet(uint8_t packet_first_header_byte, // First byte of packet header
193 const uint8_t* unecrypted_payload, // Packet payload to be encrypted
194 uint8_t* encrypted_payload, //encrypted payload (and MIC if generate_mic==1)
195 int length, //including MIC length if ( generate_mic == 1 ) ; [ just the length in the packet header ]
196 bool generate_mic, //we have MIC, or not
197 const uint8_t* sk, // Session key (16 bytes, BIG-ENDIAN)
198 const uint8_t* nonce // CCM Nonce (NONCE_LEN bytes, little-endian)
199 ){
200
201 if ( length > 0 ) { //otherwise there is nothing to encrypt and for sure no MIC to add
202 uint8_t packet_payload_len = length - generate_mic*4;
203
204 if ( Real_encryption_enabled ) {
205
206 blecrypt_packet_encrypt(
207 packet_first_header_byte,
208 packet_payload_len,
209 unecrypted_payload,
210 sk,
211 nonce,
212 encrypted_payload);
213 //this generates always the MIC at the end, but for MIC less cases we just wont transmit it
214
215 } else {
216 /*
217 * we could do something like this:
218 * Generate quickly a "nonce" as a concatenation of the tx_packet_counter and IV
219 * KK = XOR it with the sk
220 * data to transmit = KK XOR data,
221 * MIC = 4 lower bytes of KK
222 * so the MIC would be broken and the data scrambled if the security initialization was not proper
223 */
224 memcpy(encrypted_payload, unecrypted_payload, packet_payload_len /*payload excluding possible mic*/);
225 if ( generate_mic ) { //the MIC:
226 encrypted_payload[length - 4 ] = 0;
227 encrypted_payload[length - 3 ] = 'M';
228 encrypted_payload[length - 2 ] = 'I';
229 encrypted_payload[length - 1 ] = 'C';
230 }
231 }
232 }
233 }
234
BLECrypt_if_decrypt_packet(uint8_t packet_1st_header_byte,const uint8_t * encrypted_packet_payload,uint8_t * decrypted_packet_payload,int length,bool has_mic,const uint8_t * sk,const uint8_t * nonce,uint8_t * mic_error)235 void BLECrypt_if_decrypt_packet(uint8_t packet_1st_header_byte, // First byte of packet header (or just LLID and RFU (RFU=0 for BLE v4.x) - other bits are ignored)
236 const uint8_t* encrypted_packet_payload, //as received from the air (including a MIC if has_mic)
237 uint8_t* decrypted_packet_payload,
238 int length, //including MIC lenght if (has_mic == 1) ; [ just the length in the packet header ]
239 bool has_mic,
240 const uint8_t* sk, // Session key (16 bytes, BIG-ENDIAN)
241 const uint8_t* nonce, // CCM Nonce (NONCE_LEN bytes, little-endian)
242 uint8_t *mic_error /*was there a mic error in the packet (only if has_mic==1)*/
243 ){
244
245 if ( length == 0 ){ //otherwise there is nothing to decrypt and no MIC to check
246 *mic_error = 0;
247 return;
248 }
249
250 if ( has_mic && ( length < 5 ) ){
251 //if the receiver thinks we have a packet with MIC but the transmitter did
252 //not add the MIC the packet length could be 0..4 bytes long, which the
253 //real AES block should mark as a mic_error.
254 //In that case there should not be an attempt to decrypt
255 *mic_error = 1;
256 return;
257 }
258
259 uint8_t packet_payload_len = length - has_mic*4;
260
261 if ( Real_encryption_enabled ) {
262 *mic_error = !blecrypt_packet_decrypt(
263 packet_1st_header_byte,
264 packet_payload_len,
265 encrypted_packet_payload,
266 sk,
267 nonce,
268 !has_mic,
269 decrypted_packet_payload);
270 } else {
271 //exactly the same we do in BLECrypt_if_encrypt_packet()
272 memcpy(decrypted_packet_payload, encrypted_packet_payload, packet_payload_len);
273 *mic_error = 0;
274 }
275 }
276
BLECrypt_if_aes_128(const uint8_t * key_be,const uint8_t * plaintext_data_be,uint8_t * encrypted_data_be)277 void BLECrypt_if_aes_128(
278 // Inputs
279 const uint8_t *key_be, // Key (KEY_LEN bytes, big-endian)
280 const uint8_t *plaintext_data_be, // Plaintext data (KEY_LEN bytes, big-endian)
281 // Outputs (the pointers themselves are inputs and must point to large enough areas)
282 uint8_t *encrypted_data_be)
283 {
284 if ( Real_encryption_enabled ) {
285 blecrypt_aes_128(key_be,
286 plaintext_data_be,
287 encrypted_data_be);
288 } else {
289 /* we just copy the data */
290 memcpy(encrypted_data_be, plaintext_data_be, 16);
291 }
292 }
293
BLECrypt_if_aes_ecb(const uint8_t * key_be,size_t key_size,const uint8_t * plaintext_data_be,uint8_t * encrypted_data_be)294 void BLECrypt_if_aes_ecb(
295 // Inputs
296 const uint8_t *key_be, // Key (KEY_LEN bytes, big-endian)
297 size_t key_size, // Key size in bits
298 const uint8_t *plaintext_data_be, // Plaintext data (128bits/16Bytes, big-endian)
299 // Outputs (the pointers themselves are inputs and must point to large enough areas)
300 uint8_t *encrypted_data_be)
301 {
302 if (Real_encryption_enabled && (blecrypt_aes_ecb != NULL)) {
303 blecrypt_aes_ecb(key_be,
304 key_size,
305 plaintext_data_be,
306 encrypted_data_be);
307 } else {
308 static bool warned = false;
309 if (Real_encryption_enabled && (blecrypt_aes_ecb == NULL) && (warned == false)) {
310 warned = true;
311 bs_trace_warning_time_line("Too old libCrypto library please update. 54L CRACEN CM AES model will just scramble the data\n");
312 }
313 /* Let's do a quick deterministic scramble of the data */
314 uint64_t r64 = 0, r64_2;
315 uint8_t r;
316 for (int i = 0; i < key_size/64; i++) {
317 r64 ^= ((uint64_t *)key_be)[i];
318 }
319 for (int i = 0; i < 2; i++) {
320 r64 ^= ((uint64_t *)plaintext_data_be)[i];
321 }
322 r = (r64 >> 56) ^ (r64 >> 48) ^ (r64 >> 40) ^ (r64 >> 32) ^ (r64 >> 24) ^ (r64 >> 16) ^ (r64 >> 8) ^ r64;
323 r64 = r64 * 2862933555777941757ULL + 3037000493ULL;
324 r64_2 = r64 * 2862933555777941757ULL + 3037000493ULL;
325 for (int i = 0; i < 16; i++) {
326 encrypted_data_be[i] = plaintext_data_be[(16-i+r*7)%16] ^ key_be[(i + r) % (key_size/8)];
327 }
328 ((uint64_t *)encrypted_data_be)[0] ^= r64;
329 ((uint64_t *)encrypted_data_be)[1] ^= r64_2;
330 }
331 }
332
BLECrypt_if_encrypt_packet_v3(uint8_t * adata,int alen,int mlen,int maclen,int noncelen,const uint8_t * mdata,const uint8_t * sk,const uint8_t * ccm_nonce,uint8_t * encrypted_packet_payload_and_mac)333 void BLECrypt_if_encrypt_packet_v3(uint8_t *adata, //Additional Authentication Data
334 int alen, // Length of adata
335 int mlen, // Unencrypted packet payload length (i.e. *not* including header and MAC/MIC)
336 int maclen, //Size of the MAC/MIC in bytes
337 int noncelen, //Size of the nonce in bytes
338 const uint8_t *mdata, //Unencrypted/input packet payload
339 const uint8_t *sk, //Session key
340 const uint8_t *ccm_nonce, //CCM Nonce (noncelen bytes)
341 uint8_t *encrypted_packet_payload_and_mac) //Pointer to a buffer where the resulting encrypted payload with MAC appended will be stored
342 //Note that a MAC will always be added
343 {
344 if (Real_encryption_enabled) {
345 maclen = BS_MAX(maclen, 4);
346 //this generates always the MIC at the end, but for MIC less cases we just wont transmit it
347 if (latest_ccm_if) {
348 blecrypt_packet_encrypt_v3(
349 adata,
350 alen,
351 mlen,
352 maclen,
353 noncelen,
354 mdata,
355 sk,
356 ccm_nonce,
357 encrypted_packet_payload_and_mac);
358 } else {
359 blecrypt_packet_encrypt(
360 adata[0],
361 mlen,
362 mdata,
363 sk,
364 ccm_nonce,
365 encrypted_packet_payload_and_mac);
366 }
367 } else {
368 memcpy(encrypted_packet_payload_and_mac, mdata, BS_MAX(mlen, 0) /*payload excluding possible mic*/);
369 if (maclen > 0) {
370 encrypted_packet_payload_and_mac[mlen] = 'M';
371 }
372 if (maclen > 1) {
373 encrypted_packet_payload_and_mac[mlen+1] = 'I';
374 }
375 if (maclen > 2) {
376 encrypted_packet_payload_and_mac[mlen+2] = 'C';
377 }
378 for (int i = 3 ; i < maclen; i++) {
379 encrypted_packet_payload_and_mac[mlen+i] = 0;
380 }
381 }
382 }
383
384 /*
385 * Returns 1 if MIC is ok, else 0
386 */
BLECrypt_if_decrypt_packet_v3(uint8_t * adata,int alen,int mlen,int maclen,int noncelen,const uint8_t * mdata_and_mac,const uint8_t * sk,const uint8_t * ccm_nonce,int no_mac,uint8_t * decrypted_packet_payload)387 int BLECrypt_if_decrypt_packet_v3(uint8_t *adata, //Additional Authentication Data
388 int alen, // Length of adata
389 int mlen, // Unencrypted packet payload length (i.e. *not* including header and MAC/MIC)
390 int maclen, //Size of the MAC/MIC in bytes
391 int noncelen,//Size of the nonce in bytes
392 const uint8_t *mdata_and_mac, //Pointer to the encrypted packet payload (with MAC if any) to be decrypted (packet_payload_len (+ MIC_LEN) bytes)
393 const uint8_t *sk, //Session key (KEY_LEN bytes)
394 const uint8_t *ccm_nonce, //CCM Nonce (noncelen bytes)
395 int no_mac, // Set to 1 if packet to be decrypted does not include a MAC, otherwise 0
396 uint8_t *decrypted_packet_payload) //Pointer to a buffer where the resulting decrypted payload will be stored
397 {
398 if (Real_encryption_enabled) {
399 if (latest_ccm_if) {
400 return blecrypt_packet_decrypt_v3(
401 adata,
402 alen,
403 mlen,
404 maclen,
405 noncelen,
406 mdata_and_mac,
407 sk,
408 ccm_nonce,
409 no_mac,
410 decrypted_packet_payload);
411 } else {
412 if (!no_mac && (mlen < 1)) {
413 return 0;
414 }
415 if (mlen <= 0) {
416 return 1;
417 }
418 return blecrypt_packet_decrypt(
419 adata[0],
420 mlen,
421 mdata_and_mac,
422 sk,
423 ccm_nonce,
424 no_mac,
425 decrypted_packet_payload);
426 }
427 } else {
428 memcpy(decrypted_packet_payload, mdata_and_mac, BS_MAX(mlen - maclen,0));
429 return 1;
430 }
431 }
432