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