1 /**
2  * Copyright (c) 2018 Oticon A/S
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * 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, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 
19 #include <dlfcn.h>
20 #include <string.h>
21 #include "bs_types.h"
22 #include "bs_tracing.h"
23 
24 static bool Real_encryption_enabled = false;
25 static void *LibCryptoHandle = NULL;
26 //Note that if this library IF is changed, this function prototypes need to be updated:
27 //IF to the libCryptoBLE:
28 typedef enum { SLAVE_TO_MASTER_DIRECTION, MASTER_TO_SLAVE_DIRECTION } blecrypt_packet_direction_t;
29 
30 typedef void (*blecrypt_packet_encrypt_f)(
31     // Inputs
32     uint8_t packet_1st_header_byte,
33     uint8_t packet_payload_len,
34     const uint8_t *packet_payload,
35     const uint8_t *sk,
36     const uint8_t *nonce,
37     uint8_t *encrypted_packet_payload_and_mic);
38 
39 typedef int (*blecrypt_packet_decrypt_f)(
40     uint8_t packet_1st_header_byte,
41     uint8_t packet_payload_len,
42     const uint8_t *packet_payload_and_mic,
43     const uint8_t *sk,
44     const uint8_t *nonce,
45     int no_mic,
46     uint8_t *decrypted_packet_payload);
47 
48 typedef void (*blecrypt_aes_128_f)(
49     // Inputs
50     const uint8_t *key_be,            // Key (KEY_LEN bytes, big-endian)
51     const uint8_t *plaintext_data_be, // Plaintext data (KEY_LEN bytes, big-endian)
52     // Outputs (the pointers themselves are inputs and must point to large enough areas)
53     uint8_t *encrypted_data_be);      // Plaintext data (KEY_LEN bytes, big-endian)
54 
55 static blecrypt_packet_encrypt_f blecrypt_packet_encrypt;
56 static blecrypt_packet_decrypt_f blecrypt_packet_decrypt;
57 static blecrypt_aes_128_f        blecrypt_aes_128;
58 
BLECrypt_if_enable_real_encryption(bool mode)59 void BLECrypt_if_enable_real_encryption(bool mode) {
60   if ( mode ) { //if they try to enable it
61     //attempt to load the libCrypto
62     char lib_name[128];
63     char *error;
64     snprintf(lib_name,128,"../lib/libCryptov1.so"); //relative to bin folder
65     LibCryptoHandle = dlopen(lib_name, RTLD_NOW);
66     if (!LibCryptoHandle) {
67       bs_trace_warning_line("%s\n",dlerror());
68       bs_trace_warning_line("Could not open the libcrypto library, is it compiled? => disabling real encryption\n");
69       Real_encryption_enabled = false;
70       return;
71     }
72     if ((error = dlerror()) != NULL) {
73       bs_trace_error_line("%s\n",error);
74     }
75 
76     *(void **) (&blecrypt_packet_encrypt) = dlsym(LibCryptoHandle, "blecrypt_packet_encrypt");
77     if ((error = dlerror()) != NULL) {
78       bs_trace_error_line("%s\n",error);
79     }
80     *(void **) (&blecrypt_packet_decrypt) = dlsym(LibCryptoHandle, "blecrypt_packet_decrypt");
81     if ((error = dlerror()) != NULL) {
82       bs_trace_error_line("%s\n",error);
83     }
84     *(void **) (&blecrypt_aes_128) = dlsym(LibCryptoHandle, "blecrypt_aes_128");
85     if ((error = dlerror()) != NULL) {
86       bs_trace_error_line("%s\n",error);
87     }
88     Real_encryption_enabled = true;
89   } else {
90     Real_encryption_enabled = false;
91   }
92 }
93 
BLECrypt_if_free()94 void BLECrypt_if_free(){
95   if ( LibCryptoHandle != NULL ){
96     //#define DONTCLOSELIBRARIES
97 #ifndef DONTCLOSELIBRARIES /*To be able to profile time spent in libraries in callgrind*/
98     dlclose(LibCryptoHandle);
99 #endif
100   }
101 }
102 
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)103 void BLECrypt_if_encrypt_packet(uint8_t packet_first_header_byte, // First byte of packet header
104     const uint8_t* unecrypted_payload,      // Packet payload to be encrypted
105     uint8_t* encrypted_payload,  //encrypted payload (and MIC if generate_mic==1)
106     int length,        //including MIC length if ( generate_mic == 1 ) ; [ just the length in the packet header ]
107     bool generate_mic, //we have MIC, or not
108     const uint8_t* sk, // Session key (16 bytes, BIG-ENDIAN)
109     const uint8_t* nonce   // CCM Nonce (NONCE_LEN bytes, little-endian)
110 ){
111 
112   if ( length > 0 ) { //otherwise there is nothing to encrypt and for sure no MIC to add
113     uint8_t packet_payload_len = length - generate_mic*4;
114 
115     if ( Real_encryption_enabled ) {
116 
117       blecrypt_packet_encrypt(
118           packet_first_header_byte,
119           packet_payload_len,
120           unecrypted_payload,
121           sk,
122           nonce,
123           encrypted_payload);
124       //this generates always the MIC at the end, but for MIC less cases we just wont transmit it
125 
126     } else {
127       /*
128        * we could do something like this:
129        *   Generate quickly a "nonce" as a concatenation of the tx_packet_counter and IV
130        *   KK = XOR it with the sk
131        *   data to transmit = KK XOR data,
132        *   MIC = 4 lower bytes of KK
133        * so the MIC would be broken and the data scrambled if the security initialization was not proper
134        */
135       memcpy(encrypted_payload, unecrypted_payload, packet_payload_len /*payload excluding possible mic*/);
136       if ( generate_mic ) { //the MIC:
137         encrypted_payload[length - 4 ] = 0;
138         encrypted_payload[length - 3 ] = 'M';
139         encrypted_payload[length - 2 ] = 'I';
140         encrypted_payload[length - 1 ] = 'C';
141       }
142     }
143   }
144 }
145 
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)146 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)
147     const uint8_t* encrypted_packet_payload,      //as received from the air (including a MIC if has_mic)
148     uint8_t* decrypted_packet_payload,
149     int length,       //including MIC lenght if (has_mic == 1) ; [ just  the length in the packet header ]
150     bool has_mic,
151     const uint8_t* sk, // Session key (16 bytes, BIG-ENDIAN)
152     const uint8_t* nonce,   // CCM Nonce (NONCE_LEN bytes, little-endian)
153     uint8_t *mic_error       /*was there a mic error in the packet (only if has_mic==1)*/
154 ){
155 
156   if ( length == 0 ){ //otherwise there is nothing to decrypt and no MIC to check
157     *mic_error = 0;
158     return;
159   }
160 
161   if ( has_mic && ( length < 5 )  ){
162     //if the receiver thinks we have a packet with MIC but the transmitter did
163     //not add the MIC the packet length could be 0..4 bytes long, which the
164     //real AES block should mark as a mic_error.
165     //In that case there should not be an attempt to decrypt
166     *mic_error = 1;
167     return;
168   }
169 
170   uint8_t packet_payload_len = length - has_mic*4;
171 
172   if ( Real_encryption_enabled ) {
173     *mic_error = !blecrypt_packet_decrypt(
174         packet_1st_header_byte,
175         packet_payload_len,
176         encrypted_packet_payload,
177         sk,
178         nonce,
179         !has_mic,
180         decrypted_packet_payload);
181   } else {
182     //exactly the same we do in BLECrypt_if_encrypt_packet()
183     memcpy(decrypted_packet_payload, encrypted_packet_payload, packet_payload_len);
184     *mic_error = 0;
185   }
186 }
187 
BLECrypt_if_aes_128(const uint8_t * key_be,const uint8_t * plaintext_data_be,uint8_t * encrypted_data_be)188 void BLECrypt_if_aes_128(
189     // Inputs
190     const uint8_t *key_be,            // Key (KEY_LEN bytes, big-endian)
191     const uint8_t *plaintext_data_be, // Plaintext data (KEY_LEN bytes, big-endian)
192     // Outputs (the pointers themselves are inputs and must point to large enough areas)
193     uint8_t *encrypted_data_be)
194 {
195   if ( Real_encryption_enabled ) {
196     blecrypt_aes_128(key_be,
197         plaintext_data_be,
198         encrypted_data_be);
199   } else {
200     /* we just copy the data */
201     memcpy(encrypted_data_be, plaintext_data_be, 16);
202   }
203 }
204