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 MATTHIAS 24 * RINGWALD 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 * btstack_crypto.h 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 50 #if defined __cplusplus 51 extern "C" { 52 #endif 53 54 #define CMAC_TEMP_API 55 56 typedef enum { 57 BTSTACK_CRYPTO_RANDOM, 58 BTSTACK_CRYPTO_AES128, 59 BTSTACK_CRYPTO_CMAC_GENERATOR, 60 BTSTACK_CRYPTO_CMAC_MESSAGE, 61 BTSTACK_CRYPTO_ECC_P256_GENERATE_KEY, 62 BTSTACK_CRYPTO_ECC_P256_CALCULATE_DHKEY, 63 BTSTACK_CRYPTO_CCM_DIGEST_BLOCK, 64 BTSTACK_CRYPTO_CCM_ENCRYPT_BLOCK, 65 BTSTACK_CRYPTO_CCM_DECRYPT_BLOCK, 66 } btstack_crypto_operation_t; 67 68 typedef struct { 69 btstack_context_callback_registration_t context_callback; 70 btstack_crypto_operation_t operation; 71 } btstack_crypto_t; 72 73 typedef struct { 74 btstack_crypto_t btstack_crypto; 75 uint8_t * buffer; 76 uint16_t size; 77 } btstack_crypto_random_t; 78 79 typedef struct { 80 btstack_crypto_t btstack_crypto; 81 const uint8_t * key; 82 const uint8_t * plaintext; 83 uint8_t * ciphertext; 84 } btstack_crypto_aes128_t; 85 86 typedef struct { 87 btstack_crypto_t btstack_crypto; 88 const uint8_t * key; 89 uint16_t size; 90 union { 91 uint8_t (*get_byte_callback)(uint16_t pos); 92 const uint8_t * message; 93 } data; 94 uint8_t * hash; 95 } btstack_crypto_aes128_cmac_t; 96 97 typedef struct { 98 btstack_crypto_t btstack_crypto; 99 uint8_t * public_key; 100 uint8_t * dhkey; 101 } btstack_crypto_ecc_p256_t; 102 103 typedef enum { 104 CCM_CALCULATE_X1, 105 CCM_W4_X1, 106 CCM_CALCULATE_AAD_XN, 107 CCM_W4_AAD_XN, 108 CCM_CALCULATE_XN, 109 CCM_W4_XN, 110 CCM_CALCULATE_S0, 111 CCM_W4_S0, 112 CCM_CALCULATE_SN, 113 CCM_W4_SN, 114 } btstack_crypto_ccm_state_t; 115 116 typedef struct { 117 btstack_crypto_t btstack_crypto; 118 btstack_crypto_ccm_state_t state; 119 const uint8_t * key; 120 const uint8_t * nonce; 121 const uint8_t * input; 122 uint8_t * output; 123 uint8_t x_i[16]; 124 uint16_t aad_offset; 125 uint16_t aad_len; 126 uint16_t message_len; 127 uint16_t counter; 128 uint16_t block_len; 129 uint8_t auth_len; 130 uint8_t aad_remainder_len; 131 } btstack_crypto_ccm_t; 132 133 /** 134 * Initialize crypto functions 135 */ 136 void btstack_crypto_init(void); 137 138 /** 139 * Generate random data 140 * @param request 141 * @param buffer for output 142 * @param size of requested random data 143 * @param callback 144 * @param callback_arg 145 * @note request needs to stay avaliable until callback (i.e. not provided on stack) 146 */ 147 void btstack_crypto_random_generate(btstack_crypto_random_t * request, uint8_t * buffer, uint16_t size, void (* callback)(void * arg), void * callback_arg); 148 149 /** 150 * Encrypt plaintext using AES128 151 * @param request 152 * @param key (16 bytes) 153 * @param plaintext (16 bytes) 154 * @param ciphertext (16 bytes) 155 * @param callback 156 * @param callback_arg 157 * @note request needs to stay avaliable until callback (i.e. not provided on stack) 158 */ 159 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); 160 161 /** 162 * Calculate Cipher-based Message Authentication Code (CMAC) using AES128 and a generator function to provide data 163 * @param request 164 * @param key (16 bytes) 165 * @param size of message 166 * @param generator provides byte at requested position 167 * @param callback 168 * @param callback_arg 169 */ 170 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); 171 172 /** 173 * Calculate Cipher-based Message Authentication Code (CMAC) using AES128 and complete message 174 * @param request 175 * @param key (16 bytes) 176 * @param len of message 177 * @param message 178 * @param hash result 179 * @param callback 180 * @param callback_arg 181 */ 182 void btstack_crypto_aes128_cmac_message(btstack_crypto_aes128_cmac_t * request, const uint8_t * key, uint16_t len, const uint8_t * message, uint8_t * hash, void (* callback)(void * arg), void * callback_arg); 183 184 /** 185 * Calculate AES128-CMAC with key ZERO and complete message 186 * @param request 187 * @param len of message 188 * @param message 189 * @param hash 190 * @param callback 191 * @param callback_arg 192 */ 193 void btstack_crypto_aes128_cmac_zero(btstack_crypto_aes128_cmac_t * request, uint16_t len, const uint8_t * message, uint8_t * hash, void (* callback)(void * arg), void * callback_arg); 194 195 /** 196 * Generate Elliptic Curve Public/Private Key Pair (FIPS P-256) 197 * @note BTstack uses a single ECC key pair per reset. 198 * @note If LE Controller is used for ECC, private key cannot be read or managed 199 * @param request 200 * @param public_key (64 bytes) 201 * @param callback 202 * @param callback_arg 203 */ 204 void btstack_crypto_ecc_p256_generate_key(btstack_crypto_ecc_p256_t * request, uint8_t * public_key, void (* callback)(void * arg), void * callback_arg); 205 206 /** 207 * Calculate Diffie-Hellman Key based on local private key and remote public key 208 * @param request 209 * @param public_key (64 bytes) 210 * @param dhkey (32 bytes) 211 * @param callback 212 * @param callback_arg 213 */ 214 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); 215 216 /* 217 * Validate public key (not implemented for LE Controller ECC) 218 * @param public_key (64 bytes) 219 * @result 0 == valid 220 */ 221 int btstack_crypto_ecc_p256_validate_public_key(const uint8_t * public_key); 222 223 /** 224 * Initialize Counter with CBC-MAC for Bluetooth Mesh (L=2) 225 * @param request 226 * @param nonce 227 * @param key 228 * @param message_len 229 * @param additional_authenticated_data_len must be smaller than 0xff00 230 * @param auth_len 231 */ 232 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); 233 234 /** 235 * Get authentication value after encrypt or decrypt operation 236 * @param request 237 * @param authentication_value 238 */ 239 void btstack_crypto_ccm_get_authentication_value(btstack_crypto_ccm_t * request, uint8_t * authentication_value); 240 241 /** 242 * Digest Additional Authentication Data - can be called multipled times up to total additional_authenticated_data_len specified in btstack_crypto_ccm_init 243 * @param request 244 * @param additional_authenticated_data 245 * @param additional_authenticated_data_len 246 * @param callback 247 * @param callback_arg 248 */ 249 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); 250 251 /** 252 * Encrypt block - can be called multiple times. len must be a multiply of 16 for all but the last call 253 * @param request 254 * @param len (16 bytes for all but the last block) 255 * @param plaintext (16 bytes) 256 * @param ciphertext (16 bytes) 257 * @param callback 258 * @param callback_arg 259 */ 260 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); 261 262 /** 263 * Decrypt block - can be called multiple times. len must be a multiply of 16 for all but the last call 264 * @param request 265 * @param len (16 for all but last block) 266 * @param ciphertext (16 bytes) 267 * @param plaintext (16 bytes) 268 * @param callback 269 * @param callback_arg 270 */ 271 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); 272 273 // PTS testing only - not possible when using Buetooth Controller for ECC operations 274 void btstack_crypto_ecc_p256_set_key(const uint8_t * public_key, const uint8_t * private_key); 275 276 // Unit testing 277 int btstack_crypto_idle(void); 278 void btstack_crypto_reset(void); 279 280 #if defined __cplusplus 281 } 282 #endif 283 284 #endif /* BTSTACK_CTRYPTO_H */ 285