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