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 // Encrypts payload of one packet and appends MIC.
39 // 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)40 void blecrypt_packet_encrypt(
41     // Inputs
42     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)
43     uint8_t packet_payload_len,                     // Packet payload length (not including header and MIC)
44     const uint8_t *packet_payload,                  // Packet payload to be encrypted (packet_payload_len bytes)
45     const uint8_t *sk,                              // Session key (KEY_LEN bytes, BIG-ENDIAN)
46     const uint8_t *ccm_nonce,                       // CCM Nonce (NONCE_LEN bytes, little-endian)
47     // Outputs (the pointers themselves are inputs and must point to large enough areas)
48     uint8_t *encrypted_packet_payload_and_mic)      // Resulting encrypted payload with MIC appended (packet_payload_len + MIC_LEN bytes)
49 {
50     // Set additional authenticated data (AAD) to first byte of packet header with NESN = SN = MD = 0
51     uint8_t aad = packet_1st_header_byte & 0xE3;
52     blecrypt_packet_encrypt_v2(aad,
53                                packet_payload_len,
54                                packet_payload,
55                                sk,
56                                ccm_nonce,
57                                encrypted_packet_payload_and_mic);
58 }
59 
60 // Decrypt payload of one packet and checks MIC (if present).
61 // 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)62 int blecrypt_packet_decrypt(                        // Returns 1 if MIC is ok, else 0
63     // Inputs
64     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)
65     uint8_t packet_payload_len,                     // Packet payload length (not including header and MIC)
66     const uint8_t *packet_payload_and_mic,          // Packet payload (with MIC if any) to be decrypted (packet_payload_len (+ MIC_LEN) bytes)
67     const uint8_t *sk,                              // Session key (KEY_LEN bytes, BIG-ENDIAN)
68     const uint8_t *ccm_nonce,                       // CCM Nonce (NONCE_LEN bytes, little-endian)
69     int no_mic,                                     // 1 if packet to be decrypted does not include a MIC, otherwise 0
70     // Outputs (the pointers themselves are inputs and must point to large enough areas)
71     uint8_t *decrypted_packet_payload)              // Resulting decrypted payload (packet_payload_len bytes)
72 {
73     // Set additional authenticated data (AAD) to first byte of packet header with NESN = SN = MD = 0
74     uint8_t aad = packet_1st_header_byte & 0xE3;
75     return blecrypt_packet_decrypt_v2(aad,
76                                       packet_payload_len,
77                                       packet_payload_and_mic,
78                                       sk,
79                                       ccm_nonce,
80                                       no_mic,
81                                       decrypted_packet_payload);
82 }
83 
84 /**
85  * Encrypt a BLE packet payload and append the MIC,
86  * as per Bluetooth Core Specification Version 5.3 | Vol 6, Part E
87  *
88  * In comparison to blecrypt_packet_encrypt()
89  * this version is adapted to not apply the BT 4.2 AAD mask,
90  * but leave it to the caller, to be more transparent as to how the mask is meant to be applied
91  * for newer standard versions.
92  *
93  * \note Encrypted and unencrypted packet payloads must reside at different (non-overlapping) locations.
94  *
95  * \param[in] aad  Additional Authentication Data: First byte of packet header after applying the bit mask
96  *                 Note: For BT 4.2 this is 0xE3. For 5.2 it depends on the packet type.
97  * \param[in] packet_payload_len  Input packet payload length (i.e. not including header and MIC)
98  * \param[in] packet_payload  Pointer to the packet payload to be encrypted (buffer must contain packet_payload_len bytes)
99  * \param[in] sk  Session key (KEY_LEN bytes, BIG-ENDIAN)
100  * \param[in] ccm_nonce  CCM Nonce (NONCE_LEN bytes, little-endian)
101  *
102  * \param[out] encrypted_packet_payload_and_mic Pointer to a buffer where the resulting encrypted payload with MIC appended will be stored
103  *             (packet_payload_len + MIC_LEN bytes). The caller must allocate it.
104  */
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)105 void blecrypt_packet_encrypt_v2(
106     uint8_t aad,
107     int packet_payload_len,
108     const uint8_t *packet_payload,
109     const uint8_t *sk,
110     const uint8_t *ccm_nonce,
111     uint8_t *encrypted_packet_payload_and_mic)
112 {
113     int outlen;
114     // Set plaintext pointer to start of input packet payload
115     const uint8_t *pt = packet_payload;
116     // Set ciphertext pointer to start of encrypted packet payload
117     uint8_t *ct = encrypted_packet_payload_and_mic;
118     const int aad_len = 1; //Length of the Additional Authentication Data as per BT spec
119     // Allocate new cipher context
120     EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
121     // Set cipher type to 128-bit AES, and mode to CCM (Counter with CBC-MAC)
122     EVP_EncryptInit_ex(ctx, EVP_aes_128_ccm(), NULL, NULL, NULL);
123     // Set nonce length (because it is different from the 96-bit default)
124     EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_IVLEN, NONCE_LEN, NULL);
125     // Set MIC (a.k.a MAC tag) length
126     EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_TAG, MIC_LEN, NULL);
127     // Set encryption key and initialization vector (nonce)
128     EVP_EncryptInit_ex(ctx, NULL, NULL, sk, ccm_nonce);
129     // Set plaintext length (needed because AAD is used)
130     EVP_EncryptUpdate(ctx, NULL, &outlen, NULL, packet_payload_len);
131     // Provide AAD (addition authenticated data)
132     EVP_EncryptUpdate(ctx, NULL, &outlen, &aad, aad_len);
133     // Encrypt plaintext to cyphertext (and return number of encrypted bytes in outlen)
134     EVP_EncryptUpdate(ctx, ct, &outlen, pt, packet_payload_len);
135     // Get MIC and append it to encrypted data
136     EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_GET_TAG, MIC_LEN, (ct += outlen));
137     // Free cypher context
138     EVP_CIPHER_CTX_free(ctx);
139 }
140 
141 /**
142  * Decrypt a BLE packet payload and check the MIC (if present)
143  * as per Bluetooth Core Specification Version 5.3 | Vol 6, Part E
144  *
145  * In comparison to blecrypt_packet_decrypt()
146  * this version is adapted to not apply the BT 4.2 AAD mask,
147  * but leave it to the caller, to be more transparent as to how the mask is meant to be applied
148  * for newer standard versions.
149  *
150  * \note Encrypted and unencrypted packet payloads must reside at different (non-overlapping) locations.
151  *
152  * \param[in] aad  Additional Authentication Data: First byte of packet header after applying the bit mask
153  *                 Note: For BT 4.2 this is 0xE3. For 5.2 it depends on the packet type.
154  * \param[in] packet_payload_len  Unencrypted packet payload length (i.e. *not* including header and MIC)
155  * \param[in] packet_payload_and mic  Pointer to the packet payload (with MIC if any) to be decrypted (packet_payload_len (+ MIC_LEN) bytes)
156  * \param[in] sk  Session key (KEY_LEN bytes, BIG-ENDIAN)
157  * \param[in] ccm_nonce  CCM Nonce (NONCE_LEN bytes, little-endian)
158  * \param[in] no_mic  Set to 1 if packet to be decrypted does not include a MIC, otherwise 0
159  *
160  * \param[out] decrypted_packet_payload Pointer to a buffer where the resulting decrypted payload will be stored
161  *             (packet_payload_len bytes). The caller must allocate it.
162  *
163  * \return Returns 1 if MIC is ok, else 0
164  */
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)165 int blecrypt_packet_decrypt_v2(
166     uint8_t aad,
167     int packet_payload_len,
168     const uint8_t *packet_payload_and_mic,
169     const uint8_t *sk,
170     const uint8_t *ccm_nonce,
171     int no_mic,
172     uint8_t *decrypted_packet_payload)
173 {
174     int outlen, ok;
175     // Set ciphertext pointer to start of input packet payload
176     const uint8_t *ct = packet_payload_and_mic;
177     // Set plaintext pointer to start of decrypted packet payload
178     uint8_t *pt = decrypted_packet_payload;
179     const int aad_len = 1; //Length of the Additional Authentication Data as per BT spec
180     // Allocate new cipher context
181     EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
182     // Set cipher type to 128-bit AES, and mode to CCM (Counter with CBC-MAC)
183     EVP_DecryptInit(ctx, EVP_aes_128_ccm(), NULL, NULL);
184     // Set nonce length (because it is different from the 96-bit default)
185     EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_IVLEN, NONCE_LEN, NULL);
186     // Set hack flag indicating whether packet has MIC (standard BLE) or not
187     EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_IGNORE_TAG, no_mic, NULL);
188 
189     if (no_mic)
190     {
191         /* Set dummy MIC (a.k.a. tag) value to prevent complaints from OpenSSL */
192         EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_TAG, MIC_LEN, (uint8_t[MIC_LEN]){0});
193     }
194     else
195     {
196         /* Set expected MIC (a.k.a. tag) value (located at ct + packet_payload_len) */
197         EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_TAG, MIC_LEN, (uint8_t *) ct + packet_payload_len);
198     }
199     // Set decryption key and initialization vector (nonce)
200     EVP_DecryptInit(ctx, NULL, sk, ccm_nonce);
201     // Set ciphertext length (needed because AAD is used)
202     EVP_DecryptUpdate(ctx, NULL, &outlen, NULL, packet_payload_len);
203     // Provide AAD (addition authenticated data)
204     EVP_DecryptUpdate(ctx, NULL, &outlen, &aad, aad_len);
205     // Decrypt ciphertext to plaintext and verify MIC (also return number of decrypted bytes in outlen)
206     ok = EVP_DecryptUpdate(ctx, pt, &outlen, ct, packet_payload_len);
207     // Free cipher context
208     EVP_CIPHER_CTX_free(ctx);
209     return ok;
210 }
211 
212 // Reverses byte order of data
blecrypt_reverse_byte_order(const uint8_t * in_data,uint8_t * out_data,int len)213 void blecrypt_reverse_byte_order(const uint8_t *in_data, uint8_t *out_data, int len)
214 {
215     int i;
216     in_data += len - 1;
217     for (i = 0; i < len; i++)
218     {
219         *out_data++ = *in_data--;
220     }
221 }
222