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