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