1 /** 2 **************************************************************************************** 3 * 4 * @file smpc_int.h 5 * 6 * @brief Header file - SMPC. 7 * 8 * Copyright (C) RivieraWaves 2009-2016 9 * 10 * 11 **************************************************************************************** 12 */ 13 14 #ifndef SMPC_INT_H_ 15 #define SMPC_INT_H_ 16 17 /** 18 **************************************************************************************** 19 * @addtogroup SMP_INT Security Manager Protocol Internal 20 * @ingroup HOST 21 * @brief Security Manager Protocol Internals. 22 * @{ 23 * 24 **************************************************************************************** 25 */ 26 27 28 /* 29 * INCLUDE FILES 30 **************************************************************************************** 31 */ 32 #include "rwip_config.h" 33 34 #if (BLE_SMPC) 35 #include "smpc.h" 36 37 #include "smp_common.h" 38 39 #include <stdbool.h> 40 #include <stdint.h> 41 42 #include "co_bt.h" 43 #include "gap.h" 44 45 #include "smpc_api.h" 46 47 /* 48 * DEFINES 49 **************************************************************************************** 50 */ 51 52 /// Minimum Encryption key size 53 #define SMPC_MIN_ENC_SIZE_LEN (7) 54 /// Maximum Encryption Key size 55 #define SMPC_MAX_ENC_SIZE_LEN (16) 56 57 58 /// Pairing Request and Pairing Response PDU Length 59 #define SMPC_CODE_PAIRING_REQ_RESP_LEN (7) 60 61 62 /* 63 * ENUMERATIONS 64 **************************************************************************************** 65 */ 66 67 68 ///Security Properties for distributed keys(all have the issued STK's properties) 69 enum 70 { 71 ///No security properties 72 SMP_KSEC_NONE = 0x00, 73 ///Unauthenticated no MITM 74 SMP_KSEC_UNAUTH_NO_MITM, 75 ///Authenticated with MITM 76 SMP_KSEC_AUTH_MITM, 77 }; 78 79 /// Repeated Attempts Attack Detection status 80 enum smpc_attempts_status 81 { 82 /// No attack has been detected 83 SMPC_REP_ATTEMPTS_NO_ERROR = GAP_ERR_NO_ERROR, // 0x00 84 /// An attack has already been detected, drop the message 85 SMPC_REP_ATTEMPTS_ATTACK, 86 /// An attack has been detected, an indication has been sent to the HL 87 SMPC_REP_ATTEMPS_ATTACK_DETECTED, 88 /// Repeated Attempt detected, need to send a Pairing Failed PDU to the peer device 89 SMPC_REP_ATTEMPT = SMP_ERROR_REPEATED_ATTEMPTS // 0x09 90 }; 91 92 93 /// STK generation methods 94 enum smpc_method 95 { 96 ///Just Works Method 97 SMPC_METH_JW = 0x00, 98 ///PassKey Entry Method 99 SMPC_METH_PK, 100 ////OOB Method 101 SMPC_METH_OOB, 102 ////Numeric Comparison 103 SMPC_METH_NC 104 }; 105 106 /// Signature Command Types 107 enum 108 { 109 /// Generate Signature 110 SMPC_SIGN_GEN = 0x00, 111 /// Verify Signature 112 SMPC_SIGN_VERIF 113 }; 114 115 enum 116 { 117 /// Use of STK in start encryption command 118 SMPC_USE_STK = 0x00, 119 /// Use of LTK in start encryption command 120 SMPC_USE_LTK 121 }; 122 123 #if (SECURE_CONNECTIONS) 124 enum 125 { 126 SMP_AES_CMAC_KEY_GENERATION = 0x00, 127 128 SMP_AES_CMAC_BLOCK 129 }; 130 131 /// Keypress Notification types 132 enum smpc_notification_type 133 { 134 /// Passkey entry started 135 SMP_PASSKEY_ENTRY_STARTED = 0x00, 136 /// Passkey digit entered 137 SMP_PASSKEY_DIGIT_ENTERED, 138 /// Passkey digit erased 139 SMP_PASSKEY_DIGIT_ERASED, 140 /// Passkey cleared 141 SMP_PASSKEY_CLEARED, 142 /// Passkey entry completed 143 SMP_PASSKEY_ENTRY_COMPLETED 144 }; 145 #endif // (SECURE_CONNECTIONS) 146 /* 147 * STRUCTURES DEFINITION 148 **************************************************************************************** 149 */ 150 151 /* 152 * GLOBAL VARIABLES DEFINITION 153 **************************************************************************************** 154 */ 155 156 157 /* 158 * MACROS 159 **************************************************************************************** 160 */ 161 /// Authentication Request mask 162 #define SMPC_MASK_AUTH_REQ(req) (req & 0x07) 163 164 /* 165 * FUNCTION DECLARATIONS 166 **************************************************************************************** 167 */ 168 169 /** 170 **************************************************************************************** 171 * @brief Send a SMPM_USE_ENC_BLOCK_CMD message to the SMPM. Shall be use when the AES_128 172 * encryption block need to be used. 173 * 174 * @param[in] conidx Connection Index 175 * @param[in] operand_1 First operand 176 * @param[in] operand_2 Second operand 177 **************************************************************************************** 178 */ 179 void smpc_send_use_enc_block_cmd(uint8_t conidx, 180 uint8_t *operand_1, uint8_t *operand_2); 181 182 183 /** 184 **************************************************************************************** 185 * @brief Send a SMPM_GEN_DH_KEY_CMD message to the SMPM. Shall be use when we need to 186 * generate a DH KEy 187 * 188 * @param[in] conidx Connection Index 189 * @param[in] operand_1 X co-ordinate 190 * @param[in] operand_2 Y co-ordinate 191 **************************************************************************************** 192 */ 193 194 void smpc_send_gen_dh_key_cmd(uint8_t conidx, 195 uint8_t *operand_1, uint8_t *operand_2); 196 197 /** 198 **************************************************************************************** 199 * @brief Send a request to the controller to start the encryption procedure. 200 * 201 * @param[in] conidx Connection Index 202 * @param[in] operand_1 First operand 203 * @param[in] operand_2 Second operand 204 **************************************************************************************** 205 */ 206 void smpc_send_start_enc_cmd(uint8_t idx, uint8_t key_type, uint8_t *key, 207 uint8_t *randnb, uint16_t ediv); 208 209 /** 210 **************************************************************************************** 211 * @brief Send the LTK provided by the HL to the controller. 212 * 213 * @param[in] idx Connection Index 214 * @param[in] found Indicate if the requested LTK has been found by the application 215 * @param[in] key Found LTK, used only if found is set to true 216 **************************************************************************************** 217 */ 218 void smpc_send_ltk_req_rsp(uint8_t idx, bool found, uint8_t *key); 219 220 /** 221 **************************************************************************************** 222 * @brief Send a SMPC_PAIRING_REQ_IND message to the HL 223 * 224 * @param[in] conidx Connection Index 225 * @param[in] req_type Kind of request 226 **************************************************************************************** 227 */ 228 void smpc_send_pairing_req_ind(uint8_t conidx, uint8_t req_type); 229 230 /** 231 **************************************************************************************** 232 * @brief Send a SMPC_PAIRING_IND message to the HL 233 * 234 * @param[in] conidx Connection Index 235 * @param[in] ind_type Kind of indication 236 * @param[in] value Value to indicate (keys, ...) 237 **************************************************************************************** 238 */ 239 void smpc_send_pairing_ind(uint8_t conidx, uint8_t ind_type, void *value); 240 241 /** 242 **************************************************************************************** 243 * @brief Check if the provided pairing features are within the specified range. 244 * 245 * @param[in] pair_feat Pairing Features values to check 246 * 247 * @param[out] true if features are valid, else false 248 **************************************************************************************** 249 */ 250 bool smpc_check_pairing_feat(struct gapc_pairing *pair_feat); 251 252 /** 253 **************************************************************************************** 254 * @brief Check if an attack by repeated attempts has been triggered by the peer device 255 * 256 * @param[in] conidx Connection Index 257 **************************************************************************************** 258 */ 259 uint8_t smpc_check_repeated_attempts(uint8_t conidx); 260 261 /** 262 **************************************************************************************** 263 * @brief Compute and check the encryption key size to use during the connection. 264 * 265 * @param[in] conidx Connection Index 266 * 267 * @param[out] true if the resultant EKS is within the specified range [7-16 bytes], else false 268 **************************************************************************************** 269 */ 270 bool smpc_check_max_key_size(uint8_t conidx); 271 272 /** 273 **************************************************************************************** 274 * @brief Check if the keys distribution scheme is compliant with the required security 275 * level 276 * 277 * @param[in] conidx Connection Index 278 * @param[in] sec_level Security level required by the device. 279 **************************************************************************************** 280 */ 281 bool smpc_check_key_distrib(uint8_t conidx, uint8_t sec_level); 282 283 /** 284 **************************************************************************************** 285 * @brief Apply the XOR operator to the two provided operands 286 * 287 * @param[in|out] result Buffer which will contain the result of the XOR operation 288 * @param[in] operand_1 First operand 289 * @param[in] operand_2 Second operand 290 **************************************************************************************** 291 */ 292 void smpc_xor(uint8_t *result, uint8_t *operand_1, uint8_t *operand_2); 293 294 /** 295 **************************************************************************************** 296 * @brief Generate the L value during a signature verification/generation procedure. 297 * 298 * @param[in] conidx Connection Index 299 * @param[in] src Indicate the source of the CSRK which will be used (LOCAL or PEER) 300 **************************************************************************************** 301 */ 302 void smpc_generate_l(uint8_t conidx, uint8_t src); 303 304 /** 305 **************************************************************************************** 306 * @brief Generate one of the Ci value during a signature verification/generation procedure. 307 * 308 * @param[in] conidx Connection Index 309 * @param[in] src Indicate the source of the CSRK which will be used (LOCAL or PEER) 310 * @param[in] ci1 Previous computed Ci value 311 * @param[in] mi 16-byte block used to generate the ci value 312 **************************************************************************************** 313 */ 314 void smpc_generate_ci(uint8_t conidx, uint8_t src, uint8_t *ci1, uint8_t *mi); 315 316 /** 317 **************************************************************************************** 318 * @brief Generate the random value exchanged during the pairing procedure (phase 2) 319 * 320 * @param[in] conidx Connection Index 321 * @param[in] state New state of the SMPC task. 322 **************************************************************************************** 323 */ 324 void smpc_generate_rand(uint8_t conidx, uint8_t state); 325 326 /** 327 **************************************************************************************** 328 * @brief Generate the first value needed in the confirm value generation 329 * 330 * @param[in] conidx Connection Index 331 * @param[in] role Current role of the device 332 * @param[in] local true if the confirm value to generate is the confirm value of the 333 * device, false if it is the remote device's one. 334 **************************************************************************************** 335 */ 336 void smpc_generate_e1(uint8_t conidx, uint8_t role, bool local); 337 338 /** 339 **************************************************************************************** 340 * @brief Generate the confirm value 341 * 342 * @param[in] conidx Connection Index 343 * @param[in] role Current role of the device 344 * @param[in] e1 e1 value 345 **************************************************************************************** 346 */ 347 void smpc_generate_cfm(uint8_t conidx, uint8_t role, uint8_t *e1); 348 349 /** 350 **************************************************************************************** 351 * @brief Generate the STK used to encrypt a link after the pairing procedure 352 * 353 * @param[in] conidx Connection Index 354 * @param[in] role Current role of the device 355 **************************************************************************************** 356 */ 357 void smpc_generate_stk(uint8_t conidx, uint8_t role); 358 359 /** 360 **************************************************************************************** 361 * @brief Calculate one of the subkey used during the signature generation/verification 362 * procedure. 363 * 364 * @param[in] gen_k2 true if the returned subkeys is k2, false if k1 365 * @param[in] l_value L value obtained from the CSRK. 366 * @param[in|out] subkey Buffer which will contain the generated subkey. 367 **************************************************************************************** 368 */ 369 void smpc_calc_subkeys(bool gen_k2, uint8_t *l_value, uint8_t *subkey); 370 371 /** 372 **************************************************************************************** 373 * @brief Start to send the keys defined during the pairing features exchange procedure. 374 * 375 * @param[in] conidx Connection Index 376 * @param[in] role Current role of the device 377 **************************************************************************************** 378 */ 379 void smpc_tkdp_send_start(uint8_t conidx, uint8_t role); 380 381 /** 382 **************************************************************************************** 383 * @brief Define the next step of TKDP procedure (sending side). 384 * 385 * @param[in] conidx Connection Index 386 * @param[in] role Current role of the device 387 **************************************************************************************** 388 */ 389 void smpc_tkdp_send_continue(uint8_t conidx, uint8_t role); 390 391 /** 392 **************************************************************************************** 393 * @brief Put the task in a state allowing to receive the keys defined during the pairing 394 * features exchange procedure. 395 * 396 * @param[in] conidx Connection Index 397 * @param[in] role Current role of the device 398 **************************************************************************************** 399 */ 400 void smpc_tkdp_rcp_start(uint8_t conidx, uint8_t role); 401 402 /** 403 **************************************************************************************** 404 * @brief Define the next step of TKDP procedure (reception side). 405 * 406 * @param[in] conidx Connection Index 407 * @param[in] role Current role of the device 408 **************************************************************************************** 409 */ 410 void smpc_tkdp_rcp_continue(uint8_t conidx, uint8_t role); 411 412 413 /** 414 **************************************************************************************** 415 * @brief Start the timer used to detect a Repeated Attempts attack 416 * 417 * @param[in] conidx Connection Index 418 **************************************************************************************** 419 */ 420 void smpc_launch_rep_att_timer(uint8_t conidx); 421 422 /** 423 **************************************************************************************** 424 * @brief Determine the method which will be used to generate the STK during a pairing 425 * procedure 426 * 427 * @param[in] conidx Connection Index 428 **************************************************************************************** 429 */ 430 void smpc_get_key_sec_prop(uint8_t conidx); 431 432 /** 433 **************************************************************************************** 434 * @brief Check if the security mode requested by the application or the peer device can 435 * be reached with the exchanged pairing features. 436 * 437 * @param[in] conidx Connection Index 438 * @param[in] role Current role of the device 439 **************************************************************************************** 440 */ 441 bool smpc_is_sec_mode_reached(uint8_t conidx, uint8_t role); 442 443 /** 444 **************************************************************************************** 445 * @brief Define what to do once a start encryption procedure has been successfully finished. 446 * 447 * @param[in] conidx Connection Index 448 * @param[in] role Current role of the device 449 * @param[in] status Status 450 **************************************************************************************** 451 */ 452 void smpc_handle_enc_change_evt(uint8_t conidx, uint8_t role, uint8_t status); 453 454 455 #if (SECURE_CONNECTIONS) 456 /** 457 **************************************************************************************** 458 * @brief Initiate DHKey Check algorithm 459 * 460 * @param[in] conidx Connection Index 461 **************************************************************************************** 462 */ 463 void smpc_initiate_dhkey_check(uint8_t conidx); 464 465 /** 466 **************************************************************************************** 467 * @brief Initiates the f5 algorithm to calculate the MacKey and LTK for a link 468 * 469 * @param[in] conidx Connection Index 470 * 471 **************************************************************************************** 472 */ 473 474 void smpc_init_mac_key_calculation(uint8_t conidx); 475 476 /** 477 **************************************************************************************** 478 * @brief Initiates the f6 algorithm to verify a DH Key Check. 479 * 480 * @param[in] conidx Connection Index 481 * 482 **************************************************************************************** 483 */ 484 485 void smpc_initiate_dhkey_verification(uint8_t conidx); 486 487 /** 488 **************************************************************************************** 489 * @brief Determines the next bit of the passkey to be used 490 * 491 * @param[in] conidx Connection Index 492 * 493 **************************************************************************************** 494 */ 495 uint8_t smpc_get_next_passkey_bit(uint8_t conidx); 496 497 /** 498 **************************************************************************************** 499 * @brief Checks if secure connections are enabled on a link 500 * 501 * @param[in] conidx Connection Index 502 * 503 **************************************************************************************** 504 */ 505 bool smpc_secure_connections_enabled(uint8_t idx); 506 507 #endif // (SECURE_CONNECTIONS) 508 #endif //(BLE_SMPC) 509 #endif //SMPC_INT_H_ 510 511 /// @} SMPC 512