xref: /btstack/src/btstack_crypto.h (revision ced70f9bfeafe291ec597a3a9cc862e39e0da3ce)
1 /*
2  * Copyright (C) 2017 BlueKitchen GmbH
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the copyright holders nor the names of
14  *    contributors may be used to endorse or promote products derived
15  *    from this software without specific prior written permission.
16  * 4. Any redistribution, use, or modification is done solely for
17  *    personal benefit and not for any commercial purpose or for
18  *    monetary gain.
19  *
20  * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN
24  * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
30  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  *
33  * Please inquire about commercial licensing options at
34  * [email protected]
35  *
36  */
37 
38 /**
39  * Crypto-related functions
40  *
41  * Central place for all crypto-related functions with completion callbacks to allow
42  * using of MCU crypto peripherals or the Bluetooth controller
43  */
44 
45 #ifndef BTSTACK_CTRYPTO_H
46 #define BTSTACK_CTRYPTO_H
47 
48 #include "btstack_defines.h"
49 #include "btstack_config.h"
50 
51 #if defined __cplusplus
52 extern "C" {
53 #endif
54 
55 #define CMAC_TEMP_API
56 
57 typedef enum {
58 	BTSTACK_CRYPTO_RANDOM,
59 	BTSTACK_CRYPTO_AES128,
60 	BTSTACK_CRYPTO_CMAC_GENERATOR,
61 	BTSTACK_CRYPTO_CMAC_MESSAGE,
62 	BTSTACK_CRYPTO_ECC_P256_GENERATE_KEY,
63 	BTSTACK_CRYPTO_ECC_P256_CALCULATE_DHKEY,
64 	BTSTACK_CRYPTO_CCM_DIGEST_BLOCK,
65 	BTSTACK_CRYPTO_CCM_ENCRYPT_BLOCK,
66 	BTSTACK_CRYPTO_CCM_DECRYPT_BLOCK,
67 } btstack_crypto_operation_t;
68 
69 typedef struct {
70 	btstack_context_callback_registration_t context_callback;
71 	btstack_crypto_operation_t              operation;
72 } btstack_crypto_t;
73 
74 typedef struct {
75 	btstack_crypto_t btstack_crypto;
76 	uint8_t  * buffer;
77 	uint16_t   size;
78 } btstack_crypto_random_t;
79 
80 typedef struct {
81 	btstack_crypto_t btstack_crypto;
82 	const uint8_t  * key;
83 	const uint8_t  * plaintext;
84 	uint8_t  * ciphertext;
85 } btstack_crypto_aes128_t;
86 
87 typedef struct {
88 	btstack_crypto_t btstack_crypto;
89 	const uint8_t  * key;
90 	uint16_t         size;
91 	union {
92 		uint8_t (*get_byte_callback)(uint16_t pos);
93 		const uint8_t * message;
94 	} data;
95 	uint8_t  * hash;
96 } btstack_crypto_aes128_cmac_t;
97 
98 typedef struct {
99 	btstack_crypto_t btstack_crypto;
100 	uint8_t * public_key;
101     uint8_t * dhkey;
102 } btstack_crypto_ecc_p256_t;
103 
104 typedef enum {
105     CCM_CALCULATE_X1,
106     CCM_W4_X1,
107     CCM_CALCULATE_AAD_XN,
108     CCM_W4_AAD_XN,
109     CCM_CALCULATE_XN,
110     CCM_W4_XN,
111     CCM_CALCULATE_S0,
112     CCM_W4_S0,
113     CCM_CALCULATE_SN,
114     CCM_W4_SN,
115 } btstack_crypto_ccm_state_t;
116 
117 typedef struct {
118 	btstack_crypto_t btstack_crypto;
119 	btstack_crypto_ccm_state_t state;
120 	const uint8_t * key;
121 	const uint8_t * nonce;
122 	const uint8_t * input;
123 	uint8_t       * output;
124 	uint8_t         x_i[16];
125 	uint16_t        aad_offset;
126 	uint16_t        aad_len;
127 	uint16_t        message_len;
128 	uint16_t        counter;
129 	uint16_t        block_len;
130 	uint8_t         auth_len;
131 	uint8_t         aad_remainder_len;
132 } btstack_crypto_ccm_t;
133 
134 /**
135  * Initialize crypto functions
136  */
137 void btstack_crypto_init(void);
138 
139 /**
140  * Generate random data
141  * @param request
142  * @param buffer for output
143  * @param size of requested random data
144  * @param callback
145  * @param callback_arg
146  * @note request needs to stay avaliable until callback (i.e. not provided on stack)
147  */
148 void btstack_crypto_random_generate(btstack_crypto_random_t * request, uint8_t * buffer, uint16_t size, void (* callback)(void * arg), void * callback_arg);
149 
150 /**
151  * Encrypt plaintext using AES128
152  * @param request
153  * @param key (16 bytes)
154  * @param plaintext (16 bytes)
155  * @param ciphertext (16 bytes)
156  * @param callback
157  * @param callback_arg
158  * @note request needs to stay avaliable until callback (i.e. not provided on stack)
159  */
160 void btstack_crypto_aes128_encrypt(btstack_crypto_aes128_t * request, const uint8_t * key, const uint8_t * plaintext, uint8_t * ciphertext, void (* callback)(void * arg), void * callback_arg);
161 
162 /**
163  * Calculate Cipher-based Message Authentication Code (CMAC) using AES128 and a generator function to provide data
164  * @param request
165  * @param key (16 bytes)
166  * @param size of message
167  * @param generator provides byte at requested position
168  * @param callback
169  * @param callback_arg
170  */
171 void btstack_crypto_aes128_cmac_generator(btstack_crypto_aes128_cmac_t * request, const uint8_t * key, uint16_t size, uint8_t (*get_byte_callback)(uint16_t pos), uint8_t * hash, void (* callback)(void * arg), void * callback_arg);
172 
173 /**
174  * Calculate Cipher-based Message Authentication Code (CMAC) using AES128 and complete message
175  * @param request
176  * @param key (16 bytes)
177  * @param size of message
178  * @param message
179  * @param hash result
180  * @param callback
181  * @param callback_arg
182  */
183 void btstack_crypto_aes128_cmac_message(btstack_crypto_aes128_cmac_t * request, const uint8_t * key, uint16_t size, const uint8_t * message,  uint8_t * hash, void (* callback)(void * arg), void * callback_arg);
184 
185 /**
186  * Calculate AES128-CMAC with key ZERO and complete message
187  * @param request
188  * @param size of message
189  * @param message
190  * @param hash
191  * @param callback
192  * @param callback_arg
193  */
194 void btstack_crypto_aes128_cmac_zero(btstack_crypto_aes128_cmac_t * request, uint16_t size, const uint8_t * message, uint8_t * hash, void (* callback)(void * arg), void * callback_arg);
195 
196 /**
197  * Generate Elliptic Curve Public/Private Key Pair (FIPS P-256)
198  * @note BTstack uses a single ECC key pair per reset.
199  * @note If LE Controller is used for ECC, private key cannot be read or managed
200  * @param request
201  * @param public_key (64 bytes)
202  * @param callback
203  * @param callback_arg
204  */
205 void btstack_crypto_ecc_p256_generate_key(btstack_crypto_ecc_p256_t * request, uint8_t * public_key, void (* callback)(void * arg), void * callback_arg);
206 
207 /**
208  * Calculate Diffie-Hellman Key based on local private key and remote public key
209  * @note Bluetooth Core v5.1+ requires the Controller to return an error if the public key is invalid
210  *       In this case, dhkey will be set to 0xff..ff
211  * @param request
212  * @param public_key (64 bytes)
213  * @param dhkey (32 bytes)
214  * @param callback
215  * @param callback_arg
216  */
217 void btstack_crypto_ecc_p256_calculate_dhkey(btstack_crypto_ecc_p256_t * request, const uint8_t * public_key, uint8_t * dhkey, void (* callback)(void * arg), void * callback_arg);
218 
219 /*
220  * Validate public key
221  * @note Not implemented for ECC in Controller. @see btstack_crypto_ecc_p256_calculate_dhkey
222  * @param public_key (64 bytes)
223  * @result 0 == valid
224  */
225 int btstack_crypto_ecc_p256_validate_public_key(const uint8_t * public_key);
226 
227 /**
228  * Initialize Counter with CBC-MAC for Bluetooth Mesh (L=2)
229  * @param request
230  * @param nonce
231  * @param key
232  * @param message_len
233  * @param additional_authenticated_data_len must be smaller than 0xff00
234  * @param auth_len
235  */
236 void btstack_crypto_ccm_init(btstack_crypto_ccm_t * request, const uint8_t * key, const uint8_t * nonce, uint16_t message_len, uint16_t additional_authenticated_data_len, uint8_t auth_len);
237 
238 /**
239  * Get authentication value after encrypt or decrypt operation
240  * @param request
241  * @param authentication_value
242  */
243 void btstack_crypto_ccm_get_authentication_value(btstack_crypto_ccm_t * request, uint8_t * authentication_value);
244 
245 /**
246  * Digest Additional Authentication Data - can be called multipled times up to total additional_authenticated_data_len specified in btstack_crypto_ccm_init
247  * @param request
248  * @param additional_authenticated_data
249  * @param additional_authenticated_data_len
250  * @param callback
251  * @param callback_arg
252  */
253 void btstack_crypto_ccm_digest(btstack_crypto_ccm_t * request, uint8_t * additional_authenticated_data, uint16_t additional_authenticated_data_len, void (* callback)(void * arg), void * callback_arg);
254 
255 /**
256  * Encrypt block - can be called multiple times. len must be a multiply of 16 for all but the last call
257  * @param request
258  * @param len (16 bytes for all but the last block)
259  * @param plaintext  (16 bytes)
260  * @param ciphertext (16 bytes)
261  * @param callback
262  * @param callback_arg
263  */
264 void btstack_crypto_ccm_encrypt_block(btstack_crypto_ccm_t * request, uint16_t len, const uint8_t * plaintext, uint8_t * ciphertext, void (* callback)(void * arg), void * callback_arg);
265 
266 /**
267  * Decrypt block - can be called multiple times. len must be a multiply of 16 for all but the last call
268  * @param request
269  * @param len (16 for all but last block)
270  * @param ciphertext (16 bytes)
271  * @param plaintext  (16 bytes)
272  * @param callback
273  * @param callback_arg
274  */
275 void btstack_crypto_ccm_decrypt_block(btstack_crypto_ccm_t * request, uint16_t len, const uint8_t * ciphertext, uint8_t * plaintext, void (* callback)(void * arg), void * callback_arg);
276 
277 #if defined(ENABLE_SOFTWARE_AES128) || defined (HAVE_AES128)
278 /**
279  * Encrypt plaintext using AES128
280  * @note Prototype for custom AES128 implementation
281  * @param key (16 bytes)
282  * @param plaintext (16 bytes)
283  * @param ciphertext (16 bytes)
284  */
285 void btstack_aes128_calc(const uint8_t * key, const uint8_t * plaintext, uint8_t * ciphertext);
286 #endif
287 
288 /**
289  * @brief De-Init BTstack Crypto
290  */
291 void btstack_crypto_deinit(void);
292 
293 // PTS testing only - not possible when using Buetooth Controller for ECC operations
294 void btstack_crypto_ecc_p256_set_key(const uint8_t * public_key, const uint8_t * private_key);
295 
296 // Unit testing
297 int btstack_crypto_idle(void);
298 void btstack_crypto_reset(void);
299 
300 #if defined __cplusplus
301 }
302 #endif
303 
304 #endif /* BTSTACK_CTRYPTO_H */
305