1 /*
2  * Copyright 2018 Oticon A/S
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 #include <stdint.h>
7 #include <string.h>
8 #include <openssl/evp.h>
9 #include "blecrypt.h"
10 
11 // Performs simple AES-128 encryption of 128-bit data.
12 // This is the security function e (BT Core v4.2 vol 3 part H section 2.2.1).
13 // This is also the HCI_LE_Encrypt command (BT Core v4.2 vol 1 part E section 7.8.22).
14 // Applications:
15 //   * Generating and resolving resolvable random address (via ah function, BT Core v4.2 vol 3 part H section 2.2.2).
16 //   * Generating pairing confirm value (via c1 function, BT Core v4.2 vol 3 part H section 2.2.3).
17 //   * Generating short term key (via s1 function, BT Core v4.2 vol 3 part H section 2.2.4).
18 //   * Generating session key.
blecrypt_aes_128(const uint8_t * key_be,const uint8_t * plaintext_data_be,uint8_t * encrypted_data_be)19 void blecrypt_aes_128(
20     // Inputs
21     const uint8_t *key_be,                          // Key (KEY_LEN bytes, BIG-ENDIAN)
22     const uint8_t *plaintext_data_be,               // Plaintext data (KEY_LEN bytes, BIG-ENDIAN)
23     // Outputs (the pointers themselves are inputs and must point to large enough areas)
24     uint8_t *encrypted_data_be)                     // Encrypted data (KEY_LEN bytes, BIG-ENDIAN)
25 {
26     // Create OpenSSL cypher context
27     EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
28     // Set cipher type to AES-128, mode to ECB ("Electronic Codebook": simple independent encryption of blocks),
29     // and provide encryption key
30     EVP_EncryptInit(ctx, EVP_aes_128_ecb(), key_be, NULL);
31     // Encrypt plaintext data and put result in encrypted_data_be and length in outlen
32     int outlen;
33     EVP_EncryptUpdate(ctx, encrypted_data_be, &outlen, plaintext_data_be, SKD_LEN);
34     // Free cipher context
35     EVP_CIPHER_CTX_free(ctx);
36 }
37 
38 // Performs simple AES-128/192/256 encryption of 128-bit data.
blecrypt_aes_ecb(const uint8_t * key_be,size_t key_size,const uint8_t * plaintext_data_be,uint8_t * encrypted_data_be)39 void blecrypt_aes_ecb(
40     // Inputs
41     const uint8_t *key_be,                          // Key (KEY_LEN bytes, BIG-ENDIAN)
42     size_t key_size,                                // Key size in bits (only 128, 192 and 256 are supported)
43     const uint8_t *plaintext_data_be,               // Plaintext data (128bits, BIG-ENDIAN)
44     // Outputs (the pointers themselves are inputs and must point to large enough areas)
45     uint8_t *encrypted_data_be)                     // Encrypted data (128bits, BIG-ENDIAN)
46 {
47     // Create OpenSSL cypher context
48     EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
49     // Set cipher type to AES-128, mode to ECB ("Electronic Codebook": simple independent encryption of blocks),
50     // and provide encryption key
51     if (key_size == 128) {
52       EVP_EncryptInit(ctx, EVP_aes_128_ecb(), key_be, NULL);
53     } else if (key_size == 192) {
54       EVP_EncryptInit(ctx, EVP_aes_192_ecb(), key_be, NULL);
55     } else if (key_size == 256) {
56       EVP_EncryptInit(ctx, EVP_aes_256_ecb(), key_be, NULL);
57     }
58     // Encrypt plaintext data and put result in encrypted_data_be and length in outlen
59     int outlen;
60     EVP_EncryptUpdate(ctx, encrypted_data_be, &outlen, plaintext_data_be, SKD_LEN);
61     // Free cipher context
62     EVP_CIPHER_CTX_free(ctx);
63 }
64 
65 // Encrypts payload of one packet and appends MIC.
66 // Encrypted and unencrypted packet payloads must reside at different (non-overlapping) locations.
blecrypt_packet_encrypt(uint8_t packet_1st_header_byte,uint8_t packet_payload_len,const uint8_t * packet_payload,const uint8_t * sk,const uint8_t * ccm_nonce,uint8_t * encrypted_packet_payload_and_mic)67 void blecrypt_packet_encrypt(
68     // Inputs
69     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)
70     uint8_t packet_payload_len,                     // Packet payload length (not including header and MIC)
71     const uint8_t *packet_payload,                  // Packet payload to be encrypted (packet_payload_len bytes)
72     const uint8_t *sk,                              // Session key (KEY_LEN bytes, BIG-ENDIAN)
73     const uint8_t *ccm_nonce,                       // CCM Nonce (NONCE_LEN bytes, little-endian)
74     // Outputs (the pointers themselves are inputs and must point to large enough areas)
75     uint8_t *encrypted_packet_payload_and_mic)      // Resulting encrypted payload with MIC appended (packet_payload_len + MIC_LEN bytes)
76 {
77     // Set additional authenticated data (AAD) to first byte of packet header with NESN = SN = MD = 0
78     uint8_t aad = packet_1st_header_byte & 0xE3;
79     blecrypt_packet_encrypt_v2(aad,
80                                packet_payload_len,
81                                packet_payload,
82                                sk,
83                                ccm_nonce,
84                                encrypted_packet_payload_and_mic);
85 }
86 
87 // Decrypt payload of one packet and checks MIC (if present).
88 // Encrypted and unencrypted packet payloads must reside at different (non-overlapping) locations.
blecrypt_packet_decrypt(uint8_t packet_1st_header_byte,uint8_t packet_payload_len,const uint8_t * packet_payload_and_mic,const uint8_t * sk,const uint8_t * ccm_nonce,int no_mic,uint8_t * decrypted_packet_payload)89 int blecrypt_packet_decrypt(                        // Returns 1 if MIC is ok, else 0
90     // Inputs
91     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)
92     uint8_t packet_payload_len,                     // Packet payload length (not including header and MIC)
93     const uint8_t *packet_payload_and_mic,          // Packet payload (with MIC if any) to be decrypted (packet_payload_len (+ MIC_LEN) bytes)
94     const uint8_t *sk,                              // Session key (KEY_LEN bytes, BIG-ENDIAN)
95     const uint8_t *ccm_nonce,                       // CCM Nonce (NONCE_LEN bytes, little-endian)
96     int no_mic,                                     // 1 if packet to be decrypted does not include a MIC, otherwise 0
97     // Outputs (the pointers themselves are inputs and must point to large enough areas)
98     uint8_t *decrypted_packet_payload)              // Resulting decrypted payload (packet_payload_len bytes)
99 {
100     // Set additional authenticated data (AAD) to first byte of packet header with NESN = SN = MD = 0
101     uint8_t aad = packet_1st_header_byte & 0xE3;
102     return blecrypt_packet_decrypt_v2(aad,
103                                       packet_payload_len,
104                                       packet_payload_and_mic,
105                                       sk,
106                                       ccm_nonce,
107                                       no_mic,
108                                       decrypted_packet_payload);
109 }
110 
111 /**
112  * Encrypt a BLE packet payload and append the MIC,
113  * as per Bluetooth Core Specification Version 5.3 | Vol 6, Part E
114  *
115  * In comparison to blecrypt_packet_encrypt()
116  * this version is adapted to not apply the BT 4.2 AAD mask,
117  * but leave it to the caller, to be more transparent as to how the mask is meant to be applied
118  * for newer standard versions.
119  *
120  * \note Encrypted and unencrypted packet payloads must reside at different (non-overlapping) locations.
121  *
122  * \param[in] aad  Additional Authentication Data: First byte of packet header after applying the bit mask
123  *                 Note: For BT 4.2 this is 0xE3. For 5.2 it depends on the packet type.
124  * \param[in] packet_payload_len  Input packet payload length (i.e. not including header and MIC)
125  * \param[in] packet_payload  Pointer to the packet payload to be encrypted (buffer must contain packet_payload_len bytes)
126  * \param[in] sk  Session key (KEY_LEN bytes, BIG-ENDIAN)
127  * \param[in] ccm_nonce  CCM Nonce (NONCE_LEN bytes, little-endian)
128  *
129  * \param[out] encrypted_packet_payload_and_mic Pointer to a buffer where the resulting encrypted payload with MIC appended will be stored
130  *             (packet_payload_len + MIC_LEN bytes). The caller must allocate it.
131  */
blecrypt_packet_encrypt_v2(uint8_t aad,int packet_payload_len,const uint8_t * packet_payload,const uint8_t * sk,const uint8_t * ccm_nonce,uint8_t * encrypted_packet_payload_and_mic)132 void blecrypt_packet_encrypt_v2(
133     uint8_t aad,
134     int packet_payload_len,
135     const uint8_t *packet_payload,
136     const uint8_t *sk,
137     const uint8_t *ccm_nonce,
138     uint8_t *encrypted_packet_payload_and_mic)
139 {
140     int outlen;
141     // Set plaintext pointer to start of input packet payload
142     const uint8_t *pt = packet_payload;
143     // Set ciphertext pointer to start of encrypted packet payload
144     uint8_t *ct = encrypted_packet_payload_and_mic;
145     const int aad_len = 1; //Length of the Additional Authentication Data as per BT spec
146     // Allocate new cipher context
147     EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
148     // Set cipher type to 128-bit AES, and mode to CCM (Counter with CBC-MAC)
149     EVP_EncryptInit_ex(ctx, EVP_aes_128_ccm(), NULL, NULL, NULL);
150     // Set nonce length (because it is different from the 96-bit default)
151     EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_IVLEN, NONCE_LEN, NULL);
152     // Set MIC (a.k.a MAC tag) length
153     EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_TAG, MIC_LEN, NULL);
154     // Set encryption key and initialization vector (nonce)
155     EVP_EncryptInit_ex(ctx, NULL, NULL, sk, ccm_nonce);
156     // Set plaintext length (needed because AAD is used)
157     EVP_EncryptUpdate(ctx, NULL, &outlen, NULL, packet_payload_len);
158     // Provide AAD (addition authenticated data)
159     EVP_EncryptUpdate(ctx, NULL, &outlen, &aad, aad_len);
160     // Encrypt plaintext to cyphertext (and return number of encrypted bytes in outlen)
161     EVP_EncryptUpdate(ctx, ct, &outlen, pt, packet_payload_len);
162     // Get MIC and append it to encrypted data
163     EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_GET_TAG, MIC_LEN, (ct += outlen));
164     // Free cypher context
165     EVP_CIPHER_CTX_free(ctx);
166 }
167 
168 /**
169  * Decrypt a BLE packet payload and check the MIC (if present)
170  * as per Bluetooth Core Specification Version 5.3 | Vol 6, Part E
171  *
172  * In comparison to blecrypt_packet_decrypt()
173  * this version is adapted to not apply the BT 4.2 AAD mask,
174  * but leave it to the caller, to be more transparent as to how the mask is meant to be applied
175  * for newer standard versions.
176  *
177  * \note Encrypted and unencrypted packet payloads must reside at different (non-overlapping) locations.
178  *
179  * \param[in] aad  Additional Authentication Data: First byte of packet header after applying the bit mask
180  *                 Note: For BT 4.2 this is 0xE3. For 5.2 it depends on the packet type.
181  * \param[in] packet_payload_len  Unencrypted packet payload length (i.e. *not* including header and MIC)
182  * \param[in] packet_payload_and mic  Pointer to the packet payload (with MIC if any) to be decrypted (packet_payload_len (+ MIC_LEN) bytes)
183  * \param[in] sk  Session key (KEY_LEN bytes, BIG-ENDIAN)
184  * \param[in] ccm_nonce  CCM Nonce (NONCE_LEN bytes, little-endian)
185  * \param[in] no_mic  Set to 1 if packet to be decrypted does not include a MIC, otherwise 0
186  *
187  * \param[out] decrypted_packet_payload Pointer to a buffer where the resulting decrypted payload will be stored
188  *             (packet_payload_len bytes). The caller must allocate it.
189  *
190  * \return Returns 1 if MIC is ok, else 0
191  */
blecrypt_packet_decrypt_v2(uint8_t aad,int packet_payload_len,const uint8_t * packet_payload_and_mic,const uint8_t * sk,const uint8_t * ccm_nonce,int no_mic,uint8_t * decrypted_packet_payload)192 int blecrypt_packet_decrypt_v2(
193     uint8_t aad,
194     int packet_payload_len,
195     const uint8_t *packet_payload_and_mic,
196     const uint8_t *sk,
197     const uint8_t *ccm_nonce,
198     int no_mic,
199     uint8_t *decrypted_packet_payload)
200 {
201     int outlen, ok;
202     // Set ciphertext pointer to start of input packet payload
203     const uint8_t *ct = packet_payload_and_mic;
204     // Set plaintext pointer to start of decrypted packet payload
205     uint8_t *pt = decrypted_packet_payload;
206     const int aad_len = 1; //Length of the Additional Authentication Data as per BT spec
207     // Allocate new cipher context
208     EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
209     // Set cipher type to 128-bit AES, and mode to CCM (Counter with CBC-MAC)
210     EVP_DecryptInit(ctx, EVP_aes_128_ccm(), NULL, NULL);
211     // Set nonce length (because it is different from the 96-bit default)
212     EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_IVLEN, NONCE_LEN, NULL);
213     // Set hack flag indicating whether packet has MIC (standard BLE) or not
214     EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_IGNORE_TAG, no_mic, NULL);
215 
216     if (no_mic)
217     {
218         /* Set dummy MIC (a.k.a. tag) value to prevent complaints from OpenSSL */
219         EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_TAG, MIC_LEN, (uint8_t[MIC_LEN]){0});
220     }
221     else
222     {
223         /* Set expected MIC (a.k.a. tag) value (located at ct + packet_payload_len) */
224         EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_TAG, MIC_LEN, (uint8_t *) ct + packet_payload_len);
225     }
226     // Set decryption key and initialization vector (nonce)
227     EVP_DecryptInit(ctx, NULL, sk, ccm_nonce);
228     // Set ciphertext length (needed because AAD is used)
229     EVP_DecryptUpdate(ctx, NULL, &outlen, NULL, packet_payload_len);
230     // Provide AAD (addition authenticated data)
231     EVP_DecryptUpdate(ctx, NULL, &outlen, &aad, aad_len);
232     // Decrypt ciphertext to plaintext and verify MIC (also return number of decrypted bytes in outlen)
233     ok = EVP_DecryptUpdate(ctx, pt, &outlen, ct, packet_payload_len);
234     // Free cipher context
235     EVP_CIPHER_CTX_free(ctx);
236     return ok;
237 }
238 
239 
240 /**
241  * CCM encrypt a packet payload and append the MAC/MIC,
242  *
243  * In comparison to blecrypt_packet_encrypt_v2()
244  * this version accepts variable sized AAD, and variable sized MAC/MIC
245  * to support 802.15.4 usecases.
246  * As such the "blecrypt_" prefix remains only due to the component it belongs to
247  *
248  * \note Encrypted and unencrypted packet payloads must reside at different (non-overlapping) locations.
249  *
250  * \param[in] adata Additional Authentication Data. Note, for BLE any possible bitmask must be applied by the caller
251  * \param[in] alen   Length of adata
252  * \param[in] mlen   Unencrypted packet payload length (i.e. *not* including header and MAC/MIC)
253  * \param[in] maclen Size of the MAC/MIC in bytes
254  * \param[in] noncelen Size of the nonce in bytes
255  * \param[in] mdata  Unencrypted/input packet payload
256  * \param[in] sk  Session key (KEY_LEN bytes)
257  * \param[in] ccm_nonce  CCM Nonce (noncelen bytes)
258  *
259  * \param[out] encrypted_packet_payload_and_mac Pointer to a buffer where the resulting encrypted payload with MAC appended will be stored
260  *             (mlen + maclen bytes). The caller must allocate it.
261  */
blecrypt_packet_encrypt_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)262 void blecrypt_packet_encrypt_v3(
263     uint8_t *adata,
264     int alen,
265     int mlen,
266     int maclen,
267     int noncelen,
268     const uint8_t *mdata,
269     const uint8_t *sk,
270     const uint8_t *ccm_nonce,
271     uint8_t *encrypted_packet_payload_and_mac)
272 {
273   int outlen;
274   // Set plaintext pointer to start of input packet payload
275   const uint8_t *pt = mdata;
276   // Set cyphertext pointer to start of encrypted packet payload
277   uint8_t *ct = encrypted_packet_payload_and_mac;
278 
279   //  Allocate new cypher context
280   EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
281   // Set cipher type to 128-bit AES, and mode to CCM (Counter with CBC-MAC)
282   EVP_EncryptInit_ex(ctx, EVP_aes_128_ccm(), NULL, NULL, NULL);
283   // Set nonce length (because it is different from the 96-bit default)
284   EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_IVLEN, noncelen, NULL);
285   // Set MAC (a.k.a MAC tag) length
286   EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_TAG, maclen, NULL);
287   // Set encryption key and initialization vector (nonce)
288   EVP_EncryptInit_ex(ctx, NULL, NULL, sk, ccm_nonce);
289   // Set plaintext length (needed because AAD is used)
290   EVP_EncryptUpdate(ctx, NULL, &outlen, NULL, mlen);
291   // Provide AAD (addition authenticated data)
292   EVP_EncryptUpdate(ctx, NULL, &outlen, adata, alen);
293   // Encrypt plaintext to cyphertext (and return number of encrypted bytes in outlen)
294   EVP_EncryptUpdate(ctx, ct, &outlen, pt, mlen);
295   // Get MAC and append it to encrypted data
296   EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_GET_TAG, maclen, (ct += outlen));
297   // Free cypher context
298   EVP_CIPHER_CTX_free(ctx);
299 }
300 
301 
302 /*
303  * CCM decrypt a packet payload and check the MAC/MIC (if present)
304  *
305  * In comparison to blecrypt_packet_decrypt_v2()
306  * this version accepts variable sized AAD, and variable sized MAC/MIC
307  * to support 802.15.4 usecases.
308  * As such the "blecrypt_" prefix remains only due to the component it belongs to
309  *
310  * \note Encrypted and unencrypted packet payloads must reside at different (non-overlapping) locations.
311  *
312  * \param[in] adata  Additional Authentication Data. Note, for BLE any possible bitmask must be applied by the caller
313  * \param[in] alen   Length of adata
314  * \param[in] mlen   Unencrypted packet payload length (i.e. *not* including header and MAC/MIC)
315  * \param[in] maclen Size of the MAC/MIC in bytes
316  * \param[in] noncelen Size of the nonce in bytes
317  * \param[in] mdata_and_mac  Pointer to the packet payload (with MAC if any) to be decrypted (packet_payload_len (+ MIC_LEN) bytes)
318  * \param[in] sk     Session key (KEY_LEN bytes)
319  * \param[in] ccm_nonce  CCM Nonce (noncelen bytes)
320  * \param[in] no_mac  Set to 1 if packet to be decrypted does not include a MAC, otherwise 0
321  *
322  * \param[out] decrypted_packet_payload Pointer to a buffer where the resulting decrypted payload will be stored
323  *             (mlen bytes). The caller must allocate it.
324  *
325  * \return Returns 1 if MIC is ok, else 0
326  */
blecrypt_packet_decrypt_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)327 int blecrypt_packet_decrypt_v3(
328   uint8_t *adata,
329   int alen,
330   int mlen,
331   int maclen,
332   int noncelen,
333   const uint8_t *mdata_and_mac,
334   const uint8_t *sk,
335   const uint8_t *ccm_nonce,
336   int no_mac,
337   uint8_t *decrypted_packet_payload)
338 {
339   int outlen, ok;
340   // Set cyphertext pointer to start of input packet payload
341   const uint8_t *ct = mdata_and_mac;
342   // Set plaintext pointer to start of decrypted packet payload
343   uint8_t *pt = decrypted_packet_payload;
344   //  Allocate new cypher context
345   EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
346   // Set cipher type to 128-bit AES, and mode to CCM (Counter with CBC-MAC)
347   EVP_DecryptInit(ctx, EVP_aes_128_ccm(), NULL, NULL);
348   // Set nonce length (because it is different from the 96-bit default)
349   EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_IVLEN, noncelen, NULL);
350   // Set hack flag indicating whether packet has MAC or not
351   EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_IGNORE_TAG, no_mac, NULL);
352 
353   if (no_mac) {
354 #define DUMMY_MAC_LEN 4
355     /* Set dummy MAC (a.k.a. tag) value to prevent complaints from OpenSSL */
356     EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_TAG, DUMMY_MAC_LEN, (uint8_t[DUMMY_MAC_LEN]){0});
357   } else {
358     /* Set expected MAC (a.k.a. tag) value (located at ct + mlen) */
359     EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_TAG, maclen, (uint8_t *)ct + mlen);
360   }
361   // Set decryption key and initialization vector (nonce)
362   EVP_DecryptInit(ctx, NULL, sk, ccm_nonce);
363   // Set cyphertext length (needed because AAD is used)
364   EVP_DecryptUpdate(ctx, NULL, &outlen, NULL, mlen);
365   // Provide AAD (addition authenticated data)
366   // Mask the first byte of adata
367   EVP_DecryptUpdate(ctx, NULL, &outlen, adata, alen);
368   // Decrypt cyphertext to plaintext and verify MAC (also return number of decrypted bytes in outlen)
369   ok = EVP_DecryptUpdate(ctx, pt, &outlen, ct, mlen);
370   // Free cypher context
371   EVP_CIPHER_CTX_free(ctx);
372   return ok;
373 }
374 
375 // Reverses byte order of data
blecrypt_reverse_byte_order(const uint8_t * in_data,uint8_t * out_data,int len)376 void blecrypt_reverse_byte_order(const uint8_t *in_data, uint8_t *out_data, int len)
377 {
378     int i;
379     in_data += len - 1;
380     for (i = 0; i < len; i++)
381     {
382         *out_data++ = *in_data--;
383     }
384 }
385